mirror of git://gcc.gnu.org/git/gcc.git
libgo: update to go1.7rc3
Reviewed-on: https://go-review.googlesource.com/25150 From-SVN: r238662
This commit is contained in:
parent
9d04a3af4c
commit
22b955cca5
|
|
@ -1,4 +1,4 @@
|
||||||
4c88f31a83ca28963d29d6dc9fcdb2e9b093610c
|
b156d71ad75a1b73d0ed805a5370a297648d9270
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the last
|
The first line of this file holds the git revision number of the last
|
||||||
merge done from the gofrontend repository.
|
merge done from the gofrontend repository.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
f5cf5673590a68c55b2330df9dfcdd6fac75b893
|
8707f31c0abc6b607014e843b7cc188b3019daa9
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the
|
The first line of this file holds the git revision number of the
|
||||||
last merge done from the master library sources.
|
last merge done from the master library sources.
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ endif
|
||||||
toolexeclibgo_DATA = \
|
toolexeclibgo_DATA = \
|
||||||
bufio.gox \
|
bufio.gox \
|
||||||
bytes.gox \
|
bytes.gox \
|
||||||
|
context.gox \
|
||||||
crypto.gox \
|
crypto.gox \
|
||||||
encoding.gox \
|
encoding.gox \
|
||||||
errors.gox \
|
errors.gox \
|
||||||
|
|
@ -315,6 +316,7 @@ toolexeclibgonethttp_DATA = \
|
||||||
net/http/cookiejar.gox \
|
net/http/cookiejar.gox \
|
||||||
net/http/fcgi.gox \
|
net/http/fcgi.gox \
|
||||||
net/http/httptest.gox \
|
net/http/httptest.gox \
|
||||||
|
net/http/httptrace.gox \
|
||||||
net/http/httputil.gox \
|
net/http/httputil.gox \
|
||||||
net/http/pprof.gox
|
net/http/pprof.gox
|
||||||
|
|
||||||
|
|
@ -593,6 +595,9 @@ go_bytes_files = \
|
||||||
go_bytes_c_files = \
|
go_bytes_c_files = \
|
||||||
go/bytes/indexbyte.c
|
go/bytes/indexbyte.c
|
||||||
|
|
||||||
|
go_context_files = \
|
||||||
|
go/context/context.go
|
||||||
|
|
||||||
go_crypto_files = \
|
go_crypto_files = \
|
||||||
go/crypto/crypto.go
|
go/crypto/crypto.go
|
||||||
|
|
||||||
|
|
@ -776,15 +781,19 @@ if LIBGO_IS_LINUX
|
||||||
go_net_interface_file = go/net/interface_linux.go
|
go_net_interface_file = go/net/interface_linux.go
|
||||||
else
|
else
|
||||||
if LIBGO_IS_NETBSD
|
if LIBGO_IS_NETBSD
|
||||||
go_net_interface_file = go/net/interface_netbsd.go
|
go_net_interface_file = go/net/interface_bsdvar.go
|
||||||
else
|
else
|
||||||
if LIBGO_IS_DRAGONFLY
|
if LIBGO_IS_DRAGONFLY
|
||||||
go_net_interface_file = go/net/interface_dragonfly.go
|
go_net_interface_file = go/net/interface_bsdvar.go
|
||||||
|
else
|
||||||
|
if LIBGO_IS_OPENBSD
|
||||||
|
go_net_interface_file = go/net/interface_bsdvar.go
|
||||||
else
|
else
|
||||||
go_net_interface_file = go/net/interface_stub.go
|
go_net_interface_file = go/net/interface_stub.go
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
if LIBGO_IS_LINUX
|
if LIBGO_IS_LINUX
|
||||||
go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
|
go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
|
||||||
|
|
@ -845,6 +854,7 @@ go_net_common_files = \
|
||||||
go/net/nss.go \
|
go/net/nss.go \
|
||||||
go/net/parse.go \
|
go/net/parse.go \
|
||||||
go/net/pipe.go \
|
go/net/pipe.go \
|
||||||
|
go/net/port.go \
|
||||||
go/net/fd_poll_runtime.go \
|
go/net/fd_poll_runtime.go \
|
||||||
go/net/port_unix.go \
|
go/net/port_unix.go \
|
||||||
$(go_net_sendfile_file) \
|
$(go_net_sendfile_file) \
|
||||||
|
|
@ -991,6 +1001,20 @@ endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if LIBGO_IS_LINUX
|
||||||
|
go_os_wait_file = go/os/wait_waitid.go
|
||||||
|
else
|
||||||
|
if LIBGO_IS_DARWIN
|
||||||
|
go_os_wait_file = go/os/wait_waitid.go
|
||||||
|
else
|
||||||
|
if LIBGO_IS_FREEBSD
|
||||||
|
go_os_wait_file = go/os/wait_wait6.go
|
||||||
|
else
|
||||||
|
go_os_wait_file = go/os/wait_unimp.go
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
go_os_files = \
|
go_os_files = \
|
||||||
$(go_os_dir_file) \
|
$(go_os_dir_file) \
|
||||||
go/os/dir.go \
|
go/os/dir.go \
|
||||||
|
|
@ -1016,7 +1040,8 @@ go_os_files = \
|
||||||
$(go_os_sys_file) \
|
$(go_os_sys_file) \
|
||||||
$(go_os_cloexec_file) \
|
$(go_os_cloexec_file) \
|
||||||
go/os/types.go \
|
go/os/types.go \
|
||||||
go/os/types_unix.go
|
go/os/types_unix.go \
|
||||||
|
$(go_os_wait_file)
|
||||||
|
|
||||||
go_path_files = \
|
go_path_files = \
|
||||||
go/path/match.go \
|
go/path/match.go \
|
||||||
|
|
@ -1048,6 +1073,7 @@ go_runtime_files = \
|
||||||
go/runtime/error.go \
|
go/runtime/error.go \
|
||||||
go/runtime/extern.go \
|
go/runtime/extern.go \
|
||||||
go/runtime/mem.go \
|
go/runtime/mem.go \
|
||||||
|
go/runtime/symtab.go \
|
||||||
version.go
|
version.go
|
||||||
|
|
||||||
version.go: s-version; @true
|
version.go: s-version; @true
|
||||||
|
|
@ -1134,6 +1160,7 @@ go_testing_files = \
|
||||||
go/testing/benchmark.go \
|
go/testing/benchmark.go \
|
||||||
go/testing/cover.go \
|
go/testing/cover.go \
|
||||||
go/testing/example.go \
|
go/testing/example.go \
|
||||||
|
go/testing/match.go \
|
||||||
go/testing/testing.go
|
go/testing/testing.go
|
||||||
|
|
||||||
go_time_files = \
|
go_time_files = \
|
||||||
|
|
@ -1174,6 +1201,7 @@ endif
|
||||||
|
|
||||||
go_archive_tar_files = \
|
go_archive_tar_files = \
|
||||||
go/archive/tar/common.go \
|
go/archive/tar/common.go \
|
||||||
|
go/archive/tar/format.go \
|
||||||
go/archive/tar/reader.go \
|
go/archive/tar/reader.go \
|
||||||
go/archive/tar/stat_unix.go \
|
go/archive/tar/stat_unix.go \
|
||||||
go/archive/tar/writer.go \
|
go/archive/tar/writer.go \
|
||||||
|
|
@ -1192,8 +1220,9 @@ go_compress_bzip2_files = \
|
||||||
go/compress/bzip2/move_to_front.go
|
go/compress/bzip2/move_to_front.go
|
||||||
|
|
||||||
go_compress_flate_files = \
|
go_compress_flate_files = \
|
||||||
go/compress/flate/copy.go \
|
|
||||||
go/compress/flate/deflate.go \
|
go/compress/flate/deflate.go \
|
||||||
|
go/compress/flate/deflatefast.go \
|
||||||
|
go/compress/flate/dict_decoder.go \
|
||||||
go/compress/flate/huffman_bit_writer.go \
|
go/compress/flate/huffman_bit_writer.go \
|
||||||
go/compress/flate/huffman_code.go \
|
go/compress/flate/huffman_code.go \
|
||||||
go/compress/flate/inflate.go \
|
go/compress/flate/inflate.go \
|
||||||
|
|
@ -1225,7 +1254,8 @@ go_crypto_aes_files = \
|
||||||
go/crypto/aes/block.go \
|
go/crypto/aes/block.go \
|
||||||
go/crypto/aes/cipher.go \
|
go/crypto/aes/cipher.go \
|
||||||
go/crypto/aes/cipher_generic.go \
|
go/crypto/aes/cipher_generic.go \
|
||||||
go/crypto/aes/const.go
|
go/crypto/aes/const.go \
|
||||||
|
go/crypto/aes/modes.go
|
||||||
go_crypto_cipher_files = \
|
go_crypto_cipher_files = \
|
||||||
go/crypto/cipher/cbc.go \
|
go/crypto/cipher/cbc.go \
|
||||||
go/crypto/cipher/cfb.go \
|
go/crypto/cipher/cfb.go \
|
||||||
|
|
@ -1257,8 +1287,12 @@ go_crypto_md5_files = \
|
||||||
if LIBGO_IS_LINUX
|
if LIBGO_IS_LINUX
|
||||||
crypto_rand_file = go/crypto/rand/rand_linux.go
|
crypto_rand_file = go/crypto/rand/rand_linux.go
|
||||||
else
|
else
|
||||||
|
if LIBGO_IS_OPENBSD
|
||||||
|
crypto_rand_file = go/crypto/rand/rand_openbsd.go
|
||||||
|
else
|
||||||
crypto_rand_file =
|
crypto_rand_file =
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
go_crypto_rand_files = \
|
go_crypto_rand_files = \
|
||||||
go/crypto/rand/eagain.go \
|
go/crypto/rand/eagain.go \
|
||||||
|
|
@ -1280,10 +1314,12 @@ go_crypto_sha1_files = \
|
||||||
go/crypto/sha1/sha1block_generic.go
|
go/crypto/sha1/sha1block_generic.go
|
||||||
go_crypto_sha256_files = \
|
go_crypto_sha256_files = \
|
||||||
go/crypto/sha256/sha256.go \
|
go/crypto/sha256/sha256.go \
|
||||||
go/crypto/sha256/sha256block.go
|
go/crypto/sha256/sha256block.go \
|
||||||
|
go/crypto/sha256/sha256block_generic.go
|
||||||
go_crypto_sha512_files = \
|
go_crypto_sha512_files = \
|
||||||
go/crypto/sha512/sha512.go \
|
go/crypto/sha512/sha512.go \
|
||||||
go/crypto/sha512/sha512block.go
|
go/crypto/sha512/sha512block.go \
|
||||||
|
go/crypto/sha512/sha512block_generic.go
|
||||||
go_crypto_subtle_files = \
|
go_crypto_subtle_files = \
|
||||||
go/crypto/subtle/constant_time.go
|
go/crypto/subtle/constant_time.go
|
||||||
go_crypto_tls_files = \
|
go_crypto_tls_files = \
|
||||||
|
|
@ -1375,7 +1411,10 @@ go_debug_macho_files = \
|
||||||
go/debug/macho/macho.go
|
go/debug/macho/macho.go
|
||||||
go_debug_pe_files = \
|
go_debug_pe_files = \
|
||||||
go/debug/pe/file.go \
|
go/debug/pe/file.go \
|
||||||
go/debug/pe/pe.go
|
go/debug/pe/pe.go \
|
||||||
|
go/debug/pe/section.go \
|
||||||
|
go/debug/pe/string.go \
|
||||||
|
go/debug/pe/symbol.go
|
||||||
go_debug_plan9obj_files = \
|
go_debug_plan9obj_files = \
|
||||||
go/debug/plan9obj/file.go \
|
go/debug/plan9obj/file.go \
|
||||||
go/debug/plan9obj/plan9obj.go
|
go/debug/plan9obj/plan9obj.go
|
||||||
|
|
@ -1517,6 +1556,87 @@ go_go_internal_gccgoimporter_files = \
|
||||||
go/go/internal/gccgoimporter/importer.go \
|
go/go/internal/gccgoimporter/importer.go \
|
||||||
go/go/internal/gccgoimporter/parser.go
|
go/go/internal/gccgoimporter/parser.go
|
||||||
|
|
||||||
|
go_golang_org_x_net_http2_hpack_files = \
|
||||||
|
go/golang_org/x/net/http2/hpack/encode.go \
|
||||||
|
go/golang_org/x/net/http2/hpack/hpack.go \
|
||||||
|
go/golang_org/x/net/http2/hpack/huffman.go \
|
||||||
|
go/golang_org/x/net/http2/hpack/tables.go
|
||||||
|
|
||||||
|
go_golang_org_x_net_lex_httplex_files = \
|
||||||
|
go/golang_org/x/net/lex/httplex/httplex.go
|
||||||
|
|
||||||
|
if LIBGO_IS_BSD
|
||||||
|
|
||||||
|
if LIBGO_IS_DARWIN
|
||||||
|
x_net_route_files =
|
||||||
|
go/golang_org/x/net/route/interface_classic.go \
|
||||||
|
go/golang_org/x/net/route/interface_multicast.go \
|
||||||
|
go/golang_org/x/net/route/route_classic.go \
|
||||||
|
go/golang_org/x/net/route/sys_darwin.go \
|
||||||
|
go/golang_org/x/net/route/zsys_darwin.go
|
||||||
|
endif
|
||||||
|
if LIBGO_IS_DRAGONFLY
|
||||||
|
x_net_route_files =
|
||||||
|
go/golang_org/x/net/route/interface_announce.go \
|
||||||
|
go/golang_org/x/net/route/interface_classic.go \
|
||||||
|
go/golang_org/x/net/route/interface_multicast.go \
|
||||||
|
go/golang_org/x/net/route/route_classic.go \
|
||||||
|
go/golang_org/x/net/route/sys_dragonfly.go \
|
||||||
|
go/golang_org/x/net/route/zsys_dragonfly.go
|
||||||
|
endif
|
||||||
|
if LIBGO_IS_FREEBSD
|
||||||
|
if LIBGO_IS_386
|
||||||
|
x_net_route_freebsd_file =
|
||||||
|
go/golang_org/x/net/route/zsys_freebsd_386.go
|
||||||
|
endif
|
||||||
|
if LIBGO_IS_X86_64
|
||||||
|
x_net_route_freebsd_file =
|
||||||
|
go/golang_org/x/net/route/zsys_freebsd_amd64.go
|
||||||
|
endif
|
||||||
|
if LIBGO_IS_ARM
|
||||||
|
x_net_route_freebsd_file =
|
||||||
|
go/golang_org/x/net/route/zsys_freebsd_arm.go
|
||||||
|
endif
|
||||||
|
x_net_route_files =
|
||||||
|
go/golang_org/x/net/route/interface_announce.go \
|
||||||
|
go/golang_org/x/net/route/interface_freebsd.go \
|
||||||
|
go/golang_org/x/net/route/interface_multicast.go \
|
||||||
|
go/golang_org/x/net/route/route_classic.go \
|
||||||
|
go/golang_org/x/net/route/sys_freebsd.go \
|
||||||
|
$(x_net_route_freebsd_file)
|
||||||
|
endif
|
||||||
|
if LIBGO_IS_NETBSD
|
||||||
|
x_net_route_files =
|
||||||
|
go/golang_org/x/net/route/interface_announce.go \
|
||||||
|
go/golang_org/x/net/route/interface_classic.go \
|
||||||
|
go/golang_org/x/net/route/route_classic.go \
|
||||||
|
go/golang_org/x/net/route/sys_netbsd.go \
|
||||||
|
go/golang_org/x/net/route/zsys_netbsd.go
|
||||||
|
endif
|
||||||
|
if LIBGO_IS_OPENBSD
|
||||||
|
x_net_route_files =
|
||||||
|
go/golang_org/x/net/route/route_openbsd.go \
|
||||||
|
go/golang_org/x/net/route/sys_openbsd.go \
|
||||||
|
go/golang_org/x/net/route/zsys_openbsd.go
|
||||||
|
endif
|
||||||
|
|
||||||
|
go_golang_org_x_net_route_files = \
|
||||||
|
go/golang_org/x/net/route/address.go \
|
||||||
|
go/golang_org/x/net/route/binary.go \
|
||||||
|
go/golang_org/x/net/route/interface.go \
|
||||||
|
go/golang_org/x/net/route/message.go \
|
||||||
|
go/golang_org/x/net/route/route.go \
|
||||||
|
go/golang_org/x/net/route/syscall.go \
|
||||||
|
go/golang_org/x/net/route/sys.go \
|
||||||
|
$(x_net_route_files)
|
||||||
|
|
||||||
|
golang_org_x_net_route_lo = \
|
||||||
|
golang_org/x/net/route/route.lo
|
||||||
|
golang_org_x_net_route_check = \
|
||||||
|
golang_org/x/net/route/check
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
go_hash_adler32_files = \
|
go_hash_adler32_files = \
|
||||||
go/hash/adler32/adler32.go
|
go/hash/adler32/adler32.go
|
||||||
go_hash_crc32_files = \
|
go_hash_crc32_files = \
|
||||||
|
|
@ -1576,11 +1696,8 @@ go_index_suffixarray_files = \
|
||||||
go/index/suffixarray/qsufsort.go \
|
go/index/suffixarray/qsufsort.go \
|
||||||
go/index/suffixarray/suffixarray.go
|
go/index/suffixarray/suffixarray.go
|
||||||
|
|
||||||
go_internal_golang_org_x_net_http2_hpack_files = \
|
go_internal_nettrace_files = \
|
||||||
go/internal/golang.org/x/net/http2/hpack/encode.go \
|
go/internal/nettrace/nettrace.go
|
||||||
go/internal/golang.org/x/net/http2/hpack/hpack.go \
|
|
||||||
go/internal/golang.org/x/net/http2/hpack/huffman.go \
|
|
||||||
go/internal/golang.org/x/net/http2/hpack/tables.go
|
|
||||||
go_internal_race_files = \
|
go_internal_race_files = \
|
||||||
go/internal/race/doc.go \
|
go/internal/race/doc.go \
|
||||||
go/internal/race/norace.go
|
go/internal/race/norace.go
|
||||||
|
|
@ -1603,15 +1720,23 @@ else
|
||||||
if LIBGO_IS_MIPS64
|
if LIBGO_IS_MIPS64
|
||||||
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_mips64x.go
|
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_mips64x.go
|
||||||
else
|
else
|
||||||
|
if LIBGO_IS_S390X
|
||||||
|
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_s390x.go
|
||||||
|
else
|
||||||
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_generic.go
|
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_generic.go
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
if LIBGO_IS_OPENBSD
|
||||||
|
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getentropy_openbsd.go
|
||||||
else
|
else
|
||||||
internal_syscall_unix_getrandom_files =
|
internal_syscall_unix_getrandom_files =
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
go_internal_syscall_unix_files = \
|
go_internal_syscall_unix_files = \
|
||||||
go/internal/syscall/unix/dummy.go \
|
go/internal/syscall/unix/dummy.go \
|
||||||
|
|
@ -1621,6 +1746,7 @@ go_internal_testenv_files = \
|
||||||
go/internal/testenv/testenv.go
|
go/internal/testenv/testenv.go
|
||||||
go_internal_trace_files = \
|
go_internal_trace_files = \
|
||||||
go/internal/trace/goroutines.go \
|
go/internal/trace/goroutines.go \
|
||||||
|
go/internal/trace/order.go \
|
||||||
go/internal/trace/parser.go
|
go/internal/trace/parser.go
|
||||||
|
|
||||||
go_io_ioutil_files = \
|
go_io_ioutil_files = \
|
||||||
|
|
@ -1684,8 +1810,8 @@ go_net_http_files = \
|
||||||
go/net/http/fs.go \
|
go/net/http/fs.go \
|
||||||
go/net/http/h2_bundle.go \
|
go/net/http/h2_bundle.go \
|
||||||
go/net/http/header.go \
|
go/net/http/header.go \
|
||||||
|
go/net/http/http.go \
|
||||||
go/net/http/jar.go \
|
go/net/http/jar.go \
|
||||||
go/net/http/lex.go \
|
|
||||||
go/net/http/method.go \
|
go/net/http/method.go \
|
||||||
go/net/http/request.go \
|
go/net/http/request.go \
|
||||||
go/net/http/response.go \
|
go/net/http/response.go \
|
||||||
|
|
@ -1718,10 +1844,13 @@ go_net_http_fcgi_files = \
|
||||||
go/net/http/fcgi/child.go \
|
go/net/http/fcgi/child.go \
|
||||||
go/net/http/fcgi/fcgi.go
|
go/net/http/fcgi/fcgi.go
|
||||||
go_net_http_httptest_files = \
|
go_net_http_httptest_files = \
|
||||||
|
go/net/http/httptest/httptest.go \
|
||||||
go/net/http/httptest/recorder.go \
|
go/net/http/httptest/recorder.go \
|
||||||
go/net/http/httptest/server.go
|
go/net/http/httptest/server.go
|
||||||
go_net_http_pprof_files = \
|
go_net_http_pprof_files = \
|
||||||
go/net/http/pprof/pprof.go
|
go/net/http/pprof/pprof.go
|
||||||
|
go_net_http_httptrace_files = \
|
||||||
|
go/net/http/httptrace/trace.go
|
||||||
go_net_http_httputil_files = \
|
go_net_http_httputil_files = \
|
||||||
go/net/http/httputil/dump.go \
|
go/net/http/httputil/dump.go \
|
||||||
go/net/http/httputil/httputil.go \
|
go/net/http/httputil/httputil.go \
|
||||||
|
|
@ -1768,15 +1897,18 @@ go_os_signal_files = \
|
||||||
|
|
||||||
if LIBGO_IS_SOLARIS
|
if LIBGO_IS_SOLARIS
|
||||||
os_user_decls_file = go/os/user/decls_solaris.go
|
os_user_decls_file = go/os/user/decls_solaris.go
|
||||||
|
os_user_listgroups_file = go/os/user/listgroups_solaris.go
|
||||||
else
|
else
|
||||||
os_user_decls_file = go/os/user/decls_unix.go
|
os_user_decls_file = go/os/user/decls_unix.go
|
||||||
|
os_user_listgroups_file = go/os/user/listgroups_unix.go
|
||||||
endif
|
endif
|
||||||
|
|
||||||
go_os_user_files = \
|
go_os_user_files = \
|
||||||
go/os/user/lookup.go \
|
go/os/user/lookup.go \
|
||||||
go/os/user/lookup_unix.go \
|
go/os/user/lookup_unix.go \
|
||||||
go/os/user/user.go \
|
go/os/user/user.go \
|
||||||
$(os_user_decls_file)
|
$(os_user_decls_file) \
|
||||||
|
$(os_user_listgroups_file)
|
||||||
|
|
||||||
go_path_filepath_files = \
|
go_path_filepath_files = \
|
||||||
go/path/filepath/match.go \
|
go/path/filepath/match.go \
|
||||||
|
|
@ -2147,6 +2279,7 @@ libgo_go_objs = \
|
||||||
bufio.lo \
|
bufio.lo \
|
||||||
bytes.lo \
|
bytes.lo \
|
||||||
bytes/index.lo \
|
bytes/index.lo \
|
||||||
|
context.lo \
|
||||||
crypto.lo \
|
crypto.lo \
|
||||||
encoding.lo \
|
encoding.lo \
|
||||||
errors.lo \
|
errors.lo \
|
||||||
|
|
@ -2242,6 +2375,9 @@ libgo_go_objs = \
|
||||||
go/scanner.lo \
|
go/scanner.lo \
|
||||||
go/token.lo \
|
go/token.lo \
|
||||||
go/types.lo \
|
go/types.lo \
|
||||||
|
golang_org/x/net/http2/hpack.lo \
|
||||||
|
golang_org/x/net/lex/httplex.lo \
|
||||||
|
$(golang_org_x_net_route_lo) \
|
||||||
hash/adler32.lo \
|
hash/adler32.lo \
|
||||||
hash/crc32.lo \
|
hash/crc32.lo \
|
||||||
hash/crc64.lo \
|
hash/crc64.lo \
|
||||||
|
|
@ -2250,6 +2386,7 @@ libgo_go_objs = \
|
||||||
net/http/cookiejar.lo \
|
net/http/cookiejar.lo \
|
||||||
net/http/fcgi.lo \
|
net/http/fcgi.lo \
|
||||||
net/http/httptest.lo \
|
net/http/httptest.lo \
|
||||||
|
net/http/httptrace.lo \
|
||||||
net/http/httputil.lo \
|
net/http/httputil.lo \
|
||||||
net/http/internal.lo \
|
net/http/internal.lo \
|
||||||
net/http/pprof.lo \
|
net/http/pprof.lo \
|
||||||
|
|
@ -2261,7 +2398,7 @@ libgo_go_objs = \
|
||||||
image/jpeg.lo \
|
image/jpeg.lo \
|
||||||
image/png.lo \
|
image/png.lo \
|
||||||
index/suffixarray.lo \
|
index/suffixarray.lo \
|
||||||
internal/golang.org/x/net/http2/hpack.lo \
|
internal/nettrace.lo \
|
||||||
internal/race.lo \
|
internal/race.lo \
|
||||||
internal/singleflight.lo \
|
internal/singleflight.lo \
|
||||||
internal/syscall/unix.lo \
|
internal/syscall/unix.lo \
|
||||||
|
|
@ -2460,6 +2597,15 @@ bytes/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: bytes/check
|
.PHONY: bytes/check
|
||||||
|
|
||||||
|
@go_include@ context.lo.dep
|
||||||
|
context.lo.dep: $(go_context_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
context.lo: $(go_context_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
context/check: $(CHECK_DEPS)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: context/check
|
||||||
|
|
||||||
@go_include@ crypto.lo.dep
|
@go_include@ crypto.lo.dep
|
||||||
crypto.lo.dep: $(go_crypto_files)
|
crypto.lo.dep: $(go_crypto_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
|
|
@ -3275,6 +3421,35 @@ go/internal/gccgoimporter/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: go/internal/gccgoimporter/check
|
.PHONY: go/internal/gccgoimporter/check
|
||||||
|
|
||||||
|
@go_include@ golang_org/x/net/http2/hpack.lo.dep
|
||||||
|
golang_org/x/net/http2/hpack.lo.dep: $(go_golang_org_x_net_http2_hpack_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
golang_org/x/net/http2/hpack.lo: $(go_golang_org_x_net_http2_hpack_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
golang_org/x/net/http2/hpack/check: $(CHECK_DEPS)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: golang_org/x/net/http2/hpack/check
|
||||||
|
|
||||||
|
@go_include@ golang_org/x/net/lex/httplex.lo.dep
|
||||||
|
golang_org/x/net/lex/httplex.lo.dep: $(go_golang_org_x_net_lex_httplex_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
golang_org/x/net/lex/httplex.lo: $(go_golang_org_x_net_lex_httplex_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
golang_org/x/net/lex/httplex/check: $(CHECK_DEPS)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: golang_org/x/net/lex/httplex/check
|
||||||
|
|
||||||
|
if LIBGO_IS_BSD
|
||||||
|
@go_include@ golang_org/x/net/route.lo.dep
|
||||||
|
golang_org/x/net/route.lo.dep: $(go_golang_org_x_net_route_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
golang_org/x/net/route.lo: $(go_golang_org_x_net_route_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
golang_org/x/net/route/check: $(CHECK_DEPS)
|
||||||
|
@$(CHECK)
|
||||||
|
endif
|
||||||
|
.PHONY: golang_org/x/net/route/check
|
||||||
|
|
||||||
@go_include@ hash/adler32.lo.dep
|
@go_include@ hash/adler32.lo.dep
|
||||||
hash/adler32.lo.dep: $(go_hash_adler32_files)
|
hash/adler32.lo.dep: $(go_hash_adler32_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
|
|
@ -3383,14 +3558,14 @@ index/suffixarray/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: index/suffixarray/check
|
.PHONY: index/suffixarray/check
|
||||||
|
|
||||||
@go_include@ internal/golang.org/x/net/http2/hpack.lo.dep
|
@go_include@ internal/nettrace.lo.dep
|
||||||
internal/golang.org/x/net/http2/hpack.lo.dep: $(go_internal_golang_org_x_net_http2_hpack_files)
|
internal/nettrace.lo.dep: $(go_internal_nettrace_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
internal/golang.org/x/net/http2/hpack.lo: $(go_internal_golang_org_x_net_http2_hpack_files)
|
internal/nettrace.lo: $(go_internal_nettrace_files)
|
||||||
$(BUILDPACKAGE)
|
$(BUILDPACKAGE)
|
||||||
internal/golang.org/x/net/http2/hpack/check: $(CHECK_DEPS)
|
internal/nettrace/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: internal/golang.org/x/net/http2/hpack/check
|
.PHONY: internal/nettrace/check
|
||||||
|
|
||||||
@go_include@ internal/race.lo.dep
|
@go_include@ internal/race.lo.dep
|
||||||
internal/race.lo.dep: $(go_internal_race_files)
|
internal/race.lo.dep: $(go_internal_race_files)
|
||||||
|
|
@ -3593,6 +3768,15 @@ net/http/httptest/check: $(check_deps)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: net/http/httptest/check
|
.PHONY: net/http/httptest/check
|
||||||
|
|
||||||
|
@go_include@ net/http/httptrace.lo.dep
|
||||||
|
net/http/httptrace.lo.dep: $(go_net_http_httptrace_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
net/http/httptrace.lo: $(go_net_http_httptrace_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
net/http/httptrace/check: $(check_deps)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: net/http/httptrace/check
|
||||||
|
|
||||||
@go_include@ net/http/httputil.lo.dep
|
@go_include@ net/http/httputil.lo.dep
|
||||||
net/http/httputil.lo.dep: $(go_net_http_httputil_files)
|
net/http/httputil.lo.dep: $(go_net_http_httputil_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
|
|
@ -3833,6 +4017,8 @@ bufio.gox: bufio.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
bytes.gox: bytes.lo
|
bytes.gox: bytes.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
context.gox: context.lo
|
||||||
|
$(BUILDGOX)
|
||||||
crypto.gox: crypto.lo
|
crypto.gox: crypto.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
encoding.gox: encoding.lo
|
encoding.gox: encoding.lo
|
||||||
|
|
@ -4027,6 +4213,17 @@ go/internal/gcimporter.gox: go/internal/gcimporter.lo
|
||||||
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
|
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
|
||||||
|
golang_org/x/net/http2/hpack.gox: golang_org/x/net/http2/hpack.lo
|
||||||
|
$(BUILDGOX)
|
||||||
|
|
||||||
|
golang_org/x/net/lex/httplex.gox: golang_org/x/net/lex/httplex.lo
|
||||||
|
$(BUILDGOX)
|
||||||
|
|
||||||
|
if LIBGO_IS_BSD
|
||||||
|
golang_org/x/net/route.gox: golang_org/x/net/route.lo
|
||||||
|
$(BUILDGOX)
|
||||||
|
endif
|
||||||
|
|
||||||
hash/adler32.gox: hash/adler32.lo
|
hash/adler32.gox: hash/adler32.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
hash/crc32.gox: hash/crc32.lo
|
hash/crc32.gox: hash/crc32.lo
|
||||||
|
|
@ -4055,7 +4252,7 @@ image/color/palette.gox: image/color/palette.lo
|
||||||
index/suffixarray.gox: index/suffixarray.lo
|
index/suffixarray.gox: index/suffixarray.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
|
||||||
internal/golang.org/x/net/http2/hpack.gox: internal/golang.org/x/net/http2/hpack.lo
|
internal/nettrace.gox: internal/nettrace.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
internal/race.gox: internal/race.lo
|
internal/race.gox: internal/race.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
|
@ -4107,6 +4304,8 @@ net/http/fcgi.gox: net/http/fcgi.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
net/http/httptest.gox: net/http/httptest.lo
|
net/http/httptest.gox: net/http/httptest.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
net/http/httptrace.gox: net/http/httptrace.lo
|
||||||
|
$(BUILDGOX)
|
||||||
net/http/httputil.gox: net/http/httputil.lo
|
net/http/httputil.gox: net/http/httputil.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
net/http/pprof.gox: net/http/pprof.lo
|
net/http/pprof.gox: net/http/pprof.lo
|
||||||
|
|
@ -4169,6 +4368,7 @@ unicode/utf8.gox: unicode/utf8.lo
|
||||||
TEST_PACKAGES = \
|
TEST_PACKAGES = \
|
||||||
bufio/check \
|
bufio/check \
|
||||||
bytes/check \
|
bytes/check \
|
||||||
|
context/check \
|
||||||
errors/check \
|
errors/check \
|
||||||
expvar/check \
|
expvar/check \
|
||||||
flag/check \
|
flag/check \
|
||||||
|
|
@ -4252,6 +4452,9 @@ TEST_PACKAGES = \
|
||||||
go/scanner/check \
|
go/scanner/check \
|
||||||
go/token/check \
|
go/token/check \
|
||||||
go/types/check \
|
go/types/check \
|
||||||
|
golang_org/x/net/http2/hpack/check \
|
||||||
|
golang_org/x/net/lex/httplex/check \
|
||||||
|
$(golang_org_x_net_route_check) \
|
||||||
hash/adler32/check \
|
hash/adler32/check \
|
||||||
hash/crc32/check \
|
hash/crc32/check \
|
||||||
hash/crc64/check \
|
hash/crc64/check \
|
||||||
|
|
@ -4261,7 +4464,6 @@ TEST_PACKAGES = \
|
||||||
image/jpeg/check \
|
image/jpeg/check \
|
||||||
image/png/check \
|
image/png/check \
|
||||||
index/suffixarray/check \
|
index/suffixarray/check \
|
||||||
internal/golang.org/x/net/http2/hpack/check \
|
|
||||||
internal/singleflight/check \
|
internal/singleflight/check \
|
||||||
internal/trace/check \
|
internal/trace/check \
|
||||||
io/ioutil/check \
|
io/ioutil/check \
|
||||||
|
|
@ -4276,6 +4478,7 @@ TEST_PACKAGES = \
|
||||||
net/http/cookiejar/check \
|
net/http/cookiejar/check \
|
||||||
net/http/fcgi/check \
|
net/http/fcgi/check \
|
||||||
net/http/httptest/check \
|
net/http/httptest/check \
|
||||||
|
net/http/httptrace/check \
|
||||||
net/http/httputil/check \
|
net/http/httputil/check \
|
||||||
net/http/internal/check \
|
net/http/internal/check \
|
||||||
net/internal/socktest/check \
|
net/internal/socktest/check \
|
||||||
|
|
|
||||||
|
|
@ -174,14 +174,14 @@ am_libnetgo_a_OBJECTS = $(am__objects_3)
|
||||||
libnetgo_a_OBJECTS = $(am_libnetgo_a_OBJECTS)
|
libnetgo_a_OBJECTS = $(am_libnetgo_a_OBJECTS)
|
||||||
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
|
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
|
||||||
am__DEPENDENCIES_1 =
|
am__DEPENDENCIES_1 =
|
||||||
am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
|
am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo context.lo \
|
||||||
encoding.lo errors.lo expvar.lo flag.lo fmt.lo hash.lo html.lo \
|
crypto.lo encoding.lo errors.lo expvar.lo flag.lo fmt.lo \
|
||||||
image.lo io.lo log.lo math.lo mime.lo net.lo os.lo path.lo \
|
hash.lo html.lo image.lo io.lo log.lo math.lo mime.lo net.lo \
|
||||||
reflect-go.lo reflect/makefunc_ffi_c.lo regexp.lo \
|
os.lo path.lo reflect-go.lo reflect/makefunc_ffi_c.lo \
|
||||||
runtime-go.lo sort.lo strconv.lo strings.lo strings/index.lo \
|
regexp.lo runtime-go.lo sort.lo strconv.lo strings.lo \
|
||||||
sync.lo syscall.lo syscall/errno.lo syscall/signame.lo \
|
strings/index.lo sync.lo syscall.lo syscall/errno.lo \
|
||||||
syscall/wait.lo testing.lo time-go.lo unicode.lo \
|
syscall/signame.lo syscall/wait.lo testing.lo time-go.lo \
|
||||||
archive/tar.lo archive/zip.lo compress/bzip2.lo \
|
unicode.lo archive/tar.lo archive/zip.lo compress/bzip2.lo \
|
||||||
compress/flate.lo compress/gzip.lo compress/lzw.lo \
|
compress/flate.lo compress/gzip.lo compress/lzw.lo \
|
||||||
compress/zlib.lo container/heap.lo container/list.lo \
|
compress/zlib.lo container/heap.lo container/list.lo \
|
||||||
container/ring.lo crypto/aes.lo crypto/cipher.lo crypto/des.lo \
|
container/ring.lo crypto/aes.lo crypto/cipher.lo crypto/des.lo \
|
||||||
|
|
@ -199,22 +199,24 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
|
||||||
go/ast.lo go/build.lo go/constant.lo go/doc.lo go/format.lo \
|
go/ast.lo go/build.lo go/constant.lo go/doc.lo go/format.lo \
|
||||||
go/importer.lo go/internal/gcimporter.lo \
|
go/importer.lo go/internal/gcimporter.lo \
|
||||||
go/internal/gccgoimporter.lo go/parser.lo go/printer.lo \
|
go/internal/gccgoimporter.lo go/parser.lo go/printer.lo \
|
||||||
go/scanner.lo go/token.lo go/types.lo hash/adler32.lo \
|
go/scanner.lo go/token.lo go/types.lo \
|
||||||
hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \
|
golang_org/x/net/http2/hpack.lo \
|
||||||
net/http/cookiejar.lo net/http/fcgi.lo net/http/httptest.lo \
|
golang_org/x/net/lex/httplex.lo $(golang_org_x_net_route_lo) \
|
||||||
|
hash/adler32.lo hash/crc32.lo hash/crc64.lo hash/fnv.lo \
|
||||||
|
net/http/cgi.lo net/http/cookiejar.lo net/http/fcgi.lo \
|
||||||
|
net/http/httptest.lo net/http/httptrace.lo \
|
||||||
net/http/httputil.lo net/http/internal.lo net/http/pprof.lo \
|
net/http/httputil.lo net/http/internal.lo net/http/pprof.lo \
|
||||||
image/color.lo image/color/palette.lo image/draw.lo \
|
image/color.lo image/color/palette.lo image/draw.lo \
|
||||||
image/gif.lo image/internal/imageutil.lo image/jpeg.lo \
|
image/gif.lo image/internal/imageutil.lo image/jpeg.lo \
|
||||||
image/png.lo index/suffixarray.lo \
|
image/png.lo index/suffixarray.lo internal/nettrace.lo \
|
||||||
internal/golang.org/x/net/http2/hpack.lo internal/race.lo \
|
internal/race.lo internal/singleflight.lo \
|
||||||
internal/singleflight.lo internal/syscall/unix.lo \
|
internal/syscall/unix.lo internal/testenv.lo internal/trace.lo \
|
||||||
internal/testenv.lo internal/trace.lo io/ioutil.lo \
|
io/ioutil.lo log/syslog.lo log/syslog/syslog_c.lo math/big.lo \
|
||||||
log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \
|
math/cmplx.lo math/rand.lo mime/multipart.lo \
|
||||||
math/rand.lo mime/multipart.lo mime/quotedprintable.lo \
|
mime/quotedprintable.lo net/http.lo net/internal/socktest.lo \
|
||||||
net/http.lo net/internal/socktest.lo net/mail.lo net/rpc.lo \
|
net/mail.lo net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
|
||||||
net/smtp.lo net/textproto.lo net/url.lo old/regexp.lo \
|
old/regexp.lo old/template.lo os/exec.lo $(am__DEPENDENCIES_1) \
|
||||||
old/template.lo os/exec.lo $(am__DEPENDENCIES_1) os/signal.lo \
|
os/signal.lo os/user.lo path/filepath.lo regexp/syntax.lo \
|
||||||
os/user.lo path/filepath.lo regexp/syntax.lo \
|
|
||||||
net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
|
net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
|
||||||
sync/atomic.lo sync/atomic_c.lo text/scanner.lo \
|
sync/atomic.lo sync/atomic_c.lo text/scanner.lo \
|
||||||
text/tabwriter.lo text/template.lo text/template/parse.lo \
|
text/tabwriter.lo text/template.lo text/template/parse.lo \
|
||||||
|
|
@ -576,6 +578,7 @@ FLAGS_TO_PASS = $(AM_MAKEFLAGS)
|
||||||
toolexeclibgo_DATA = \
|
toolexeclibgo_DATA = \
|
||||||
bufio.gox \
|
bufio.gox \
|
||||||
bytes.gox \
|
bytes.gox \
|
||||||
|
context.gox \
|
||||||
crypto.gox \
|
crypto.gox \
|
||||||
encoding.gox \
|
encoding.gox \
|
||||||
errors.gox \
|
errors.gox \
|
||||||
|
|
@ -758,6 +761,7 @@ toolexeclibgonethttp_DATA = \
|
||||||
net/http/cookiejar.gox \
|
net/http/cookiejar.gox \
|
||||||
net/http/fcgi.gox \
|
net/http/fcgi.gox \
|
||||||
net/http/httptest.gox \
|
net/http/httptest.gox \
|
||||||
|
net/http/httptrace.gox \
|
||||||
net/http/httputil.gox \
|
net/http/httputil.gox \
|
||||||
net/http/pprof.gox
|
net/http/pprof.gox
|
||||||
|
|
||||||
|
|
@ -946,6 +950,9 @@ go_bytes_files = \
|
||||||
go_bytes_c_files = \
|
go_bytes_c_files = \
|
||||||
go/bytes/indexbyte.c
|
go/bytes/indexbyte.c
|
||||||
|
|
||||||
|
go_context_files = \
|
||||||
|
go/context/context.go
|
||||||
|
|
||||||
go_crypto_files = \
|
go_crypto_files = \
|
||||||
go/crypto/crypto.go
|
go/crypto/crypto.go
|
||||||
|
|
||||||
|
|
@ -1086,9 +1093,10 @@ go_mime_files = \
|
||||||
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_dragonfly.go
|
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_dragonfly.go
|
||||||
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go
|
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go
|
||||||
@LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
|
@LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
|
||||||
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_stub.go
|
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@go_net_interface_file = go/net/interface_stub.go
|
||||||
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_dragonfly.go
|
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_TRUE@go_net_interface_file = go/net/interface_bsdvar.go
|
||||||
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@go_net_interface_file = go/net/interface_netbsd.go
|
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_bsdvar.go
|
||||||
|
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@go_net_interface_file = go/net/interface_bsdvar.go
|
||||||
@LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go
|
@LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go
|
||||||
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go
|
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go
|
||||||
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
|
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
|
||||||
|
|
@ -1129,6 +1137,7 @@ go_net_common_files = \
|
||||||
go/net/nss.go \
|
go/net/nss.go \
|
||||||
go/net/parse.go \
|
go/net/parse.go \
|
||||||
go/net/pipe.go \
|
go/net/pipe.go \
|
||||||
|
go/net/port.go \
|
||||||
go/net/fd_poll_runtime.go \
|
go/net/fd_poll_runtime.go \
|
||||||
go/net/port_unix.go \
|
go/net/port_unix.go \
|
||||||
$(go_net_sendfile_file) \
|
$(go_net_sendfile_file) \
|
||||||
|
|
@ -1190,6 +1199,10 @@ go_netgo_files = \
|
||||||
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
|
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
|
||||||
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
|
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
|
||||||
@LIBGO_IS_DARWIN_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
|
@LIBGO_IS_DARWIN_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
|
||||||
|
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_os_wait_file = go/os/wait_unimp.go
|
||||||
|
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_os_wait_file = go/os/wait_wait6.go
|
||||||
|
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@go_os_wait_file = go/os/wait_waitid.go
|
||||||
|
@LIBGO_IS_LINUX_TRUE@go_os_wait_file = go/os/wait_waitid.go
|
||||||
go_os_files = \
|
go_os_files = \
|
||||||
$(go_os_dir_file) \
|
$(go_os_dir_file) \
|
||||||
go/os/dir.go \
|
go/os/dir.go \
|
||||||
|
|
@ -1215,7 +1228,8 @@ go_os_files = \
|
||||||
$(go_os_sys_file) \
|
$(go_os_sys_file) \
|
||||||
$(go_os_cloexec_file) \
|
$(go_os_cloexec_file) \
|
||||||
go/os/types.go \
|
go/os/types.go \
|
||||||
go/os/types_unix.go
|
go/os/types_unix.go \
|
||||||
|
$(go_os_wait_file)
|
||||||
|
|
||||||
go_path_files = \
|
go_path_files = \
|
||||||
go/path/match.go \
|
go/path/match.go \
|
||||||
|
|
@ -1248,6 +1262,7 @@ go_runtime_files = \
|
||||||
go/runtime/error.go \
|
go/runtime/error.go \
|
||||||
go/runtime/extern.go \
|
go/runtime/extern.go \
|
||||||
go/runtime/mem.go \
|
go/runtime/mem.go \
|
||||||
|
go/runtime/symtab.go \
|
||||||
version.go
|
version.go
|
||||||
|
|
||||||
noinst_DATA = zstdpkglist.go
|
noinst_DATA = zstdpkglist.go
|
||||||
|
|
@ -1304,6 +1319,7 @@ go_testing_files = \
|
||||||
go/testing/benchmark.go \
|
go/testing/benchmark.go \
|
||||||
go/testing/cover.go \
|
go/testing/cover.go \
|
||||||
go/testing/example.go \
|
go/testing/example.go \
|
||||||
|
go/testing/match.go \
|
||||||
go/testing/testing.go
|
go/testing/testing.go
|
||||||
|
|
||||||
go_time_files = \
|
go_time_files = \
|
||||||
|
|
@ -1331,6 +1347,7 @@ go_unicode_files = \
|
||||||
@LIBGO_IS_SOLARIS_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
|
@LIBGO_IS_SOLARIS_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
|
||||||
go_archive_tar_files = \
|
go_archive_tar_files = \
|
||||||
go/archive/tar/common.go \
|
go/archive/tar/common.go \
|
||||||
|
go/archive/tar/format.go \
|
||||||
go/archive/tar/reader.go \
|
go/archive/tar/reader.go \
|
||||||
go/archive/tar/stat_unix.go \
|
go/archive/tar/stat_unix.go \
|
||||||
go/archive/tar/writer.go \
|
go/archive/tar/writer.go \
|
||||||
|
|
@ -1349,8 +1366,9 @@ go_compress_bzip2_files = \
|
||||||
go/compress/bzip2/move_to_front.go
|
go/compress/bzip2/move_to_front.go
|
||||||
|
|
||||||
go_compress_flate_files = \
|
go_compress_flate_files = \
|
||||||
go/compress/flate/copy.go \
|
|
||||||
go/compress/flate/deflate.go \
|
go/compress/flate/deflate.go \
|
||||||
|
go/compress/flate/deflatefast.go \
|
||||||
|
go/compress/flate/dict_decoder.go \
|
||||||
go/compress/flate/huffman_bit_writer.go \
|
go/compress/flate/huffman_bit_writer.go \
|
||||||
go/compress/flate/huffman_code.go \
|
go/compress/flate/huffman_code.go \
|
||||||
go/compress/flate/inflate.go \
|
go/compress/flate/inflate.go \
|
||||||
|
|
@ -1382,7 +1400,8 @@ go_crypto_aes_files = \
|
||||||
go/crypto/aes/block.go \
|
go/crypto/aes/block.go \
|
||||||
go/crypto/aes/cipher.go \
|
go/crypto/aes/cipher.go \
|
||||||
go/crypto/aes/cipher_generic.go \
|
go/crypto/aes/cipher_generic.go \
|
||||||
go/crypto/aes/const.go
|
go/crypto/aes/const.go \
|
||||||
|
go/crypto/aes/modes.go
|
||||||
|
|
||||||
go_crypto_cipher_files = \
|
go_crypto_cipher_files = \
|
||||||
go/crypto/cipher/cbc.go \
|
go/crypto/cipher/cbc.go \
|
||||||
|
|
@ -1418,7 +1437,8 @@ go_crypto_md5_files = \
|
||||||
go/crypto/md5/md5block.go \
|
go/crypto/md5/md5block.go \
|
||||||
go/crypto/md5/md5block_generic.go
|
go/crypto/md5/md5block_generic.go
|
||||||
|
|
||||||
@LIBGO_IS_LINUX_FALSE@crypto_rand_file =
|
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_FALSE@crypto_rand_file =
|
||||||
|
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_TRUE@crypto_rand_file = go/crypto/rand/rand_openbsd.go
|
||||||
@LIBGO_IS_LINUX_TRUE@crypto_rand_file = go/crypto/rand/rand_linux.go
|
@LIBGO_IS_LINUX_TRUE@crypto_rand_file = go/crypto/rand/rand_linux.go
|
||||||
go_crypto_rand_files = \
|
go_crypto_rand_files = \
|
||||||
go/crypto/rand/eagain.go \
|
go/crypto/rand/eagain.go \
|
||||||
|
|
@ -1443,11 +1463,13 @@ go_crypto_sha1_files = \
|
||||||
|
|
||||||
go_crypto_sha256_files = \
|
go_crypto_sha256_files = \
|
||||||
go/crypto/sha256/sha256.go \
|
go/crypto/sha256/sha256.go \
|
||||||
go/crypto/sha256/sha256block.go
|
go/crypto/sha256/sha256block.go \
|
||||||
|
go/crypto/sha256/sha256block_generic.go
|
||||||
|
|
||||||
go_crypto_sha512_files = \
|
go_crypto_sha512_files = \
|
||||||
go/crypto/sha512/sha512.go \
|
go/crypto/sha512/sha512.go \
|
||||||
go/crypto/sha512/sha512block.go
|
go/crypto/sha512/sha512block.go \
|
||||||
|
go/crypto/sha512/sha512block_generic.go
|
||||||
|
|
||||||
go_crypto_subtle_files = \
|
go_crypto_subtle_files = \
|
||||||
go/crypto/subtle/constant_time.go
|
go/crypto/subtle/constant_time.go
|
||||||
|
|
@ -1523,7 +1545,10 @@ go_debug_macho_files = \
|
||||||
|
|
||||||
go_debug_pe_files = \
|
go_debug_pe_files = \
|
||||||
go/debug/pe/file.go \
|
go/debug/pe/file.go \
|
||||||
go/debug/pe/pe.go
|
go/debug/pe/pe.go \
|
||||||
|
go/debug/pe/section.go \
|
||||||
|
go/debug/pe/string.go \
|
||||||
|
go/debug/pe/symbol.go
|
||||||
|
|
||||||
go_debug_plan9obj_files = \
|
go_debug_plan9obj_files = \
|
||||||
go/debug/plan9obj/file.go \
|
go/debug/plan9obj/file.go \
|
||||||
|
|
@ -1688,6 +1713,39 @@ go_go_internal_gccgoimporter_files = \
|
||||||
go/go/internal/gccgoimporter/importer.go \
|
go/go/internal/gccgoimporter/importer.go \
|
||||||
go/go/internal/gccgoimporter/parser.go
|
go/go/internal/gccgoimporter/parser.go
|
||||||
|
|
||||||
|
go_golang_org_x_net_http2_hpack_files = \
|
||||||
|
go/golang_org/x/net/http2/hpack/encode.go \
|
||||||
|
go/golang_org/x/net/http2/hpack/hpack.go \
|
||||||
|
go/golang_org/x/net/http2/hpack/huffman.go \
|
||||||
|
go/golang_org/x/net/http2/hpack/tables.go
|
||||||
|
|
||||||
|
go_golang_org_x_net_lex_httplex_files = \
|
||||||
|
go/golang_org/x/net/lex/httplex/httplex.go
|
||||||
|
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DARWIN_TRUE@x_net_route_files =
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DRAGONFLY_TRUE@x_net_route_files =
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@x_net_route_files =
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_NETBSD_TRUE@x_net_route_files =
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_OPENBSD_TRUE@x_net_route_files =
|
||||||
|
@LIBGO_IS_386_TRUE@@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@x_net_route_freebsd_file =
|
||||||
|
@LIBGO_IS_ARM_TRUE@@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@x_net_route_freebsd_file =
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_X86_64_TRUE@x_net_route_freebsd_file =
|
||||||
|
@LIBGO_IS_BSD_TRUE@go_golang_org_x_net_route_files = \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ go/golang_org/x/net/route/address.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ go/golang_org/x/net/route/binary.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ go/golang_org/x/net/route/interface.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ go/golang_org/x/net/route/message.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ go/golang_org/x/net/route/route.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ go/golang_org/x/net/route/syscall.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ go/golang_org/x/net/route/sys.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ $(x_net_route_files)
|
||||||
|
|
||||||
|
@LIBGO_IS_BSD_TRUE@golang_org_x_net_route_lo = \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ golang_org/x/net/route/route.lo
|
||||||
|
|
||||||
|
@LIBGO_IS_BSD_TRUE@golang_org_x_net_route_check = \
|
||||||
|
@LIBGO_IS_BSD_TRUE@ golang_org/x/net/route/check
|
||||||
|
|
||||||
go_hash_adler32_files = \
|
go_hash_adler32_files = \
|
||||||
go/hash/adler32/adler32.go
|
go/hash/adler32/adler32.go
|
||||||
|
|
||||||
|
|
@ -1750,11 +1808,8 @@ go_index_suffixarray_files = \
|
||||||
go/index/suffixarray/qsufsort.go \
|
go/index/suffixarray/qsufsort.go \
|
||||||
go/index/suffixarray/suffixarray.go
|
go/index/suffixarray/suffixarray.go
|
||||||
|
|
||||||
go_internal_golang_org_x_net_http2_hpack_files = \
|
go_internal_nettrace_files = \
|
||||||
go/internal/golang.org/x/net/http2/hpack/encode.go \
|
go/internal/nettrace/nettrace.go
|
||||||
go/internal/golang.org/x/net/http2/hpack/hpack.go \
|
|
||||||
go/internal/golang.org/x/net/http2/hpack/huffman.go \
|
|
||||||
go/internal/golang.org/x/net/http2/hpack/tables.go
|
|
||||||
|
|
||||||
go_internal_race_files = \
|
go_internal_race_files = \
|
||||||
go/internal/race/doc.go \
|
go/internal/race/doc.go \
|
||||||
|
|
@ -1763,13 +1818,15 @@ go_internal_race_files = \
|
||||||
go_internal_singleflight_files = \
|
go_internal_singleflight_files = \
|
||||||
go/internal/singleflight/singleflight.go
|
go/internal/singleflight/singleflight.go
|
||||||
|
|
||||||
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_MIPS64_FALSE@@LIBGO_IS_PPC64_FALSE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_generic.go
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_MIPS64_FALSE@@LIBGO_IS_PPC64_FALSE@@LIBGO_IS_S390X_FALSE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_generic.go
|
||||||
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_MIPS64_FALSE@@LIBGO_IS_PPC64_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_s390x.go
|
||||||
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_MIPS64_TRUE@@LIBGO_IS_PPC64_FALSE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_mips64x.go
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_MIPS64_TRUE@@LIBGO_IS_PPC64_FALSE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_mips64x.go
|
||||||
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_PPC64_TRUE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_ppc64x.go
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_PPC64_TRUE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_ppc64x.go
|
||||||
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_TRUE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_arm.go
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_ARM_TRUE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_X86_64_FALSE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_arm.go
|
||||||
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_X86_64_TRUE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_amd64.go
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_X86_64_TRUE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_amd64.go
|
||||||
@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_TRUE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_386.go
|
@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_TRUE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_386.go
|
||||||
@LIBGO_IS_LINUX_FALSE@internal_syscall_unix_getrandom_files =
|
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_FALSE@internal_syscall_unix_getrandom_files =
|
||||||
|
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_TRUE@internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getentropy_openbsd.go
|
||||||
go_internal_syscall_unix_files = \
|
go_internal_syscall_unix_files = \
|
||||||
go/internal/syscall/unix/dummy.go \
|
go/internal/syscall/unix/dummy.go \
|
||||||
$(internal_syscall_unix_getrandom_files)
|
$(internal_syscall_unix_getrandom_files)
|
||||||
|
|
@ -1779,6 +1836,7 @@ go_internal_testenv_files = \
|
||||||
|
|
||||||
go_internal_trace_files = \
|
go_internal_trace_files = \
|
||||||
go/internal/trace/goroutines.go \
|
go/internal/trace/goroutines.go \
|
||||||
|
go/internal/trace/order.go \
|
||||||
go/internal/trace/parser.go
|
go/internal/trace/parser.go
|
||||||
|
|
||||||
go_io_ioutil_files = \
|
go_io_ioutil_files = \
|
||||||
|
|
@ -1844,8 +1902,8 @@ go_net_http_files = \
|
||||||
go/net/http/fs.go \
|
go/net/http/fs.go \
|
||||||
go/net/http/h2_bundle.go \
|
go/net/http/h2_bundle.go \
|
||||||
go/net/http/header.go \
|
go/net/http/header.go \
|
||||||
|
go/net/http/http.go \
|
||||||
go/net/http/jar.go \
|
go/net/http/jar.go \
|
||||||
go/net/http/lex.go \
|
|
||||||
go/net/http/method.go \
|
go/net/http/method.go \
|
||||||
go/net/http/request.go \
|
go/net/http/request.go \
|
||||||
go/net/http/response.go \
|
go/net/http/response.go \
|
||||||
|
|
@ -1885,12 +1943,16 @@ go_net_http_fcgi_files = \
|
||||||
go/net/http/fcgi/fcgi.go
|
go/net/http/fcgi/fcgi.go
|
||||||
|
|
||||||
go_net_http_httptest_files = \
|
go_net_http_httptest_files = \
|
||||||
|
go/net/http/httptest/httptest.go \
|
||||||
go/net/http/httptest/recorder.go \
|
go/net/http/httptest/recorder.go \
|
||||||
go/net/http/httptest/server.go
|
go/net/http/httptest/server.go
|
||||||
|
|
||||||
go_net_http_pprof_files = \
|
go_net_http_pprof_files = \
|
||||||
go/net/http/pprof/pprof.go
|
go/net/http/pprof/pprof.go
|
||||||
|
|
||||||
|
go_net_http_httptrace_files = \
|
||||||
|
go/net/http/httptrace/trace.go
|
||||||
|
|
||||||
go_net_http_httputil_files = \
|
go_net_http_httputil_files = \
|
||||||
go/net/http/httputil/dump.go \
|
go/net/http/httputil/dump.go \
|
||||||
go/net/http/httputil/httputil.go \
|
go/net/http/httputil/httputil.go \
|
||||||
|
|
@ -1932,11 +1994,14 @@ go_os_signal_files = \
|
||||||
|
|
||||||
@LIBGO_IS_SOLARIS_FALSE@os_user_decls_file = go/os/user/decls_unix.go
|
@LIBGO_IS_SOLARIS_FALSE@os_user_decls_file = go/os/user/decls_unix.go
|
||||||
@LIBGO_IS_SOLARIS_TRUE@os_user_decls_file = go/os/user/decls_solaris.go
|
@LIBGO_IS_SOLARIS_TRUE@os_user_decls_file = go/os/user/decls_solaris.go
|
||||||
|
@LIBGO_IS_SOLARIS_FALSE@os_user_listgroups_file = go/os/user/listgroups_unix.go
|
||||||
|
@LIBGO_IS_SOLARIS_TRUE@os_user_listgroups_file = go/os/user/listgroups_solaris.go
|
||||||
go_os_user_files = \
|
go_os_user_files = \
|
||||||
go/os/user/lookup.go \
|
go/os/user/lookup.go \
|
||||||
go/os/user/lookup_unix.go \
|
go/os/user/lookup_unix.go \
|
||||||
go/os/user/user.go \
|
go/os/user/user.go \
|
||||||
$(os_user_decls_file)
|
$(os_user_decls_file) \
|
||||||
|
$(os_user_listgroups_file)
|
||||||
|
|
||||||
go_path_filepath_files = \
|
go_path_filepath_files = \
|
||||||
go/path/filepath/match.go \
|
go/path/filepath/match.go \
|
||||||
|
|
@ -2158,6 +2223,7 @@ libgo_go_objs = \
|
||||||
bufio.lo \
|
bufio.lo \
|
||||||
bytes.lo \
|
bytes.lo \
|
||||||
bytes/index.lo \
|
bytes/index.lo \
|
||||||
|
context.lo \
|
||||||
crypto.lo \
|
crypto.lo \
|
||||||
encoding.lo \
|
encoding.lo \
|
||||||
errors.lo \
|
errors.lo \
|
||||||
|
|
@ -2253,6 +2319,9 @@ libgo_go_objs = \
|
||||||
go/scanner.lo \
|
go/scanner.lo \
|
||||||
go/token.lo \
|
go/token.lo \
|
||||||
go/types.lo \
|
go/types.lo \
|
||||||
|
golang_org/x/net/http2/hpack.lo \
|
||||||
|
golang_org/x/net/lex/httplex.lo \
|
||||||
|
$(golang_org_x_net_route_lo) \
|
||||||
hash/adler32.lo \
|
hash/adler32.lo \
|
||||||
hash/crc32.lo \
|
hash/crc32.lo \
|
||||||
hash/crc64.lo \
|
hash/crc64.lo \
|
||||||
|
|
@ -2261,6 +2330,7 @@ libgo_go_objs = \
|
||||||
net/http/cookiejar.lo \
|
net/http/cookiejar.lo \
|
||||||
net/http/fcgi.lo \
|
net/http/fcgi.lo \
|
||||||
net/http/httptest.lo \
|
net/http/httptest.lo \
|
||||||
|
net/http/httptrace.lo \
|
||||||
net/http/httputil.lo \
|
net/http/httputil.lo \
|
||||||
net/http/internal.lo \
|
net/http/internal.lo \
|
||||||
net/http/pprof.lo \
|
net/http/pprof.lo \
|
||||||
|
|
@ -2272,7 +2342,7 @@ libgo_go_objs = \
|
||||||
image/jpeg.lo \
|
image/jpeg.lo \
|
||||||
image/png.lo \
|
image/png.lo \
|
||||||
index/suffixarray.lo \
|
index/suffixarray.lo \
|
||||||
internal/golang.org/x/net/http2/hpack.lo \
|
internal/nettrace.lo \
|
||||||
internal/race.lo \
|
internal/race.lo \
|
||||||
internal/singleflight.lo \
|
internal/singleflight.lo \
|
||||||
internal/syscall/unix.lo \
|
internal/syscall/unix.lo \
|
||||||
|
|
@ -2439,6 +2509,7 @@ BUILDGOX = \
|
||||||
TEST_PACKAGES = \
|
TEST_PACKAGES = \
|
||||||
bufio/check \
|
bufio/check \
|
||||||
bytes/check \
|
bytes/check \
|
||||||
|
context/check \
|
||||||
errors/check \
|
errors/check \
|
||||||
expvar/check \
|
expvar/check \
|
||||||
flag/check \
|
flag/check \
|
||||||
|
|
@ -2522,6 +2593,9 @@ TEST_PACKAGES = \
|
||||||
go/scanner/check \
|
go/scanner/check \
|
||||||
go/token/check \
|
go/token/check \
|
||||||
go/types/check \
|
go/types/check \
|
||||||
|
golang_org/x/net/http2/hpack/check \
|
||||||
|
golang_org/x/net/lex/httplex/check \
|
||||||
|
$(golang_org_x_net_route_check) \
|
||||||
hash/adler32/check \
|
hash/adler32/check \
|
||||||
hash/crc32/check \
|
hash/crc32/check \
|
||||||
hash/crc64/check \
|
hash/crc64/check \
|
||||||
|
|
@ -2531,7 +2605,6 @@ TEST_PACKAGES = \
|
||||||
image/jpeg/check \
|
image/jpeg/check \
|
||||||
image/png/check \
|
image/png/check \
|
||||||
index/suffixarray/check \
|
index/suffixarray/check \
|
||||||
internal/golang.org/x/net/http2/hpack/check \
|
|
||||||
internal/singleflight/check \
|
internal/singleflight/check \
|
||||||
internal/trace/check \
|
internal/trace/check \
|
||||||
io/ioutil/check \
|
io/ioutil/check \
|
||||||
|
|
@ -2546,6 +2619,7 @@ TEST_PACKAGES = \
|
||||||
net/http/cookiejar/check \
|
net/http/cookiejar/check \
|
||||||
net/http/fcgi/check \
|
net/http/fcgi/check \
|
||||||
net/http/httptest/check \
|
net/http/httptest/check \
|
||||||
|
net/http/httptrace/check \
|
||||||
net/http/httputil/check \
|
net/http/httputil/check \
|
||||||
net/http/internal/check \
|
net/http/internal/check \
|
||||||
net/internal/socktest/check \
|
net/internal/socktest/check \
|
||||||
|
|
@ -4761,6 +4835,34 @@ s-zstdpkglist: Makefile
|
||||||
echo '}' >> zstdpkglist.go.tmp
|
echo '}' >> zstdpkglist.go.tmp
|
||||||
$(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
|
$(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
|
||||||
$(STAMP) $@
|
$(STAMP) $@
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DARWIN_TRUE@ go/golang_org/x/net/route/interface_classic.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DARWIN_TRUE@ go/golang_org/x/net/route/interface_multicast.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DARWIN_TRUE@ go/golang_org/x/net/route/route_classic.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DARWIN_TRUE@ go/golang_org/x/net/route/sys_darwin.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DARWIN_TRUE@ go/golang_org/x/net/route/zsys_darwin.go
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DRAGONFLY_TRUE@ go/golang_org/x/net/route/interface_announce.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DRAGONFLY_TRUE@ go/golang_org/x/net/route/interface_classic.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DRAGONFLY_TRUE@ go/golang_org/x/net/route/interface_multicast.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DRAGONFLY_TRUE@ go/golang_org/x/net/route/route_classic.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DRAGONFLY_TRUE@ go/golang_org/x/net/route/sys_dragonfly.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_DRAGONFLY_TRUE@ go/golang_org/x/net/route/zsys_dragonfly.go
|
||||||
|
@LIBGO_IS_386_TRUE@@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ go/golang_org/x/net/route/zsys_freebsd_386.go
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_X86_64_TRUE@ go/golang_org/x/net/route/zsys_freebsd_amd64.go
|
||||||
|
@LIBGO_IS_ARM_TRUE@@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ go/golang_org/x/net/route/zsys_freebsd_arm.go
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ go/golang_org/x/net/route/interface_announce.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ go/golang_org/x/net/route/interface_freebsd.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ go/golang_org/x/net/route/interface_multicast.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ go/golang_org/x/net/route/route_classic.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ go/golang_org/x/net/route/sys_freebsd.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_FREEBSD_TRUE@ $(x_net_route_freebsd_file)
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_NETBSD_TRUE@ go/golang_org/x/net/route/interface_announce.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_NETBSD_TRUE@ go/golang_org/x/net/route/interface_classic.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_NETBSD_TRUE@ go/golang_org/x/net/route/route_classic.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_NETBSD_TRUE@ go/golang_org/x/net/route/sys_netbsd.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_NETBSD_TRUE@ go/golang_org/x/net/route/zsys_netbsd.go
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_OPENBSD_TRUE@ go/golang_org/x/net/route/route_openbsd.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_OPENBSD_TRUE@ go/golang_org/x/net/route/sys_openbsd.go \
|
||||||
|
@LIBGO_IS_BSD_TRUE@@LIBGO_IS_OPENBSD_TRUE@ go/golang_org/x/net/route/zsys_openbsd.go
|
||||||
|
|
||||||
libcalls.go: s-libcalls; @true
|
libcalls.go: s-libcalls; @true
|
||||||
s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files)
|
s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files)
|
||||||
|
|
@ -4841,6 +4943,15 @@ bytes/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: bytes/check
|
.PHONY: bytes/check
|
||||||
|
|
||||||
|
@go_include@ context.lo.dep
|
||||||
|
context.lo.dep: $(go_context_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
context.lo: $(go_context_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
context/check: $(CHECK_DEPS)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: context/check
|
||||||
|
|
||||||
@go_include@ crypto.lo.dep
|
@go_include@ crypto.lo.dep
|
||||||
crypto.lo.dep: $(go_crypto_files)
|
crypto.lo.dep: $(go_crypto_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
|
|
@ -5656,6 +5767,33 @@ go/internal/gccgoimporter/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: go/internal/gccgoimporter/check
|
.PHONY: go/internal/gccgoimporter/check
|
||||||
|
|
||||||
|
@go_include@ golang_org/x/net/http2/hpack.lo.dep
|
||||||
|
golang_org/x/net/http2/hpack.lo.dep: $(go_golang_org_x_net_http2_hpack_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
golang_org/x/net/http2/hpack.lo: $(go_golang_org_x_net_http2_hpack_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
golang_org/x/net/http2/hpack/check: $(CHECK_DEPS)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: golang_org/x/net/http2/hpack/check
|
||||||
|
|
||||||
|
@go_include@ golang_org/x/net/lex/httplex.lo.dep
|
||||||
|
golang_org/x/net/lex/httplex.lo.dep: $(go_golang_org_x_net_lex_httplex_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
golang_org/x/net/lex/httplex.lo: $(go_golang_org_x_net_lex_httplex_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
golang_org/x/net/lex/httplex/check: $(CHECK_DEPS)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: golang_org/x/net/lex/httplex/check
|
||||||
|
|
||||||
|
@LIBGO_IS_BSD_TRUE@@go_include@ golang_org/x/net/route.lo.dep
|
||||||
|
@LIBGO_IS_BSD_TRUE@golang_org/x/net/route.lo.dep: $(go_golang_org_x_net_route_files)
|
||||||
|
@LIBGO_IS_BSD_TRUE@ $(BUILDDEPS)
|
||||||
|
@LIBGO_IS_BSD_TRUE@golang_org/x/net/route.lo: $(go_golang_org_x_net_route_files)
|
||||||
|
@LIBGO_IS_BSD_TRUE@ $(BUILDPACKAGE)
|
||||||
|
@LIBGO_IS_BSD_TRUE@golang_org/x/net/route/check: $(CHECK_DEPS)
|
||||||
|
@LIBGO_IS_BSD_TRUE@ @$(CHECK)
|
||||||
|
.PHONY: golang_org/x/net/route/check
|
||||||
|
|
||||||
@go_include@ hash/adler32.lo.dep
|
@go_include@ hash/adler32.lo.dep
|
||||||
hash/adler32.lo.dep: $(go_hash_adler32_files)
|
hash/adler32.lo.dep: $(go_hash_adler32_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
|
|
@ -5764,14 +5902,14 @@ index/suffixarray/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: index/suffixarray/check
|
.PHONY: index/suffixarray/check
|
||||||
|
|
||||||
@go_include@ internal/golang.org/x/net/http2/hpack.lo.dep
|
@go_include@ internal/nettrace.lo.dep
|
||||||
internal/golang.org/x/net/http2/hpack.lo.dep: $(go_internal_golang_org_x_net_http2_hpack_files)
|
internal/nettrace.lo.dep: $(go_internal_nettrace_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
internal/golang.org/x/net/http2/hpack.lo: $(go_internal_golang_org_x_net_http2_hpack_files)
|
internal/nettrace.lo: $(go_internal_nettrace_files)
|
||||||
$(BUILDPACKAGE)
|
$(BUILDPACKAGE)
|
||||||
internal/golang.org/x/net/http2/hpack/check: $(CHECK_DEPS)
|
internal/nettrace/check: $(CHECK_DEPS)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: internal/golang.org/x/net/http2/hpack/check
|
.PHONY: internal/nettrace/check
|
||||||
|
|
||||||
@go_include@ internal/race.lo.dep
|
@go_include@ internal/race.lo.dep
|
||||||
internal/race.lo.dep: $(go_internal_race_files)
|
internal/race.lo.dep: $(go_internal_race_files)
|
||||||
|
|
@ -5974,6 +6112,15 @@ net/http/httptest/check: $(check_deps)
|
||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: net/http/httptest/check
|
.PHONY: net/http/httptest/check
|
||||||
|
|
||||||
|
@go_include@ net/http/httptrace.lo.dep
|
||||||
|
net/http/httptrace.lo.dep: $(go_net_http_httptrace_files)
|
||||||
|
$(BUILDDEPS)
|
||||||
|
net/http/httptrace.lo: $(go_net_http_httptrace_files)
|
||||||
|
$(BUILDPACKAGE)
|
||||||
|
net/http/httptrace/check: $(check_deps)
|
||||||
|
@$(CHECK)
|
||||||
|
.PHONY: net/http/httptrace/check
|
||||||
|
|
||||||
@go_include@ net/http/httputil.lo.dep
|
@go_include@ net/http/httputil.lo.dep
|
||||||
net/http/httputil.lo.dep: $(go_net_http_httputil_files)
|
net/http/httputil.lo.dep: $(go_net_http_httputil_files)
|
||||||
$(BUILDDEPS)
|
$(BUILDDEPS)
|
||||||
|
|
@ -6205,6 +6352,8 @@ bufio.gox: bufio.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
bytes.gox: bytes.lo
|
bytes.gox: bytes.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
context.gox: context.lo
|
||||||
|
$(BUILDGOX)
|
||||||
crypto.gox: crypto.lo
|
crypto.gox: crypto.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
encoding.gox: encoding.lo
|
encoding.gox: encoding.lo
|
||||||
|
|
@ -6399,6 +6548,15 @@ go/internal/gcimporter.gox: go/internal/gcimporter.lo
|
||||||
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
|
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
|
||||||
|
golang_org/x/net/http2/hpack.gox: golang_org/x/net/http2/hpack.lo
|
||||||
|
$(BUILDGOX)
|
||||||
|
|
||||||
|
golang_org/x/net/lex/httplex.gox: golang_org/x/net/lex/httplex.lo
|
||||||
|
$(BUILDGOX)
|
||||||
|
|
||||||
|
@LIBGO_IS_BSD_TRUE@golang_org/x/net/route.gox: golang_org/x/net/route.lo
|
||||||
|
@LIBGO_IS_BSD_TRUE@ $(BUILDGOX)
|
||||||
|
|
||||||
hash/adler32.gox: hash/adler32.lo
|
hash/adler32.gox: hash/adler32.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
hash/crc32.gox: hash/crc32.lo
|
hash/crc32.gox: hash/crc32.lo
|
||||||
|
|
@ -6427,7 +6585,7 @@ image/color/palette.gox: image/color/palette.lo
|
||||||
index/suffixarray.gox: index/suffixarray.lo
|
index/suffixarray.gox: index/suffixarray.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
|
||||||
internal/golang.org/x/net/http2/hpack.gox: internal/golang.org/x/net/http2/hpack.lo
|
internal/nettrace.gox: internal/nettrace.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
internal/race.gox: internal/race.lo
|
internal/race.gox: internal/race.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
|
@ -6479,6 +6637,8 @@ net/http/fcgi.gox: net/http/fcgi.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
net/http/httptest.gox: net/http/httptest.lo
|
net/http/httptest.gox: net/http/httptest.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
net/http/httptrace.gox: net/http/httptrace.lo
|
||||||
|
$(BUILDGOX)
|
||||||
net/http/httputil.gox: net/http/httputil.lo
|
net/http/httputil.gox: net/http/httputil.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
net/http/pprof.gox: net/http/pprof.lo
|
net/http/pprof.gox: net/http/pprof.lo
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
go1.6.1
|
go1.7rc3
|
||||||
|
|
|
||||||
|
|
@ -670,6 +670,8 @@ LIBGO_IS_386_FALSE
|
||||||
LIBGO_IS_386_TRUE
|
LIBGO_IS_386_TRUE
|
||||||
USE_DEJAGNU
|
USE_DEJAGNU
|
||||||
GOOS
|
GOOS
|
||||||
|
LIBGO_IS_BSD_FALSE
|
||||||
|
LIBGO_IS_BSD_TRUE
|
||||||
LIBGO_IS_SOLARIS_FALSE
|
LIBGO_IS_SOLARIS_FALSE
|
||||||
LIBGO_IS_SOLARIS_TRUE
|
LIBGO_IS_SOLARIS_TRUE
|
||||||
LIBGO_IS_RTEMS_FALSE
|
LIBGO_IS_RTEMS_FALSE
|
||||||
|
|
@ -11126,7 +11128,7 @@ else
|
||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<_LT_EOF
|
cat > conftest.$ac_ext <<_LT_EOF
|
||||||
#line 11129 "configure"
|
#line 11131 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
|
|
@ -11232,7 +11234,7 @@ else
|
||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<_LT_EOF
|
cat > conftest.$ac_ext <<_LT_EOF
|
||||||
#line 11235 "configure"
|
#line 11237 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
|
|
@ -13611,6 +13613,14 @@ else
|
||||||
LIBGO_IS_SOLARIS_FALSE=
|
LIBGO_IS_SOLARIS_FALSE=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test $is_darwin = yes -o $is_dragonfly = yes -o $is_freebsd = yes -o $is_netbsd = yes -o $is_openbsd = yes; then
|
||||||
|
LIBGO_IS_BSD_TRUE=
|
||||||
|
LIBGO_IS_BSD_FALSE='#'
|
||||||
|
else
|
||||||
|
LIBGO_IS_BSD_TRUE='#'
|
||||||
|
LIBGO_IS_BSD_FALSE=
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
USE_DEJAGNU=no
|
USE_DEJAGNU=no
|
||||||
|
|
@ -15769,6 +15779,10 @@ if test -z "${LIBGO_IS_SOLARIS_TRUE}" && test -z "${LIBGO_IS_SOLARIS_FALSE}"; th
|
||||||
as_fn_error "conditional \"LIBGO_IS_SOLARIS\" was never defined.
|
as_fn_error "conditional \"LIBGO_IS_SOLARIS\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
fi
|
fi
|
||||||
|
if test -z "${LIBGO_IS_BSD_TRUE}" && test -z "${LIBGO_IS_BSD_FALSE}"; then
|
||||||
|
as_fn_error "conditional \"LIBGO_IS_BSD\" was never defined.
|
||||||
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
|
fi
|
||||||
if test -z "${LIBGO_IS_386_TRUE}" && test -z "${LIBGO_IS_386_FALSE}"; then
|
if test -z "${LIBGO_IS_386_TRUE}" && test -z "${LIBGO_IS_386_FALSE}"; then
|
||||||
as_fn_error "conditional \"LIBGO_IS_386\" was never defined.
|
as_fn_error "conditional \"LIBGO_IS_386\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ AM_CONDITIONAL(LIBGO_IS_OPENBSD, test $is_openbsd = yes)
|
||||||
AM_CONDITIONAL(LIBGO_IS_DRAGONFLY, test $is_dragonfly = yes)
|
AM_CONDITIONAL(LIBGO_IS_DRAGONFLY, test $is_dragonfly = yes)
|
||||||
AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
|
AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
|
||||||
AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes)
|
AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes)
|
||||||
|
AM_CONDITIONAL(LIBGO_IS_BSD, test $is_darwin = yes -o $is_dragonfly = yes -o $is_freebsd = yes -o $is_netbsd = yes -o $is_openbsd = yes)
|
||||||
AC_SUBST(GOOS)
|
AC_SUBST(GOOS)
|
||||||
|
|
||||||
dnl Test whether we need to use DejaGNU or whether we can use the
|
dnl Test whether we need to use DejaGNU or whether we can use the
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Header type flags.
|
||||||
const (
|
const (
|
||||||
blockSize = 512
|
|
||||||
|
|
||||||
// Types
|
|
||||||
TypeReg = '0' // regular file
|
TypeReg = '0' // regular file
|
||||||
TypeRegA = '\x00' // regular file
|
TypeRegA = '\x00' // regular file
|
||||||
TypeLink = '1' // hard link
|
TypeLink = '1' // hard link
|
||||||
|
|
@ -61,12 +59,6 @@ type Header struct {
|
||||||
Xattrs map[string]string
|
Xattrs map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// File name constants from the tar spec.
|
|
||||||
const (
|
|
||||||
fileNameSize = 100 // Maximum number of bytes in a standard tar name.
|
|
||||||
fileNamePrefixSize = 155 // Maximum number of ustar extension bytes.
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileInfo returns an os.FileInfo for the Header.
|
// FileInfo returns an os.FileInfo for the Header.
|
||||||
func (h *Header) FileInfo() os.FileInfo {
|
func (h *Header) FileInfo() os.FileInfo {
|
||||||
return headerFileInfo{h}
|
return headerFileInfo{h}
|
||||||
|
|
@ -279,33 +271,6 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroBlock = make([]byte, blockSize)
|
|
||||||
|
|
||||||
// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values.
|
|
||||||
// We compute and return both.
|
|
||||||
func checksum(header []byte) (unsigned int64, signed int64) {
|
|
||||||
for i := 0; i < len(header); i++ {
|
|
||||||
if i == 148 {
|
|
||||||
// The chksum field (header[148:156]) is special: it should be treated as space bytes.
|
|
||||||
unsigned += ' ' * 8
|
|
||||||
signed += ' ' * 8
|
|
||||||
i += 7
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
unsigned += int64(header[i])
|
|
||||||
signed += int64(int8(header[i]))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type slicer []byte
|
|
||||||
|
|
||||||
func (sp *slicer) next(n int) (b []byte) {
|
|
||||||
s := *sp
|
|
||||||
b, *sp = s[0:n], s[n:]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func isASCII(s string) bool {
|
func isASCII(s string) bool {
|
||||||
for _, c := range s {
|
for _, c := range s {
|
||||||
if c >= 0x80 {
|
if c >= 0x80 {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
// Copyright 2016 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 tar
|
||||||
|
|
||||||
|
// Constants to identify various tar formats.
|
||||||
|
const (
|
||||||
|
// The format is unknown.
|
||||||
|
formatUnknown = (1 << iota) / 2 // Sequence of 0, 1, 2, 4, 8, etc...
|
||||||
|
|
||||||
|
// The format of the original Unix V7 tar tool prior to standardization.
|
||||||
|
formatV7
|
||||||
|
|
||||||
|
// The old and new GNU formats, which are incompatible with USTAR.
|
||||||
|
// This does cover the old GNU sparse extension.
|
||||||
|
// This does not cover the GNU sparse extensions using PAX headers,
|
||||||
|
// versions 0.0, 0.1, and 1.0; these fall under the PAX format.
|
||||||
|
formatGNU
|
||||||
|
|
||||||
|
// Schily's tar format, which is incompatible with USTAR.
|
||||||
|
// This does not cover STAR extensions to the PAX format; these fall under
|
||||||
|
// the PAX format.
|
||||||
|
formatSTAR
|
||||||
|
|
||||||
|
// USTAR is the former standardization of tar defined in POSIX.1-1988.
|
||||||
|
// This is incompatible with the GNU and STAR formats.
|
||||||
|
formatUSTAR
|
||||||
|
|
||||||
|
// PAX is the latest standardization of tar defined in POSIX.1-2001.
|
||||||
|
// This is an extension of USTAR and is "backwards compatible" with it.
|
||||||
|
//
|
||||||
|
// Some newer formats add their own extensions to PAX, such as GNU sparse
|
||||||
|
// files and SCHILY extended attributes. Since they are backwards compatible
|
||||||
|
// with PAX, they will be labelled as "PAX".
|
||||||
|
formatPAX
|
||||||
|
)
|
||||||
|
|
||||||
|
// Magics used to identify various formats.
|
||||||
|
const (
|
||||||
|
magicGNU, versionGNU = "ustar ", " \x00"
|
||||||
|
magicUSTAR, versionUSTAR = "ustar\x00", "00"
|
||||||
|
trailerSTAR = "tar\x00"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Size constants from various tar specifications.
|
||||||
|
const (
|
||||||
|
blockSize = 512 // Size of each block in a tar stream
|
||||||
|
nameSize = 100 // Max length of the name field in USTAR format
|
||||||
|
prefixSize = 155 // Max length of the prefix field in USTAR format
|
||||||
|
)
|
||||||
|
|
||||||
|
var zeroBlock block
|
||||||
|
|
||||||
|
type block [blockSize]byte
|
||||||
|
|
||||||
|
// Convert block to any number of formats.
|
||||||
|
func (b *block) V7() *headerV7 { return (*headerV7)(b) }
|
||||||
|
func (b *block) GNU() *headerGNU { return (*headerGNU)(b) }
|
||||||
|
func (b *block) STAR() *headerSTAR { return (*headerSTAR)(b) }
|
||||||
|
func (b *block) USTAR() *headerUSTAR { return (*headerUSTAR)(b) }
|
||||||
|
func (b *block) Sparse() sparseArray { return (sparseArray)(b[:]) }
|
||||||
|
|
||||||
|
// GetFormat checks that the block is a valid tar header based on the checksum.
|
||||||
|
// It then attempts to guess the specific format based on magic values.
|
||||||
|
// If the checksum fails, then formatUnknown is returned.
|
||||||
|
func (b *block) GetFormat() (format int) {
|
||||||
|
// Verify checksum.
|
||||||
|
var p parser
|
||||||
|
value := p.parseOctal(b.V7().Chksum())
|
||||||
|
chksum1, chksum2 := b.ComputeChecksum()
|
||||||
|
if p.err != nil || (value != chksum1 && value != chksum2) {
|
||||||
|
return formatUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guess the magic values.
|
||||||
|
magic := string(b.USTAR().Magic())
|
||||||
|
version := string(b.USTAR().Version())
|
||||||
|
trailer := string(b.STAR().Trailer())
|
||||||
|
switch {
|
||||||
|
case magic == magicUSTAR && trailer == trailerSTAR:
|
||||||
|
return formatSTAR
|
||||||
|
case magic == magicUSTAR:
|
||||||
|
return formatUSTAR
|
||||||
|
case magic == magicGNU && version == versionGNU:
|
||||||
|
return formatGNU
|
||||||
|
default:
|
||||||
|
return formatV7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFormat writes the magic values necessary for specified format
|
||||||
|
// and then updates the checksum accordingly.
|
||||||
|
func (b *block) SetFormat(format int) {
|
||||||
|
// Set the magic values.
|
||||||
|
switch format {
|
||||||
|
case formatV7:
|
||||||
|
// Do nothing.
|
||||||
|
case formatGNU:
|
||||||
|
copy(b.GNU().Magic(), magicGNU)
|
||||||
|
copy(b.GNU().Version(), versionGNU)
|
||||||
|
case formatSTAR:
|
||||||
|
copy(b.STAR().Magic(), magicUSTAR)
|
||||||
|
copy(b.STAR().Version(), versionUSTAR)
|
||||||
|
copy(b.STAR().Trailer(), trailerSTAR)
|
||||||
|
case formatUSTAR, formatPAX:
|
||||||
|
copy(b.USTAR().Magic(), magicUSTAR)
|
||||||
|
copy(b.USTAR().Version(), versionUSTAR)
|
||||||
|
default:
|
||||||
|
panic("invalid format")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update checksum.
|
||||||
|
// This field is special in that it is terminated by a NULL then space.
|
||||||
|
var f formatter
|
||||||
|
field := b.V7().Chksum()
|
||||||
|
chksum, _ := b.ComputeChecksum() // Possible values are 256..128776
|
||||||
|
f.formatOctal(field[:7], chksum) // Never fails since 128776 < 262143
|
||||||
|
field[7] = ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComputeChecksum computes the checksum for the header block.
|
||||||
|
// POSIX specifies a sum of the unsigned byte values, but the Sun tar used
|
||||||
|
// signed byte values.
|
||||||
|
// We compute and return both.
|
||||||
|
func (b *block) ComputeChecksum() (unsigned, signed int64) {
|
||||||
|
for i, c := range b {
|
||||||
|
if 148 <= i && i < 156 {
|
||||||
|
c = ' ' // Treat the checksum field itself as all spaces.
|
||||||
|
}
|
||||||
|
unsigned += int64(uint8(c))
|
||||||
|
signed += int64(int8(c))
|
||||||
|
}
|
||||||
|
return unsigned, signed
|
||||||
|
}
|
||||||
|
|
||||||
|
type headerV7 [blockSize]byte
|
||||||
|
|
||||||
|
func (h *headerV7) Name() []byte { return h[000:][:100] }
|
||||||
|
func (h *headerV7) Mode() []byte { return h[100:][:8] }
|
||||||
|
func (h *headerV7) UID() []byte { return h[108:][:8] }
|
||||||
|
func (h *headerV7) GID() []byte { return h[116:][:8] }
|
||||||
|
func (h *headerV7) Size() []byte { return h[124:][:12] }
|
||||||
|
func (h *headerV7) ModTime() []byte { return h[136:][:12] }
|
||||||
|
func (h *headerV7) Chksum() []byte { return h[148:][:8] }
|
||||||
|
func (h *headerV7) TypeFlag() []byte { return h[156:][:1] }
|
||||||
|
func (h *headerV7) LinkName() []byte { return h[157:][:100] }
|
||||||
|
|
||||||
|
type headerGNU [blockSize]byte
|
||||||
|
|
||||||
|
func (h *headerGNU) V7() *headerV7 { return (*headerV7)(h) }
|
||||||
|
func (h *headerGNU) Magic() []byte { return h[257:][:6] }
|
||||||
|
func (h *headerGNU) Version() []byte { return h[263:][:2] }
|
||||||
|
func (h *headerGNU) UserName() []byte { return h[265:][:32] }
|
||||||
|
func (h *headerGNU) GroupName() []byte { return h[297:][:32] }
|
||||||
|
func (h *headerGNU) DevMajor() []byte { return h[329:][:8] }
|
||||||
|
func (h *headerGNU) DevMinor() []byte { return h[337:][:8] }
|
||||||
|
func (h *headerGNU) AccessTime() []byte { return h[345:][:12] }
|
||||||
|
func (h *headerGNU) ChangeTime() []byte { return h[357:][:12] }
|
||||||
|
func (h *headerGNU) Sparse() sparseArray { return (sparseArray)(h[386:][:24*4+1]) }
|
||||||
|
func (h *headerGNU) RealSize() []byte { return h[483:][:12] }
|
||||||
|
|
||||||
|
type headerSTAR [blockSize]byte
|
||||||
|
|
||||||
|
func (h *headerSTAR) V7() *headerV7 { return (*headerV7)(h) }
|
||||||
|
func (h *headerSTAR) Magic() []byte { return h[257:][:6] }
|
||||||
|
func (h *headerSTAR) Version() []byte { return h[263:][:2] }
|
||||||
|
func (h *headerSTAR) UserName() []byte { return h[265:][:32] }
|
||||||
|
func (h *headerSTAR) GroupName() []byte { return h[297:][:32] }
|
||||||
|
func (h *headerSTAR) DevMajor() []byte { return h[329:][:8] }
|
||||||
|
func (h *headerSTAR) DevMinor() []byte { return h[337:][:8] }
|
||||||
|
func (h *headerSTAR) Prefix() []byte { return h[345:][:131] }
|
||||||
|
func (h *headerSTAR) AccessTime() []byte { return h[476:][:12] }
|
||||||
|
func (h *headerSTAR) ChangeTime() []byte { return h[488:][:12] }
|
||||||
|
func (h *headerSTAR) Trailer() []byte { return h[508:][:4] }
|
||||||
|
|
||||||
|
type headerUSTAR [blockSize]byte
|
||||||
|
|
||||||
|
func (h *headerUSTAR) V7() *headerV7 { return (*headerV7)(h) }
|
||||||
|
func (h *headerUSTAR) Magic() []byte { return h[257:][:6] }
|
||||||
|
func (h *headerUSTAR) Version() []byte { return h[263:][:2] }
|
||||||
|
func (h *headerUSTAR) UserName() []byte { return h[265:][:32] }
|
||||||
|
func (h *headerUSTAR) GroupName() []byte { return h[297:][:32] }
|
||||||
|
func (h *headerUSTAR) DevMajor() []byte { return h[329:][:8] }
|
||||||
|
func (h *headerUSTAR) DevMinor() []byte { return h[337:][:8] }
|
||||||
|
func (h *headerUSTAR) Prefix() []byte { return h[345:][:155] }
|
||||||
|
|
||||||
|
type sparseArray []byte
|
||||||
|
|
||||||
|
func (s sparseArray) Entry(i int) sparseNode { return (sparseNode)(s[i*24:]) }
|
||||||
|
func (s sparseArray) IsExtended() []byte { return s[24*s.MaxEntries():][:1] }
|
||||||
|
func (s sparseArray) MaxEntries() int { return len(s) / 24 }
|
||||||
|
|
||||||
|
type sparseNode []byte
|
||||||
|
|
||||||
|
func (s sparseNode) Offset() []byte { return s[00:][:12] }
|
||||||
|
func (s sparseNode) NumBytes() []byte { return s[12:][:12] }
|
||||||
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -30,11 +29,11 @@ const maxNanoSecondIntSize = 9
|
||||||
// The Next method advances to the next file in the archive (including the first),
|
// The Next method advances to the next file in the archive (including the first),
|
||||||
// and then it can be treated as an io.Reader to access the file's data.
|
// and then it can be treated as an io.Reader to access the file's data.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
r io.Reader
|
r io.Reader
|
||||||
err error
|
err error
|
||||||
pad int64 // amount of padding (ignored) after current file entry
|
pad int64 // amount of padding (ignored) after current file entry
|
||||||
curr numBytesReader // reader for current file entry
|
curr numBytesReader // reader for current file entry
|
||||||
hdrBuff [blockSize]byte // buffer to use in readHeader
|
blk block // buffer to use as temporary local storage
|
||||||
}
|
}
|
||||||
|
|
||||||
type parser struct {
|
type parser struct {
|
||||||
|
|
@ -99,17 +98,6 @@ const (
|
||||||
paxGNUSparseRealSize = "GNU.sparse.realsize"
|
paxGNUSparseRealSize = "GNU.sparse.realsize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Keywords for old GNU sparse headers
|
|
||||||
const (
|
|
||||||
oldGNUSparseMainHeaderOffset = 386
|
|
||||||
oldGNUSparseMainHeaderIsExtendedOffset = 482
|
|
||||||
oldGNUSparseMainHeaderNumEntries = 4
|
|
||||||
oldGNUSparseExtendedHeaderIsExtendedOffset = 504
|
|
||||||
oldGNUSparseExtendedHeaderNumEntries = 21
|
|
||||||
oldGNUSparseOffsetSize = 12
|
|
||||||
oldGNUSparseNumBytesSize = 12
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewReader creates a new Reader reading from r.
|
// NewReader creates a new Reader reading from r.
|
||||||
func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
|
func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
|
||||||
|
|
||||||
|
|
@ -307,7 +295,7 @@ func mergePAX(hdr *Header, headers map[string]string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hdr.Size = int64(size)
|
hdr.Size = size
|
||||||
default:
|
default:
|
||||||
if strings.HasPrefix(k, paxXattr) {
|
if strings.HasPrefix(k, paxXattr) {
|
||||||
if hdr.Xattrs == nil {
|
if hdr.Xattrs == nil {
|
||||||
|
|
@ -337,17 +325,17 @@ func parsePAXTime(t string) (time.Time, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, err
|
||||||
}
|
}
|
||||||
nano_buf := string(buf[pos+1:])
|
nanoBuf := string(buf[pos+1:])
|
||||||
// Pad as needed before converting to a decimal.
|
// Pad as needed before converting to a decimal.
|
||||||
// For example .030 -> .030000000 -> 30000000 nanoseconds
|
// For example .030 -> .030000000 -> 30000000 nanoseconds
|
||||||
if len(nano_buf) < maxNanoSecondIntSize {
|
if len(nanoBuf) < maxNanoSecondIntSize {
|
||||||
// Right pad
|
// Right pad
|
||||||
nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf))
|
nanoBuf += strings.Repeat("0", maxNanoSecondIntSize-len(nanoBuf))
|
||||||
} else if len(nano_buf) > maxNanoSecondIntSize {
|
} else if len(nanoBuf) > maxNanoSecondIntSize {
|
||||||
// Right truncate
|
// Right truncate
|
||||||
nano_buf = nano_buf[:maxNanoSecondIntSize]
|
nanoBuf = nanoBuf[:maxNanoSecondIntSize]
|
||||||
}
|
}
|
||||||
nanoseconds, err = strconv.ParseInt(string(nano_buf), 10, 0)
|
nanoseconds, err = strconv.ParseInt(nanoBuf, 10, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -379,14 +367,14 @@ func parsePAX(r io.Reader) (map[string]string, error) {
|
||||||
}
|
}
|
||||||
sbuf = residual
|
sbuf = residual
|
||||||
|
|
||||||
keyStr := string(key)
|
keyStr := key
|
||||||
if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes {
|
if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes {
|
||||||
// GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map.
|
// GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map.
|
||||||
sparseMap.WriteString(value)
|
sparseMap.WriteString(value)
|
||||||
sparseMap.Write([]byte{','})
|
sparseMap.Write([]byte{','})
|
||||||
} else {
|
} else {
|
||||||
// Normal key. Set the value in the headers map.
|
// Normal key. Set the value in the headers map.
|
||||||
headers[keyStr] = string(value)
|
headers[keyStr] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sparseMap.Len() != 0 {
|
if sparseMap.Len() != 0 {
|
||||||
|
|
@ -523,10 +511,10 @@ func (tr *Reader) skipUnread() error {
|
||||||
// io.Seeker, but calling Seek always returns an error and performs
|
// io.Seeker, but calling Seek always returns an error and performs
|
||||||
// no action. Thus, we try an innocent seek to the current position
|
// no action. Thus, we try an innocent seek to the current position
|
||||||
// to see if Seek is really supported.
|
// to see if Seek is really supported.
|
||||||
pos1, err := sr.Seek(0, os.SEEK_CUR)
|
pos1, err := sr.Seek(0, io.SeekCurrent)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Seek seems supported, so perform the real Seek.
|
// Seek seems supported, so perform the real Seek.
|
||||||
pos2, err := sr.Seek(dataSkip-1, os.SEEK_CUR)
|
pos2, err := sr.Seek(dataSkip-1, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tr.err = err
|
tr.err = err
|
||||||
return tr.err
|
return tr.err
|
||||||
|
|
@ -543,17 +531,6 @@ func (tr *Reader) skipUnread() error {
|
||||||
return tr.err
|
return tr.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *Reader) verifyChecksum(header []byte) bool {
|
|
||||||
if tr.err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var p parser
|
|
||||||
given := p.parseOctal(header[148:156])
|
|
||||||
unsigned, signed := checksum(header)
|
|
||||||
return p.err == nil && (given == unsigned || given == signed)
|
|
||||||
}
|
|
||||||
|
|
||||||
// readHeader reads the next block header and assumes that the underlying reader
|
// readHeader reads the next block header and assumes that the underlying reader
|
||||||
// is already aligned to a block boundary.
|
// is already aligned to a block boundary.
|
||||||
//
|
//
|
||||||
|
|
@ -562,19 +539,16 @@ func (tr *Reader) verifyChecksum(header []byte) bool {
|
||||||
// * Exactly 1 block of zeros is read and EOF is hit.
|
// * Exactly 1 block of zeros is read and EOF is hit.
|
||||||
// * At least 2 blocks of zeros are read.
|
// * At least 2 blocks of zeros are read.
|
||||||
func (tr *Reader) readHeader() *Header {
|
func (tr *Reader) readHeader() *Header {
|
||||||
header := tr.hdrBuff[:]
|
if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
|
||||||
copy(header, zeroBlock)
|
|
||||||
|
|
||||||
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
|
||||||
return nil // io.EOF is okay here
|
return nil // io.EOF is okay here
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two blocks of zero bytes marks the end of the archive.
|
// Two blocks of zero bytes marks the end of the archive.
|
||||||
if bytes.Equal(header, zeroBlock[0:blockSize]) {
|
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
|
||||||
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
|
||||||
return nil // io.EOF is okay here
|
return nil // io.EOF is okay here
|
||||||
}
|
}
|
||||||
if bytes.Equal(header, zeroBlock[0:blockSize]) {
|
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
|
||||||
tr.err = io.EOF
|
tr.err = io.EOF
|
||||||
} else {
|
} else {
|
||||||
tr.err = ErrHeader // zero block and then non-zero block
|
tr.err = ErrHeader // zero block and then non-zero block
|
||||||
|
|
@ -582,71 +556,55 @@ func (tr *Reader) readHeader() *Header {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !tr.verifyChecksum(header) {
|
// Verify the header matches a known format.
|
||||||
|
format := tr.blk.GetFormat()
|
||||||
|
if format == formatUnknown {
|
||||||
tr.err = ErrHeader
|
tr.err = ErrHeader
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack
|
|
||||||
var p parser
|
var p parser
|
||||||
hdr := new(Header)
|
hdr := new(Header)
|
||||||
s := slicer(header)
|
|
||||||
|
|
||||||
hdr.Name = p.parseString(s.next(100))
|
// Unpack the V7 header.
|
||||||
hdr.Mode = p.parseNumeric(s.next(8))
|
v7 := tr.blk.V7()
|
||||||
hdr.Uid = int(p.parseNumeric(s.next(8)))
|
hdr.Name = p.parseString(v7.Name())
|
||||||
hdr.Gid = int(p.parseNumeric(s.next(8)))
|
hdr.Mode = p.parseNumeric(v7.Mode())
|
||||||
hdr.Size = p.parseNumeric(s.next(12))
|
hdr.Uid = int(p.parseNumeric(v7.UID()))
|
||||||
hdr.ModTime = time.Unix(p.parseNumeric(s.next(12)), 0)
|
hdr.Gid = int(p.parseNumeric(v7.GID()))
|
||||||
s.next(8) // chksum
|
hdr.Size = p.parseNumeric(v7.Size())
|
||||||
hdr.Typeflag = s.next(1)[0]
|
hdr.ModTime = time.Unix(p.parseNumeric(v7.ModTime()), 0)
|
||||||
hdr.Linkname = p.parseString(s.next(100))
|
hdr.Typeflag = v7.TypeFlag()[0]
|
||||||
|
hdr.Linkname = p.parseString(v7.LinkName())
|
||||||
|
|
||||||
// The remainder of the header depends on the value of magic.
|
// Unpack format specific fields.
|
||||||
// The original (v7) version of tar had no explicit magic field,
|
if format > formatV7 {
|
||||||
// so its magic bytes, like the rest of the block, are NULs.
|
ustar := tr.blk.USTAR()
|
||||||
magic := string(s.next(8)) // contains version field as well.
|
hdr.Uname = p.parseString(ustar.UserName())
|
||||||
var format string
|
hdr.Gname = p.parseString(ustar.GroupName())
|
||||||
switch {
|
|
||||||
case magic[:6] == "ustar\x00": // POSIX tar (1003.1-1988)
|
|
||||||
if string(header[508:512]) == "tar\x00" {
|
|
||||||
format = "star"
|
|
||||||
} else {
|
|
||||||
format = "posix"
|
|
||||||
}
|
|
||||||
case magic == "ustar \x00": // old GNU tar
|
|
||||||
format = "gnu"
|
|
||||||
}
|
|
||||||
|
|
||||||
switch format {
|
|
||||||
case "posix", "gnu", "star":
|
|
||||||
hdr.Uname = p.parseString(s.next(32))
|
|
||||||
hdr.Gname = p.parseString(s.next(32))
|
|
||||||
devmajor := s.next(8)
|
|
||||||
devminor := s.next(8)
|
|
||||||
if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock {
|
if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock {
|
||||||
hdr.Devmajor = p.parseNumeric(devmajor)
|
hdr.Devmajor = p.parseNumeric(ustar.DevMajor())
|
||||||
hdr.Devminor = p.parseNumeric(devminor)
|
hdr.Devminor = p.parseNumeric(ustar.DevMinor())
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefix string
|
var prefix string
|
||||||
switch format {
|
switch format {
|
||||||
case "posix", "gnu":
|
case formatUSTAR, formatGNU:
|
||||||
prefix = p.parseString(s.next(155))
|
// TODO(dsnet): Do not use the prefix field for the GNU format!
|
||||||
case "star":
|
// See golang.org/issues/12594
|
||||||
prefix = p.parseString(s.next(131))
|
ustar := tr.blk.USTAR()
|
||||||
hdr.AccessTime = time.Unix(p.parseNumeric(s.next(12)), 0)
|
prefix = p.parseString(ustar.Prefix())
|
||||||
hdr.ChangeTime = time.Unix(p.parseNumeric(s.next(12)), 0)
|
case formatSTAR:
|
||||||
|
star := tr.blk.STAR()
|
||||||
|
prefix = p.parseString(star.Prefix())
|
||||||
|
hdr.AccessTime = time.Unix(p.parseNumeric(star.AccessTime()), 0)
|
||||||
|
hdr.ChangeTime = time.Unix(p.parseNumeric(star.ChangeTime()), 0)
|
||||||
}
|
}
|
||||||
if len(prefix) > 0 {
|
if len(prefix) > 0 {
|
||||||
hdr.Name = prefix + "/" + hdr.Name
|
hdr.Name = prefix + "/" + hdr.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.err != nil {
|
|
||||||
tr.err = p.err
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
nb := hdr.Size
|
nb := hdr.Size
|
||||||
if isHeaderOnlyType(hdr.Typeflag) {
|
if isHeaderOnlyType(hdr.Typeflag) {
|
||||||
nb = 0
|
nb = 0
|
||||||
|
|
@ -663,14 +621,14 @@ func (tr *Reader) readHeader() *Header {
|
||||||
// Check for old GNU sparse format entry.
|
// Check for old GNU sparse format entry.
|
||||||
if hdr.Typeflag == TypeGNUSparse {
|
if hdr.Typeflag == TypeGNUSparse {
|
||||||
// Get the real size of the file.
|
// Get the real size of the file.
|
||||||
hdr.Size = p.parseNumeric(header[483:495])
|
hdr.Size = p.parseNumeric(tr.blk.GNU().RealSize())
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
tr.err = p.err
|
tr.err = p.err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the sparse map.
|
// Read the sparse map.
|
||||||
sp := tr.readOldGNUSparseMap(header)
|
sp := tr.readOldGNUSparseMap(&tr.blk)
|
||||||
if tr.err != nil {
|
if tr.err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -682,26 +640,24 @@ func (tr *Reader) readHeader() *Header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.err != nil {
|
||||||
|
tr.err = p.err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return hdr
|
return hdr
|
||||||
}
|
}
|
||||||
|
|
||||||
// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format.
|
// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format.
|
||||||
// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries,
|
// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries,
|
||||||
// then one or more extension headers are used to store the rest of the sparse map.
|
// then one or more extension headers are used to store the rest of the sparse map.
|
||||||
func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
|
func (tr *Reader) readOldGNUSparseMap(blk *block) []sparseEntry {
|
||||||
var p parser
|
var p parser
|
||||||
isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0
|
var s sparseArray = blk.GNU().Sparse()
|
||||||
spCap := oldGNUSparseMainHeaderNumEntries
|
var sp = make([]sparseEntry, 0, s.MaxEntries())
|
||||||
if isExtended {
|
for i := 0; i < s.MaxEntries(); i++ {
|
||||||
spCap += oldGNUSparseExtendedHeaderNumEntries
|
offset := p.parseOctal(s.Entry(i).Offset())
|
||||||
}
|
numBytes := p.parseOctal(s.Entry(i).NumBytes())
|
||||||
sp := make([]sparseEntry, 0, spCap)
|
|
||||||
s := slicer(header[oldGNUSparseMainHeaderOffset:])
|
|
||||||
|
|
||||||
// Read the four entries from the main tar header
|
|
||||||
for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ {
|
|
||||||
offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize))
|
|
||||||
numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize))
|
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
tr.err = p.err
|
tr.err = p.err
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -712,17 +668,17 @@ func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
|
||||||
sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
|
sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
|
||||||
}
|
}
|
||||||
|
|
||||||
for isExtended {
|
for s.IsExtended()[0] > 0 {
|
||||||
// There are more entries. Read an extension header and parse its entries.
|
// There are more entries. Read an extension header and parse its entries.
|
||||||
sparseHeader := make([]byte, blockSize)
|
var blk block
|
||||||
if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil {
|
if _, tr.err = io.ReadFull(tr.r, blk[:]); tr.err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0
|
s = blk.Sparse()
|
||||||
s = slicer(sparseHeader)
|
|
||||||
for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ {
|
for i := 0; i < s.MaxEntries(); i++ {
|
||||||
offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize))
|
offset := p.parseOctal(s.Entry(i).Offset())
|
||||||
numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize))
|
numBytes := p.parseOctal(s.Entry(i).NumBytes())
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
tr.err = p.err
|
tr.err = p.err
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,10 @@ type Writer struct {
|
||||||
nb int64 // number of unwritten bytes for current file entry
|
nb int64 // number of unwritten bytes for current file entry
|
||||||
pad int64 // amount of padding to write after current file entry
|
pad int64 // amount of padding to write after current file entry
|
||||||
closed bool
|
closed bool
|
||||||
usedBinary bool // whether the binary numeric field extension was used
|
usedBinary bool // whether the binary numeric field extension was used
|
||||||
preferPax bool // use pax header instead of binary numeric header
|
preferPax bool // use PAX header instead of binary numeric header
|
||||||
hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header
|
hdrBuff block // buffer to use in writeHeader when writing a regular header
|
||||||
paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
|
paxHdrBuff block // buffer to use in writeHeader when writing a PAX header
|
||||||
}
|
}
|
||||||
|
|
||||||
type formatter struct {
|
type formatter struct {
|
||||||
|
|
@ -153,27 +153,24 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||||
// a map to hold pax header records, if any are needed
|
// a map to hold pax header records, if any are needed
|
||||||
paxHeaders := make(map[string]string)
|
paxHeaders := make(map[string]string)
|
||||||
|
|
||||||
// TODO(shanemhansen): we might want to use PAX headers for
|
// TODO(dsnet): we might want to use PAX headers for
|
||||||
// subsecond time resolution, but for now let's just capture
|
// subsecond time resolution, but for now let's just capture
|
||||||
// too long fields or non ascii characters
|
// too long fields or non ascii characters
|
||||||
|
|
||||||
var f formatter
|
|
||||||
var header []byte
|
|
||||||
|
|
||||||
// We need to select which scratch buffer to use carefully,
|
// We need to select which scratch buffer to use carefully,
|
||||||
// since this method is called recursively to write PAX headers.
|
// since this method is called recursively to write PAX headers.
|
||||||
// If allowPax is true, this is the non-recursive call, and we will use hdrBuff.
|
// If allowPax is true, this is the non-recursive call, and we will use hdrBuff.
|
||||||
// If allowPax is false, we are being called by writePAXHeader, and hdrBuff is
|
// If allowPax is false, we are being called by writePAXHeader, and hdrBuff is
|
||||||
// already being used by the non-recursive call, so we must use paxHdrBuff.
|
// already being used by the non-recursive call, so we must use paxHdrBuff.
|
||||||
header = tw.hdrBuff[:]
|
header := &tw.hdrBuff
|
||||||
if !allowPax {
|
if !allowPax {
|
||||||
header = tw.paxHdrBuff[:]
|
header = &tw.paxHdrBuff
|
||||||
}
|
}
|
||||||
copy(header, zeroBlock)
|
copy(header[:], zeroBlock[:])
|
||||||
s := slicer(header)
|
|
||||||
|
|
||||||
// Wrappers around formatter that automatically sets paxHeaders if the
|
// Wrappers around formatter that automatically sets paxHeaders if the
|
||||||
// argument extends beyond the capacity of the input byte slice.
|
// argument extends beyond the capacity of the input byte slice.
|
||||||
|
var f formatter
|
||||||
var formatString = func(b []byte, s string, paxKeyword string) {
|
var formatString = func(b []byte, s string, paxKeyword string) {
|
||||||
needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s)
|
needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s)
|
||||||
if needsPaxHeader {
|
if needsPaxHeader {
|
||||||
|
|
@ -202,44 +199,33 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||||
f.formatNumeric(b, x)
|
f.formatNumeric(b, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
|
|
||||||
pathHeaderBytes := s.next(fileNameSize)
|
|
||||||
|
|
||||||
formatString(pathHeaderBytes, hdr.Name, paxPath)
|
|
||||||
|
|
||||||
// Handle out of range ModTime carefully.
|
// Handle out of range ModTime carefully.
|
||||||
var modTime int64
|
var modTime int64
|
||||||
if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
|
if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
|
||||||
modTime = hdr.ModTime.Unix()
|
modTime = hdr.ModTime.Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
f.formatOctal(s.next(8), hdr.Mode) // 100:108
|
v7 := header.V7()
|
||||||
formatNumeric(s.next(8), int64(hdr.Uid), paxUid) // 108:116
|
formatString(v7.Name(), hdr.Name, paxPath)
|
||||||
formatNumeric(s.next(8), int64(hdr.Gid), paxGid) // 116:124
|
// TODO(dsnet): The GNU format permits the mode field to be encoded in
|
||||||
formatNumeric(s.next(12), hdr.Size, paxSize) // 124:136
|
// base-256 format. Thus, we can use formatNumeric instead of formatOctal.
|
||||||
formatNumeric(s.next(12), modTime, paxNone) // 136:148 --- consider using pax for finer granularity
|
f.formatOctal(v7.Mode(), hdr.Mode)
|
||||||
s.next(8) // chksum (148:156)
|
formatNumeric(v7.UID(), int64(hdr.Uid), paxUid)
|
||||||
s.next(1)[0] = hdr.Typeflag // 156:157
|
formatNumeric(v7.GID(), int64(hdr.Gid), paxGid)
|
||||||
|
formatNumeric(v7.Size(), hdr.Size, paxSize)
|
||||||
|
// TODO(dsnet): Consider using PAX for finer time granularity.
|
||||||
|
formatNumeric(v7.ModTime(), modTime, paxNone)
|
||||||
|
v7.TypeFlag()[0] = hdr.Typeflag
|
||||||
|
formatString(v7.LinkName(), hdr.Linkname, paxLinkpath)
|
||||||
|
|
||||||
formatString(s.next(100), hdr.Linkname, paxLinkpath)
|
ustar := header.USTAR()
|
||||||
|
formatString(ustar.UserName(), hdr.Uname, paxUname)
|
||||||
|
formatString(ustar.GroupName(), hdr.Gname, paxGname)
|
||||||
|
formatNumeric(ustar.DevMajor(), hdr.Devmajor, paxNone)
|
||||||
|
formatNumeric(ustar.DevMinor(), hdr.Devminor, paxNone)
|
||||||
|
|
||||||
copy(s.next(8), []byte("ustar\x0000")) // 257:265
|
|
||||||
formatString(s.next(32), hdr.Uname, paxUname) // 265:297
|
|
||||||
formatString(s.next(32), hdr.Gname, paxGname) // 297:329
|
|
||||||
formatNumeric(s.next(8), hdr.Devmajor, paxNone) // 329:337
|
|
||||||
formatNumeric(s.next(8), hdr.Devminor, paxNone) // 337:345
|
|
||||||
|
|
||||||
// keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
|
|
||||||
prefixHeaderBytes := s.next(155)
|
|
||||||
formatString(prefixHeaderBytes, "", paxNone) // 345:500 prefix
|
|
||||||
|
|
||||||
// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
|
|
||||||
if tw.usedBinary {
|
|
||||||
copy(header[257:265], []byte("ustar \x00"))
|
|
||||||
}
|
|
||||||
|
|
||||||
_, paxPathUsed := paxHeaders[paxPath]
|
|
||||||
// try to use a ustar header when only the name is too long
|
// try to use a ustar header when only the name is too long
|
||||||
|
_, paxPathUsed := paxHeaders[paxPath]
|
||||||
if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
|
if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
|
||||||
prefix, suffix, ok := splitUSTARPath(hdr.Name)
|
prefix, suffix, ok := splitUSTARPath(hdr.Name)
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -247,16 +233,16 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||||
delete(paxHeaders, paxPath)
|
delete(paxHeaders, paxPath)
|
||||||
|
|
||||||
// Update the path fields
|
// Update the path fields
|
||||||
formatString(pathHeaderBytes, suffix, paxNone)
|
formatString(v7.Name(), suffix, paxNone)
|
||||||
formatString(prefixHeaderBytes, prefix, paxNone)
|
formatString(ustar.Prefix(), prefix, paxNone)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The chksum field is terminated by a NUL and a space.
|
if tw.usedBinary {
|
||||||
// This is different from the other octal fields.
|
header.SetFormat(formatGNU)
|
||||||
chksum, _ := checksum(header)
|
} else {
|
||||||
f.formatOctal(header[148:155], chksum) // Never fails
|
header.SetFormat(formatUSTAR)
|
||||||
header[155] = ' '
|
}
|
||||||
|
|
||||||
// Check if there were any formatting errors.
|
// Check if there were any formatting errors.
|
||||||
if f.err != nil {
|
if f.err != nil {
|
||||||
|
|
@ -278,10 +264,10 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tw.nb = int64(hdr.Size)
|
tw.nb = hdr.Size
|
||||||
tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize
|
tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize
|
||||||
|
|
||||||
_, tw.err = tw.w.Write(header)
|
_, tw.err = tw.w.Write(header[:])
|
||||||
return tw.err
|
return tw.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,10 +275,10 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||||
// If the path is not splittable, then it will return ("", "", false).
|
// If the path is not splittable, then it will return ("", "", false).
|
||||||
func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
||||||
length := len(name)
|
length := len(name)
|
||||||
if length <= fileNameSize || !isASCII(name) {
|
if length <= nameSize || !isASCII(name) {
|
||||||
return "", "", false
|
return "", "", false
|
||||||
} else if length > fileNamePrefixSize+1 {
|
} else if length > prefixSize+1 {
|
||||||
length = fileNamePrefixSize + 1
|
length = prefixSize + 1
|
||||||
} else if name[length-1] == '/' {
|
} else if name[length-1] == '/' {
|
||||||
length--
|
length--
|
||||||
}
|
}
|
||||||
|
|
@ -300,7 +286,7 @@ func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
||||||
i := strings.LastIndex(name[:length], "/")
|
i := strings.LastIndex(name[:length], "/")
|
||||||
nlen := len(name) - i - 1 // nlen is length of suffix
|
nlen := len(name) - i - 1 // nlen is length of suffix
|
||||||
plen := i // plen is length of prefix
|
plen := i // plen is length of prefix
|
||||||
if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize {
|
if i <= 0 || nlen > nameSize || nlen == 0 || plen > prefixSize {
|
||||||
return "", "", false
|
return "", "", false
|
||||||
}
|
}
|
||||||
return name[:i], name[i+1:], true
|
return name[:i], name[i+1:], true
|
||||||
|
|
@ -316,15 +302,15 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
|
||||||
// succeed, and seems harmless enough.
|
// succeed, and seems harmless enough.
|
||||||
ext.ModTime = hdr.ModTime
|
ext.ModTime = hdr.ModTime
|
||||||
// The spec asks that we namespace our pseudo files
|
// The spec asks that we namespace our pseudo files
|
||||||
// with the current pid. However, this results in differing outputs
|
// with the current pid. However, this results in differing outputs
|
||||||
// for identical inputs. As such, the constant 0 is now used instead.
|
// for identical inputs. As such, the constant 0 is now used instead.
|
||||||
// golang.org/issue/12358
|
// golang.org/issue/12358
|
||||||
dir, file := path.Split(hdr.Name)
|
dir, file := path.Split(hdr.Name)
|
||||||
fullName := path.Join(dir, "PaxHeaders.0", file)
|
fullName := path.Join(dir, "PaxHeaders.0", file)
|
||||||
|
|
||||||
ascii := toASCII(fullName)
|
ascii := toASCII(fullName)
|
||||||
if len(ascii) > 100 {
|
if len(ascii) > nameSize {
|
||||||
ascii = ascii[:100]
|
ascii = ascii[:nameSize]
|
||||||
}
|
}
|
||||||
ext.Name = ascii
|
ext.Name = ascii
|
||||||
// Construct the body
|
// Construct the body
|
||||||
|
|
@ -407,7 +393,7 @@ func (tw *Writer) Close() error {
|
||||||
|
|
||||||
// trailer: two zero blocks
|
// trailer: two zero blocks
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
_, tw.err = tw.w.Write(zeroBlock)
|
_, tw.err = tw.w.Write(zeroBlock[:])
|
||||||
if tw.err != nil {
|
if tw.err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -587,17 +587,17 @@ func TestSplitUSTARPath(t *testing.T) {
|
||||||
{"", "", "", false},
|
{"", "", "", false},
|
||||||
{"abc", "", "", false},
|
{"abc", "", "", false},
|
||||||
{"用戶名", "", "", false},
|
{"用戶名", "", "", false},
|
||||||
{sr("a", fileNameSize), "", "", false},
|
{sr("a", nameSize), "", "", false},
|
||||||
{sr("a", fileNameSize) + "/", "", "", false},
|
{sr("a", nameSize) + "/", "", "", false},
|
||||||
{sr("a", fileNameSize) + "/a", sr("a", fileNameSize), "a", true},
|
{sr("a", nameSize) + "/a", sr("a", nameSize), "a", true},
|
||||||
{sr("a", fileNamePrefixSize) + "/", "", "", false},
|
{sr("a", prefixSize) + "/", "", "", false},
|
||||||
{sr("a", fileNamePrefixSize) + "/a", sr("a", fileNamePrefixSize), "a", true},
|
{sr("a", prefixSize) + "/a", sr("a", prefixSize), "a", true},
|
||||||
{sr("a", fileNameSize+1), "", "", false},
|
{sr("a", nameSize+1), "", "", false},
|
||||||
{sr("/", fileNameSize+1), sr("/", fileNameSize-1), "/", true},
|
{sr("/", nameSize+1), sr("/", nameSize-1), "/", true},
|
||||||
{sr("a", fileNamePrefixSize) + "/" + sr("b", fileNameSize),
|
{sr("a", prefixSize) + "/" + sr("b", nameSize),
|
||||||
sr("a", fileNamePrefixSize), sr("b", fileNameSize), true},
|
sr("a", prefixSize), sr("b", nameSize), true},
|
||||||
{sr("a", fileNamePrefixSize) + "//" + sr("b", fileNameSize), "", "", false},
|
{sr("a", prefixSize) + "//" + sr("b", nameSize), "", "", false},
|
||||||
{sr("a/", fileNameSize), sr("a/", 77) + "a", sr("a/", 22), true},
|
{sr("a/", nameSize), sr("a/", 77) + "a", sr("a/", 22), true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range vectors {
|
for _, v := range vectors {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||||
z.File = make([]*File, 0, end.directoryRecords)
|
z.File = make([]*File, 0, end.directoryRecords)
|
||||||
z.Comment = end.comment
|
z.Comment = end.comment
|
||||||
rs := io.NewSectionReader(r, 0, size)
|
rs := io.NewSectionReader(r, 0, size)
|
||||||
if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
|
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf := bufio.NewReader(rs)
|
buf := bufio.NewReader(rs)
|
||||||
|
|
@ -153,19 +153,18 @@ func (f *File) DataOffset() (offset int64, err error) {
|
||||||
|
|
||||||
// Open returns a ReadCloser that provides access to the File's contents.
|
// Open returns a ReadCloser that provides access to the File's contents.
|
||||||
// Multiple files may be read concurrently.
|
// Multiple files may be read concurrently.
|
||||||
func (f *File) Open() (rc io.ReadCloser, err error) {
|
func (f *File) Open() (io.ReadCloser, error) {
|
||||||
bodyOffset, err := f.findBodyOffset()
|
bodyOffset, err := f.findBodyOffset()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
size := int64(f.CompressedSize64)
|
size := int64(f.CompressedSize64)
|
||||||
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
|
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
|
||||||
dcomp := f.zip.decompressor(f.Method)
|
dcomp := f.zip.decompressor(f.Method)
|
||||||
if dcomp == nil {
|
if dcomp == nil {
|
||||||
err = ErrAlgorithm
|
return nil, ErrAlgorithm
|
||||||
return
|
|
||||||
}
|
}
|
||||||
rc = dcomp(r)
|
var rc io.ReadCloser = dcomp(r)
|
||||||
var desr io.Reader
|
var desr io.Reader
|
||||||
if f.hasDataDescriptor() {
|
if f.hasDataDescriptor() {
|
||||||
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
|
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
|
||||||
|
|
@ -176,7 +175,7 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
|
||||||
f: f,
|
f: f,
|
||||||
desr: desr,
|
desr: desr,
|
||||||
}
|
}
|
||||||
return
|
return rc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type checksumReader struct {
|
type checksumReader struct {
|
||||||
|
|
|
||||||
|
|
@ -399,7 +399,7 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
|
||||||
// Don't bother uncompressing: too big.
|
// Don't bother uncompressing: too big.
|
||||||
if ft.Content == nil && ft.File == "" && ft.Size > 0 {
|
if ft.Content == nil && ft.File == "" && ft.Size > 0 {
|
||||||
if size != ft.Size {
|
if size != ft.Size {
|
||||||
t.Errorf("%v: uncompressed size %#x, want %#x", size, ft.Size)
|
t.Errorf("%v: uncompressed size %#x, want %#x", ft.Name, size, ft.Size)
|
||||||
}
|
}
|
||||||
r.Close()
|
r.Close()
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,44 @@ func (w *pooledFlateWriter) Close() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var flateReaderPool sync.Pool
|
||||||
|
|
||||||
|
func newFlateReader(r io.Reader) io.ReadCloser {
|
||||||
|
fr, ok := flateReaderPool.Get().(io.ReadCloser)
|
||||||
|
if ok {
|
||||||
|
fr.(flate.Resetter).Reset(r, nil)
|
||||||
|
} else {
|
||||||
|
fr = flate.NewReader(r)
|
||||||
|
}
|
||||||
|
return &pooledFlateReader{fr: fr}
|
||||||
|
}
|
||||||
|
|
||||||
|
type pooledFlateReader struct {
|
||||||
|
mu sync.Mutex // guards Close and Read
|
||||||
|
fr io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *pooledFlateReader) Read(p []byte) (n int, err error) {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
if r.fr == nil {
|
||||||
|
return 0, errors.New("Read after Close")
|
||||||
|
}
|
||||||
|
return r.fr.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *pooledFlateReader) Close() error {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
var err error
|
||||||
|
if r.fr != nil {
|
||||||
|
err = r.fr.Close()
|
||||||
|
flateReaderPool.Put(r.fr)
|
||||||
|
r.fr = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mu sync.RWMutex // guards compressor and decompressor maps
|
mu sync.RWMutex // guards compressor and decompressor maps
|
||||||
|
|
||||||
|
|
@ -74,7 +112,7 @@ var (
|
||||||
|
|
||||||
decompressors = map[uint16]Decompressor{
|
decompressors = map[uint16]Decompressor{
|
||||||
Store: ioutil.NopCloser,
|
Store: ioutil.NopCloser,
|
||||||
Deflate: flate.NewReader,
|
Deflate: newFlateReader,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
/*
|
/*
|
||||||
Package zip provides support for reading and writing ZIP archives.
|
Package zip provides support for reading and writing ZIP archives.
|
||||||
|
|
||||||
See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
|
See: https://www.pkware.com/documents/casestudies/APPNOTE.TXT
|
||||||
|
|
||||||
This package does not support disk spanning.
|
This package does not support disk spanning.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ func (w *Writer) Flush() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close finishes writing the zip file by writing the central directory.
|
// Close finishes writing the zip file by writing the central directory.
|
||||||
// It does not (and can not) close the underlying writer.
|
// It does not (and cannot) close the underlying writer.
|
||||||
func (w *Writer) Close() error {
|
func (w *Writer) Close() error {
|
||||||
if w.last != nil && !w.last.closed {
|
if w.last != nil && !w.last.closed {
|
||||||
if err := w.last.close(); err != nil {
|
if err := w.last.close(); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ func BenchmarkCompressedZipGarbage(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
bigBuf := bytes.Repeat([]byte("a"), 1<<20)
|
bigBuf := bytes.Repeat([]byte("a"), 1<<20)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i <= b.N; i++ {
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
zw := NewWriter(&buf)
|
zw := NewWriter(&buf)
|
||||||
for j := 0; j < 3; j++ {
|
for j := 0; j < 3; j++ {
|
||||||
|
|
@ -195,5 +195,11 @@ func BenchmarkCompressedZipGarbage(b *testing.B) {
|
||||||
w.Write(bigBuf)
|
w.Write(bigBuf)
|
||||||
}
|
}
|
||||||
zw.Close()
|
zw.Close()
|
||||||
|
if i == 0 {
|
||||||
|
// Reset the timer after the first time through.
|
||||||
|
// This effectively discards the very large initial flate setup cost,
|
||||||
|
// as well as the initialization of bigBuf.
|
||||||
|
b.ResetTimer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -366,27 +366,6 @@ func testZip64DirectoryRecordLength(buf *rleBuffer, t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInvalidHeader(h *FileHeader, t *testing.T) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
z := NewWriter(&buf)
|
|
||||||
|
|
||||||
f, err := z.CreateHeader(h)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error creating header: %v", err)
|
|
||||||
}
|
|
||||||
if _, err := f.Write([]byte("hi")); err != nil {
|
|
||||||
t.Fatalf("error writing content: %v", err)
|
|
||||||
}
|
|
||||||
if err := z.Close(); err != nil {
|
|
||||||
t.Fatalf("error closing zip writer: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b := buf.Bytes()
|
|
||||||
if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != ErrFormat {
|
|
||||||
t.Fatalf("got %v, expected ErrFormat", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testValidHeader(h *FileHeader, t *testing.T) {
|
func testValidHeader(h *FileHeader, t *testing.T) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
z := NewWriter(&buf)
|
z := NewWriter(&buf)
|
||||||
|
|
|
||||||
|
|
@ -124,14 +124,16 @@ func (b *Reader) Peek(n int) ([]byte, error) {
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
return nil, ErrNegativeCount
|
return nil, ErrNegativeCount
|
||||||
}
|
}
|
||||||
if n > len(b.buf) {
|
|
||||||
return nil, ErrBufferFull
|
for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil {
|
||||||
}
|
|
||||||
// 0 <= n <= len(b.buf)
|
|
||||||
for b.w-b.r < n && b.err == nil {
|
|
||||||
b.fill() // b.w-b.r < len(b.buf) => buffer is not full
|
b.fill() // b.w-b.r < len(b.buf) => buffer is not full
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n > len(b.buf) {
|
||||||
|
return b.buf[b.r:b.w], ErrBufferFull
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 <= n <= len(b.buf)
|
||||||
var err error
|
var err error
|
||||||
if avail := b.w - b.r; avail < n {
|
if avail := b.w - b.r; avail < n {
|
||||||
// not enough data in buffer
|
// not enough data in buffer
|
||||||
|
|
@ -220,7 +222,7 @@ func (b *Reader) Read(p []byte) (n int, err error) {
|
||||||
|
|
||||||
// ReadByte reads and returns a single byte.
|
// ReadByte reads and returns a single byte.
|
||||||
// If no byte is available, returns an error.
|
// If no byte is available, returns an error.
|
||||||
func (b *Reader) ReadByte() (c byte, err error) {
|
func (b *Reader) ReadByte() (byte, error) {
|
||||||
b.lastRuneSize = -1
|
b.lastRuneSize = -1
|
||||||
for b.r == b.w {
|
for b.r == b.w {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
|
|
@ -228,13 +230,13 @@ func (b *Reader) ReadByte() (c byte, err error) {
|
||||||
}
|
}
|
||||||
b.fill() // buffer is empty
|
b.fill() // buffer is empty
|
||||||
}
|
}
|
||||||
c = b.buf[b.r]
|
c := b.buf[b.r]
|
||||||
b.r++
|
b.r++
|
||||||
b.lastByte = int(c)
|
b.lastByte = int(c)
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnreadByte unreads the last byte. Only the most recently read byte can be unread.
|
// UnreadByte unreads the last byte. Only the most recently read byte can be unread.
|
||||||
func (b *Reader) UnreadByte() error {
|
func (b *Reader) UnreadByte() error {
|
||||||
if b.lastByte < 0 || b.r == 0 && b.w > 0 {
|
if b.lastByte < 0 || b.r == 0 && b.w > 0 {
|
||||||
return ErrInvalidUnreadByte
|
return ErrInvalidUnreadByte
|
||||||
|
|
@ -264,7 +266,7 @@ func (b *Reader) ReadRune() (r rune, size int, err error) {
|
||||||
return 0, 0, b.readErr()
|
return 0, 0, b.readErr()
|
||||||
}
|
}
|
||||||
r, size = rune(b.buf[b.r]), 1
|
r, size = rune(b.buf[b.r]), 1
|
||||||
if r >= 0x80 {
|
if r >= utf8.RuneSelf {
|
||||||
r, size = utf8.DecodeRune(b.buf[b.r:b.w])
|
r, size = utf8.DecodeRune(b.buf[b.r:b.w])
|
||||||
}
|
}
|
||||||
b.r += size
|
b.r += size
|
||||||
|
|
@ -273,7 +275,7 @@ func (b *Reader) ReadRune() (r rune, size int, err error) {
|
||||||
return r, size, nil
|
return r, size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnreadRune unreads the last rune. If the most recent read operation on
|
// UnreadRune unreads the last rune. If the most recent read operation on
|
||||||
// the buffer was not a ReadRune, UnreadRune returns an error. (In this
|
// the buffer was not a ReadRune, UnreadRune returns an error. (In this
|
||||||
// regard it is stricter than UnreadByte, which will unread the last byte
|
// regard it is stricter than UnreadByte, which will unread the last byte
|
||||||
// from any read operation.)
|
// from any read operation.)
|
||||||
|
|
@ -395,12 +397,12 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
|
||||||
// ReadBytes returns err != nil if and only if the returned data does not end in
|
// ReadBytes returns err != nil if and only if the returned data does not end in
|
||||||
// delim.
|
// delim.
|
||||||
// For simple uses, a Scanner may be more convenient.
|
// For simple uses, a Scanner may be more convenient.
|
||||||
func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
|
func (b *Reader) ReadBytes(delim byte) ([]byte, error) {
|
||||||
// Use ReadSlice to look for array,
|
// Use ReadSlice to look for array,
|
||||||
// accumulating full buffers.
|
// accumulating full buffers.
|
||||||
var frag []byte
|
var frag []byte
|
||||||
var full [][]byte
|
var full [][]byte
|
||||||
|
var err error
|
||||||
for {
|
for {
|
||||||
var e error
|
var e error
|
||||||
frag, e = b.ReadSlice(delim)
|
frag, e = b.ReadSlice(delim)
|
||||||
|
|
@ -442,10 +444,9 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
|
||||||
// ReadString returns err != nil if and only if the returned data does not end in
|
// ReadString returns err != nil if and only if the returned data does not end in
|
||||||
// delim.
|
// delim.
|
||||||
// For simple uses, a Scanner may be more convenient.
|
// For simple uses, a Scanner may be more convenient.
|
||||||
func (b *Reader) ReadString(delim byte) (line string, err error) {
|
func (b *Reader) ReadString(delim byte) (string, error) {
|
||||||
bytes, err := b.ReadBytes(delim)
|
bytes, err := b.ReadBytes(delim)
|
||||||
line = string(bytes)
|
return string(bytes), err
|
||||||
return line, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteTo implements io.WriterTo.
|
// WriteTo implements io.WriterTo.
|
||||||
|
|
@ -705,7 +706,7 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
// If we filled the buffer exactly, flush pre-emptively.
|
// If we filled the buffer exactly, flush preemptively.
|
||||||
if b.Available() == 0 {
|
if b.Available() == 0 {
|
||||||
err = b.flush()
|
err = b.flush()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -673,8 +673,8 @@ func TestPeek(t *testing.T) {
|
||||||
if _, err := buf.Peek(-1); err != ErrNegativeCount {
|
if _, err := buf.Peek(-1); err != ErrNegativeCount {
|
||||||
t.Fatalf("want ErrNegativeCount got %v", err)
|
t.Fatalf("want ErrNegativeCount got %v", err)
|
||||||
}
|
}
|
||||||
if _, err := buf.Peek(32); err != ErrBufferFull {
|
if s, err := buf.Peek(32); string(s) != "abcdefghijklmnop" || err != ErrBufferFull {
|
||||||
t.Fatalf("want ErrBufFull got %v", err)
|
t.Fatalf("want %q, ErrBufFull got %q, err=%v", "abcdefghijklmnop", string(s), err)
|
||||||
}
|
}
|
||||||
if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
|
if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
|
||||||
t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err)
|
t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err)
|
||||||
|
|
@ -1475,7 +1475,7 @@ func BenchmarkReaderWriteToOptimal(b *testing.B) {
|
||||||
b.Fatal("ioutil.Discard doesn't support ReaderFrom")
|
b.Fatal("ioutil.Discard doesn't support ReaderFrom")
|
||||||
}
|
}
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r.Seek(0, 0)
|
r.Seek(0, io.SeekStart)
|
||||||
srcReader.Reset(onlyReader{r})
|
srcReader.Reset(onlyReader{r})
|
||||||
n, err := srcReader.WriteTo(ioutil.Discard)
|
n, err := srcReader.WriteTo(ioutil.Discard)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -264,10 +264,6 @@ func testNoNewline(text string, lines []string, t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var noNewlineLines = []string{
|
|
||||||
"abcdefghijklmn\nopqrstuvwxyz",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that the line splitter handles a final line without a newline.
|
// Test that the line splitter handles a final line without a newline.
|
||||||
func TestScanLineNoNewline(t *testing.T) {
|
func TestScanLineNoNewline(t *testing.T) {
|
||||||
const text = "abcdefghijklmn\nopqrstuvwxyz"
|
const text = "abcdefghijklmn\nopqrstuvwxyz"
|
||||||
|
|
@ -351,7 +347,7 @@ func TestSplitError(t *testing.T) {
|
||||||
// Test that an EOF is overridden by a user-generated scan error.
|
// Test that an EOF is overridden by a user-generated scan error.
|
||||||
func TestErrAtEOF(t *testing.T) {
|
func TestErrAtEOF(t *testing.T) {
|
||||||
s := NewScanner(strings.NewReader("1 2 33"))
|
s := NewScanner(strings.NewReader("1 2 33"))
|
||||||
// This spitter will fail on last entry, after s.err==EOF.
|
// This splitter will fail on last entry, after s.err==EOF.
|
||||||
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
advance, token, err = ScanWords(data, atEOF)
|
advance, token, err = ScanWords(data, atEOF)
|
||||||
if len(token) > 1 {
|
if len(token) > 1 {
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ import (
|
||||||
type Buffer struct {
|
type Buffer struct {
|
||||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
buf []byte // contents are the bytes buf[off : len(buf)]
|
||||||
off int // read at &buf[off], write at &buf[len(buf)]
|
off int // read at &buf[off], write at &buf[len(buf)]
|
||||||
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
|
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each call to WriteRune
|
||||||
bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation.
|
bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
|
||||||
lastRead readOp // last read operation, so that Unread* can work correctly.
|
lastRead readOp // last read operation, so that Unread* can work correctly.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ var ErrTooLarge = errors.New("bytes.Buffer: too large")
|
||||||
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
|
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
|
||||||
|
|
||||||
// String returns the contents of the unread portion of the buffer
|
// String returns the contents of the unread portion of the buffer
|
||||||
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
|
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
|
||||||
func (b *Buffer) String() string {
|
func (b *Buffer) String() string {
|
||||||
if b == nil {
|
if b == nil {
|
||||||
// Special case, useful in debugging.
|
// Special case, useful in debugging.
|
||||||
|
|
@ -145,7 +145,7 @@ func (b *Buffer) WriteString(s string) (n int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MinRead is the minimum slice size passed to a Read call by
|
// MinRead is the minimum slice size passed to a Read call by
|
||||||
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
|
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
|
||||||
// what is required to hold the contents of r, ReadFrom will not grow the
|
// what is required to hold the contents of r, ReadFrom will not grow the
|
||||||
// underlying buffer.
|
// underlying buffer.
|
||||||
const MinRead = 512
|
const MinRead = 512
|
||||||
|
|
@ -252,7 +252,7 @@ func (b *Buffer) WriteRune(r rune) (n int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads the next len(p) bytes from the buffer or until the buffer
|
// Read reads the next len(p) bytes from the buffer or until the buffer
|
||||||
// is drained. The return value n is the number of bytes read. If the
|
// is drained. The return value n is the number of bytes read. If the
|
||||||
// buffer has no data to return, err is io.EOF (unless len(p) is zero);
|
// buffer has no data to return, err is io.EOF (unless len(p) is zero);
|
||||||
// otherwise it is nil.
|
// otherwise it is nil.
|
||||||
func (b *Buffer) Read(p []byte) (n int, err error) {
|
func (b *Buffer) Read(p []byte) (n int, err error) {
|
||||||
|
|
@ -293,14 +293,14 @@ func (b *Buffer) Next(n int) []byte {
|
||||||
|
|
||||||
// ReadByte reads and returns the next byte from the buffer.
|
// ReadByte reads and returns the next byte from the buffer.
|
||||||
// If no byte is available, it returns error io.EOF.
|
// If no byte is available, it returns error io.EOF.
|
||||||
func (b *Buffer) ReadByte() (c byte, err error) {
|
func (b *Buffer) ReadByte() (byte, error) {
|
||||||
b.lastRead = opInvalid
|
b.lastRead = opInvalid
|
||||||
if b.off >= len(b.buf) {
|
if b.off >= len(b.buf) {
|
||||||
// Buffer is empty, reset to recover space.
|
// Buffer is empty, reset to recover space.
|
||||||
b.Truncate(0)
|
b.Truncate(0)
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
c = b.buf[b.off]
|
c := b.buf[b.off]
|
||||||
b.off++
|
b.off++
|
||||||
b.lastRead = opRead
|
b.lastRead = opRead
|
||||||
return c, nil
|
return c, nil
|
||||||
|
|
@ -347,7 +347,7 @@ func (b *Buffer) UnreadRune() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnreadByte unreads the last byte returned by the most recent
|
// UnreadByte unreads the last byte returned by the most recent
|
||||||
// read operation. If write has happened since the last read, UnreadByte
|
// read operation. If write has happened since the last read, UnreadByte
|
||||||
// returns an error.
|
// returns an error.
|
||||||
func (b *Buffer) UnreadByte() error {
|
func (b *Buffer) UnreadByte() error {
|
||||||
if b.lastRead != opReadRune && b.lastRead != opRead {
|
if b.lastRead != opReadRune && b.lastRead != opRead {
|
||||||
|
|
@ -400,7 +400,7 @@ func (b *Buffer) ReadString(delim byte) (line string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBuffer creates and initializes a new Buffer using buf as its initial
|
// 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
|
// contents. It is intended to prepare a Buffer to read existing data. It
|
||||||
// can also be used 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.
|
// buf should have the desired capacity but a length of zero.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,16 @@ func Contains(b, subslice []byte) bool {
|
||||||
return Index(b, subslice) != -1
|
return Index(b, subslice) != -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainsAny reports whether any of the UTF-8-encoded Unicode code points in chars are within b.
|
||||||
|
func ContainsAny(b []byte, chars string) bool {
|
||||||
|
return IndexAny(b, chars) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsRune reports whether the Unicode code point r is within b.
|
||||||
|
func ContainsRune(b []byte, r rune) bool {
|
||||||
|
return IndexRune(b, r) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
||||||
func Index(s, sep []byte) int {
|
func Index(s, sep []byte) int {
|
||||||
n := len(sep)
|
n := len(sep)
|
||||||
|
|
@ -164,7 +174,7 @@ func IndexRune(s []byte, r rune) int {
|
||||||
|
|
||||||
// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
|
// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
|
||||||
// It returns the byte index of the first occurrence in s of any of the Unicode
|
// It returns the byte index of the first 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
|
// code points in chars. It returns -1 if chars is empty or if there is no code
|
||||||
// point in common.
|
// point in common.
|
||||||
func IndexAny(s []byte, chars string) int {
|
func IndexAny(s []byte, chars string) int {
|
||||||
if len(chars) > 0 {
|
if len(chars) > 0 {
|
||||||
|
|
@ -188,8 +198,8 @@ func IndexAny(s []byte, chars string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code
|
// 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
|
// 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
|
// the Unicode code points in chars. It returns -1 if chars is empty or if
|
||||||
// there is no code point in common.
|
// there is no code point in common.
|
||||||
func LastIndexAny(s []byte, chars string) int {
|
func LastIndexAny(s []byte, chars string) int {
|
||||||
if len(chars) > 0 {
|
if len(chars) > 0 {
|
||||||
|
|
@ -276,7 +286,7 @@ func Fields(s []byte) [][]byte {
|
||||||
|
|
||||||
// FieldsFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
|
// FieldsFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
|
||||||
// It splits the slice s at each run of code points c satisfying f(c) and
|
// It splits the slice s at each run of code points c satisfying f(c) and
|
||||||
// returns a slice of subslices of s. If all code points in s satisfy f(c), or
|
// returns a slice of subslices of s. If all code points in s satisfy f(c), or
|
||||||
// len(s) == 0, an empty slice is returned.
|
// len(s) == 0, an empty slice is returned.
|
||||||
// FieldsFunc makes no guarantees about the order in which it calls f(c).
|
// FieldsFunc makes no guarantees about the order in which it calls f(c).
|
||||||
// If f does not return consistent results for a given c, FieldsFunc may crash.
|
// If f does not return consistent results for a given c, FieldsFunc may crash.
|
||||||
|
|
@ -352,12 +362,12 @@ func HasSuffix(s, suffix []byte) bool {
|
||||||
|
|
||||||
// Map returns a copy of the byte slice s with all its characters modified
|
// Map returns a copy of the byte slice s with all its characters modified
|
||||||
// according to the mapping function. If mapping returns a negative value, the character is
|
// according to the mapping function. If mapping returns a negative value, the character is
|
||||||
// dropped from the string with no replacement. The characters in s and the
|
// dropped from the string with no replacement. The characters in s and the
|
||||||
// output are interpreted as UTF-8-encoded Unicode code points.
|
// output are interpreted as UTF-8-encoded Unicode code points.
|
||||||
func Map(mapping func(r rune) rune, s []byte) []byte {
|
func Map(mapping func(r rune) rune, s []byte) []byte {
|
||||||
// In the worst case, the slice can grow when mapped, making
|
// In the worst case, the slice can grow when mapped, making
|
||||||
// things unpleasant. But it's so rare we barge in assuming it's
|
// things unpleasant. But it's so rare we barge in assuming it's
|
||||||
// fine. It could also shrink but that falls out naturally.
|
// fine. It could also shrink but that falls out naturally.
|
||||||
maxbytes := len(s) // length of b
|
maxbytes := len(s) // length of b
|
||||||
nbytes := 0 // number of bytes encoded in b
|
nbytes := 0 // number of bytes encoded in b
|
||||||
b := make([]byte, maxbytes)
|
b := make([]byte, maxbytes)
|
||||||
|
|
@ -697,7 +707,7 @@ func EqualFold(s, t []byte) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// General case. SimpleFold(x) returns the next equivalent rune > x
|
// General case. SimpleFold(x) returns the next equivalent rune > x
|
||||||
// or wraps around to smaller values.
|
// or wraps around to smaller values.
|
||||||
r := unicode.SimpleFold(sr)
|
r := unicode.SimpleFold(sr)
|
||||||
for r != sr && r < tr {
|
for r != sr && r < tr {
|
||||||
|
|
@ -709,6 +719,6 @@ func EqualFold(s, t []byte) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// One string is empty. Are both?
|
// One string is empty. Are both?
|
||||||
return len(s) == len(t)
|
return len(s) == len(t)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ package bytes_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "bytes"
|
. "bytes"
|
||||||
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -47,32 +48,6 @@ type BinOpTest struct {
|
||||||
i int
|
i int
|
||||||
}
|
}
|
||||||
|
|
||||||
var equalTests = []struct {
|
|
||||||
a, b []byte
|
|
||||||
i int
|
|
||||||
}{
|
|
||||||
{[]byte(""), []byte(""), 0},
|
|
||||||
{[]byte("a"), []byte(""), 1},
|
|
||||||
{[]byte(""), []byte("a"), -1},
|
|
||||||
{[]byte("abc"), []byte("abc"), 0},
|
|
||||||
{[]byte("ab"), []byte("abc"), -1},
|
|
||||||
{[]byte("abc"), []byte("ab"), 1},
|
|
||||||
{[]byte("x"), []byte("ab"), 1},
|
|
||||||
{[]byte("ab"), []byte("x"), -1},
|
|
||||||
{[]byte("x"), []byte("a"), 1},
|
|
||||||
{[]byte("b"), []byte("x"), -1},
|
|
||||||
// test runtime·memeq's chunked implementation
|
|
||||||
{[]byte("abcdefgh"), []byte("abcdefgh"), 0},
|
|
||||||
{[]byte("abcdefghi"), []byte("abcdefghi"), 0},
|
|
||||||
{[]byte("abcdefghi"), []byte("abcdefghj"), -1},
|
|
||||||
// nil tests
|
|
||||||
{nil, nil, 0},
|
|
||||||
{[]byte(""), nil, 0},
|
|
||||||
{nil, []byte(""), 0},
|
|
||||||
{[]byte("a"), nil, 1},
|
|
||||||
{nil, []byte("a"), -1},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqual(t *testing.T) {
|
func TestEqual(t *testing.T) {
|
||||||
for _, tt := range compareTests {
|
for _, tt := range compareTests {
|
||||||
eql := Equal(tt.a, tt.b)
|
eql := Equal(tt.a, tt.b)
|
||||||
|
|
@ -113,7 +88,7 @@ func TestEqualExhaustive(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure Equal returns false for minimally different strings. The data
|
// make sure Equal returns false for minimally different strings. The data
|
||||||
// is all zeros except for a single one in one location.
|
// is all zeros except for a single one in one location.
|
||||||
func TestNotEqual(t *testing.T) {
|
func TestNotEqual(t *testing.T) {
|
||||||
var size = 128
|
var size = 128
|
||||||
|
|
@ -335,6 +310,41 @@ func TestIndexByteBig(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test a small index across all page offsets
|
||||||
|
func TestIndexByteSmall(t *testing.T) {
|
||||||
|
b := make([]byte, 5015) // bigger than a page
|
||||||
|
// Make sure we find the correct byte even when straddling a page.
|
||||||
|
for i := 0; i <= len(b)-15; i++ {
|
||||||
|
for j := 0; j < 15; j++ {
|
||||||
|
b[i+j] = byte(100 + j)
|
||||||
|
}
|
||||||
|
for j := 0; j < 15; j++ {
|
||||||
|
p := IndexByte(b[i:i+15], byte(100+j))
|
||||||
|
if p != j {
|
||||||
|
t.Errorf("IndexByte(%q, %d) = %d", b[i:i+15], 100+j, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j := 0; j < 15; j++ {
|
||||||
|
b[i+j] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make sure matches outside the slice never trigger.
|
||||||
|
for i := 0; i <= len(b)-15; i++ {
|
||||||
|
for j := 0; j < 15; j++ {
|
||||||
|
b[i+j] = 1
|
||||||
|
}
|
||||||
|
for j := 0; j < 15; j++ {
|
||||||
|
p := IndexByte(b[i:i+15], byte(0))
|
||||||
|
if p != -1 {
|
||||||
|
t.Errorf("IndexByte(%q, %d) = %d", b[i:i+15], 0, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j := 0; j < 15; j++ {
|
||||||
|
b[i+j] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIndexRune(t *testing.T) {
|
func TestIndexRune(t *testing.T) {
|
||||||
for _, tt := range indexRuneTests {
|
for _, tt := range indexRuneTests {
|
||||||
a := []byte(tt.a)
|
a := []byte(tt.a)
|
||||||
|
|
@ -348,165 +358,152 @@ func TestIndexRune(t *testing.T) {
|
||||||
|
|
||||||
var bmbuf []byte
|
var bmbuf []byte
|
||||||
|
|
||||||
func BenchmarkIndexByte32(b *testing.B) { bmIndexByte(b, IndexByte, 32) }
|
func valName(x int) string {
|
||||||
func BenchmarkIndexByte4K(b *testing.B) { bmIndexByte(b, IndexByte, 4<<10) }
|
if s := x >> 20; s<<20 == x {
|
||||||
func BenchmarkIndexByte4M(b *testing.B) { bmIndexByte(b, IndexByte, 4<<20) }
|
return fmt.Sprintf("%dM", s)
|
||||||
func BenchmarkIndexByte64M(b *testing.B) { bmIndexByte(b, IndexByte, 64<<20) }
|
|
||||||
func BenchmarkIndexBytePortable32(b *testing.B) { bmIndexByte(b, IndexBytePortable, 32) }
|
|
||||||
func BenchmarkIndexBytePortable4K(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<10) }
|
|
||||||
func BenchmarkIndexBytePortable4M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<20) }
|
|
||||||
func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) }
|
|
||||||
|
|
||||||
func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {
|
|
||||||
if len(bmbuf) < n {
|
|
||||||
bmbuf = make([]byte, n)
|
|
||||||
}
|
}
|
||||||
b.SetBytes(int64(n))
|
if s := x >> 10; s<<10 == x {
|
||||||
buf := bmbuf[0:n]
|
return fmt.Sprintf("%dK", s)
|
||||||
buf[n-1] = 'x'
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j := index(buf, 'x')
|
|
||||||
if j != n-1 {
|
|
||||||
b.Fatal("bad index", j)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
buf[n-1] = '\x00'
|
return fmt.Sprint(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkEqual0(b *testing.B) {
|
func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
|
||||||
var buf [4]byte
|
for _, n := range sizes {
|
||||||
buf1 := buf[0:0]
|
b.Run(valName(n), func(b *testing.B) {
|
||||||
buf2 := buf[1:1]
|
if len(bmbuf) < n {
|
||||||
for i := 0; i < b.N; i++ {
|
bmbuf = make([]byte, n)
|
||||||
eq := Equal(buf1, buf2)
|
}
|
||||||
if !eq {
|
b.SetBytes(int64(n))
|
||||||
b.Fatal("bad equal")
|
f(b, n)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkEqual1(b *testing.B) { bmEqual(b, Equal, 1) }
|
var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||||
func BenchmarkEqual6(b *testing.B) { bmEqual(b, Equal, 6) }
|
|
||||||
func BenchmarkEqual9(b *testing.B) { bmEqual(b, Equal, 9) }
|
|
||||||
func BenchmarkEqual15(b *testing.B) { bmEqual(b, Equal, 15) }
|
|
||||||
func BenchmarkEqual16(b *testing.B) { bmEqual(b, Equal, 16) }
|
|
||||||
func BenchmarkEqual20(b *testing.B) { bmEqual(b, Equal, 20) }
|
|
||||||
func BenchmarkEqual32(b *testing.B) { bmEqual(b, Equal, 32) }
|
|
||||||
func BenchmarkEqual4K(b *testing.B) { bmEqual(b, Equal, 4<<10) }
|
|
||||||
func BenchmarkEqual4M(b *testing.B) { bmEqual(b, Equal, 4<<20) }
|
|
||||||
func BenchmarkEqual64M(b *testing.B) { bmEqual(b, Equal, 64<<20) }
|
|
||||||
func BenchmarkEqualPort1(b *testing.B) { bmEqual(b, EqualPortable, 1) }
|
|
||||||
func BenchmarkEqualPort6(b *testing.B) { bmEqual(b, EqualPortable, 6) }
|
|
||||||
func BenchmarkEqualPort32(b *testing.B) { bmEqual(b, EqualPortable, 32) }
|
|
||||||
func BenchmarkEqualPort4K(b *testing.B) { bmEqual(b, EqualPortable, 4<<10) }
|
|
||||||
func BenchmarkEqualPortable4M(b *testing.B) { bmEqual(b, EqualPortable, 4<<20) }
|
|
||||||
func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) }
|
|
||||||
|
|
||||||
func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {
|
func BenchmarkIndexByte(b *testing.B) {
|
||||||
if len(bmbuf) < 2*n {
|
benchBytes(b, indexSizes, bmIndexByte(IndexByte))
|
||||||
bmbuf = make([]byte, 2*n)
|
|
||||||
}
|
|
||||||
b.SetBytes(int64(n))
|
|
||||||
buf1 := bmbuf[0:n]
|
|
||||||
buf2 := bmbuf[n : 2*n]
|
|
||||||
buf1[n-1] = 'x'
|
|
||||||
buf2[n-1] = 'x'
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
eq := equal(buf1, buf2)
|
|
||||||
if !eq {
|
|
||||||
b.Fatal("bad equal")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf1[n-1] = '\x00'
|
|
||||||
buf2[n-1] = '\x00'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkIndex32(b *testing.B) { bmIndex(b, Index, 32) }
|
func BenchmarkIndexBytePortable(b *testing.B) {
|
||||||
func BenchmarkIndex4K(b *testing.B) { bmIndex(b, Index, 4<<10) }
|
benchBytes(b, indexSizes, bmIndexByte(IndexBytePortable))
|
||||||
func BenchmarkIndex4M(b *testing.B) { bmIndex(b, Index, 4<<20) }
|
|
||||||
func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) }
|
|
||||||
|
|
||||||
func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) {
|
|
||||||
if len(bmbuf) < n {
|
|
||||||
bmbuf = make([]byte, n)
|
|
||||||
}
|
|
||||||
b.SetBytes(int64(n))
|
|
||||||
buf := bmbuf[0:n]
|
|
||||||
buf[n-1] = 'x'
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j := index(buf, buf[n-7:])
|
|
||||||
if j != n-7 {
|
|
||||||
b.Fatal("bad index", j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf[n-1] = '\x00'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkIndexEasy32(b *testing.B) { bmIndexEasy(b, Index, 32) }
|
func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) {
|
||||||
func BenchmarkIndexEasy4K(b *testing.B) { bmIndexEasy(b, Index, 4<<10) }
|
return func(b *testing.B, n int) {
|
||||||
func BenchmarkIndexEasy4M(b *testing.B) { bmIndexEasy(b, Index, 4<<20) }
|
buf := bmbuf[0:n]
|
||||||
func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) }
|
buf[n-1] = 'x'
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) {
|
j := index(buf, 'x')
|
||||||
if len(bmbuf) < n {
|
if j != n-1 {
|
||||||
bmbuf = make([]byte, n)
|
b.Fatal("bad index", j)
|
||||||
}
|
}
|
||||||
b.SetBytes(int64(n))
|
|
||||||
buf := bmbuf[0:n]
|
|
||||||
buf[n-1] = 'x'
|
|
||||||
buf[n-7] = 'x'
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j := index(buf, buf[n-7:])
|
|
||||||
if j != n-7 {
|
|
||||||
b.Fatal("bad index", j)
|
|
||||||
}
|
}
|
||||||
|
buf[n-1] = '\x00'
|
||||||
}
|
}
|
||||||
buf[n-1] = '\x00'
|
|
||||||
buf[n-7] = '\x00'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCount32(b *testing.B) { bmCount(b, Count, 32) }
|
func BenchmarkEqual(b *testing.B) {
|
||||||
func BenchmarkCount4K(b *testing.B) { bmCount(b, Count, 4<<10) }
|
b.Run("0", func(b *testing.B) {
|
||||||
func BenchmarkCount4M(b *testing.B) { bmCount(b, Count, 4<<20) }
|
var buf [4]byte
|
||||||
func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) }
|
buf1 := buf[0:0]
|
||||||
|
buf2 := buf[1:1]
|
||||||
func bmCount(b *testing.B, count func([]byte, []byte) int, n int) {
|
for i := 0; i < b.N; i++ {
|
||||||
if len(bmbuf) < n {
|
eq := Equal(buf1, buf2)
|
||||||
bmbuf = make([]byte, n)
|
if !eq {
|
||||||
}
|
b.Fatal("bad equal")
|
||||||
b.SetBytes(int64(n))
|
}
|
||||||
buf := bmbuf[0:n]
|
|
||||||
buf[n-1] = 'x'
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j := count(buf, buf[n-7:])
|
|
||||||
if j != 1 {
|
|
||||||
b.Fatal("bad count", j)
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
buf[n-1] = '\x00'
|
|
||||||
|
sizes := []int{1, 6, 9, 15, 16, 20, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||||
|
benchBytes(b, sizes, bmEqual(Equal))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCountEasy32(b *testing.B) { bmCountEasy(b, Count, 32) }
|
func BenchmarkEqualPort(b *testing.B) {
|
||||||
func BenchmarkCountEasy4K(b *testing.B) { bmCountEasy(b, Count, 4<<10) }
|
sizes := []int{1, 6, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||||
func BenchmarkCountEasy4M(b *testing.B) { bmCountEasy(b, Count, 4<<20) }
|
benchBytes(b, sizes, bmEqual(EqualPortable))
|
||||||
func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) }
|
}
|
||||||
|
|
||||||
func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) {
|
func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) {
|
||||||
if len(bmbuf) < n {
|
return func(b *testing.B, n int) {
|
||||||
bmbuf = make([]byte, n)
|
if len(bmbuf) < 2*n {
|
||||||
}
|
bmbuf = make([]byte, 2*n)
|
||||||
b.SetBytes(int64(n))
|
|
||||||
buf := bmbuf[0:n]
|
|
||||||
buf[n-1] = 'x'
|
|
||||||
buf[n-7] = 'x'
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j := count(buf, buf[n-7:])
|
|
||||||
if j != 1 {
|
|
||||||
b.Fatal("bad count", j)
|
|
||||||
}
|
}
|
||||||
|
buf1 := bmbuf[0:n]
|
||||||
|
buf2 := bmbuf[n : 2*n]
|
||||||
|
buf1[n-1] = 'x'
|
||||||
|
buf2[n-1] = 'x'
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
eq := equal(buf1, buf2)
|
||||||
|
if !eq {
|
||||||
|
b.Fatal("bad equal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf1[n-1] = '\x00'
|
||||||
|
buf2[n-1] = '\x00'
|
||||||
}
|
}
|
||||||
buf[n-1] = '\x00'
|
}
|
||||||
buf[n-7] = '\x00'
|
|
||||||
|
func BenchmarkIndex(b *testing.B) {
|
||||||
|
benchBytes(b, indexSizes, func(b *testing.B, n int) {
|
||||||
|
buf := bmbuf[0:n]
|
||||||
|
buf[n-1] = 'x'
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j := Index(buf, buf[n-7:])
|
||||||
|
if j != n-7 {
|
||||||
|
b.Fatal("bad index", j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[n-1] = '\x00'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIndexEasy(b *testing.B) {
|
||||||
|
benchBytes(b, indexSizes, func(b *testing.B, n int) {
|
||||||
|
buf := bmbuf[0:n]
|
||||||
|
buf[n-1] = 'x'
|
||||||
|
buf[n-7] = 'x'
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j := Index(buf, buf[n-7:])
|
||||||
|
if j != n-7 {
|
||||||
|
b.Fatal("bad index", j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[n-1] = '\x00'
|
||||||
|
buf[n-7] = '\x00'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCount(b *testing.B) {
|
||||||
|
benchBytes(b, indexSizes, func(b *testing.B, n int) {
|
||||||
|
buf := bmbuf[0:n]
|
||||||
|
buf[n-1] = 'x'
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j := Count(buf, buf[n-7:])
|
||||||
|
if j != 1 {
|
||||||
|
b.Fatal("bad count", j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[n-1] = '\x00'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCountEasy(b *testing.B) {
|
||||||
|
benchBytes(b, indexSizes, func(b *testing.B, n int) {
|
||||||
|
buf := bmbuf[0:n]
|
||||||
|
buf[n-1] = 'x'
|
||||||
|
buf[n-7] = 'x'
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j := Count(buf, buf[n-7:])
|
||||||
|
if j != 1 {
|
||||||
|
b.Fatal("bad count", j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[n-1] = '\x00'
|
||||||
|
buf[n-7] = '\x00'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExplodeTest struct {
|
type ExplodeTest struct {
|
||||||
|
|
@ -760,7 +757,7 @@ func TestMap(t *testing.T) {
|
||||||
// Run a couple of awful growth/shrinkage tests
|
// Run a couple of awful growth/shrinkage tests
|
||||||
a := tenRunes('a')
|
a := tenRunes('a')
|
||||||
|
|
||||||
// 1. Grow. This triggers two reallocations in Map.
|
// 1. Grow. This triggers two reallocations in Map.
|
||||||
maxRune := func(r rune) rune { return unicode.MaxRune }
|
maxRune := func(r rune) rune { return unicode.MaxRune }
|
||||||
m := Map(maxRune, []byte(a))
|
m := Map(maxRune, []byte(a))
|
||||||
expect := tenRunes(unicode.MaxRune)
|
expect := tenRunes(unicode.MaxRune)
|
||||||
|
|
@ -1207,6 +1204,57 @@ func TestContains(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ContainsAnyTests = []struct {
|
||||||
|
b []byte
|
||||||
|
substr string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{[]byte(""), "", false},
|
||||||
|
{[]byte(""), "a", false},
|
||||||
|
{[]byte(""), "abc", false},
|
||||||
|
{[]byte("a"), "", false},
|
||||||
|
{[]byte("a"), "a", true},
|
||||||
|
{[]byte("aaa"), "a", true},
|
||||||
|
{[]byte("abc"), "xyz", false},
|
||||||
|
{[]byte("abc"), "xcz", true},
|
||||||
|
{[]byte("a☺b☻c☹d"), "uvw☻xyz", true},
|
||||||
|
{[]byte("aRegExp*"), ".(|)*+?^$[]", true},
|
||||||
|
{[]byte(dots + dots + dots), " ", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContainsAny(t *testing.T) {
|
||||||
|
for _, ct := range ContainsAnyTests {
|
||||||
|
if ContainsAny(ct.b, ct.substr) != ct.expected {
|
||||||
|
t.Errorf("ContainsAny(%s, %s) = %v, want %v",
|
||||||
|
ct.b, ct.substr, !ct.expected, ct.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ContainsRuneTests = []struct {
|
||||||
|
b []byte
|
||||||
|
r rune
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{[]byte(""), 'a', false},
|
||||||
|
{[]byte("a"), 'a', true},
|
||||||
|
{[]byte("aaa"), 'a', true},
|
||||||
|
{[]byte("abc"), 'y', false},
|
||||||
|
{[]byte("abc"), 'c', true},
|
||||||
|
{[]byte("a☺b☻c☹d"), 'x', false},
|
||||||
|
{[]byte("a☺b☻c☹d"), '☻', true},
|
||||||
|
{[]byte("aRegExp*"), '*', true},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContainsRune(t *testing.T) {
|
||||||
|
for _, ct := range ContainsRuneTests {
|
||||||
|
if ContainsRune(ct.b, ct.r) != ct.expected {
|
||||||
|
t.Errorf("ContainsRune(%q, %q) = %v, want %v",
|
||||||
|
ct.b, ct.r, !ct.expected, ct.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var makeFieldsInput = func() []byte {
|
var makeFieldsInput = func() []byte {
|
||||||
x := make([]byte, 1<<20)
|
x := make([]byte, 1<<20)
|
||||||
// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
|
// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
|
||||||
|
|
@ -1256,33 +1304,24 @@ func BenchmarkRepeat(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func benchmarkBytesCompare(b *testing.B, n int) {
|
func BenchmarkBytesCompare(b *testing.B) {
|
||||||
var x = make([]byte, n)
|
for n := 1; n <= 2048; n <<= 1 {
|
||||||
var y = make([]byte, n)
|
b.Run(fmt.Sprint(n), func(b *testing.B) {
|
||||||
|
var x = make([]byte, n)
|
||||||
|
var y = make([]byte, n)
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
x[i] = 'a'
|
x[i] = 'a'
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
y[i] = 'a'
|
y[i] = 'a'
|
||||||
}
|
}
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
Compare(x, y)
|
Compare(x, y)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkBytesCompare1(b *testing.B) { benchmarkBytesCompare(b, 1) }
|
|
||||||
func BenchmarkBytesCompare2(b *testing.B) { benchmarkBytesCompare(b, 2) }
|
|
||||||
func BenchmarkBytesCompare4(b *testing.B) { benchmarkBytesCompare(b, 4) }
|
|
||||||
func BenchmarkBytesCompare8(b *testing.B) { benchmarkBytesCompare(b, 8) }
|
|
||||||
func BenchmarkBytesCompare16(b *testing.B) { benchmarkBytesCompare(b, 16) }
|
|
||||||
func BenchmarkBytesCompare32(b *testing.B) { benchmarkBytesCompare(b, 32) }
|
|
||||||
func BenchmarkBytesCompare64(b *testing.B) { benchmarkBytesCompare(b, 64) }
|
|
||||||
func BenchmarkBytesCompare128(b *testing.B) { benchmarkBytesCompare(b, 128) }
|
|
||||||
func BenchmarkBytesCompare256(b *testing.B) { benchmarkBytesCompare(b, 256) }
|
|
||||||
func BenchmarkBytesCompare512(b *testing.B) { benchmarkBytesCompare(b, 512) }
|
|
||||||
func BenchmarkBytesCompare1024(b *testing.B) { benchmarkBytesCompare(b, 1024) }
|
|
||||||
func BenchmarkBytesCompare2048(b *testing.B) { benchmarkBytesCompare(b, 2048) }
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ func TestCompareBytes(t *testing.T) {
|
||||||
a := make([]byte, n+1)
|
a := make([]byte, n+1)
|
||||||
b := make([]byte, n+1)
|
b := make([]byte, n+1)
|
||||||
for len := 0; len < 128; len++ {
|
for len := 0; len < 128; len++ {
|
||||||
// randomish but deterministic data. No 0 or 255.
|
// randomish but deterministic data. No 0 or 255.
|
||||||
for i := 0; i < len; i++ {
|
for i := 0; i < len; i++ {
|
||||||
a[i] = byte(1 + 31*i%254)
|
a[i] = byte(1 + 31*i%254)
|
||||||
b[i] = byte(1 + 31*i%254)
|
b[i] = byte(1 + 31*i%254)
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// This file tests the situation where memeq is checking
|
// This file tests the situation where memeq is checking
|
||||||
// data very near to a page boundary. We want to make sure
|
// data very near to a page boundary. We want to make sure
|
||||||
// equal does not read across the boundary and cause a page
|
// equal does not read across the boundary and cause a page
|
||||||
// fault where it shouldn't.
|
// fault where it shouldn't.
|
||||||
|
|
||||||
// This test runs only on linux. The code being tested is
|
// This test runs only on linux. The code being tested is
|
||||||
// not OS-specific, so it does not need to be tested on all
|
// not OS-specific, so it does not need to be tested on all
|
||||||
// operating systems.
|
// operating systems.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,6 @@ func (r *Reader) Len() int {
|
||||||
func (r *Reader) Size() int64 { return int64(len(r.s)) }
|
func (r *Reader) Size() int64 { return int64(len(r.s)) }
|
||||||
|
|
||||||
func (r *Reader) Read(b []byte) (n int, err error) {
|
func (r *Reader) Read(b []byte) (n int, err error) {
|
||||||
if len(b) == 0 {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
if r.i >= int64(len(r.s)) {
|
if r.i >= int64(len(r.s)) {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
|
|
@ -63,14 +60,14 @@ func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) ReadByte() (b byte, err error) {
|
func (r *Reader) ReadByte() (byte, error) {
|
||||||
r.prevRune = -1
|
r.prevRune = -1
|
||||||
if r.i >= int64(len(r.s)) {
|
if r.i >= int64(len(r.s)) {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
b = r.s[r.i]
|
b := r.s[r.i]
|
||||||
r.i++
|
r.i++
|
||||||
return
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) UnreadByte() error {
|
func (r *Reader) UnreadByte() error {
|
||||||
|
|
@ -111,11 +108,11 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||||
r.prevRune = -1
|
r.prevRune = -1
|
||||||
var abs int64
|
var abs int64
|
||||||
switch whence {
|
switch whence {
|
||||||
case 0:
|
case io.SeekStart:
|
||||||
abs = offset
|
abs = offset
|
||||||
case 1:
|
case io.SeekCurrent:
|
||||||
abs = int64(r.i) + offset
|
abs = r.i + offset
|
||||||
case 2:
|
case io.SeekEnd:
|
||||||
abs = int64(len(r.s)) + offset
|
abs = int64(len(r.s)) + offset
|
||||||
default:
|
default:
|
||||||
return 0, errors.New("bytes.Reader.Seek: invalid whence")
|
return 0, errors.New("bytes.Reader.Seek: invalid whence")
|
||||||
|
|
@ -146,5 +143,8 @@ func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset resets the Reader to be reading from b.
|
||||||
|
func (r *Reader) Reset(b []byte) { *r = Reader{b, 0, -1} }
|
||||||
|
|
||||||
// NewReader returns a new Reader reading from b.
|
// NewReader returns a new Reader reading from b.
|
||||||
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
|
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
@ -22,17 +21,18 @@ func TestReader(t *testing.T) {
|
||||||
n int
|
n int
|
||||||
want string
|
want string
|
||||||
wantpos int64
|
wantpos int64
|
||||||
|
readerr error
|
||||||
seekerr string
|
seekerr string
|
||||||
}{
|
}{
|
||||||
{seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"},
|
{seek: io.SeekStart, off: 0, n: 20, want: "0123456789"},
|
||||||
{seek: os.SEEK_SET, off: 1, n: 1, want: "1"},
|
{seek: io.SeekStart, off: 1, n: 1, want: "1"},
|
||||||
{seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"},
|
{seek: io.SeekCurrent, off: 1, wantpos: 3, n: 2, want: "34"},
|
||||||
{seek: os.SEEK_SET, off: -1, seekerr: "bytes.Reader.Seek: negative position"},
|
{seek: io.SeekStart, off: -1, seekerr: "bytes.Reader.Seek: negative position"},
|
||||||
{seek: os.SEEK_SET, off: 1 << 33, wantpos: 1 << 33},
|
{seek: io.SeekStart, off: 1 << 33, wantpos: 1 << 33, readerr: io.EOF},
|
||||||
{seek: os.SEEK_CUR, off: 1, wantpos: 1<<33 + 1},
|
{seek: io.SeekCurrent, off: 1, wantpos: 1<<33 + 1, readerr: io.EOF},
|
||||||
{seek: os.SEEK_SET, n: 5, want: "01234"},
|
{seek: io.SeekStart, n: 5, want: "01234"},
|
||||||
{seek: os.SEEK_CUR, n: 5, want: "56789"},
|
{seek: io.SeekCurrent, n: 5, want: "56789"},
|
||||||
{seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"},
|
{seek: io.SeekEnd, off: -1, n: 1, wantpos: 9, want: "9"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
|
|
@ -50,8 +50,8 @@ func TestReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
buf := make([]byte, tt.n)
|
buf := make([]byte, tt.n)
|
||||||
n, err := r.Read(buf)
|
n, err := r.Read(buf)
|
||||||
if err != nil {
|
if err != tt.readerr {
|
||||||
t.Errorf("%d. read = %v", i, err)
|
t.Errorf("%d. read = %v; want %v", i, err, tt.readerr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
got := string(buf[:n])
|
got := string(buf[:n])
|
||||||
|
|
@ -63,7 +63,7 @@ func TestReader(t *testing.T) {
|
||||||
|
|
||||||
func TestReadAfterBigSeek(t *testing.T) {
|
func TestReadAfterBigSeek(t *testing.T) {
|
||||||
r := NewReader([]byte("0123456789"))
|
r := NewReader([]byte("0123456789"))
|
||||||
if _, err := r.Seek(1<<31+5, os.SEEK_SET); err != nil {
|
if _, err := r.Seek(1<<31+5, io.SeekStart); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF {
|
if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF {
|
||||||
|
|
@ -174,7 +174,7 @@ func TestReaderLen(t *testing.T) {
|
||||||
t.Errorf("r.Len(): got %d, want %d", got, want)
|
t.Errorf("r.Len(): got %d, want %d", got, want)
|
||||||
}
|
}
|
||||||
if n, err := r.Read(make([]byte, 1)); err != nil || n != 1 {
|
if n, err := r.Read(make([]byte, 1)); err != nil || n != 1 {
|
||||||
t.Errorf("Read failed: read %d %v", n, err)
|
t.Errorf("Read failed: read %d %v; want 1, nil", n, err)
|
||||||
}
|
}
|
||||||
if got, want := r.Len(), 0; got != want {
|
if got, want := r.Len(), 0; got != want {
|
||||||
t.Errorf("r.Len(): got %d, want %d", got, want)
|
t.Errorf("r.Len(): got %d, want %d", got, want)
|
||||||
|
|
@ -188,7 +188,7 @@ var UnreadRuneErrorTests = []struct {
|
||||||
{"Read", func(r *Reader) { r.Read([]byte{0}) }},
|
{"Read", func(r *Reader) { r.Read([]byte{0}) }},
|
||||||
{"ReadByte", func(r *Reader) { r.ReadByte() }},
|
{"ReadByte", func(r *Reader) { r.ReadByte() }},
|
||||||
{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
|
{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
|
||||||
{"Seek", func(r *Reader) { r.Seek(0, 1) }},
|
{"Seek", func(r *Reader) { r.Seek(0, io.SeekCurrent) }},
|
||||||
{"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }},
|
{"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -256,3 +256,23 @@ func TestReaderLenSize(t *testing.T) {
|
||||||
t.Errorf("Size = %d; want 3", r.Size())
|
t.Errorf("Size = %d; want 3", r.Size())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReaderReset(t *testing.T) {
|
||||||
|
r := NewReader([]byte("世界"))
|
||||||
|
if _, _, err := r.ReadRune(); err != nil {
|
||||||
|
t.Errorf("ReadRune: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const want = "abcdef"
|
||||||
|
r.Reset([]byte(want))
|
||||||
|
if err := r.UnreadRune(); err == nil {
|
||||||
|
t.Errorf("UnreadRune: expected error, got nil")
|
||||||
|
}
|
||||||
|
buf, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ReadAll: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if got := string(buf); got != want {
|
||||||
|
t.Errorf("ReadAll: got %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ func sourceLine(n ast.Node) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadGo populates f with information learned from reading the
|
// ReadGo populates f with information learned from reading the
|
||||||
// Go source file with the given file name. It gathers the C preamble
|
// Go source file with the given file name. It gathers the C preamble
|
||||||
// attached to the import "C" comment, a list of references to C.xxx,
|
// attached to the import "C" comment, a list of references to C.xxx,
|
||||||
// a list of exported functions, and the actual AST, to be rewritten and
|
// a list of exported functions, and the actual AST, to be rewritten and
|
||||||
// printed.
|
// printed.
|
||||||
|
|
@ -73,7 +73,7 @@ func (f *File) ReadGo(name string) {
|
||||||
}
|
}
|
||||||
for _, spec := range d.Specs {
|
for _, spec := range d.Specs {
|
||||||
s, ok := spec.(*ast.ImportSpec)
|
s, ok := spec.(*ast.ImportSpec)
|
||||||
if !ok || string(s.Path.Value) != `"C"` {
|
if !ok || s.Path.Value != `"C"` {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sawC = true
|
sawC = true
|
||||||
|
|
@ -106,7 +106,7 @@ func (f *File) ReadGo(name string) {
|
||||||
ws := 0
|
ws := 0
|
||||||
for _, spec := range d.Specs {
|
for _, spec := range d.Specs {
|
||||||
s, ok := spec.(*ast.ImportSpec)
|
s, ok := spec.(*ast.ImportSpec)
|
||||||
if !ok || string(s.Path.Value) != `"C"` {
|
if !ok || s.Path.Value != `"C"` {
|
||||||
d.Specs[ws] = spec
|
d.Specs[ws] = spec
|
||||||
ws++
|
ws++
|
||||||
}
|
}
|
||||||
|
|
@ -147,7 +147,7 @@ func commentText(g *ast.CommentGroup) string {
|
||||||
}
|
}
|
||||||
var pieces []string
|
var pieces []string
|
||||||
for _, com := range g.List {
|
for _, com := range g.List {
|
||||||
c := string(com.Text)
|
c := com.Text
|
||||||
// Remove comment markers.
|
// Remove comment markers.
|
||||||
// The parser has given us exactly the comment text.
|
// The parser has given us exactly the comment text.
|
||||||
switch c[1] {
|
switch c[1] {
|
||||||
|
|
@ -172,7 +172,7 @@ func (f *File) saveExprs(x interface{}, context string) {
|
||||||
f.saveRef(x, context)
|
f.saveRef(x, context)
|
||||||
}
|
}
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
f.saveCall(x)
|
f.saveCall(x, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ func (f *File) saveRef(n *ast.Expr, context string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save calls to C.xxx for later processing.
|
// Save calls to C.xxx for later processing.
|
||||||
func (f *File) saveCall(call *ast.CallExpr) {
|
func (f *File) saveCall(call *ast.CallExpr, context string) {
|
||||||
sel, ok := call.Fun.(*ast.SelectorExpr)
|
sel, ok := call.Fun.(*ast.SelectorExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
|
|
@ -228,7 +228,8 @@ func (f *File) saveCall(call *ast.CallExpr) {
|
||||||
if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
|
if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f.Calls = append(f.Calls, call)
|
c := &Call{Call: call, Deferred: context == "defer"}
|
||||||
|
f.Calls = append(f.Calls, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a function should be exported add it to ExpFunc.
|
// If a function should be exported add it to ExpFunc.
|
||||||
|
|
@ -242,11 +243,11 @@ func (f *File) saveExport(x interface{}, context string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, c := range n.Doc.List {
|
for _, c := range n.Doc.List {
|
||||||
if !strings.HasPrefix(string(c.Text), "//export ") {
|
if !strings.HasPrefix(c.Text, "//export ") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
name := strings.TrimSpace(string(c.Text[9:]))
|
name := strings.TrimSpace(c.Text[9:])
|
||||||
if name == "" {
|
if name == "" {
|
||||||
error_(c.Pos(), "export missing name")
|
error_(c.Pos(), "export missing name")
|
||||||
}
|
}
|
||||||
|
|
@ -401,7 +402,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
|
||||||
case *ast.GoStmt:
|
case *ast.GoStmt:
|
||||||
f.walk(n.Call, "expr", visit)
|
f.walk(n.Call, "expr", visit)
|
||||||
case *ast.DeferStmt:
|
case *ast.DeferStmt:
|
||||||
f.walk(n.Call, "expr", visit)
|
f.walk(n.Call, "defer", visit)
|
||||||
case *ast.ReturnStmt:
|
case *ast.ReturnStmt:
|
||||||
f.walk(n.Results, "expr", visit)
|
f.walk(n.Results, "expr", visit)
|
||||||
case *ast.BranchStmt:
|
case *ast.BranchStmt:
|
||||||
|
|
@ -447,7 +448,11 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
|
||||||
case *ast.ImportSpec:
|
case *ast.ImportSpec:
|
||||||
case *ast.ValueSpec:
|
case *ast.ValueSpec:
|
||||||
f.walk(&n.Type, "type", visit)
|
f.walk(&n.Type, "type", visit)
|
||||||
f.walk(n.Values, "expr", visit)
|
if len(n.Names) == 2 && len(n.Values) == 1 {
|
||||||
|
f.walk(&n.Values[0], "as2", visit)
|
||||||
|
} else {
|
||||||
|
f.walk(n.Values, "expr", visit)
|
||||||
|
}
|
||||||
case *ast.TypeSpec:
|
case *ast.TypeSpec:
|
||||||
f.walk(&n.Type, "type", visit)
|
f.walk(&n.Type, "type", visit)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -31,9 +31,9 @@ See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See
|
||||||
"C? Go? Cgo!" for an introduction to using cgo:
|
"C? Go? Cgo!" for an introduction to using cgo:
|
||||||
https://golang.org/doc/articles/c_go_cgo.html.
|
https://golang.org/doc/articles/c_go_cgo.html.
|
||||||
|
|
||||||
CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo
|
CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS and LDFLAGS may be defined with pseudo
|
||||||
directives within these comments to tweak the behavior of the C or C++
|
#cgo directives within these comments to tweak the behavior of the C, C++
|
||||||
compiler. Values defined in multiple directives are concatenated
|
or Fortran compiler. Values defined in multiple directives are concatenated
|
||||||
together. The directive can include a list of build constraints limiting its
|
together. The directive can include a list of build constraints limiting its
|
||||||
effect to systems satisfying one of the constraints
|
effect to systems satisfying one of the constraints
|
||||||
(see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
|
(see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
|
||||||
|
|
@ -53,7 +53,7 @@ For example:
|
||||||
// #include <png.h>
|
// #include <png.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS and
|
When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and
|
||||||
CGO_LDFLAGS environment variables are added to the flags derived from
|
CGO_LDFLAGS environment variables are added to the flags derived from
|
||||||
these directives. Package-specific flags should be set using the
|
these directives. Package-specific flags should be set using the
|
||||||
directives, not the environment variables, so that builds work in
|
directives, not the environment variables, so that builds work in
|
||||||
|
|
@ -62,10 +62,11 @@ unmodified environments.
|
||||||
All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and
|
All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and
|
||||||
used to compile C files in that package. All the CPPFLAGS and CXXFLAGS
|
used to compile C files in that package. All the CPPFLAGS and CXXFLAGS
|
||||||
directives in a package are concatenated and used to compile C++ files in that
|
directives in a package are concatenated and used to compile C++ files in that
|
||||||
package. All the LDFLAGS directives in any package in the program are
|
package. All the CPPFLAGS and FFLAGS directives in a package are concatenated
|
||||||
concatenated and used at link time. All the pkg-config directives are
|
and used to compile Fortran files in that package. All the LDFLAGS directives
|
||||||
concatenated and sent to pkg-config simultaneously to add to each appropriate
|
in any package in the program are concatenated and used at link time. All the
|
||||||
set of command-line flags.
|
pkg-config directives are concatenated and sent to pkg-config simultaneously
|
||||||
|
to add to each appropriate set of command-line flags.
|
||||||
|
|
||||||
When the cgo directives are parsed, any occurrence of the string ${SRCDIR}
|
When the cgo directives are parsed, any occurrence of the string ${SRCDIR}
|
||||||
will be replaced by the absolute path to the directory containing the source
|
will be replaced by the absolute path to the directory containing the source
|
||||||
|
|
@ -83,7 +84,8 @@ When the Go tool sees that one or more Go files use the special import
|
||||||
"C", it will look for other non-Go files in the directory and compile
|
"C", it will look for other non-Go files in the directory and compile
|
||||||
them as part of the Go package. Any .c, .s, or .S files will be
|
them as part of the Go package. Any .c, .s, or .S files will be
|
||||||
compiled with the C compiler. Any .cc, .cpp, or .cxx files will be
|
compiled with the C compiler. Any .cc, .cpp, or .cxx files will be
|
||||||
compiled with the C++ compiler. Any .h, .hh, .hpp, or .hxx files will
|
compiled with the C++ compiler. Any .f, .F, .for or .f90 files will be
|
||||||
|
compiled with the fortran compiler. Any .h, .hh, .hpp, or .hxx files will
|
||||||
not be compiled separately, but, if these header files are changed,
|
not be compiled separately, but, if these header files are changed,
|
||||||
the C and C++ files will be recompiled. The default C and C++
|
the C and C++ files will be recompiled. The default C and C++
|
||||||
compilers may be changed by the CC and CXX environment variables,
|
compilers may be changed by the CC and CXX environment variables,
|
||||||
|
|
@ -133,7 +135,7 @@ C's union types are represented as a Go byte array with the same length.
|
||||||
|
|
||||||
Go structs cannot embed fields with C types.
|
Go structs cannot embed fields with C types.
|
||||||
|
|
||||||
Go code can not refer to zero-sized fields that occur at the end of
|
Go code cannot refer to zero-sized fields that occur at the end of
|
||||||
non-empty C structs. To get the address of such a field (which is the
|
non-empty C structs. To get the address of such a field (which is the
|
||||||
only operation you can do with a zero-sized field) you must take the
|
only operation you can do with a zero-sized field) you must take the
|
||||||
address of the struct and add the size of the struct.
|
address of the struct and add the size of the struct.
|
||||||
|
|
@ -148,8 +150,9 @@ assignment context to retrieve both the return value (if any) and the
|
||||||
C errno variable as an error (use _ to skip the result value if the
|
C errno variable as an error (use _ to skip the result value if the
|
||||||
function returns void). For example:
|
function returns void). For example:
|
||||||
|
|
||||||
n, err := C.sqrt(-1)
|
n, err = C.sqrt(-1)
|
||||||
_, err := C.voidFunc()
|
_, err := C.voidFunc()
|
||||||
|
var n, err = C.sqrt(1)
|
||||||
|
|
||||||
Calling C function pointers is currently not supported, however you can
|
Calling C function pointers is currently not supported, however you can
|
||||||
declare Go variables which hold C function pointers and pass them
|
declare Go variables which hold C function pointers and pass them
|
||||||
|
|
@ -195,6 +198,13 @@ by making copies of the data. In pseudo-Go definitions:
|
||||||
// if C.free is needed).
|
// if C.free is needed).
|
||||||
func C.CString(string) *C.char
|
func C.CString(string) *C.char
|
||||||
|
|
||||||
|
// Go []byte slice to C array
|
||||||
|
// The C array is allocated in the C heap using malloc.
|
||||||
|
// It is the caller's responsibility to arrange for it to be
|
||||||
|
// freed, such as by calling C.free (be sure to include stdlib.h
|
||||||
|
// if C.free is needed).
|
||||||
|
func C.CBytes([]byte) unsafe.Pointer
|
||||||
|
|
||||||
// C string to Go string
|
// C string to Go string
|
||||||
func C.GoString(*C.char) string
|
func C.GoString(*C.char) string
|
||||||
|
|
||||||
|
|
@ -501,7 +511,6 @@ file compiled by gcc, the file x.cgo2.c:
|
||||||
void
|
void
|
||||||
_cgo_be59f0f25121_Cfunc_puts(void *v)
|
_cgo_be59f0f25121_Cfunc_puts(void *v)
|
||||||
{
|
{
|
||||||
_cgo_wait_runtime_init_done();
|
|
||||||
struct {
|
struct {
|
||||||
char* p0;
|
char* p0;
|
||||||
int r;
|
int r;
|
||||||
|
|
@ -510,8 +519,7 @@ file compiled by gcc, the file x.cgo2.c:
|
||||||
a->r = puts((void*)a->p0);
|
a->r = puts((void*)a->p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
It waits for Go runtime to be initialized (required for shared libraries),
|
It extracts the arguments from the pointer to _Cfunc_puts's argument
|
||||||
extracts the arguments from the pointer to _Cfunc_puts's argument
|
|
||||||
frame, invokes the system C function (in this case, puts), stores the
|
frame, invokes the system C function (in this case, puts), stores the
|
||||||
result in the frame, and returns.
|
result in the frame, and returns.
|
||||||
|
|
||||||
|
|
@ -529,8 +537,8 @@ linkage to the desired libraries. The main function is provided by
|
||||||
_cgo_main.c:
|
_cgo_main.c:
|
||||||
|
|
||||||
int main() { return 0; }
|
int main() { return 0; }
|
||||||
void crosscall2(void(*fn)(void*, int), void *a, int c) { }
|
void crosscall2(void(*fn)(void*, int, uintptr_t), void *a, int c, uintptr_t ctxt) { }
|
||||||
void _cgo_wait_runtime_init_done() { }
|
uintptr_t _cgo_wait_runtime_init_done() { }
|
||||||
void _cgo_allocate(void *a, int c) { }
|
void _cgo_allocate(void *a, int c) { }
|
||||||
void _cgo_panic(void *a, int c) { }
|
void _cgo_panic(void *a, int c) { }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ func (f *File) DiscardCgoDirectives() {
|
||||||
f.Preamble = strings.Join(linesOut, "\n")
|
f.Preamble = strings.Join(linesOut, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// addToFlag appends args to flag. All flags are later written out onto the
|
// addToFlag appends args to flag. All flags are later written out onto the
|
||||||
// _cgo_flags file for the build system to use.
|
// _cgo_flags file for the build system to use.
|
||||||
func (p *Package) addToFlag(flag string, args []string) {
|
func (p *Package) addToFlag(flag string, args []string) {
|
||||||
p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
|
p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
|
||||||
|
|
@ -99,7 +99,7 @@ func (p *Package) addToFlag(flag string, args []string) {
|
||||||
// Single quotes and double quotes are recognized to prevent splitting within the
|
// Single quotes and double quotes are recognized to prevent splitting within the
|
||||||
// quoted region, and are removed from the resulting substrings. If a quote in s
|
// quoted region, and are removed from the resulting substrings. If a quote in s
|
||||||
// isn't closed err will be set and r will have the unclosed argument as the
|
// isn't closed err will be set and r will have the unclosed argument as the
|
||||||
// last element. The backslash is used for escaping.
|
// last element. The backslash is used for escaping.
|
||||||
//
|
//
|
||||||
// For example, the following string:
|
// For example, the following string:
|
||||||
//
|
//
|
||||||
|
|
@ -236,7 +236,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
if isConst {
|
if isConst {
|
||||||
n.Kind = "const"
|
n.Kind = "const"
|
||||||
// Turn decimal into hex, just for consistency
|
// Turn decimal into hex, just for consistency
|
||||||
// with enum-derived constants. Otherwise
|
// with enum-derived constants. Otherwise
|
||||||
// in the cgo -godefs output half the constants
|
// in the cgo -godefs output half the constants
|
||||||
// are in hex and half are in whatever the #define used.
|
// are in hex and half are in whatever the #define used.
|
||||||
i, err := strconv.ParseInt(n.Define, 0, 64)
|
i, err := strconv.ParseInt(n.Define, 0, 64)
|
||||||
|
|
@ -385,7 +385,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
if nerrors > 0 {
|
if nerrors > 0 {
|
||||||
// Check if compiling the preamble by itself causes any errors,
|
// Check if compiling the preamble by itself causes any errors,
|
||||||
// because the messages we've printed out so far aren't helpful
|
// because the messages we've printed out so far aren't helpful
|
||||||
// to users debugging preamble mistakes. See issue 8442.
|
// to users debugging preamble mistakes. See issue 8442.
|
||||||
preambleErrors := p.gccErrors([]byte(f.Preamble))
|
preambleErrors := p.gccErrors([]byte(f.Preamble))
|
||||||
if len(preambleErrors) > 0 {
|
if len(preambleErrors) > 0 {
|
||||||
error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors)
|
error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors)
|
||||||
|
|
@ -403,7 +403,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
// being referred to as C.xxx.
|
// being referred to as C.xxx.
|
||||||
func (p *Package) loadDWARF(f *File, names []*Name) {
|
func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
// Extract the types from the DWARF section of an object
|
// Extract the types from the DWARF section of an object
|
||||||
// from a well-formed C program. Gcc only generates DWARF info
|
// from a well-formed C program. Gcc only generates DWARF info
|
||||||
// for symbols in the object file, so it is not enough to print the
|
// for symbols in the object file, so it is not enough to print the
|
||||||
// preamble and hope the symbols we care about will be there.
|
// preamble and hope the symbols we care about will be there.
|
||||||
// Instead, emit
|
// Instead, emit
|
||||||
|
|
@ -421,7 +421,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apple's LLVM-based gcc does not include the enumeration
|
// Apple's LLVM-based gcc does not include the enumeration
|
||||||
// names and values in its DWARF debug output. In case we're
|
// names and values in its DWARF debug output. In case we're
|
||||||
// using such a gcc, create a data block initialized with the values.
|
// using such a gcc, create a data block initialized with the values.
|
||||||
// We can read them out of the object file.
|
// We can read them out of the object file.
|
||||||
fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
|
fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
|
||||||
|
|
@ -432,7 +432,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
fmt.Fprintf(&b, "\t0,\n")
|
fmt.Fprintf(&b, "\t0,\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for the last entry, we can not use 0, otherwise
|
// for the last entry, we cannot use 0, otherwise
|
||||||
// in case all __cgodebug_data is zero initialized,
|
// in case all __cgodebug_data is zero initialized,
|
||||||
// LLVM-based gcc will place the it in the __DATA.__common
|
// LLVM-based gcc will place the it in the __DATA.__common
|
||||||
// zero-filled section (our debug/macho doesn't support
|
// zero-filled section (our debug/macho doesn't support
|
||||||
|
|
@ -581,7 +581,7 @@ func (p *Package) mangleName(n *Name) {
|
||||||
func (p *Package) rewriteCalls(f *File) {
|
func (p *Package) rewriteCalls(f *File) {
|
||||||
for _, call := range f.Calls {
|
for _, call := range f.Calls {
|
||||||
// This is a call to C.xxx; set goname to "xxx".
|
// This is a call to C.xxx; set goname to "xxx".
|
||||||
goname := call.Fun.(*ast.SelectorExpr).Sel.Name
|
goname := call.Call.Fun.(*ast.SelectorExpr).Sel.Name
|
||||||
if goname == "malloc" {
|
if goname == "malloc" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -594,39 +594,62 @@ func (p *Package) rewriteCalls(f *File) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewriteCall rewrites one call to add pointer checks. We replace
|
// rewriteCall rewrites one call to add pointer checks. We replace
|
||||||
// each pointer argument x with _cgoCheckPointer(x).(T).
|
// each pointer argument x with _cgoCheckPointer(x).(T).
|
||||||
func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
|
func (p *Package) rewriteCall(f *File, call *Call, name *Name) {
|
||||||
|
// Avoid a crash if the number of arguments is
|
||||||
|
// less than the number of parameters.
|
||||||
|
// This will be caught when the generated file is compiled.
|
||||||
|
if len(call.Call.Args) < len(name.FuncType.Params) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
any := false
|
||||||
for i, param := range name.FuncType.Params {
|
for i, param := range name.FuncType.Params {
|
||||||
if len(call.Args) <= i {
|
if p.needsPointerCheck(f, param.Go, call.Call.Args[i]) {
|
||||||
// Avoid a crash; this will be caught when the
|
any = true
|
||||||
// generated file is compiled.
|
break
|
||||||
return
|
}
|
||||||
|
}
|
||||||
|
if !any {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to rewrite this call.
|
||||||
|
//
|
||||||
|
// We are going to rewrite C.f(p) to C.f(_cgoCheckPointer(p)).
|
||||||
|
// If the call to C.f is deferred, that will check p at the
|
||||||
|
// point of the defer statement, not when the function is called, so
|
||||||
|
// rewrite to func(_cgo0 ptype) { C.f(_cgoCheckPointer(_cgo0)) }(p)
|
||||||
|
|
||||||
|
var dargs []ast.Expr
|
||||||
|
if call.Deferred {
|
||||||
|
dargs = make([]ast.Expr, len(name.FuncType.Params))
|
||||||
|
}
|
||||||
|
for i, param := range name.FuncType.Params {
|
||||||
|
origArg := call.Call.Args[i]
|
||||||
|
darg := origArg
|
||||||
|
|
||||||
|
if call.Deferred {
|
||||||
|
dargs[i] = darg
|
||||||
|
darg = ast.NewIdent(fmt.Sprintf("_cgo%d", i))
|
||||||
|
call.Call.Args[i] = darg
|
||||||
}
|
}
|
||||||
|
|
||||||
// An untyped nil does not need a pointer check, and
|
if !p.needsPointerCheck(f, param.Go, origArg) {
|
||||||
// when _cgoCheckPointer returns the untyped nil the
|
|
||||||
// type assertion we are going to insert will fail.
|
|
||||||
// Easier to just skip nil arguments.
|
|
||||||
// TODO: Note that this fails if nil is shadowed.
|
|
||||||
if id, ok := call.Args[i].(*ast.Ident); ok && id.Name == "nil" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !p.needsPointerCheck(f, param.Go) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &ast.CallExpr{
|
c := &ast.CallExpr{
|
||||||
Fun: ast.NewIdent("_cgoCheckPointer"),
|
Fun: ast.NewIdent("_cgoCheckPointer"),
|
||||||
Args: []ast.Expr{
|
Args: []ast.Expr{
|
||||||
call.Args[i],
|
darg,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add optional additional arguments for an address
|
// Add optional additional arguments for an address
|
||||||
// expression.
|
// expression.
|
||||||
c.Args = p.checkAddrArgs(f, c.Args, call.Args[i])
|
c.Args = p.checkAddrArgs(f, c.Args, origArg)
|
||||||
|
|
||||||
// _cgoCheckPointer returns interface{}.
|
// _cgoCheckPointer returns interface{}.
|
||||||
// We need to type assert that to the type we want.
|
// We need to type assert that to the type we want.
|
||||||
|
|
@ -636,19 +659,19 @@ func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
|
||||||
// Instead we use a local variant of _cgoCheckPointer.
|
// Instead we use a local variant of _cgoCheckPointer.
|
||||||
|
|
||||||
var arg ast.Expr
|
var arg ast.Expr
|
||||||
if n := p.unsafeCheckPointerName(param.Go); n != "" {
|
if n := p.unsafeCheckPointerName(param.Go, call.Deferred); n != "" {
|
||||||
c.Fun = ast.NewIdent(n)
|
c.Fun = ast.NewIdent(n)
|
||||||
arg = c
|
arg = c
|
||||||
} else {
|
} else {
|
||||||
// In order for the type assertion to succeed,
|
// In order for the type assertion to succeed,
|
||||||
// we need it to match the actual type of the
|
// we need it to match the actual type of the
|
||||||
// argument. The only type we have is the
|
// argument. The only type we have is the
|
||||||
// type of the function parameter. We know
|
// type of the function parameter. We know
|
||||||
// that the argument type must be assignable
|
// that the argument type must be assignable
|
||||||
// to the function parameter type, or the code
|
// to the function parameter type, or the code
|
||||||
// would not compile, but there is nothing
|
// would not compile, but there is nothing
|
||||||
// requiring that the types be exactly the
|
// requiring that the types be exactly the
|
||||||
// same. Add a type conversion to the
|
// same. Add a type conversion to the
|
||||||
// argument so that the type assertion will
|
// argument so that the type assertion will
|
||||||
// succeed.
|
// succeed.
|
||||||
c.Args[0] = &ast.CallExpr{
|
c.Args[0] = &ast.CallExpr{
|
||||||
|
|
@ -664,18 +687,77 @@ func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
call.Args[i] = arg
|
call.Call.Args[i] = arg
|
||||||
|
}
|
||||||
|
|
||||||
|
if call.Deferred {
|
||||||
|
params := make([]*ast.Field, len(name.FuncType.Params))
|
||||||
|
for i, param := range name.FuncType.Params {
|
||||||
|
ptype := param.Go
|
||||||
|
if p.hasUnsafePointer(ptype) {
|
||||||
|
// Avoid generating unsafe.Pointer by using
|
||||||
|
// interface{}. This works because we are
|
||||||
|
// going to call a _cgoCheckPointer function
|
||||||
|
// anyhow.
|
||||||
|
ptype = &ast.InterfaceType{
|
||||||
|
Methods: &ast.FieldList{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params[i] = &ast.Field{
|
||||||
|
Names: []*ast.Ident{
|
||||||
|
ast.NewIdent(fmt.Sprintf("_cgo%d", i)),
|
||||||
|
},
|
||||||
|
Type: ptype,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbody := &ast.CallExpr{
|
||||||
|
Fun: call.Call.Fun,
|
||||||
|
Args: call.Call.Args,
|
||||||
|
}
|
||||||
|
call.Call.Fun = &ast.FuncLit{
|
||||||
|
Type: &ast.FuncType{
|
||||||
|
Params: &ast.FieldList{
|
||||||
|
List: params,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Body: &ast.BlockStmt{
|
||||||
|
List: []ast.Stmt{
|
||||||
|
&ast.ExprStmt{
|
||||||
|
X: dbody,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
call.Call.Args = dargs
|
||||||
|
call.Call.Lparen = token.NoPos
|
||||||
|
call.Call.Rparen = token.NoPos
|
||||||
|
|
||||||
|
// There is a Ref pointing to the old call.Call.Fun.
|
||||||
|
for _, ref := range f.Ref {
|
||||||
|
if ref.Expr == &call.Call.Fun {
|
||||||
|
ref.Expr = &dbody.Fun
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// needsPointerCheck returns whether the type t needs a pointer check.
|
// needsPointerCheck returns whether the type t needs a pointer check.
|
||||||
// This is true if t is a pointer and if the value to which it points
|
// This is true if t is a pointer and if the value to which it points
|
||||||
// might contain a pointer.
|
// might contain a pointer.
|
||||||
func (p *Package) needsPointerCheck(f *File, t ast.Expr) bool {
|
func (p *Package) needsPointerCheck(f *File, t ast.Expr, arg ast.Expr) bool {
|
||||||
|
// An untyped nil does not need a pointer check, and when
|
||||||
|
// _cgoCheckPointer returns the untyped nil the type assertion we
|
||||||
|
// are going to insert will fail. Easier to just skip nil arguments.
|
||||||
|
// TODO: Note that this fails if nil is shadowed.
|
||||||
|
if id, ok := arg.(*ast.Ident); ok && id.Name == "nil" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return p.hasPointer(f, t, true)
|
return p.hasPointer(f, t, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasPointer is used by needsPointerCheck. If top is true it returns
|
// hasPointer is used by needsPointerCheck. If top is true it returns
|
||||||
// whether t is or contains a pointer that might point to a pointer.
|
// whether t is or contains a pointer that might point to a pointer.
|
||||||
// If top is false it returns whether t is or contains a pointer.
|
// If top is false it returns whether t is or contains a pointer.
|
||||||
// f may be nil.
|
// f may be nil.
|
||||||
|
|
@ -732,7 +814,7 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
|
||||||
if goTypes[t.Name] != nil {
|
if goTypes[t.Name] != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// We can't figure out the type. Conservative
|
// We can't figure out the type. Conservative
|
||||||
// approach is to assume it has a pointer.
|
// approach is to assume it has a pointer.
|
||||||
return true
|
return true
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
|
|
@ -750,7 +832,7 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
|
||||||
if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
|
if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
|
||||||
return p.hasPointer(f, name.Type.Go, top)
|
return p.hasPointer(f, name.Type.Go, top)
|
||||||
}
|
}
|
||||||
// We can't figure out the type. Conservative
|
// We can't figure out the type. Conservative
|
||||||
// approach is to assume it has a pointer.
|
// approach is to assume it has a pointer.
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
|
|
@ -760,14 +842,14 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkAddrArgs tries to add arguments to the call of
|
// checkAddrArgs tries to add arguments to the call of
|
||||||
// _cgoCheckPointer when the argument is an address expression. We
|
// _cgoCheckPointer when the argument is an address expression. We
|
||||||
// pass true to mean that the argument is an address operation of
|
// pass true to mean that the argument is an address operation of
|
||||||
// something other than a slice index, which means that it's only
|
// something other than a slice index, which means that it's only
|
||||||
// necessary to check the specific element pointed to, not the entire
|
// necessary to check the specific element pointed to, not the entire
|
||||||
// object. This is for &s.f, where f is a field in a struct. We can
|
// object. This is for &s.f, where f is a field in a struct. We can
|
||||||
// pass a slice or array, meaning that we should check the entire
|
// pass a slice or array, meaning that we should check the entire
|
||||||
// slice or array but need not check any other part of the object.
|
// slice or array but need not check any other part of the object.
|
||||||
// This is for &s.a[i], where we need to check all of a. However, we
|
// This is for &s.a[i], where we need to check all of a. However, we
|
||||||
// only pass the slice or array if we can refer to it without side
|
// only pass the slice or array if we can refer to it without side
|
||||||
// effects.
|
// effects.
|
||||||
func (p *Package) checkAddrArgs(f *File, args []ast.Expr, x ast.Expr) []ast.Expr {
|
func (p *Package) checkAddrArgs(f *File, args []ast.Expr, x ast.Expr) []ast.Expr {
|
||||||
|
|
@ -786,7 +868,7 @@ func (p *Package) checkAddrArgs(f *File, args []ast.Expr, x ast.Expr) []ast.Expr
|
||||||
index, ok := u.X.(*ast.IndexExpr)
|
index, ok := u.X.(*ast.IndexExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
// This is the address of something that is not an
|
// This is the address of something that is not an
|
||||||
// index expression. We only need to examine the
|
// index expression. We only need to examine the
|
||||||
// single value to which it points.
|
// single value to which it points.
|
||||||
// TODO: what if true is shadowed?
|
// TODO: what if true is shadowed?
|
||||||
return append(args, ast.NewIdent("true"))
|
return append(args, ast.NewIdent("true"))
|
||||||
|
|
@ -819,14 +901,17 @@ func (p *Package) hasSideEffects(f *File, x ast.Expr) bool {
|
||||||
func (p *Package) isType(t ast.Expr) bool {
|
func (p *Package) isType(t ast.Expr) bool {
|
||||||
switch t := t.(type) {
|
switch t := t.(type) {
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
if t.Sel.Name != "Pointer" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
id, ok := t.X.(*ast.Ident)
|
id, ok := t.X.(*ast.Ident)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return id.Name == "unsafe"
|
if id.Name == "unsafe" && t.Sel.Name == "Pointer" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if id.Name == "C" && typedef["_Ctype_"+t.Sel.Name] != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
// TODO: This ignores shadowing.
|
// TODO: This ignores shadowing.
|
||||||
switch t.Name {
|
switch t.Name {
|
||||||
|
|
@ -850,26 +935,37 @@ func (p *Package) isType(t ast.Expr) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsafeCheckPointerName is given the Go version of a C type. If the
|
// unsafeCheckPointerName is given the Go version of a C type. If the
|
||||||
// type uses unsafe.Pointer, we arrange to build a version of
|
// type uses unsafe.Pointer, we arrange to build a version of
|
||||||
// _cgoCheckPointer that returns that type. This avoids using a type
|
// _cgoCheckPointer that returns that type. This avoids using a type
|
||||||
// assertion to unsafe.Pointer in our copy of user code. We return
|
// assertion to unsafe.Pointer in our copy of user code. We return
|
||||||
// the name of the _cgoCheckPointer function we are going to build, or
|
// the name of the _cgoCheckPointer function we are going to build, or
|
||||||
// the empty string if the type does not use unsafe.Pointer.
|
// the empty string if the type does not use unsafe.Pointer.
|
||||||
func (p *Package) unsafeCheckPointerName(t ast.Expr) string {
|
//
|
||||||
|
// The deferred parameter is true if this check is for the argument of
|
||||||
|
// a deferred function. In that case we need to use an empty interface
|
||||||
|
// as the argument type, because the deferred function we introduce in
|
||||||
|
// rewriteCall will use an empty interface type, and we can't add a
|
||||||
|
// type assertion. This is handled by keeping a separate list, and
|
||||||
|
// writing out the lists separately in writeDefs.
|
||||||
|
func (p *Package) unsafeCheckPointerName(t ast.Expr, deferred bool) string {
|
||||||
if !p.hasUnsafePointer(t) {
|
if !p.hasUnsafePointer(t) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
conf.Fprint(&buf, fset, t)
|
conf.Fprint(&buf, fset, t)
|
||||||
s := buf.String()
|
s := buf.String()
|
||||||
for i, t := range p.CgoChecks {
|
checks := &p.CgoChecks
|
||||||
|
if deferred {
|
||||||
|
checks = &p.DeferredCgoChecks
|
||||||
|
}
|
||||||
|
for i, t := range *checks {
|
||||||
if s == t {
|
if s == t {
|
||||||
return p.unsafeCheckPointerNameIndex(i)
|
return p.unsafeCheckPointerNameIndex(i, deferred)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.CgoChecks = append(p.CgoChecks, s)
|
*checks = append(*checks, s)
|
||||||
return p.unsafeCheckPointerNameIndex(len(p.CgoChecks) - 1)
|
return p.unsafeCheckPointerNameIndex(len(*checks)-1, deferred)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasUnsafePointer returns whether the Go type t uses unsafe.Pointer.
|
// hasUnsafePointer returns whether the Go type t uses unsafe.Pointer.
|
||||||
|
|
@ -897,13 +993,16 @@ func (p *Package) hasUnsafePointer(t ast.Expr) bool {
|
||||||
|
|
||||||
// unsafeCheckPointerNameIndex returns the name to use for a
|
// unsafeCheckPointerNameIndex returns the name to use for a
|
||||||
// _cgoCheckPointer variant based on the index in the CgoChecks slice.
|
// _cgoCheckPointer variant based on the index in the CgoChecks slice.
|
||||||
func (p *Package) unsafeCheckPointerNameIndex(i int) string {
|
func (p *Package) unsafeCheckPointerNameIndex(i int, deferred bool) string {
|
||||||
|
if deferred {
|
||||||
|
return fmt.Sprintf("_cgoCheckPointerInDefer%d", i)
|
||||||
|
}
|
||||||
return fmt.Sprintf("_cgoCheckPointer%d", i)
|
return fmt.Sprintf("_cgoCheckPointer%d", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
|
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
|
||||||
// Go equivalents, now that we have figured out the meaning of all
|
// Go equivalents, now that we have figured out the meaning of all
|
||||||
// the xxx. In *godefs mode, rewriteRef replaces the names
|
// the xxx. In *godefs mode, rewriteRef replaces the names
|
||||||
// with full definitions instead of mangled names.
|
// with full definitions instead of mangled names.
|
||||||
func (p *Package) rewriteRef(f *File) {
|
func (p *Package) rewriteRef(f *File) {
|
||||||
// Keep a list of all the functions, to remove the ones
|
// Keep a list of all the functions, to remove the ones
|
||||||
|
|
@ -926,7 +1025,7 @@ func (p *Package) rewriteRef(f *File) {
|
||||||
|
|
||||||
// Now that we have all the name types filled in,
|
// Now that we have all the name types filled in,
|
||||||
// scan through the Refs to identify the ones that
|
// scan through the Refs to identify the ones that
|
||||||
// are trying to do a ,err call. Also check that
|
// are trying to do a ,err call. Also check that
|
||||||
// functions are only used in calls.
|
// functions are only used in calls.
|
||||||
for _, r := range f.Ref {
|
for _, r := range f.Ref {
|
||||||
if r.Name.Kind == "const" && r.Name.Const == "" {
|
if r.Name.Kind == "const" && r.Name.Const == "" {
|
||||||
|
|
@ -984,7 +1083,7 @@ func (p *Package) rewriteRef(f *File) {
|
||||||
f.Name[fpName] = name
|
f.Name[fpName] = name
|
||||||
}
|
}
|
||||||
r.Name = name
|
r.Name = name
|
||||||
// Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
|
// Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
|
||||||
// function is defined in out.go and simply returns its argument. See
|
// function is defined in out.go and simply returns its argument. See
|
||||||
// issue 7757.
|
// issue 7757.
|
||||||
expr = &ast.CallExpr{
|
expr = &ast.CallExpr{
|
||||||
|
|
@ -1006,7 +1105,7 @@ func (p *Package) rewriteRef(f *File) {
|
||||||
if r.Name.Kind == "var" {
|
if r.Name.Kind == "var" {
|
||||||
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
|
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
|
||||||
} else {
|
} else {
|
||||||
error_(r.Pos(), "only C variables allowed in selector expression", fixGo(r.Name.Go))
|
error_(r.Pos(), "only C variables allowed in selector expression %s", fixGo(r.Name.Go))
|
||||||
}
|
}
|
||||||
|
|
||||||
case "type":
|
case "type":
|
||||||
|
|
@ -1086,6 +1185,8 @@ func (p *Package) gccMachine() []string {
|
||||||
return []string{"-m31"}
|
return []string{"-m31"}
|
||||||
case "s390x":
|
case "s390x":
|
||||||
return []string{"-m64"}
|
return []string{"-m64"}
|
||||||
|
case "mips64", "mips64le":
|
||||||
|
return []string{"-mabi=64"}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1152,7 +1253,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
|
||||||
for i := range f.Symtab.Syms {
|
for i := range f.Symtab.Syms {
|
||||||
s := &f.Symtab.Syms[i]
|
s := &f.Symtab.Syms[i]
|
||||||
if isDebugData(s.Name) {
|
if isDebugData(s.Name) {
|
||||||
// Found it. Now find data section.
|
// Found it. Now find data section.
|
||||||
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
|
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
|
||||||
sect := f.Sections[i]
|
sect := f.Sections[i]
|
||||||
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
||||||
|
|
@ -1179,7 +1280,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
|
||||||
for i := range symtab {
|
for i := range symtab {
|
||||||
s := &symtab[i]
|
s := &symtab[i]
|
||||||
if isDebugData(s.Name) {
|
if isDebugData(s.Name) {
|
||||||
// Found it. Now find data section.
|
// Found it. Now find data section.
|
||||||
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
|
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
|
||||||
sect := f.Sections[i]
|
sect := f.Sections[i]
|
||||||
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
||||||
|
|
@ -1232,18 +1333,26 @@ func (p *Package) gccDefines(stdin []byte) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// gccErrors runs gcc over the C program stdin and returns
|
// gccErrors runs gcc over the C program stdin and returns
|
||||||
// the errors that gcc prints. That is, this function expects
|
// the errors that gcc prints. That is, this function expects
|
||||||
// gcc to fail.
|
// gcc to fail.
|
||||||
func (p *Package) gccErrors(stdin []byte) string {
|
func (p *Package) gccErrors(stdin []byte) string {
|
||||||
// TODO(rsc): require failure
|
// TODO(rsc): require failure
|
||||||
args := p.gccCmd()
|
args := p.gccCmd()
|
||||||
|
|
||||||
|
// Optimization options can confuse the error messages; remove them.
|
||||||
|
nargs := make([]string, 0, len(args))
|
||||||
|
for _, arg := range args {
|
||||||
|
if !strings.HasPrefix(arg, "-O") {
|
||||||
|
nargs = append(nargs, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if *debugGcc {
|
if *debugGcc {
|
||||||
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
|
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
|
||||||
os.Stderr.Write(stdin)
|
os.Stderr.Write(stdin)
|
||||||
fmt.Fprint(os.Stderr, "EOF\n")
|
fmt.Fprint(os.Stderr, "EOF\n")
|
||||||
}
|
}
|
||||||
stdout, stderr, _ := run(stdin, args)
|
stdout, stderr, _ := run(stdin, nargs)
|
||||||
if *debugGcc {
|
if *debugGcc {
|
||||||
os.Stderr.Write(stdout)
|
os.Stderr.Write(stdout)
|
||||||
os.Stderr.Write(stderr)
|
os.Stderr.Write(stderr)
|
||||||
|
|
@ -1279,8 +1388,7 @@ func runGcc(stdin []byte, args []string) (string, string) {
|
||||||
// with equivalent memory layout.
|
// with equivalent memory layout.
|
||||||
type typeConv struct {
|
type typeConv struct {
|
||||||
// Cache of already-translated or in-progress types.
|
// Cache of already-translated or in-progress types.
|
||||||
m map[dwarf.Type]*Type
|
m map[dwarf.Type]*Type
|
||||||
typedef map[string]ast.Expr
|
|
||||||
|
|
||||||
// Map from types to incomplete pointers to those types.
|
// Map from types to incomplete pointers to those types.
|
||||||
ptrs map[dwarf.Type][]*Type
|
ptrs map[dwarf.Type][]*Type
|
||||||
|
|
@ -1372,7 +1480,7 @@ var dwarfToName = map[string]string{
|
||||||
|
|
||||||
const signedDelta = 64
|
const signedDelta = 64
|
||||||
|
|
||||||
// String returns the current type representation. Format arguments
|
// String returns the current type representation. Format arguments
|
||||||
// are assembled within this method so that any changes in mutable
|
// are assembled within this method so that any changes in mutable
|
||||||
// values are taken into account.
|
// values are taken into account.
|
||||||
func (tr *TypeRepr) String() string {
|
func (tr *TypeRepr) String() string {
|
||||||
|
|
@ -1812,7 +1920,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
|
||||||
}
|
}
|
||||||
case *dwarf.TypedefType:
|
case *dwarf.TypedefType:
|
||||||
// C has much more relaxed rules than Go for
|
// C has much more relaxed rules than Go for
|
||||||
// implicit type conversions. When the parameter
|
// implicit type conversions. When the parameter
|
||||||
// is type T defined as *X, simulate a little of the
|
// is type T defined as *X, simulate a little of the
|
||||||
// laxness of C by making the argument *X instead of T.
|
// laxness of C by making the argument *X instead of T.
|
||||||
if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
|
if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
|
||||||
|
|
@ -1828,7 +1936,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember the C spelling, in case the struct
|
// Remember the C spelling, in case the struct
|
||||||
// has __attribute__((unavailable)) on it. See issue 2888.
|
// has __attribute__((unavailable)) on it. See issue 2888.
|
||||||
t.Typedef = dt.Name
|
t.Typedef = dt.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1843,7 +1951,7 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
|
||||||
for i, f := range dtype.ParamType {
|
for i, f := range dtype.ParamType {
|
||||||
// gcc's DWARF generator outputs a single DotDotDotType parameter for
|
// gcc's DWARF generator outputs a single DotDotDotType parameter for
|
||||||
// function pointers that specify no parameters (e.g. void
|
// function pointers that specify no parameters (e.g. void
|
||||||
// (*__cgo_0)()). Treat this special case as void. This case is
|
// (*__cgo_0)()). Treat this special case as void. This case is
|
||||||
// invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
|
// invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
|
||||||
// legal).
|
// legal).
|
||||||
if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
|
if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
|
||||||
|
|
@ -1914,8 +2022,8 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||||
off := int64(0)
|
off := int64(0)
|
||||||
|
|
||||||
// Rename struct fields that happen to be named Go keywords into
|
// Rename struct fields that happen to be named Go keywords into
|
||||||
// _{keyword}. Create a map from C ident -> Go ident. The Go ident will
|
// _{keyword}. Create a map from C ident -> Go ident. The Go ident will
|
||||||
// be mangled. Any existing identifier that already has the same name on
|
// be mangled. Any existing identifier that already has the same name on
|
||||||
// the C-side will cause the Go-mangled version to be prefixed with _.
|
// the C-side will cause the Go-mangled version to be prefixed with _.
|
||||||
// (e.g. in a struct with fields '_type' and 'type', the latter would be
|
// (e.g. in a struct with fields '_type' and 'type', the latter would be
|
||||||
// rendered as '__type' in Go).
|
// rendered as '__type' in Go).
|
||||||
|
|
@ -1955,7 +2063,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||||
|
|
||||||
// In godefs mode, if this field is a C11
|
// In godefs mode, if this field is a C11
|
||||||
// anonymous union then treat the first field in the
|
// anonymous union then treat the first field in the
|
||||||
// union as the field in the struct. This handles
|
// union as the field in the struct. This handles
|
||||||
// cases like the glibc <sys/resource.h> file; see
|
// cases like the glibc <sys/resource.h> file; see
|
||||||
// issue 6677.
|
// issue 6677.
|
||||||
if *godefs {
|
if *godefs {
|
||||||
|
|
@ -2025,7 +2133,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||||
// We can't permit that, because then the size of the Go
|
// We can't permit that, because then the size of the Go
|
||||||
// struct will not be the same as the size of the C struct.
|
// struct will not be the same as the size of the C struct.
|
||||||
// Our only option in such a case is to remove the field,
|
// Our only option in such a case is to remove the field,
|
||||||
// which means that it can not be referenced from Go.
|
// which means that it cannot be referenced from Go.
|
||||||
for off > 0 && sizes[len(sizes)-1] == 0 {
|
for off > 0 && sizes[len(sizes)-1] == 0 {
|
||||||
n := len(sizes)
|
n := len(sizes)
|
||||||
fld = fld[0 : n-1]
|
fld = fld[0 : n-1]
|
||||||
|
|
@ -2079,7 +2187,7 @@ func godefsFields(fld []*ast.Field) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fieldPrefix returns the prefix that should be removed from all the
|
// fieldPrefix returns the prefix that should be removed from all the
|
||||||
// field names when generating the C or Go code. For generated
|
// field names when generating the C or Go code. For generated
|
||||||
// C, we leave the names as is (tv_sec, tv_usec), since that's what
|
// C, we leave the names as is (tv_sec, tv_usec), since that's what
|
||||||
// people are used to seeing in C. For generated Go code, such as
|
// people are used to seeing in C. For generated Go code, such as
|
||||||
// package syscall's data structures, we drop a common prefix
|
// package syscall's data structures, we drop a common prefix
|
||||||
|
|
@ -2089,7 +2197,7 @@ func fieldPrefix(fld []*ast.Field) string {
|
||||||
for _, f := range fld {
|
for _, f := range fld {
|
||||||
for _, n := range f.Names {
|
for _, n := range f.Names {
|
||||||
// Ignore field names that don't have the prefix we're
|
// Ignore field names that don't have the prefix we're
|
||||||
// looking for. It is common in C headers to have fields
|
// looking for. It is common in C headers to have fields
|
||||||
// named, say, _pad in an otherwise prefixed header.
|
// named, say, _pad in an otherwise prefixed header.
|
||||||
// If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
|
// If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
|
||||||
// still want to remove the tv_ prefix.
|
// still want to remove the tv_ prefix.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -42,7 +42,10 @@ type Package struct {
|
||||||
GoFiles []string // list of Go files
|
GoFiles []string // list of Go files
|
||||||
GccFiles []string // list of gcc output files
|
GccFiles []string // list of gcc output files
|
||||||
Preamble string // collected preamble for _cgo_export.h
|
Preamble string // collected preamble for _cgo_export.h
|
||||||
CgoChecks []string // see unsafeCheckPointerName
|
|
||||||
|
// See unsafeCheckPointerName.
|
||||||
|
CgoChecks []string
|
||||||
|
DeferredCgoChecks []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// A File collects information about a single Go input file.
|
// A File collects information about a single Go input file.
|
||||||
|
|
@ -52,7 +55,7 @@ type File struct {
|
||||||
Package string // Package name
|
Package string // Package name
|
||||||
Preamble string // C preamble (doc comment on import "C")
|
Preamble string // C preamble (doc comment on import "C")
|
||||||
Ref []*Ref // all references to C.xxx in AST
|
Ref []*Ref // all references to C.xxx in AST
|
||||||
Calls []*ast.CallExpr // all calls to C.xxx in AST
|
Calls []*Call // all calls to C.xxx in AST
|
||||||
ExpFunc []*ExpFunc // exported functions for this file
|
ExpFunc []*ExpFunc // exported functions for this file
|
||||||
Name map[string]*Name // map from Go name to Name
|
Name map[string]*Name // map from Go name to Name
|
||||||
}
|
}
|
||||||
|
|
@ -66,6 +69,12 @@ func nameKeys(m map[string]*Name) []string {
|
||||||
return ks
|
return ks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Call refers to a call of a C.xxx function in the AST.
|
||||||
|
type Call struct {
|
||||||
|
Call *ast.CallExpr
|
||||||
|
Deferred bool
|
||||||
|
}
|
||||||
|
|
||||||
// A Ref refers to an expression of the form C.xxx in the AST.
|
// A Ref refers to an expression of the form C.xxx in the AST.
|
||||||
type Ref struct {
|
type Ref struct {
|
||||||
Name *Name
|
Name *Name
|
||||||
|
|
@ -208,9 +217,9 @@ func main() {
|
||||||
|
|
||||||
if *dynobj != "" {
|
if *dynobj != "" {
|
||||||
// cgo -dynimport is essentially a separate helper command
|
// cgo -dynimport is essentially a separate helper command
|
||||||
// built into the cgo binary. It scans a gcc-produced executable
|
// built into the cgo binary. It scans a gcc-produced executable
|
||||||
// and dumps information about the imported symbols and the
|
// and dumps information about the imported symbols and the
|
||||||
// imported libraries. The 'go build' rules for cgo prepare an
|
// imported libraries. The 'go build' rules for cgo prepare an
|
||||||
// appropriate executable and then use its import information
|
// appropriate executable and then use its import information
|
||||||
// instead of needing to make the linkers duplicate all the
|
// instead of needing to make the linkers duplicate all the
|
||||||
// specialized knowledge gcc has about where to look for imported
|
// specialized knowledge gcc has about where to look for imported
|
||||||
|
|
@ -245,6 +254,12 @@ func main() {
|
||||||
|
|
||||||
goFiles := args[i:]
|
goFiles := args[i:]
|
||||||
|
|
||||||
|
for _, arg := range args[:i] {
|
||||||
|
if arg == "-fsanitize=thread" {
|
||||||
|
tsanProlog = yesTsanProlog
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p := newPackage(args[:i])
|
p := newPackage(args[:i])
|
||||||
|
|
||||||
// Record CGO_LDFLAGS from the environment for external linking.
|
// Record CGO_LDFLAGS from the environment for external linking.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -50,14 +50,16 @@ func (p *Package) writeDefs() {
|
||||||
// Write C main file for using gcc to resolve imports.
|
// Write C main file for using gcc to resolve imports.
|
||||||
fmt.Fprintf(fm, "int main() { return 0; }\n")
|
fmt.Fprintf(fm, "int main() { return 0; }\n")
|
||||||
if *importRuntimeCgo {
|
if *importRuntimeCgo {
|
||||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
|
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { }\n")
|
||||||
fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done() { }\n")
|
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; }\n")
|
||||||
|
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt) { }\n")
|
||||||
fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
|
fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
|
||||||
} else {
|
} else {
|
||||||
// If we're not importing runtime/cgo, we *are* runtime/cgo,
|
// If we're not importing runtime/cgo, we *are* runtime/cgo,
|
||||||
// which provides these functions. We just need a prototype.
|
// which provides these functions. We just need a prototype.
|
||||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
|
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt);\n")
|
||||||
fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done();\n")
|
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done();\n")
|
||||||
|
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
|
fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
|
||||||
fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
|
fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
|
||||||
|
|
@ -110,7 +112,13 @@ func (p *Package) writeDefs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, t := range p.CgoChecks {
|
for i, t := range p.CgoChecks {
|
||||||
n := p.unsafeCheckPointerNameIndex(i)
|
n := p.unsafeCheckPointerNameIndex(i, false)
|
||||||
|
fmt.Fprintf(fgo2, "\nfunc %s(p %s, args ...interface{}) %s {\n", n, t, t)
|
||||||
|
fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
|
||||||
|
fmt.Fprintf(fgo2, "}\n")
|
||||||
|
}
|
||||||
|
for i, t := range p.DeferredCgoChecks {
|
||||||
|
n := p.unsafeCheckPointerNameIndex(i, true)
|
||||||
fmt.Fprintf(fgo2, "\nfunc %s(p interface{}, args ...interface{}) %s {\n", n, t)
|
fmt.Fprintf(fgo2, "\nfunc %s(p interface{}, args ...interface{}) %s {\n", n, t)
|
||||||
fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
|
fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
|
||||||
fmt.Fprintf(fgo2, "}\n")
|
fmt.Fprintf(fgo2, "}\n")
|
||||||
|
|
@ -173,10 +181,11 @@ func (p *Package) writeDefs() {
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgo2, "\n")
|
fmt.Fprintf(fgo2, "\n")
|
||||||
|
|
||||||
|
callsMalloc := false
|
||||||
for _, key := range nameKeys(p.Name) {
|
for _, key := range nameKeys(p.Name) {
|
||||||
n := p.Name[key]
|
n := p.Name[key]
|
||||||
if n.FuncType != nil {
|
if n.FuncType != nil {
|
||||||
p.writeDefsFunc(fgo2, n)
|
p.writeDefsFunc(fgo2, n, &callsMalloc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,6 +196,12 @@ func (p *Package) writeDefs() {
|
||||||
} else {
|
} else {
|
||||||
p.writeExports(fgo2, fm, fgcc, fgcch)
|
p.writeExports(fgo2, fm, fgcc, fgcch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if callsMalloc && !*gccgo {
|
||||||
|
fmt.Fprint(fgo2, strings.Replace(cMallocDefGo, "PREFIX", cPrefix, -1))
|
||||||
|
fmt.Fprint(fgcc, strings.Replace(strings.Replace(cMallocDefC, "PREFIX", cPrefix, -1), "PACKED", p.packedAttribute(), -1))
|
||||||
|
}
|
||||||
|
|
||||||
if err := fgcc.Close(); err != nil {
|
if err := fgcc.Close(); err != nil {
|
||||||
fatalf("%s", err)
|
fatalf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -350,7 +365,7 @@ func (p *Package) structType(n *Name) (string, int64) {
|
||||||
return buf.String(), off
|
return buf.String(), off
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
|
func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name, callsMalloc *bool) {
|
||||||
name := n.Go
|
name := n.Go
|
||||||
gtype := n.FuncType.Go
|
gtype := n.FuncType.Go
|
||||||
void := gtype.Results == nil || len(gtype.Results.List) == 0
|
void := gtype.Results == nil || len(gtype.Results.List) == 0
|
||||||
|
|
@ -439,6 +454,9 @@ func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
|
||||||
|
|
||||||
if inProlog {
|
if inProlog {
|
||||||
fmt.Fprint(fgo2, builtinDefs[name])
|
fmt.Fprint(fgo2, builtinDefs[name])
|
||||||
|
if strings.Contains(builtinDefs[name], "_cgo_cmalloc") {
|
||||||
|
*callsMalloc = true
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -458,6 +476,7 @@ func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(fgo2, "\n")
|
fmt.Fprint(fgo2, "\n")
|
||||||
|
fmt.Fprint(fgo2, "//go:cgo_unsafe_args\n")
|
||||||
conf.Fprint(fgo2, fset, d)
|
conf.Fprint(fgo2, fset, d)
|
||||||
fmt.Fprint(fgo2, " {\n")
|
fmt.Fprint(fgo2, " {\n")
|
||||||
|
|
||||||
|
|
@ -507,6 +526,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
|
||||||
// Gcc output starts with the preamble.
|
// Gcc output starts with the preamble.
|
||||||
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
||||||
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
||||||
|
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||||
|
|
||||||
for _, key := range nameKeys(f.Name) {
|
for _, key := range nameKeys(f.Name) {
|
||||||
n := f.Name[key]
|
n := f.Name[key]
|
||||||
|
|
@ -531,6 +551,7 @@ func fixGo(name string) string {
|
||||||
|
|
||||||
var isBuiltin = map[string]bool{
|
var isBuiltin = map[string]bool{
|
||||||
"_Cfunc_CString": true,
|
"_Cfunc_CString": true,
|
||||||
|
"_Cfunc_CBytes": true,
|
||||||
"_Cfunc_GoString": true,
|
"_Cfunc_GoString": true,
|
||||||
"_Cfunc_GoStringN": true,
|
"_Cfunc_GoStringN": true,
|
||||||
"_Cfunc_GoBytes": true,
|
"_Cfunc_GoBytes": true,
|
||||||
|
|
@ -555,6 +576,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||||
|
|
||||||
// Gcc wrapper unpacks the C argument struct
|
// Gcc wrapper unpacks the C argument struct
|
||||||
// and calls the actual C function.
|
// and calls the actual C function.
|
||||||
|
fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
|
||||||
if n.AddError {
|
if n.AddError {
|
||||||
fmt.Fprintf(fgcc, "int\n")
|
fmt.Fprintf(fgcc, "int\n")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -563,7 +585,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||||
fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
|
fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
|
||||||
fmt.Fprintf(fgcc, "{\n")
|
fmt.Fprintf(fgcc, "{\n")
|
||||||
if n.AddError {
|
if n.AddError {
|
||||||
fmt.Fprintf(fgcc, "\terrno = 0;\n")
|
fmt.Fprintf(fgcc, "\tint _cgo_errno;\n")
|
||||||
}
|
}
|
||||||
// We're trying to write a gcc struct that matches gc's layout.
|
// We're trying to write a gcc struct that matches gc's layout.
|
||||||
// Use packed attribute to force no padding in this struct in case
|
// Use packed attribute to force no padding in this struct in case
|
||||||
|
|
@ -573,10 +595,18 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||||
// Save the stack top for use below.
|
// Save the stack top for use below.
|
||||||
fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n")
|
fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n")
|
||||||
}
|
}
|
||||||
|
tr := n.FuncType.Result
|
||||||
|
if tr != nil {
|
||||||
|
fmt.Fprintf(fgcc, "\t__typeof__(a->r) r;\n")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
|
||||||
|
if n.AddError {
|
||||||
|
fmt.Fprintf(fgcc, "\terrno = 0;\n")
|
||||||
|
}
|
||||||
fmt.Fprintf(fgcc, "\t")
|
fmt.Fprintf(fgcc, "\t")
|
||||||
if t := n.FuncType.Result; t != nil {
|
if tr != nil {
|
||||||
fmt.Fprintf(fgcc, "__typeof__(a->r) r = ")
|
fmt.Fprintf(fgcc, "r = ")
|
||||||
if c := t.C.String(); c[len(c)-1] == '*' {
|
if c := tr.C.String(); c[len(c)-1] == '*' {
|
||||||
fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
|
fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -589,7 +619,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||||
// the Go equivalents had good type params.
|
// the Go equivalents had good type params.
|
||||||
// However, our version of the type omits the magic
|
// However, our version of the type omits the magic
|
||||||
// words const and volatile, which can provoke
|
// words const and volatile, which can provoke
|
||||||
// C compiler warnings. Silence them by casting
|
// C compiler warnings. Silence them by casting
|
||||||
// all pointers to void*. (Eventually that will produce
|
// all pointers to void*. (Eventually that will produce
|
||||||
// other warnings.)
|
// other warnings.)
|
||||||
if c := t.C.String(); c[len(c)-1] == '*' {
|
if c := t.C.String(); c[len(c)-1] == '*' {
|
||||||
|
|
@ -598,6 +628,10 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||||
fmt.Fprintf(fgcc, "a->p%d", i)
|
fmt.Fprintf(fgcc, "a->p%d", i)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcc, ");\n")
|
fmt.Fprintf(fgcc, ");\n")
|
||||||
|
if n.AddError {
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_errno = errno;\n")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
|
||||||
if n.FuncType.Result != nil {
|
if n.FuncType.Result != nil {
|
||||||
// The cgo call may have caused a stack copy (via a callback).
|
// The cgo call may have caused a stack copy (via a callback).
|
||||||
// Adjust the return value pointer appropriately.
|
// Adjust the return value pointer appropriately.
|
||||||
|
|
@ -606,18 +640,19 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||||
fmt.Fprintf(fgcc, "\ta->r = r;\n")
|
fmt.Fprintf(fgcc, "\ta->r = r;\n")
|
||||||
}
|
}
|
||||||
if n.AddError {
|
if n.AddError {
|
||||||
fmt.Fprintf(fgcc, "\treturn errno;\n")
|
fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcc, "}\n")
|
fmt.Fprintf(fgcc, "}\n")
|
||||||
fmt.Fprintf(fgcc, "\n")
|
fmt.Fprintf(fgcc, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out a wrapper for a function when using gccgo. This is a
|
// Write out a wrapper for a function when using gccgo. This is a
|
||||||
// simple wrapper that just calls the real function. We only need a
|
// simple wrapper that just calls the real function. We only need a
|
||||||
// wrapper to support static functions in the prologue--without a
|
// wrapper to support static functions in the prologue--without a
|
||||||
// wrapper, we can't refer to the function, since the reference is in
|
// wrapper, we can't refer to the function, since the reference is in
|
||||||
// a different file.
|
// a different file.
|
||||||
func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
||||||
|
fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
|
||||||
if t := n.FuncType.Result; t != nil {
|
if t := n.FuncType.Result; t != nil {
|
||||||
fmt.Fprintf(fgcc, "%s\n", t.C.String())
|
fmt.Fprintf(fgcc, "%s\n", t.C.String())
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -636,9 +671,13 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcc, ")\n")
|
fmt.Fprintf(fgcc, ")\n")
|
||||||
fmt.Fprintf(fgcc, "{\n")
|
fmt.Fprintf(fgcc, "{\n")
|
||||||
|
if t := n.FuncType.Result; t != nil {
|
||||||
|
fmt.Fprintf(fgcc, "\t%s r;\n", t.C.String())
|
||||||
|
}
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
|
||||||
fmt.Fprintf(fgcc, "\t")
|
fmt.Fprintf(fgcc, "\t")
|
||||||
if t := n.FuncType.Result; t != nil {
|
if t := n.FuncType.Result; t != nil {
|
||||||
fmt.Fprintf(fgcc, "return ")
|
fmt.Fprintf(fgcc, "r = ")
|
||||||
// Cast to void* to avoid warnings due to omitted qualifiers.
|
// Cast to void* to avoid warnings due to omitted qualifiers.
|
||||||
if c := t.C.String(); c[len(c)-1] == '*' {
|
if c := t.C.String(); c[len(c)-1] == '*' {
|
||||||
fmt.Fprintf(fgcc, "(void*)")
|
fmt.Fprintf(fgcc, "(void*)")
|
||||||
|
|
@ -656,6 +695,16 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
||||||
fmt.Fprintf(fgcc, "p%d", i)
|
fmt.Fprintf(fgcc, "p%d", i)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcc, ");\n")
|
fmt.Fprintf(fgcc, ");\n")
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
|
||||||
|
if t := n.FuncType.Result; t != nil {
|
||||||
|
fmt.Fprintf(fgcc, "\treturn ")
|
||||||
|
// Cast to void* to avoid warnings due to omitted qualifiers
|
||||||
|
// and explicit incompatible struct types.
|
||||||
|
if c := t.C.String(); c[len(c)-1] == '*' {
|
||||||
|
fmt.Fprintf(fgcc, "(void*)")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(fgcc, "r;\n")
|
||||||
|
}
|
||||||
fmt.Fprintf(fgcc, "}\n")
|
fmt.Fprintf(fgcc, "}\n")
|
||||||
fmt.Fprintf(fgcc, "\n")
|
fmt.Fprintf(fgcc, "\n")
|
||||||
}
|
}
|
||||||
|
|
@ -679,16 +728,20 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
p.writeExportHeader(fgcch)
|
p.writeExportHeader(fgcch)
|
||||||
|
|
||||||
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
|
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
|
||||||
|
fmt.Fprintf(fgcc, "#include <stdlib.h>\n")
|
||||||
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
|
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
|
||||||
|
|
||||||
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int), void *, int);\n")
|
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__);\n")
|
||||||
fmt.Fprintf(fgcc, "extern void _cgo_wait_runtime_init_done();\n\n")
|
fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done();\n")
|
||||||
|
fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
|
||||||
|
fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
|
||||||
|
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||||
|
|
||||||
for _, exp := range p.ExpFunc {
|
for _, exp := range p.ExpFunc {
|
||||||
fn := exp.Func
|
fn := exp.Func
|
||||||
|
|
||||||
// Construct a gcc struct matching the gc argument and
|
// Construct a gcc struct matching the gc argument and
|
||||||
// result frame. The gcc struct will be compiled with
|
// result frame. The gcc struct will be compiled with
|
||||||
// __attribute__((packed)) so all padding must be accounted
|
// __attribute__((packed)) so all padding must be accounted
|
||||||
// for explicitly.
|
// for explicitly.
|
||||||
ctype := "struct {\n"
|
ctype := "struct {\n"
|
||||||
|
|
@ -783,10 +836,11 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
|
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
|
||||||
|
|
||||||
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
|
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int, __SIZE_TYPE__);\n", cPrefix, exp.ExpName)
|
||||||
|
fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD")
|
||||||
fmt.Fprintf(fgcc, "\n%s\n", s)
|
fmt.Fprintf(fgcc, "\n%s\n", s)
|
||||||
fmt.Fprintf(fgcc, "{\n")
|
fmt.Fprintf(fgcc, "{\n")
|
||||||
fmt.Fprintf(fgcc, "\t_cgo_wait_runtime_init_done();\n")
|
fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
|
||||||
fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
|
fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
|
||||||
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
|
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
|
||||||
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
|
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
|
||||||
|
|
@ -798,7 +852,10 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
func(i int, aname string, atype ast.Expr) {
|
func(i int, aname string, atype ast.Expr) {
|
||||||
fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
|
fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
|
||||||
})
|
})
|
||||||
fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
|
||||||
|
fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off)
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_release_context(_cgo_ctxt);\n")
|
||||||
if gccResult != "void" {
|
if gccResult != "void" {
|
||||||
if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
|
if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
|
||||||
fmt.Fprintf(fgcc, "\treturn a.r0;\n")
|
fmt.Fprintf(fgcc, "\treturn a.r0;\n")
|
||||||
|
|
@ -823,10 +880,10 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
|
fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
|
||||||
fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
|
fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
|
||||||
fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted
|
fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted
|
||||||
fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {\n", cPrefix, exp.ExpName)
|
fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32, ctxt uintptr) {\n", cPrefix, exp.ExpName)
|
||||||
fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
|
fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
|
||||||
// The indirect here is converting from a Go function pointer to a C function pointer.
|
// The indirect here is converting from a Go function pointer to a C function pointer.
|
||||||
fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
|
fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt);\n")
|
||||||
fmt.Fprintf(fgo2, "}\n")
|
fmt.Fprintf(fgo2, "}\n")
|
||||||
|
|
||||||
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
|
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
|
||||||
|
|
@ -915,6 +972,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
|
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
|
||||||
|
|
||||||
fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
|
fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
|
||||||
|
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||||
|
|
||||||
for _, exp := range p.ExpFunc {
|
for _, exp := range p.ExpFunc {
|
||||||
fn := exp.Func
|
fn := exp.Func
|
||||||
|
|
@ -983,13 +1041,17 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
|
fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
|
||||||
fmt.Fprint(fgcc, "\n")
|
fmt.Fprint(fgcc, "\n")
|
||||||
|
|
||||||
fmt.Fprint(fgcc, "\n")
|
fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n")
|
||||||
fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
|
fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
|
||||||
|
if resultCount > 0 {
|
||||||
|
fmt.Fprintf(fgcc, "\t%s r;\n", cRet)
|
||||||
|
}
|
||||||
fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n")
|
fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n")
|
||||||
fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n")
|
fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n")
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
|
||||||
fmt.Fprint(fgcc, "\t")
|
fmt.Fprint(fgcc, "\t")
|
||||||
if resultCount > 0 {
|
if resultCount > 0 {
|
||||||
fmt.Fprint(fgcc, "return ")
|
fmt.Fprint(fgcc, "r = ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcc, "%s(", goName)
|
fmt.Fprintf(fgcc, "%s(", goName)
|
||||||
if fn.Recv != nil {
|
if fn.Recv != nil {
|
||||||
|
|
@ -1003,6 +1065,10 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
fmt.Fprintf(fgcc, "p%d", i)
|
fmt.Fprintf(fgcc, "p%d", i)
|
||||||
})
|
})
|
||||||
fmt.Fprint(fgcc, ");\n")
|
fmt.Fprint(fgcc, ");\n")
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
|
||||||
|
if resultCount > 0 {
|
||||||
|
fmt.Fprint(fgcc, "\treturn r;\n")
|
||||||
|
}
|
||||||
fmt.Fprint(fgcc, "}\n")
|
fmt.Fprint(fgcc, "}\n")
|
||||||
|
|
||||||
// Dummy declaration for _cgo_main.c
|
// Dummy declaration for _cgo_main.c
|
||||||
|
|
@ -1257,6 +1323,36 @@ extern char* _cgo_topofstack(void);
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// Prologue defining TSAN functions in C.
|
||||||
|
const noTsanProlog = `
|
||||||
|
#define CGO_NO_SANITIZE_THREAD
|
||||||
|
#define _cgo_tsan_acquire()
|
||||||
|
#define _cgo_tsan_release()
|
||||||
|
`
|
||||||
|
|
||||||
|
// This must match the TSAN code in runtime/cgo/libcgo.h.
|
||||||
|
const yesTsanProlog = `
|
||||||
|
#define CGO_NO_SANITIZE_THREAD __attribute__ ((no_sanitize_thread))
|
||||||
|
|
||||||
|
long long _cgo_sync __attribute__ ((common));
|
||||||
|
|
||||||
|
extern void __tsan_acquire(void*);
|
||||||
|
extern void __tsan_release(void*);
|
||||||
|
|
||||||
|
__attribute__ ((unused))
|
||||||
|
static void _cgo_tsan_acquire() {
|
||||||
|
__tsan_acquire(&_cgo_sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((unused))
|
||||||
|
static void _cgo_tsan_release() {
|
||||||
|
__tsan_release(&_cgo_sync);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// Set to yesTsanProlog if we see -fsanitize=thread in the flags for gcc.
|
||||||
|
var tsanProlog = noTsanProlog
|
||||||
|
|
||||||
const builtinProlog = `
|
const builtinProlog = `
|
||||||
#include <stddef.h> /* for ptrdiff_t and size_t below */
|
#include <stddef.h> /* for ptrdiff_t and size_t below */
|
||||||
|
|
||||||
|
|
@ -1269,6 +1365,7 @@ _GoString_ GoString(char *p);
|
||||||
_GoString_ GoStringN(char *p, int l);
|
_GoString_ GoStringN(char *p, int l);
|
||||||
_GoBytes_ GoBytes(void *p, int n);
|
_GoBytes_ GoBytes(void *p, int n);
|
||||||
char *CString(_GoString_);
|
char *CString(_GoString_);
|
||||||
|
void *CBytes(_GoBytes_);
|
||||||
void *_CMalloc(size_t);
|
void *_CMalloc(size_t);
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -1276,11 +1373,8 @@ const goProlog = `
|
||||||
//go:linkname _cgo_runtime_cgocall runtime.cgocall
|
//go:linkname _cgo_runtime_cgocall runtime.cgocall
|
||||||
func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
|
func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
|
||||||
|
|
||||||
//go:linkname _cgo_runtime_cmalloc runtime.cmalloc
|
|
||||||
func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
|
|
||||||
|
|
||||||
//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
|
//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
|
||||||
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
|
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr)
|
||||||
|
|
||||||
//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
|
//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
|
||||||
func _cgoCheckPointer(interface{}, ...interface{}) interface{}
|
func _cgoCheckPointer(interface{}, ...interface{}) interface{}
|
||||||
|
|
@ -1324,7 +1418,7 @@ func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
|
||||||
|
|
||||||
const cStringDef = `
|
const cStringDef = `
|
||||||
func _Cfunc_CString(s string) *_Ctype_char {
|
func _Cfunc_CString(s string) *_Ctype_char {
|
||||||
p := _cgo_runtime_cmalloc(uintptr(len(s)+1))
|
p := _cgo_cmalloc(uint64(len(s)+1))
|
||||||
pp := (*[1<<30]byte)(p)
|
pp := (*[1<<30]byte)(p)
|
||||||
copy(pp[:], s)
|
copy(pp[:], s)
|
||||||
pp[len(s)] = 0
|
pp[len(s)] = 0
|
||||||
|
|
@ -1332,9 +1426,18 @@ func _Cfunc_CString(s string) *_Ctype_char {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const cBytesDef = `
|
||||||
|
func _Cfunc_CBytes(b []byte) unsafe.Pointer {
|
||||||
|
p := _cgo_cmalloc(uint64(len(b)))
|
||||||
|
pp := (*[1<<30]byte)(p)
|
||||||
|
copy(pp[:], b)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
const cMallocDef = `
|
const cMallocDef = `
|
||||||
func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
|
func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
|
||||||
return _cgo_runtime_cmalloc(uintptr(n))
|
return _cgo_cmalloc(uint64(n))
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -1343,9 +1446,54 @@ var builtinDefs = map[string]string{
|
||||||
"GoStringN": goStringNDef,
|
"GoStringN": goStringNDef,
|
||||||
"GoBytes": goBytesDef,
|
"GoBytes": goBytesDef,
|
||||||
"CString": cStringDef,
|
"CString": cStringDef,
|
||||||
|
"CBytes": cBytesDef,
|
||||||
"_CMalloc": cMallocDef,
|
"_CMalloc": cMallocDef,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Definitions for C.malloc in Go and in C. We define it ourselves
|
||||||
|
// since we call it from functions we define, such as C.CString.
|
||||||
|
// Also, we have historically ensured that C.malloc does not return
|
||||||
|
// nil even for an allocation of 0.
|
||||||
|
|
||||||
|
const cMallocDefGo = `
|
||||||
|
//go:cgo_import_static _cgoPREFIX_Cfunc__Cmalloc
|
||||||
|
//go:linkname __cgofn__cgoPREFIX_Cfunc__Cmalloc _cgoPREFIX_Cfunc__Cmalloc
|
||||||
|
var __cgofn__cgoPREFIX_Cfunc__Cmalloc byte
|
||||||
|
var _cgoPREFIX_Cfunc__Cmalloc = unsafe.Pointer(&__cgofn__cgoPREFIX_Cfunc__Cmalloc)
|
||||||
|
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func _cgo_cmalloc(p0 uint64) (r1 unsafe.Pointer) {
|
||||||
|
_cgo_runtime_cgocall(_cgoPREFIX_Cfunc__Cmalloc, uintptr(unsafe.Pointer(&p0)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// cMallocDefC defines the C version of C.malloc for the gc compiler.
|
||||||
|
// It is defined here because C.CString and friends need a definition.
|
||||||
|
// We define it by hand, rather than simply inventing a reference to
|
||||||
|
// C.malloc, because <stdlib.h> may not have been included.
|
||||||
|
// This is approximately what writeOutputFunc would generate, but
|
||||||
|
// skips the cgo_topofstack code (which is only needed if the C code
|
||||||
|
// calls back into Go). This also avoids returning nil for an
|
||||||
|
// allocation of 0 bytes.
|
||||||
|
const cMallocDefC = `
|
||||||
|
CGO_NO_SANITIZE_THREAD
|
||||||
|
void _cgoPREFIX_Cfunc__Cmalloc(void *v) {
|
||||||
|
struct {
|
||||||
|
unsigned long long p0;
|
||||||
|
void *r1;
|
||||||
|
} PACKED *a = v;
|
||||||
|
void *ret;
|
||||||
|
_cgo_tsan_acquire();
|
||||||
|
ret = malloc(a->p0);
|
||||||
|
if (ret == 0 && a->p0 == 0) {
|
||||||
|
ret = malloc(1);
|
||||||
|
}
|
||||||
|
a->r1 = ret;
|
||||||
|
_cgo_tsan_release();
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
func (p *Package) cPrologGccgo() string {
|
func (p *Package) cPrologGccgo() string {
|
||||||
return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
|
return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
|
||||||
"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
|
"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
|
||||||
|
|
@ -1380,6 +1528,12 @@ const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *_cgoPREFIX_Cfunc_CBytes(struct __go_open_array b) {
|
||||||
|
char *p = malloc(b.__count);
|
||||||
|
memmove(p, b.__values, b.__count);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
|
struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
|
||||||
intgo len = (p != NULL) ? strlen(p) : 0;
|
intgo len = (p != NULL) ? strlen(p) : 0;
|
||||||
return __go_byte_array_to_string(p, len);
|
return __go_byte_array_to_string(p, len);
|
||||||
|
|
@ -1505,5 +1659,5 @@ static void GoInit(void) {
|
||||||
runtime_iscgo = 1;
|
runtime_iscgo = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void _cgo_wait_runtime_init_done() __attribute__ ((weak));
|
extern __SIZE_TYPE__ _cgo_wait_runtime_init_done() __attribute__ ((weak));
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
@ -16,6 +17,43 @@ import (
|
||||||
// It returns the output to standard output and standard error.
|
// It returns the output to standard output and standard error.
|
||||||
// ok indicates whether the command exited successfully.
|
// ok indicates whether the command exited successfully.
|
||||||
func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
||||||
|
if i := find(argv, "-xc"); i >= 0 && argv[len(argv)-1] == "-" {
|
||||||
|
// Some compilers have trouble with standard input.
|
||||||
|
// Others have trouble with -xc.
|
||||||
|
// Avoid both problems by writing a file with a .c extension.
|
||||||
|
f, err := ioutil.TempFile("", "cgo-gcc-input-")
|
||||||
|
if err != nil {
|
||||||
|
fatalf("%s", err)
|
||||||
|
}
|
||||||
|
name := f.Name()
|
||||||
|
f.Close()
|
||||||
|
if err := ioutil.WriteFile(name+".c", stdin, 0666); err != nil {
|
||||||
|
os.Remove(name)
|
||||||
|
fatalf("%s", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(name)
|
||||||
|
defer os.Remove(name + ".c")
|
||||||
|
|
||||||
|
// Build new argument list without -xc and trailing -.
|
||||||
|
new := append(argv[:i:i], argv[i+1:len(argv)-1]...)
|
||||||
|
|
||||||
|
// Since we are going to write the file to a temporary directory,
|
||||||
|
// we will need to add -I . explicitly to the command line:
|
||||||
|
// any #include "foo" before would have looked in the current
|
||||||
|
// directory as the directory "holding" standard input, but now
|
||||||
|
// the temporary directory holds the input.
|
||||||
|
// We've also run into compilers that reject "-I." but allow "-I", ".",
|
||||||
|
// so be sure to use two arguments.
|
||||||
|
// This matters mainly for people invoking cgo -godefs by hand.
|
||||||
|
new = append(new, "-I", ".")
|
||||||
|
|
||||||
|
// Finish argument list with path to C file.
|
||||||
|
new = append(new, name+".c")
|
||||||
|
|
||||||
|
argv = new
|
||||||
|
stdin = nil
|
||||||
|
}
|
||||||
|
|
||||||
p := exec.Command(argv[0], argv[1:]...)
|
p := exec.Command(argv[0], argv[1:]...)
|
||||||
p.Stdin = bytes.NewReader(stdin)
|
p.Stdin = bytes.NewReader(stdin)
|
||||||
var bout, berr bytes.Buffer
|
var bout, berr bytes.Buffer
|
||||||
|
|
@ -30,6 +68,15 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func find(argv []string, target string) int {
|
||||||
|
for i, arg := range argv {
|
||||||
|
if arg == target {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
func lineno(pos token.Pos) string {
|
func lineno(pos token.Pos) string {
|
||||||
return fset.Position(pos).String()
|
return fset.Position(pos).String()
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +84,7 @@ func lineno(pos token.Pos) string {
|
||||||
// Die with an error message.
|
// Die with an error message.
|
||||||
func fatalf(msg string, args ...interface{}) {
|
func fatalf(msg string, args ...interface{}) {
|
||||||
// If we've already printed other errors, they might have
|
// If we've already printed other errors, they might have
|
||||||
// caused the fatal condition. Assume they're enough.
|
// caused the fatal condition. Assume they're enough.
|
||||||
if nerrors == 0 {
|
if nerrors == 0 {
|
||||||
fmt.Fprintf(os.Stderr, msg+"\n", args...)
|
fmt.Fprintf(os.Stderr, msg+"\n", args...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -48,6 +48,8 @@ When compiling multiple packages or a single non-main package,
|
||||||
build compiles the packages but discards the resulting object,
|
build compiles the packages but discards the resulting object,
|
||||||
serving only as a check that the packages can be built.
|
serving only as a check that the packages can be built.
|
||||||
|
|
||||||
|
When compiling packages, build ignores files that end in '_test.go'.
|
||||||
|
|
||||||
The -o flag, only allowed when compiling a single package,
|
The -o flag, only allowed when compiling a single package,
|
||||||
forces build to write the resulting executable or object
|
forces build to write the resulting executable or object
|
||||||
to the named output file, instead of the default behavior described
|
to the named output file, instead of the default behavior described
|
||||||
|
|
@ -65,8 +67,7 @@ and test commands:
|
||||||
-p n
|
-p n
|
||||||
the number of programs, such as build commands or
|
the number of programs, such as build commands or
|
||||||
test binaries, that can be run in parallel.
|
test binaries, that can be run in parallel.
|
||||||
The default is the number of CPUs available, except
|
The default is the number of CPUs available.
|
||||||
on darwin/arm which defaults to 1.
|
|
||||||
-race
|
-race
|
||||||
enable data race detection.
|
enable data race detection.
|
||||||
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
|
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
|
||||||
|
|
@ -145,17 +146,6 @@ func init() {
|
||||||
|
|
||||||
addBuildFlags(cmdBuild)
|
addBuildFlags(cmdBuild)
|
||||||
addBuildFlags(cmdInstall)
|
addBuildFlags(cmdInstall)
|
||||||
|
|
||||||
if buildContext.GOOS == "darwin" {
|
|
||||||
switch buildContext.GOARCH {
|
|
||||||
case "arm", "arm64":
|
|
||||||
// darwin/arm cannot run multiple tests simultaneously.
|
|
||||||
// Parallelism is limited in go_darwin_arm_exec, but
|
|
||||||
// also needs to be limited here so go test std does not
|
|
||||||
// timeout tests that waiting to run.
|
|
||||||
buildP = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flags set by multiple commands.
|
// Flags set by multiple commands.
|
||||||
|
|
@ -352,6 +342,11 @@ func buildModeInit() {
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
switch platform {
|
||||||
|
case "darwin/arm", "darwin/arm64":
|
||||||
|
codegenArg = "-shared"
|
||||||
|
default:
|
||||||
|
}
|
||||||
exeSuffix = ".a"
|
exeSuffix = ".a"
|
||||||
ldBuildmode = "c-archive"
|
ldBuildmode = "c-archive"
|
||||||
case "c-shared":
|
case "c-shared":
|
||||||
|
|
@ -374,6 +369,9 @@ func buildModeInit() {
|
||||||
case "android/arm", "android/arm64", "android/amd64", "android/386":
|
case "android/arm", "android/arm64", "android/amd64", "android/386":
|
||||||
codegenArg = "-shared"
|
codegenArg = "-shared"
|
||||||
ldBuildmode = "pie"
|
ldBuildmode = "pie"
|
||||||
|
case "darwin/arm", "darwin/arm64":
|
||||||
|
codegenArg = "-shared"
|
||||||
|
fallthrough
|
||||||
default:
|
default:
|
||||||
ldBuildmode = "exe"
|
ldBuildmode = "exe"
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +383,7 @@ func buildModeInit() {
|
||||||
fatalf("-buildmode=pie not supported by gccgo")
|
fatalf("-buildmode=pie not supported by gccgo")
|
||||||
} else {
|
} else {
|
||||||
switch platform {
|
switch platform {
|
||||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le",
|
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
|
||||||
"android/amd64", "android/arm", "android/arm64", "android/386":
|
"android/amd64", "android/arm", "android/arm64", "android/386":
|
||||||
codegenArg = "-shared"
|
codegenArg = "-shared"
|
||||||
default:
|
default:
|
||||||
|
|
@ -399,7 +397,7 @@ func buildModeInit() {
|
||||||
codegenArg = "-fPIC"
|
codegenArg = "-fPIC"
|
||||||
} else {
|
} else {
|
||||||
switch platform {
|
switch platform {
|
||||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le":
|
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
|
||||||
default:
|
default:
|
||||||
fatalf("-buildmode=shared not supported on %s\n", platform)
|
fatalf("-buildmode=shared not supported on %s\n", platform)
|
||||||
}
|
}
|
||||||
|
|
@ -417,7 +415,7 @@ func buildModeInit() {
|
||||||
codegenArg = "-fPIC"
|
codegenArg = "-fPIC"
|
||||||
} else {
|
} else {
|
||||||
switch platform {
|
switch platform {
|
||||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le":
|
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
|
||||||
buildAsmflags = append(buildAsmflags, "-D=GOBUILDMODE_shared=1")
|
buildAsmflags = append(buildAsmflags, "-D=GOBUILDMODE_shared=1")
|
||||||
default:
|
default:
|
||||||
fatalf("-linkshared not supported on %s\n", platform)
|
fatalf("-linkshared not supported on %s\n", platform)
|
||||||
|
|
@ -483,6 +481,7 @@ func runBuild(cmd *Command, args []string) {
|
||||||
p := pkgs[0]
|
p := pkgs[0]
|
||||||
p.target = *buildO
|
p.target = *buildO
|
||||||
p.Stale = true // must build - not up to date
|
p.Stale = true // must build - not up to date
|
||||||
|
p.StaleReason = "build -o flag in use"
|
||||||
a := b.action(modeInstall, depMode, p)
|
a := b.action(modeInstall, depMode, p)
|
||||||
b.do(a)
|
b.do(a)
|
||||||
return
|
return
|
||||||
|
|
@ -525,7 +524,7 @@ func isMetaPackage(name string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// libname returns the filename to use for the shared library when using
|
// libname returns the filename to use for the shared library when using
|
||||||
// -buildmode=shared. The rules we use are:
|
// -buildmode=shared. The rules we use are:
|
||||||
// Use arguments for special 'meta' packages:
|
// Use arguments for special 'meta' packages:
|
||||||
// std --> libstd.so
|
// std --> libstd.so
|
||||||
// std cmd --> libstd,cmd.so
|
// std cmd --> libstd,cmd.so
|
||||||
|
|
@ -681,6 +680,7 @@ var (
|
||||||
func init() {
|
func init() {
|
||||||
goarch = buildContext.GOARCH
|
goarch = buildContext.GOARCH
|
||||||
goos = buildContext.GOOS
|
goos = buildContext.GOOS
|
||||||
|
|
||||||
if goos == "windows" {
|
if goos == "windows" {
|
||||||
exeSuffix = ".exe"
|
exeSuffix = ".exe"
|
||||||
}
|
}
|
||||||
|
|
@ -694,6 +694,7 @@ type builder struct {
|
||||||
work string // the temporary work directory (ends in filepath.Separator)
|
work string // the temporary work directory (ends in filepath.Separator)
|
||||||
actionCache map[cacheKey]*action // a cache of already-constructed actions
|
actionCache map[cacheKey]*action // a cache of already-constructed actions
|
||||||
mkdirCache map[string]bool // a cache of created directories
|
mkdirCache map[string]bool // a cache of created directories
|
||||||
|
flagCache map[string]bool // a cache of supported compiler flags
|
||||||
print func(args ...interface{}) (int, error)
|
print func(args ...interface{}) (int, error)
|
||||||
|
|
||||||
output sync.Mutex
|
output sync.Mutex
|
||||||
|
|
@ -795,7 +796,7 @@ func goFilesPackage(gofiles []string) *Package {
|
||||||
|
|
||||||
// Synthesize fake "directory" that only shows the named files,
|
// Synthesize fake "directory" that only shows the named files,
|
||||||
// to make it look like this is a standard package or
|
// to make it look like this is a standard package or
|
||||||
// command directory. So that local imports resolve
|
// command directory. So that local imports resolve
|
||||||
// consistently, the files must all be in the same directory.
|
// consistently, the files must all be in the same directory.
|
||||||
var dirent []os.FileInfo
|
var dirent []os.FileInfo
|
||||||
var dir string
|
var dir string
|
||||||
|
|
@ -853,6 +854,7 @@ func goFilesPackage(gofiles []string) *Package {
|
||||||
|
|
||||||
pkg.Target = pkg.target
|
pkg.Target = pkg.target
|
||||||
pkg.Stale = true
|
pkg.Stale = true
|
||||||
|
pkg.StaleReason = "files named on command line"
|
||||||
|
|
||||||
computeStale(pkg)
|
computeStale(pkg)
|
||||||
return pkg
|
return pkg
|
||||||
|
|
@ -957,7 +959,7 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
|
||||||
// If we are not doing a cross-build, then record the binary we'll
|
// If we are not doing a cross-build, then record the binary we'll
|
||||||
// generate for cgo as a dependency of the build of any package
|
// generate for cgo as a dependency of the build of any package
|
||||||
// using cgo, to make sure we do not overwrite the binary while
|
// using cgo, to make sure we do not overwrite the binary while
|
||||||
// a package is using it. If this is a cross-build, then the cgo we
|
// a package is using it. If this is a cross-build, then the cgo we
|
||||||
// are writing is not the cgo we need to use.
|
// are writing is not the cgo we need to use.
|
||||||
if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan && reqStdPkgSrc {
|
if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan && reqStdPkgSrc {
|
||||||
if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !buildLinkshared && buildBuildmode != "shared" {
|
if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !buildLinkshared && buildBuildmode != "shared" {
|
||||||
|
|
@ -993,7 +995,7 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.local && p.target == "" {
|
if p.local && p.target == "" {
|
||||||
// Imported via local path. No permanent target.
|
// Imported via local path. No permanent target.
|
||||||
mode = modeBuild
|
mode = modeBuild
|
||||||
}
|
}
|
||||||
work := p.pkgdir
|
work := p.pkgdir
|
||||||
|
|
@ -1041,7 +1043,7 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
|
||||||
// the name will show up in ps listings. If the caller has specified
|
// the name will show up in ps listings. If the caller has specified
|
||||||
// a name, use that instead of a.out. The binary is generated
|
// a name, use that instead of a.out. The binary is generated
|
||||||
// in an otherwise empty subdirectory named exe to avoid
|
// in an otherwise empty subdirectory named exe to avoid
|
||||||
// naming conflicts. The only possible conflict is if we were
|
// naming conflicts. The only possible conflict is if we were
|
||||||
// to create a top-level package named exe.
|
// to create a top-level package named exe.
|
||||||
name := "a.out"
|
name := "a.out"
|
||||||
if p.exeName != "" {
|
if p.exeName != "" {
|
||||||
|
|
@ -1227,14 +1229,22 @@ func allArchiveActions(root *action) []*action {
|
||||||
|
|
||||||
// do runs the action graph rooted at root.
|
// do runs the action graph rooted at root.
|
||||||
func (b *builder) do(root *action) {
|
func (b *builder) do(root *action) {
|
||||||
|
/* Commented out for gccgo, which does not have osArchSupportsCgo.
|
||||||
|
|
||||||
|
if _, ok := osArchSupportsCgo[goos+"/"+goarch]; !ok && buildContext.Compiler == "gc" {
|
||||||
|
fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", goos, goarch)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Build list of all actions, assigning depth-first post-order priority.
|
// Build list of all actions, assigning depth-first post-order priority.
|
||||||
// The original implementation here was a true queue
|
// The original implementation here was a true queue
|
||||||
// (using a channel) but it had the effect of getting
|
// (using a channel) but it had the effect of getting
|
||||||
// distracted by low-level leaf actions to the detriment
|
// distracted by low-level leaf actions to the detriment
|
||||||
// of completing higher-level actions. The order of
|
// of completing higher-level actions. The order of
|
||||||
// work does not matter much to overall execution time,
|
// work does not matter much to overall execution time,
|
||||||
// but when running "go test std" it is nice to see each test
|
// but when running "go test std" it is nice to see each test
|
||||||
// results as soon as possible. The priorities assigned
|
// results as soon as possible. The priorities assigned
|
||||||
// ensure that, all else being equal, the execution prefers
|
// ensure that, all else being equal, the execution prefers
|
||||||
// to do what it would have done first in a simple depth-first
|
// to do what it would have done first in a simple depth-first
|
||||||
// dependency order traversal.
|
// dependency order traversal.
|
||||||
|
|
@ -1331,18 +1341,15 @@ func (b *builder) do(root *action) {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasString reports whether s appears in the list of strings.
|
|
||||||
func hasString(strings []string, s string) bool {
|
|
||||||
for _, t := range strings {
|
|
||||||
if s == t {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// build is the action for building a single package or command.
|
// build is the action for building a single package or command.
|
||||||
func (b *builder) build(a *action) (err error) {
|
func (b *builder) build(a *action) (err error) {
|
||||||
|
// Return an error for binary-only package.
|
||||||
|
// We only reach this if isStale believes the binary form is
|
||||||
|
// either not present or not usable.
|
||||||
|
if a.p.BinaryOnly {
|
||||||
|
return fmt.Errorf("missing or invalid package binary for binary-only package %s", a.p.ImportPath)
|
||||||
|
}
|
||||||
|
|
||||||
// Return an error if the package has CXX files but it's not using
|
// Return an error if the package has CXX files but it's not using
|
||||||
// cgo nor SWIG, since the CXX files can only be processed by cgo
|
// cgo nor SWIG, since the CXX files can only be processed by cgo
|
||||||
// and SWIG.
|
// and SWIG.
|
||||||
|
|
@ -1355,6 +1362,12 @@ func (b *builder) build(a *action) (err error) {
|
||||||
return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG",
|
return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG",
|
||||||
a.p.ImportPath, strings.Join(a.p.MFiles, ","))
|
a.p.ImportPath, strings.Join(a.p.MFiles, ","))
|
||||||
}
|
}
|
||||||
|
// Same as above for Fortran files
|
||||||
|
if len(a.p.FFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
|
||||||
|
return fmt.Errorf("can't build package %s because it contains Fortran files (%s) but it's not using cgo nor SWIG",
|
||||||
|
a.p.ImportPath, strings.Join(a.p.FFiles, ","))
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil && err != errPrintedOutput {
|
if err != nil && err != errPrintedOutput {
|
||||||
err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
|
err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
|
||||||
|
|
@ -1421,6 +1434,8 @@ func (b *builder) build(a *action) (err error) {
|
||||||
// cgo and non-cgo worlds, so it necessarily has files in both.
|
// cgo and non-cgo worlds, so it necessarily has files in both.
|
||||||
// In that case gcc only gets the gcc_* files.
|
// In that case gcc only gets the gcc_* files.
|
||||||
var gccfiles []string
|
var gccfiles []string
|
||||||
|
gccfiles = append(gccfiles, cfiles...)
|
||||||
|
cfiles = nil
|
||||||
if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
|
if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
|
||||||
filter := func(files, nongcc, gcc []string) ([]string, []string) {
|
filter := func(files, nongcc, gcc []string) ([]string, []string) {
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
|
@ -1432,11 +1447,9 @@ func (b *builder) build(a *action) (err error) {
|
||||||
}
|
}
|
||||||
return nongcc, gcc
|
return nongcc, gcc
|
||||||
}
|
}
|
||||||
cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles)
|
|
||||||
sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
|
sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
|
||||||
} else {
|
} else {
|
||||||
gccfiles = append(cfiles, sfiles...)
|
gccfiles = append(gccfiles, sfiles...)
|
||||||
cfiles = nil
|
|
||||||
sfiles = nil
|
sfiles = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1444,7 +1457,7 @@ func (b *builder) build(a *action) (err error) {
|
||||||
if a.cgo != nil && a.cgo.target != "" {
|
if a.cgo != nil && a.cgo.target != "" {
|
||||||
cgoExe = a.cgo.target
|
cgoExe = a.cgo.target
|
||||||
}
|
}
|
||||||
outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, cxxfiles, a.p.MFiles)
|
outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, cxxfiles, a.p.MFiles, a.p.FFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -1552,7 +1565,7 @@ func (b *builder) build(a *action) (err error) {
|
||||||
|
|
||||||
// NOTE(rsc): On Windows, it is critically important that the
|
// NOTE(rsc): On Windows, it is critically important that the
|
||||||
// gcc-compiled objects (cgoObjects) be listed after the ordinary
|
// gcc-compiled objects (cgoObjects) be listed after the ordinary
|
||||||
// objects in the archive. I do not know why this is.
|
// objects in the archive. I do not know why this is.
|
||||||
// https://golang.org/issue/2601
|
// https://golang.org/issue/2601
|
||||||
objects = append(objects, cgoObjects...)
|
objects = append(objects, cgoObjects...)
|
||||||
|
|
||||||
|
|
@ -1658,7 +1671,7 @@ func (b *builder) install(a *action) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove object dir to keep the amount of
|
// remove object dir to keep the amount of
|
||||||
// garbage down in a large build. On an operating system
|
// garbage down in a large build. On an operating system
|
||||||
// with aggressive buffering, cleaning incrementally like
|
// with aggressive buffering, cleaning incrementally like
|
||||||
// this keeps the intermediate objects from hitting the disk.
|
// this keeps the intermediate objects from hitting the disk.
|
||||||
if !buildWork {
|
if !buildWork {
|
||||||
|
|
@ -1803,7 +1816,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
|
||||||
df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
|
df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
|
||||||
if err != nil && toolIsWindows {
|
if err != nil && toolIsWindows {
|
||||||
// Windows does not allow deletion of a binary file
|
// Windows does not allow deletion of a binary file
|
||||||
// while it is executing. Try to move it out of the way.
|
// while it is executing. Try to move it out of the way.
|
||||||
// If the move fails, which is likely, we'll try again the
|
// If the move fails, which is likely, we'll try again the
|
||||||
// next time we do an install of this binary.
|
// next time we do an install of this binary.
|
||||||
if err := os.Rename(dst, dst+"~"); err == nil {
|
if err := os.Rename(dst, dst+"~"); err == nil {
|
||||||
|
|
@ -1933,7 +1946,7 @@ func (b *builder) showcmd(dir string, format string, args ...interface{}) {
|
||||||
// The output is expected to contain references to 'dir', usually
|
// The output is expected to contain references to 'dir', usually
|
||||||
// the source directory for the package that has failed to build.
|
// the source directory for the package that has failed to build.
|
||||||
// showOutput rewrites mentions of dir with a relative path to dir
|
// showOutput rewrites mentions of dir with a relative path to dir
|
||||||
// when the relative path is shorter. This is usually more pleasant.
|
// when the relative path is shorter. This is usually more pleasant.
|
||||||
// For example, if fmt doesn't compile and we are in src/html,
|
// For example, if fmt doesn't compile and we are in src/html,
|
||||||
// the output is
|
// the output is
|
||||||
//
|
//
|
||||||
|
|
@ -1991,7 +2004,7 @@ func relPaths(paths []string) []string {
|
||||||
// errPrintedOutput is a special error indicating that a command failed
|
// errPrintedOutput is a special error indicating that a command failed
|
||||||
// but that it generated output as well, and that output has already
|
// but that it generated output as well, and that output has already
|
||||||
// been printed, so there's no point showing 'exit status 1' or whatever
|
// been printed, so there's no point showing 'exit status 1' or whatever
|
||||||
// the wait status was. The main executor, builder.do, knows not to
|
// the wait status was. The main executor, builder.do, knows not to
|
||||||
// print this error.
|
// print this error.
|
||||||
var errPrintedOutput = errors.New("already printed output - no need to show error")
|
var errPrintedOutput = errors.New("already printed output - no need to show error")
|
||||||
|
|
||||||
|
|
@ -2060,7 +2073,7 @@ func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
|
|
||||||
// cmd.Run will fail on Unix if some other process has the binary
|
// cmd.Run will fail on Unix if some other process has the binary
|
||||||
// we want to run open for writing. This can happen here because
|
// we want to run open for writing. This can happen here because
|
||||||
// we build and install the cgo command and then run it.
|
// we build and install the cgo command and then run it.
|
||||||
// If another command was kicked off while we were writing the
|
// If another command was kicked off while we were writing the
|
||||||
// cgo binary, the child process for that command may be holding
|
// cgo binary, the child process for that command may be holding
|
||||||
|
|
@ -2072,27 +2085,27 @@ func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter
|
||||||
// The answer is that running a command is fork and exec.
|
// The answer is that running a command is fork and exec.
|
||||||
// A child forked while the cgo fd is open inherits that fd.
|
// A child forked while the cgo fd is open inherits that fd.
|
||||||
// Until the child has called exec, it holds the fd open and the
|
// Until the child has called exec, it holds the fd open and the
|
||||||
// kernel will not let us run cgo. Even if the child were to close
|
// kernel will not let us run cgo. Even if the child were to close
|
||||||
// the fd explicitly, it would still be open from the time of the fork
|
// the fd explicitly, it would still be open from the time of the fork
|
||||||
// until the time of the explicit close, and the race would remain.
|
// until the time of the explicit close, and the race would remain.
|
||||||
//
|
//
|
||||||
// On Unix systems, this results in ETXTBSY, which formats
|
// On Unix systems, this results in ETXTBSY, which formats
|
||||||
// as "text file busy". Rather than hard-code specific error cases,
|
// as "text file busy". Rather than hard-code specific error cases,
|
||||||
// we just look for that string. If this happens, sleep a little
|
// we just look for that string. If this happens, sleep a little
|
||||||
// and try again. We let this happen three times, with increasing
|
// and try again. We let this happen three times, with increasing
|
||||||
// sleep lengths: 100+200+400 ms = 0.7 seconds.
|
// sleep lengths: 100+200+400 ms = 0.7 seconds.
|
||||||
//
|
//
|
||||||
// An alternate solution might be to split the cmd.Run into
|
// An alternate solution might be to split the cmd.Run into
|
||||||
// separate cmd.Start and cmd.Wait, and then use an RWLock
|
// separate cmd.Start and cmd.Wait, and then use an RWLock
|
||||||
// to make sure that copyFile only executes when no cmd.Start
|
// to make sure that copyFile only executes when no cmd.Start
|
||||||
// call is in progress. However, cmd.Start (really syscall.forkExec)
|
// call is in progress. However, cmd.Start (really syscall.forkExec)
|
||||||
// only guarantees that when it returns, the exec is committed to
|
// only guarantees that when it returns, the exec is committed to
|
||||||
// happen and succeed. It uses a close-on-exec file descriptor
|
// happen and succeed. It uses a close-on-exec file descriptor
|
||||||
// itself to determine this, so we know that when cmd.Start returns,
|
// itself to determine this, so we know that when cmd.Start returns,
|
||||||
// at least one close-on-exec file descriptor has been closed.
|
// at least one close-on-exec file descriptor has been closed.
|
||||||
// However, we cannot be sure that all of them have been closed,
|
// However, we cannot be sure that all of them have been closed,
|
||||||
// so the program might still encounter ETXTBSY even with such
|
// so the program might still encounter ETXTBSY even with such
|
||||||
// an RWLock. The race window would be smaller, perhaps, but not
|
// an RWLock. The race window would be smaller, perhaps, but not
|
||||||
// guaranteed to be gone.
|
// guaranteed to be gone.
|
||||||
//
|
//
|
||||||
// Sleeping when we observe the race seems to be the most reliable
|
// Sleeping when we observe the race seems to be the most reliable
|
||||||
|
|
@ -2142,7 +2155,7 @@ func (b *builder) mkdir(dir string) error {
|
||||||
b.exec.Lock()
|
b.exec.Lock()
|
||||||
defer b.exec.Unlock()
|
defer b.exec.Unlock()
|
||||||
// We can be a little aggressive about being
|
// We can be a little aggressive about being
|
||||||
// sure directories exist. Skip repeated calls.
|
// sure directories exist. Skip repeated calls.
|
||||||
if b.mkdirCache[dir] {
|
if b.mkdirCache[dir] {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -2180,7 +2193,6 @@ func mkAbs(dir, f string) string {
|
||||||
type toolchain interface {
|
type toolchain interface {
|
||||||
// gc runs the compiler in a specific directory on a set of files
|
// gc runs the compiler in a specific directory on a set of files
|
||||||
// and returns the name of the generated output file.
|
// and returns the name of the generated output file.
|
||||||
// The compiler runs in the directory dir.
|
|
||||||
gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
|
gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
|
||||||
// cc runs the toolchain's C compiler in a directory on a C file
|
// cc runs the toolchain's C compiler in a directory on a C file
|
||||||
// to produce an output file.
|
// to produce an output file.
|
||||||
|
|
@ -2282,7 +2294,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
|
||||||
// so that it can give good error messages about forward declarations.
|
// so that it can give good error messages about forward declarations.
|
||||||
// Exceptions: a few standard packages have forward declarations for
|
// Exceptions: a few standard packages have forward declarations for
|
||||||
// pieces supplied behind-the-scenes by package runtime.
|
// pieces supplied behind-the-scenes by package runtime.
|
||||||
extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
|
extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.FFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
|
||||||
if p.Standard {
|
if p.Standard {
|
||||||
switch p.ImportPath {
|
switch p.ImportPath {
|
||||||
case "bytes", "net", "os", "runtime/pprof", "sync", "time":
|
case "bytes", "net", "os", "runtime/pprof", "sync", "time":
|
||||||
|
|
@ -2334,7 +2346,15 @@ func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
|
||||||
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
|
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
|
||||||
inc := filepath.Join(goroot, "pkg", "include")
|
inc := filepath.Join(goroot, "pkg", "include")
|
||||||
sfile = mkAbs(p.Dir, sfile)
|
sfile = mkAbs(p.Dir, sfile)
|
||||||
args := []interface{}{buildToolExec, tool("asm"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags, sfile}
|
args := []interface{}{buildToolExec, tool("asm"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
|
||||||
|
if p.ImportPath == "runtime" && goarch == "386" {
|
||||||
|
for _, arg := range buildAsmflags {
|
||||||
|
if arg == "-dynlink" {
|
||||||
|
args = append(args, "-D=GOBUILDMODE_shared=1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args = append(args, sfile)
|
||||||
if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
|
if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -2381,8 +2401,10 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
|
||||||
|
|
||||||
// The archive file should have been created by the compiler.
|
// The archive file should have been created by the compiler.
|
||||||
// Since it used to not work that way, verify.
|
// Since it used to not work that way, verify.
|
||||||
if _, err := os.Stat(absAfile); err != nil {
|
if !buildN {
|
||||||
fatalf("os.Stat of archive file failed: %v", err)
|
if _, err := os.Stat(absAfile); err != nil {
|
||||||
|
fatalf("os.Stat of archive file failed: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if buildN || buildX {
|
if buildN || buildX {
|
||||||
|
|
@ -2629,18 +2651,23 @@ func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
|
||||||
return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objDir, afile), absOfiles)
|
return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objDir, afile), absOfiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
|
func (tools gccgoToolchain) link(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string, buildmode, desc string) error {
|
||||||
// gccgo needs explicit linking with all package dependencies,
|
// gccgo needs explicit linking with all package dependencies,
|
||||||
// and all LDFLAGS from cgo dependencies.
|
// and all LDFLAGS from cgo dependencies.
|
||||||
apackagesSeen := make(map[*Package]bool)
|
apackagePathsSeen := make(map[string]bool)
|
||||||
afiles := []string{}
|
afiles := []string{}
|
||||||
shlibs := []string{}
|
shlibs := []string{}
|
||||||
xfiles := []string{}
|
|
||||||
ldflags := b.gccArchArgs()
|
ldflags := b.gccArchArgs()
|
||||||
cgoldflags := []string{}
|
cgoldflags := []string{}
|
||||||
usesCgo := false
|
usesCgo := false
|
||||||
cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
|
cxx := false
|
||||||
objc := len(root.p.MFiles) > 0
|
objc := false
|
||||||
|
fortran := false
|
||||||
|
if root.p != nil {
|
||||||
|
cxx = len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
|
||||||
|
objc = len(root.p.MFiles) > 0
|
||||||
|
fortran = len(root.p.FFiles) > 0
|
||||||
|
}
|
||||||
|
|
||||||
readCgoFlags := func(flagsFile string) error {
|
readCgoFlags := func(flagsFile string) error {
|
||||||
flags, err := ioutil.ReadFile(flagsFile)
|
flags, err := ioutil.ReadFile(flagsFile)
|
||||||
|
|
@ -2687,11 +2714,11 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
}
|
}
|
||||||
|
|
||||||
newarchive := newa.Name()
|
newarchive := newa.Name()
|
||||||
err = b.run(b.work, root.p.ImportPath, nil, "ar", "x", newarchive, "_cgo_flags")
|
err = b.run(b.work, desc, nil, "ar", "x", newarchive, "_cgo_flags")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
err = b.run(".", root.p.ImportPath, nil, "ar", "d", newarchive, "_cgo_flags")
|
err = b.run(".", desc, nil, "ar", "d", newarchive, "_cgo_flags")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -2723,10 +2750,10 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
// rather than the 'build' location (which may not exist any
|
// rather than the 'build' location (which may not exist any
|
||||||
// more). We still need to traverse the dependencies of the
|
// more). We still need to traverse the dependencies of the
|
||||||
// build action though so saying
|
// build action though so saying
|
||||||
// if apackagesSeen[a.p] { return }
|
// if apackagePathsSeen[a.p.ImportPath] { return }
|
||||||
// doesn't work.
|
// doesn't work.
|
||||||
if !apackagesSeen[a.p] {
|
if !apackagePathsSeen[a.p.ImportPath] {
|
||||||
apackagesSeen[a.p] = true
|
apackagePathsSeen[a.p.ImportPath] = true
|
||||||
target := a.target
|
target := a.target
|
||||||
if len(a.p.CgoFiles) > 0 {
|
if len(a.p.CgoFiles) > 0 {
|
||||||
target, err = readAndRemoveCgoFlags(target)
|
target, err = readAndRemoveCgoFlags(target)
|
||||||
|
|
@ -2734,17 +2761,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if a.p.fake && a.p.external {
|
afiles = append(afiles, target)
|
||||||
// external _tests, if present must come before
|
|
||||||
// internal _tests. Store these on a separate list
|
|
||||||
// and place them at the head after this loop.
|
|
||||||
xfiles = append(xfiles, target)
|
|
||||||
} else if a.p.fake {
|
|
||||||
// move _test files to the top of the link order
|
|
||||||
afiles = append([]string{target}, afiles...)
|
|
||||||
} else {
|
|
||||||
afiles = append(afiles, target)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(a.target, ".so") {
|
if strings.HasSuffix(a.target, ".so") {
|
||||||
|
|
@ -2764,7 +2781,6 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
afiles = append(xfiles, afiles...)
|
|
||||||
|
|
||||||
for _, a := range allactions {
|
for _, a := range allactions {
|
||||||
// Gather CgoLDFLAGS, but not from standard packages.
|
// Gather CgoLDFLAGS, but not from standard packages.
|
||||||
|
|
@ -2789,6 +2805,9 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
if len(a.p.MFiles) > 0 {
|
if len(a.p.MFiles) > 0 {
|
||||||
objc = true
|
objc = true
|
||||||
}
|
}
|
||||||
|
if len(a.p.FFiles) > 0 {
|
||||||
|
fortran = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, o := range ofiles {
|
for i, o := range ofiles {
|
||||||
|
|
@ -2805,7 +2824,9 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
|
|
||||||
ldflags = append(ldflags, cgoldflags...)
|
ldflags = append(ldflags, cgoldflags...)
|
||||||
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
|
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
|
||||||
ldflags = append(ldflags, root.p.CgoLDFLAGS...)
|
if root.p != nil {
|
||||||
|
ldflags = append(ldflags, root.p.CgoLDFLAGS...)
|
||||||
|
}
|
||||||
|
|
||||||
ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)")
|
ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)")
|
||||||
|
|
||||||
|
|
@ -2820,7 +2841,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
}
|
}
|
||||||
|
|
||||||
var realOut string
|
var realOut string
|
||||||
switch ldBuildmode {
|
switch buildmode {
|
||||||
case "exe":
|
case "exe":
|
||||||
if usesCgo && goos == "linux" {
|
if usesCgo && goos == "linux" {
|
||||||
ldflags = append(ldflags, "-Wl,-E")
|
ldflags = append(ldflags, "-Wl,-E")
|
||||||
|
|
@ -2836,7 +2857,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
// initialization code.
|
// initialization code.
|
||||||
//
|
//
|
||||||
// The user remains responsible for linking against
|
// The user remains responsible for linking against
|
||||||
// -lgo -lpthread -lm in the final link. We can't use
|
// -lgo -lpthread -lm in the final link. We can't use
|
||||||
// -r to pick them up because we can't combine
|
// -r to pick them up because we can't combine
|
||||||
// split-stack and non-split-stack code in a single -r
|
// split-stack and non-split-stack code in a single -r
|
||||||
// link, and libgo picks up non-split-stack code from
|
// link, and libgo picks up non-split-stack code from
|
||||||
|
|
@ -2855,12 +2876,14 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
|
|
||||||
case "c-shared":
|
case "c-shared":
|
||||||
ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc")
|
ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc")
|
||||||
|
case "shared":
|
||||||
|
ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatalf("-buildmode=%s not supported for gccgo", ldBuildmode)
|
fatalf("-buildmode=%s not supported for gccgo", buildmode)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ldBuildmode {
|
switch buildmode {
|
||||||
case "exe", "c-shared":
|
case "exe", "c-shared":
|
||||||
if cxx {
|
if cxx {
|
||||||
ldflags = append(ldflags, "-lstdc++")
|
ldflags = append(ldflags, "-lstdc++")
|
||||||
|
|
@ -2868,43 +2891,40 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||||
if objc {
|
if objc {
|
||||||
ldflags = append(ldflags, "-lobjc")
|
ldflags = append(ldflags, "-lobjc")
|
||||||
}
|
}
|
||||||
|
if fortran {
|
||||||
|
fc := os.Getenv("FC")
|
||||||
|
if fc == "" {
|
||||||
|
fc = "gfortran"
|
||||||
|
}
|
||||||
|
// support gfortran out of the box and let others pass the correct link options
|
||||||
|
// via CGO_LDFLAGS
|
||||||
|
if strings.Contains(fc, "gfortran") {
|
||||||
|
ldflags = append(ldflags, "-lgfortran")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := b.run(".", root.p.ImportPath, nil, tools.linker(), "-o", out, ofiles, ldflags, buildGccgoflags); err != nil {
|
if err := b.run(".", desc, nil, tools.linker(), "-o", out, ofiles, ldflags, buildGccgoflags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ldBuildmode {
|
switch buildmode {
|
||||||
case "c-archive":
|
case "c-archive":
|
||||||
if err := b.run(".", root.p.ImportPath, nil, "ar", "rc", realOut, out); err != nil {
|
if err := b.run(".", desc, nil, "ar", "rc", realOut, out); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
|
||||||
|
return tools.link(b, root, out, allactions, mainpkg, ofiles, ldBuildmode, root.p.ImportPath)
|
||||||
|
}
|
||||||
|
|
||||||
func (tools gccgoToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
|
func (tools gccgoToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
|
||||||
args := []string{"-o", out, "-shared", "-nostdlib", "-zdefs", "-Wl,--whole-archive"}
|
fakeRoot := &action{}
|
||||||
for _, a := range toplevelactions {
|
fakeRoot.deps = toplevelactions
|
||||||
args = append(args, a.target)
|
return tools.link(b, fakeRoot, out, allactions, "", nil, "shared", out)
|
||||||
}
|
|
||||||
args = append(args, "-Wl,--no-whole-archive", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
|
|
||||||
shlibs := []string{}
|
|
||||||
for _, a := range allactions {
|
|
||||||
if strings.HasSuffix(a.target, ".so") {
|
|
||||||
shlibs = append(shlibs, a.target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, shlib := range shlibs {
|
|
||||||
args = append(
|
|
||||||
args,
|
|
||||||
"-L"+filepath.Dir(shlib),
|
|
||||||
"-Wl,-rpath="+filepath.Dir(shlib),
|
|
||||||
"-l"+strings.TrimSuffix(
|
|
||||||
strings.TrimPrefix(filepath.Base(shlib), "lib"),
|
|
||||||
".so"))
|
|
||||||
}
|
|
||||||
return b.run(".", out, nil, tools.linker(), args, buildGccgoflags)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
|
func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
|
||||||
|
|
@ -2962,6 +2982,11 @@ func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) er
|
||||||
return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
|
return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
|
||||||
|
func (b *builder) gfortran(p *Package, out string, flags []string, ffile string) error {
|
||||||
|
return b.ccompile(p, out, flags, ffile, b.gfortranCmd(p.Dir))
|
||||||
|
}
|
||||||
|
|
||||||
// ccompile runs the given C or C++ compiler and creates an object from a single source file.
|
// ccompile runs the given C or C++ compiler and creates an object from a single source file.
|
||||||
func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error {
|
func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error {
|
||||||
file = mkAbs(p.Dir, file)
|
file = mkAbs(p.Dir, file)
|
||||||
|
|
@ -2991,6 +3016,11 @@ func (b *builder) gxxCmd(objdir string) []string {
|
||||||
return b.ccompilerCmd("CXX", defaultCXX, objdir)
|
return b.ccompilerCmd("CXX", defaultCXX, objdir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gfortranCmd returns a gfortran command line prefix.
|
||||||
|
func (b *builder) gfortranCmd(objdir string) []string {
|
||||||
|
return b.ccompilerCmd("FC", "gfortran", objdir)
|
||||||
|
}
|
||||||
|
|
||||||
// ccompilerCmd returns a command line prefix for the given environment
|
// ccompilerCmd returns a command line prefix for the given environment
|
||||||
// variable and using the default command when the variable is empty.
|
// variable and using the default command when the variable is empty.
|
||||||
func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
|
func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
|
||||||
|
|
@ -3028,6 +3058,17 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
|
||||||
// disable word wrapping in error messages
|
// disable word wrapping in error messages
|
||||||
a = append(a, "-fmessage-length=0")
|
a = append(a, "-fmessage-length=0")
|
||||||
|
|
||||||
|
// Tell gcc not to include the work directory in object files.
|
||||||
|
if b.gccSupportsFlag("-fdebug-prefix-map=a=b") {
|
||||||
|
a = append(a, "-fdebug-prefix-map="+b.work+"=/tmp/go-build")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell gcc not to include flags in object files, which defeats the
|
||||||
|
// point of -fdebug-prefix-map above.
|
||||||
|
if b.gccSupportsFlag("-gno-record-gcc-switches") {
|
||||||
|
a = append(a, "-gno-record-gcc-switches")
|
||||||
|
}
|
||||||
|
|
||||||
// On OS X, some of the compilers behave as if -fno-common
|
// On OS X, some of the compilers behave as if -fno-common
|
||||||
// is always set, and the Mach-O linker in 6l/8l assumes this.
|
// is always set, and the Mach-O linker in 6l/8l assumes this.
|
||||||
// See https://golang.org/issue/3253.
|
// See https://golang.org/issue/3253.
|
||||||
|
|
@ -3042,19 +3083,24 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
|
||||||
// -no-pie must be passed when doing a partial link with -Wl,-r. But -no-pie is
|
// -no-pie must be passed when doing a partial link with -Wl,-r. But -no-pie is
|
||||||
// not supported by all compilers.
|
// not supported by all compilers.
|
||||||
func (b *builder) gccSupportsNoPie() bool {
|
func (b *builder) gccSupportsNoPie() bool {
|
||||||
if goos != "linux" {
|
return b.gccSupportsFlag("-no-pie")
|
||||||
// On some BSD platforms, error messages from the
|
}
|
||||||
// compiler make it to the console despite cmd.Std*
|
|
||||||
// all being nil. As -no-pie is only required on linux
|
// gccSupportsFlag checks to see if the compiler supports a flag.
|
||||||
// systems so far, we only test there.
|
func (b *builder) gccSupportsFlag(flag string) bool {
|
||||||
return false
|
b.exec.Lock()
|
||||||
|
defer b.exec.Unlock()
|
||||||
|
if b, ok := b.flagCache[flag]; ok {
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
src := filepath.Join(b.work, "trivial.c")
|
if b.flagCache == nil {
|
||||||
if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
|
src := filepath.Join(b.work, "trivial.c")
|
||||||
return false
|
if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
b.flagCache = make(map[string]bool)
|
||||||
}
|
}
|
||||||
cmdArgs := b.gccCmd(b.work)
|
cmdArgs := append(envList("CC", defaultCC), flag, "-c", "trivial.c")
|
||||||
cmdArgs = append(cmdArgs, "-no-pie", "-c", "trivial.c")
|
|
||||||
if buildN || buildX {
|
if buildN || buildX {
|
||||||
b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs))
|
b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs))
|
||||||
if buildN {
|
if buildN {
|
||||||
|
|
@ -3063,9 +3109,11 @@ func (b *builder) gccSupportsNoPie() bool {
|
||||||
}
|
}
|
||||||
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
||||||
cmd.Dir = b.work
|
cmd.Dir = b.work
|
||||||
cmd.Env = envForDir(cmd.Dir, os.Environ())
|
cmd.Env = mergeEnvLists([]string{"LC_ALL=C"}, envForDir(cmd.Dir, os.Environ()))
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
return err == nil && !bytes.Contains(out, []byte("unrecognized"))
|
supported := err == nil && !bytes.Contains(out, []byte("unrecognized"))
|
||||||
|
b.flagCache[flag] = supported
|
||||||
|
return supported
|
||||||
}
|
}
|
||||||
|
|
||||||
// gccArchArgs returns arguments to pass to gcc based on the architecture.
|
// gccArchArgs returns arguments to pass to gcc based on the architecture.
|
||||||
|
|
@ -3077,6 +3125,10 @@ func (b *builder) gccArchArgs() []string {
|
||||||
return []string{"-m64"}
|
return []string{"-m64"}
|
||||||
case "arm":
|
case "arm":
|
||||||
return []string{"-marm"} // not thumb
|
return []string{"-marm"} // not thumb
|
||||||
|
case "s390x":
|
||||||
|
return []string{"-m64", "-march=z196"}
|
||||||
|
case "mips64", "mips64le":
|
||||||
|
return []string{"-mabi=64"}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -3091,8 +3143,8 @@ func envList(key, def string) []string {
|
||||||
return strings.Fields(v)
|
return strings.Fields(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the flags to use when invoking the C or C++ compilers, or cgo.
|
// Return the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
|
||||||
func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {
|
func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
|
||||||
var defaults string
|
var defaults string
|
||||||
if def {
|
if def {
|
||||||
defaults = "-g -O2"
|
defaults = "-g -O2"
|
||||||
|
|
@ -3101,15 +3153,16 @@ func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldfl
|
||||||
cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
|
cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
|
||||||
cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
|
cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
|
||||||
cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
|
cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
|
||||||
|
fflags = stringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
|
||||||
ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
|
ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgoRe = regexp.MustCompile(`[/\\:]`)
|
var cgoRe = regexp.MustCompile(`[/\\:]`)
|
||||||
|
|
||||||
func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
|
func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
|
||||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true)
|
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.cflags(p, true)
|
||||||
_, cgoexeCFLAGS, _, _ := b.cflags(p, false)
|
_, cgoexeCFLAGS, _, _, _ := b.cflags(p, false)
|
||||||
cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
|
cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
|
||||||
cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
|
cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
|
||||||
// If we are compiling Objective-C code, then we need to link against libobjc
|
// If we are compiling Objective-C code, then we need to link against libobjc
|
||||||
|
|
@ -3117,6 +3170,19 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
|
||||||
cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
|
cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Likewise for Fortran, except there are many Fortran compilers.
|
||||||
|
// Support gfortran out of the box and let others pass the correct link options
|
||||||
|
// via CGO_LDFLAGS
|
||||||
|
if len(ffiles) > 0 {
|
||||||
|
fc := os.Getenv("FC")
|
||||||
|
if fc == "" {
|
||||||
|
fc = "gfortran"
|
||||||
|
}
|
||||||
|
if strings.Contains(fc, "gfortran") {
|
||||||
|
cgoLDFLAGS = append(cgoLDFLAGS, "-lgfortran")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if buildMSan && p.ImportPath != "runtime/cgo" {
|
if buildMSan && p.ImportPath != "runtime/cgo" {
|
||||||
cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
|
cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
|
||||||
cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
|
cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
|
||||||
|
|
@ -3221,7 +3287,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
|
||||||
case strings.HasPrefix(f, "-fsanitize="):
|
case strings.HasPrefix(f, "-fsanitize="):
|
||||||
continue
|
continue
|
||||||
// runpath flags not applicable unless building a shared
|
// runpath flags not applicable unless building a shared
|
||||||
// object or executable; see issue 12115 for details. This
|
// object or executable; see issue 12115 for details. This
|
||||||
// is necessary as Go currently does not offer a way to
|
// is necessary as Go currently does not offer a way to
|
||||||
// specify the set of LDFLAGS that only apply to shared
|
// specify the set of LDFLAGS that only apply to shared
|
||||||
// objects.
|
// objects.
|
||||||
|
|
@ -3284,6 +3350,17 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
|
||||||
outObj = append(outObj, ofile)
|
outObj = append(outObj, ofile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fflags := stringList(cgoCPPFLAGS, cgoFFLAGS)
|
||||||
|
for _, file := range ffiles {
|
||||||
|
// Append .o to the file, just in case the pkg has file.c and file.f
|
||||||
|
ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
|
||||||
|
if err := b.gfortran(p, ofile, fflags, file); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
linkobj = append(linkobj, ofile)
|
||||||
|
outObj = append(outObj, ofile)
|
||||||
|
}
|
||||||
|
|
||||||
linkobj = append(linkobj, p.SysoFiles...)
|
linkobj = append(linkobj, p.SysoFiles...)
|
||||||
dynobj := obj + "_cgo_.o"
|
dynobj := obj + "_cgo_.o"
|
||||||
pie := (goarch == "arm" && goos == "linux") || goos == "android"
|
pie := (goarch == "arm" && goos == "linux") || goos == "android"
|
||||||
|
|
@ -3449,6 +3526,13 @@ func (b *builder) swigVersionCheck() error {
|
||||||
return swigCheck
|
return swigCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the value to pass for the -intgosize option to swig.
|
||||||
|
var (
|
||||||
|
swigIntSizeOnce sync.Once
|
||||||
|
swigIntSize string
|
||||||
|
swigIntSizeError error
|
||||||
|
)
|
||||||
|
|
||||||
// This code fails to build if sizeof(int) <= 32
|
// This code fails to build if sizeof(int) <= 32
|
||||||
const swigIntSizeCode = `
|
const swigIntSizeCode = `
|
||||||
package main
|
package main
|
||||||
|
|
@ -3456,8 +3540,8 @@ const i int = 1 << 32
|
||||||
`
|
`
|
||||||
|
|
||||||
// Determine the size of int on the target system for the -intgosize option
|
// Determine the size of int on the target system for the -intgosize option
|
||||||
// of swig >= 2.0.9
|
// of swig >= 2.0.9. Run only once.
|
||||||
func (b *builder) swigIntSize(obj string) (intsize string, err error) {
|
func (b *builder) swigDoIntSize(obj string) (intsize string, err error) {
|
||||||
if buildN {
|
if buildN {
|
||||||
return "$INTBITS", nil
|
return "$INTBITS", nil
|
||||||
}
|
}
|
||||||
|
|
@ -3475,9 +3559,18 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
|
||||||
return "64", nil
|
return "64", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine the size of int on the target system for the -intgosize option
|
||||||
|
// of swig >= 2.0.9.
|
||||||
|
func (b *builder) swigIntSize(obj string) (intsize string, err error) {
|
||||||
|
swigIntSizeOnce.Do(func() {
|
||||||
|
swigIntSize, swigIntSizeError = b.swigDoIntSize(obj)
|
||||||
|
})
|
||||||
|
return swigIntSize, swigIntSizeError
|
||||||
|
}
|
||||||
|
|
||||||
// Run SWIG on one SWIG input file.
|
// Run SWIG on one SWIG input file.
|
||||||
func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
|
func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
|
||||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true)
|
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.cflags(p, true)
|
||||||
var cflags []string
|
var cflags []string
|
||||||
if cxx {
|
if cxx {
|
||||||
cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
|
cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
|
||||||
|
|
@ -3545,12 +3638,12 @@ func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx b
|
||||||
|
|
||||||
// disableBuildID adjusts a linker command line to avoid creating a
|
// disableBuildID adjusts a linker command line to avoid creating a
|
||||||
// build ID when creating an object file rather than an executable or
|
// build ID when creating an object file rather than an executable or
|
||||||
// shared library. Some systems, such as Ubuntu, always add
|
// shared library. Some systems, such as Ubuntu, always add
|
||||||
// --build-id to every link, but we don't want a build ID when we are
|
// --build-id to every link, but we don't want a build ID when we are
|
||||||
// producing an object file. On some of those system a plain -r (not
|
// producing an object file. On some of those system a plain -r (not
|
||||||
// -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a
|
// -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a
|
||||||
// plain -r. I don't know how to turn off --build-id when using clang
|
// plain -r. I don't know how to turn off --build-id when using clang
|
||||||
// other than passing a trailing --build-id=none. So that is what we
|
// other than passing a trailing --build-id=none. So that is what we
|
||||||
// do, but only on systems likely to support it, which is to say,
|
// do, but only on systems likely to support it, which is to say,
|
||||||
// systems that normally use gold or the GNU linker.
|
// systems that normally use gold or the GNU linker.
|
||||||
func (b *builder) disableBuildID(ldflags []string) []string {
|
func (b *builder) disableBuildID(ldflags []string) []string {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -26,6 +26,7 @@ func newContext(c *build.Context) *Context {
|
||||||
GOARCH: c.GOARCH,
|
GOARCH: c.GOARCH,
|
||||||
GOOS: c.GOOS,
|
GOOS: c.GOOS,
|
||||||
GOROOT: c.GOROOT,
|
GOROOT: c.GOROOT,
|
||||||
|
GOPATH: c.GOPATH,
|
||||||
CgoEnabled: c.CgoEnabled,
|
CgoEnabled: c.CgoEnabled,
|
||||||
UseAllFiles: c.UseAllFiles,
|
UseAllFiles: c.UseAllFiles,
|
||||||
Compiler: c.Compiler,
|
Compiler: c.Compiler,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:generate ./mkalldocs.sh
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
var cmdDoc = &Command{
|
var cmdDoc = &Command{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -33,11 +33,6 @@ func mkEnv() []envVar {
|
||||||
var b builder
|
var b builder
|
||||||
b.init()
|
b.init()
|
||||||
|
|
||||||
vendorExpValue := "0"
|
|
||||||
if go15VendorExperiment {
|
|
||||||
vendorExpValue = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
env := []envVar{
|
env := []envVar{
|
||||||
{"GOARCH", goarch},
|
{"GOARCH", goarch},
|
||||||
{"GOBIN", gobin},
|
{"GOBIN", gobin},
|
||||||
|
|
@ -49,7 +44,6 @@ func mkEnv() []envVar {
|
||||||
{"GORACE", os.Getenv("GORACE")},
|
{"GORACE", os.Getenv("GORACE")},
|
||||||
{"GOROOT", goroot},
|
{"GOROOT", goroot},
|
||||||
{"GOTOOLDIR", toolDir},
|
{"GOTOOLDIR", toolDir},
|
||||||
{"GO15VENDOREXPERIMENT", vendorExpValue},
|
|
||||||
|
|
||||||
// disable escape codes in clang errors
|
// disable escape codes in clang errors
|
||||||
{"TERM", "dumb"},
|
{"TERM", "dumb"},
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -14,10 +14,8 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdGenerate = &Command{
|
var cmdGenerate = &Command{
|
||||||
|
|
@ -277,8 +275,8 @@ func isGoGenerate(buf []byte) bool {
|
||||||
// single go:generate command.
|
// single go:generate command.
|
||||||
func (g *Generator) setEnv() {
|
func (g *Generator) setEnv() {
|
||||||
g.env = []string{
|
g.env = []string{
|
||||||
"GOARCH=" + runtime.GOARCH,
|
"GOARCH=" + buildContext.GOARCH,
|
||||||
"GOOS=" + runtime.GOOS,
|
"GOOS=" + buildContext.GOOS,
|
||||||
"GOFILE=" + g.file,
|
"GOFILE=" + g.file,
|
||||||
"GOLINE=" + strconv.Itoa(g.lineNum),
|
"GOLINE=" + strconv.Itoa(g.lineNum),
|
||||||
"GOPACKAGE=" + g.pkg,
|
"GOPACKAGE=" + g.pkg,
|
||||||
|
|
@ -371,17 +369,6 @@ func (g *Generator) expandVar(word string) string {
|
||||||
return os.Getenv(word)
|
return os.Getenv(word)
|
||||||
}
|
}
|
||||||
|
|
||||||
// identLength returns the length of the identifier beginning the string.
|
|
||||||
func (g *Generator) identLength(word string) int {
|
|
||||||
for i, r := range word {
|
|
||||||
if r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
return len(word)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setShorthand installs a new shorthand as defined by a -command directive.
|
// setShorthand installs a new shorthand as defined by a -command directive.
|
||||||
func (g *Generator) setShorthand(words []string) {
|
func (g *Generator) setShorthand(words []string) {
|
||||||
// Create command shorthand.
|
// Create command shorthand.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -19,8 +19,8 @@ var cmdGet = &Command{
|
||||||
UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]",
|
UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]",
|
||||||
Short: "download and install packages and dependencies",
|
Short: "download and install packages and dependencies",
|
||||||
Long: `
|
Long: `
|
||||||
Get downloads and installs the packages named by the import paths,
|
Get downloads the packages named by the import paths, along with their
|
||||||
along with their dependencies.
|
dependencies. It then installs the named packages, like 'go install'.
|
||||||
|
|
||||||
The -d flag instructs get to stop after downloading the packages; that is,
|
The -d flag instructs get to stop after downloading the packages; that is,
|
||||||
it instructs get not to install the packages.
|
it instructs get not to install the packages.
|
||||||
|
|
@ -45,7 +45,7 @@ missing packages but does not use it to look for updates to existing packages.
|
||||||
|
|
||||||
Get also accepts build flags to control the installation. See 'go help build'.
|
Get also accepts build flags to control the installation. See 'go help build'.
|
||||||
|
|
||||||
When checking out a new package, get creates the target directory
|
When checking out a new package, get creates the target directory
|
||||||
GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
|
GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
|
||||||
get uses the first one. See 'go help gopath'.
|
get uses the first one. See 'go help gopath'.
|
||||||
|
|
||||||
|
|
@ -55,8 +55,7 @@ rule is that if the local installation is running version "go1", get
|
||||||
searches for a branch or tag named "go1". If no such version exists it
|
searches for a branch or tag named "go1". If no such version exists it
|
||||||
retrieves the most recent version of the package.
|
retrieves the most recent version of the package.
|
||||||
|
|
||||||
Unless vendoring support is disabled (see 'go help gopath'),
|
When go get checks out or updates a Git repository,
|
||||||
when go get checks out or updates a Git repository,
|
|
||||||
it also updates any git submodules referenced by the repository.
|
it also updates any git submodules referenced by the repository.
|
||||||
|
|
||||||
Get never checks out or updates code stored in vendor directories.
|
Get never checks out or updates code stored in vendor directories.
|
||||||
|
|
@ -112,13 +111,21 @@ func runGet(cmd *Command, args []string) {
|
||||||
|
|
||||||
// Code we downloaded and all code that depends on it
|
// Code we downloaded and all code that depends on it
|
||||||
// needs to be evicted from the package cache so that
|
// needs to be evicted from the package cache so that
|
||||||
// the information will be recomputed. Instead of keeping
|
// the information will be recomputed. Instead of keeping
|
||||||
// track of the reverse dependency information, evict
|
// track of the reverse dependency information, evict
|
||||||
// everything.
|
// everything.
|
||||||
for name := range packageCache {
|
for name := range packageCache {
|
||||||
delete(packageCache, name)
|
delete(packageCache, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In order to rebuild packages information completely,
|
||||||
|
// we need to clear commands cache. Command packages are
|
||||||
|
// referring to evicted packages from the package cache.
|
||||||
|
// This leads to duplicated loads of the standard packages.
|
||||||
|
for name := range cmdCache {
|
||||||
|
delete(cmdCache, name)
|
||||||
|
}
|
||||||
|
|
||||||
args = importPaths(args)
|
args = importPaths(args)
|
||||||
packagesForBuild(args)
|
packagesForBuild(args)
|
||||||
|
|
||||||
|
|
@ -134,7 +141,7 @@ func runGet(cmd *Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// downloadPaths prepares the list of paths to pass to download.
|
// downloadPaths prepares the list of paths to pass to download.
|
||||||
// It expands ... patterns that can be expanded. If there is no match
|
// It expands ... patterns that can be expanded. If there is no match
|
||||||
// for a particular pattern, downloadPaths leaves it in the result list,
|
// for a particular pattern, downloadPaths leaves it in the result list,
|
||||||
// in the hope that we can figure out the repository from the
|
// in the hope that we can figure out the repository from the
|
||||||
// initial ...-free prefix.
|
// initial ...-free prefix.
|
||||||
|
|
@ -145,7 +152,7 @@ func downloadPaths(args []string) []string {
|
||||||
if strings.Contains(a, "...") {
|
if strings.Contains(a, "...") {
|
||||||
var expand []string
|
var expand []string
|
||||||
// Use matchPackagesInFS to avoid printing
|
// Use matchPackagesInFS to avoid printing
|
||||||
// warnings. They will be printed by the
|
// warnings. They will be printed by the
|
||||||
// eventual call to importPaths instead.
|
// eventual call to importPaths instead.
|
||||||
if build.IsLocalImport(a) {
|
if build.IsLocalImport(a) {
|
||||||
expand = matchPackagesInFS(a)
|
expand = matchPackagesInFS(a)
|
||||||
|
|
@ -228,16 +235,6 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
|
||||||
stk.pop()
|
stk.pop()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn that code.google.com is shutting down. We
|
|
||||||
// issue the warning here because this is where we
|
|
||||||
// have the import stack.
|
|
||||||
if strings.HasPrefix(p.ImportPath, "code.google.com") {
|
|
||||||
fmt.Fprintf(os.Stderr, "warning: code.google.com is shutting down; import path %v will stop working\n", p.ImportPath)
|
|
||||||
if len(*stk) > 1 {
|
|
||||||
fmt.Fprintf(os.Stderr, "warning: package %v\n", strings.Join(*stk, "\n\timports "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stk.pop()
|
stk.pop()
|
||||||
|
|
||||||
args := []string{arg}
|
args := []string{arg}
|
||||||
|
|
@ -347,8 +344,8 @@ func downloadPackage(p *Package) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.build.SrcRoot != "" {
|
if p.build.SrcRoot != "" {
|
||||||
// Directory exists. Look for checkout along path to src.
|
// Directory exists. Look for checkout along path to src.
|
||||||
vcs, rootPath, err = vcsForDir(p)
|
vcs, rootPath, err = vcsFromDir(p.Dir, p.build.SrcRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +353,7 @@ func downloadPackage(p *Package) error {
|
||||||
|
|
||||||
// Double-check where it came from.
|
// Double-check where it came from.
|
||||||
if *getU && vcs.remoteRepo != nil {
|
if *getU && vcs.remoteRepo != nil {
|
||||||
dir := filepath.Join(p.build.SrcRoot, rootPath)
|
dir := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
|
||||||
remote, err := vcs.remoteRepo(vcs, dir)
|
remote, err := vcs.remoteRepo(vcs, dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -391,7 +388,7 @@ func downloadPackage(p *Package) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.build.SrcRoot == "" {
|
if p.build.SrcRoot == "" {
|
||||||
// Package not found. Put in first directory of $GOPATH.
|
// Package not found. Put in first directory of $GOPATH.
|
||||||
list := filepath.SplitList(buildContext.GOPATH)
|
list := filepath.SplitList(buildContext.GOPATH)
|
||||||
if len(list) == 0 {
|
if len(list) == 0 {
|
||||||
return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath")
|
return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath")
|
||||||
|
|
@ -403,7 +400,7 @@ func downloadPackage(p *Package) error {
|
||||||
p.build.SrcRoot = filepath.Join(list[0], "src")
|
p.build.SrcRoot = filepath.Join(list[0], "src")
|
||||||
p.build.PkgRoot = filepath.Join(list[0], "pkg")
|
p.build.PkgRoot = filepath.Join(list[0], "pkg")
|
||||||
}
|
}
|
||||||
root := filepath.Join(p.build.SrcRoot, rootPath)
|
root := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
|
||||||
// If we've considered this repository already, don't do it again.
|
// If we've considered this repository already, don't do it again.
|
||||||
if downloadRootCache[root] {
|
if downloadRootCache[root] {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -422,7 +419,7 @@ func downloadPackage(p *Package) error {
|
||||||
return fmt.Errorf("%s exists but is not a directory", meta)
|
return fmt.Errorf("%s exists but is not a directory", meta)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Metadata directory does not exist. Prepare to checkout new copy.
|
// Metadata directory does not exist. Prepare to checkout new copy.
|
||||||
// Some version control tools require the target directory not to exist.
|
// Some version control tools require the target directory not to exist.
|
||||||
// We require that too, just to avoid stepping on existing work.
|
// We require that too, just to avoid stepping on existing work.
|
||||||
if _, err := os.Stat(root); err == nil {
|
if _, err := os.Stat(root); err == nil {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ func TestMain(m *testing.M) {
|
||||||
os.Exit(r)
|
os.Exit(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The length of an mtime tick on this system. This is an estimate of
|
// The length of an mtime tick on this system. This is an estimate of
|
||||||
// how long we need to sleep to ensure that the mtime of two files is
|
// how long we need to sleep to ensure that the mtime of two files is
|
||||||
// different.
|
// different.
|
||||||
// We used to try to be clever but that didn't always work (see golang.org/issue/12205).
|
// We used to try to be clever but that didn't always work (see golang.org/issue/12205).
|
||||||
|
|
@ -181,7 +181,7 @@ func (tg *testgoData) pwd() string {
|
||||||
return wd
|
return wd
|
||||||
}
|
}
|
||||||
|
|
||||||
// cd changes the current directory to the named directory. Note that
|
// cd changes the current directory to the named directory. Note that
|
||||||
// using this means that the test must not be run in parallel with any
|
// using this means that the test must not be run in parallel with any
|
||||||
// other tests.
|
// other tests.
|
||||||
func (tg *testgoData) cd(dir string) {
|
func (tg *testgoData) cd(dir string) {
|
||||||
|
|
@ -325,7 +325,7 @@ func (tg *testgoData) getStderr() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// doGrepMatch looks for a regular expression in a buffer, and returns
|
// doGrepMatch looks for a regular expression in a buffer, and returns
|
||||||
// whether it is found. The regular expression is matched against
|
// whether it is found. The regular expression is matched against
|
||||||
// each line separately, as with the grep command.
|
// each line separately, as with the grep command.
|
||||||
func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
|
func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
|
||||||
if !tg.ran {
|
if !tg.ran {
|
||||||
|
|
@ -341,7 +341,7 @@ func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// doGrep looks for a regular expression in a buffer and fails if it
|
// doGrep looks for a regular expression in a buffer and fails if it
|
||||||
// is not found. The name argument is the name of the output we are
|
// is not found. The name argument is the name of the output we are
|
||||||
// searching, "output" or "error". The msg argument is logged on
|
// searching, "output" or "error". The msg argument is logged on
|
||||||
// failure.
|
// failure.
|
||||||
func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
|
func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
|
||||||
|
|
@ -375,7 +375,7 @@ func (tg *testgoData) grepBoth(match, msg string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// doGrepNot looks for a regular expression in a buffer and fails if
|
// doGrepNot looks for a regular expression in a buffer and fails if
|
||||||
// it is found. The name and msg arguments are as for doGrep.
|
// it is found. The name and msg arguments are as for doGrep.
|
||||||
func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
|
func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
|
||||||
if tg.doGrepMatch(match, b) {
|
if tg.doGrepMatch(match, b) {
|
||||||
tg.t.Log(msg)
|
tg.t.Log(msg)
|
||||||
|
|
@ -421,18 +421,6 @@ func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// grepCountStdout returns the number of times a regexp is seen in
|
|
||||||
// standard output.
|
|
||||||
func (tg *testgoData) grepCountStdout(match string) int {
|
|
||||||
return tg.doGrepCount(match, &tg.stdout)
|
|
||||||
}
|
|
||||||
|
|
||||||
// grepCountStderr returns the number of times a regexp is seen in
|
|
||||||
// standard error.
|
|
||||||
func (tg *testgoData) grepCountStderr(match string) int {
|
|
||||||
return tg.doGrepCount(match, &tg.stderr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// grepCountBoth returns the number of times a regexp is seen in both
|
// grepCountBoth returns the number of times a regexp is seen in both
|
||||||
// standard output and standard error.
|
// standard output and standard error.
|
||||||
func (tg *testgoData) grepCountBoth(match string) int {
|
func (tg *testgoData) grepCountBoth(match string) int {
|
||||||
|
|
@ -440,8 +428,8 @@ func (tg *testgoData) grepCountBoth(match string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// creatingTemp records that the test plans to create a temporary file
|
// creatingTemp records that the test plans to create a temporary file
|
||||||
// or directory. If the file or directory exists already, it will be
|
// or directory. If the file or directory exists already, it will be
|
||||||
// removed. When the test completes, the file or directory will be
|
// removed. When the test completes, the file or directory will be
|
||||||
// removed if it exists.
|
// removed if it exists.
|
||||||
func (tg *testgoData) creatingTemp(path string) {
|
func (tg *testgoData) creatingTemp(path string) {
|
||||||
if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
|
if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
|
||||||
|
|
@ -457,7 +445,7 @@ func (tg *testgoData) creatingTemp(path string) {
|
||||||
tg.temps = append(tg.temps, path)
|
tg.temps = append(tg.temps, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeTempdir makes a temporary directory for a run of testgo. If
|
// makeTempdir makes a temporary directory for a run of testgo. If
|
||||||
// the temporary directory was already created, this does nothing.
|
// the temporary directory was already created, this does nothing.
|
||||||
func (tg *testgoData) makeTempdir() {
|
func (tg *testgoData) makeTempdir() {
|
||||||
if tg.tempdir == "" {
|
if tg.tempdir == "" {
|
||||||
|
|
@ -501,6 +489,16 @@ func (tg *testgoData) path(name string) string {
|
||||||
return filepath.Join(tg.tempdir, name)
|
return filepath.Join(tg.tempdir, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mustExist fails if path does not exist.
|
||||||
|
func (tg *testgoData) mustExist(path string) {
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
tg.t.Fatalf("%s does not exist but should", path)
|
||||||
|
}
|
||||||
|
tg.t.Fatalf("%s stat failed: %v", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// mustNotExist fails if path exists.
|
// mustNotExist fails if path exists.
|
||||||
func (tg *testgoData) mustNotExist(path string) {
|
func (tg *testgoData) mustNotExist(path string) {
|
||||||
if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
|
if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
|
||||||
|
|
@ -536,32 +534,43 @@ func (tg *testgoData) wantArchive(path string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isStale returns whether pkg is stale.
|
// isStale reports whether pkg is stale, and why
|
||||||
func (tg *testgoData) isStale(pkg string) bool {
|
func (tg *testgoData) isStale(pkg string) (bool, string) {
|
||||||
tg.run("list", "-f", "{{.Stale}}", pkg)
|
tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
|
||||||
switch v := strings.TrimSpace(tg.getStdout()); v {
|
v := strings.TrimSpace(tg.getStdout())
|
||||||
case "true":
|
f := strings.SplitN(v, ":", 2)
|
||||||
return true
|
if len(f) == 2 {
|
||||||
case "false":
|
switch f[0] {
|
||||||
return false
|
case "true":
|
||||||
default:
|
return true, f[1]
|
||||||
tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
|
case "false":
|
||||||
panic("unreachable")
|
return false, f[1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
|
||||||
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
// wantStale fails with msg if pkg is not stale.
|
// wantStale fails with msg if pkg is not stale.
|
||||||
func (tg *testgoData) wantStale(pkg, msg string) {
|
func (tg *testgoData) wantStale(pkg, reason, msg string) {
|
||||||
if !tg.isStale(pkg) {
|
stale, why := tg.isStale(pkg)
|
||||||
|
if !stale {
|
||||||
tg.t.Fatal(msg)
|
tg.t.Fatal(msg)
|
||||||
}
|
}
|
||||||
|
if reason == "" && why != "" || !strings.Contains(why, reason) {
|
||||||
|
tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// wantNotStale fails with msg if pkg is stale.
|
// wantNotStale fails with msg if pkg is stale.
|
||||||
func (tg *testgoData) wantNotStale(pkg, msg string) {
|
func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
|
||||||
if tg.isStale(pkg) {
|
stale, why := tg.isStale(pkg)
|
||||||
|
if stale {
|
||||||
tg.t.Fatal(msg)
|
tg.t.Fatal(msg)
|
||||||
}
|
}
|
||||||
|
if reason == "" && why != "" || !strings.Contains(why, reason) {
|
||||||
|
tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanup cleans up a test that runs testgo.
|
// cleanup cleans up a test that runs testgo.
|
||||||
|
|
@ -581,32 +590,6 @@ func (tg *testgoData) cleanup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resetReadOnlyFlagAll resets windows read-only flag
|
|
||||||
// set on path and any children it contains.
|
|
||||||
// The flag is set by git and has to be removed.
|
|
||||||
// os.Remove refuses to remove files with read-only flag set.
|
|
||||||
func (tg *testgoData) resetReadOnlyFlagAll(path string) {
|
|
||||||
fi, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
tg.t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
|
|
||||||
}
|
|
||||||
if !fi.IsDir() {
|
|
||||||
err := os.Chmod(path, 0666)
|
|
||||||
if err != nil {
|
|
||||||
tg.t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fd, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
tg.t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
|
|
||||||
}
|
|
||||||
defer fd.Close()
|
|
||||||
names, _ := fd.Readdirnames(-1)
|
|
||||||
for _, name := range names {
|
|
||||||
tg.resetReadOnlyFlagAll(path + string(filepath.Separator) + name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// failSSH puts an ssh executable in the PATH that always fails.
|
// failSSH puts an ssh executable in the PATH that always fails.
|
||||||
// This is to stub out uses of ssh by go get.
|
// This is to stub out uses of ssh by go get.
|
||||||
func (tg *testgoData) failSSH() {
|
func (tg *testgoData) failSSH() {
|
||||||
|
|
@ -720,7 +703,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
||||||
tg.tempFile("d1/src/p1/p1.go", `package p1`)
|
tg.tempFile("d1/src/p1/p1.go", `package p1`)
|
||||||
tg.setenv("GOPATH", tg.path("d1"))
|
tg.setenv("GOPATH", tg.path("d1"))
|
||||||
tg.run("install", "-a", "p1")
|
tg.run("install", "-a", "p1")
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly")
|
||||||
tg.sleep()
|
tg.sleep()
|
||||||
|
|
||||||
// Changing mtime and content of runtime/internal/sys/sys.go
|
// Changing mtime and content of runtime/internal/sys/sys.go
|
||||||
|
|
@ -729,28 +712,28 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
||||||
sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go"
|
sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go"
|
||||||
restore := addNL(sys)
|
restore := addNL(sys)
|
||||||
defer restore()
|
defer restore()
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after updating runtime/internal/sys/sys.go")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating runtime/internal/sys/sys.go")
|
||||||
restore()
|
restore()
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after restoring runtime/internal/sys/sys.go")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after restoring runtime/internal/sys/sys.go")
|
||||||
|
|
||||||
// But changing runtime/internal/sys/zversion.go should have an effect:
|
// But changing runtime/internal/sys/zversion.go should have an effect:
|
||||||
// that's how we tell when we flip from one release to another.
|
// that's how we tell when we flip from one release to another.
|
||||||
zversion := runtime.GOROOT() + "/src/runtime/internal/sys/zversion.go"
|
zversion := runtime.GOROOT() + "/src/runtime/internal/sys/zversion.go"
|
||||||
restore = addNL(zversion)
|
restore = addNL(zversion)
|
||||||
defer restore()
|
defer restore()
|
||||||
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to new release")
|
tg.wantStale("p1", "build ID mismatch", "./testgo list claims p1 is NOT stale, incorrectly, after changing to new release")
|
||||||
restore()
|
restore()
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
|
||||||
addNL(zversion)
|
addNL(zversion)
|
||||||
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing again to new release")
|
tg.wantStale("p1", "build ID mismatch", "./testgo list claims p1 is NOT stale, incorrectly, after changing again to new release")
|
||||||
tg.run("install", "p1")
|
tg.run("install", "p1")
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with new release")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
|
||||||
|
|
||||||
// Restore to "old" release.
|
// Restore to "old" release.
|
||||||
restore()
|
restore()
|
||||||
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to old release after new build")
|
tg.wantStale("p1", "build ID mismatch", "./testgo list claims p1 is NOT stale, incorrectly, after changing to old release after new build")
|
||||||
tg.run("install", "p1")
|
tg.run("install", "p1")
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with old release")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
|
||||||
|
|
||||||
// Everything is out of date. Rebuild to leave things in a better state.
|
// Everything is out of date. Rebuild to leave things in a better state.
|
||||||
tg.run("install", "std")
|
tg.run("install", "std")
|
||||||
|
|
@ -833,8 +816,8 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
|
||||||
sep := string(filepath.ListSeparator)
|
sep := string(filepath.ListSeparator)
|
||||||
tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2"))
|
tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2"))
|
||||||
tg.run("install", "p1")
|
tg.run("install", "p1")
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly")
|
||||||
tg.wantNotStale("p2", "./testgo list claims p2 is stale, incorrectly")
|
tg.wantNotStale("p2", "", "./testgo list claims p2 is stale, incorrectly")
|
||||||
tg.sleep()
|
tg.sleep()
|
||||||
if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil {
|
if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -843,12 +826,12 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
|
||||||
} else {
|
} else {
|
||||||
tg.must(f.Close())
|
tg.must(f.Close())
|
||||||
}
|
}
|
||||||
tg.wantStale("p2", "./testgo list claims p2 is NOT stale, incorrectly")
|
tg.wantStale("p2", "newer source file", "./testgo list claims p2 is NOT stale, incorrectly")
|
||||||
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly")
|
tg.wantStale("p1", "stale dependency", "./testgo list claims p1 is NOT stale, incorrectly")
|
||||||
|
|
||||||
tg.run("install", "p1")
|
tg.run("install", "p1")
|
||||||
tg.wantNotStale("p2", "./testgo list claims p2 is stale after reinstall, incorrectly")
|
tg.wantNotStale("p2", "", "./testgo list claims p2 is stale after reinstall, incorrectly")
|
||||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale after reinstall, incorrectly")
|
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after reinstall, incorrectly")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoInstallDetectsRemovedFiles(t *testing.T) {
|
func TestGoInstallDetectsRemovedFiles(t *testing.T) {
|
||||||
|
|
@ -862,13 +845,13 @@ func TestGoInstallDetectsRemovedFiles(t *testing.T) {
|
||||||
package mypkg`)
|
package mypkg`)
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.run("install", "mypkg")
|
tg.run("install", "mypkg")
|
||||||
tg.wantNotStale("mypkg", "./testgo list mypkg claims mypkg is stale, incorrectly")
|
tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale, incorrectly")
|
||||||
// z.go was not part of the build; removing it is okay.
|
// z.go was not part of the build; removing it is okay.
|
||||||
tg.must(os.Remove(tg.path("src/mypkg/z.go")))
|
tg.must(os.Remove(tg.path("src/mypkg/z.go")))
|
||||||
tg.wantNotStale("mypkg", "./testgo list mypkg claims mypkg is stale after removing z.go; should not be stale")
|
tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale after removing z.go; should not be stale")
|
||||||
// y.go was part of the package; removing it should be detected.
|
// y.go was part of the package; removing it should be detected.
|
||||||
tg.must(os.Remove(tg.path("src/mypkg/y.go")))
|
tg.must(os.Remove(tg.path("src/mypkg/y.go")))
|
||||||
tg.wantStale("mypkg", "./testgo list mypkg claims mypkg is NOT stale after removing y.go; should be stale")
|
tg.wantStale("mypkg", "build ID mismatch", "./testgo list mypkg claims mypkg is NOT stale after removing y.go; should be stale")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) {
|
func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) {
|
||||||
|
|
@ -931,13 +914,13 @@ func TestGoInstallDetectsRemovedFilesInPackageMain(t *testing.T) {
|
||||||
package main`)
|
package main`)
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.run("install", "mycmd")
|
tg.run("install", "mycmd")
|
||||||
tg.wantNotStale("mycmd", "./testgo list mypkg claims mycmd is stale, incorrectly")
|
tg.wantNotStale("mycmd", "", "./testgo list mypkg claims mycmd is stale, incorrectly")
|
||||||
// z.go was not part of the build; removing it is okay.
|
// z.go was not part of the build; removing it is okay.
|
||||||
tg.must(os.Remove(tg.path("src/mycmd/z.go")))
|
tg.must(os.Remove(tg.path("src/mycmd/z.go")))
|
||||||
tg.wantNotStale("mycmd", "./testgo list mycmd claims mycmd is stale after removing z.go; should not be stale")
|
tg.wantNotStale("mycmd", "", "./testgo list mycmd claims mycmd is stale after removing z.go; should not be stale")
|
||||||
// y.go was part of the package; removing it should be detected.
|
// y.go was part of the package; removing it should be detected.
|
||||||
tg.must(os.Remove(tg.path("src/mycmd/y.go")))
|
tg.must(os.Remove(tg.path("src/mycmd/y.go")))
|
||||||
tg.wantStale("mycmd", "./testgo list mycmd claims mycmd is NOT stale after removing y.go; should be stale")
|
tg.wantStale("mycmd", "build ID mismatch", "./testgo list mycmd claims mycmd is NOT stale after removing y.go; should be stale")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLocalRun(tg *testgoData, exepath, local, match string) {
|
func testLocalRun(tg *testgoData, exepath, local, match string) {
|
||||||
|
|
@ -1105,8 +1088,8 @@ func testMove(t *testing.T, vcs, url, base, config string) {
|
||||||
}
|
}
|
||||||
if vcs == "git" {
|
if vcs == "git" {
|
||||||
// git will ask for a username and password when we
|
// git will ask for a username and password when we
|
||||||
// run go get -d -f -u. An empty username and
|
// run go get -d -f -u. An empty username and
|
||||||
// password will work. Prevent asking by setting
|
// password will work. Prevent asking by setting
|
||||||
// GIT_ASKPASS.
|
// GIT_ASKPASS.
|
||||||
tg.creatingTemp("sink" + exeSuffix)
|
tg.creatingTemp("sink" + exeSuffix)
|
||||||
tg.tempFile("src/sink/sink.go", `package main; func main() {}`)
|
tg.tempFile("src/sink/sink.go", `package main; func main() {}`)
|
||||||
|
|
@ -1178,7 +1161,7 @@ func TestImportCommentConflict(t *testing.T) {
|
||||||
tg.grepStderr("found import comments", "go build did not mention comment conflict")
|
tg.grepStderr("found import comments", "go build did not mention comment conflict")
|
||||||
}
|
}
|
||||||
|
|
||||||
// cmd/go: custom import path checking should not apply to github.com/xxx/yyy.
|
// cmd/go: custom import path checking should not apply to Go packages without import comment.
|
||||||
func TestIssue10952(t *testing.T) {
|
func TestIssue10952(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
if _, err := exec.LookPath("git"); err != nil {
|
if _, err := exec.LookPath("git"); err != nil {
|
||||||
|
|
@ -1193,11 +1176,38 @@ func TestIssue10952(t *testing.T) {
|
||||||
const importPath = "github.com/zombiezen/go-get-issue-10952"
|
const importPath = "github.com/zombiezen/go-get-issue-10952"
|
||||||
tg.run("get", "-d", "-u", importPath)
|
tg.run("get", "-d", "-u", importPath)
|
||||||
repoDir := tg.path("src/" + importPath)
|
repoDir := tg.path("src/" + importPath)
|
||||||
defer tg.resetReadOnlyFlagAll(repoDir)
|
|
||||||
tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
|
tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
|
||||||
tg.run("get", "-d", "-u", importPath)
|
tg.run("get", "-d", "-u", importPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test git clone URL that uses SCP-like syntax and custom import path checking.
|
||||||
|
func TestIssue11457(t *testing.T) {
|
||||||
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
if _, err := exec.LookPath("git"); err != nil {
|
||||||
|
t.Skip("skipping because git binary not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
tg.tempDir("src")
|
||||||
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
|
const importPath = "github.com/rsc/go-get-issue-11457"
|
||||||
|
tg.run("get", "-d", "-u", importPath)
|
||||||
|
repoDir := tg.path("src/" + importPath)
|
||||||
|
tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457")
|
||||||
|
|
||||||
|
// At this time, custom import path checking compares remotes verbatim (rather than
|
||||||
|
// just the host and path, skipping scheme and user), so we expect go get -u to fail.
|
||||||
|
// However, the goal of this test is to verify that gitRemoteRepo correctly parsed
|
||||||
|
// the SCP-like syntax, and we expect it to appear in the error message.
|
||||||
|
tg.runFail("get", "-d", "-u", importPath)
|
||||||
|
want := " is checked out from ssh://git@github.com/rsc/go-get-issue-11457"
|
||||||
|
if !strings.HasSuffix(strings.TrimSpace(tg.getStderr()), want) {
|
||||||
|
t.Error("expected clone URL to appear in stderr")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetGitDefaultBranch(t *testing.T) {
|
func TestGetGitDefaultBranch(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
if _, err := exec.LookPath("git"); err != nil {
|
if _, err := exec.LookPath("git"); err != nil {
|
||||||
|
|
@ -1217,7 +1227,6 @@ func TestGetGitDefaultBranch(t *testing.T) {
|
||||||
|
|
||||||
tg.run("get", "-d", importPath)
|
tg.run("get", "-d", importPath)
|
||||||
repoDir := tg.path("src/" + importPath)
|
repoDir := tg.path("src/" + importPath)
|
||||||
defer tg.resetReadOnlyFlagAll(repoDir)
|
|
||||||
tg.runGit(repoDir, "branch", "--contains", "HEAD")
|
tg.runGit(repoDir, "branch", "--contains", "HEAD")
|
||||||
tg.grepStdout(`\* another-branch`, "not on correct default branch")
|
tg.grepStdout(`\* another-branch`, "not on correct default branch")
|
||||||
|
|
||||||
|
|
@ -1226,14 +1235,6 @@ func TestGetGitDefaultBranch(t *testing.T) {
|
||||||
tg.grepStdout(`\* another-branch`, "not on correct default branch")
|
tg.grepStdout(`\* another-branch`, "not on correct default branch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDisallowedCSourceFiles(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("build", "badc")
|
|
||||||
tg.grepStderr("C source files not allowed", "go test did not say C source files not allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
|
func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -1337,19 +1338,35 @@ func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
|
||||||
tg.sleep()
|
tg.sleep()
|
||||||
tg.run("test", "main_test")
|
tg.run("test", "main_test")
|
||||||
tg.run("install", "main_test")
|
tg.run("install", "main_test")
|
||||||
tg.wantNotStale("main_test", "after go install, main listed as stale")
|
tg.wantNotStale("main_test", "", "after go install, main listed as stale")
|
||||||
tg.run("test", "main_test")
|
tg.run("test", "main_test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The runtime version string takes one of two forms:
|
||||||
|
// "go1.X[.Y]" for Go releases, and "devel +hash" at tip.
|
||||||
|
// Determine whether we are in a released copy by
|
||||||
|
// inspecting the version.
|
||||||
|
var isGoRelease = strings.HasPrefix(runtime.Version(), "go1")
|
||||||
|
|
||||||
// Issue 12690
|
// Issue 12690
|
||||||
func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
|
func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
||||||
|
// Make sure the packages below are not stale.
|
||||||
|
tg.run("install", "runtime", "os", "io")
|
||||||
|
|
||||||
goroot := runtime.GOROOT()
|
goroot := runtime.GOROOT()
|
||||||
tg.setenv("GOROOT", goroot+"/")
|
tg.setenv("GOROOT", goroot+"/")
|
||||||
tg.wantNotStale("runtime", "with trailing slash in GOROOT, runtime listed as stale")
|
|
||||||
tg.wantNotStale("os", "with trailing slash in GOROOT, os listed as stale")
|
want := ""
|
||||||
tg.wantNotStale("io", "with trailing slash in GOROOT, io listed as stale")
|
if isGoRelease {
|
||||||
|
want = "standard package in Go release distribution"
|
||||||
|
}
|
||||||
|
|
||||||
|
tg.wantNotStale("runtime", want, "with trailing slash in GOROOT, runtime listed as stale")
|
||||||
|
tg.wantNotStale("os", want, "with trailing slash in GOROOT, os listed as stale")
|
||||||
|
tg.wantNotStale("io", want, "with trailing slash in GOROOT, io listed as stale")
|
||||||
}
|
}
|
||||||
|
|
||||||
// With $GOBIN set, binaries get installed to $GOBIN.
|
// With $GOBIN set, binaries get installed to $GOBIN.
|
||||||
|
|
@ -1397,28 +1414,6 @@ func TestInstallToGOBINCommandLinePackage(t *testing.T) {
|
||||||
tg.wantExecutable("testdata/bin1/helloworld"+exeSuffix, "go install testdata/src/go-cmd-test/helloworld.go did not write testdata/bin1/helloworld")
|
tg.wantExecutable("testdata/bin1/helloworld"+exeSuffix, "go install testdata/src/go-cmd-test/helloworld.go did not write testdata/bin1/helloworld")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGodocInstalls(t *testing.T) {
|
|
||||||
testenv.MustHaveExternalNetwork(t)
|
|
||||||
|
|
||||||
// godoc installs into GOBIN
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.parallel()
|
|
||||||
tg.tempDir("gobin")
|
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
|
||||||
tg.setenv("GOBIN", tg.path("gobin"))
|
|
||||||
tg.run("get", "golang.org/x/tools/cmd/godoc")
|
|
||||||
tg.wantExecutable(tg.path("gobin/godoc"), "did not install godoc to $GOBIN")
|
|
||||||
tg.unsetenv("GOBIN")
|
|
||||||
|
|
||||||
// godoc installs into GOROOT
|
|
||||||
goroot := runtime.GOROOT()
|
|
||||||
tg.setenv("GOROOT", goroot)
|
|
||||||
tg.check(os.RemoveAll(filepath.Join(goroot, "bin", "godoc")))
|
|
||||||
tg.run("install", "golang.org/x/tools/cmd/godoc")
|
|
||||||
tg.wantExecutable(filepath.Join(goroot, "bin", "godoc"), "did not install godoc to $GOROOT/bin")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoGetNonPkg(t *testing.T) {
|
func TestGoGetNonPkg(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
|
||||||
|
|
@ -1508,7 +1503,7 @@ func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.parallel()
|
tg.parallel()
|
||||||
tg.run("test", "errors", "errors", "errors", "errors", "errors")
|
tg.run("test", "errors", "errors", "errors", "errors", "errors")
|
||||||
if strings.Index(strings.TrimSpace(tg.getStdout()), "\n") != -1 {
|
if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
|
||||||
t.Error("go test errors errors errors errors errors tested the same package multiple times")
|
t.Error("go test errors errors errors errors errors tested the same package multiple times")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1537,7 +1532,7 @@ func TestGoListCmdOnlyShowsCommands(t *testing.T) {
|
||||||
tg.run("list", "cmd")
|
tg.run("list", "cmd")
|
||||||
out := strings.TrimSpace(tg.getStdout())
|
out := strings.TrimSpace(tg.getStdout())
|
||||||
for _, line := range strings.Split(out, "\n") {
|
for _, line := range strings.Split(out, "\n") {
|
||||||
if strings.Index(line, "cmd/") == -1 {
|
if !strings.Contains(line, "cmd/") {
|
||||||
t.Error("go list cmd shows non-commands")
|
t.Error("go list cmd shows non-commands")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -1657,8 +1652,8 @@ func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
|
||||||
func main() {
|
func main() {
|
||||||
println(extern)
|
println(extern)
|
||||||
}`)
|
}`)
|
||||||
tg.run("run", "-ldflags", `-X main.extern "hello world"`, tg.path("main.go"))
|
tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
|
||||||
tg.grepStderr("^hello world", `ldflags -X main.extern 'hello world' failed`)
|
tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
|
func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
|
||||||
|
|
@ -1726,7 +1721,6 @@ func TestSymlinksVendor(t *testing.T) {
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.tempDir("gopath/src/dir1/vendor/v")
|
tg.tempDir("gopath/src/dir1/vendor/v")
|
||||||
tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `v`\nfunc main(){}")
|
tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `v`\nfunc main(){}")
|
||||||
tg.tempFile("gopath/src/dir1/vendor/v/v.go", "package v")
|
tg.tempFile("gopath/src/dir1/vendor/v/v.go", "package v")
|
||||||
|
|
@ -1879,7 +1873,9 @@ func TestShadowingLogic(t *testing.T) {
|
||||||
}
|
}
|
||||||
// The output will have makeImportValid applies, but we only
|
// The output will have makeImportValid applies, but we only
|
||||||
// bother to deal with characters we might reasonably see.
|
// bother to deal with characters we might reasonably see.
|
||||||
pwdForwardSlash = strings.Replace(pwdForwardSlash, ":", "_", -1)
|
for _, r := range " :" {
|
||||||
|
pwdForwardSlash = strings.Replace(pwdForwardSlash, string(r), "_", -1)
|
||||||
|
}
|
||||||
want := "(_" + pwdForwardSlash + "/testdata/shadow/root1/src/math) (" + filepath.Join(runtime.GOROOT(), "src", "math") + ")"
|
want := "(_" + pwdForwardSlash + "/testdata/shadow/root1/src/math) (" + filepath.Join(runtime.GOROOT(), "src", "math") + ")"
|
||||||
if strings.TrimSpace(tg.getStdout()) != want {
|
if strings.TrimSpace(tg.getStdout()) != want {
|
||||||
t.Error("shadowed math is not shadowed; looking for", want)
|
t.Error("shadowed math is not shadowed; looking for", want)
|
||||||
|
|
@ -2001,6 +1997,27 @@ func TestCoverageUsesActualSettingToOverrideEvenForRace(t *testing.T) {
|
||||||
checkCoverage(tg, data)
|
checkCoverage(tg, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildDryRunWithCgo(t *testing.T) {
|
||||||
|
if !canCgo {
|
||||||
|
t.Skip("skipping because cgo not enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.tempFile("foo.go", `package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <limits.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(C.INT_MAX)
|
||||||
|
}`)
|
||||||
|
tg.run("build", "-n", tg.path("foo.go"))
|
||||||
|
tg.grepStderrNot(`os.Stat .* no such file or directory`, "unexpected stat of archive file")
|
||||||
|
}
|
||||||
|
|
||||||
func TestCoverageWithCgo(t *testing.T) {
|
func TestCoverageWithCgo(t *testing.T) {
|
||||||
if !canCgo {
|
if !canCgo {
|
||||||
t.Skip("skipping because cgo not enabled")
|
t.Skip("skipping because cgo not enabled")
|
||||||
|
|
@ -2106,10 +2123,33 @@ func main() { C.f() }`)
|
||||||
tg.grepStderr(`gccgo.*\-L alibpath \-lalib`, `no Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage`)
|
tg.grepStderr(`gccgo.*\-L alibpath \-lalib`, `no Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListTemplateCanUseContextFunction(t *testing.T) {
|
func TestListTemplateContextFunction(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.run("list", "-f", "GOARCH: {{context.GOARCH}}")
|
for _, tt := range []struct {
|
||||||
|
v string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"GOARCH", runtime.GOARCH},
|
||||||
|
{"GOOS", runtime.GOOS},
|
||||||
|
{"GOROOT", filepath.Clean(runtime.GOROOT())},
|
||||||
|
{"GOPATH", os.Getenv("GOPATH")},
|
||||||
|
{"CgoEnabled", ""},
|
||||||
|
{"UseAllFiles", ""},
|
||||||
|
{"Compiler", ""},
|
||||||
|
{"BuildTags", ""},
|
||||||
|
{"ReleaseTags", ""},
|
||||||
|
{"InstallSuffix", ""},
|
||||||
|
} {
|
||||||
|
tmpl := "{{context." + tt.v + "}}"
|
||||||
|
tg.run("list", "-f", tmpl)
|
||||||
|
if tt.want == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
|
||||||
|
t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cmd/go: "go test" should fail if package does not build
|
// cmd/go: "go test" should fail if package does not build
|
||||||
|
|
@ -2123,7 +2163,7 @@ func TestIssue7108(t *testing.T) {
|
||||||
// cmd/go: go test -a foo does not rebuild regexp.
|
// cmd/go: go test -a foo does not rebuild regexp.
|
||||||
func TestIssue6844(t *testing.T) {
|
func TestIssue6844(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("don't rebuild the standard libary in short mode")
|
t.Skip("don't rebuild the standard library in short mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
|
|
@ -2295,8 +2335,7 @@ func TestGoVetWithExternalTests(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.makeTempdir()
|
tg.makeTempdir()
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.run("install", "cmd/vet")
|
||||||
tg.run("get", "golang.org/x/tools/cmd/vet")
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.runFail("vet", "vetpkg")
|
tg.runFail("vet", "vetpkg")
|
||||||
tg.grepBoth("missing argument for Printf", "go vet vetpkg did not find missing argument for Printf")
|
tg.grepBoth("missing argument for Printf", "go vet vetpkg did not find missing argument for Printf")
|
||||||
|
|
@ -2308,8 +2347,7 @@ func TestGoVetWithTags(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.makeTempdir()
|
tg.makeTempdir()
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.run("install", "cmd/vet")
|
||||||
tg.run("get", "golang.org/x/tools/cmd/vet")
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.runFail("vet", "-tags", "tagtest", "vetpkg")
|
tg.runFail("vet", "-tags", "tagtest", "vetpkg")
|
||||||
tg.grepBoth(`c\.go.*wrong number of args for format`, "go get vetpkg did not run scan tagged file")
|
tg.grepBoth(`c\.go.*wrong number of args for format`, "go get vetpkg did not run scan tagged file")
|
||||||
|
|
@ -2330,6 +2368,11 @@ func TestGoGetRscIoToolstash(t *testing.T) {
|
||||||
// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS
|
// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS
|
||||||
func TestGoGetHTTPS404(t *testing.T) {
|
func TestGoGetHTTPS404(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "linux", "freebsd":
|
||||||
|
default:
|
||||||
|
t.Skipf("test case does not work on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -2338,7 +2381,7 @@ func TestGoGetHTTPS404(t *testing.T) {
|
||||||
tg.run("get", "bazil.org/fuse/fs/fstestutil")
|
tg.run("get", "bazil.org/fuse/fs/fstestutil")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that you can not import a main package.
|
// Test that you cannot import a main package.
|
||||||
func TestIssue4210(t *testing.T) {
|
func TestIssue4210(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -2359,6 +2402,8 @@ func TestIssue4210(t *testing.T) {
|
||||||
func TestGoGetInsecure(t *testing.T) {
|
func TestGoGetInsecure(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
|
||||||
|
t.Skip("golang.org/issue/15410")
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.makeTempdir()
|
tg.makeTempdir()
|
||||||
|
|
@ -2414,22 +2459,6 @@ func TestGoGetInsecureCustomDomain(t *testing.T) {
|
||||||
tg.run("get", "-d", "-insecure", repo)
|
tg.run("get", "-d", "-insecure", repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue10193(t *testing.T) {
|
|
||||||
t.Skip("depends on code.google.com")
|
|
||||||
testenv.MustHaveExternalNetwork(t)
|
|
||||||
if _, err := exec.LookPath("hg"); err != nil {
|
|
||||||
t.Skip("skipping because hg binary not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.parallel()
|
|
||||||
tg.tempDir("src")
|
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
|
||||||
tg.runFail("get", "code.google.com/p/rsc/pdf")
|
|
||||||
tg.grepStderr("is shutting down", "missed warning about code.google.com")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoRunDirs(t *testing.T) {
|
func TestGoRunDirs(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -2759,3 +2788,169 @@ func TestParallelTest(t *testing.T) {
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
|
tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCgoConsistentResults(t *testing.T) {
|
||||||
|
if !canCgo {
|
||||||
|
t.Skip("skipping because cgo not enabled")
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "solaris" {
|
||||||
|
// See https://golang.org/issue/13247
|
||||||
|
t.Skip("skipping because Solaris builds are known to be inconsistent; see #13247")
|
||||||
|
}
|
||||||
|
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
tg.makeTempdir()
|
||||||
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
|
exe1 := tg.path("cgotest1" + exeSuffix)
|
||||||
|
exe2 := tg.path("cgotest2" + exeSuffix)
|
||||||
|
tg.run("build", "-o", exe1, "cgotest")
|
||||||
|
tg.run("build", "-x", "-o", exe2, "cgotest")
|
||||||
|
b1, err := ioutil.ReadFile(exe1)
|
||||||
|
tg.must(err)
|
||||||
|
b2, err := ioutil.ReadFile(exe2)
|
||||||
|
tg.must(err)
|
||||||
|
|
||||||
|
if !tg.doGrepMatch(`-fdebug-prefix-map=\$WORK`, &tg.stderr) {
|
||||||
|
t.Skip("skipping because C compiler does not support -fdebug-prefix-map")
|
||||||
|
}
|
||||||
|
if !bytes.Equal(b1, b2) {
|
||||||
|
t.Error("building cgotest twice did not produce the same output")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue 14444: go get -u .../ duplicate loads errors
|
||||||
|
func TestGoGetUpdateAllDoesNotTryToLoadDuplicates(t *testing.T) {
|
||||||
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.makeTempdir()
|
||||||
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
|
tg.run("get", "-u", ".../")
|
||||||
|
tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFatalInBenchmarkCauseNonZeroExitStatus(t *testing.T) {
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.runFail("test", "-bench", ".", "./testdata/src/benchfatal")
|
||||||
|
tg.grepBothNot("^ok", "test passed unexpectedly")
|
||||||
|
tg.grepBoth("FAIL.*benchfatal", "test did not run everything")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryOnlyPackages(t *testing.T) {
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.makeTempdir()
|
||||||
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
|
|
||||||
|
tg.tempFile("src/p1/p1.go", `//go:binary-only-package
|
||||||
|
|
||||||
|
package p1
|
||||||
|
`)
|
||||||
|
tg.wantStale("p1", "cannot access install target", "p1 is binary-only but has no binary, should be stale")
|
||||||
|
tg.runFail("install", "p1")
|
||||||
|
tg.grepStderr("missing or invalid package binary", "did not report attempt to compile binary-only package")
|
||||||
|
|
||||||
|
tg.tempFile("src/p1/p1.go", `
|
||||||
|
package p1
|
||||||
|
import "fmt"
|
||||||
|
func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
|
||||||
|
`)
|
||||||
|
tg.run("install", "p1")
|
||||||
|
os.Remove(tg.path("src/p1/p1.go"))
|
||||||
|
tg.mustNotExist(tg.path("src/p1/p1.go"))
|
||||||
|
|
||||||
|
tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
|
||||||
|
|
||||||
|
package p2
|
||||||
|
import "p1"
|
||||||
|
func F() { p1.F(true) }
|
||||||
|
`)
|
||||||
|
tg.runFail("install", "p2")
|
||||||
|
tg.grepStderr("no buildable Go source files", "did not complain about missing sources")
|
||||||
|
|
||||||
|
tg.tempFile("src/p1/missing.go", `//go:binary-only-package
|
||||||
|
|
||||||
|
package p1
|
||||||
|
func G()
|
||||||
|
`)
|
||||||
|
tg.wantNotStale("p1", "no source code", "should NOT want to rebuild p1 (first)")
|
||||||
|
tg.run("install", "-x", "p1") // no-op, up to date
|
||||||
|
tg.grepBothNot("/compile", "should not have run compiler")
|
||||||
|
tg.run("install", "p2") // does not rebuild p1 (or else p2 will fail)
|
||||||
|
tg.wantNotStale("p2", "", "should NOT want to rebuild p2")
|
||||||
|
|
||||||
|
// changes to the non-source-code do not matter,
|
||||||
|
// and only one file needs the special comment.
|
||||||
|
tg.tempFile("src/p1/missing2.go", `
|
||||||
|
package p1
|
||||||
|
func H()
|
||||||
|
`)
|
||||||
|
tg.wantNotStale("p1", "no source code", "should NOT want to rebuild p1 (second)")
|
||||||
|
tg.wantNotStale("p2", "", "should NOT want to rebuild p2")
|
||||||
|
|
||||||
|
tg.tempFile("src/p3/p3.go", `
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"p1"
|
||||||
|
"p2"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
p1.F(false)
|
||||||
|
p2.F()
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
tg.run("install", "p3")
|
||||||
|
|
||||||
|
tg.run("run", tg.path("src/p3/p3.go"))
|
||||||
|
tg.grepStdout("hello from p1", "did not see message from p1")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue 16050.
|
||||||
|
func TestAlwaysLinkSysoFiles(t *testing.T) {
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
tg.tempDir("src/syso")
|
||||||
|
tg.tempFile("src/syso/a.syso", ``)
|
||||||
|
tg.tempFile("src/syso/b.go", `package syso`)
|
||||||
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
|
|
||||||
|
// We should see the .syso file regardless of the setting of
|
||||||
|
// CGO_ENABLED.
|
||||||
|
|
||||||
|
tg.setenv("CGO_ENABLED", "1")
|
||||||
|
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
|
||||||
|
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
|
||||||
|
|
||||||
|
tg.setenv("CGO_ENABLED", "0")
|
||||||
|
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
|
||||||
|
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue 16120.
|
||||||
|
func TestGenerateUsesBuildContext(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Skip("this test won't run under Windows")
|
||||||
|
}
|
||||||
|
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
tg.tempDir("src/gen")
|
||||||
|
tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
|
||||||
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
|
|
||||||
|
tg.setenv("GOOS", "linux")
|
||||||
|
tg.setenv("GOARCH", "amd64")
|
||||||
|
tg.run("generate", "gen")
|
||||||
|
tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
|
||||||
|
|
||||||
|
tg.setenv("GOOS", "darwin")
|
||||||
|
tg.setenv("GOARCH", "386")
|
||||||
|
tg.run("generate", "gen")
|
||||||
|
tg.grepStdout("darwin 386", "unexpected GOOS/GOARCH combination")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -149,14 +149,6 @@ A few common code hosting sites have special syntax:
|
||||||
import "github.com/user/project"
|
import "github.com/user/project"
|
||||||
import "github.com/user/project/sub/directory"
|
import "github.com/user/project/sub/directory"
|
||||||
|
|
||||||
Google Code Project Hosting (Git, Mercurial, Subversion)
|
|
||||||
|
|
||||||
import "code.google.com/p/project"
|
|
||||||
import "code.google.com/p/project/sub/directory"
|
|
||||||
|
|
||||||
import "code.google.com/p/project.subrepository"
|
|
||||||
import "code.google.com/p/project.subrepository/sub/directory"
|
|
||||||
|
|
||||||
Launchpad (Bazaar)
|
Launchpad (Bazaar)
|
||||||
|
|
||||||
import "launchpad.net/project"
|
import "launchpad.net/project"
|
||||||
|
|
@ -269,10 +261,9 @@ unless it is being referred to by that import path. In this way, import comments
|
||||||
let package authors make sure the custom import path is used and not a
|
let package authors make sure the custom import path is used and not a
|
||||||
direct path to the underlying code hosting site.
|
direct path to the underlying code hosting site.
|
||||||
|
|
||||||
If vendoring is enabled (see 'go help gopath'), then import path checking is
|
Import path checking is disabled for code found within vendor trees.
|
||||||
disabled for code found within vendor trees. This makes it possible to copy
|
This makes it possible to copy code into alternate locations in vendor trees
|
||||||
code into alternate locations in vendor trees without needing to update import
|
without needing to update import comments.
|
||||||
comments.
|
|
||||||
|
|
||||||
See https://golang.org/s/go14customimport for details.
|
See https://golang.org/s/go14customimport for details.
|
||||||
`,
|
`,
|
||||||
|
|
@ -421,12 +412,6 @@ Vendor directories do not affect the placement of new repositories
|
||||||
being checked out for the first time by 'go get': those are always
|
being checked out for the first time by 'go get': those are always
|
||||||
placed in the main GOPATH, never in a vendor subtree.
|
placed in the main GOPATH, never in a vendor subtree.
|
||||||
|
|
||||||
In Go 1.5, as an experiment, setting the environment variable
|
|
||||||
GO15VENDOREXPERIMENT=1 enabled these features.
|
|
||||||
As of Go 1.6 they are on by default. To turn them off, set
|
|
||||||
GO15VENDOREXPERIMENT=0. In Go 1.7, the environment
|
|
||||||
variable will stop having any effect.
|
|
||||||
|
|
||||||
See https://golang.org/s/go15vendor for details.
|
See https://golang.org/s/go15vendor for details.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
@ -497,8 +482,6 @@ Special-purpose environment variables:
|
||||||
installed in a location other than where it is built.
|
installed in a location other than where it is built.
|
||||||
File names in stack traces are rewritten from GOROOT to
|
File names in stack traces are rewritten from GOROOT to
|
||||||
GOROOT_FINAL.
|
GOROOT_FINAL.
|
||||||
GO15VENDOREXPERIMENT
|
|
||||||
Set to 0 to disable vendoring semantics.
|
|
||||||
GO_EXTLINK_ENABLED
|
GO_EXTLINK_ENABLED
|
||||||
Whether the linker should use external linking mode
|
Whether the linker should use external linking mode
|
||||||
when using -linkmode=auto with code that uses cgo.
|
when using -linkmode=auto with code that uses cgo.
|
||||||
|
|
@ -540,7 +523,15 @@ the extension of the file name. These extensions are:
|
||||||
Files of each of these types except .syso may contain build
|
Files of each of these types except .syso may contain build
|
||||||
constraints, but the go command stops scanning for build constraints
|
constraints, but the go command stops scanning for build constraints
|
||||||
at the first item in the file that is not a blank line or //-style
|
at the first item in the file that is not a blank line or //-style
|
||||||
line comment.
|
line comment. See the go/build package documentation for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
Non-test Go source files can also include a //go:binary-only-package
|
||||||
|
comment, indicating that the package sources are included
|
||||||
|
for documentation only and must not be used to build the
|
||||||
|
package binary. This enables distribution of Go packages in
|
||||||
|
their compiled form alone. See the go/build package documentation
|
||||||
|
for more details.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ var httpClient = http.DefaultClient
|
||||||
// when we're connecting to https servers that might not be there
|
// when we're connecting to https servers that might not be there
|
||||||
// or might be using self-signed certificates.
|
// or might be using self-signed certificates.
|
||||||
var impatientInsecureHTTPClient = &http.Client{
|
var impatientInsecureHTTPClient = &http.Client{
|
||||||
Timeout: time.Duration(5 * time.Second),
|
Timeout: 5 * time.Second,
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -41,7 +41,10 @@ syntax of package template. The default output is equivalent to -f
|
||||||
Goroot bool // is this package in the Go root?
|
Goroot bool // is this package in the Go root?
|
||||||
Standard bool // is this package part of the standard Go library?
|
Standard bool // is this package part of the standard Go library?
|
||||||
Stale bool // would 'go install' do anything for this package?
|
Stale bool // would 'go install' do anything for this package?
|
||||||
|
StaleReason string // explanation for Stale==true
|
||||||
Root string // Go root or Go path dir containing this package
|
Root string // Go root or Go path dir containing this package
|
||||||
|
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||||
|
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||||
|
|
||||||
// Source files
|
// Source files
|
||||||
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||||
|
|
@ -51,6 +54,7 @@ syntax of package template. The default output is equivalent to -f
|
||||||
CXXFiles []string // .cc, .cxx and .cpp source files
|
CXXFiles []string // .cc, .cxx and .cpp source files
|
||||||
MFiles []string // .m source files
|
MFiles []string // .m source files
|
||||||
HFiles []string // .h, .hh, .hpp and .hxx source files
|
HFiles []string // .h, .hh, .hpp and .hxx source files
|
||||||
|
FFiles []string // .f, .F, .for and .f90 Fortran source files
|
||||||
SFiles []string // .s source files
|
SFiles []string // .s source files
|
||||||
SwigFiles []string // .swig files
|
SwigFiles []string // .swig files
|
||||||
SwigCXXFiles []string // .swigcxx files
|
SwigCXXFiles []string // .swigcxx files
|
||||||
|
|
@ -60,6 +64,7 @@ syntax of package template. The default output is equivalent to -f
|
||||||
CgoCFLAGS []string // cgo: flags for C compiler
|
CgoCFLAGS []string // cgo: flags for C compiler
|
||||||
CgoCPPFLAGS []string // cgo: flags for C preprocessor
|
CgoCPPFLAGS []string // cgo: flags for C preprocessor
|
||||||
CgoCXXFLAGS []string // cgo: flags for C++ compiler
|
CgoCXXFLAGS []string // cgo: flags for C++ compiler
|
||||||
|
CgoFFLAGS []string // cgo: flags for Fortran compiler
|
||||||
CgoLDFLAGS []string // cgo: flags for linker
|
CgoLDFLAGS []string // cgo: flags for linker
|
||||||
CgoPkgConfig []string // cgo: pkg-config names
|
CgoPkgConfig []string // cgo: pkg-config names
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -214,15 +214,7 @@ var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}
|
||||||
{{end}}{{.Long | trim}}
|
{{end}}{{.Long | trim}}
|
||||||
`
|
`
|
||||||
|
|
||||||
var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reserved.
|
var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.
|
|
||||||
// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.
|
|
||||||
|
|
||||||
/*
|
|
||||||
{{range .}}{{if .Short}}{{.Short | capitalize}}
|
|
||||||
|
|
||||||
{{end}}{{if .Runnable}}Usage:
|
{{end}}{{if .Runnable}}Usage:
|
||||||
|
|
||||||
|
|
@ -231,9 +223,39 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
|
||||||
{{end}}{{.Long | trim}}
|
{{end}}{{.Long | trim}}
|
||||||
|
|
||||||
|
|
||||||
{{end}}*/
|
{{end}}`
|
||||||
package main
|
|
||||||
`
|
// commentWriter writes a Go comment to the underlying io.Writer,
|
||||||
|
// using line comment form (//).
|
||||||
|
type commentWriter struct {
|
||||||
|
W io.Writer
|
||||||
|
wroteSlashes bool // Wrote "//" at the beginning of the current line.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *commentWriter) Write(p []byte) (int, error) {
|
||||||
|
var n int
|
||||||
|
for i, b := range p {
|
||||||
|
if !c.wroteSlashes {
|
||||||
|
s := "//"
|
||||||
|
if b != '\n' {
|
||||||
|
s = "// "
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(c.W, s); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
c.wroteSlashes = true
|
||||||
|
}
|
||||||
|
n0, err := c.W.Write(p[i : i+1])
|
||||||
|
n += n0
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
if b == '\n' {
|
||||||
|
c.wroteSlashes = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
// An errWriter wraps a writer, recording whether a write error occurred.
|
// An errWriter wraps a writer, recording whether a write error occurred.
|
||||||
type errWriter struct {
|
type errWriter struct {
|
||||||
|
|
@ -310,10 +332,18 @@ func help(args []string) {
|
||||||
|
|
||||||
// 'go help documentation' generates doc.go.
|
// 'go help documentation' generates doc.go.
|
||||||
if arg == "documentation" {
|
if arg == "documentation" {
|
||||||
|
fmt.Println("// Copyright 2011 The Go Authors. All rights reserved.")
|
||||||
|
fmt.Println("// Use of this source code is governed by a BSD-style")
|
||||||
|
fmt.Println("// license that can be found in the LICENSE file.")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.")
|
||||||
|
fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.")
|
||||||
|
fmt.Println()
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
printUsage(buf)
|
printUsage(buf)
|
||||||
usage := &Command{Long: buf.String()}
|
usage := &Command{Long: buf.String()}
|
||||||
tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))
|
tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*Command{usage}, commands...))
|
||||||
|
fmt.Println("package main")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,7 +369,7 @@ func importPathsNoDotExpansion(args []string) []string {
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
// Arguments are supposed to be import paths, but
|
// Arguments are supposed to be import paths, but
|
||||||
// as a courtesy to Windows developers, rewrite \ to /
|
// as a courtesy to Windows developers, rewrite \ to /
|
||||||
// in command-line arguments. Handles .\... and so on.
|
// in command-line arguments. Handles .\... and so on.
|
||||||
if filepath.Separator == '\\' {
|
if filepath.Separator == '\\' {
|
||||||
a = strings.Replace(a, `\`, `/`, -1)
|
a = strings.Replace(a, `\`, `/`, -1)
|
||||||
}
|
}
|
||||||
|
|
@ -403,8 +433,6 @@ func errorf(format string, args ...interface{}) {
|
||||||
setExitStatus(1)
|
setExitStatus(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var logf = log.Printf
|
|
||||||
|
|
||||||
func exitIfErrors() {
|
func exitIfErrors() {
|
||||||
if exitStatus != 0 {
|
if exitStatus != 0 {
|
||||||
exit()
|
exit()
|
||||||
|
|
@ -428,19 +456,6 @@ func run(cmdargs ...interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runOut(dir string, cmdargs ...interface{}) []byte {
|
|
||||||
cmdline := stringList(cmdargs...)
|
|
||||||
cmd := exec.Command(cmdline[0], cmdline[1:]...)
|
|
||||||
cmd.Dir = dir
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
os.Stderr.Write(out)
|
|
||||||
errorf("%v", err)
|
|
||||||
out = nil
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// envForDir returns a copy of the environment
|
// envForDir returns a copy of the environment
|
||||||
// suitable for running in the given directory.
|
// suitable for running in the given directory.
|
||||||
// The environment is the current process's environment
|
// The environment is the current process's environment
|
||||||
|
|
@ -472,7 +487,7 @@ NextVar:
|
||||||
}
|
}
|
||||||
|
|
||||||
// matchPattern(pattern)(name) reports whether
|
// matchPattern(pattern)(name) reports whether
|
||||||
// name matches pattern. Pattern is a limited glob
|
// name matches pattern. Pattern is a limited glob
|
||||||
// pattern in which '...' means 'any string' and there
|
// pattern in which '...' means 'any string' and there
|
||||||
// is no other special syntax.
|
// is no other special syntax.
|
||||||
func matchPattern(pattern string) func(name string) bool {
|
func matchPattern(pattern string) func(name string) bool {
|
||||||
|
|
@ -629,7 +644,7 @@ func matchPackages(pattern string) []string {
|
||||||
|
|
||||||
// allPackagesInFS is like allPackages but is passed a pattern
|
// allPackagesInFS is like allPackages but is passed a pattern
|
||||||
// beginning ./ or ../, meaning it should scan the tree rooted
|
// beginning ./ or ../, meaning it should scan the tree rooted
|
||||||
// at the given directory. There are ... in the pattern too.
|
// at the given directory. There are ... in the pattern too.
|
||||||
func allPackagesInFS(pattern string) []string {
|
func allPackagesInFS(pattern string) []string {
|
||||||
pkgs := matchPackagesInFS(pattern)
|
pkgs := matchPackagesInFS(pattern)
|
||||||
if len(pkgs) == 0 {
|
if len(pkgs) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ func readELFNote(filename, name string, typ int32) ([]byte, error) {
|
||||||
var elfGoNote = []byte("Go\x00\x00")
|
var elfGoNote = []byte("Go\x00\x00")
|
||||||
|
|
||||||
// The Go build ID is stored in a note described by an ELF PT_NOTE prog
|
// The Go build ID is stored in a note described by an ELF PT_NOTE prog
|
||||||
// header. The caller has already opened filename, to get f, and read
|
// header. The caller has already opened filename, to get f, and read
|
||||||
// at least 4 kB out, in data.
|
// at least 4 kB out, in data.
|
||||||
func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string, err error) {
|
func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string, err error) {
|
||||||
// Assume the note content is in the data, already read.
|
// Assume the note content is in the data, already read.
|
||||||
|
|
@ -110,7 +110,7 @@ func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string,
|
||||||
// or even the first few megabytes of the file
|
// or even the first few megabytes of the file
|
||||||
// due to differences in note segment placement;
|
// due to differences in note segment placement;
|
||||||
// in that case, extract the note data manually.
|
// in that case, extract the note data manually.
|
||||||
_, err = f.Seek(int64(p.Off), 0)
|
_, err = f.Seek(int64(p.Off), io.SeekStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -47,8 +47,6 @@ func testNoteReading(t *testing.T) {
|
||||||
t.Skipf("skipping - no cgo, so assuming external linking not available")
|
t.Skipf("skipping - no cgo, so assuming external linking not available")
|
||||||
case runtime.GOOS == "linux" && (runtime.GOARCH == "ppc64le" || runtime.GOARCH == "ppc64"):
|
case runtime.GOOS == "linux" && (runtime.GOARCH == "ppc64le" || runtime.GOARCH == "ppc64"):
|
||||||
t.Skipf("skipping - external linking not supported, golang.org/issue/11184")
|
t.Skipf("skipping - external linking not supported, golang.org/issue/11184")
|
||||||
case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64le" || runtime.GOARCH == "mips64"):
|
|
||||||
t.Skipf("skipping - external linking not supported, golang.org/issue/12560")
|
|
||||||
case runtime.GOOS == "openbsd" && runtime.GOARCH == "arm":
|
case runtime.GOOS == "openbsd" && runtime.GOARCH == "arm":
|
||||||
t.Skipf("skipping - external linking not supported, golang.org/issue/10619")
|
t.Skipf("skipping - external linking not supported, golang.org/issue/10619")
|
||||||
case runtime.GOOS == "plan9":
|
case runtime.GOOS == "plan9":
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -27,8 +27,8 @@ import (
|
||||||
// A Package describes a single package found in a directory.
|
// A Package describes a single package found in a directory.
|
||||||
type Package struct {
|
type Package struct {
|
||||||
// Note: These fields are part of the go command's public API.
|
// Note: These fields are part of the go command's public API.
|
||||||
// See list.go. It is okay to add fields, but not to change or
|
// See list.go. It is okay to add fields, but not to change or
|
||||||
// remove existing ones. Keep in sync with list.go
|
// remove existing ones. Keep in sync with list.go
|
||||||
Dir string `json:",omitempty"` // directory containing package sources
|
Dir string `json:",omitempty"` // directory containing package sources
|
||||||
ImportPath string `json:",omitempty"` // import path of package in dir
|
ImportPath string `json:",omitempty"` // import path of package in dir
|
||||||
ImportComment string `json:",omitempty"` // path in import comment on package statement
|
ImportComment string `json:",omitempty"` // path in import comment on package statement
|
||||||
|
|
@ -39,8 +39,10 @@ type Package struct {
|
||||||
Goroot bool `json:",omitempty"` // is this package found in the Go root?
|
Goroot bool `json:",omitempty"` // is this package found in the Go root?
|
||||||
Standard bool `json:",omitempty"` // is this package part of the standard Go library?
|
Standard bool `json:",omitempty"` // is this package part of the standard Go library?
|
||||||
Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
|
Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
|
||||||
|
StaleReason string `json:",omitempty"` // why is Stale true?
|
||||||
Root string `json:",omitempty"` // Go root or Go path dir containing this package
|
Root string `json:",omitempty"` // Go root or Go path dir containing this package
|
||||||
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
|
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
|
||||||
|
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||||
|
|
||||||
// Source files
|
// Source files
|
||||||
GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||||
|
|
@ -50,6 +52,7 @@ type Package struct {
|
||||||
CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files
|
CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files
|
||||||
MFiles []string `json:",omitempty"` // .m source files
|
MFiles []string `json:",omitempty"` // .m source files
|
||||||
HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files
|
HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files
|
||||||
|
FFiles []string `json:",omitempty"` // .f, .F, .for and .f90 Fortran source files
|
||||||
SFiles []string `json:",omitempty"` // .s source files
|
SFiles []string `json:",omitempty"` // .s source files
|
||||||
SwigFiles []string `json:",omitempty"` // .swig files
|
SwigFiles []string `json:",omitempty"` // .swig files
|
||||||
SwigCXXFiles []string `json:",omitempty"` // .swigcxx files
|
SwigCXXFiles []string `json:",omitempty"` // .swigcxx files
|
||||||
|
|
@ -59,6 +62,7 @@ type Package struct {
|
||||||
CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler
|
CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler
|
||||||
CgoCPPFLAGS []string `json:",omitempty"` // cgo: flags for C preprocessor
|
CgoCPPFLAGS []string `json:",omitempty"` // cgo: flags for C preprocessor
|
||||||
CgoCXXFLAGS []string `json:",omitempty"` // cgo: flags for C++ compiler
|
CgoCXXFLAGS []string `json:",omitempty"` // cgo: flags for C++ compiler
|
||||||
|
CgoFFLAGS []string `json:",omitempty"` // cgo: flags for Fortran compiler
|
||||||
CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker
|
CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker
|
||||||
CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names
|
CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names
|
||||||
|
|
||||||
|
|
@ -88,7 +92,6 @@ type Package struct {
|
||||||
target string // installed file for this package (may be executable)
|
target string // installed file for this package (may be executable)
|
||||||
fake bool // synthesized package
|
fake bool // synthesized package
|
||||||
external bool // synthesized external test package
|
external bool // synthesized external test package
|
||||||
forceBuild bool // this package must be rebuilt
|
|
||||||
forceLibrary bool // this package is a library (even if named "main")
|
forceLibrary bool // this package is a library (even if named "main")
|
||||||
cmdline bool // defined by files listed on command line
|
cmdline bool // defined by files listed on command line
|
||||||
local bool // imported via local path (./ or ../)
|
local bool // imported via local path (./ or ../)
|
||||||
|
|
@ -151,6 +154,8 @@ func (p *Package) copyBuild(pp *build.Package) {
|
||||||
p.Doc = pp.Doc
|
p.Doc = pp.Doc
|
||||||
p.Root = pp.Root
|
p.Root = pp.Root
|
||||||
p.ConflictDir = pp.ConflictDir
|
p.ConflictDir = pp.ConflictDir
|
||||||
|
p.BinaryOnly = pp.BinaryOnly
|
||||||
|
|
||||||
// TODO? Target
|
// TODO? Target
|
||||||
p.Goroot = pp.Goroot
|
p.Goroot = pp.Goroot
|
||||||
if buildContext.Compiler == "gccgo" {
|
if buildContext.Compiler == "gccgo" {
|
||||||
|
|
@ -165,6 +170,7 @@ func (p *Package) copyBuild(pp *build.Package) {
|
||||||
p.CXXFiles = pp.CXXFiles
|
p.CXXFiles = pp.CXXFiles
|
||||||
p.MFiles = pp.MFiles
|
p.MFiles = pp.MFiles
|
||||||
p.HFiles = pp.HFiles
|
p.HFiles = pp.HFiles
|
||||||
|
p.FFiles = pp.FFiles
|
||||||
p.SFiles = pp.SFiles
|
p.SFiles = pp.SFiles
|
||||||
p.SwigFiles = pp.SwigFiles
|
p.SwigFiles = pp.SwigFiles
|
||||||
p.SwigCXXFiles = pp.SwigCXXFiles
|
p.SwigCXXFiles = pp.SwigCXXFiles
|
||||||
|
|
@ -209,7 +215,7 @@ func (p *PackageError) Error() string {
|
||||||
return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports "))
|
return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports "))
|
||||||
}
|
}
|
||||||
if p.Pos != "" {
|
if p.Pos != "" {
|
||||||
// Omit import stack. The full path to the file where the error
|
// Omit import stack. The full path to the file where the error
|
||||||
// is the most important thing.
|
// is the most important thing.
|
||||||
return p.Pos + ": " + p.Err
|
return p.Pos + ": " + p.Err
|
||||||
}
|
}
|
||||||
|
|
@ -267,18 +273,9 @@ func reloadPackage(arg string, stk *importStack) *Package {
|
||||||
return loadPackage(arg, stk)
|
return loadPackage(arg, stk)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Go 1.5 vendoring experiment was enabled by setting GO15VENDOREXPERIMENT=1.
|
|
||||||
// In Go 1.6 this is on by default and is disabled by setting GO15VENDOREXPERIMENT=0.
|
|
||||||
// In Go 1.7 the variable will stop having any effect.
|
|
||||||
// The variable is obnoxiously long so that years from now when people find it in
|
|
||||||
// their profiles and wonder what it does, there is some chance that a web search
|
|
||||||
// might answer the question.
|
|
||||||
// There is a copy of this variable in src/go/build/build.go. Delete that one when this one goes away.
|
|
||||||
var go15VendorExperiment = os.Getenv("GO15VENDOREXPERIMENT") != "0"
|
|
||||||
|
|
||||||
// dirToImportPath returns the pseudo-import path we use for a package
|
// dirToImportPath returns the pseudo-import path we use for a package
|
||||||
// outside the Go path. It begins with _/ and then contains the full path
|
// outside the Go path. It begins with _/ and then contains the full path
|
||||||
// to the directory. If the package lives in c:\home\gopher\my\pkg then
|
// to the directory. If the package lives in c:\home\gopher\my\pkg then
|
||||||
// the pseudo-import path is _/c_/home/gopher/my/pkg.
|
// the pseudo-import path is _/c_/home/gopher/my/pkg.
|
||||||
// Using a pseudo-import path like this makes the ./ imports no longer
|
// Using a pseudo-import path like this makes the ./ imports no longer
|
||||||
// a special case, so that all the code to deal with ordinary imports works
|
// a special case, so that all the code to deal with ordinary imports works
|
||||||
|
|
@ -365,7 +362,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
|
||||||
// TODO: After Go 1, decide when to pass build.AllowBinary here.
|
// TODO: After Go 1, decide when to pass build.AllowBinary here.
|
||||||
// See issue 3268 for mistakes to avoid.
|
// See issue 3268 for mistakes to avoid.
|
||||||
buildMode := build.ImportComment
|
buildMode := build.ImportComment
|
||||||
if !go15VendorExperiment || mode&useVendor == 0 || path != origPath {
|
if mode&useVendor == 0 || path != origPath {
|
||||||
// Not vendoring, or we already found the vendored path.
|
// Not vendoring, or we already found the vendored path.
|
||||||
buildMode |= build.IgnoreVendor
|
buildMode |= build.IgnoreVendor
|
||||||
}
|
}
|
||||||
|
|
@ -375,7 +372,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
|
||||||
bp.BinDir = gobin
|
bp.BinDir = gobin
|
||||||
}
|
}
|
||||||
if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path &&
|
if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path &&
|
||||||
(!go15VendorExperiment || (!strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/"))) {
|
!strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {
|
||||||
err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
|
err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
|
||||||
}
|
}
|
||||||
p.load(stk, bp, err)
|
p.load(stk, bp, err)
|
||||||
|
|
@ -416,7 +413,7 @@ func isDir(path string) bool {
|
||||||
// x/vendor/path, vendor/path, or else stay path if none of those exist.
|
// x/vendor/path, vendor/path, or else stay path if none of those exist.
|
||||||
// vendoredImportPath returns the expanded path or, if no expansion is found, the original.
|
// vendoredImportPath returns the expanded path or, if no expansion is found, the original.
|
||||||
func vendoredImportPath(parent *Package, path string) (found string) {
|
func vendoredImportPath(parent *Package, path string) (found string) {
|
||||||
if parent == nil || parent.Root == "" || !go15VendorExperiment {
|
if parent == nil || parent.Root == "" {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -445,6 +442,12 @@ func vendoredImportPath(parent *Package, path string) (found string) {
|
||||||
}
|
}
|
||||||
targ := filepath.Join(dir[:i], vpath)
|
targ := filepath.Join(dir[:i], vpath)
|
||||||
if isDir(targ) && hasGoFiles(targ) {
|
if isDir(targ) && hasGoFiles(targ) {
|
||||||
|
importPath := parent.ImportPath
|
||||||
|
if importPath == "command-line-arguments" {
|
||||||
|
// If parent.ImportPath is 'command-line-arguments'.
|
||||||
|
// set to relative directory to root (also chopped root directory)
|
||||||
|
importPath = dir[len(root)+1:]
|
||||||
|
}
|
||||||
// We started with parent's dir c:\gopath\src\foo\bar\baz\quux\xyzzy.
|
// We started with parent's dir c:\gopath\src\foo\bar\baz\quux\xyzzy.
|
||||||
// We know the import path for parent's dir.
|
// We know the import path for parent's dir.
|
||||||
// We chopped off some number of path elements and
|
// We chopped off some number of path elements and
|
||||||
|
|
@ -454,14 +457,14 @@ func vendoredImportPath(parent *Package, path string) (found string) {
|
||||||
// (actually the same number of bytes) from parent's import path
|
// (actually the same number of bytes) from parent's import path
|
||||||
// and then append /vendor/path.
|
// and then append /vendor/path.
|
||||||
chopped := len(dir) - i
|
chopped := len(dir) - i
|
||||||
if chopped == len(parent.ImportPath)+1 {
|
if chopped == len(importPath)+1 {
|
||||||
// We walked up from c:\gopath\src\foo\bar
|
// We walked up from c:\gopath\src\foo\bar
|
||||||
// and found c:\gopath\src\vendor\path.
|
// and found c:\gopath\src\vendor\path.
|
||||||
// We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7).
|
// We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7).
|
||||||
// Use "vendor/path" without any prefix.
|
// Use "vendor/path" without any prefix.
|
||||||
return vpath
|
return vpath
|
||||||
}
|
}
|
||||||
return parent.ImportPath[:len(parent.ImportPath)-chopped] + "/" + vpath
|
return importPath[:len(importPath)-chopped] + "/" + vpath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
|
|
@ -482,7 +485,7 @@ func hasGoFiles(dir string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reusePackage reuses package p to satisfy the import at the top
|
// reusePackage reuses package p to satisfy the import at the top
|
||||||
// of the import stack stk. If this use causes an import loop,
|
// of the import stack stk. If this use causes an import loop,
|
||||||
// reusePackage updates p's error information to record the loop.
|
// reusePackage updates p's error information to record the loop.
|
||||||
func reusePackage(p *Package, stk *importStack) *Package {
|
func reusePackage(p *Package, stk *importStack) *Package {
|
||||||
// We use p.imports==nil to detect a package that
|
// We use p.imports==nil to detect a package that
|
||||||
|
|
@ -528,7 +531,7 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for "internal" element: four cases depending on begin of string and/or end of string.
|
// Check for "internal" element: three cases depending on begin of string and/or end of string.
|
||||||
i, ok := findInternal(p.ImportPath)
|
i, ok := findInternal(p.ImportPath)
|
||||||
if !ok {
|
if !ok {
|
||||||
return p
|
return p
|
||||||
|
|
@ -565,7 +568,7 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
|
||||||
// If there isn't one, findInternal returns ok=false.
|
// If there isn't one, findInternal returns ok=false.
|
||||||
// Otherwise, findInternal returns ok=true and the index of the "internal".
|
// Otherwise, findInternal returns ok=true and the index of the "internal".
|
||||||
func findInternal(path string) (index int, ok bool) {
|
func findInternal(path string) (index int, ok bool) {
|
||||||
// Four cases, depending on internal at start/end of string or not.
|
// Three cases, depending on internal at start/end of string or not.
|
||||||
// The order matters: we must return the index of the final element,
|
// The order matters: we must return the index of the final element,
|
||||||
// because the final one produces the most restrictive requirement
|
// because the final one produces the most restrictive requirement
|
||||||
// on the importer.
|
// on the importer.
|
||||||
|
|
@ -584,10 +587,6 @@ func findInternal(path string) (index int, ok bool) {
|
||||||
// If the import is allowed, disallowVendor returns the original package p.
|
// If the import is allowed, disallowVendor returns the original package p.
|
||||||
// If not, it returns a new package containing just an appropriate error.
|
// If not, it returns a new package containing just an appropriate error.
|
||||||
func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package {
|
func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package {
|
||||||
if !go15VendorExperiment {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// The stack includes p.ImportPath.
|
// The stack includes p.ImportPath.
|
||||||
// If that's the only thing on the stack, we started
|
// If that's the only thing on the stack, we started
|
||||||
// with a name given on the command line, not an
|
// with a name given on the command line, not an
|
||||||
|
|
@ -667,7 +666,7 @@ func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Pack
|
||||||
|
|
||||||
// findVendor looks for the last non-terminating "vendor" path element in the given import path.
|
// findVendor looks for the last non-terminating "vendor" path element in the given import path.
|
||||||
// If there isn't one, findVendor returns ok=false.
|
// If there isn't one, findVendor returns ok=false.
|
||||||
// Otherwise, findInternal returns ok=true and the index of the "vendor".
|
// Otherwise, findVendor returns ok=true and the index of the "vendor".
|
||||||
//
|
//
|
||||||
// Note that terminating "vendor" elements don't count: "x/vendor" is its own package,
|
// Note that terminating "vendor" elements don't count: "x/vendor" is its own package,
|
||||||
// not the vendored copy of an import "" (the empty import path).
|
// not the vendored copy of an import "" (the empty import path).
|
||||||
|
|
@ -691,7 +690,6 @@ type targetDir int
|
||||||
const (
|
const (
|
||||||
toRoot targetDir = iota // to bin dir inside package root (default)
|
toRoot targetDir = iota // to bin dir inside package root (default)
|
||||||
toTool // GOROOT/pkg/tool
|
toTool // GOROOT/pkg/tool
|
||||||
toBin // GOROOT/bin
|
|
||||||
stalePath // the old import path; fail to build
|
stalePath // the old import path; fail to build
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -715,7 +713,6 @@ var goTools = map[string]targetDir{
|
||||||
"cmd/trace": toTool,
|
"cmd/trace": toTool,
|
||||||
"cmd/vet": toTool,
|
"cmd/vet": toTool,
|
||||||
"cmd/yacc": toTool,
|
"cmd/yacc": toTool,
|
||||||
"golang.org/x/tools/cmd/godoc": toBin,
|
|
||||||
"code.google.com/p/go.tools/cmd/cover": stalePath,
|
"code.google.com/p/go.tools/cmd/cover": stalePath,
|
||||||
"code.google.com/p/go.tools/cmd/godoc": stalePath,
|
"code.google.com/p/go.tools/cmd/godoc": stalePath,
|
||||||
"code.google.com/p/go.tools/cmd/vet": stalePath,
|
"code.google.com/p/go.tools/cmd/vet": stalePath,
|
||||||
|
|
@ -729,7 +726,7 @@ func expandScanner(err error) error {
|
||||||
// Prepare error with \n before each message.
|
// Prepare error with \n before each message.
|
||||||
// When printed in something like context: %v
|
// When printed in something like context: %v
|
||||||
// this will put the leading file positions each on
|
// this will put the leading file positions each on
|
||||||
// its own line. It will also show all the errors
|
// its own line. It will also show all the errors
|
||||||
// instead of just the first, as err.Error does.
|
// instead of just the first, as err.Error does.
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
for _, e := range err {
|
for _, e := range err {
|
||||||
|
|
@ -802,12 +799,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
|
||||||
// Install cross-compiled binaries to subdirectories of bin.
|
// Install cross-compiled binaries to subdirectories of bin.
|
||||||
elem = full
|
elem = full
|
||||||
}
|
}
|
||||||
if p.build.BinDir != gobin && goTools[p.ImportPath] == toBin {
|
if p.build.BinDir != "" {
|
||||||
// Override BinDir.
|
|
||||||
// This is from a subrepo but installs to $GOROOT/bin
|
|
||||||
// by default anyway (like godoc).
|
|
||||||
p.target = filepath.Join(gorootBin, elem)
|
|
||||||
} else if p.build.BinDir != "" {
|
|
||||||
// Install to GOBIN or bin of GOPATH entry.
|
// Install to GOBIN or bin of GOPATH entry.
|
||||||
p.target = filepath.Join(p.build.BinDir, elem)
|
p.target = filepath.Join(p.build.BinDir, elem)
|
||||||
if !p.Goroot && strings.Contains(elem, "/") && gobin != "" {
|
if !p.Goroot && strings.Contains(elem, "/") && gobin != "" {
|
||||||
|
|
@ -930,6 +922,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
|
||||||
p.CXXFiles,
|
p.CXXFiles,
|
||||||
p.MFiles,
|
p.MFiles,
|
||||||
p.HFiles,
|
p.HFiles,
|
||||||
|
p.FFiles,
|
||||||
p.SFiles,
|
p.SFiles,
|
||||||
p.SysoFiles,
|
p.SysoFiles,
|
||||||
p.SwigFiles,
|
p.SwigFiles,
|
||||||
|
|
@ -1032,6 +1025,20 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
|
||||||
}
|
}
|
||||||
p.Target = p.target
|
p.Target = p.target
|
||||||
|
|
||||||
|
// If cgo is not enabled, ignore cgo supporting sources
|
||||||
|
// just as we ignore go files containing import "C".
|
||||||
|
if !buildContext.CgoEnabled {
|
||||||
|
p.CFiles = nil
|
||||||
|
p.CXXFiles = nil
|
||||||
|
p.MFiles = nil
|
||||||
|
p.SwigFiles = nil
|
||||||
|
p.SwigCXXFiles = nil
|
||||||
|
// Note that SFiles are okay (they go to the Go assembler)
|
||||||
|
// and HFiles are okay (they might be used by the SFiles).
|
||||||
|
// Also Sysofiles are okay (they might not contain object
|
||||||
|
// code; see issue #16050).
|
||||||
|
}
|
||||||
|
|
||||||
// The gc toolchain only permits C source files with cgo.
|
// The gc toolchain only permits C source files with cgo.
|
||||||
if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && buildContext.Compiler == "gc" {
|
if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && buildContext.Compiler == "gc" {
|
||||||
p.Error = &PackageError{
|
p.Error = &PackageError{
|
||||||
|
|
@ -1054,7 +1061,15 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
computeBuildID(p)
|
if p.BinaryOnly {
|
||||||
|
// For binary-only package, use build ID from supplied package binary.
|
||||||
|
buildID, err := readBuildID(p)
|
||||||
|
if err == nil {
|
||||||
|
p.buildID = buildID
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
computeBuildID(p)
|
||||||
|
}
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1094,7 +1109,7 @@ func packageList(roots []*Package) []*Package {
|
||||||
// at the named pkgs (command-line arguments).
|
// at the named pkgs (command-line arguments).
|
||||||
func computeStale(pkgs ...*Package) {
|
func computeStale(pkgs ...*Package) {
|
||||||
for _, p := range packageList(pkgs) {
|
for _, p := range packageList(pkgs) {
|
||||||
p.Stale = isStale(p)
|
p.Stale, p.StaleReason = isStale(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1240,7 +1255,7 @@ var isGoRelease = strings.HasPrefix(runtime.Version(), "go1")
|
||||||
// an explicit data comparison. Specifically, we build a list of the
|
// an explicit data comparison. Specifically, we build a list of the
|
||||||
// inputs to the build, compute its SHA1 hash, and record that as the
|
// inputs to the build, compute its SHA1 hash, and record that as the
|
||||||
// ``build ID'' in the generated object. At the next build, we can
|
// ``build ID'' in the generated object. At the next build, we can
|
||||||
// recompute the buid ID and compare it to the one in the generated
|
// recompute the build ID and compare it to the one in the generated
|
||||||
// object. If they differ, the list of inputs has changed, so the object
|
// object. If they differ, the list of inputs has changed, so the object
|
||||||
// is out of date and must be rebuilt.
|
// is out of date and must be rebuilt.
|
||||||
//
|
//
|
||||||
|
|
@ -1365,40 +1380,50 @@ var isGoRelease = strings.HasPrefix(runtime.Version(), "go1")
|
||||||
// standard library, even in release versions. This makes
|
// standard library, even in release versions. This makes
|
||||||
// 'go build -tags netgo' work, among other things.
|
// 'go build -tags netgo' work, among other things.
|
||||||
|
|
||||||
// isStale reports whether package p needs to be rebuilt.
|
// isStale reports whether package p needs to be rebuilt,
|
||||||
func isStale(p *Package) bool {
|
// along with the reason why.
|
||||||
|
func isStale(p *Package) (bool, string) {
|
||||||
if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
|
if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
|
||||||
// fake, builtin package
|
// fake, builtin package
|
||||||
return false
|
return false, "builtin package"
|
||||||
}
|
}
|
||||||
if p.Error != nil {
|
if p.Error != nil {
|
||||||
return true
|
return true, "errors loading package"
|
||||||
|
}
|
||||||
|
if p.Stale {
|
||||||
|
return true, p.StaleReason
|
||||||
}
|
}
|
||||||
|
|
||||||
// A package without Go sources means we only found
|
// If this is a package with no source code, it cannot be rebuilt.
|
||||||
// the installed .a file. Since we don't know how to rebuild
|
// If the binary is missing, we mark the package stale so that
|
||||||
// it, it can't be stale, even if -a is set. This enables binary-only
|
// if a rebuild is needed, that rebuild attempt will produce a useful error.
|
||||||
// distributions of Go packages, although such binaries are
|
// (Some commands, such as 'go list', do not attempt to rebuild.)
|
||||||
// only useful with the specific version of the toolchain that
|
if p.BinaryOnly {
|
||||||
// created them.
|
if p.target == "" {
|
||||||
if len(p.gofiles) == 0 && !p.usesSwig() {
|
// Fail if a build is attempted.
|
||||||
return false
|
return true, "no source code for package, but no install target"
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(p.target); err != nil {
|
||||||
|
// Fail if a build is attempted.
|
||||||
|
return true, "no source code for package, but cannot access install target: " + err.Error()
|
||||||
|
}
|
||||||
|
return false, "no source code for package"
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the -a flag is given, rebuild everything.
|
// If the -a flag is given, rebuild everything.
|
||||||
if buildA {
|
if buildA {
|
||||||
return true
|
return true, "build -a flag in use"
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no install target or it's already marked stale, we have to rebuild.
|
// If there's no install target, we have to rebuild.
|
||||||
if p.target == "" || p.Stale {
|
if p.target == "" {
|
||||||
return true
|
return true, "no install target"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package is stale if completely unbuilt.
|
// Package is stale if completely unbuilt.
|
||||||
fi, err := os.Stat(p.target)
|
fi, err := os.Stat(p.target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true
|
return true, "cannot stat install target"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package is stale if the expected build ID differs from the
|
// Package is stale if the expected build ID differs from the
|
||||||
|
|
@ -1411,13 +1436,13 @@ func isStale(p *Package) bool {
|
||||||
// See issue 8290 and issue 10702.
|
// See issue 8290 and issue 10702.
|
||||||
targetBuildID, err := readBuildID(p)
|
targetBuildID, err := readBuildID(p)
|
||||||
if err == nil && targetBuildID != p.buildID {
|
if err == nil && targetBuildID != p.buildID {
|
||||||
return true
|
return true, "build ID mismatch"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package is stale if a dependency is.
|
// Package is stale if a dependency is.
|
||||||
for _, p1 := range p.deps {
|
for _, p1 := range p.deps {
|
||||||
if p1.Stale {
|
if p1.Stale {
|
||||||
return true
|
return true, "stale dependency"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1440,7 +1465,7 @@ func isStale(p *Package) bool {
|
||||||
// install is to run make.bash, which will remove the old package archives
|
// install is to run make.bash, which will remove the old package archives
|
||||||
// before rebuilding.)
|
// before rebuilding.)
|
||||||
if p.Standard && isGoRelease {
|
if p.Standard && isGoRelease {
|
||||||
return false
|
return false, "standard package in Go release distribution"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time-based staleness.
|
// Time-based staleness.
|
||||||
|
|
@ -1455,14 +1480,14 @@ func isStale(p *Package) bool {
|
||||||
// Package is stale if a dependency is, or if a dependency is newer.
|
// Package is stale if a dependency is, or if a dependency is newer.
|
||||||
for _, p1 := range p.deps {
|
for _, p1 := range p.deps {
|
||||||
if p1.target != "" && olderThan(p1.target) {
|
if p1.target != "" && olderThan(p1.target) {
|
||||||
return true
|
return true, "newer dependency"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// As a courtesy to developers installing new versions of the compiler
|
// As a courtesy to developers installing new versions of the compiler
|
||||||
// frequently, define that packages are stale if they are
|
// frequently, define that packages are stale if they are
|
||||||
// older than the compiler, and commands if they are older than
|
// older than the compiler, and commands if they are older than
|
||||||
// the linker. This heuristic will not work if the binaries are
|
// the linker. This heuristic will not work if the binaries are
|
||||||
// back-dated, as some binary distributions may do, but it does handle
|
// back-dated, as some binary distributions may do, but it does handle
|
||||||
// a very common case.
|
// a very common case.
|
||||||
// See issue 3036.
|
// See issue 3036.
|
||||||
|
|
@ -1474,10 +1499,10 @@ func isStale(p *Package) bool {
|
||||||
// taken care of above (at least when the installed Go is a released version).
|
// taken care of above (at least when the installed Go is a released version).
|
||||||
if p.Root != goroot {
|
if p.Root != goroot {
|
||||||
if olderThan(buildToolchain.compiler()) {
|
if olderThan(buildToolchain.compiler()) {
|
||||||
return true
|
return true, "newer compiler"
|
||||||
}
|
}
|
||||||
if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
|
if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
|
||||||
return true
|
return true, "newer linker"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1519,14 +1544,14 @@ func isStale(p *Package) bool {
|
||||||
// to test for write access, and then skip GOPATH roots we don't have write
|
// to test for write access, and then skip GOPATH roots we don't have write
|
||||||
// access to. But hopefully we can just use the mtimes always.
|
// access to. But hopefully we can just use the mtimes always.
|
||||||
|
|
||||||
srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
|
srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
if olderThan(filepath.Join(p.Dir, src)) {
|
if olderThan(filepath.Join(p.Dir, src)) {
|
||||||
return true
|
return true, "newer source file"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// computeBuildID computes the build ID for p, leaving it in p.buildID.
|
// computeBuildID computes the build ID for p, leaving it in p.buildID.
|
||||||
|
|
@ -1584,7 +1609,7 @@ var cwd, _ = os.Getwd()
|
||||||
var cmdCache = map[string]*Package{}
|
var cmdCache = map[string]*Package{}
|
||||||
|
|
||||||
// loadPackage is like loadImport but is used for command-line arguments,
|
// loadPackage is like loadImport but is used for command-line arguments,
|
||||||
// not for paths found in import statements. In addition to ordinary import paths,
|
// not for paths found in import statements. In addition to ordinary import paths,
|
||||||
// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
|
// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
|
||||||
// in the Go command directory, as well as paths to those directories.
|
// in the Go command directory, as well as paths to those directories.
|
||||||
func loadPackage(arg string, stk *importStack) *Package {
|
func loadPackage(arg string, stk *importStack) *Package {
|
||||||
|
|
@ -1648,7 +1673,7 @@ func loadPackage(arg string, stk *importStack) *Package {
|
||||||
// command line arguments 'args'. If a named package
|
// command line arguments 'args'. If a named package
|
||||||
// cannot be loaded at all (for example, if the directory does not exist),
|
// cannot be loaded at all (for example, if the directory does not exist),
|
||||||
// then packages prints an error and does not include that
|
// then packages prints an error and does not include that
|
||||||
// package in the results. However, if errors occur trying
|
// package in the results. However, if errors occur trying
|
||||||
// to load dependencies of a named package, the named
|
// to load dependencies of a named package, the named
|
||||||
// package is still returned, with p.Incomplete = true
|
// package is still returned, with p.Incomplete = true
|
||||||
// and details in p.DepsErrors.
|
// and details in p.DepsErrors.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -161,9 +161,12 @@ func TestSharedLibName(t *testing.T) {
|
||||||
}
|
}
|
||||||
oldGopath := buildContext.GOPATH
|
oldGopath := buildContext.GOPATH
|
||||||
defer func() {
|
defer func() {
|
||||||
os.RemoveAll(tmpGopath)
|
|
||||||
buildContext.GOPATH = oldGopath
|
buildContext.GOPATH = oldGopath
|
||||||
os.Chdir(cwd)
|
os.Chdir(cwd)
|
||||||
|
err := os.RemoveAll(tmpGopath)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
root := filepath.Join(tmpGopath, "src", data.rootedAt)
|
root := filepath.Join(tmpGopath, "src", data.rootedAt)
|
||||||
err = os.MkdirAll(root, 0755)
|
err = os.MkdirAll(root, 0755)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -128,7 +128,7 @@ func runRun(cmd *Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// runProgram is the action for running a binary that has already
|
// runProgram is the action for running a binary that has already
|
||||||
// been compiled. We ignore exit status.
|
// been compiled. We ignore exit status.
|
||||||
func (b *builder) runProgram(a *action) error {
|
func (b *builder) runProgram(a *action) error {
|
||||||
cmdline := stringList(findExecCmd(), a.deps[0].target, a.args)
|
cmdline := stringList(findExecCmd(), a.deps[0].target, a.args)
|
||||||
if buildN || buildX {
|
if buildN || buildX {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -59,6 +59,9 @@ Each listed package causes the execution of a separate test binary.
|
||||||
Test files that declare a package with the suffix "_test" will be compiled as a
|
Test files that declare a package with the suffix "_test" will be compiled as a
|
||||||
separate package, and then linked and run with the main test binary.
|
separate package, and then linked and run with the main test binary.
|
||||||
|
|
||||||
|
The go tool will ignore a directory named "testdata", making it available
|
||||||
|
to hold ancillary data needed by the tests.
|
||||||
|
|
||||||
By default, go test needs no arguments. It compiles and tests the package
|
By default, go test needs no arguments. It compiles and tests the package
|
||||||
with source in the current directory, including tests, and runs the tests.
|
with source in the current directory, including tests, and runs the tests.
|
||||||
|
|
||||||
|
|
@ -125,7 +128,10 @@ control the execution of any test:
|
||||||
|
|
||||||
const testFlag2 = `
|
const testFlag2 = `
|
||||||
-bench regexp
|
-bench regexp
|
||||||
Run benchmarks matching the regular expression.
|
Run (sub)benchmarks matching a regular expression.
|
||||||
|
The given regular expression is split into smaller ones by
|
||||||
|
top-level '/', where each must match the corresponding part of a
|
||||||
|
benchmark's identifier.
|
||||||
By default, no benchmarks run. To run all benchmarks,
|
By default, no benchmarks run. To run all benchmarks,
|
||||||
use '-bench .' or '-bench=.'.
|
use '-bench .' or '-bench=.'.
|
||||||
|
|
||||||
|
|
@ -213,8 +219,10 @@ const testFlag2 = `
|
||||||
(see 'go help build').
|
(see 'go help build').
|
||||||
|
|
||||||
-run regexp
|
-run regexp
|
||||||
Run only those tests and examples matching the regular
|
Run only those tests and examples matching the regular expression.
|
||||||
expression.
|
For tests the regular expression is split into smaller ones by
|
||||||
|
top-level '/', where each must match the corresponding part of a
|
||||||
|
test's identifier.
|
||||||
|
|
||||||
-short
|
-short
|
||||||
Tell long-running tests to shorten their run time.
|
Tell long-running tests to shorten their run time.
|
||||||
|
|
@ -228,7 +236,6 @@ const testFlag2 = `
|
||||||
|
|
||||||
-trace trace.out
|
-trace trace.out
|
||||||
Write an execution trace to the specified file before exiting.
|
Write an execution trace to the specified file before exiting.
|
||||||
Writes test binary as -c would.
|
|
||||||
|
|
||||||
-v
|
-v
|
||||||
Verbose output: log all tests as they are run. Also print all
|
Verbose output: log all tests as they are run. Also print all
|
||||||
|
|
@ -256,7 +263,7 @@ execution, not to the test itself.)
|
||||||
The test flags that generate profiles (other than for coverage) also
|
The test flags that generate profiles (other than for coverage) also
|
||||||
leave the test binary in pkg.test for use when analyzing the profiles.
|
leave the test binary in pkg.test for use when analyzing the profiles.
|
||||||
|
|
||||||
When 'go test' runs a test binary, it does so from within the
|
When 'go test' runs a test binary, it does so from within the
|
||||||
corresponding package's source code directory. Depending on the test,
|
corresponding package's source code directory. Depending on the test,
|
||||||
it may be necessary to do the same when invoking a generated test
|
it may be necessary to do the same when invoking a generated test
|
||||||
binary directly.
|
binary directly.
|
||||||
|
|
@ -311,10 +318,11 @@ A benchmark function is one named BenchmarkXXX and should have the signature,
|
||||||
|
|
||||||
An example function is similar to a test function but, instead of using
|
An example function is similar to a test function but, instead of using
|
||||||
*testing.T to report success or failure, prints output to os.Stdout.
|
*testing.T to report success or failure, prints output to os.Stdout.
|
||||||
That output is compared against the function's "Output:" comment, which
|
If the last comment in the function starts with "Output:" then the output
|
||||||
must be the last comment in the function body (see example below). An
|
is compared exactly against the comment (see examples below). If the last
|
||||||
example with no such comment, or with no text after "Output:" is compiled
|
comment begins with "Unordered output:" then the output is compared to the
|
||||||
but not executed.
|
comment, however the order of the lines is ignored. An example with no such
|
||||||
|
comment, or with no text after "Output:" is compiled but not executed.
|
||||||
|
|
||||||
Godoc displays the body of ExampleXXX to demonstrate the use
|
Godoc displays the body of ExampleXXX to demonstrate the use
|
||||||
of the function, constant, or variable XXX. An example of a method M with
|
of the function, constant, or variable XXX. An example of a method M with
|
||||||
|
|
@ -330,6 +338,20 @@ Here is an example of an example:
|
||||||
// this example.
|
// this example.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Here is another example where the ordering of the output is ignored:
|
||||||
|
|
||||||
|
func ExamplePerm() {
|
||||||
|
for _, value := range Perm(4) {
|
||||||
|
fmt.Println(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unordered output: 4
|
||||||
|
// 2
|
||||||
|
// 1
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
|
||||||
The entire test file is presented as the example when it contains a single
|
The entire test file is presented as the example when it contains a single
|
||||||
example function, at least one other function, type, variable, or constant
|
example function, at least one other function, type, variable, or constant
|
||||||
declaration, and no test or benchmark functions.
|
declaration, and no test or benchmark functions.
|
||||||
|
|
@ -388,7 +410,7 @@ func runTest(cmd *Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a test timeout was given and is parseable, set our kill timeout
|
// If a test timeout was given and is parseable, set our kill timeout
|
||||||
// to that timeout plus one minute. This is a backup alarm in case
|
// to that timeout plus one minute. This is a backup alarm in case
|
||||||
// the test wedges with a goroutine spinning and its background
|
// the test wedges with a goroutine spinning and its background
|
||||||
// timer does not get a chance to fire.
|
// timer does not get a chance to fire.
|
||||||
if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 {
|
if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 {
|
||||||
|
|
@ -495,7 +517,8 @@ func runTest(cmd *Command, args []string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p.Stale = true // rebuild
|
p.Stale = true // rebuild
|
||||||
p.fake = true // do not warn about rebuild
|
p.StaleReason = "rebuild for coverage"
|
||||||
|
p.fake = true // do not warn about rebuild
|
||||||
p.coverMode = testCoverMode
|
p.coverMode = testCoverMode
|
||||||
var coverFiles []string
|
var coverFiles []string
|
||||||
coverFiles = append(coverFiles, p.GoFiles...)
|
coverFiles = append(coverFiles, p.GoFiles...)
|
||||||
|
|
@ -700,7 +723,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
|
||||||
// the usual place in the temporary tree, because then
|
// the usual place in the temporary tree, because then
|
||||||
// other tests will see it as the real package.
|
// other tests will see it as the real package.
|
||||||
// Instead we make a _test directory under the import path
|
// Instead we make a _test directory under the import path
|
||||||
// and then repeat the import path there. We tell the
|
// and then repeat the import path there. We tell the
|
||||||
// compiler and linker to look in that _test directory first.
|
// compiler and linker to look in that _test directory first.
|
||||||
//
|
//
|
||||||
// That is, if the package under test is unicode/utf8,
|
// That is, if the package under test is unicode/utf8,
|
||||||
|
|
@ -738,6 +761,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
|
||||||
ptest.fake = true
|
ptest.fake = true
|
||||||
ptest.forceLibrary = true
|
ptest.forceLibrary = true
|
||||||
ptest.Stale = true
|
ptest.Stale = true
|
||||||
|
ptest.StaleReason = "rebuild for test"
|
||||||
ptest.build = new(build.Package)
|
ptest.build = new(build.Package)
|
||||||
*ptest.build = *p.build
|
*ptest.build = *p.build
|
||||||
m := map[string][]token.Position{}
|
m := map[string][]token.Position{}
|
||||||
|
|
@ -1019,6 +1043,7 @@ func recompileForTest(pmain, preal, ptest *Package, testDir string) {
|
||||||
p.target = ""
|
p.target = ""
|
||||||
p.fake = true
|
p.fake = true
|
||||||
p.Stale = true
|
p.Stale = true
|
||||||
|
p.StaleReason = "depends on package being tested"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1218,11 +1243,11 @@ func (b *builder) notest(a *action) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isTestMain tells whether fn is a TestMain(m *testing.M) function.
|
// isTestFunc tells whether fn has the type of a testing function. arg
|
||||||
func isTestMain(fn *ast.FuncDecl) bool {
|
// specifies the parameter type we look for: B, M or T.
|
||||||
if fn.Name.String() != "TestMain" ||
|
func isTestFunc(fn *ast.FuncDecl, arg string) bool {
|
||||||
fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
|
if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
|
||||||
fn.Type.Params == nil ||
|
fn.Type.Params.List == nil ||
|
||||||
len(fn.Type.Params.List) != 1 ||
|
len(fn.Type.Params.List) != 1 ||
|
||||||
len(fn.Type.Params.List[0].Names) > 1 {
|
len(fn.Type.Params.List[0].Names) > 1 {
|
||||||
return false
|
return false
|
||||||
|
|
@ -1234,10 +1259,11 @@ func isTestMain(fn *ast.FuncDecl) bool {
|
||||||
// We can't easily check that the type is *testing.M
|
// We can't easily check that the type is *testing.M
|
||||||
// because we don't know how testing has been imported,
|
// because we don't know how testing has been imported,
|
||||||
// but at least check that it's *M or *something.M.
|
// but at least check that it's *M or *something.M.
|
||||||
if name, ok := ptr.X.(*ast.Ident); ok && name.Name == "M" {
|
// Same applies for B and T.
|
||||||
|
if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == "M" {
|
if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -1334,9 +1360,10 @@ func (t *testFuncs) Tested() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testFunc struct {
|
type testFunc struct {
|
||||||
Package string // imported package name (_test or _xtest)
|
Package string // imported package name (_test or _xtest)
|
||||||
Name string // function name
|
Name string // function name
|
||||||
Output string // output, for examples
|
Output string // output, for examples
|
||||||
|
Unordered bool // output is allowed to be unordered.
|
||||||
}
|
}
|
||||||
|
|
||||||
var testFileSet = token.NewFileSet()
|
var testFileSet = token.NewFileSet()
|
||||||
|
|
@ -1356,17 +1383,25 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
|
||||||
}
|
}
|
||||||
name := n.Name.String()
|
name := n.Name.String()
|
||||||
switch {
|
switch {
|
||||||
case isTestMain(n):
|
case name == "TestMain" && isTestFunc(n, "M"):
|
||||||
if t.TestMain != nil {
|
if t.TestMain != nil {
|
||||||
return errors.New("multiple definitions of TestMain")
|
return errors.New("multiple definitions of TestMain")
|
||||||
}
|
}
|
||||||
t.TestMain = &testFunc{pkg, name, ""}
|
t.TestMain = &testFunc{pkg, name, "", false}
|
||||||
*doImport, *seen = true, true
|
*doImport, *seen = true, true
|
||||||
case isTest(name, "Test"):
|
case isTest(name, "Test"):
|
||||||
t.Tests = append(t.Tests, testFunc{pkg, name, ""})
|
err := checkTestFunc(n, "T")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
|
||||||
*doImport, *seen = true, true
|
*doImport, *seen = true, true
|
||||||
case isTest(name, "Benchmark"):
|
case isTest(name, "Benchmark"):
|
||||||
t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""})
|
err := checkTestFunc(n, "B")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false})
|
||||||
*doImport, *seen = true, true
|
*doImport, *seen = true, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1378,12 +1413,21 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
|
||||||
// Don't run examples with no output.
|
// Don't run examples with no output.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output})
|
t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered})
|
||||||
*seen = true
|
*seen = true
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkTestFunc(fn *ast.FuncDecl, arg string) error {
|
||||||
|
if !isTestFunc(fn, arg) {
|
||||||
|
name := fn.Name.String()
|
||||||
|
pos := testFileSet.Position(fn.Pos())
|
||||||
|
return fmt.Errorf("%s: wrong signature for %s, must be: func %s(%s *testing.%s)", pos, name, name, strings.ToLower(arg), arg)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type byOrder []*doc.Example
|
type byOrder []*doc.Example
|
||||||
|
|
||||||
func (x byOrder) Len() int { return len(x) }
|
func (x byOrder) Len() int { return len(x) }
|
||||||
|
|
@ -1429,7 +1473,7 @@ var benchmarks = []testing.InternalBenchmark{
|
||||||
|
|
||||||
var examples = []testing.InternalExample{
|
var examples = []testing.InternalExample{
|
||||||
{{range .Examples}}
|
{{range .Examples}}
|
||||||
{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}},
|
{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
|
||||||
{{end}}
|
{{end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package benchfatal
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func BenchmarkThatCallsFatal(b *testing.B) {
|
||||||
|
b.Fatal("called by benchmark")
|
||||||
|
}
|
||||||
|
|
@ -149,9 +149,11 @@ func testFlags(args []string) (packageNames, passToTest []string) {
|
||||||
testBench = true
|
testBench = true
|
||||||
case "timeout":
|
case "timeout":
|
||||||
testTimeout = value
|
testTimeout = value
|
||||||
case "blockprofile", "cpuprofile", "memprofile", "trace":
|
case "blockprofile", "cpuprofile", "memprofile":
|
||||||
testProfile = true
|
testProfile = true
|
||||||
testNeedBinary = true
|
testNeedBinary = true
|
||||||
|
case "trace":
|
||||||
|
testProfile = true
|
||||||
case "coverpkg":
|
case "coverpkg":
|
||||||
testCover = true
|
testCover = true
|
||||||
if value == "" {
|
if value == "" {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -93,7 +93,7 @@ var vcsHg = &vcsCmd{
|
||||||
downloadCmd: []string{"pull"},
|
downloadCmd: []string{"pull"},
|
||||||
|
|
||||||
// We allow both tag and branch names as 'tags'
|
// We allow both tag and branch names as 'tags'
|
||||||
// for selecting a version. This lets people have
|
// for selecting a version. This lets people have
|
||||||
// a go.release.r60 branch and a go1 branch
|
// a go.release.r60 branch and a go1 branch
|
||||||
// and make changes in both, without constantly
|
// and make changes in both, without constantly
|
||||||
// editing .hgtags.
|
// editing .hgtags.
|
||||||
|
|
@ -171,10 +171,10 @@ func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error
|
||||||
// Eg, "git@github.com:user/repo" becomes
|
// Eg, "git@github.com:user/repo" becomes
|
||||||
// "ssh://git@github.com/user/repo".
|
// "ssh://git@github.com/user/repo".
|
||||||
repoURL = &url.URL{
|
repoURL = &url.URL{
|
||||||
Scheme: "ssh",
|
Scheme: "ssh",
|
||||||
User: url.User(m[1]),
|
User: url.User(m[1]),
|
||||||
Host: m[2],
|
Host: m[2],
|
||||||
RawPath: m[3],
|
Path: m[3],
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
repoURL, err = url.Parse(out)
|
repoURL, err = url.Parse(out)
|
||||||
|
|
@ -253,7 +253,7 @@ func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string
|
||||||
return "", fmt.Errorf("unable to parse output of bzr info")
|
return "", fmt.Errorf("unable to parse output of bzr info")
|
||||||
}
|
}
|
||||||
out = out[:i]
|
out = out[:i]
|
||||||
return strings.TrimSpace(string(out)), nil
|
return strings.TrimSpace(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// vcsSvn describes how to use Subversion.
|
// vcsSvn describes how to use Subversion.
|
||||||
|
|
@ -294,7 +294,7 @@ func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error
|
||||||
return "", fmt.Errorf("unable to parse output of svn info")
|
return "", fmt.Errorf("unable to parse output of svn info")
|
||||||
}
|
}
|
||||||
out = out[:i]
|
out = out[:i]
|
||||||
return strings.TrimSpace(string(out)), nil
|
return strings.TrimSpace(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *vcsCmd) String() string {
|
func (v *vcsCmd) String() string {
|
||||||
|
|
@ -383,9 +383,6 @@ func (v *vcsCmd) ping(scheme, repo string) error {
|
||||||
// The parent of dir must exist; dir must not.
|
// The parent of dir must exist; dir must not.
|
||||||
func (v *vcsCmd) create(dir, repo string) error {
|
func (v *vcsCmd) create(dir, repo string) error {
|
||||||
for _, cmd := range v.createCmd {
|
for _, cmd := range v.createCmd {
|
||||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
|
if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -396,9 +393,6 @@ func (v *vcsCmd) create(dir, repo string) error {
|
||||||
// download downloads any new changes for the repo in dir.
|
// download downloads any new changes for the repo in dir.
|
||||||
func (v *vcsCmd) download(dir string) error {
|
func (v *vcsCmd) download(dir string) error {
|
||||||
for _, cmd := range v.downloadCmd {
|
for _, cmd := range v.downloadCmd {
|
||||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := v.run(dir, cmd); err != nil {
|
if err := v.run(dir, cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -445,9 +439,6 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
|
||||||
|
|
||||||
if tag == "" && v.tagSyncDefault != nil {
|
if tag == "" && v.tagSyncDefault != nil {
|
||||||
for _, cmd := range v.tagSyncDefault {
|
for _, cmd := range v.tagSyncDefault {
|
||||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := v.run(dir, cmd); err != nil {
|
if err := v.run(dir, cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -456,9 +447,6 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cmd := range v.tagSyncCmd {
|
for _, cmd := range v.tagSyncCmd {
|
||||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := v.run(dir, cmd, "tag", tag); err != nil {
|
if err := v.run(dir, cmd, "tag", tag); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -479,15 +467,14 @@ type vcsPath struct {
|
||||||
regexp *regexp.Regexp // cached compiled form of re
|
regexp *regexp.Regexp // cached compiled form of re
|
||||||
}
|
}
|
||||||
|
|
||||||
// vcsForDir inspects dir and its parents to determine the
|
// vcsFromDir inspects dir and its parents to determine the
|
||||||
// version control system and code repository to use.
|
// version control system and code repository to use.
|
||||||
// On return, root is the import path
|
// On return, root is the import path
|
||||||
// corresponding to the root of the repository
|
// corresponding to the root of the repository.
|
||||||
// (thus root is a prefix of importPath).
|
func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
|
||||||
func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) {
|
|
||||||
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
|
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
|
||||||
dir := filepath.Clean(p.Dir)
|
dir = filepath.Clean(dir)
|
||||||
srcRoot := filepath.Clean(p.build.SrcRoot)
|
srcRoot = filepath.Clean(srcRoot)
|
||||||
if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
|
if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
|
||||||
return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
|
return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
|
||||||
}
|
}
|
||||||
|
|
@ -496,7 +483,7 @@ func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) {
|
||||||
for len(dir) > len(srcRoot) {
|
for len(dir) > len(srcRoot) {
|
||||||
for _, vcs := range vcsList {
|
for _, vcs := range vcsList {
|
||||||
if fi, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil && fi.IsDir() {
|
if fi, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil && fi.IsDir() {
|
||||||
return vcs, dir[len(srcRoot)+1:], nil
|
return vcs, filepath.ToSlash(dir[len(srcRoot)+1:]), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -780,15 +767,31 @@ type metaImport struct {
|
||||||
// errNoMatch is returned from matchGoImport when there's no applicable match.
|
// errNoMatch is returned from matchGoImport when there's no applicable match.
|
||||||
var errNoMatch = errors.New("no import match")
|
var errNoMatch = errors.New("no import match")
|
||||||
|
|
||||||
|
func splitPathHasPrefix(path, prefix []string) bool {
|
||||||
|
if len(path) < len(prefix) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, p := range prefix {
|
||||||
|
if path[i] != p {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// matchGoImport returns the metaImport from imports matching importPath.
|
// matchGoImport returns the metaImport from imports matching importPath.
|
||||||
// An error is returned if there are multiple matches.
|
// An error is returned if there are multiple matches.
|
||||||
// errNoMatch is returned if none match.
|
// errNoMatch is returned if none match.
|
||||||
func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) {
|
func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) {
|
||||||
match := -1
|
match := -1
|
||||||
|
imp := strings.Split(importPath, "/")
|
||||||
for i, im := range imports {
|
for i, im := range imports {
|
||||||
if !strings.HasPrefix(importPath, im.Prefix) {
|
pre := strings.Split(im.Prefix, "/")
|
||||||
|
|
||||||
|
if !splitPathHasPrefix(imp, pre) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if match != -1 {
|
if match != -1 {
|
||||||
err = fmt.Errorf("multiple meta tags match import path %q", importPath)
|
err = fmt.Errorf("multiple meta tags match import path %q", importPath)
|
||||||
return
|
return
|
||||||
|
|
@ -815,20 +818,6 @@ func expand(match map[string]string, s string) string {
|
||||||
// and import paths referring to a fully-qualified importPath
|
// and import paths referring to a fully-qualified importPath
|
||||||
// containing a VCS type (foo.com/repo.git/dir)
|
// containing a VCS type (foo.com/repo.git/dir)
|
||||||
var vcsPaths = []*vcsPath{
|
var vcsPaths = []*vcsPath{
|
||||||
// Google Code - new syntax
|
|
||||||
{
|
|
||||||
prefix: "code.google.com/",
|
|
||||||
re: `^(?P<root>code\.google\.com/p/(?P<project>[a-z0-9\-]+)(\.(?P<subrepo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
|
|
||||||
repo: "https://{root}",
|
|
||||||
check: googleCodeVCS,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Google Code - old syntax
|
|
||||||
{
|
|
||||||
re: `^(?P<project>[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P<path>/.*)?$`,
|
|
||||||
check: oldGoogleCode,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Github
|
// Github
|
||||||
{
|
{
|
||||||
prefix: "github.com/",
|
prefix: "github.com/",
|
||||||
|
|
@ -863,6 +852,14 @@ var vcsPaths = []*vcsPath{
|
||||||
repo: "https://{root}",
|
repo: "https://{root}",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Git at OpenStack
|
||||||
|
{
|
||||||
|
prefix: "git.openstack.org",
|
||||||
|
re: `^(?P<root>git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`,
|
||||||
|
vcs: "git",
|
||||||
|
repo: "https://{root}",
|
||||||
|
},
|
||||||
|
|
||||||
// General syntax for any server.
|
// General syntax for any server.
|
||||||
// Must be last.
|
// Must be last.
|
||||||
{
|
{
|
||||||
|
|
@ -911,45 +908,6 @@ func noVCSSuffix(match map[string]string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
|
|
||||||
|
|
||||||
// googleCodeVCS determines the version control system for
|
|
||||||
// a code.google.com repository, by scraping the project's
|
|
||||||
// /source/checkout page.
|
|
||||||
func googleCodeVCS(match map[string]string) error {
|
|
||||||
if err := noVCSSuffix(match); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if m := googleCheckout.FindSubmatch(data); m != nil {
|
|
||||||
if vcs := vcsByCmd(string(m[1])); vcs != nil {
|
|
||||||
// Subversion requires the old URLs.
|
|
||||||
// TODO: Test.
|
|
||||||
if vcs == vcsSvn {
|
|
||||||
if match["subrepo"] != "" {
|
|
||||||
return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects")
|
|
||||||
}
|
|
||||||
match["repo"] = expand(match, "https://{project}.googlecode.com/svn")
|
|
||||||
}
|
|
||||||
match["vcs"] = vcs.cmd
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("unable to detect version control system for code.google.com/ path")
|
|
||||||
}
|
|
||||||
|
|
||||||
// oldGoogleCode is invoked for old-style foo.googlecode.com paths.
|
|
||||||
// It prints an error giving the equivalent new path.
|
|
||||||
func oldGoogleCode(match map[string]string) error {
|
|
||||||
return fmt.Errorf("invalid Google Code import path: use %s instead",
|
|
||||||
expand(match, "code.google.com/p/{project}{path}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// bitbucketVCS determines the version control system for a
|
// bitbucketVCS determines the version control system for a
|
||||||
// Bitbucket repository, by using the Bitbucket API.
|
// Bitbucket repository, by using the Bitbucket API.
|
||||||
func bitbucketVCS(match map[string]string) error {
|
func bitbucketVCS(match map[string]string) error {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -18,20 +23,6 @@ func TestRepoRootForImportPath(t *testing.T) {
|
||||||
path string
|
path string
|
||||||
want *repoRoot
|
want *repoRoot
|
||||||
}{
|
}{
|
||||||
/*{
|
|
||||||
"code.google.com/p/go",
|
|
||||||
&repoRoot{
|
|
||||||
vcs: vcsHg,
|
|
||||||
repo: "https://code.google.com/p/go",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"code.google.com/r/go",
|
|
||||||
&repoRoot{
|
|
||||||
vcs: vcsHg,
|
|
||||||
repo: "https://code.google.com/r/go",
|
|
||||||
},
|
|
||||||
},*/
|
|
||||||
{
|
{
|
||||||
"github.com/golang/groupcache",
|
"github.com/golang/groupcache",
|
||||||
&repoRoot{
|
&repoRoot{
|
||||||
|
|
@ -96,6 +87,39 @@ func TestRepoRootForImportPath(t *testing.T) {
|
||||||
"hub.jazz.net/git/USER/pkgname",
|
"hub.jazz.net/git/USER/pkgname",
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
// OpenStack tests
|
||||||
|
{
|
||||||
|
"git.openstack.org/openstack/swift",
|
||||||
|
&repoRoot{
|
||||||
|
vcs: vcsGit,
|
||||||
|
repo: "https://git.openstack.org/openstack/swift",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Trailing .git is less preferred but included for
|
||||||
|
// compatibility purposes while the same source needs to
|
||||||
|
// be compilable on both old and new go
|
||||||
|
{
|
||||||
|
"git.openstack.org/openstack/swift.git",
|
||||||
|
&repoRoot{
|
||||||
|
vcs: vcsGit,
|
||||||
|
repo: "https://git.openstack.org/openstack/swift",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"git.openstack.org/openstack/swift/go/hummingbird",
|
||||||
|
&repoRoot{
|
||||||
|
vcs: vcsGit,
|
||||||
|
repo: "https://git.openstack.org/openstack/swift",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"git.openstack.org",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"git.openstack.org/openstack",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
// Spaces are not valid in package name
|
// Spaces are not valid in package name
|
||||||
{
|
{
|
||||||
"git.apache.org/package name/path/to/lib",
|
"git.apache.org/package name/path/to/lib",
|
||||||
|
|
@ -142,6 +166,37 @@ func TestRepoRootForImportPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that vcsFromDir correctly inspects a given directory and returns the right VCS and root.
|
||||||
|
func TestFromDir(t *testing.T) {
|
||||||
|
tempDir, err := ioutil.TempDir("", "vcstest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
|
for _, vcs := range vcsList {
|
||||||
|
dir := filepath.Join(tempDir, "example.com", vcs.name, "."+vcs.cmd)
|
||||||
|
err := os.MkdirAll(dir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := repoRoot{
|
||||||
|
vcs: vcs,
|
||||||
|
root: path.Join("example.com", vcs.name),
|
||||||
|
}
|
||||||
|
var got repoRoot
|
||||||
|
got.vcs, got.root, err = vcsFromDir(dir, tempDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if got.vcs.name != want.vcs.name || got.root != want.root {
|
||||||
|
t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", dir, tempDir, got.vcs, got.root, want.vcs, want.root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsSecure(t *testing.T) {
|
func TestIsSecure(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
vcs *vcsCmd
|
vcs *vcsCmd
|
||||||
|
|
@ -173,3 +228,96 @@ func TestIsSecure(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMatchGoImport(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
imports []metaImport
|
||||||
|
path string
|
||||||
|
mi metaImport
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/foo",
|
||||||
|
mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/foo/",
|
||||||
|
mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
{Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/foo",
|
||||||
|
mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
{Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/fooa",
|
||||||
|
mi: metaImport{Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/foo/bar",
|
||||||
|
err: errors.New("should not be allowed to create nested repo"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/foo/bar/baz",
|
||||||
|
err: errors.New("should not be allowed to create nested repo"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/foo/bar/baz/qux",
|
||||||
|
err: errors.New("should not be allowed to create nested repo"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com/user/foo/bar/baz/",
|
||||||
|
err: errors.New("should not be allowed to create nested repo"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imports: []metaImport{
|
||||||
|
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
|
||||||
|
},
|
||||||
|
path: "example.com",
|
||||||
|
err: errors.New("pathologically short path"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
mi, err := matchGoImport(test.imports, test.path)
|
||||||
|
if mi != test.mi {
|
||||||
|
t.Errorf("unexpected metaImport; got %v, want %v", mi, test.mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := err
|
||||||
|
want := test.err
|
||||||
|
if (got == nil) != (want == nil) {
|
||||||
|
t.Errorf("unexpected error; got %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -20,7 +20,6 @@ func TestVendorImports(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...")
|
tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...")
|
||||||
want := `
|
want := `
|
||||||
vend [vend/vendor/p r]
|
vend [vend/vendor/p r]
|
||||||
|
|
@ -51,7 +50,6 @@ func TestVendorBuild(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.run("build", "vend/x")
|
tg.run("build", "vend/x")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,7 +57,6 @@ func TestVendorRun(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
|
tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
|
||||||
tg.run("run", "hello.go")
|
tg.run("run", "hello.go")
|
||||||
tg.grepStdout("hello, world", "missing hello world output")
|
tg.grepStdout("hello, world", "missing hello world output")
|
||||||
|
|
@ -74,7 +71,6 @@ func TestVendorGOPATH(t *testing.T) {
|
||||||
}
|
}
|
||||||
gopath := changeVolume(filepath.Join(tg.pwd(), "testdata"), strings.ToLower)
|
gopath := changeVolume(filepath.Join(tg.pwd(), "testdata"), strings.ToLower)
|
||||||
tg.setenv("GOPATH", gopath)
|
tg.setenv("GOPATH", gopath)
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
cd := changeVolume(filepath.Join(tg.pwd(), "testdata/src/vend/hello"), strings.ToUpper)
|
cd := changeVolume(filepath.Join(tg.pwd(), "testdata/src/vend/hello"), strings.ToUpper)
|
||||||
tg.cd(cd)
|
tg.cd(cd)
|
||||||
tg.run("run", "hello.go")
|
tg.run("run", "hello.go")
|
||||||
|
|
@ -85,7 +81,6 @@ func TestVendorTest(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
|
tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
|
||||||
tg.run("test", "-v")
|
tg.run("test", "-v")
|
||||||
tg.grepStdout("TestMsgInternal", "missing use in internal test")
|
tg.grepStdout("TestMsgInternal", "missing use in internal test")
|
||||||
|
|
@ -96,7 +91,6 @@ func TestVendorInvalid(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
|
|
||||||
tg.runFail("build", "vend/x/invalid")
|
tg.runFail("build", "vend/x/invalid")
|
||||||
tg.grepStderr("must be imported as foo", "missing vendor import error")
|
tg.grepStderr("must be imported as foo", "missing vendor import error")
|
||||||
|
|
@ -106,7 +100,6 @@ func TestVendorImportError(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
|
|
||||||
tg.runFail("build", "vend/x/vendor/p/p")
|
tg.runFail("build", "vend/x/vendor/p/p")
|
||||||
|
|
||||||
|
|
@ -173,7 +166,6 @@ func TestVendorGet(t *testing.T) {
|
||||||
package p
|
package p
|
||||||
const C = 1`)
|
const C = 1`)
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.cd(tg.path("src/v"))
|
tg.cd(tg.path("src/v"))
|
||||||
tg.run("run", "m.go")
|
tg.run("run", "m.go")
|
||||||
tg.run("test")
|
tg.run("test")
|
||||||
|
|
@ -192,7 +184,6 @@ func TestVendorGetUpdate(t *testing.T) {
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.makeTempdir()
|
tg.makeTempdir()
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.run("get", "github.com/rsc/go-get-issue-11864")
|
tg.run("get", "github.com/rsc/go-get-issue-11864")
|
||||||
tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
|
tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
|
||||||
}
|
}
|
||||||
|
|
@ -204,16 +195,15 @@ func TestGetSubmodules(t *testing.T) {
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.makeTempdir()
|
tg.makeTempdir()
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.run("get", "-d", "github.com/rsc/go-get-issue-12612")
|
tg.run("get", "-d", "github.com/rsc/go-get-issue-12612")
|
||||||
tg.run("get", "-u", "-d", "github.com/rsc/go-get-issue-12612")
|
tg.run("get", "-u", "-d", "github.com/rsc/go-get-issue-12612")
|
||||||
|
tg.mustExist(tg.path("src/github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVendorCache(t *testing.T) {
|
func TestVendorCache(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.runFail("build", "p")
|
tg.runFail("build", "p")
|
||||||
tg.grepStderr("must be imported as x", "did not fail to build p")
|
tg.grepStderr("must be imported as x", "did not fail to build p")
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +215,6 @@ func TestVendorTest2(t *testing.T) {
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.makeTempdir()
|
tg.makeTempdir()
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.run("get", "github.com/rsc/go-get-issue-11864")
|
tg.run("get", "github.com/rsc/go-get-issue-11864")
|
||||||
|
|
||||||
// build -i should work
|
// build -i should work
|
||||||
|
|
@ -244,6 +233,32 @@ func TestVendorTest2(t *testing.T) {
|
||||||
tg.run("test", "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2")
|
tg.run("test", "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVendorTest3(t *testing.T) {
|
||||||
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.makeTempdir()
|
||||||
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
|
tg.run("get", "github.com/clsung/go-vendor-issue-14613")
|
||||||
|
|
||||||
|
tg.run("build", "-o", tg.path("a.out"), "-i", "github.com/clsung/go-vendor-issue-14613")
|
||||||
|
|
||||||
|
// test folder should work
|
||||||
|
tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613")
|
||||||
|
tg.run("test", "github.com/clsung/go-vendor-issue-14613")
|
||||||
|
|
||||||
|
// test with specified _test.go should work too
|
||||||
|
tg.cd(filepath.Join(tg.path("."), "src"))
|
||||||
|
tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
|
||||||
|
tg.run("test", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
|
||||||
|
|
||||||
|
// test with imported and not used
|
||||||
|
tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
|
||||||
|
tg.runFail("test", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
|
||||||
|
tg.grepStderr("imported and not used:", `should say "imported and not used"`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestVendorList(t *testing.T) {
|
func TestVendorList(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
|
||||||
|
|
@ -251,7 +266,6 @@ func TestVendorList(t *testing.T) {
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.makeTempdir()
|
tg.makeTempdir()
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.run("get", "github.com/rsc/go-get-issue-11864")
|
tg.run("get", "github.com/rsc/go-get-issue-11864")
|
||||||
|
|
||||||
tg.run("list", "-f", `{{join .TestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/t")
|
tg.run("list", "-f", `{{join .TestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/t")
|
||||||
|
|
@ -272,7 +286,6 @@ func TestVendor12156(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2"))
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2"))
|
||||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
|
||||||
tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p"))
|
tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p"))
|
||||||
tg.runFail("build", "p.go")
|
tg.runFail("build", "p.go")
|
||||||
tg.grepStderrNot("panic", "panicked")
|
tg.grepStderrNot("panic", "panicked")
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,6 @@ func report(err error) {
|
||||||
func usage() {
|
func usage() {
|
||||||
fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
|
fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initParserMode() {
|
func initParserMode() {
|
||||||
|
|
@ -143,7 +142,9 @@ func visitFile(path string, f os.FileInfo, err error) error {
|
||||||
if err == nil && isGoFile(f) {
|
if err == nil && isGoFile(f) {
|
||||||
err = processFile(path, nil, os.Stdout, false)
|
err = processFile(path, nil, os.Stdout, false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
// Don't complain if a file was deleted in the meantime (i.e.
|
||||||
|
// the directory changed concurrently while running gofmt).
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
report(err)
|
report(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ func TestCRLF(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
if bytes.Index(data, []byte("\r\n")) < 0 {
|
if !bytes.Contains(data, []byte("\r\n")) {
|
||||||
t.Errorf("%s contains no CR/LF's", input)
|
t.Errorf("%s contains no CR/LF's", input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,7 +167,7 @@ func TestCRLF(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
if bytes.Index(data, []byte("\r")) >= 0 {
|
if bytes.Contains(data, []byte("\r")) {
|
||||||
t.Errorf("%s contains CR's", golden)
|
t.Errorf("%s contains CR's", golden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
|
||||||
) {
|
) {
|
||||||
// Try as whole source file.
|
// Try as whole source file.
|
||||||
file, err = parser.ParseFile(fset, filename, src, parserMode)
|
file, err = parser.ParseFile(fset, filename, src, parserMode)
|
||||||
// If there's no error, return. If the error is that the source file didn't begin with a
|
// If there's no error, return. If the error is that the source file didn't begin with a
|
||||||
// package line and source fragments are ok, fall through to
|
// package line and source fragments are ok, fall through to
|
||||||
// try as a source fragment. Stop and return on any other error.
|
// try as a source fragment. Stop and return on any other error.
|
||||||
if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") {
|
if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +59,7 @@ func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
|
||||||
|
|
||||||
// If this is a statement list, make it a source file
|
// If this is a statement list, make it a source file
|
||||||
// by inserting a package clause and turning the list
|
// by inserting a package clause and turning the list
|
||||||
// into a function body. This handles expressions too.
|
// into a function body. This handles expressions too.
|
||||||
// Insert using a ;, not a newline, so that the line numbers
|
// Insert using a ;, not a newline, so that the line numbers
|
||||||
// in fsrc match the ones in src. Add an extra '\n' before the '}'
|
// in fsrc match the ones in src. Add an extra '\n' before the '}'
|
||||||
// to make sure comments are flushed before the '}'.
|
// to make sure comments are flushed before the '}'.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ func isWildcard(s string) bool {
|
||||||
// recording wildcard submatches in m.
|
// recording wildcard submatches in m.
|
||||||
// If m == nil, match checks whether pattern == val.
|
// If m == nil, match checks whether pattern == val.
|
||||||
func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
|
func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
|
||||||
// Wildcard matches any expression. If it appears multiple
|
// Wildcard matches any expression. If it appears multiple
|
||||||
// times in the pattern, it must match the same expression
|
// times in the pattern, it must match the same expression
|
||||||
// each time.
|
// each time.
|
||||||
if m != nil && pattern.IsValid() && pattern.Type() == identType {
|
if m != nil && pattern.IsValid() && pattern.Type() == identType {
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,9 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type simplifier struct {
|
type simplifier struct{}
|
||||||
hasDotImport bool // package file contains: import . "some/import/path"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *simplifier) Visit(node ast.Node) ast.Visitor {
|
func (s simplifier) Visit(node ast.Node) ast.Visitor {
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
case *ast.CompositeLit:
|
case *ast.CompositeLit:
|
||||||
// array, slice, and map composite literals may be simplified
|
// array, slice, and map composite literals may be simplified
|
||||||
|
|
@ -68,10 +66,13 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
|
||||||
// a slice expression of the form: s[a:len(s)]
|
// a slice expression of the form: s[a:len(s)]
|
||||||
// can be simplified to: s[a:]
|
// can be simplified to: s[a:]
|
||||||
// if s is "simple enough" (for now we only accept identifiers)
|
// if s is "simple enough" (for now we only accept identifiers)
|
||||||
if n.Max != nil || s.hasDotImport {
|
//
|
||||||
|
// Note: This may not be correct because len may have been redeclared in another
|
||||||
|
// file belonging to the same package. However, this is extremely unlikely
|
||||||
|
// and so far (April 2016, after years of supporting this rewrite feature)
|
||||||
|
// has never come up, so let's keep it working as is (see also #15153).
|
||||||
|
if n.Max != nil {
|
||||||
// - 3-index slices always require the 2nd and 3rd index
|
// - 3-index slices always require the 2nd and 3rd index
|
||||||
// - if dot imports are present, we cannot be certain that an
|
|
||||||
// unresolved "len" identifier refers to the predefined len()
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil {
|
if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil {
|
||||||
|
|
@ -118,20 +119,11 @@ func isBlank(x ast.Expr) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func simplify(f *ast.File) {
|
func simplify(f *ast.File) {
|
||||||
var s simplifier
|
|
||||||
|
|
||||||
// determine if f contains dot imports
|
|
||||||
for _, imp := range f.Imports {
|
|
||||||
if imp.Name != nil && imp.Name.Name == "." {
|
|
||||||
s.hasDotImport = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove empty declarations such as "const ()", etc
|
// remove empty declarations such as "const ()", etc
|
||||||
removeEmptyDeclGroups(f)
|
removeEmptyDeclGroups(f)
|
||||||
|
|
||||||
ast.Walk(&s, f)
|
var s simplifier
|
||||||
|
ast.Walk(s, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeEmptyDeclGroups(f *ast.File) {
|
func removeEmptyDeclGroups(f *ast.File) {
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
//gofmt -s
|
|
||||||
|
|
||||||
// Test cases for slice expression simplification.
|
|
||||||
// Because of a dot import, these slices must remain untouched.
|
|
||||||
package p
|
|
||||||
|
|
||||||
import . "math"
|
|
||||||
|
|
||||||
var (
|
|
||||||
a [10]byte
|
|
||||||
b [20]float32
|
|
||||||
s []int
|
|
||||||
t struct {
|
|
||||||
s []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = a[0:]
|
|
||||||
_ = a[1:10]
|
|
||||||
_ = a[2:len(a)]
|
|
||||||
_ = a[3:(len(a))]
|
|
||||||
_ = a[len(a) : len(a)-1]
|
|
||||||
_ = a[0:len(b)]
|
|
||||||
|
|
||||||
_ = a[:]
|
|
||||||
_ = a[:10]
|
|
||||||
_ = a[:len(a)]
|
|
||||||
_ = a[:(len(a))]
|
|
||||||
_ = a[:len(a)-1]
|
|
||||||
_ = a[:len(b)]
|
|
||||||
|
|
||||||
_ = s[0:]
|
|
||||||
_ = s[1:10]
|
|
||||||
_ = s[2:len(s)]
|
|
||||||
_ = s[3:(len(s))]
|
|
||||||
_ = s[len(a) : len(s)-1]
|
|
||||||
_ = s[0:len(b)]
|
|
||||||
|
|
||||||
_ = s[:]
|
|
||||||
_ = s[:10]
|
|
||||||
_ = s[:len(s)]
|
|
||||||
_ = s[:(len(s))]
|
|
||||||
_ = s[:len(s)-1]
|
|
||||||
_ = s[:len(b)]
|
|
||||||
|
|
||||||
_ = t.s[0:]
|
|
||||||
_ = t.s[1:10]
|
|
||||||
_ = t.s[2:len(t.s)]
|
|
||||||
_ = t.s[3:(len(t.s))]
|
|
||||||
_ = t.s[len(a) : len(t.s)-1]
|
|
||||||
_ = t.s[0:len(b)]
|
|
||||||
|
|
||||||
_ = t.s[:]
|
|
||||||
_ = t.s[:10]
|
|
||||||
_ = t.s[:len(t.s)]
|
|
||||||
_ = t.s[:(len(t.s))]
|
|
||||||
_ = t.s[:len(t.s)-1]
|
|
||||||
_ = t.s[:len(b)]
|
|
||||||
)
|
|
||||||
|
|
||||||
func _() {
|
|
||||||
s := s[0:len(s)]
|
|
||||||
_ = s
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
//gofmt -s
|
|
||||||
|
|
||||||
// Test cases for slice expression simplification.
|
|
||||||
// Because of a dot import, these slices must remain untouched.
|
|
||||||
package p
|
|
||||||
|
|
||||||
import . "math"
|
|
||||||
|
|
||||||
var (
|
|
||||||
a [10]byte
|
|
||||||
b [20]float32
|
|
||||||
s []int
|
|
||||||
t struct {
|
|
||||||
s []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = a[0:]
|
|
||||||
_ = a[1:10]
|
|
||||||
_ = a[2:len(a)]
|
|
||||||
_ = a[3:(len(a))]
|
|
||||||
_ = a[len(a) : len(a)-1]
|
|
||||||
_ = a[0:len(b)]
|
|
||||||
|
|
||||||
_ = a[:]
|
|
||||||
_ = a[:10]
|
|
||||||
_ = a[:len(a)]
|
|
||||||
_ = a[:(len(a))]
|
|
||||||
_ = a[:len(a)-1]
|
|
||||||
_ = a[:len(b)]
|
|
||||||
|
|
||||||
_ = s[0:]
|
|
||||||
_ = s[1:10]
|
|
||||||
_ = s[2:len(s)]
|
|
||||||
_ = s[3:(len(s))]
|
|
||||||
_ = s[len(a) : len(s)-1]
|
|
||||||
_ = s[0:len(b)]
|
|
||||||
|
|
||||||
_ = s[:]
|
|
||||||
_ = s[:10]
|
|
||||||
_ = s[:len(s)]
|
|
||||||
_ = s[:(len(s))]
|
|
||||||
_ = s[:len(s)-1]
|
|
||||||
_ = s[:len(b)]
|
|
||||||
|
|
||||||
_ = t.s[0:]
|
|
||||||
_ = t.s[1:10]
|
|
||||||
_ = t.s[2:len(t.s)]
|
|
||||||
_ = t.s[3:(len(t.s))]
|
|
||||||
_ = t.s[len(a) : len(t.s)-1]
|
|
||||||
_ = t.s[0:len(b)]
|
|
||||||
|
|
||||||
_ = t.s[:]
|
|
||||||
_ = t.s[:10]
|
|
||||||
_ = t.s[:len(t.s)]
|
|
||||||
_ = t.s[:(len(t.s))]
|
|
||||||
_ = t.s[:len(t.s)-1]
|
|
||||||
_ = t.s[:len(b)]
|
|
||||||
)
|
|
||||||
|
|
||||||
func _() {
|
|
||||||
s := s[0:len(s)]
|
|
||||||
_ = s
|
|
||||||
}
|
|
||||||
|
|
@ -27,9 +27,8 @@ type reader struct {
|
||||||
blockCRC uint32
|
blockCRC uint32
|
||||||
wantBlockCRC uint32
|
wantBlockCRC uint32
|
||||||
setupDone bool // true if we have parsed the bzip2 header.
|
setupDone bool // true if we have parsed the bzip2 header.
|
||||||
blockSize int // blockSize in bytes, i.e. 900 * 1024.
|
blockSize int // blockSize in bytes, i.e. 900 * 1000.
|
||||||
eof bool
|
eof bool
|
||||||
buf []byte // stores Burrows-Wheeler transformed data.
|
|
||||||
c [256]uint // the `C' array for the inverse BWT.
|
c [256]uint // the `C' array for the inverse BWT.
|
||||||
tt []uint32 // mirrors the `tt' array in the bzip2 source and contains the P array in the upper 24 bits.
|
tt []uint32 // mirrors the `tt' array in the bzip2 source and contains the P array in the upper 24 bits.
|
||||||
tPos uint32 // Index of the next output byte in tt.
|
tPos uint32 // Index of the next output byte in tt.
|
||||||
|
|
@ -76,7 +75,7 @@ func (bz2 *reader) setup(needMagic bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
bz2.fileCRC = 0
|
bz2.fileCRC = 0
|
||||||
bz2.blockSize = 100 * 1024 * (int(level) - '0')
|
bz2.blockSize = 100 * 1000 * (level - '0')
|
||||||
if bz2.blockSize > len(bz2.tt) {
|
if bz2.blockSize > len(bz2.tt) {
|
||||||
bz2.tt = make([]uint32, bz2.blockSize)
|
bz2.tt = make([]uint32, bz2.blockSize)
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +293,7 @@ func (bz2 *reader) readBlock() (err error) {
|
||||||
if c >= numHuffmanTrees {
|
if c >= numHuffmanTrees {
|
||||||
return StructuralError("tree index too large")
|
return StructuralError("tree index too large")
|
||||||
}
|
}
|
||||||
treeIndexes[i] = uint8(mtfTreeDecoder.Decode(c))
|
treeIndexes[i] = mtfTreeDecoder.Decode(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The list of symbols for the move-to-front transform is taken from
|
// The list of symbols for the move-to-front transform is taken from
|
||||||
|
|
@ -319,6 +318,9 @@ func (bz2 *reader) readBlock() (err error) {
|
||||||
length := br.ReadBits(5)
|
length := br.ReadBits(5)
|
||||||
for j := range lengths {
|
for j := range lengths {
|
||||||
for {
|
for {
|
||||||
|
if length < 1 || length > 20 {
|
||||||
|
return StructuralError("Huffman length out of range")
|
||||||
|
}
|
||||||
if !br.ReadBit() {
|
if !br.ReadBit() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -328,9 +330,6 @@ func (bz2 *reader) readBlock() (err error) {
|
||||||
length++
|
length++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if length < 0 || length > 20 {
|
|
||||||
return StructuralError("Huffman length out of range")
|
|
||||||
}
|
|
||||||
lengths[j] = uint8(length)
|
lengths[j] = uint8(length)
|
||||||
}
|
}
|
||||||
huffmanTrees[i], err = newHuffmanTree(lengths)
|
huffmanTrees[i], err = newHuffmanTree(lengths)
|
||||||
|
|
@ -400,7 +399,7 @@ func (bz2 *reader) readBlock() (err error) {
|
||||||
return StructuralError("repeats past end of block")
|
return StructuralError("repeats past end of block")
|
||||||
}
|
}
|
||||||
for i := 0; i < repeat; i++ {
|
for i := 0; i < repeat; i++ {
|
||||||
b := byte(mtf.First())
|
b := mtf.First()
|
||||||
bz2.tt[bufIndex] = uint32(b)
|
bz2.tt[bufIndex] = uint32(b)
|
||||||
bz2.c[b]++
|
bz2.c[b]++
|
||||||
bufIndex++
|
bufIndex++
|
||||||
|
|
@ -421,7 +420,7 @@ func (bz2 *reader) readBlock() (err error) {
|
||||||
// it's always referenced with a run-length of 1. Thus 0
|
// it's always referenced with a run-length of 1. Thus 0
|
||||||
// doesn't need to be encoded and we have |v-1| in the next
|
// doesn't need to be encoded and we have |v-1| in the next
|
||||||
// line.
|
// line.
|
||||||
b := byte(mtf.Decode(int(v - 1)))
|
b := mtf.Decode(int(v - 1))
|
||||||
if bufIndex >= bz2.blockSize {
|
if bufIndex >= bz2.blockSize {
|
||||||
return StructuralError("data exceeds block size")
|
return StructuralError("data exceeds block size")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,193 +6,221 @@ package bzip2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBitReader(t *testing.T) {
|
func mustDecodeHex(s string) []byte {
|
||||||
buf := bytes.NewReader([]byte{0xaa})
|
b, err := hex.DecodeString(s)
|
||||||
br := newBitReader(buf)
|
|
||||||
if n := br.ReadBits(1); n != 1 {
|
|
||||||
t.Errorf("read 1 wrong")
|
|
||||||
}
|
|
||||||
if n := br.ReadBits(1); n != 0 {
|
|
||||||
t.Errorf("read 2 wrong")
|
|
||||||
}
|
|
||||||
if n := br.ReadBits(1); n != 1 {
|
|
||||||
t.Errorf("read 3 wrong")
|
|
||||||
}
|
|
||||||
if n := br.ReadBits(1); n != 0 {
|
|
||||||
t.Errorf("read 4 wrong")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBitReaderLarge(t *testing.T) {
|
|
||||||
buf := bytes.NewReader([]byte{0x12, 0x34, 0x56, 0x78})
|
|
||||||
br := newBitReader(buf)
|
|
||||||
if n := br.ReadBits(32); n != 0x12345678 {
|
|
||||||
t.Errorf("got: %x want: %x", n, 0x12345678)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readerFromHex(s string) io.Reader {
|
|
||||||
data, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("readerFromHex: bad input")
|
panic(err)
|
||||||
}
|
}
|
||||||
return bytes.NewReader(data)
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func decompressHex(s string) (out []byte, err error) {
|
func mustLoadFile(f string) []byte {
|
||||||
r := NewReader(readerFromHex(s))
|
b, err := ioutil.ReadFile(f)
|
||||||
return ioutil.ReadAll(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHelloWorldBZ2(t *testing.T) {
|
|
||||||
out, err := decompressHex(helloWorldBZ2Hex)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error from Read: %s", err)
|
panic(err)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(helloWorld, out) {
|
|
||||||
t.Errorf("got %x, want %x", out, helloWorld)
|
|
||||||
}
|
}
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConcat(t *testing.T) {
|
func trim(b []byte) string {
|
||||||
out, err := decompressHex(helloWorldBZ2Hex + helloWorldBZ2Hex)
|
const limit = 1024
|
||||||
if err != nil {
|
if len(b) < limit {
|
||||||
t.Errorf("error from Read: %s", err)
|
return fmt.Sprintf("%q", b)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hello2 := bytes.Repeat(helloWorld, 2)
|
|
||||||
if !bytes.Equal(hello2, out) {
|
|
||||||
t.Errorf("got %x, want %x", out, hello2)
|
|
||||||
}
|
}
|
||||||
|
return fmt.Sprintf("%q...", b[:limit])
|
||||||
}
|
}
|
||||||
|
|
||||||
func testZeros(t *testing.T, inHex string, n int) {
|
func TestReader(t *testing.T) {
|
||||||
out, err := decompressHex(inHex)
|
var vectors = []struct {
|
||||||
if err != nil {
|
desc string
|
||||||
t.Errorf("error from Read: %s", err)
|
input []byte
|
||||||
return
|
output []byte
|
||||||
}
|
fail bool
|
||||||
|
}{{
|
||||||
|
desc: "hello world",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a68393141592653594eece83600000251800010400006449080200031064c" +
|
||||||
|
"4101a7a9a580bb9431f8bb9229c28482776741b0",
|
||||||
|
),
|
||||||
|
output: []byte("hello world\n"),
|
||||||
|
}, {
|
||||||
|
desc: "concatenated files",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a68393141592653594eece83600000251800010400006449080200031064c" +
|
||||||
|
"4101a7a9a580bb9431f8bb9229c28482776741b0425a68393141592653594eec" +
|
||||||
|
"e83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb92" +
|
||||||
|
"29c28482776741b0",
|
||||||
|
),
|
||||||
|
output: []byte("hello world\nhello world\n"),
|
||||||
|
}, {
|
||||||
|
desc: "32B zeros",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a6839314159265359b5aa5098000000600040000004200021008283177245" +
|
||||||
|
"385090b5aa5098",
|
||||||
|
),
|
||||||
|
output: make([]byte, 32),
|
||||||
|
}, {
|
||||||
|
desc: "1MiB zeros",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a683931415926535938571ce50008084000c0040008200030cc0529a60806" +
|
||||||
|
"c4201e2ee48a70a12070ae39ca",
|
||||||
|
),
|
||||||
|
output: make([]byte, 1<<20),
|
||||||
|
}, {
|
||||||
|
desc: "random data",
|
||||||
|
input: mustLoadFile("testdata/pass-random1.bz2"),
|
||||||
|
output: mustLoadFile("testdata/pass-random1.bin"),
|
||||||
|
}, {
|
||||||
|
desc: "random data - full symbol range",
|
||||||
|
input: mustLoadFile("testdata/pass-random2.bz2"),
|
||||||
|
output: mustLoadFile("testdata/pass-random2.bin"),
|
||||||
|
}, {
|
||||||
|
desc: "random data - uses RLE1 stage",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a6839314159265359d992d0f60000137dfe84020310091c1e280e100e0428" +
|
||||||
|
"01099210094806c0110002e70806402000546034000034000000f28300000320" +
|
||||||
|
"00d3403264049270eb7a9280d308ca06ad28f6981bee1bf8160727c7364510d7" +
|
||||||
|
"3a1e123083421b63f031f63993a0f40051fbf177245385090d992d0f60",
|
||||||
|
),
|
||||||
|
output: mustDecodeHex("" +
|
||||||
|
"92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f871" +
|
||||||
|
"9e6c2a2bd4f5f88db07ecd0da3a33b263483db9b2c158786ad6363be35d17335" +
|
||||||
|
"ba",
|
||||||
|
),
|
||||||
|
}, {
|
||||||
|
desc: "1MiB sawtooth",
|
||||||
|
input: mustLoadFile("testdata/pass-sawtooth.bz2"),
|
||||||
|
output: func() []byte {
|
||||||
|
b := make([]byte, 1<<20)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = byte(i)
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}(),
|
||||||
|
}, {
|
||||||
|
desc: "RLE2 buffer overrun - issue 5747",
|
||||||
|
input: mustLoadFile("testdata/fail-issue5747.bz2"),
|
||||||
|
fail: true,
|
||||||
|
}, {
|
||||||
|
desc: "out-of-range selector - issue 8363",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a68393141592653594eece83600000251800010400006449080200031064c" +
|
||||||
|
"4101a7a9a580bb943117724538509000000000",
|
||||||
|
),
|
||||||
|
fail: true,
|
||||||
|
}, {
|
||||||
|
desc: "bad block size - issue 13941",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a683131415926535936dc55330063ffc0006000200020a40830008b0008b8" +
|
||||||
|
"bb9229c28481b6e2a998",
|
||||||
|
),
|
||||||
|
fail: true,
|
||||||
|
}, {
|
||||||
|
desc: "bad huffman delta",
|
||||||
|
input: mustDecodeHex("" +
|
||||||
|
"425a6836314159265359b1f7404b000000400040002000217d184682ee48a70a" +
|
||||||
|
"12163ee80960",
|
||||||
|
),
|
||||||
|
fail: true,
|
||||||
|
}}
|
||||||
|
|
||||||
expected := make([]byte, n)
|
for i, v := range vectors {
|
||||||
|
rd := NewReader(bytes.NewReader(v.input))
|
||||||
|
buf, err := ioutil.ReadAll(rd)
|
||||||
|
|
||||||
if !bytes.Equal(expected, out) {
|
if fail := bool(err != nil); fail != v.fail {
|
||||||
allZeros := true
|
if fail {
|
||||||
for _, b := range out {
|
t.Errorf("test %d (%s), unexpected failure: %v", i, v.desc, err)
|
||||||
if b != 0 {
|
} else {
|
||||||
allZeros = false
|
t.Errorf("test %d (%s), unexpected success", i, v.desc)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Errorf("incorrect result, got %d bytes (allZeros: %t)", len(out), allZeros)
|
if !v.fail && !bytes.Equal(buf, v.output) {
|
||||||
|
t.Errorf("test %d (%s), output mismatch:\ngot %s\nwant %s", i, v.desc, trim(buf), trim(v.output))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test32Zeros(t *testing.T) {
|
func TestBitReader(t *testing.T) {
|
||||||
testZeros(t, thirtyTwoZerosBZ2Hex, 32)
|
var vectors = []struct {
|
||||||
}
|
nbits uint // Number of bits to read
|
||||||
|
value int // Expected output value (0 for error)
|
||||||
func Test1MBZeros(t *testing.T) {
|
fail bool // Expected operation failure?
|
||||||
testZeros(t, oneMBZerosBZ2Hex, 1024*1024)
|
}{
|
||||||
}
|
{nbits: 1, value: 1},
|
||||||
|
{nbits: 1, value: 0},
|
||||||
func testRandomData(t *testing.T, compressedHex, uncompressedHex string) {
|
{nbits: 1, value: 1},
|
||||||
out, err := decompressHex(compressedHex)
|
{nbits: 5, value: 11},
|
||||||
if err != nil {
|
{nbits: 32, value: 0x12345678},
|
||||||
t.Errorf("error from Read: %s", err)
|
{nbits: 15, value: 14495},
|
||||||
return
|
{nbits: 3, value: 6},
|
||||||
|
{nbits: 6, value: 13},
|
||||||
|
{nbits: 1, fail: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected, _ := hex.DecodeString(uncompressedHex)
|
rd := bytes.NewReader([]byte{0xab, 0x12, 0x34, 0x56, 0x78, 0x71, 0x3f, 0x8d})
|
||||||
|
br := newBitReader(rd)
|
||||||
if !bytes.Equal(out, expected) {
|
for i, v := range vectors {
|
||||||
t.Errorf("incorrect result\ngot: %x\nwant: %x", out, expected)
|
val := br.ReadBits(v.nbits)
|
||||||
|
if fail := bool(br.err != nil); fail != v.fail {
|
||||||
|
if fail {
|
||||||
|
t.Errorf("test %d, unexpected failure: ReadBits(%d) = %v", i, v.nbits, br.err)
|
||||||
|
} else {
|
||||||
|
t.Errorf("test %d, unexpected success: ReadBits(%d) = nil", i, v.nbits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !v.fail && val != v.value {
|
||||||
|
t.Errorf("test %d, mismatching value: ReadBits(%d) = %d, want %d", i, v.nbits, val, v.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRandomData1(t *testing.T) {
|
func TestMTF(t *testing.T) {
|
||||||
testRandomData(t, randBZ2Hex, randHex)
|
var vectors = []struct {
|
||||||
}
|
idx int // Input index
|
||||||
|
sym uint8 // Expected output symbol
|
||||||
func TestRandomData2(t *testing.T) {
|
}{
|
||||||
// This test involves several repeated bytes in the output, but they
|
{idx: 1, sym: 1}, // [1 0 2 3 4]
|
||||||
// should trigger RLE decoding.
|
{idx: 0, sym: 1}, // [1 0 2 3 4]
|
||||||
testRandomData(t, rand2BZ2Hex, rand2Hex)
|
{idx: 1, sym: 0}, // [0 1 2 3 4]
|
||||||
}
|
{idx: 4, sym: 4}, // [4 0 1 2 3]
|
||||||
|
{idx: 1, sym: 0}, // [0 4 1 2 3]
|
||||||
func TestRandomData3(t *testing.T) {
|
|
||||||
// This test uses the full range of symbols.
|
|
||||||
testRandomData(t, rand3BZ2Hex, rand3Hex)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test1MBSawtooth(t *testing.T) {
|
|
||||||
out, err := decompressHex(oneMBSawtoothBZ2Hex)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error from Read: %s", err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := make([]byte, 1024*1024)
|
mtf := newMTFDecoderWithRange(5)
|
||||||
|
for i, v := range vectors {
|
||||||
for i := range expected {
|
sym := mtf.Decode(v.idx)
|
||||||
expected[i] = byte(i)
|
t.Log(mtf)
|
||||||
}
|
if sym != v.sym {
|
||||||
|
t.Errorf("test %d, symbol mismatch: Decode(%d) = %d, want %d", i, v.idx, sym, v.sym)
|
||||||
if !bytes.Equal(out, expected) {
|
}
|
||||||
t.Error("incorrect result")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const helloWorldBZ2Hex = "425a68393141592653594eece83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb9229c28482776741b0"
|
var (
|
||||||
|
digits = mustLoadFile("testdata/e.txt.bz2")
|
||||||
var helloWorld = []byte("hello world\n")
|
twain = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.bz2")
|
||||||
|
random = mustLoadFile("testdata/random.data.bz2")
|
||||||
const thirtyTwoZerosBZ2Hex = "425a6839314159265359b5aa5098000000600040000004200021008283177245385090b5aa5098"
|
|
||||||
const oneMBZerosBZ2Hex = "425a683931415926535938571ce50008084000c0040008200030cc0529a60806c4201e2ee48a70a12070ae39ca"
|
|
||||||
|
|
||||||
const randBZ2Hex = "425a6839314159265359905d990d0001957fffffffffffafffffffffffffffffbfff6fffdfffffffffffffffffffffffffffffc002b6dd75676ed5b77720098320d11a64626981323d4da47a83131a13d09e8040f534cd4f4d27a464d193008cd09804601347a980026350c9886234d36864193d1351b44c136919e90340d26127a4cd264c32023009898981310c0344c340027a8303427a99a04c00003534c230d034f5006468d268cf54d36a3009a69a62626261311b40026013d34201a6934c9a604c98ca6c8460989fa9346234d30d3469a2604fd4131a7aa6d0046043d4c62098479269e89e835190d018d4c046001a11e801a0264792321932308c43a130688c260d46686804cd01a9e80981193684c6a68c00000004c4c20c04627a4c0000260003400d04c0681a01334026009a6f48041466132581ec5212b081d96b0effc16543e2228b052fcd30f2567ee8d970e0f10aabca68dd8270591c376cfc1baae0dba00aaff2d6caf6b211322c997cc18eaee5927f75185336bf907021324c71626c1dd20e22b9b0977f05d0f901eaa51db9fbaf7c603b4c87bc82890e6dd7e61d0079e27ec050dd788fd958152061cd01e222f9547cb9efc465d775b6fc98bac7d387bffd151ae09dadf19494f7a638e2eae58e550faba5fe6820ea520eb986096de4e527d80def3ba625e71fbefdcf7e7844e0a25d29b52dcd1344fca083737d42692aab38d230485f3c8ed54c2ed31f15cf0270c8143765b10b92157233fa1dfe0d7ce8ffe70b8b8f7250071701dfe9f1c94de362c9031455951c93eb098a6b50ee45c6131fefc3b6f9643e21f4adc59497138e246f5c57d834aa67c4f10d8bd8b3908d8130dd7388409c299a268eab3664fa4907c5c31574874bd8d388a4ab22b339660804e53e1b8d05867d40e3082560608d35d5d2c6054e8bab23da28f61f83efd41d25529ad6ea15fb50505cacfabb0902166427354ca3830a2c8415f21b19e592690fbe447020d685a4bcd16ecc4ff1a1c0e572627d0ef6265c008a43fc243240541061ed7840606be466d1c0dac2c53250ed567507d926c844154560d631960c65e15157829b2c7f16859f111a3a8cb72bf24ffa57a680c3be67b1be67c8dd8aea73ac2437a78df5b686d427080ebc01bd30b71a49f6ea31dc0f08e4849e38face96717690239538bc08b6cc5aa8d467cb9c36aa83d40ac7e58bddbfa185b22065e89a86c0145569d9e23726651aec49e31588d70f40fe9a4449dcf4f89eac220171e9c938e803dc195679651004b79ad33cc0c13aeeba5941b33ffeeb8fbe16e76c7811445c67b4269c90479433ddf9e8ed1d00c166b6c17217fb22c3ef1b0c1c7e28e185446a111c37f1ea6c07a59fbcc6546ecc6968d36ba58bc5489a5640647e426b0c39350cb6f07d5dc7a717648c4ec7f841467597ae1f65f408fd2d9940a4b1b860b3c9ae351dcae0b4425f7e8538710f2e40b7f70d13b51ac05ccc6ecda8264a88cad2d721d18132a9b9110a9e759c2483c77dcefc7e464ec88588174cb0c9abff93230ea0bed8decdd8ed8bfe2b5df0a253803678df04fab44c03b9ab7cc97d6e6d6fd0c4c840ce0efc498436f453bbb181603459471f2b588724592b222ec990614db530e10cadd84705621cfdd9261fa44a5f5806a2d74b575056b3c915255c65678f9c16e6dc00a99180fef1a840aff0e842ac02731080cc92782538360a60a727991013984da4fad95f79d5030677b7528d076b2483685fca4429edf804682fdc110dfc2f7c30e23e20a72e039108a0ad6fdee2f76985a4b4be4f5afc6101bf9d5042b657a05dc914e1424241766434"
|
|
||||||
const randHex = "c95138082bdf2b9bfa5b1072b23f729735d42c785eeb94320fb14c265b9c2ca421d01a3db986df1ac2acde5a0e6bf955d6f95e61261540905928e195f1a66644cc7f37281744fff4dc6df35566a494c41a8167151950eb74f5fc45f85ad0e5ed28b49adfe218aa7ec1707e8e1d55825f61f72beda3b4c006b8c9188d7336a5d875329b1b58c27cc4e89ecbae02c7712400c39dd131d2c6de82e2863da51d472bdfb21ecce62cc9cf769ed28aedc7583d755da45a0d90874bda269dd53283a9bdfd05f95fc8e9a304bb338ea1a2111894678c18134f17d31a15d9bfc1237894650f3e715e2548639ecbddb845cfe4a46a7b3a3c540f48629488e8c869f1e9f3f4c552243a8105b20eb8e264994214349dae83b165fd6c2a5b8e83fce09fc0a80d3281c8d53a9a08095bd19cbc1388df23975646ed259e003d39261ee68cbece8bcf32971f7fe7e588e8ba8f5e8597909abaea693836a79a1964050ed910a45a0f13a58cd2d3ae18992c5b23082407fd920d0bf01e33118a017bb5e39f44931346845af52128f7965206759433a346034ea481671f501280067567619f5ecef6cded077f92ed7f3b3ce8e308c80f34ba06939e9303f91b4318c8c1dd4cc223c1f057ac0c91211c629cd30e46ee9ec1d9fd493086b7bc2bc83e33f08749a5d430b0ed4f79d70f481940c9b0930b16321886a0df4fa5a1465d5208c7d3494a7987d9a5e42aa256f0c9523947f8318d0ef0af3d59a45cfc2418d0785c9a548b32b81e7de18be7d55a69a4c156bbb3d7579c0ac8e9c72b24646e54b0d0e8725f8f49fb44ae3c6b9d0287be118586255a90a4a83483ed0328518037e52aa959c5748ed83e13023e532306be98b8288da306bbb040bcf5d92176f84a9306dc6b274b040370b61d71fde58dd6d20e6fee348eae0c54bd0a5a487b2d005f329794f2a902c296af0a4c1f638f63292a1fa18e006c1b1838636f4de71c73635b25660d32e88a0917e1a5677f6a02ca65585b82cbd99fb4badbfa97a585da1e6cadf6737b4ec6ca33f245d66ee6a9fae6785d69b003c17b9fc6ec34fe5824ab8caae5e8e14dc6f9e116e7bf4a60c04388783c8ae929e1b46b3ef3bbe81b38f2fa6da771bf39dfba2374d3d2ed356b8e2c42081d885a91a3afb2f31986d2f9873354c48cf5448492c32e62385af423aa4f83db6d1b2669650379a1134b0a04cbca0862d6f9743c791cbb527d36cd5d1f0fc7f503831c8bd1b7a0ef8ae1a5ed1155dfdd9e32b6bb33138112d3d476b802179cb85a2a6c354ccfed2f31604fbd8d6ec4baf9f1c8454f72c6588c06a7df3178c43a6970bfa02dd6f74cb5ec3b63f9eddaa17db5cbf27fac6de8e57c384afd0954179f7b5690c3bee42abc4fa79b4b12101a9cf5f0b9aecdda945def0bd04163237247d3539850e123fe18139f316fa0256d5bd2faa8"
|
|
||||||
|
|
||||||
const oneMBSawtoothBZ2Hex = "425a683931415926535971931ea00006ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe007de00000000000000024c00130001300000000000000000000000000000000000000000000000000000000126000980009800000000000000000000000000000000000000000000000000000000930004c0004c000000000000000000000000000000000000000000000000000000004980026000260000000000000000000000000000000000000000000000000000000009aaaaa0000000000000000000000000000000000000000000000000000000000000000498002600026000000000000000000000000000000000000000000000000000000007fc42271980d044c0a822607411304a08982d044c1a82260f411308a08984d044c2a82261741130ca08986d044c3a82261f411310a08988d044c4a822627411314a0898ad044c5a82262f411318a0898cd044c6a82263741131ca0898ed044c7a82263f411320a08990d044c8a822647411324a08992d044c9a82264f411328a08994d044caa82265741132ca08996d044cba82265f411330a08998d044cca822667411334a0899ad044cda82266f411338a0899cd044cea82267741133ca0899ed044cfa82267f411340a089a0d044d0a822687411344a089a2d044d1a82268f411348a089a4d044d2a82269741134ca089a6d044d3a82269f411350a089a8d044d4a8226a7411354a089aad044d5a8226af411358a089acd044d6a8226b741135ca089aed044d7a8226bf411360a089b0d044d8a8226c7411364a089b2d044d9a8226cf411368a089b4d044daa8226d741136ca089b6d044dba8226df411370a089b8d044dca8226e7411374a089bad044dda8226ef411378a089bcd044dea8226f741137ca089bed044dfa8226ff411380a089c0d044e0a822707411384a089c2d044e1a82270f411388a089c4d044e2a82271741138ca089c59089c69089c71089c79089c81089c89089c91089c99089ca1089ca9089cb1089cb9089cc1089cc9089cd1089cd9089ce1089ce9089cf1089cf9089d01089d09089d11089d19089d21089d29089d31089d39089d41089d49089d51089d59089d61089d69089d71089d79089d81089d89089d91089d99089da1089da9089db1089db9089dc1089dc9089dd1089dd9089de1089de9089df1089df9089e01089e09089e11089e19089e21089e29089e31089e39089e41089e49089e51089e59089e61089e69089e71089e79089e81089e89089e91089e99089ea1089ea9089eb1089eb9089ec1089ec9089ed1089ed9089ee1089ee9089ef1089ef9089f01089f09089f11089f19089f21089f29089f31089f39089f41089f49089f51089f59089f61089f69089f71089f79089f81089f89089f91089f99089fa1089fa9089fb1089fb9089fc1089fc9089fd1089fd9089fe1089fe9089ff1089ff98a0ac9329acf23ba884804fdd3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0034f800000000000024c00130001300000000000000000000000000000000000000000000000000000000126000980009800000000000000000000000000000000000000000000000000000000930004c0004c000000000000000000000000000000000000000000000000000000004980026000260000000000000000000000000000000000000000000000000000000024c0013000130000000000000000000000000000000000000000000000000000000002955540000000000000000000000000000000000000000000000000000000000000001ff108c00846024230221181908c108460a4230621183908c20846124230a21185908c308461a4230e21187908c40846224231221189908c508462a423162118b908c60846324231a2118d908c708463a4231e2118f908c80846424232221191908c908464a4232621193908ca0846524232a21195908cb08465a4232e21197908cc0846624233221199908cd08466a423362119b908ce0846724233a2119d908cf08467a4233e2119f908d008468242342211a1908d108468a42346211a3908d20846924234a211a5908d308469a4234e211a7908d40846a242352211a9908d50846aa42356211ab908d60846b24235a211ad908d70846ba4235e211af908d80846c242362211b1908d90846ca42366211b3908da0846d24236a211b5908db0846da4236e211b7908dc0846e242372211b9908dd0846ea42376211bb908de0846f24237a211bd908df0846fa4237e211bf908e008470242382211c1908e108470a42386211c3908e20847124238a211c5908e2f8c211c6c8471d211c7c84721211c8c84725211c9c84729211cac8472d211cbc84731211ccc84735211cdc84739211cec8473d211cfc84741211d0c84745211d1c84749211d2c8474d211d3c84751211d4c84755211d5c84759211d6c8475d211d7c84761211d8c84765211d9c84769211dac8476d211dbc84771211dcc84775211ddc84779211dec8477d211dfc84781211e0c84785211e1c84789211e2c8478d211e3c84791211e4c84795211e5c84799211e6c8479d211e7c847a1211e8c847a5211e9c847a9211eac847ad211ebc847b1211ecc847b5211edc847b9211eec847bd211efc847c1211f0c847c5211f1c847c9211f2c847cd211f3c847d1211f4c847d5211f5c847d9211f6c847dd211f7c847e1211f8c847e5211f9c847e9211fac847ed211fbc847f1211fcc847f5211fdc847f9211fec847fd211ff8bb9229c284803a8b6248"
|
|
||||||
|
|
||||||
const rand2BZ2Hex = "425a6839314159265359d992d0f60000137dfe84020310091c1e280e100e042801099210094806c0110002e70806402000546034000034000000f2830000032000d3403264049270eb7a9280d308ca06ad28f6981bee1bf8160727c7364510d73a1e123083421b63f031f63993a0f40051fbf177245385090d992d0f60"
|
|
||||||
const rand2Hex = "92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f8719e6c2a2bd4f5f88db07ecd0da3a33b263483db9b2c158786ad6363be35d17335ba"
|
|
||||||
|
|
||||||
const rand3BZ2Hex = "425a68393141592653593be669d00000327ffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffc002b3b2b1b6e2bae400004c00132300004c0d268c004c08c0130026001a008683234c0684c34008c230261a04c0260064d07a8d00034000d27a1268c9931a8d327a3427a41faa69ea0da264c1a34219326869b51b49a6469a3268c689fa53269a62794687a9a68f5189994c9e487a8f534fd49a3d34043629e8c93d04da4f4648d30d4f44d3234c4d3023d0840680984d309934c234d3131a000640984f536a6132601300130130c8d00d04d1841ea7a8d31a02609b40023460010c01a34d4c1a0d04d3069306810034d0d0d4c0046130d034d0131a9a64d321804c68003400098344c13000991808c0001a00000000098004d3d4da4604c47a13012140aadf8d673c922c607ef6212a8c0403adea4b28aee578900e653b9cdeb8d11e6b838815f3ebaad5a01c5408d84a332170aff8734d4e06612d3c2889f31925fb89e33561f5100ae89b1f7047102e729373d3667e58d73aaa80fa7be368a1cc2dadd81d81ec8e1b504bd772ca31d03649269b01ceddaca07bf3d4eba24de141be3f86f93601e03714c0f64654671684f9f9528626fd4e1b76753dc0c54b842486b8d59d8ab314e86ca818e7a1f079463cbbd70d9b79b283c7edc419406311022e4be98c2c1374df9cdde2d008ce1d00e5f06ad1024baf555631f70831fc1023034e62be7c4bcb648caf276963ffa20e96bb50377fe1c113da0db4625b50741c35a058edb009c6ee5dbf93b8a6b060eec568180e8db791b82aab96cbf4326ca98361461379425ba8dcc347be670bdba7641883e5526ae3d833f6e9cb9bac9557747c79e206151072f7f0071dff3880411846f66bf4075c7462f302b53cb3400a74cf35652ad5641ed33572fd54e7ed7f85f58a0acba89327e7c6be5c58cb71528b99df2431f1d0358f8d28d81d95292da631fb06701decabb205fac59ff0fb1df536afc681eece6ea658c4d9eaa45f1342aa1ff70bdaff2ddaf25ec88c22f12829a0553db1ec2505554cb17d7b282e213a5a2aa30431ded2bce665bb199d023840832fedb2c0c350a27291407ff77440792872137df281592e82076a05c64c345ffb058c64f7f7c207ef78420b7010520610f17e302cc4dfcfaef72a0ed091aab4b541eb0531bbe941ca2f792bf7b31ca6162882b68054a8470115bc2c19f2df2023f7800432b39b04d3a304e8085ba3f1f0ca5b1ba4d38d339e6084de979cdea6d0e244c6c9fa0366bd890621e3d30846f5e8497e21597b8f29bbf52c961a485dfbea647600da0fc1f25ce4d203a8352ece310c39073525044e7ac46acf2ed9120bae1b4f6f02364abfe343f80b290983160c103557af1c68416480d024cc31b6c06cfec011456f1e95c420a12b48b1c3fe220c2879a982fb099948ac440db844b9a112a5188c7783fd3b19593290785f908d95c9db4b280bafe89c1313aeec24772046d9bc089645f0d182a21184e143823c5f52de50e5d7e98d3d7ab56f5413bbccd1415c9bcff707def475b643fb7f29842582104d4cc1dbaaca8f10a2f44273c339e0984f2b1e06ab2f0771db01fafa8142298345f3196f23e5847bda024034b6f59b11c29e981c881456e40d211929fd4f766200258aad8212016322bd5c605790dcfdf1bd2a93d99c9b8f498722d311d7eae7ff420496a31804c55f4759a7b13aaaf5f7ce006c3a8a998897d5e0a504398c2b627852545baf440798bcc5cc049357cf3f17d9771e4528a1af3d77dc794a11346e1bdf5efe37a405b127b4c43b616d61fbc5dc914e14240ef99a7400"
|
|
||||||
const rand3Hex = "1744b384d68c042371244e13500d4bfb98c6244e3d71a5b700224420b59c593553f33bd786e3d0ce31626f511bc985f59d1a88aa38ba8ad6218d306abee60dd9172540232b95be1af146c69e72e5fde667a090dc3f93bdc5c5af0ab80acdbaa7a505f628c59dc0247b31a439cacf5010a94376d71521df08c178b02fb96fdb1809144ea38c68536187c53201fea8631fb0a880b4451ccdca7cc61f6aafca21cc7449d920599db61789ac3b1e164b3390124f95022aeea39ccca3ec1053f4fa10de2978e2861ea58e477085c2220021a0927aa94c5d0006b5055abba340e4f9eba22e969978dfd18e278a8b89d877328ae34268bc0174cfe211954c0036f078025217d1269fac1932a03b05a0b616012271bbe1fb554171c7a59b196d8a4479f45a77931b5d97aaf6c0c673cbe597b79b96e2a0c1eae2e66e46ccc8c85798e23ffe972ebdaa3f6caea243c004e60321eb47cd79137d78fd0613be606feacc5b3637bdc96a89c13746db8cad886f3ccf912b2178c823bcac395f06d28080269bdca2debf3419c66c690fd1adcfbd53e32e79443d7a42511a84cb22ca94fffad9149275a075b2f8ae0b021dcde9bf62b102db920733b897560518b06e1ad7f4b03458493ddaa7f4fa2c1609f7a1735aeeb1b3e2cea3ab45fc376323cc91873b7e9c90d07c192e38d3f5dfc9bfab1fd821c854da9e607ea596c391c7ec4161c6c4493929a8176badaa5a5af7211c623f29643a937677d3df0da9266181b7c4da5dd40376db677fe8f4a1dc456adf6f33c1e37cec471dd318c2647644fe52f93707a77da7d1702380a80e14cc0fdce7bf2eed48a529090bae0388ee277ce6c7018c5fb00b88362554362205c641f0d0fab94fd5b8357b5ff08b207fee023709bc126ec90cfb17c006754638f8186aaeb1265e80be0c1189ec07d01d5f6f96cb9ce82744147d18490de7dc72862f42f024a16968891a356f5e7e0e695d8c933ba5b5e43ad4c4ade5399bc2cae9bb6189b7870d7f22956194d277f28b10e01c10c6ffe3e065f7e2d6d056aa790db5649ca84dc64c35566c0af1b68c32b5b7874aaa66467afa44f40e9a0846a07ae75360a641dd2acc69d93219b2891f190621511e62a27f5e4fbe641ece1fa234fc7e9a74f48d2a760d82160d9540f649256b169d1fed6fbefdc491126530f3cbad7913e19fbd7aa53b1e243fbf28d5f38c10ebd77c8b986775975cc1d619efb27cdcd733fa1ca36cffe9c0a33cc9f02463c91a886601fd349efee85ef1462065ef9bd2c8f533220ad93138b8382d5938103ab25b2d9af8ae106e1211eb9b18793fba033900c809c02cd6d17e2f3e6fc84dae873411f8e87c3f0a8f1765b7825d185ce3730f299c3028d4a62da9ee95c2b870fb70c79370d485f9d5d9acb78926d20444033d960524d2776dc31988ec7c0dbf23b9905d"
|
|
||||||
|
|
||||||
const (
|
|
||||||
digits = iota
|
|
||||||
twain
|
|
||||||
random
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var testfiles = []string{
|
func benchmarkDecode(b *testing.B, compressed []byte) {
|
||||||
// Digits is the digits of the irrational number e. Its decimal representation
|
// Determine the uncompressed size of testfile.
|
||||||
// does not repeat, but there are only 10 possible digits, so it should be
|
uncompressedSize, err := io.Copy(ioutil.Discard, NewReader(bytes.NewReader(compressed)))
|
||||||
// reasonably compressible.
|
|
||||||
digits: "testdata/e.txt.bz2",
|
|
||||||
// Twain is Mark Twain's classic English novel.
|
|
||||||
twain: "testdata/Mark.Twain-Tom.Sawyer.txt.bz2",
|
|
||||||
// 16KB of random data from /dev/urandom
|
|
||||||
random: "testdata/random.data.bz2",
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchmarkDecode(b *testing.B, testfile int) {
|
|
||||||
compressed, err := ioutil.ReadFile(testfiles[testfile])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
b.SetBytes(int64(len(compressed)))
|
|
||||||
|
b.SetBytes(uncompressedSize)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r := bytes.NewReader(compressed)
|
r := bytes.NewReader(compressed)
|
||||||
io.Copy(ioutil.Discard, NewReader(r))
|
io.Copy(ioutil.Discard, NewReader(r))
|
||||||
|
|
@ -202,222 +230,3 @@ func benchmarkDecode(b *testing.B, testfile int) {
|
||||||
func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
|
func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
|
||||||
func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) }
|
func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) }
|
||||||
func BenchmarkDecodeRand(b *testing.B) { benchmarkDecode(b, random) }
|
func BenchmarkDecodeRand(b *testing.B) { benchmarkDecode(b, random) }
|
||||||
|
|
||||||
func TestBufferOverrun(t *testing.T) {
|
|
||||||
// Tests https://golang.org/issue/5747.
|
|
||||||
buffer := bytes.NewReader([]byte(bufferOverrunBase64))
|
|
||||||
decoder := base64.NewDecoder(base64.StdEncoding, buffer)
|
|
||||||
decompressor := NewReader(decoder)
|
|
||||||
// This shouldn't panic.
|
|
||||||
ioutil.ReadAll(decompressor)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOutOfRangeSelector(t *testing.T) {
|
|
||||||
// Tests https://golang.org/issue/8363.
|
|
||||||
buffer := bytes.NewReader(outOfRangeSelector)
|
|
||||||
decompressor := NewReader(buffer)
|
|
||||||
// This shouldn't panic.
|
|
||||||
ioutil.ReadAll(decompressor)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMTF(t *testing.T) {
|
|
||||||
mtf := newMTFDecoderWithRange(5)
|
|
||||||
|
|
||||||
// 0 1 2 3 4
|
|
||||||
expect := byte(1)
|
|
||||||
x := mtf.Decode(1)
|
|
||||||
if x != expect {
|
|
||||||
t.Errorf("expected %v, got %v", expect, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 0 2 3 4
|
|
||||||
x = mtf.Decode(0)
|
|
||||||
if x != expect {
|
|
||||||
t.Errorf("expected %v, got %v", expect, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 0 2 3 4
|
|
||||||
expect = byte(0)
|
|
||||||
x = mtf.Decode(1)
|
|
||||||
if x != expect {
|
|
||||||
t.Errorf("expected %v, got %v", expect, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0 1 2 3 4
|
|
||||||
expect = byte(4)
|
|
||||||
x = mtf.Decode(4)
|
|
||||||
if x != expect {
|
|
||||||
t.Errorf("expected %v, got %v", expect, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4 0 1 2 3
|
|
||||||
expect = byte(0)
|
|
||||||
x = mtf.Decode(1)
|
|
||||||
if x != expect {
|
|
||||||
t.Errorf("expected %v, got %v", expect, x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var bufferOverrunBase64 string = `
|
|
||||||
QlpoNTFBWSZTWTzyiGcACMP/////////////////////////////////3/7f3///
|
|
||||||
////4N/fCZODak2Xo44GIHZgkGzDRbFAuwAAKoFV7T6AO6qwA6APb6s2rOoAkAAD
|
|
||||||
oACUoDtndh0iQAPkAAAAaPWihQoCgr5t97Obju21ChQB0NBm3RbA7apXrRoBooAA
|
|
||||||
AhA+IAHWl2Us3O7t9yieb3udvd76+4+fd33nd3HO1bVvfcGRne6+3vfPvfc++995
|
|
||||||
w7k973eJhasLVec970tzDNXdX28LoPXZ3H3K9z0s5ufWAfes49d5594c3dUYtI+2
|
|
||||||
+h1dvtpRa+uvrVEAG9bl893RVEN7cWvroSqWjPMGgAQi7Gq8TJSgKKdjKFBIB9Ae
|
|
||||||
LqWxleu715eXe7ml9e5098Z6G1vr7t1QZ6ot76YzPd3j7333t2ql2Chm7XrA9ICQ
|
|
||||||
VF77z3rVBWqkSXtlfb099hyezAr6USbGpICTSCFAaqHrKo+tUnm32rpE4Ue+t2mj
|
|
||||||
bKUeipEqwc93EdhhTwmQpOhhesC9iqDSPNTWYNSnUtBdm1nsA0nqqNd7OWwDXtFL
|
|
||||||
ONmmA6Ubke26I9UblvWIPR5VOWOnctai443URunnDy77uVC59OfRvezlDu33Z7Ly
|
|
||||||
3NNuuHW63088xu3t3NHZhkZbG7tXRlj00qOtbaXTJUUdspTbABR9R6EUwQAEAAAA
|
|
||||||
EMEwRpoAAAABMmhoAAjBNNAaCMhponpoGpgJpk9TEyp6niGKZkAaAEfqMQ09U80p
|
|
||||||
+pMGSCKngIAAAAgAAg0AAJhGgABGCEaaTyTKeNI1PE0wkj01GajMSNPSZGnqbU9T
|
|
||||||
anlPUNAHqGQ0DQAMg9TamgAAYRU/IAAICAmjQJgjQBMEwp5DTSaaYmhTeqfplPID
|
|
||||||
U1T9TynoU82pT1NPU/VP0j1NHqRpk9TTR7SnqaNNGmmQAaAD1Aeo0PSAAAAaaBiK
|
|
||||||
eBAQBGgIABGQA0AmBNNBoaAgaJmpglPEyYap6npiTT0agGjJjUaaDTQAAAAAAM1A
|
|
||||||
9QAaAAAADU8iEAQAEyAJk0NNNJgIZTJ5E00YSemiaZNGm1MpGNJ+lPU9qm9U2RDM
|
|
||||||
oY0EzJB6h6nqDID1NMBDDRpo1AGNAjCMmhkMgaYSJIgAAAQyAAEyBoATECCNhTT0
|
|
||||||
U/IZAmCM1DSTxkzUE8p6NDaGiZGJqntTFHvUyU9qPQp7Kn5GgKNPU9QAGg9QAAA3
|
|
||||||
wz0Pk/g/m/m9P9H4vxv2+dH3gCS8nhbbbbbYxtgNsBsG0m2MbG0NNtsbYNsaY0wb
|
|
||||||
bBibGmm22mxptNpsaGNDTY02JsG0MY0xg2MaYNNDbGwG0L5vsK/F9DO+EAA447Kq
|
|
||||||
p7Wdf6Y+5c20T7DfHyMXIzRKrZexw72uiQI+y55vOe52xpqbCLC2uR20JdER7Zvr
|
|
||||||
7ufuKb6zhiBxLuj0eA27v8RpMLucw9Ohwcizi2wrpt+yU1FdpM7ZYPcwS3XTef+A
|
|
||||||
Wzjxwhdrgw3aH1LeC1eZW900x8V9Nv4hTPXp4l067P/4ANVZFF/imOe/d5bdueam
|
|
||||||
/DFFokQWnFaU+ZqLBCM+d0PialJQWnLqRQZk/KhfbbYc2pCUTgffcSYbrCM1N+8l
|
|
||||||
HU6gSz+h2GJXs+tbrNviL83M97X0vcTn/F82P8wen8/3/h3sHY+sf9CSej9ThYTV
|
|
||||||
3lQ+FUHpfpGD4kv7dYMV995dpDX/y3xR8FoXx1bjUxBTNxuutwQ/h/Eedn9wpn6w
|
|
||||||
E3+ND8YhN1HSriIxRE/6uFyMv6/oC6Elarw3aHMMqHJkGiiz6tejmvnYLQa+Qm6G
|
|
||||||
deZ7jXTZV6NlpocgDnRdimS06bTYSkvPAL/xoWNLkX6N6VljU0dfKSBmm2uZE/xu
|
|
||||||
sutQ1EdP7GdjhglIq4xlOFUFEQpmX+xx7R8y6c0GSAaqusOjNZwxZRudOvmXm1tZ
|
|
||||||
T+YnbeB2ir9eiHNrtJNSLD/J/WDyuQpwBUtLKo0krccY/wIILP7f86teb9Z/9oyz
|
|
||||||
OX05qEWbObfhpRw+9+rCvp/35ML8KX3aHaI0n+tudbFRsV5FLW+Oa8ruLN4peyVL
|
|
||||||
DWjTHrXNthq/s7zAJYMeFJZkZt5mT9rfpH+5g3nc+piOSZ+J5nHtOnKI7Ff8Xl+j
|
|
||||||
0t76XTNucCHQ6whav1OHdF53TY5wuv5OzvrdnxoId8fTyUvERr0ERINu/8XxZZ5f
|
|
||||||
B5/kTZ8bBO0wv54Jp+ED/GQI8lZHzIQCP3vfQhwnCTj9TvITic7P4mYLDbH3fyzR
|
|
||||||
i+6EajCcpXLWSGf+ZXkOrWspDWDhXtEKas0v3UqWksqgY1rTj45krX4KihN+daXs
|
|
||||||
pZl5WPlta5p06CX6Xm2SfzqkMw12/3ix1bpnnZ+kFeBNX7A+E9zzG6OZaN78GOpl
|
|
||||||
9Ht/eZn9PqWdav852zr0zqkDK2H5IjdvNah+b1YVGdQGzwR4Nw+f13yEKnV+y66W
|
|
||||||
djfq7zWp7m5w+hzfv+Ly8O7oet5Vvd8/wQvO7qzOZ2vjf9X8Tj8PnMb/nc/nKqRR
|
|
||||||
+ml4UEhOOwfCeJEEI109CMYSh91iAJqPjMyH6KjrPD7W25llZVcREYNCTg6htbQt
|
|
||||||
M38wYoquCWP6tdKYlVIv14xTNUeUf4El/FunCf6csZkmv+9tfWx7t59wuKIa3saU
|
|
||||||
tZs9M+3HFOZtz3OLg/Unoaj9BYazYqA78xBU9tZzrtmF/rQL9CGJt90o/oYnSfcS
|
|
||||||
SL3haaw351LXWQ1XOsv1SmH3v6ymuxEpPPnEDmBELaTYsvvMIWJsmPZFFww++Kd7
|
|
||||||
s/Jo0JFeUU7uNtI+gVosAIpVVuWfI/9tOIycz7I5Z7zjV+NR2OuZbYtW5F08KX4o
|
|
||||||
2k/xuJIchcNFPtxPfw9dkDgscRbMckyFMrzuZ3IvrcGzk0J6iI5ytrv37bGpAXMz
|
|
||||||
WK9mMMPebepNevmLjjo/QWoM968Sjv7ldlPS5AinHcXwsFv6dmmh8lJt7UOJWoKu
|
|
||||||
lMD1cB2ksIGpMdv8iuqR42Rn/kn+17BhhUZcwDBaUXVdX6bKW7fxlUYbq+mlqIcf
|
|
||||||
a9v8HF87M9ANbi9bq9onf9TD7nQ6Xf6vZci8TBPX+/GI0He6j31fTVQYW+NsQxvO
|
|
||||||
J8xrx+e58CCLQNjxeIyPt+F+qk/QMiXw+LyxGVkV/XcGQT9X03jSDP6beJ5QG1JW
|
|
||||||
9Q3qLv/YixWI7gPV9Mrhf2oRYTc/9KLFRhkE3SjKOTKuSSBKQ24fI+hEznamH71D
|
|
||||||
66Hwez8/0et7AtTv9zvamv2OD5He6fMV4k+ePl6+qPfO5CdHtK+eCDZL5+4f5yrl
|
|
||||||
gTcRFiq8fXbc5IaI5fbbc1KMM/2T0Mr7+Hwaco6FtXm0fmhCgTZRqY4pKiEIfmaz
|
|
||||||
QwHNOOCrtMJ2VwsyMumt7xsOolGnizRev6lILH43qPcczQM7Gc5zRin80YvFt1Qm
|
|
||||||
h/57Z0auR2h0fuX50MBO4XQ+26y5l6v4j902R66c0j3z2KHstKQ04J/h6LbuNQE4
|
|
||||||
D6cu/lyfK69DxxX8wb8XaQkMUcJdo1LzqUGDAb3Kfn/A3P/JYc99MO9qv67+SxWb
|
|
||||||
wYTyqKdWTd+1KbR/Rcn0Io5zI/QquX7FA1bxfMytjQ/X+l0fh0Pf+Hx97meH4fQL
|
|
||||||
7/T8/sdTm9Tn8nELvedyhydLlPPTScINdXyLIq9wgIJr4fWPbp9ZhFh/56fdSgOG
|
|
||||||
HDXg+gkXsN2Rddr4HQ5P3u+RhLzmSjhzoqY5EsPC4QvRlX9JXjB84rPV5USR66qa
|
|
||||||
/kjw4156GJnzoXtydKJE53t6PHfZWO+3ujsfI6iAdshc7OFzGXiZB9PtItKodhYq
|
|
||||||
nABkTKdcpu4+TOpf9h5piX5slsaBjkeTnj/Ba02ilboQfcDVigxrYn/iTH5ySWUW
|
|
||||||
/lHtg78s5UZM8sErwhNe3N3w+6ZOMnU+5i86/xFNtqZfDdXTGy1H3PzGbdtZXYT+
|
|
||||||
Ixx2vpwBYzbPVYHxKosM5rPiVmcTllI9nuoSfeh9ib4foFWauOpvdmhBDqpTpKTX
|
|
||||||
u8EO2l2Z195G2RIV7TlKSxGWjR5sl/nALu1uzBeLd9zpSujzMTd1uTX9Qk/Q1S+r
|
|
||||||
vaW6bm8qqPO4jb6Wx6XIkm321nrIF6Ae25d1+Dpv/P5G4NoLd2j6/EtENC3FeR5z
|
|
||||||
oo7bA+tI8yEQRhiF0z1FlJXLD5ZbhNNWQm/j/IbzRfh8JtOFZU7ruShLvHXysW9S
|
|
||||||
9V909tr9jn8/E/Hb5N/1NVNHnZu2HIUvJvHJiHd2ucmeI9PWUMnppmE65GQ5E9xV
|
|
||||||
ZRlGEH0X85EvmHyEupkMrCC0oMv9RCq+/H8gcfpe00Hs/S+regT5p58cyYomh93v
|
|
||||||
qvuw/A06BE/wzJESuYbN9pqYpoXqXFemW1NksHEJ2w+PYMJ27WJyD5FpaXB85VaW
|
|
||||||
qMOhDfO8E3QdH8ybyKt/UgI8/tDGpFbyOlaVdIv1FXJhoLp8soAA4Djg6/KZ066N
|
|
||||||
ZFYuS8WdjpSZGP4/Lw+1yaXlzNznc/k2uHe2uXP3uFuPcHx+Dm44utxldoO1uBPy
|
|
||||||
+jzOs14+MIgOjOHMVNqAbMd8fUedLlhJMCfMtm4uz01enLNKcMrtLlPIR37Yukh1
|
|
||||||
YEMXYpm7eU4XU+j+Jj3pDyaXtXs+p1fWfTN/cy9/Oxs4umUXQ4uHh1kObtayDJ56
|
|
||||||
/QMxiHobjHNKuKfMxsrYEwN+QVIyVjAwMDYuMjQ1AAA9IwJniiBLRkZDAAAXt0Ja
|
|
||||||
aDQxQVkmU1lZtwytAACLf///////////////////+//////v//////////bv78//
|
|
||||||
/+AXO133uwO2xB2UxIvbKXrCqCoURUBL2ytFI82AFdcOwMhVTHtk5rD3szEVNYD4
|
|
||||||
aIQINCaMRoTaSn7SbSMJiYmEwieTEp+psqbMCp+VNPaFNpqbBNR7UmanlPUeKfqm
|
|
||||||
j1PU0/VPU08o9Q9EeKHlPJtKbYqeTCYhN6U9T1NH6mp+lPyoGNTI/Knkyg1MggAg
|
|
||||||
CaMEyQnqZoaaRtRtJpppppoDaTR6hpphGh6mmgHpMQBpkGTTEAAaAAAA00AZDag0
|
|
||||||
ADIBkGgABqemiRNTI0k8aU0PRGRoAZlP0UAAAGgAAAyAADQaAAAaAAAAAAAAAAAA
|
|
||||||
AaAAAAM0kgRBJ5MlPFP1Gj0jTTTUaekxNAbUGjTQMgaZANNAAAAaAADTQAAAAAAA
|
|
||||||
ANAA0AAANADQ0QAAAAAAAAAaGgAAAAAAABoA0AAA0AAAAAAAAAAAAANAAAAAkSEI
|
|
||||||
aTRpomp5DUxNNDTJPTKaep6T09Kemmo2JG0aTQ9ENogaaGhkABo0NHqaBoDTI0DC
|
|
||||||
Gj0gNAMhoDQ9QMQNAGQAaDDwyMPIMlbG1vhRBTFo6JksSupgpAjPbY0ec02IGXjb
|
|
||||||
eS+FBsh01+O4ZOaD+srUZCFaT4DRjVDLx7uKIsFtESIDUg1ZkhyCSYov05C00MtR
|
|
||||||
BdNNa/AYPGOQZWcs+VegXOPrkushFbZ3mBoRD6WamClkpBaHZrUhUl02bIfRXX4w
|
|
||||||
b3/9cW9nHDVxh2qFBxqgRKfmq7/Jc/tdJk05nVrGbckGVy2PnIy30CDhpWmqrSot
|
|
||||||
K2bOnX0NbP1iy2cd0Na0ZmbRstm4MzMzbbMySTd35F7f+zPP8DC+NJLYcakkkkRd
|
|
||||||
NZlupJt3OMFoDAD2g+N3FAMCydhIpoRHRQAdFI5nNg4ugEXHCYxkMyGCwtaJmial
|
|
||||||
y0IMlpSYYM/weXNJAhFqS0GNmvaPEtYGjbvaucMdklOTmBX1vfVAkTYB1uXCSK64
|
|
||||||
UNIixOqRKLuRCFtqIQtgwqaFrCkIYbbewErWABa+VGADWsJXJjfx5SJViLuwiGXq
|
|
||||||
Ru6vCuwmU5CJiJz3UiBpmLv0r2wskxUhY4tzPVGQ9RMXJl65eLSNwZVwaSyGZ9Cm
|
|
||||||
A3jztQUUpFeUryBTskW95iVwRMFrhBCwZBAFJBZvhMEMNoDJJlUoIhQkAkjbExp2
|
|
||||||
YZio+ZYeAZUwmH1qUbdQixmxf0+61+aVgJ1hwxsO1yG3hFx4pfjc09ITVht0pG8u
|
|
||||||
FtVFhPa1KE0gTRUSVXywkITucqk0Waz5Fs6qJpVHYdNrbYRFxnFsQGY1qmsTLjK6
|
|
||||||
4QX5Rddo6krM/Bx9CqIAKq4CzVQYHrmIAd2EBhYmwVYwLvhzKIUrc2EirnGIvyuD
|
|
||||||
O4YZDSwsVTA0BpVvUOjDErkCraBoSutcKwUSSLGhVvNYHLz3klgZD++wWsa/swLw
|
|
||||||
gvNDY2De+sncOv8X2lq4HD95ZdwPuTIMXCwSbg4RrIqv+L0y6F17pqDecyQYPEj3
|
|
||||||
iN/0BBeWZlJAyBMi5U3Q1zAlsK8IlDhaXGmvZrgISq5CfNjmUgxDeMggOKqxu4sI
|
|
||||||
OrilS49Lkl1J3u3GjXTuH+rX+4ccyFAQnizCpPClcY77F59j63S6fr5vr+y99tuO
|
|
||||||
7Ox7Wg/ljwhdyaK4xMmXczeJbx7x07htJNtC4xcQfAtvzeznLrN6MN/ILIBOI65I
|
|
||||||
qIA2D5fHHj1XN4aN6TvOjWDaSbSWqxCSCvXUpzkNJAkWXAuTwF8k5uSJvQj/rVo0
|
|
||||||
hAhEMEIYkCRGx9AX+byIuXWlLMbbVeliHNUL5AQYmNwLFu4SkmGD+UWtBMyVHQOQ
|
|
||||||
ss0ggoVKSKOBUgnVS6ljt7WE1qXqJJ4QA1pEwYNLEaguEE1LtPNoVr5WzjbSbWPk
|
|
||||||
V9OW3y9IneUDLoIV5pAkEFTEFGFVjeTFxtpzBBfGgycBxVCdz8eESBIzsamRchAa
|
|
||||||
TQunQH8DHnpfod9QuAuRvc7JBlKUCYmCjMvynLcxIFohxCaYrDvGw4QbXZB7oWQ7
|
|
||||||
hpoGlz23ayDfB8NrRRzdilsEQyQniu9ASLQg7RrGZnoTr1ai12IbCEUCGdFq03P5
|
|
||||||
nBnRFAGmisQGcyykV9gKtcVMWLhCuVmXg86dndn7slUpRNSSEAU20oaWIm1maFTu
|
|
||||||
E0DT4gTbg0nuhjtz3kNOz+i7sBm0bkXjxQWuLqlZEmp60ZTyRZJDUqKSEKg6hqcy
|
|
||||||
ERxdU22CSNOO10RYUUiDVpKhPNdKTOIE1thp02sBNoNTFSht8WJtaBQ09qN3jd5r
|
|
||||||
dOLX4IA5fevRyCCzDgRXfV4wzik4KROjmxmTMglBySlIMEzcXehnDXCRiZSlvwA2
|
|
||||||
0YsIOROcm4UrIRFxJHctJH7OdN5u1aHVHb5UaLHpv48NgmFRE56KTSoaWunqm2st
|
|
||||||
S0mrAdOiqcR12PWVbdVRJKcQ0DQuhwlAPcRtpxN3D4kbXJjToSYJIFw406G2CSaK
|
|
||||||
jQMIJPZGlQmgyFhoCSzeGS1VSq5SKKQQxs5RqKUcVUNY57YUETb4mXzV84SPngKi
|
|
||||||
nsce0mXByZq5BKUA9puHZWLNwQIYuDaJUNgG+E01E3pDYVNLKYQ0hsVesgV5gZY0
|
|
||||||
htDsRdGtm0+iGnkN6+Ea9YJtUZNAkx2GgSoix12nTW0avTUfxR3oYcpvZ7IdtABE
|
|
||||||
UhBcjG4qZtDZsS1JQHys243vhLaDTSvvTeBiJA2tmokqECTBcSOCAGkAxMKlVAva
|
|
||||||
4IsLRaBBqhxDbcGtgdw03mFcLUaFuhtKuuEIEkUleJQwby/zwu9uvvZK4xTV+ECM
|
|
||||||
a8lmzxKmqkBggYK1+xPdbmJclm6tSZhE/OSJtCEjs+unJIQkT9hCWgBJqGMS07Eh
|
|
||||||
AJNmBiuVEVdTyjkIJkavuZmx2sJF13htgEZUCC23lZFOE6gWbM9WyYNJTM8yCQrb
|
|
||||||
0Sx3OQvBML5cRATAQkSQkAJOAhoxpQkNi4ZiEVDbdtJAME0RXNDXGHA3M3Q0mm1o
|
|
||||||
IEwbWpaM1DQCSMbGRCAu3iRIQiT6RlBpT1n3tfwvUXz3gIVlx3mEximY/kZW1kNG
|
|
||||||
sgEJIrBisaEoGYPJ+1CQUYFBw+eGEHJQBpNHjErXUJY2iWHQ30hXwFBuMSxQ2lB5
|
|
||||||
bg+/LX3euG6HsHUB1lFvBvaiaBrITVwkCTa1d0s9CHZCiDZjbWReKyrpPE2oSa7o
|
|
||||||
LPrR4BJvys9ttjUpzETSSMxh8vsr9dXTwKBtK+1xCTGDQmNIaE29HmHdS5GSxpya
|
|
||||||
MismcAUSEgSxHBrKtgsZzduG7vHZn16l3kFkVITtENIzS2JsiBwFTDlhgexsjBHv
|
|
||||||
5HXOYxHBzoSDCcPZ0ctvkY9aS5XpoQuFYkGJgCsqjJZeUMNUEpDSbKcnUc1PifIA
|
|
||||||
CbR2UoXawBlspkEBr9HBfvUi/MUakZVOf1WKYrqSaIXce62JOyhJLq3qJBloTA0F
|
|
||||||
VbILEtM+heFmNRCFt70GJrExVJri0ArYbCRbADSGDBpBXxxb/6fo+s3C7uaL7RjM
|
|
||||||
LV2IQBNrAJrKFeJwTsPnxbAsemirUx2lk1kaxschzdK4TQNJN5wQnolIFg401OZ4
|
|
||||||
2na11LnT3lR+1k1TMJhiAjXMk0F1ooHnYlt9LKfJ3ZIOmeY+2l9bUQHWFNGyEyfj
|
|
||||||
EAcu3kpGLq0Ez7XOS+EpAASRQTAYMATfVQibHLTT30zG732+pNe9za1JNt8sNJYn
|
|
||||||
RjWuJ6jL5ILV0rcd9vT7X9fObvcXitpvJ2XBJE+PhX2HaTkyWeF9pwnlQNrTe9hV
|
|
||||||
tzhA+ihZrDrHNmLcQjZbnv/IMubqq8egxY80t5n6vZ6U5TR6U9uZJvai1xtqAyCR
|
|
||||||
NWkW52m00rDTEuO6BA4q2RHDWwbETF55rRsWLIgNW9qJCyMHPbTM/dMBmWMQSMxz
|
|
||||||
4M2pRzt47SICxA327UqSCEERqMFybmYi3nUxePtLgHYplqRiw4ynMbXd/kiQ0LE0
|
|
||||||
PKJSSCXA42ymziCpAxNWflzpzQdJZusahRFr6t6m+4p273/Taj7k+hZyNgBAgXAY
|
|
||||||
8F7pTts6orLb8IA6o4TOwkwQYmKvKu9VwMrE7+GUhVIAgY9a8DyQMiDBkEAwh7S1
|
|
||||||
KgCBfao8DK1CwSS8Z3WjL5MEgt93z2koUQCD/YxMBppiCMp7SDVSmkkIHptfGpeh
|
|
||||||
t+M13Ccv1tavIASFiaQl6rBz3K4N3DSGwNkCibrvEAC0fQirOWnc4NVbcLKpFG1l
|
|
||||||
NQXF/eqdT79wq1Mvlap3QSCLhcD2D3fCkKVWid4aSjtp9FOX1Uaf7P9eT93zd9Sv
|
|
||||||
mj2yNLRUGzyI/0oONNSzmmkvJ5Cq2X2CdldIWMGZO57RJ8oyATAWTQmRmNkfh0Sx
|
|
||||||
uuR/J9oUsomVy1AEntc0dlPivkqBkBqrxU3j5PnWkaI3ZRGc0gg9spCQEISh4xEU
|
|
||||||
pMhVrnmDQLfLP8Ouqpx917MAw7hkjQk6BJFTAbXDsz3LSHIxo/gB8qrA1vbvdZZh
|
|
||||||
LtR0frJdfdppX8nAQX/TAxOQ8+H6yw8a9i7/zJEfSYIhop59N/fhcWW2F14cj2Xc
|
|
||||||
fyHaZ04lTO4uPnly91jwuFPaREuZVp8AxImIhlkxkAN61tWdWG7tEbaCgszh6VIz
|
|
||||||
ThFnHo2Vi8SQXPrXCN7J9Tc9ZYiAYqoThV/u6SYsea5aZL8deOvKBQCgZZuIxX1z
|
|
||||||
4EnfcqG176vY4VqMBIC4pMJz0WcHJYqN+j7BiwGoMBwExrIdTB7q4XIFLotcIpS0
|
|
||||||
1MqyVsesvoQq7WObmGQXdMliMirSLcDuSx8Qy+4pIBgGDIyMp1qbonnGdcHYvU8S
|
|
||||||
O0A8s/iua5oFdNZTWvbVI4FUH9sKcLiB3/fIAF+sB4n8q6L+UCfmbPcAo/crQ6b3
|
|
||||||
HqhDBMY9J0q/jdz9GNYZ/1fbXdkUqAQKFePhtzJDRBZba27+LPQNMCcrHMq06F1T
|
|
||||||
4QmLmkHt7LxB2pAczUO+T2O9bHEw/HWw+dYf2MoRDUw=
|
|
||||||
`
|
|
||||||
|
|
||||||
var outOfRangeSelector = []byte{
|
|
||||||
0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26,
|
|
||||||
0x53, 0x59, 0x4e, 0xec, 0xe8, 0x36, 0x00, 0x00,
|
|
||||||
0x02, 0x51, 0x80, 0x00, 0x10, 0x40, 0x00, 0x06,
|
|
||||||
0x44, 0x90, 0x80, 0x20, 0x00, 0x31, 0x06, 0x4c,
|
|
||||||
0x41, 0x01, 0xa7, 0xa9, 0xa5, 0x80, 0xbb, 0x94,
|
|
||||||
0x31, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x00,
|
|
||||||
0x00, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
||||||
|
’Õe&¬DJJ¯Š9d¬ E
CÖÏ#;Ð23ôº’øqžl*+Ôõø<C3B5>°~Í
££;&4ƒÛ›,‡†cc¾5Ñs5º
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,32 +0,0 @@
|
||||||
// Copyright 2012 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 flate
|
|
||||||
|
|
||||||
// forwardCopy is like the built-in copy function except that it always goes
|
|
||||||
// forward from the start, even if the dst and src overlap.
|
|
||||||
// It is equivalent to:
|
|
||||||
// for i := 0; i < n; i++ {
|
|
||||||
// mem[dst+i] = mem[src+i]
|
|
||||||
// }
|
|
||||||
func forwardCopy(mem []byte, dst, src, n int) {
|
|
||||||
if dst <= src {
|
|
||||||
copy(mem[dst:dst+n], mem[src:src+n])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
if dst >= src+n {
|
|
||||||
copy(mem[dst:dst+n], mem[src:src+n])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// There is some forward overlap. The destination
|
|
||||||
// will be filled with a repeated pattern of mem[src:src+k].
|
|
||||||
// We copy one instance of the pattern here, then repeat.
|
|
||||||
// Each time around this loop k will double.
|
|
||||||
k := dst - src
|
|
||||||
copy(mem[dst:dst+k], mem[src:src+k])
|
|
||||||
n -= k
|
|
||||||
dst += k
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
// Copyright 2012 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 flate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestForwardCopy(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
dst0, dst1 int
|
|
||||||
src0, src1 int
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{0, 9, 0, 9, "012345678"},
|
|
||||||
{0, 5, 4, 9, "45678"},
|
|
||||||
{4, 9, 0, 5, "01230"},
|
|
||||||
{1, 6, 3, 8, "34567"},
|
|
||||||
{3, 8, 1, 6, "12121"},
|
|
||||||
{0, 9, 3, 6, "345"},
|
|
||||||
{3, 6, 0, 9, "012"},
|
|
||||||
{1, 6, 0, 9, "00000"},
|
|
||||||
{0, 4, 7, 8, "7"},
|
|
||||||
{0, 1, 6, 8, "6"},
|
|
||||||
{4, 4, 6, 9, ""},
|
|
||||||
{2, 8, 6, 6, ""},
|
|
||||||
{0, 0, 0, 0, ""},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
b := []byte("0123456789")
|
|
||||||
n := tc.dst1 - tc.dst0
|
|
||||||
if tc.src1-tc.src0 < n {
|
|
||||||
n = tc.src1 - tc.src0
|
|
||||||
}
|
|
||||||
forwardCopy(b, tc.dst0, tc.src0, n)
|
|
||||||
got := string(b[tc.dst0 : tc.dst0+n])
|
|
||||||
if got != tc.want {
|
|
||||||
t.Errorf("dst=b[%d:%d], src=b[%d:%d]: got %q, want %q",
|
|
||||||
tc.dst0, tc.dst1, tc.src0, tc.src1, got, tc.want)
|
|
||||||
}
|
|
||||||
// Check that the bytes outside of dst[:n] were not modified.
|
|
||||||
for i, x := range b {
|
|
||||||
if i >= tc.dst0 && i < tc.dst0+n {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if int(x) != '0'+i {
|
|
||||||
t.Errorf("dst=b[%d:%d], src=b[%d:%d]: copy overrun at b[%d]: got '%c', want '%c'",
|
|
||||||
tc.dst0, tc.dst1, tc.src0, tc.src1, i, x, '0'+i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue