mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-15 05:10:27 +08:00
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
|
||||
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
|
||||
last merge done from the master library sources.
|
||||
|
@ -111,6 +111,7 @@ endif
|
||||
toolexeclibgo_DATA = \
|
||||
bufio.gox \
|
||||
bytes.gox \
|
||||
context.gox \
|
||||
crypto.gox \
|
||||
encoding.gox \
|
||||
errors.gox \
|
||||
@ -315,6 +316,7 @@ toolexeclibgonethttp_DATA = \
|
||||
net/http/cookiejar.gox \
|
||||
net/http/fcgi.gox \
|
||||
net/http/httptest.gox \
|
||||
net/http/httptrace.gox \
|
||||
net/http/httputil.gox \
|
||||
net/http/pprof.gox
|
||||
|
||||
@ -593,6 +595,9 @@ go_bytes_files = \
|
||||
go_bytes_c_files = \
|
||||
go/bytes/indexbyte.c
|
||||
|
||||
go_context_files = \
|
||||
go/context/context.go
|
||||
|
||||
go_crypto_files = \
|
||||
go/crypto/crypto.go
|
||||
|
||||
@ -776,15 +781,19 @@ if LIBGO_IS_LINUX
|
||||
go_net_interface_file = go/net/interface_linux.go
|
||||
else
|
||||
if LIBGO_IS_NETBSD
|
||||
go_net_interface_file = go/net/interface_netbsd.go
|
||||
go_net_interface_file = go/net/interface_bsdvar.go
|
||||
else
|
||||
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
|
||||
go_net_interface_file = go/net/interface_stub.go
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if LIBGO_IS_LINUX
|
||||
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/parse.go \
|
||||
go/net/pipe.go \
|
||||
go/net/port.go \
|
||||
go/net/fd_poll_runtime.go \
|
||||
go/net/port_unix.go \
|
||||
$(go_net_sendfile_file) \
|
||||
@ -991,6 +1001,20 @@ 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_dir_file) \
|
||||
go/os/dir.go \
|
||||
@ -1016,7 +1040,8 @@ go_os_files = \
|
||||
$(go_os_sys_file) \
|
||||
$(go_os_cloexec_file) \
|
||||
go/os/types.go \
|
||||
go/os/types_unix.go
|
||||
go/os/types_unix.go \
|
||||
$(go_os_wait_file)
|
||||
|
||||
go_path_files = \
|
||||
go/path/match.go \
|
||||
@ -1048,6 +1073,7 @@ go_runtime_files = \
|
||||
go/runtime/error.go \
|
||||
go/runtime/extern.go \
|
||||
go/runtime/mem.go \
|
||||
go/runtime/symtab.go \
|
||||
version.go
|
||||
|
||||
version.go: s-version; @true
|
||||
@ -1134,6 +1160,7 @@ go_testing_files = \
|
||||
go/testing/benchmark.go \
|
||||
go/testing/cover.go \
|
||||
go/testing/example.go \
|
||||
go/testing/match.go \
|
||||
go/testing/testing.go
|
||||
|
||||
go_time_files = \
|
||||
@ -1174,6 +1201,7 @@ endif
|
||||
|
||||
go_archive_tar_files = \
|
||||
go/archive/tar/common.go \
|
||||
go/archive/tar/format.go \
|
||||
go/archive/tar/reader.go \
|
||||
go/archive/tar/stat_unix.go \
|
||||
go/archive/tar/writer.go \
|
||||
@ -1192,8 +1220,9 @@ go_compress_bzip2_files = \
|
||||
go/compress/bzip2/move_to_front.go
|
||||
|
||||
go_compress_flate_files = \
|
||||
go/compress/flate/copy.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_code.go \
|
||||
go/compress/flate/inflate.go \
|
||||
@ -1225,7 +1254,8 @@ go_crypto_aes_files = \
|
||||
go/crypto/aes/block.go \
|
||||
go/crypto/aes/cipher.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/cbc.go \
|
||||
go/crypto/cipher/cfb.go \
|
||||
@ -1257,8 +1287,12 @@ go_crypto_md5_files = \
|
||||
if LIBGO_IS_LINUX
|
||||
crypto_rand_file = go/crypto/rand/rand_linux.go
|
||||
else
|
||||
if LIBGO_IS_OPENBSD
|
||||
crypto_rand_file = go/crypto/rand/rand_openbsd.go
|
||||
else
|
||||
crypto_rand_file =
|
||||
endif
|
||||
endif
|
||||
|
||||
go_crypto_rand_files = \
|
||||
go/crypto/rand/eagain.go \
|
||||
@ -1280,10 +1314,12 @@ go_crypto_sha1_files = \
|
||||
go/crypto/sha1/sha1block_generic.go
|
||||
go_crypto_sha256_files = \
|
||||
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/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/constant_time.go
|
||||
go_crypto_tls_files = \
|
||||
@ -1375,7 +1411,10 @@ go_debug_macho_files = \
|
||||
go/debug/macho/macho.go
|
||||
go_debug_pe_files = \
|
||||
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/file.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/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/adler32.go
|
||||
go_hash_crc32_files = \
|
||||
@ -1576,11 +1696,8 @@ go_index_suffixarray_files = \
|
||||
go/index/suffixarray/qsufsort.go \
|
||||
go/index/suffixarray/suffixarray.go
|
||||
|
||||
go_internal_golang_org_x_net_http2_hpack_files = \
|
||||
go/internal/golang.org/x/net/http2/hpack/encode.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_nettrace_files = \
|
||||
go/internal/nettrace/nettrace.go
|
||||
go_internal_race_files = \
|
||||
go/internal/race/doc.go \
|
||||
go/internal/race/norace.go
|
||||
@ -1603,15 +1720,23 @@ else
|
||||
if LIBGO_IS_MIPS64
|
||||
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getrandom_linux.go go/internal/syscall/unix/getrandom_linux_mips64x.go
|
||||
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
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else
|
||||
if LIBGO_IS_OPENBSD
|
||||
internal_syscall_unix_getrandom_files = go/internal/syscall/unix/getentropy_openbsd.go
|
||||
else
|
||||
internal_syscall_unix_getrandom_files =
|
||||
endif
|
||||
endif
|
||||
|
||||
go_internal_syscall_unix_files = \
|
||||
go/internal/syscall/unix/dummy.go \
|
||||
@ -1621,6 +1746,7 @@ go_internal_testenv_files = \
|
||||
go/internal/testenv/testenv.go
|
||||
go_internal_trace_files = \
|
||||
go/internal/trace/goroutines.go \
|
||||
go/internal/trace/order.go \
|
||||
go/internal/trace/parser.go
|
||||
|
||||
go_io_ioutil_files = \
|
||||
@ -1684,8 +1810,8 @@ go_net_http_files = \
|
||||
go/net/http/fs.go \
|
||||
go/net/http/h2_bundle.go \
|
||||
go/net/http/header.go \
|
||||
go/net/http/http.go \
|
||||
go/net/http/jar.go \
|
||||
go/net/http/lex.go \
|
||||
go/net/http/method.go \
|
||||
go/net/http/request.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/fcgi.go
|
||||
go_net_http_httptest_files = \
|
||||
go/net/http/httptest/httptest.go \
|
||||
go/net/http/httptest/recorder.go \
|
||||
go/net/http/httptest/server.go
|
||||
go_net_http_pprof_files = \
|
||||
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/dump.go \
|
||||
go/net/http/httputil/httputil.go \
|
||||
@ -1768,15 +1897,18 @@ go_os_signal_files = \
|
||||
|
||||
if LIBGO_IS_SOLARIS
|
||||
os_user_decls_file = go/os/user/decls_solaris.go
|
||||
os_user_listgroups_file = go/os/user/listgroups_solaris.go
|
||||
else
|
||||
os_user_decls_file = go/os/user/decls_unix.go
|
||||
os_user_listgroups_file = go/os/user/listgroups_unix.go
|
||||
endif
|
||||
|
||||
go_os_user_files = \
|
||||
go/os/user/lookup.go \
|
||||
go/os/user/lookup_unix.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/match.go \
|
||||
@ -2147,6 +2279,7 @@ libgo_go_objs = \
|
||||
bufio.lo \
|
||||
bytes.lo \
|
||||
bytes/index.lo \
|
||||
context.lo \
|
||||
crypto.lo \
|
||||
encoding.lo \
|
||||
errors.lo \
|
||||
@ -2242,6 +2375,9 @@ libgo_go_objs = \
|
||||
go/scanner.lo \
|
||||
go/token.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/crc32.lo \
|
||||
hash/crc64.lo \
|
||||
@ -2250,6 +2386,7 @@ libgo_go_objs = \
|
||||
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 \
|
||||
@ -2261,7 +2398,7 @@ libgo_go_objs = \
|
||||
image/jpeg.lo \
|
||||
image/png.lo \
|
||||
index/suffixarray.lo \
|
||||
internal/golang.org/x/net/http2/hpack.lo \
|
||||
internal/nettrace.lo \
|
||||
internal/race.lo \
|
||||
internal/singleflight.lo \
|
||||
internal/syscall/unix.lo \
|
||||
@ -2460,6 +2597,15 @@ bytes/check: $(CHECK_DEPS)
|
||||
@$(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
|
||||
crypto.lo.dep: $(go_crypto_files)
|
||||
$(BUILDDEPS)
|
||||
@ -3275,6 +3421,35 @@ go/internal/gccgoimporter/check: $(CHECK_DEPS)
|
||||
@$(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
|
||||
hash/adler32.lo.dep: $(go_hash_adler32_files)
|
||||
$(BUILDDEPS)
|
||||
@ -3383,14 +3558,14 @@ index/suffixarray/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: index/suffixarray/check
|
||||
|
||||
@go_include@ internal/golang.org/x/net/http2/hpack.lo.dep
|
||||
internal/golang.org/x/net/http2/hpack.lo.dep: $(go_internal_golang_org_x_net_http2_hpack_files)
|
||||
@go_include@ internal/nettrace.lo.dep
|
||||
internal/nettrace.lo.dep: $(go_internal_nettrace_files)
|
||||
$(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)
|
||||
internal/golang.org/x/net/http2/hpack/check: $(CHECK_DEPS)
|
||||
internal/nettrace/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: internal/golang.org/x/net/http2/hpack/check
|
||||
.PHONY: internal/nettrace/check
|
||||
|
||||
@go_include@ internal/race.lo.dep
|
||||
internal/race.lo.dep: $(go_internal_race_files)
|
||||
@ -3593,6 +3768,15 @@ net/http/httptest/check: $(check_deps)
|
||||
@$(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
|
||||
net/http/httputil.lo.dep: $(go_net_http_httputil_files)
|
||||
$(BUILDDEPS)
|
||||
@ -3833,6 +4017,8 @@ bufio.gox: bufio.lo
|
||||
$(BUILDGOX)
|
||||
bytes.gox: bytes.lo
|
||||
$(BUILDGOX)
|
||||
context.gox: context.lo
|
||||
$(BUILDGOX)
|
||||
crypto.gox: crypto.lo
|
||||
$(BUILDGOX)
|
||||
encoding.gox: encoding.lo
|
||||
@ -4027,6 +4213,17 @@ go/internal/gcimporter.gox: go/internal/gcimporter.lo
|
||||
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
|
||||
$(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
|
||||
$(BUILDGOX)
|
||||
hash/crc32.gox: hash/crc32.lo
|
||||
@ -4055,7 +4252,7 @@ image/color/palette.gox: image/color/palette.lo
|
||||
index/suffixarray.gox: index/suffixarray.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
internal/golang.org/x/net/http2/hpack.gox: internal/golang.org/x/net/http2/hpack.lo
|
||||
internal/nettrace.gox: internal/nettrace.lo
|
||||
$(BUILDGOX)
|
||||
internal/race.gox: internal/race.lo
|
||||
$(BUILDGOX)
|
||||
@ -4107,6 +4304,8 @@ net/http/fcgi.gox: net/http/fcgi.lo
|
||||
$(BUILDGOX)
|
||||
net/http/httptest.gox: net/http/httptest.lo
|
||||
$(BUILDGOX)
|
||||
net/http/httptrace.gox: net/http/httptrace.lo
|
||||
$(BUILDGOX)
|
||||
net/http/httputil.gox: net/http/httputil.lo
|
||||
$(BUILDGOX)
|
||||
net/http/pprof.gox: net/http/pprof.lo
|
||||
@ -4169,6 +4368,7 @@ unicode/utf8.gox: unicode/utf8.lo
|
||||
TEST_PACKAGES = \
|
||||
bufio/check \
|
||||
bytes/check \
|
||||
context/check \
|
||||
errors/check \
|
||||
expvar/check \
|
||||
flag/check \
|
||||
@ -4252,6 +4452,9 @@ TEST_PACKAGES = \
|
||||
go/scanner/check \
|
||||
go/token/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/crc32/check \
|
||||
hash/crc64/check \
|
||||
@ -4261,7 +4464,6 @@ TEST_PACKAGES = \
|
||||
image/jpeg/check \
|
||||
image/png/check \
|
||||
index/suffixarray/check \
|
||||
internal/golang.org/x/net/http2/hpack/check \
|
||||
internal/singleflight/check \
|
||||
internal/trace/check \
|
||||
io/ioutil/check \
|
||||
@ -4276,6 +4478,7 @@ TEST_PACKAGES = \
|
||||
net/http/cookiejar/check \
|
||||
net/http/fcgi/check \
|
||||
net/http/httptest/check \
|
||||
net/http/httptrace/check \
|
||||
net/http/httputil/check \
|
||||
net/http/internal/check \
|
||||
net/internal/socktest/check \
|
||||
|
@ -174,14 +174,14 @@ am_libnetgo_a_OBJECTS = $(am__objects_3)
|
||||
libnetgo_a_OBJECTS = $(am_libnetgo_a_OBJECTS)
|
||||
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
|
||||
am__DEPENDENCIES_1 =
|
||||
am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
|
||||
encoding.lo errors.lo expvar.lo flag.lo fmt.lo hash.lo html.lo \
|
||||
image.lo io.lo log.lo math.lo mime.lo net.lo os.lo path.lo \
|
||||
reflect-go.lo reflect/makefunc_ffi_c.lo regexp.lo \
|
||||
runtime-go.lo sort.lo strconv.lo strings.lo strings/index.lo \
|
||||
sync.lo syscall.lo syscall/errno.lo syscall/signame.lo \
|
||||
syscall/wait.lo testing.lo time-go.lo unicode.lo \
|
||||
archive/tar.lo archive/zip.lo compress/bzip2.lo \
|
||||
am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo context.lo \
|
||||
crypto.lo encoding.lo errors.lo expvar.lo flag.lo fmt.lo \
|
||||
hash.lo html.lo image.lo io.lo log.lo math.lo mime.lo net.lo \
|
||||
os.lo path.lo reflect-go.lo reflect/makefunc_ffi_c.lo \
|
||||
regexp.lo runtime-go.lo sort.lo strconv.lo strings.lo \
|
||||
strings/index.lo sync.lo syscall.lo syscall/errno.lo \
|
||||
syscall/signame.lo syscall/wait.lo testing.lo time-go.lo \
|
||||
unicode.lo archive/tar.lo archive/zip.lo compress/bzip2.lo \
|
||||
compress/flate.lo compress/gzip.lo compress/lzw.lo \
|
||||
compress/zlib.lo container/heap.lo container/list.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/importer.lo go/internal/gcimporter.lo \
|
||||
go/internal/gccgoimporter.lo go/parser.lo go/printer.lo \
|
||||
go/scanner.lo go/token.lo go/types.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 \
|
||||
go/scanner.lo go/token.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/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 \
|
||||
image/color.lo image/color/palette.lo image/draw.lo \
|
||||
image/gif.lo image/internal/imageutil.lo image/jpeg.lo \
|
||||
image/png.lo index/suffixarray.lo \
|
||||
internal/golang.org/x/net/http2/hpack.lo internal/race.lo \
|
||||
internal/singleflight.lo internal/syscall/unix.lo \
|
||||
internal/testenv.lo internal/trace.lo io/ioutil.lo \
|
||||
log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \
|
||||
math/rand.lo mime/multipart.lo mime/quotedprintable.lo \
|
||||
net/http.lo net/internal/socktest.lo net/mail.lo net/rpc.lo \
|
||||
net/smtp.lo net/textproto.lo net/url.lo old/regexp.lo \
|
||||
old/template.lo os/exec.lo $(am__DEPENDENCIES_1) os/signal.lo \
|
||||
os/user.lo path/filepath.lo regexp/syntax.lo \
|
||||
image/png.lo index/suffixarray.lo internal/nettrace.lo \
|
||||
internal/race.lo internal/singleflight.lo \
|
||||
internal/syscall/unix.lo internal/testenv.lo internal/trace.lo \
|
||||
io/ioutil.lo log/syslog.lo log/syslog/syslog_c.lo math/big.lo \
|
||||
math/cmplx.lo math/rand.lo mime/multipart.lo \
|
||||
mime/quotedprintable.lo net/http.lo net/internal/socktest.lo \
|
||||
net/mail.lo net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
|
||||
old/regexp.lo old/template.lo os/exec.lo $(am__DEPENDENCIES_1) \
|
||||
os/signal.lo os/user.lo path/filepath.lo regexp/syntax.lo \
|
||||
net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
|
||||
sync/atomic.lo sync/atomic_c.lo text/scanner.lo \
|
||||
text/tabwriter.lo text/template.lo text/template/parse.lo \
|
||||
@ -576,6 +578,7 @@ FLAGS_TO_PASS = $(AM_MAKEFLAGS)
|
||||
toolexeclibgo_DATA = \
|
||||
bufio.gox \
|
||||
bytes.gox \
|
||||
context.gox \
|
||||
crypto.gox \
|
||||
encoding.gox \
|
||||
errors.gox \
|
||||
@ -758,6 +761,7 @@ toolexeclibgonethttp_DATA = \
|
||||
net/http/cookiejar.gox \
|
||||
net/http/fcgi.gox \
|
||||
net/http/httptest.gox \
|
||||
net/http/httptrace.gox \
|
||||
net/http/httputil.gox \
|
||||
net/http/pprof.gox
|
||||
|
||||
@ -946,6 +950,9 @@ go_bytes_files = \
|
||||
go_bytes_c_files = \
|
||||
go/bytes/indexbyte.c
|
||||
|
||||
go_context_files = \
|
||||
go/context/context.go
|
||||
|
||||
go_crypto_files = \
|
||||
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_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_DRAGONFLY_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_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_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@go_net_interface_file = go/net/interface_netbsd.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_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_TRUE@go_net_interface_file = go/net/interface_bsdvar.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_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
|
||||
@ -1129,6 +1137,7 @@ go_net_common_files = \
|
||||
go/net/nss.go \
|
||||
go/net/parse.go \
|
||||
go/net/pipe.go \
|
||||
go/net/port.go \
|
||||
go/net/fd_poll_runtime.go \
|
||||
go/net/port_unix.go \
|
||||
$(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_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_dir_file) \
|
||||
go/os/dir.go \
|
||||
@ -1215,7 +1228,8 @@ go_os_files = \
|
||||
$(go_os_sys_file) \
|
||||
$(go_os_cloexec_file) \
|
||||
go/os/types.go \
|
||||
go/os/types_unix.go
|
||||
go/os/types_unix.go \
|
||||
$(go_os_wait_file)
|
||||
|
||||
go_path_files = \
|
||||
go/path/match.go \
|
||||
@ -1248,6 +1262,7 @@ go_runtime_files = \
|
||||
go/runtime/error.go \
|
||||
go/runtime/extern.go \
|
||||
go/runtime/mem.go \
|
||||
go/runtime/symtab.go \
|
||||
version.go
|
||||
|
||||
noinst_DATA = zstdpkglist.go
|
||||
@ -1304,6 +1319,7 @@ go_testing_files = \
|
||||
go/testing/benchmark.go \
|
||||
go/testing/cover.go \
|
||||
go/testing/example.go \
|
||||
go/testing/match.go \
|
||||
go/testing/testing.go
|
||||
|
||||
go_time_files = \
|
||||
@ -1331,6 +1347,7 @@ go_unicode_files = \
|
||||
@LIBGO_IS_SOLARIS_TRUE@archive_tar_atim_file = go/archive/tar/stat_atim.go
|
||||
go_archive_tar_files = \
|
||||
go/archive/tar/common.go \
|
||||
go/archive/tar/format.go \
|
||||
go/archive/tar/reader.go \
|
||||
go/archive/tar/stat_unix.go \
|
||||
go/archive/tar/writer.go \
|
||||
@ -1349,8 +1366,9 @@ go_compress_bzip2_files = \
|
||||
go/compress/bzip2/move_to_front.go
|
||||
|
||||
go_compress_flate_files = \
|
||||
go/compress/flate/copy.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_code.go \
|
||||
go/compress/flate/inflate.go \
|
||||
@ -1382,7 +1400,8 @@ go_crypto_aes_files = \
|
||||
go/crypto/aes/block.go \
|
||||
go/crypto/aes/cipher.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/cbc.go \
|
||||
@ -1418,7 +1437,8 @@ go_crypto_md5_files = \
|
||||
go/crypto/md5/md5block.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
|
||||
go_crypto_rand_files = \
|
||||
go/crypto/rand/eagain.go \
|
||||
@ -1443,11 +1463,13 @@ go_crypto_sha1_files = \
|
||||
|
||||
go_crypto_sha256_files = \
|
||||
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/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/constant_time.go
|
||||
@ -1523,7 +1545,10 @@ go_debug_macho_files = \
|
||||
|
||||
go_debug_pe_files = \
|
||||
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/file.go \
|
||||
@ -1688,6 +1713,39 @@ go_go_internal_gccgoimporter_files = \
|
||||
go/go/internal/gccgoimporter/importer.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/adler32.go
|
||||
|
||||
@ -1750,11 +1808,8 @@ go_index_suffixarray_files = \
|
||||
go/index/suffixarray/qsufsort.go \
|
||||
go/index/suffixarray/suffixarray.go
|
||||
|
||||
go_internal_golang_org_x_net_http2_hpack_files = \
|
||||
go/internal/golang.org/x/net/http2/hpack/encode.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_nettrace_files = \
|
||||
go/internal/nettrace/nettrace.go
|
||||
|
||||
go_internal_race_files = \
|
||||
go/internal/race/doc.go \
|
||||
@ -1763,13 +1818,15 @@ go_internal_race_files = \
|
||||
go_internal_singleflight_files = \
|
||||
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_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_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_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/dummy.go \
|
||||
$(internal_syscall_unix_getrandom_files)
|
||||
@ -1779,6 +1836,7 @@ go_internal_testenv_files = \
|
||||
|
||||
go_internal_trace_files = \
|
||||
go/internal/trace/goroutines.go \
|
||||
go/internal/trace/order.go \
|
||||
go/internal/trace/parser.go
|
||||
|
||||
go_io_ioutil_files = \
|
||||
@ -1844,8 +1902,8 @@ go_net_http_files = \
|
||||
go/net/http/fs.go \
|
||||
go/net/http/h2_bundle.go \
|
||||
go/net/http/header.go \
|
||||
go/net/http/http.go \
|
||||
go/net/http/jar.go \
|
||||
go/net/http/lex.go \
|
||||
go/net/http/method.go \
|
||||
go/net/http/request.go \
|
||||
go/net/http/response.go \
|
||||
@ -1885,12 +1943,16 @@ go_net_http_fcgi_files = \
|
||||
go/net/http/fcgi/fcgi.go
|
||||
|
||||
go_net_http_httptest_files = \
|
||||
go/net/http/httptest/httptest.go \
|
||||
go/net/http/httptest/recorder.go \
|
||||
go/net/http/httptest/server.go
|
||||
|
||||
go_net_http_pprof_files = \
|
||||
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/dump.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_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/lookup.go \
|
||||
go/os/user/lookup_unix.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/match.go \
|
||||
@ -2158,6 +2223,7 @@ libgo_go_objs = \
|
||||
bufio.lo \
|
||||
bytes.lo \
|
||||
bytes/index.lo \
|
||||
context.lo \
|
||||
crypto.lo \
|
||||
encoding.lo \
|
||||
errors.lo \
|
||||
@ -2253,6 +2319,9 @@ libgo_go_objs = \
|
||||
go/scanner.lo \
|
||||
go/token.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/crc32.lo \
|
||||
hash/crc64.lo \
|
||||
@ -2261,6 +2330,7 @@ libgo_go_objs = \
|
||||
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 \
|
||||
@ -2272,7 +2342,7 @@ libgo_go_objs = \
|
||||
image/jpeg.lo \
|
||||
image/png.lo \
|
||||
index/suffixarray.lo \
|
||||
internal/golang.org/x/net/http2/hpack.lo \
|
||||
internal/nettrace.lo \
|
||||
internal/race.lo \
|
||||
internal/singleflight.lo \
|
||||
internal/syscall/unix.lo \
|
||||
@ -2439,6 +2509,7 @@ BUILDGOX = \
|
||||
TEST_PACKAGES = \
|
||||
bufio/check \
|
||||
bytes/check \
|
||||
context/check \
|
||||
errors/check \
|
||||
expvar/check \
|
||||
flag/check \
|
||||
@ -2522,6 +2593,9 @@ TEST_PACKAGES = \
|
||||
go/scanner/check \
|
||||
go/token/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/crc32/check \
|
||||
hash/crc64/check \
|
||||
@ -2531,7 +2605,6 @@ TEST_PACKAGES = \
|
||||
image/jpeg/check \
|
||||
image/png/check \
|
||||
index/suffixarray/check \
|
||||
internal/golang.org/x/net/http2/hpack/check \
|
||||
internal/singleflight/check \
|
||||
internal/trace/check \
|
||||
io/ioutil/check \
|
||||
@ -2546,6 +2619,7 @@ TEST_PACKAGES = \
|
||||
net/http/cookiejar/check \
|
||||
net/http/fcgi/check \
|
||||
net/http/httptest/check \
|
||||
net/http/httptrace/check \
|
||||
net/http/httputil/check \
|
||||
net/http/internal/check \
|
||||
net/internal/socktest/check \
|
||||
@ -4761,6 +4835,34 @@ s-zstdpkglist: Makefile
|
||||
echo '}' >> zstdpkglist.go.tmp
|
||||
$(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
|
||||
$(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
|
||||
s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files)
|
||||
@ -4841,6 +4943,15 @@ bytes/check: $(CHECK_DEPS)
|
||||
@$(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
|
||||
crypto.lo.dep: $(go_crypto_files)
|
||||
$(BUILDDEPS)
|
||||
@ -5656,6 +5767,33 @@ go/internal/gccgoimporter/check: $(CHECK_DEPS)
|
||||
@$(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
|
||||
hash/adler32.lo.dep: $(go_hash_adler32_files)
|
||||
$(BUILDDEPS)
|
||||
@ -5764,14 +5902,14 @@ index/suffixarray/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: index/suffixarray/check
|
||||
|
||||
@go_include@ internal/golang.org/x/net/http2/hpack.lo.dep
|
||||
internal/golang.org/x/net/http2/hpack.lo.dep: $(go_internal_golang_org_x_net_http2_hpack_files)
|
||||
@go_include@ internal/nettrace.lo.dep
|
||||
internal/nettrace.lo.dep: $(go_internal_nettrace_files)
|
||||
$(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)
|
||||
internal/golang.org/x/net/http2/hpack/check: $(CHECK_DEPS)
|
||||
internal/nettrace/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: internal/golang.org/x/net/http2/hpack/check
|
||||
.PHONY: internal/nettrace/check
|
||||
|
||||
@go_include@ internal/race.lo.dep
|
||||
internal/race.lo.dep: $(go_internal_race_files)
|
||||
@ -5974,6 +6112,15 @@ net/http/httptest/check: $(check_deps)
|
||||
@$(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
|
||||
net/http/httputil.lo.dep: $(go_net_http_httputil_files)
|
||||
$(BUILDDEPS)
|
||||
@ -6205,6 +6352,8 @@ bufio.gox: bufio.lo
|
||||
$(BUILDGOX)
|
||||
bytes.gox: bytes.lo
|
||||
$(BUILDGOX)
|
||||
context.gox: context.lo
|
||||
$(BUILDGOX)
|
||||
crypto.gox: crypto.lo
|
||||
$(BUILDGOX)
|
||||
encoding.gox: encoding.lo
|
||||
@ -6399,6 +6548,15 @@ go/internal/gcimporter.gox: go/internal/gcimporter.lo
|
||||
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
|
||||
$(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
|
||||
$(BUILDGOX)
|
||||
hash/crc32.gox: hash/crc32.lo
|
||||
@ -6427,7 +6585,7 @@ image/color/palette.gox: image/color/palette.lo
|
||||
index/suffixarray.gox: index/suffixarray.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
internal/golang.org/x/net/http2/hpack.gox: internal/golang.org/x/net/http2/hpack.lo
|
||||
internal/nettrace.gox: internal/nettrace.lo
|
||||
$(BUILDGOX)
|
||||
internal/race.gox: internal/race.lo
|
||||
$(BUILDGOX)
|
||||
@ -6479,6 +6637,8 @@ net/http/fcgi.gox: net/http/fcgi.lo
|
||||
$(BUILDGOX)
|
||||
net/http/httptest.gox: net/http/httptest.lo
|
||||
$(BUILDGOX)
|
||||
net/http/httptrace.gox: net/http/httptrace.lo
|
||||
$(BUILDGOX)
|
||||
net/http/httputil.gox: net/http/httputil.lo
|
||||
$(BUILDGOX)
|
||||
net/http/pprof.gox: net/http/pprof.lo
|
||||
|
@ -1 +1 @@
|
||||
go1.6.1
|
||||
go1.7rc3
|
||||
|
18
libgo/configure
vendored
18
libgo/configure
vendored
@ -670,6 +670,8 @@ LIBGO_IS_386_FALSE
|
||||
LIBGO_IS_386_TRUE
|
||||
USE_DEJAGNU
|
||||
GOOS
|
||||
LIBGO_IS_BSD_FALSE
|
||||
LIBGO_IS_BSD_TRUE
|
||||
LIBGO_IS_SOLARIS_FALSE
|
||||
LIBGO_IS_SOLARIS_TRUE
|
||||
LIBGO_IS_RTEMS_FALSE
|
||||
@ -11126,7 +11128,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 11129 "configure"
|
||||
#line 11131 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -11232,7 +11234,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 11235 "configure"
|
||||
#line 11237 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -13611,6 +13613,14 @@ else
|
||||
LIBGO_IS_SOLARIS_FALSE=
|
||||
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
|
||||
@ -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.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
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
|
||||
as_fn_error "conditional \"LIBGO_IS_386\" was never defined.
|
||||
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_RTEMS, test $is_rtems = 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)
|
||||
|
||||
dnl Test whether we need to use DejaGNU or whether we can use the
|
||||
|
@ -21,10 +21,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Header type flags.
|
||||
const (
|
||||
blockSize = 512
|
||||
|
||||
// Types
|
||||
TypeReg = '0' // regular file
|
||||
TypeRegA = '\x00' // regular file
|
||||
TypeLink = '1' // hard link
|
||||
@ -61,12 +59,6 @@ type Header struct {
|
||||
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.
|
||||
func (h *Header) FileInfo() os.FileInfo {
|
||||
return headerFileInfo{h}
|
||||
@ -279,33 +271,6 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
|
||||
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 {
|
||||
for _, c := range s {
|
||||
if c >= 0x80 {
|
||||
|
197
libgo/go/archive/tar/format.go
Normal file
197
libgo/go/archive/tar/format.go
Normal file
@ -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/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -30,11 +29,11 @@ const maxNanoSecondIntSize = 9
|
||||
// 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.
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
err error
|
||||
pad int64 // amount of padding (ignored) after current file entry
|
||||
curr numBytesReader // reader for current file entry
|
||||
hdrBuff [blockSize]byte // buffer to use in readHeader
|
||||
r io.Reader
|
||||
err error
|
||||
pad int64 // amount of padding (ignored) after current file entry
|
||||
curr numBytesReader // reader for current file entry
|
||||
blk block // buffer to use as temporary local storage
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
@ -99,17 +98,6 @@ const (
|
||||
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.
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
hdr.Size = int64(size)
|
||||
hdr.Size = size
|
||||
default:
|
||||
if strings.HasPrefix(k, paxXattr) {
|
||||
if hdr.Xattrs == nil {
|
||||
@ -337,17 +325,17 @@ func parsePAXTime(t string) (time.Time, error) {
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
nano_buf := string(buf[pos+1:])
|
||||
nanoBuf := string(buf[pos+1:])
|
||||
// Pad as needed before converting to a decimal.
|
||||
// For example .030 -> .030000000 -> 30000000 nanoseconds
|
||||
if len(nano_buf) < maxNanoSecondIntSize {
|
||||
if len(nanoBuf) < maxNanoSecondIntSize {
|
||||
// Right pad
|
||||
nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf))
|
||||
} else if len(nano_buf) > maxNanoSecondIntSize {
|
||||
nanoBuf += strings.Repeat("0", maxNanoSecondIntSize-len(nanoBuf))
|
||||
} else if len(nanoBuf) > maxNanoSecondIntSize {
|
||||
// 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 {
|
||||
return time.Time{}, err
|
||||
}
|
||||
@ -379,14 +367,14 @@ func parsePAX(r io.Reader) (map[string]string, error) {
|
||||
}
|
||||
sbuf = residual
|
||||
|
||||
keyStr := string(key)
|
||||
keyStr := key
|
||||
if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes {
|
||||
// GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map.
|
||||
sparseMap.WriteString(value)
|
||||
sparseMap.Write([]byte{','})
|
||||
} else {
|
||||
// Normal key. Set the value in the headers map.
|
||||
headers[keyStr] = string(value)
|
||||
headers[keyStr] = value
|
||||
}
|
||||
}
|
||||
if sparseMap.Len() != 0 {
|
||||
@ -523,10 +511,10 @@ func (tr *Reader) skipUnread() error {
|
||||
// io.Seeker, but calling Seek always returns an error and performs
|
||||
// no action. Thus, we try an innocent seek to the current position
|
||||
// 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 {
|
||||
// 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 {
|
||||
tr.err = err
|
||||
return tr.err
|
||||
@ -543,17 +531,6 @@ func (tr *Reader) skipUnread() error {
|
||||
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
|
||||
// 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.
|
||||
// * At least 2 blocks of zeros are read.
|
||||
func (tr *Reader) readHeader() *Header {
|
||||
header := tr.hdrBuff[:]
|
||||
copy(header, 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
|
||||
}
|
||||
|
||||
// Two blocks of zero bytes marks the end of the archive.
|
||||
if bytes.Equal(header, zeroBlock[0:blockSize]) {
|
||||
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
||||
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
|
||||
if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
|
||||
return nil // io.EOF is okay here
|
||||
}
|
||||
if bytes.Equal(header, zeroBlock[0:blockSize]) {
|
||||
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
|
||||
tr.err = io.EOF
|
||||
} else {
|
||||
tr.err = ErrHeader // zero block and then non-zero block
|
||||
@ -582,71 +556,55 @@ func (tr *Reader) readHeader() *Header {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !tr.verifyChecksum(header) {
|
||||
// Verify the header matches a known format.
|
||||
format := tr.blk.GetFormat()
|
||||
if format == formatUnknown {
|
||||
tr.err = ErrHeader
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unpack
|
||||
var p parser
|
||||
hdr := new(Header)
|
||||
s := slicer(header)
|
||||
|
||||
hdr.Name = p.parseString(s.next(100))
|
||||
hdr.Mode = p.parseNumeric(s.next(8))
|
||||
hdr.Uid = int(p.parseNumeric(s.next(8)))
|
||||
hdr.Gid = int(p.parseNumeric(s.next(8)))
|
||||
hdr.Size = p.parseNumeric(s.next(12))
|
||||
hdr.ModTime = time.Unix(p.parseNumeric(s.next(12)), 0)
|
||||
s.next(8) // chksum
|
||||
hdr.Typeflag = s.next(1)[0]
|
||||
hdr.Linkname = p.parseString(s.next(100))
|
||||
// Unpack the V7 header.
|
||||
v7 := tr.blk.V7()
|
||||
hdr.Name = p.parseString(v7.Name())
|
||||
hdr.Mode = p.parseNumeric(v7.Mode())
|
||||
hdr.Uid = int(p.parseNumeric(v7.UID()))
|
||||
hdr.Gid = int(p.parseNumeric(v7.GID()))
|
||||
hdr.Size = p.parseNumeric(v7.Size())
|
||||
hdr.ModTime = time.Unix(p.parseNumeric(v7.ModTime()), 0)
|
||||
hdr.Typeflag = v7.TypeFlag()[0]
|
||||
hdr.Linkname = p.parseString(v7.LinkName())
|
||||
|
||||
// The remainder of the header depends on the value of magic.
|
||||
// The original (v7) version of tar had no explicit magic field,
|
||||
// so its magic bytes, like the rest of the block, are NULs.
|
||||
magic := string(s.next(8)) // contains version field as well.
|
||||
var format string
|
||||
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)
|
||||
// Unpack format specific fields.
|
||||
if format > formatV7 {
|
||||
ustar := tr.blk.USTAR()
|
||||
hdr.Uname = p.parseString(ustar.UserName())
|
||||
hdr.Gname = p.parseString(ustar.GroupName())
|
||||
if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock {
|
||||
hdr.Devmajor = p.parseNumeric(devmajor)
|
||||
hdr.Devminor = p.parseNumeric(devminor)
|
||||
hdr.Devmajor = p.parseNumeric(ustar.DevMajor())
|
||||
hdr.Devminor = p.parseNumeric(ustar.DevMinor())
|
||||
}
|
||||
|
||||
var prefix string
|
||||
switch format {
|
||||
case "posix", "gnu":
|
||||
prefix = p.parseString(s.next(155))
|
||||
case "star":
|
||||
prefix = p.parseString(s.next(131))
|
||||
hdr.AccessTime = time.Unix(p.parseNumeric(s.next(12)), 0)
|
||||
hdr.ChangeTime = time.Unix(p.parseNumeric(s.next(12)), 0)
|
||||
case formatUSTAR, formatGNU:
|
||||
// TODO(dsnet): Do not use the prefix field for the GNU format!
|
||||
// See golang.org/issues/12594
|
||||
ustar := tr.blk.USTAR()
|
||||
prefix = p.parseString(ustar.Prefix())
|
||||
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 {
|
||||
hdr.Name = prefix + "/" + hdr.Name
|
||||
}
|
||||
}
|
||||
|
||||
if p.err != nil {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
}
|
||||
|
||||
nb := hdr.Size
|
||||
if isHeaderOnlyType(hdr.Typeflag) {
|
||||
nb = 0
|
||||
@ -663,14 +621,14 @@ func (tr *Reader) readHeader() *Header {
|
||||
// Check for old GNU sparse format entry.
|
||||
if hdr.Typeflag == TypeGNUSparse {
|
||||
// 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 {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read the sparse map.
|
||||
sp := tr.readOldGNUSparseMap(header)
|
||||
sp := tr.readOldGNUSparseMap(&tr.blk)
|
||||
if tr.err != nil {
|
||||
return nil
|
||||
}
|
||||
@ -682,26 +640,24 @@ func (tr *Reader) readHeader() *Header {
|
||||
}
|
||||
}
|
||||
|
||||
if p.err != nil {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
}
|
||||
|
||||
return hdr
|
||||
}
|
||||
|
||||
// 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,
|
||||
// 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
|
||||
isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0
|
||||
spCap := oldGNUSparseMainHeaderNumEntries
|
||||
if isExtended {
|
||||
spCap += oldGNUSparseExtendedHeaderNumEntries
|
||||
}
|
||||
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))
|
||||
var s sparseArray = blk.GNU().Sparse()
|
||||
var sp = make([]sparseEntry, 0, s.MaxEntries())
|
||||
for i := 0; i < s.MaxEntries(); i++ {
|
||||
offset := p.parseOctal(s.Entry(i).Offset())
|
||||
numBytes := p.parseOctal(s.Entry(i).NumBytes())
|
||||
if p.err != nil {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
@ -712,17 +668,17 @@ func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
|
||||
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.
|
||||
sparseHeader := make([]byte, blockSize)
|
||||
if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil {
|
||||
var blk block
|
||||
if _, tr.err = io.ReadFull(tr.r, blk[:]); tr.err != nil {
|
||||
return nil
|
||||
}
|
||||
isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0
|
||||
s = slicer(sparseHeader)
|
||||
for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ {
|
||||
offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize))
|
||||
numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize))
|
||||
s = blk.Sparse()
|
||||
|
||||
for i := 0; i < s.MaxEntries(); i++ {
|
||||
offset := p.parseOctal(s.Entry(i).Offset())
|
||||
numBytes := p.parseOctal(s.Entry(i).NumBytes())
|
||||
if p.err != nil {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
|
@ -36,10 +36,10 @@ type Writer struct {
|
||||
nb int64 // number of unwritten bytes for current file entry
|
||||
pad int64 // amount of padding to write after current file entry
|
||||
closed bool
|
||||
usedBinary bool // whether the binary numeric field extension was used
|
||||
preferPax bool // use pax header instead of binary numeric header
|
||||
hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header
|
||||
paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
|
||||
usedBinary bool // whether the binary numeric field extension was used
|
||||
preferPax bool // use PAX header instead of binary numeric header
|
||||
hdrBuff block // buffer to use in writeHeader when writing a regular header
|
||||
paxHdrBuff block // buffer to use in writeHeader when writing a PAX header
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
// too long fields or non ascii characters
|
||||
|
||||
var f formatter
|
||||
var header []byte
|
||||
|
||||
// We need to select which scratch buffer to use carefully,
|
||||
// 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 false, we are being called by writePAXHeader, and hdrBuff is
|
||||
// already being used by the non-recursive call, so we must use paxHdrBuff.
|
||||
header = tw.hdrBuff[:]
|
||||
header := &tw.hdrBuff
|
||||
if !allowPax {
|
||||
header = tw.paxHdrBuff[:]
|
||||
header = &tw.paxHdrBuff
|
||||
}
|
||||
copy(header, zeroBlock)
|
||||
s := slicer(header)
|
||||
copy(header[:], zeroBlock[:])
|
||||
|
||||
// Wrappers around formatter that automatically sets paxHeaders if the
|
||||
// argument extends beyond the capacity of the input byte slice.
|
||||
var f formatter
|
||||
var formatString = func(b []byte, s string, paxKeyword string) {
|
||||
needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s)
|
||||
if needsPaxHeader {
|
||||
@ -202,44 +199,33 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||
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.
|
||||
var modTime int64
|
||||
if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
|
||||
modTime = hdr.ModTime.Unix()
|
||||
}
|
||||
|
||||
f.formatOctal(s.next(8), hdr.Mode) // 100:108
|
||||
formatNumeric(s.next(8), int64(hdr.Uid), paxUid) // 108:116
|
||||
formatNumeric(s.next(8), int64(hdr.Gid), paxGid) // 116:124
|
||||
formatNumeric(s.next(12), hdr.Size, paxSize) // 124:136
|
||||
formatNumeric(s.next(12), modTime, paxNone) // 136:148 --- consider using pax for finer granularity
|
||||
s.next(8) // chksum (148:156)
|
||||
s.next(1)[0] = hdr.Typeflag // 156:157
|
||||
v7 := header.V7()
|
||||
formatString(v7.Name(), hdr.Name, paxPath)
|
||||
// TODO(dsnet): The GNU format permits the mode field to be encoded in
|
||||
// base-256 format. Thus, we can use formatNumeric instead of formatOctal.
|
||||
f.formatOctal(v7.Mode(), hdr.Mode)
|
||||
formatNumeric(v7.UID(), int64(hdr.Uid), paxUid)
|
||||
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
|
||||
_, paxPathUsed := paxHeaders[paxPath]
|
||||
if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
|
||||
prefix, suffix, ok := splitUSTARPath(hdr.Name)
|
||||
if ok {
|
||||
@ -247,16 +233,16 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||
delete(paxHeaders, paxPath)
|
||||
|
||||
// Update the path fields
|
||||
formatString(pathHeaderBytes, suffix, paxNone)
|
||||
formatString(prefixHeaderBytes, prefix, paxNone)
|
||||
formatString(v7.Name(), suffix, paxNone)
|
||||
formatString(ustar.Prefix(), prefix, paxNone)
|
||||
}
|
||||
}
|
||||
|
||||
// The chksum field is terminated by a NUL and a space.
|
||||
// This is different from the other octal fields.
|
||||
chksum, _ := checksum(header)
|
||||
f.formatOctal(header[148:155], chksum) // Never fails
|
||||
header[155] = ' '
|
||||
if tw.usedBinary {
|
||||
header.SetFormat(formatGNU)
|
||||
} else {
|
||||
header.SetFormat(formatUSTAR)
|
||||
}
|
||||
|
||||
// Check if there were any formatting errors.
|
||||
if f.err != nil {
|
||||
@ -278,10 +264,10 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
tw.nb = int64(hdr.Size)
|
||||
tw.nb = hdr.Size
|
||||
tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize
|
||||
|
||||
_, tw.err = tw.w.Write(header)
|
||||
_, tw.err = tw.w.Write(header[:])
|
||||
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).
|
||||
func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
||||
length := len(name)
|
||||
if length <= fileNameSize || !isASCII(name) {
|
||||
if length <= nameSize || !isASCII(name) {
|
||||
return "", "", false
|
||||
} else if length > fileNamePrefixSize+1 {
|
||||
length = fileNamePrefixSize + 1
|
||||
} else if length > prefixSize+1 {
|
||||
length = prefixSize + 1
|
||||
} else if name[length-1] == '/' {
|
||||
length--
|
||||
}
|
||||
@ -300,7 +286,7 @@ func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
||||
i := strings.LastIndex(name[:length], "/")
|
||||
nlen := len(name) - i - 1 // nlen is length of suffix
|
||||
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 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.
|
||||
ext.ModTime = hdr.ModTime
|
||||
// The spec asks that we namespace our pseudo files
|
||||
// with the current pid. However, this results in differing outputs
|
||||
// for identical inputs. As such, the constant 0 is now used instead.
|
||||
// with the current pid. However, this results in differing outputs
|
||||
// for identical inputs. As such, the constant 0 is now used instead.
|
||||
// golang.org/issue/12358
|
||||
dir, file := path.Split(hdr.Name)
|
||||
fullName := path.Join(dir, "PaxHeaders.0", file)
|
||||
|
||||
ascii := toASCII(fullName)
|
||||
if len(ascii) > 100 {
|
||||
ascii = ascii[:100]
|
||||
if len(ascii) > nameSize {
|
||||
ascii = ascii[:nameSize]
|
||||
}
|
||||
ext.Name = ascii
|
||||
// Construct the body
|
||||
@ -407,7 +393,7 @@ func (tw *Writer) Close() error {
|
||||
|
||||
// trailer: two zero blocks
|
||||
for i := 0; i < 2; i++ {
|
||||
_, tw.err = tw.w.Write(zeroBlock)
|
||||
_, tw.err = tw.w.Write(zeroBlock[:])
|
||||
if tw.err != nil {
|
||||
break
|
||||
}
|
||||
|
@ -587,17 +587,17 @@ func TestSplitUSTARPath(t *testing.T) {
|
||||
{"", "", "", false},
|
||||
{"abc", "", "", false},
|
||||
{"用戶名", "", "", false},
|
||||
{sr("a", fileNameSize), "", "", false},
|
||||
{sr("a", fileNameSize) + "/", "", "", false},
|
||||
{sr("a", fileNameSize) + "/a", sr("a", fileNameSize), "a", true},
|
||||
{sr("a", fileNamePrefixSize) + "/", "", "", false},
|
||||
{sr("a", fileNamePrefixSize) + "/a", sr("a", fileNamePrefixSize), "a", true},
|
||||
{sr("a", fileNameSize+1), "", "", false},
|
||||
{sr("/", fileNameSize+1), sr("/", fileNameSize-1), "/", true},
|
||||
{sr("a", fileNamePrefixSize) + "/" + sr("b", fileNameSize),
|
||||
sr("a", fileNamePrefixSize), sr("b", fileNameSize), true},
|
||||
{sr("a", fileNamePrefixSize) + "//" + sr("b", fileNameSize), "", "", false},
|
||||
{sr("a/", fileNameSize), sr("a/", 77) + "a", sr("a/", 22), true},
|
||||
{sr("a", nameSize), "", "", false},
|
||||
{sr("a", nameSize) + "/", "", "", false},
|
||||
{sr("a", nameSize) + "/a", sr("a", nameSize), "a", true},
|
||||
{sr("a", prefixSize) + "/", "", "", false},
|
||||
{sr("a", prefixSize) + "/a", sr("a", prefixSize), "a", true},
|
||||
{sr("a", nameSize+1), "", "", false},
|
||||
{sr("/", nameSize+1), sr("/", nameSize-1), "/", true},
|
||||
{sr("a", prefixSize) + "/" + sr("b", nameSize),
|
||||
sr("a", prefixSize), sr("b", nameSize), true},
|
||||
{sr("a", prefixSize) + "//" + sr("b", nameSize), "", "", false},
|
||||
{sr("a/", nameSize), sr("a/", 77) + "a", sr("a/", 22), true},
|
||||
}
|
||||
|
||||
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.Comment = end.comment
|
||||
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
|
||||
}
|
||||
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.
|
||||
// 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()
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
size := int64(f.CompressedSize64)
|
||||
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
|
||||
dcomp := f.zip.decompressor(f.Method)
|
||||
if dcomp == nil {
|
||||
err = ErrAlgorithm
|
||||
return
|
||||
return nil, ErrAlgorithm
|
||||
}
|
||||
rc = dcomp(r)
|
||||
var rc io.ReadCloser = dcomp(r)
|
||||
var desr io.Reader
|
||||
if f.hasDataDescriptor() {
|
||||
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,
|
||||
desr: desr,
|
||||
}
|
||||
return
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
type checksumReader struct {
|
||||
|
@ -399,7 +399,7 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
|
||||
// Don't bother uncompressing: too big.
|
||||
if ft.Content == nil && ft.File == "" && ft.Size > 0 {
|
||||
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()
|
||||
return
|
||||
|
@ -64,6 +64,44 @@ func (w *pooledFlateWriter) Close() error {
|
||||
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 (
|
||||
mu sync.RWMutex // guards compressor and decompressor maps
|
||||
|
||||
@ -74,7 +112,7 @@ var (
|
||||
|
||||
decompressors = map[uint16]Decompressor{
|
||||
Store: ioutil.NopCloser,
|
||||
Deflate: flate.NewReader,
|
||||
Deflate: newFlateReader,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
|
@ -52,7 +52,7 @@ func (w *Writer) Flush() error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if w.last != nil && !w.last.closed {
|
||||
if err := w.last.close(); err != nil {
|
||||
|
@ -184,7 +184,7 @@ func BenchmarkCompressedZipGarbage(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
var buf bytes.Buffer
|
||||
bigBuf := bytes.Repeat([]byte("a"), 1<<20)
|
||||
for i := 0; i < b.N; i++ {
|
||||
for i := 0; i <= b.N; i++ {
|
||||
buf.Reset()
|
||||
zw := NewWriter(&buf)
|
||||
for j := 0; j < 3; j++ {
|
||||
@ -195,5 +195,11 @@ func BenchmarkCompressedZipGarbage(b *testing.B) {
|
||||
w.Write(bigBuf)
|
||||
}
|
||||
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) {
|
||||
var buf bytes.Buffer
|
||||
z := NewWriter(&buf)
|
||||
|
@ -124,14 +124,16 @@ func (b *Reader) Peek(n int) ([]byte, error) {
|
||||
if n < 0 {
|
||||
return nil, ErrNegativeCount
|
||||
}
|
||||
if n > len(b.buf) {
|
||||
return nil, ErrBufferFull
|
||||
}
|
||||
// 0 <= n <= len(b.buf)
|
||||
for b.w-b.r < n && b.err == nil {
|
||||
|
||||
for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil {
|
||||
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
|
||||
if avail := b.w - b.r; avail < n {
|
||||
// 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.
|
||||
// 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
|
||||
for b.r == b.w {
|
||||
if b.err != nil {
|
||||
@ -228,13 +230,13 @@ func (b *Reader) ReadByte() (c byte, err error) {
|
||||
}
|
||||
b.fill() // buffer is empty
|
||||
}
|
||||
c = b.buf[b.r]
|
||||
c := b.buf[b.r]
|
||||
b.r++
|
||||
b.lastByte = int(c)
|
||||
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 {
|
||||
if b.lastByte < 0 || b.r == 0 && b.w > 0 {
|
||||
return ErrInvalidUnreadByte
|
||||
@ -264,7 +266,7 @@ func (b *Reader) ReadRune() (r rune, size int, err error) {
|
||||
return 0, 0, b.readErr()
|
||||
}
|
||||
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])
|
||||
}
|
||||
b.r += size
|
||||
@ -273,7 +275,7 @@ func (b *Reader) ReadRune() (r rune, size int, err error) {
|
||||
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
|
||||
// regard it is stricter than UnreadByte, which will unread the last byte
|
||||
// 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
|
||||
// delim.
|
||||
// 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,
|
||||
// accumulating full buffers.
|
||||
var frag []byte
|
||||
var full [][]byte
|
||||
|
||||
var err error
|
||||
for {
|
||||
var e error
|
||||
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
|
||||
// delim.
|
||||
// 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)
|
||||
line = string(bytes)
|
||||
return line, err
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
// WriteTo implements io.WriterTo.
|
||||
@ -705,7 +706,7 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
err = b.flush()
|
||||
} else {
|
||||
|
@ -673,8 +673,8 @@ func TestPeek(t *testing.T) {
|
||||
if _, err := buf.Peek(-1); err != ErrNegativeCount {
|
||||
t.Fatalf("want ErrNegativeCount got %v", err)
|
||||
}
|
||||
if _, err := buf.Peek(32); err != ErrBufferFull {
|
||||
t.Fatalf("want ErrBufFull got %v", err)
|
||||
if s, err := buf.Peek(32); string(s) != "abcdefghijklmnop" || err != ErrBufferFull {
|
||||
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 {
|
||||
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")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
r.Seek(0, 0)
|
||||
r.Seek(0, io.SeekStart)
|
||||
srcReader.Reset(onlyReader{r})
|
||||
n, err := srcReader.WriteTo(ioutil.Discard)
|
||||
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.
|
||||
func TestScanLineNoNewline(t *testing.T) {
|
||||
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.
|
||||
func TestErrAtEOF(t *testing.T) {
|
||||
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) {
|
||||
advance, token, err = ScanWords(data, atEOF)
|
||||
if len(token) > 1 {
|
||||
|
@ -17,8 +17,8 @@ import (
|
||||
type Buffer struct {
|
||||
buf []byte // contents are the bytes buf[off : 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
|
||||
bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation.
|
||||
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each call to WriteRune
|
||||
bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
|
||||
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:] }
|
||||
|
||||
// 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 {
|
||||
if b == nil {
|
||||
// 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
|
||||
// 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
|
||||
// underlying buffer.
|
||||
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
|
||||
// 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);
|
||||
// otherwise it is nil.
|
||||
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.
|
||||
// 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
|
||||
if b.off >= len(b.buf) {
|
||||
// Buffer is empty, reset to recover space.
|
||||
b.Truncate(0)
|
||||
return 0, io.EOF
|
||||
}
|
||||
c = b.buf[b.off]
|
||||
c := b.buf[b.off]
|
||||
b.off++
|
||||
b.lastRead = opRead
|
||||
return c, nil
|
||||
@ -347,7 +347,7 @@ func (b *Buffer) UnreadRune() error {
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (b *Buffer) UnreadByte() error {
|
||||
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
|
||||
// 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,
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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.
|
||||
func Index(s, sep []byte) int {
|
||||
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.
|
||||
// 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.
|
||||
func IndexAny(s []byte, chars string) int {
|
||||
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
|
||||
// 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
|
||||
// points. It returns the byte index of the last occurrence in s of any of
|
||||
// the Unicode code points in chars. It returns -1 if chars is empty or if
|
||||
// there is no code point in common.
|
||||
func LastIndexAny(s []byte, chars string) int {
|
||||
if len(chars) > 0 {
|
||||
@ -276,7 +286,7 @@ func Fields(s []byte) [][]byte {
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
// 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.
|
||||
@ -352,12 +362,12 @@ func HasSuffix(s, suffix []byte) bool {
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
func Map(mapping func(r rune) rune, s []byte) []byte {
|
||||
// In the worst case, the slice can grow when mapped, making
|
||||
// things unpleasant. But it's so rare we barge in assuming it's
|
||||
// fine. It could also shrink but that falls out naturally.
|
||||
// things unpleasant. But it's so rare we barge in assuming it's
|
||||
// fine. It could also shrink but that falls out naturally.
|
||||
maxbytes := len(s) // length of b
|
||||
nbytes := 0 // number of bytes encoded in b
|
||||
b := make([]byte, maxbytes)
|
||||
@ -697,7 +707,7 @@ func EqualFold(s, t []byte) bool {
|
||||
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.
|
||||
r := unicode.SimpleFold(sr)
|
||||
for r != sr && r < tr {
|
||||
@ -709,6 +719,6 @@ func EqualFold(s, t []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// One string is empty. Are both?
|
||||
// One string is empty. Are both?
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -6,6 +6,7 @@ package bytes_test
|
||||
|
||||
import (
|
||||
. "bytes"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
@ -47,32 +48,6 @@ type BinOpTest struct {
|
||||
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) {
|
||||
for _, tt := range compareTests {
|
||||
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.
|
||||
func TestNotEqual(t *testing.T) {
|
||||
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) {
|
||||
for _, tt := range indexRuneTests {
|
||||
a := []byte(tt.a)
|
||||
@ -348,165 +358,152 @@ func TestIndexRune(t *testing.T) {
|
||||
|
||||
var bmbuf []byte
|
||||
|
||||
func BenchmarkIndexByte32(b *testing.B) { bmIndexByte(b, IndexByte, 32) }
|
||||
func BenchmarkIndexByte4K(b *testing.B) { bmIndexByte(b, IndexByte, 4<<10) }
|
||||
func BenchmarkIndexByte4M(b *testing.B) { bmIndexByte(b, IndexByte, 4<<20) }
|
||||
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)
|
||||
func valName(x int) string {
|
||||
if s := x >> 20; s<<20 == x {
|
||||
return fmt.Sprintf("%dM", s)
|
||||
}
|
||||
b.SetBytes(int64(n))
|
||||
buf := bmbuf[0:n]
|
||||
buf[n-1] = 'x'
|
||||
for i := 0; i < b.N; i++ {
|
||||
j := index(buf, 'x')
|
||||
if j != n-1 {
|
||||
b.Fatal("bad index", j)
|
||||
}
|
||||
if s := x >> 10; s<<10 == x {
|
||||
return fmt.Sprintf("%dK", s)
|
||||
}
|
||||
buf[n-1] = '\x00'
|
||||
return fmt.Sprint(x)
|
||||
}
|
||||
|
||||
func BenchmarkEqual0(b *testing.B) {
|
||||
var buf [4]byte
|
||||
buf1 := buf[0:0]
|
||||
buf2 := buf[1:1]
|
||||
for i := 0; i < b.N; i++ {
|
||||
eq := Equal(buf1, buf2)
|
||||
if !eq {
|
||||
b.Fatal("bad equal")
|
||||
}
|
||||
func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
|
||||
for _, n := range sizes {
|
||||
b.Run(valName(n), func(b *testing.B) {
|
||||
if len(bmbuf) < n {
|
||||
bmbuf = make([]byte, n)
|
||||
}
|
||||
b.SetBytes(int64(n))
|
||||
f(b, n)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEqual1(b *testing.B) { bmEqual(b, Equal, 1) }
|
||||
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) }
|
||||
var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||
|
||||
func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {
|
||||
if len(bmbuf) < 2*n {
|
||||
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 BenchmarkIndexByte(b *testing.B) {
|
||||
benchBytes(b, indexSizes, bmIndexByte(IndexByte))
|
||||
}
|
||||
|
||||
func BenchmarkIndex32(b *testing.B) { bmIndex(b, Index, 32) }
|
||||
func BenchmarkIndex4K(b *testing.B) { bmIndex(b, Index, 4<<10) }
|
||||
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 BenchmarkIndexBytePortable(b *testing.B) {
|
||||
benchBytes(b, indexSizes, bmIndexByte(IndexBytePortable))
|
||||
}
|
||||
|
||||
func BenchmarkIndexEasy32(b *testing.B) { bmIndexEasy(b, Index, 32) }
|
||||
func BenchmarkIndexEasy4K(b *testing.B) { bmIndexEasy(b, Index, 4<<10) }
|
||||
func BenchmarkIndexEasy4M(b *testing.B) { bmIndexEasy(b, Index, 4<<20) }
|
||||
func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) }
|
||||
|
||||
func bmIndexEasy(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'
|
||||
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)
|
||||
func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) {
|
||||
return func(b *testing.B, n int) {
|
||||
buf := bmbuf[0:n]
|
||||
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'
|
||||
}
|
||||
buf[n-1] = '\x00'
|
||||
buf[n-7] = '\x00'
|
||||
}
|
||||
|
||||
func BenchmarkCount32(b *testing.B) { bmCount(b, Count, 32) }
|
||||
func BenchmarkCount4K(b *testing.B) { bmCount(b, Count, 4<<10) }
|
||||
func BenchmarkCount4M(b *testing.B) { bmCount(b, Count, 4<<20) }
|
||||
func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) }
|
||||
|
||||
func bmCount(b *testing.B, count 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 := count(buf, buf[n-7:])
|
||||
if j != 1 {
|
||||
b.Fatal("bad count", j)
|
||||
func BenchmarkEqual(b *testing.B) {
|
||||
b.Run("0", func(b *testing.B) {
|
||||
var buf [4]byte
|
||||
buf1 := buf[0:0]
|
||||
buf2 := buf[1:1]
|
||||
for i := 0; i < b.N; i++ {
|
||||
eq := Equal(buf1, buf2)
|
||||
if !eq {
|
||||
b.Fatal("bad equal")
|
||||
}
|
||||
}
|
||||
}
|
||||
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 BenchmarkCountEasy4K(b *testing.B) { bmCountEasy(b, Count, 4<<10) }
|
||||
func BenchmarkCountEasy4M(b *testing.B) { bmCountEasy(b, Count, 4<<20) }
|
||||
func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) }
|
||||
func BenchmarkEqualPort(b *testing.B) {
|
||||
sizes := []int{1, 6, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||
benchBytes(b, sizes, bmEqual(EqualPortable))
|
||||
}
|
||||
|
||||
func bmCountEasy(b *testing.B, count 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'
|
||||
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)
|
||||
func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) {
|
||||
return func(b *testing.B, n int) {
|
||||
if len(bmbuf) < 2*n {
|
||||
bmbuf = make([]byte, 2*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'
|
||||
}
|
||||
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 {
|
||||
@ -760,7 +757,7 @@ func TestMap(t *testing.T) {
|
||||
// Run a couple of awful growth/shrinkage tests
|
||||
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 }
|
||||
m := Map(maxRune, []byte(a))
|
||||
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 {
|
||||
x := make([]byte, 1<<20)
|
||||
// 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) {
|
||||
var x = make([]byte, n)
|
||||
var y = make([]byte, n)
|
||||
func BenchmarkBytesCompare(b *testing.B) {
|
||||
for n := 1; n <= 2048; n <<= 1 {
|
||||
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++ {
|
||||
x[i] = 'a'
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
x[i] = 'a'
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
y[i] = 'a'
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
y[i] = 'a'
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Compare(x, y)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
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)
|
||||
b := make([]byte, n+1)
|
||||
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++ {
|
||||
a[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
|
||||
// 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
|
||||
// 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
|
||||
// operating systems.
|
||||
|
||||
|
@ -36,9 +36,6 @@ func (r *Reader) Len() int {
|
||||
func (r *Reader) Size() int64 { return int64(len(r.s)) }
|
||||
|
||||
func (r *Reader) Read(b []byte) (n int, err error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if r.i >= int64(len(r.s)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
@ -63,14 +60,14 @@ func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Reader) ReadByte() (b byte, err error) {
|
||||
func (r *Reader) ReadByte() (byte, error) {
|
||||
r.prevRune = -1
|
||||
if r.i >= int64(len(r.s)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
b = r.s[r.i]
|
||||
b := r.s[r.i]
|
||||
r.i++
|
||||
return
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (r *Reader) UnreadByte() error {
|
||||
@ -111,11 +108,11 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||
r.prevRune = -1
|
||||
var abs int64
|
||||
switch whence {
|
||||
case 0:
|
||||
case io.SeekStart:
|
||||
abs = offset
|
||||
case 1:
|
||||
abs = int64(r.i) + offset
|
||||
case 2:
|
||||
case io.SeekCurrent:
|
||||
abs = r.i + offset
|
||||
case io.SeekEnd:
|
||||
abs = int64(len(r.s)) + offset
|
||||
default:
|
||||
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
|
||||
}
|
||||
|
||||
// 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.
|
||||
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
@ -22,17 +21,18 @@ func TestReader(t *testing.T) {
|
||||
n int
|
||||
want string
|
||||
wantpos int64
|
||||
readerr error
|
||||
seekerr string
|
||||
}{
|
||||
{seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"},
|
||||
{seek: os.SEEK_SET, off: 1, n: 1, want: "1"},
|
||||
{seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"},
|
||||
{seek: os.SEEK_SET, off: -1, seekerr: "bytes.Reader.Seek: negative position"},
|
||||
{seek: os.SEEK_SET, off: 1 << 33, wantpos: 1 << 33},
|
||||
{seek: os.SEEK_CUR, off: 1, wantpos: 1<<33 + 1},
|
||||
{seek: os.SEEK_SET, n: 5, want: "01234"},
|
||||
{seek: os.SEEK_CUR, n: 5, want: "56789"},
|
||||
{seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"},
|
||||
{seek: io.SeekStart, off: 0, n: 20, want: "0123456789"},
|
||||
{seek: io.SeekStart, off: 1, n: 1, want: "1"},
|
||||
{seek: io.SeekCurrent, off: 1, wantpos: 3, n: 2, want: "34"},
|
||||
{seek: io.SeekStart, off: -1, seekerr: "bytes.Reader.Seek: negative position"},
|
||||
{seek: io.SeekStart, off: 1 << 33, wantpos: 1 << 33, readerr: io.EOF},
|
||||
{seek: io.SeekCurrent, off: 1, wantpos: 1<<33 + 1, readerr: io.EOF},
|
||||
{seek: io.SeekStart, n: 5, want: "01234"},
|
||||
{seek: io.SeekCurrent, n: 5, want: "56789"},
|
||||
{seek: io.SeekEnd, off: -1, n: 1, wantpos: 9, want: "9"},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
@ -50,8 +50,8 @@ func TestReader(t *testing.T) {
|
||||
}
|
||||
buf := make([]byte, tt.n)
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
t.Errorf("%d. read = %v", i, err)
|
||||
if err != tt.readerr {
|
||||
t.Errorf("%d. read = %v; want %v", i, err, tt.readerr)
|
||||
continue
|
||||
}
|
||||
got := string(buf[:n])
|
||||
@ -63,7 +63,7 @@ func TestReader(t *testing.T) {
|
||||
|
||||
func TestReadAfterBigSeek(t *testing.T) {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
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}) }},
|
||||
{"ReadByte", func(r *Reader) { r.ReadByte() }},
|
||||
{"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{}) }},
|
||||
}
|
||||
|
||||
@ -256,3 +256,23 @@ func TestReaderLenSize(t *testing.T) {
|
||||
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
|
||||
// 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
|
||||
// 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,
|
||||
// a list of exported functions, and the actual AST, to be rewritten and
|
||||
// printed.
|
||||
@ -73,7 +73,7 @@ func (f *File) ReadGo(name string) {
|
||||
}
|
||||
for _, spec := range d.Specs {
|
||||
s, ok := spec.(*ast.ImportSpec)
|
||||
if !ok || string(s.Path.Value) != `"C"` {
|
||||
if !ok || s.Path.Value != `"C"` {
|
||||
continue
|
||||
}
|
||||
sawC = true
|
||||
@ -106,7 +106,7 @@ func (f *File) ReadGo(name string) {
|
||||
ws := 0
|
||||
for _, spec := range d.Specs {
|
||||
s, ok := spec.(*ast.ImportSpec)
|
||||
if !ok || string(s.Path.Value) != `"C"` {
|
||||
if !ok || s.Path.Value != `"C"` {
|
||||
d.Specs[ws] = spec
|
||||
ws++
|
||||
}
|
||||
@ -147,7 +147,7 @@ func commentText(g *ast.CommentGroup) string {
|
||||
}
|
||||
var pieces []string
|
||||
for _, com := range g.List {
|
||||
c := string(com.Text)
|
||||
c := com.Text
|
||||
// Remove comment markers.
|
||||
// The parser has given us exactly the comment text.
|
||||
switch c[1] {
|
||||
@ -172,7 +172,7 @@ func (f *File) saveExprs(x interface{}, context string) {
|
||||
f.saveRef(x, context)
|
||||
}
|
||||
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.
|
||||
func (f *File) saveCall(call *ast.CallExpr) {
|
||||
func (f *File) saveCall(call *ast.CallExpr, context string) {
|
||||
sel, ok := call.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return
|
||||
@ -228,7 +228,8 @@ func (f *File) saveCall(call *ast.CallExpr) {
|
||||
if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
|
||||
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.
|
||||
@ -242,11 +243,11 @@ func (f *File) saveExport(x interface{}, context string) {
|
||||
return
|
||||
}
|
||||
for _, c := range n.Doc.List {
|
||||
if !strings.HasPrefix(string(c.Text), "//export ") {
|
||||
if !strings.HasPrefix(c.Text, "//export ") {
|
||||
continue
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(string(c.Text[9:]))
|
||||
name := strings.TrimSpace(c.Text[9:])
|
||||
if 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:
|
||||
f.walk(n.Call, "expr", visit)
|
||||
case *ast.DeferStmt:
|
||||
f.walk(n.Call, "expr", visit)
|
||||
f.walk(n.Call, "defer", visit)
|
||||
case *ast.ReturnStmt:
|
||||
f.walk(n.Results, "expr", visit)
|
||||
case *ast.BranchStmt:
|
||||
@ -447,7 +448,11 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
|
||||
case *ast.ImportSpec:
|
||||
case *ast.ValueSpec:
|
||||
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:
|
||||
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
|
||||
// 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:
|
||||
https://golang.org/doc/articles/c_go_cgo.html.
|
||||
|
||||
CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo
|
||||
directives within these comments to tweak the behavior of the C or C++
|
||||
compiler. Values defined in multiple directives are concatenated
|
||||
CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS and LDFLAGS may be defined with pseudo
|
||||
#cgo directives within these comments to tweak the behavior of the C, C++
|
||||
or Fortran compiler. Values defined in multiple directives are concatenated
|
||||
together. The directive can include a list of build constraints limiting its
|
||||
effect to systems satisfying one of the constraints
|
||||
(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>
|
||||
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
|
||||
these directives. Package-specific flags should be set using the
|
||||
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
|
||||
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
|
||||
package. All the LDFLAGS directives in any package in the program are
|
||||
concatenated and used at link time. All the pkg-config directives are
|
||||
concatenated and sent to pkg-config simultaneously to add to each appropriate
|
||||
set of command-line flags.
|
||||
package. All the CPPFLAGS and FFLAGS directives in a package are concatenated
|
||||
and used to compile Fortran files in that package. All the LDFLAGS directives
|
||||
in any package in the program are concatenated and used at link time. All the
|
||||
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}
|
||||
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
|
||||
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 .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,
|
||||
the C and C++ files will be recompiled. The default C and C++
|
||||
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 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
|
||||
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.
|
||||
@ -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
|
||||
function returns void). For example:
|
||||
|
||||
n, err := C.sqrt(-1)
|
||||
n, err = C.sqrt(-1)
|
||||
_, err := C.voidFunc()
|
||||
var n, err = C.sqrt(1)
|
||||
|
||||
Calling C function pointers is currently not supported, however you can
|
||||
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).
|
||||
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
|
||||
func C.GoString(*C.char) string
|
||||
|
||||
@ -501,7 +511,6 @@ file compiled by gcc, the file x.cgo2.c:
|
||||
void
|
||||
_cgo_be59f0f25121_Cfunc_puts(void *v)
|
||||
{
|
||||
_cgo_wait_runtime_init_done();
|
||||
struct {
|
||||
char* p0;
|
||||
int r;
|
||||
@ -510,8 +519,7 @@ file compiled by gcc, the file x.cgo2.c:
|
||||
a->r = puts((void*)a->p0);
|
||||
}
|
||||
|
||||
It waits for Go runtime to be initialized (required for shared libraries),
|
||||
extracts the arguments from the pointer to _Cfunc_puts's argument
|
||||
It extracts the arguments from the pointer to _Cfunc_puts's argument
|
||||
frame, invokes the system C function (in this case, puts), stores the
|
||||
result in the frame, and returns.
|
||||
|
||||
@ -529,8 +537,8 @@ linkage to the desired libraries. The main function is provided by
|
||||
_cgo_main.c:
|
||||
|
||||
int main() { return 0; }
|
||||
void crosscall2(void(*fn)(void*, int), void *a, int c) { }
|
||||
void _cgo_wait_runtime_init_done() { }
|
||||
void crosscall2(void(*fn)(void*, int, uintptr_t), void *a, int c, uintptr_t ctxt) { }
|
||||
uintptr_t _cgo_wait_runtime_init_done() { }
|
||||
void _cgo_allocate(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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -83,7 +83,7 @@ func (f *File) DiscardCgoDirectives() {
|
||||
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.
|
||||
func (p *Package) addToFlag(flag string, args []string) {
|
||||
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
|
||||
// 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
|
||||
// last element. The backslash is used for escaping.
|
||||
// last element. The backslash is used for escaping.
|
||||
//
|
||||
// For example, the following string:
|
||||
//
|
||||
@ -236,7 +236,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||
if isConst {
|
||||
n.Kind = "const"
|
||||
// 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
|
||||
// are in hex and half are in whatever the #define used.
|
||||
i, err := strconv.ParseInt(n.Define, 0, 64)
|
||||
@ -385,7 +385,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||
if nerrors > 0 {
|
||||
// Check if compiling the preamble by itself causes any errors,
|
||||
// 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))
|
||||
if len(preambleErrors) > 0 {
|
||||
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.
|
||||
func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||
// 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
|
||||
// preamble and hope the symbols we care about will be there.
|
||||
// Instead, emit
|
||||
@ -421,7 +421,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||
}
|
||||
|
||||
// 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.
|
||||
// We can read them out of the object file.
|
||||
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")
|
||||
}
|
||||
}
|
||||
// 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,
|
||||
// LLVM-based gcc will place the it in the __DATA.__common
|
||||
// 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) {
|
||||
for _, call := range f.Calls {
|
||||
// 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" {
|
||||
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).
|
||||
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 {
|
||||
if len(call.Args) <= i {
|
||||
// Avoid a crash; this will be caught when the
|
||||
// generated file is compiled.
|
||||
return
|
||||
if p.needsPointerCheck(f, param.Go, call.Call.Args[i]) {
|
||||
any = true
|
||||
break
|
||||
}
|
||||
}
|
||||
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
|
||||
// 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) {
|
||||
if !p.needsPointerCheck(f, param.Go, origArg) {
|
||||
continue
|
||||
}
|
||||
|
||||
c := &ast.CallExpr{
|
||||
Fun: ast.NewIdent("_cgoCheckPointer"),
|
||||
Args: []ast.Expr{
|
||||
call.Args[i],
|
||||
darg,
|
||||
},
|
||||
}
|
||||
|
||||
// Add optional additional arguments for an address
|
||||
// expression.
|
||||
c.Args = p.checkAddrArgs(f, c.Args, call.Args[i])
|
||||
c.Args = p.checkAddrArgs(f, c.Args, origArg)
|
||||
|
||||
// _cgoCheckPointer returns interface{}.
|
||||
// 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.
|
||||
|
||||
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)
|
||||
arg = c
|
||||
} else {
|
||||
// In order for the type assertion to succeed,
|
||||
// we need it to match the actual type of the
|
||||
// argument. The only type we have is the
|
||||
// type of the function parameter. We know
|
||||
// argument. The only type we have is the
|
||||
// type of the function parameter. We know
|
||||
// that the argument type must be assignable
|
||||
// to the function parameter type, or the code
|
||||
// would not compile, but there is nothing
|
||||
// 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
|
||||
// succeed.
|
||||
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.
|
||||
// This is true if t is a pointer and if the value to which it points
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
// If top is false it returns whether t is or contains a pointer.
|
||||
// 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 {
|
||||
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.
|
||||
return true
|
||||
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 {
|
||||
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.
|
||||
return true
|
||||
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
|
||||
// _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
|
||||
// something other than a slice index, which means that it's only
|
||||
// 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
|
||||
// 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
|
||||
// effects.
|
||||
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)
|
||||
if !ok {
|
||||
// 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.
|
||||
// TODO: what if true is shadowed?
|
||||
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 {
|
||||
switch t := t.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
if t.Sel.Name != "Pointer" {
|
||||
return false
|
||||
}
|
||||
id, ok := t.X.(*ast.Ident)
|
||||
if !ok {
|
||||
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:
|
||||
// TODO: This ignores shadowing.
|
||||
switch t.Name {
|
||||
@ -850,26 +935,37 @@ func (p *Package) isType(t ast.Expr) bool {
|
||||
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
|
||||
// _cgoCheckPointer that returns that type. This avoids using a type
|
||||
// assertion to unsafe.Pointer in our copy of user code. We return
|
||||
// _cgoCheckPointer that returns that type. This avoids using a type
|
||||
// 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 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) {
|
||||
return ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
conf.Fprint(&buf, fset, t)
|
||||
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 {
|
||||
return p.unsafeCheckPointerNameIndex(i)
|
||||
return p.unsafeCheckPointerNameIndex(i, deferred)
|
||||
}
|
||||
}
|
||||
p.CgoChecks = append(p.CgoChecks, s)
|
||||
return p.unsafeCheckPointerNameIndex(len(p.CgoChecks) - 1)
|
||||
*checks = append(*checks, s)
|
||||
return p.unsafeCheckPointerNameIndex(len(*checks)-1, deferred)
|
||||
}
|
||||
|
||||
// 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
|
||||
// _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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
func (p *Package) rewriteRef(f *File) {
|
||||
// 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,
|
||||
// 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.
|
||||
for _, r := range f.Ref {
|
||||
if r.Name.Kind == "const" && r.Name.Const == "" {
|
||||
@ -984,7 +1083,7 @@ func (p *Package) rewriteRef(f *File) {
|
||||
f.Name[fpName] = 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
|
||||
// issue 7757.
|
||||
expr = &ast.CallExpr{
|
||||
@ -1006,7 +1105,7 @@ func (p *Package) rewriteRef(f *File) {
|
||||
if r.Name.Kind == "var" {
|
||||
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
|
||||
} 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":
|
||||
@ -1086,6 +1185,8 @@ func (p *Package) gccMachine() []string {
|
||||
return []string{"-m31"}
|
||||
case "s390x":
|
||||
return []string{"-m64"}
|
||||
case "mips64", "mips64le":
|
||||
return []string{"-mabi=64"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1152,7 +1253,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
|
||||
for i := range f.Symtab.Syms {
|
||||
s := &f.Symtab.Syms[i]
|
||||
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) {
|
||||
sect := f.Sections[i]
|
||||
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 {
|
||||
s := &symtab[i]
|
||||
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) {
|
||||
sect := f.Sections[i]
|
||||
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
|
||||
// the errors that gcc prints. That is, this function expects
|
||||
// the errors that gcc prints. That is, this function expects
|
||||
// gcc to fail.
|
||||
func (p *Package) gccErrors(stdin []byte) string {
|
||||
// TODO(rsc): require failure
|
||||
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 {
|
||||
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
|
||||
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
|
||||
os.Stderr.Write(stdin)
|
||||
fmt.Fprint(os.Stderr, "EOF\n")
|
||||
}
|
||||
stdout, stderr, _ := run(stdin, args)
|
||||
stdout, stderr, _ := run(stdin, nargs)
|
||||
if *debugGcc {
|
||||
os.Stderr.Write(stdout)
|
||||
os.Stderr.Write(stderr)
|
||||
@ -1279,8 +1388,7 @@ func runGcc(stdin []byte, args []string) (string, string) {
|
||||
// with equivalent memory layout.
|
||||
type typeConv struct {
|
||||
// Cache of already-translated or in-progress types.
|
||||
m map[dwarf.Type]*Type
|
||||
typedef map[string]ast.Expr
|
||||
m map[dwarf.Type]*Type
|
||||
|
||||
// Map from types to incomplete pointers to those types.
|
||||
ptrs map[dwarf.Type][]*Type
|
||||
@ -1372,7 +1480,7 @@ var dwarfToName = map[string]string{
|
||||
|
||||
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
|
||||
// values are taken into account.
|
||||
func (tr *TypeRepr) String() string {
|
||||
@ -1812,7 +1920,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
|
||||
}
|
||||
case *dwarf.TypedefType:
|
||||
// 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
|
||||
// laxness of C by making the argument *X instead of T.
|
||||
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
|
||||
// has __attribute__((unavailable)) on it. See issue 2888.
|
||||
// has __attribute__((unavailable)) on it. See issue 2888.
|
||||
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 {
|
||||
// gcc's DWARF generator outputs a single DotDotDotType parameter for
|
||||
// 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
|
||||
// legal).
|
||||
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)
|
||||
|
||||
// Rename struct fields that happen to be named Go keywords into
|
||||
// _{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
|
||||
// _{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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// issue 6677.
|
||||
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
|
||||
// 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,
|
||||
// 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 {
|
||||
n := len(sizes)
|
||||
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
|
||||
// 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
|
||||
// people are used to seeing in C. For generated Go code, such as
|
||||
// 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 _, n := range f.Names {
|
||||
// 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.
|
||||
// If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
|
||||
// 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
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -42,7 +42,10 @@ type Package struct {
|
||||
GoFiles []string // list of Go files
|
||||
GccFiles []string // list of gcc output files
|
||||
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.
|
||||
@ -52,7 +55,7 @@ type File struct {
|
||||
Package string // Package name
|
||||
Preamble string // C preamble (doc comment on import "C")
|
||||
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
|
||||
Name map[string]*Name // map from Go name to Name
|
||||
}
|
||||
@ -66,6 +69,12 @@ func nameKeys(m map[string]*Name) []string {
|
||||
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.
|
||||
type Ref struct {
|
||||
Name *Name
|
||||
@ -208,9 +217,9 @@ func main() {
|
||||
|
||||
if *dynobj != "" {
|
||||
// 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
|
||||
// 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
|
||||
// instead of needing to make the linkers duplicate all the
|
||||
// specialized knowledge gcc has about where to look for imported
|
||||
@ -245,6 +254,12 @@ func main() {
|
||||
|
||||
goFiles := args[i:]
|
||||
|
||||
for _, arg := range args[:i] {
|
||||
if arg == "-fsanitize=thread" {
|
||||
tsanProlog = yesTsanProlog
|
||||
}
|
||||
}
|
||||
|
||||
p := newPackage(args[:i])
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
fmt.Fprintf(fm, "int main() { return 0; }\n")
|
||||
if *importRuntimeCgo {
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
|
||||
fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done() { }\n")
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { }\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")
|
||||
} else {
|
||||
// If we're not importing runtime/cgo, we *are* runtime/cgo,
|
||||
// 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 _cgo_wait_runtime_init_done();\n")
|
||||
// which provides these functions. We just need a prototype.
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt);\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_panic(void *a, int c) { }\n")
|
||||
@ -110,7 +112,13 @@ func (p *Package) writeDefs() {
|
||||
}
|
||||
|
||||
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, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
|
||||
fmt.Fprintf(fgo2, "}\n")
|
||||
@ -173,10 +181,11 @@ func (p *Package) writeDefs() {
|
||||
}
|
||||
fmt.Fprintf(fgo2, "\n")
|
||||
|
||||
callsMalloc := false
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
if n.FuncType != nil {
|
||||
p.writeDefsFunc(fgo2, n)
|
||||
p.writeDefsFunc(fgo2, n, &callsMalloc)
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,6 +196,12 @@ func (p *Package) writeDefs() {
|
||||
} else {
|
||||
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 {
|
||||
fatalf("%s", err)
|
||||
}
|
||||
@ -350,7 +365,7 @@ func (p *Package) structType(n *Name) (string, int64) {
|
||||
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
|
||||
gtype := n.FuncType.Go
|
||||
void := gtype.Results == nil || len(gtype.Results.List) == 0
|
||||
@ -439,6 +454,9 @@ func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
|
||||
|
||||
if inProlog {
|
||||
fmt.Fprint(fgo2, builtinDefs[name])
|
||||
if strings.Contains(builtinDefs[name], "_cgo_cmalloc") {
|
||||
*callsMalloc = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -458,6 +476,7 @@ func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
|
||||
}
|
||||
|
||||
fmt.Fprint(fgo2, "\n")
|
||||
fmt.Fprint(fgo2, "//go:cgo_unsafe_args\n")
|
||||
conf.Fprint(fgo2, fset, d)
|
||||
fmt.Fprint(fgo2, " {\n")
|
||||
|
||||
@ -507,6 +526,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
|
||||
// Gcc output starts with the preamble.
|
||||
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
||||
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||
|
||||
for _, key := range nameKeys(f.Name) {
|
||||
n := f.Name[key]
|
||||
@ -531,6 +551,7 @@ func fixGo(name string) string {
|
||||
|
||||
var isBuiltin = map[string]bool{
|
||||
"_Cfunc_CString": true,
|
||||
"_Cfunc_CBytes": true,
|
||||
"_Cfunc_GoString": true,
|
||||
"_Cfunc_GoStringN": true,
|
||||
"_Cfunc_GoBytes": true,
|
||||
@ -555,6 +576,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||
|
||||
// Gcc wrapper unpacks the C argument struct
|
||||
// and calls the actual C function.
|
||||
fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
|
||||
if n.AddError {
|
||||
fmt.Fprintf(fgcc, "int\n")
|
||||
} 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, "{\n")
|
||||
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.
|
||||
// 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.
|
||||
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")
|
||||
if t := n.FuncType.Result; t != nil {
|
||||
fmt.Fprintf(fgcc, "__typeof__(a->r) r = ")
|
||||
if c := t.C.String(); c[len(c)-1] == '*' {
|
||||
if tr != nil {
|
||||
fmt.Fprintf(fgcc, "r = ")
|
||||
if c := tr.C.String(); c[len(c)-1] == '*' {
|
||||
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.
|
||||
// However, our version of the type omits the magic
|
||||
// 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
|
||||
// other warnings.)
|
||||
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, ");\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 {
|
||||
// The cgo call may have caused a stack copy (via a callback).
|
||||
// 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")
|
||||
}
|
||||
if n.AddError {
|
||||
fmt.Fprintf(fgcc, "\treturn errno;\n")
|
||||
fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n")
|
||||
}
|
||||
fmt.Fprintf(fgcc, "}\n")
|
||||
fmt.Fprintf(fgcc, "\n")
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// wrapper to support static functions in the prologue--without a
|
||||
// wrapper, we can't refer to the function, since the reference is in
|
||||
// a different file.
|
||||
func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
||||
fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
|
||||
if t := n.FuncType.Result; t != nil {
|
||||
fmt.Fprintf(fgcc, "%s\n", t.C.String())
|
||||
} else {
|
||||
@ -636,9 +671,13 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
||||
}
|
||||
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")
|
||||
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.
|
||||
if c := t.C.String(); c[len(c)-1] == '*' {
|
||||
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, ");\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")
|
||||
}
|
||||
@ -679,16 +728,20 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||
p.writeExportHeader(fgcch)
|
||||
|
||||
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, "extern void crosscall2(void (*fn)(void *, int), void *, int);\n")
|
||||
fmt.Fprintf(fgcc, "extern void _cgo_wait_runtime_init_done();\n\n")
|
||||
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__);\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 {
|
||||
fn := exp.Func
|
||||
|
||||
// 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
|
||||
// for explicitly.
|
||||
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(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")
|
||||
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())
|
||||
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
|
||||
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) {
|
||||
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 len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
|
||||
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: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, "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)
|
||||
// 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(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, "%s\n", gccgoExportFileProlog)
|
||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||
|
||||
for _, exp := range p.ExpFunc {
|
||||
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.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)
|
||||
if resultCount > 0 {
|
||||
fmt.Fprintf(fgcc, "\t%s r;\n", cRet)
|
||||
}
|
||||
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_cgo_tsan_release();\n")
|
||||
fmt.Fprint(fgcc, "\t")
|
||||
if resultCount > 0 {
|
||||
fmt.Fprint(fgcc, "return ")
|
||||
fmt.Fprint(fgcc, "r = ")
|
||||
}
|
||||
fmt.Fprintf(fgcc, "%s(", goName)
|
||||
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.Fprint(fgcc, ");\n")
|
||||
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
|
||||
if resultCount > 0 {
|
||||
fmt.Fprint(fgcc, "\treturn r;\n")
|
||||
}
|
||||
fmt.Fprint(fgcc, "}\n")
|
||||
|
||||
// Dummy declaration for _cgo_main.c
|
||||
@ -1257,6 +1323,36 @@ extern char* _cgo_topofstack(void);
|
||||
#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 = `
|
||||
#include <stddef.h> /* for ptrdiff_t and size_t below */
|
||||
|
||||
@ -1269,6 +1365,7 @@ _GoString_ GoString(char *p);
|
||||
_GoString_ GoStringN(char *p, int l);
|
||||
_GoBytes_ GoBytes(void *p, int n);
|
||||
char *CString(_GoString_);
|
||||
void *CBytes(_GoBytes_);
|
||||
void *_CMalloc(size_t);
|
||||
`
|
||||
|
||||
@ -1276,11 +1373,8 @@ const goProlog = `
|
||||
//go:linkname _cgo_runtime_cgocall runtime.cgocall
|
||||
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
|
||||
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
|
||||
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr)
|
||||
|
||||
//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
|
||||
func _cgoCheckPointer(interface{}, ...interface{}) interface{}
|
||||
@ -1324,7 +1418,7 @@ func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
|
||||
|
||||
const cStringDef = `
|
||||
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)
|
||||
copy(pp[:], s)
|
||||
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 = `
|
||||
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,
|
||||
"GoBytes": goBytesDef,
|
||||
"CString": cStringDef,
|
||||
"CBytes": cBytesDef,
|
||||
"_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 {
|
||||
return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
|
||||
"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
|
||||
@ -1380,6 +1528,12 @@ const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
|
||||
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) {
|
||||
intgo len = (p != NULL) ? strlen(p) : 0;
|
||||
return __go_byte_array_to_string(p, len);
|
||||
@ -1505,5 +1659,5 @@ static void GoInit(void) {
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
@ -16,6 +17,43 @@ import (
|
||||
// It returns the output to standard output and standard error.
|
||||
// ok indicates whether the command exited successfully.
|
||||
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.Stdin = bytes.NewReader(stdin)
|
||||
var bout, berr bytes.Buffer
|
||||
@ -30,6 +68,15 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
||||
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 {
|
||||
return fset.Position(pos).String()
|
||||
}
|
||||
@ -37,7 +84,7 @@ func lineno(pos token.Pos) string {
|
||||
// Die with an error message.
|
||||
func fatalf(msg string, args ...interface{}) {
|
||||
// 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 {
|
||||
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
|
||||
// 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
|
||||
// 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,
|
||||
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,
|
||||
forces build to write the resulting executable or object
|
||||
to the named output file, instead of the default behavior described
|
||||
@ -65,8 +67,7 @@ and test commands:
|
||||
-p n
|
||||
the number of programs, such as build commands or
|
||||
test binaries, that can be run in parallel.
|
||||
The default is the number of CPUs available, except
|
||||
on darwin/arm which defaults to 1.
|
||||
The default is the number of CPUs available.
|
||||
-race
|
||||
enable data race detection.
|
||||
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
|
||||
@ -145,17 +146,6 @@ func init() {
|
||||
|
||||
addBuildFlags(cmdBuild)
|
||||
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.
|
||||
@ -352,6 +342,11 @@ func buildModeInit() {
|
||||
}
|
||||
return p
|
||||
}
|
||||
switch platform {
|
||||
case "darwin/arm", "darwin/arm64":
|
||||
codegenArg = "-shared"
|
||||
default:
|
||||
}
|
||||
exeSuffix = ".a"
|
||||
ldBuildmode = "c-archive"
|
||||
case "c-shared":
|
||||
@ -374,6 +369,9 @@ func buildModeInit() {
|
||||
case "android/arm", "android/arm64", "android/amd64", "android/386":
|
||||
codegenArg = "-shared"
|
||||
ldBuildmode = "pie"
|
||||
case "darwin/arm", "darwin/arm64":
|
||||
codegenArg = "-shared"
|
||||
fallthrough
|
||||
default:
|
||||
ldBuildmode = "exe"
|
||||
}
|
||||
@ -385,7 +383,7 @@ func buildModeInit() {
|
||||
fatalf("-buildmode=pie not supported by gccgo")
|
||||
} else {
|
||||
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":
|
||||
codegenArg = "-shared"
|
||||
default:
|
||||
@ -399,7 +397,7 @@ func buildModeInit() {
|
||||
codegenArg = "-fPIC"
|
||||
} else {
|
||||
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:
|
||||
fatalf("-buildmode=shared not supported on %s\n", platform)
|
||||
}
|
||||
@ -417,7 +415,7 @@ func buildModeInit() {
|
||||
codegenArg = "-fPIC"
|
||||
} else {
|
||||
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")
|
||||
default:
|
||||
fatalf("-linkshared not supported on %s\n", platform)
|
||||
@ -483,6 +481,7 @@ func runBuild(cmd *Command, args []string) {
|
||||
p := pkgs[0]
|
||||
p.target = *buildO
|
||||
p.Stale = true // must build - not up to date
|
||||
p.StaleReason = "build -o flag in use"
|
||||
a := b.action(modeInstall, depMode, p)
|
||||
b.do(a)
|
||||
return
|
||||
@ -525,7 +524,7 @@ func isMetaPackage(name string) bool {
|
||||
}
|
||||
|
||||
// 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:
|
||||
// std --> libstd.so
|
||||
// std cmd --> libstd,cmd.so
|
||||
@ -681,6 +680,7 @@ var (
|
||||
func init() {
|
||||
goarch = buildContext.GOARCH
|
||||
goos = buildContext.GOOS
|
||||
|
||||
if goos == "windows" {
|
||||
exeSuffix = ".exe"
|
||||
}
|
||||
@ -694,6 +694,7 @@ type builder struct {
|
||||
work string // the temporary work directory (ends in filepath.Separator)
|
||||
actionCache map[cacheKey]*action // a cache of already-constructed actions
|
||||
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)
|
||||
|
||||
output sync.Mutex
|
||||
@ -795,7 +796,7 @@ func goFilesPackage(gofiles []string) *Package {
|
||||
|
||||
// Synthesize fake "directory" that only shows the named files,
|
||||
// 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.
|
||||
var dirent []os.FileInfo
|
||||
var dir string
|
||||
@ -853,6 +854,7 @@ func goFilesPackage(gofiles []string) *Package {
|
||||
|
||||
pkg.Target = pkg.target
|
||||
pkg.Stale = true
|
||||
pkg.StaleReason = "files named on command line"
|
||||
|
||||
computeStale(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
|
||||
// generate for cgo as a dependency of the build of any package
|
||||
// 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.
|
||||
if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan && reqStdPkgSrc {
|
||||
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 == "" {
|
||||
// Imported via local path. No permanent target.
|
||||
// Imported via local path. No permanent target.
|
||||
mode = modeBuild
|
||||
}
|
||||
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
|
||||
// a name, use that instead of a.out. The binary is generated
|
||||
// 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.
|
||||
name := "a.out"
|
||||
if p.exeName != "" {
|
||||
@ -1227,14 +1229,22 @@ func allArchiveActions(root *action) []*action {
|
||||
|
||||
// do runs the action graph rooted at root.
|
||||
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.
|
||||
// The original implementation here was a true queue
|
||||
// (using a channel) but it had the effect of getting
|
||||
// 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,
|
||||
// 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
|
||||
// to do what it would have done first in a simple depth-first
|
||||
// dependency order traversal.
|
||||
@ -1331,18 +1341,15 @@ func (b *builder) do(root *action) {
|
||||
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.
|
||||
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
|
||||
// cgo nor SWIG, since the CXX files can only be processed by cgo
|
||||
// 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",
|
||||
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() {
|
||||
if err != nil && err != errPrintedOutput {
|
||||
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.
|
||||
// In that case gcc only gets the gcc_* files.
|
||||
var gccfiles []string
|
||||
gccfiles = append(gccfiles, cfiles...)
|
||||
cfiles = nil
|
||||
if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
|
||||
filter := func(files, nongcc, gcc []string) ([]string, []string) {
|
||||
for _, f := range files {
|
||||
@ -1432,11 +1447,9 @@ func (b *builder) build(a *action) (err error) {
|
||||
}
|
||||
return nongcc, gcc
|
||||
}
|
||||
cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles)
|
||||
sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
|
||||
} else {
|
||||
gccfiles = append(cfiles, sfiles...)
|
||||
cfiles = nil
|
||||
gccfiles = append(gccfiles, sfiles...)
|
||||
sfiles = nil
|
||||
}
|
||||
|
||||
@ -1444,7 +1457,7 @@ func (b *builder) build(a *action) (err error) {
|
||||
if a.cgo != nil && 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 {
|
||||
return err
|
||||
}
|
||||
@ -1552,7 +1565,7 @@ func (b *builder) build(a *action) (err error) {
|
||||
|
||||
// NOTE(rsc): On Windows, it is critically important that the
|
||||
// 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
|
||||
objects = append(objects, cgoObjects...)
|
||||
|
||||
@ -1658,7 +1671,7 @@ func (b *builder) install(a *action) (err error) {
|
||||
}
|
||||
|
||||
// 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
|
||||
// this keeps the intermediate objects from hitting the disk.
|
||||
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)
|
||||
if err != nil && toolIsWindows {
|
||||
// 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
|
||||
// next time we do an install of this binary.
|
||||
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 source directory for the package that has failed to build.
|
||||
// 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,
|
||||
// the output is
|
||||
//
|
||||
@ -1991,7 +2004,7 @@ func relPaths(paths []string) []string {
|
||||
// errPrintedOutput is a special error indicating that a command failed
|
||||
// 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
|
||||
// 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.
|
||||
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()
|
||||
|
||||
// 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.
|
||||
// If another command was kicked off while we were writing the
|
||||
// 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.
|
||||
// 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
|
||||
// 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
|
||||
// until the time of the explicit close, and the race would remain.
|
||||
//
|
||||
// On Unix systems, this results in ETXTBSY, which formats
|
||||
// as "text file busy". Rather than hard-code specific error cases,
|
||||
// we just look for that string. If this happens, sleep a little
|
||||
// and try again. We let this happen three times, with increasing
|
||||
// we just look for that string. If this happens, sleep a little
|
||||
// and try again. We let this happen three times, with increasing
|
||||
// sleep lengths: 100+200+400 ms = 0.7 seconds.
|
||||
//
|
||||
// An alternate solution might be to split the cmd.Run into
|
||||
// separate cmd.Start and cmd.Wait, and then use an RWLock
|
||||
// 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
|
||||
// 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,
|
||||
// at least one close-on-exec file descriptor has been closed.
|
||||
// However, we cannot be sure that all of them have been closed,
|
||||
// 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.
|
||||
//
|
||||
// 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()
|
||||
defer b.exec.Unlock()
|
||||
// We can be a little aggressive about being
|
||||
// sure directories exist. Skip repeated calls.
|
||||
// sure directories exist. Skip repeated calls.
|
||||
if b.mkdirCache[dir] {
|
||||
return nil
|
||||
}
|
||||
@ -2180,7 +2193,6 @@ func mkAbs(dir, f string) string {
|
||||
type toolchain interface {
|
||||
// gc runs the compiler in a specific directory on a set of files
|
||||
// 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)
|
||||
// cc runs the toolchain's C compiler in a directory on a C 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.
|
||||
// Exceptions: a few standard packages have forward declarations for
|
||||
// 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 {
|
||||
switch p.ImportPath {
|
||||
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.
|
||||
inc := filepath.Join(goroot, "pkg", "include")
|
||||
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 {
|
||||
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.
|
||||
// Since it used to not work that way, verify.
|
||||
if _, err := os.Stat(absAfile); err != nil {
|
||||
fatalf("os.Stat of archive file failed: %v", err)
|
||||
if !buildN {
|
||||
if _, err := os.Stat(absAfile); err != nil {
|
||||
fatalf("os.Stat of archive file failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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,
|
||||
// and all LDFLAGS from cgo dependencies.
|
||||
apackagesSeen := make(map[*Package]bool)
|
||||
apackagePathsSeen := make(map[string]bool)
|
||||
afiles := []string{}
|
||||
shlibs := []string{}
|
||||
xfiles := []string{}
|
||||
ldflags := b.gccArchArgs()
|
||||
cgoldflags := []string{}
|
||||
usesCgo := false
|
||||
cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
|
||||
objc := len(root.p.MFiles) > 0
|
||||
cxx := false
|
||||
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 {
|
||||
flags, err := ioutil.ReadFile(flagsFile)
|
||||
@ -2687,11 +2714,11 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
// more). We still need to traverse the dependencies of the
|
||||
// build action though so saying
|
||||
// if apackagesSeen[a.p] { return }
|
||||
// if apackagePathsSeen[a.p.ImportPath] { return }
|
||||
// doesn't work.
|
||||
if !apackagesSeen[a.p] {
|
||||
apackagesSeen[a.p] = true
|
||||
if !apackagePathsSeen[a.p.ImportPath] {
|
||||
apackagePathsSeen[a.p.ImportPath] = true
|
||||
target := a.target
|
||||
if len(a.p.CgoFiles) > 0 {
|
||||
target, err = readAndRemoveCgoFlags(target)
|
||||
@ -2734,17 +2761,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||
return
|
||||
}
|
||||
}
|
||||
if a.p.fake && a.p.external {
|
||||
// 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)
|
||||
}
|
||||
afiles = append(afiles, target)
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(a.target, ".so") {
|
||||
@ -2764,7 +2781,6 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||
return err
|
||||
}
|
||||
}
|
||||
afiles = append(xfiles, afiles...)
|
||||
|
||||
for _, a := range allactions {
|
||||
// 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 {
|
||||
objc = true
|
||||
}
|
||||
if len(a.p.FFiles) > 0 {
|
||||
fortran = true
|
||||
}
|
||||
}
|
||||
|
||||
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, envList("CGO_LDFLAGS", "")...)
|
||||
ldflags = append(ldflags, root.p.CgoLDFLAGS...)
|
||||
if root.p != nil {
|
||||
ldflags = append(ldflags, root.p.CgoLDFLAGS...)
|
||||
}
|
||||
|
||||
ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)")
|
||||
|
||||
@ -2820,7 +2841,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||
}
|
||||
|
||||
var realOut string
|
||||
switch ldBuildmode {
|
||||
switch buildmode {
|
||||
case "exe":
|
||||
if usesCgo && goos == "linux" {
|
||||
ldflags = append(ldflags, "-Wl,-E")
|
||||
@ -2836,7 +2857,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||
// initialization code.
|
||||
//
|
||||
// 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
|
||||
// split-stack and non-split-stack code in a single -r
|
||||
// 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":
|
||||
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:
|
||||
fatalf("-buildmode=%s not supported for gccgo", ldBuildmode)
|
||||
fatalf("-buildmode=%s not supported for gccgo", buildmode)
|
||||
}
|
||||
|
||||
switch ldBuildmode {
|
||||
switch buildmode {
|
||||
case "exe", "c-shared":
|
||||
if cxx {
|
||||
ldflags = append(ldflags, "-lstdc++")
|
||||
@ -2868,43 +2891,40 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
||||
if objc {
|
||||
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
|
||||
}
|
||||
|
||||
switch ldBuildmode {
|
||||
switch buildmode {
|
||||
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 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 {
|
||||
args := []string{"-o", out, "-shared", "-nostdlib", "-zdefs", "-Wl,--whole-archive"}
|
||||
for _, a := range toplevelactions {
|
||||
args = append(args, a.target)
|
||||
}
|
||||
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)
|
||||
fakeRoot := &action{}
|
||||
fakeRoot.deps = toplevelactions
|
||||
return tools.link(b, fakeRoot, out, allactions, "", nil, "shared", out)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error {
|
||||
file = mkAbs(p.Dir, file)
|
||||
@ -2991,6 +3016,11 @@ func (b *builder) gxxCmd(objdir string) []string {
|
||||
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
|
||||
// variable and using the default command when the variable is empty.
|
||||
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
|
||||
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
|
||||
// is always set, and the Mach-O linker in 6l/8l assumes this.
|
||||
// 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
|
||||
// not supported by all compilers.
|
||||
func (b *builder) gccSupportsNoPie() bool {
|
||||
if goos != "linux" {
|
||||
// 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
|
||||
// systems so far, we only test there.
|
||||
return false
|
||||
return b.gccSupportsFlag("-no-pie")
|
||||
}
|
||||
|
||||
// gccSupportsFlag checks to see if the compiler supports a flag.
|
||||
func (b *builder) gccSupportsFlag(flag string) bool {
|
||||
b.exec.Lock()
|
||||
defer b.exec.Unlock()
|
||||
if b, ok := b.flagCache[flag]; ok {
|
||||
return b
|
||||
}
|
||||
src := filepath.Join(b.work, "trivial.c")
|
||||
if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
|
||||
return false
|
||||
if b.flagCache == nil {
|
||||
src := filepath.Join(b.work, "trivial.c")
|
||||
if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
|
||||
return false
|
||||
}
|
||||
b.flagCache = make(map[string]bool)
|
||||
}
|
||||
cmdArgs := b.gccCmd(b.work)
|
||||
cmdArgs = append(cmdArgs, "-no-pie", "-c", "trivial.c")
|
||||
cmdArgs := append(envList("CC", defaultCC), flag, "-c", "trivial.c")
|
||||
if buildN || buildX {
|
||||
b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs))
|
||||
if buildN {
|
||||
@ -3063,9 +3109,11 @@ func (b *builder) gccSupportsNoPie() bool {
|
||||
}
|
||||
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
||||
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()
|
||||
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.
|
||||
@ -3077,6 +3125,10 @@ func (b *builder) gccArchArgs() []string {
|
||||
return []string{"-m64"}
|
||||
case "arm":
|
||||
return []string{"-marm"} // not thumb
|
||||
case "s390x":
|
||||
return []string{"-m64", "-march=z196"}
|
||||
case "mips64", "mips64le":
|
||||
return []string{"-mabi=64"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -3091,8 +3143,8 @@ func envList(key, def string) []string {
|
||||
return strings.Fields(v)
|
||||
}
|
||||
|
||||
// Return the flags to use when invoking the C or C++ compilers, or cgo.
|
||||
func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {
|
||||
// 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, fflags, ldflags []string) {
|
||||
var defaults string
|
||||
if def {
|
||||
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)
|
||||
cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
|
||||
cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
|
||||
fflags = stringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
|
||||
ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
|
||||
return
|
||||
}
|
||||
|
||||
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) {
|
||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true)
|
||||
_, cgoexeCFLAGS, _, _ := b.cflags(p, false)
|
||||
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, cgoFFLAGS, cgoLDFLAGS := b.cflags(p, true)
|
||||
_, cgoexeCFLAGS, _, _, _ := b.cflags(p, false)
|
||||
cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
|
||||
cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
|
||||
// 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")
|
||||
}
|
||||
|
||||
// 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" {
|
||||
cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
|
||||
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="):
|
||||
continue
|
||||
// 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
|
||||
// specify the set of LDFLAGS that only apply to shared
|
||||
// objects.
|
||||
@ -3284,6 +3350,17 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
|
||||
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...)
|
||||
dynobj := obj + "_cgo_.o"
|
||||
pie := (goarch == "arm" && goos == "linux") || goos == "android"
|
||||
@ -3449,6 +3526,13 @@ func (b *builder) swigVersionCheck() error {
|
||||
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
|
||||
const swigIntSizeCode = `
|
||||
package main
|
||||
@ -3456,8 +3540,8 @@ const i int = 1 << 32
|
||||
`
|
||||
|
||||
// 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) {
|
||||
// of swig >= 2.0.9. Run only once.
|
||||
func (b *builder) swigDoIntSize(obj string) (intsize string, err error) {
|
||||
if buildN {
|
||||
return "$INTBITS", nil
|
||||
}
|
||||
@ -3475,9 +3559,18 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
|
||||
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.
|
||||
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
|
||||
if cxx {
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// do, but only on systems likely to support it, which is to say,
|
||||
// systems that normally use gold or the GNU linker.
|
||||
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
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -26,6 +26,7 @@ func newContext(c *build.Context) *Context {
|
||||
GOARCH: c.GOARCH,
|
||||
GOOS: c.GOOS,
|
||||
GOROOT: c.GOROOT,
|
||||
GOPATH: c.GOPATH,
|
||||
CgoEnabled: c.CgoEnabled,
|
||||
UseAllFiles: c.UseAllFiles,
|
||||
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
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate ./mkalldocs.sh
|
||||
|
||||
package main
|
||||
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -33,11 +33,6 @@ func mkEnv() []envVar {
|
||||
var b builder
|
||||
b.init()
|
||||
|
||||
vendorExpValue := "0"
|
||||
if go15VendorExperiment {
|
||||
vendorExpValue = "1"
|
||||
}
|
||||
|
||||
env := []envVar{
|
||||
{"GOARCH", goarch},
|
||||
{"GOBIN", gobin},
|
||||
@ -49,7 +44,6 @@ func mkEnv() []envVar {
|
||||
{"GORACE", os.Getenv("GORACE")},
|
||||
{"GOROOT", goroot},
|
||||
{"GOTOOLDIR", toolDir},
|
||||
{"GO15VENDOREXPERIMENT", vendorExpValue},
|
||||
|
||||
// disable escape codes in clang errors
|
||||
{"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
|
||||
// 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
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -14,10 +14,8 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
var cmdGenerate = &Command{
|
||||
@ -277,8 +275,8 @@ func isGoGenerate(buf []byte) bool {
|
||||
// single go:generate command.
|
||||
func (g *Generator) setEnv() {
|
||||
g.env = []string{
|
||||
"GOARCH=" + runtime.GOARCH,
|
||||
"GOOS=" + runtime.GOOS,
|
||||
"GOARCH=" + buildContext.GOARCH,
|
||||
"GOOS=" + buildContext.GOOS,
|
||||
"GOFILE=" + g.file,
|
||||
"GOLINE=" + strconv.Itoa(g.lineNum),
|
||||
"GOPACKAGE=" + g.pkg,
|
||||
@ -371,17 +369,6 @@ func (g *Generator) expandVar(word string) string {
|
||||
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.
|
||||
func (g *Generator) setShorthand(words []string) {
|
||||
// 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
|
||||
// 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
|
||||
// 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]",
|
||||
Short: "download and install packages and dependencies",
|
||||
Long: `
|
||||
Get downloads and installs the packages named by the import paths,
|
||||
along with their dependencies.
|
||||
Get downloads the packages named by the import paths, along with their
|
||||
dependencies. It then installs the named packages, like 'go install'.
|
||||
|
||||
The -d flag instructs get to stop after downloading the packages; that is,
|
||||
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'.
|
||||
|
||||
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,
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
// 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
|
||||
// everything.
|
||||
for name := range packageCache {
|
||||
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)
|
||||
packagesForBuild(args)
|
||||
|
||||
@ -134,7 +141,7 @@ func runGet(cmd *Command, args []string) {
|
||||
}
|
||||
|
||||
// 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,
|
||||
// in the hope that we can figure out the repository from the
|
||||
// initial ...-free prefix.
|
||||
@ -145,7 +152,7 @@ func downloadPaths(args []string) []string {
|
||||
if strings.Contains(a, "...") {
|
||||
var expand []string
|
||||
// Use matchPackagesInFS to avoid printing
|
||||
// warnings. They will be printed by the
|
||||
// warnings. They will be printed by the
|
||||
// eventual call to importPaths instead.
|
||||
if build.IsLocalImport(a) {
|
||||
expand = matchPackagesInFS(a)
|
||||
@ -228,16 +235,6 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
|
||||
stk.pop()
|
||||
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()
|
||||
|
||||
args := []string{arg}
|
||||
@ -347,8 +344,8 @@ func downloadPackage(p *Package) error {
|
||||
}
|
||||
|
||||
if p.build.SrcRoot != "" {
|
||||
// Directory exists. Look for checkout along path to src.
|
||||
vcs, rootPath, err = vcsForDir(p)
|
||||
// Directory exists. Look for checkout along path to src.
|
||||
vcs, rootPath, err = vcsFromDir(p.Dir, p.build.SrcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -356,7 +353,7 @@ func downloadPackage(p *Package) error {
|
||||
|
||||
// Double-check where it came from.
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -391,7 +388,7 @@ func downloadPackage(p *Package) error {
|
||||
}
|
||||
|
||||
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)
|
||||
if len(list) == 0 {
|
||||
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.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 downloadRootCache[root] {
|
||||
return nil
|
||||
@ -422,7 +419,7 @@ func downloadPackage(p *Package) error {
|
||||
return fmt.Errorf("%s exists but is not a directory", meta)
|
||||
}
|
||||
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.
|
||||
// We require that too, just to avoid stepping on existing work.
|
||||
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
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -109,7 +109,7 @@ func TestMain(m *testing.M) {
|
||||
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
|
||||
// different.
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
// other tests.
|
||||
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
|
||||
// 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.
|
||||
func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
|
||||
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
|
||||
// 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
|
||||
// failure.
|
||||
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
|
||||
// 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) {
|
||||
if tg.doGrepMatch(match, b) {
|
||||
tg.t.Log(msg)
|
||||
@ -421,18 +421,6 @@ func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
|
||||
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
|
||||
// standard output and standard error.
|
||||
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
|
||||
// or directory. If the file or directory exists already, it will be
|
||||
// removed. When the test completes, the file or directory 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 if it exists.
|
||||
func (tg *testgoData) creatingTemp(path string) {
|
||||
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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (tg *testgoData) makeTempdir() {
|
||||
if tg.tempdir == "" {
|
||||
@ -501,6 +489,16 @@ func (tg *testgoData) path(name string) string {
|
||||
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.
|
||||
func (tg *testgoData) mustNotExist(path string) {
|
||||
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.
|
||||
func (tg *testgoData) isStale(pkg string) bool {
|
||||
tg.run("list", "-f", "{{.Stale}}", pkg)
|
||||
switch v := strings.TrimSpace(tg.getStdout()); v {
|
||||
case "true":
|
||||
return true
|
||||
case "false":
|
||||
return false
|
||||
default:
|
||||
tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
|
||||
panic("unreachable")
|
||||
// isStale reports whether pkg is stale, and why
|
||||
func (tg *testgoData) isStale(pkg string) (bool, string) {
|
||||
tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
|
||||
v := strings.TrimSpace(tg.getStdout())
|
||||
f := strings.SplitN(v, ":", 2)
|
||||
if len(f) == 2 {
|
||||
switch f[0] {
|
||||
case "true":
|
||||
return true, f[1]
|
||||
case "false":
|
||||
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.
|
||||
func (tg *testgoData) wantStale(pkg, msg string) {
|
||||
if !tg.isStale(pkg) {
|
||||
func (tg *testgoData) wantStale(pkg, reason, msg string) {
|
||||
stale, why := tg.isStale(pkg)
|
||||
if !stale {
|
||||
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.
|
||||
func (tg *testgoData) wantNotStale(pkg, msg string) {
|
||||
if tg.isStale(pkg) {
|
||||
func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
|
||||
stale, why := tg.isStale(pkg)
|
||||
if stale {
|
||||
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.
|
||||
@ -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.
|
||||
// This is to stub out uses of ssh by go get.
|
||||
func (tg *testgoData) failSSH() {
|
||||
@ -720,7 +703,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
||||
tg.tempFile("d1/src/p1/p1.go", `package p1`)
|
||||
tg.setenv("GOPATH", tg.path("d1"))
|
||||
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()
|
||||
|
||||
// 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"
|
||||
restore := addNL(sys)
|
||||
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()
|
||||
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:
|
||||
// that's how we tell when we flip from one release to another.
|
||||
zversion := runtime.GOROOT() + "/src/runtime/internal/sys/zversion.go"
|
||||
restore = addNL(zversion)
|
||||
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()
|
||||
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)
|
||||
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.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()
|
||||
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.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.
|
||||
tg.run("install", "std")
|
||||
@ -833,8 +816,8 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
|
||||
sep := string(filepath.ListSeparator)
|
||||
tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2"))
|
||||
tg.run("install", "p1")
|
||||
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly")
|
||||
tg.wantNotStale("p2", "./testgo list claims p2 is stale, incorrectly")
|
||||
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly")
|
||||
tg.wantNotStale("p2", "", "./testgo list claims p2 is stale, incorrectly")
|
||||
tg.sleep()
|
||||
if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -843,12 +826,12 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
|
||||
} else {
|
||||
tg.must(f.Close())
|
||||
}
|
||||
tg.wantStale("p2", "./testgo list claims p2 is NOT stale, incorrectly")
|
||||
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly")
|
||||
tg.wantStale("p2", "newer source file", "./testgo list claims p2 is NOT stale, incorrectly")
|
||||
tg.wantStale("p1", "stale dependency", "./testgo list claims p1 is NOT stale, incorrectly")
|
||||
|
||||
tg.run("install", "p1")
|
||||
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("p2", "", "./testgo list claims p2 is stale after reinstall, incorrectly")
|
||||
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after reinstall, incorrectly")
|
||||
}
|
||||
|
||||
func TestGoInstallDetectsRemovedFiles(t *testing.T) {
|
||||
@ -862,13 +845,13 @@ func TestGoInstallDetectsRemovedFiles(t *testing.T) {
|
||||
package mypkg`)
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
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.
|
||||
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.
|
||||
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) {
|
||||
@ -931,13 +914,13 @@ func TestGoInstallDetectsRemovedFilesInPackageMain(t *testing.T) {
|
||||
package main`)
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
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.
|
||||
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.
|
||||
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) {
|
||||
@ -1105,8 +1088,8 @@ func testMove(t *testing.T, vcs, url, base, config string) {
|
||||
}
|
||||
if vcs == "git" {
|
||||
// git will ask for a username and password when we
|
||||
// run go get -d -f -u. An empty username and
|
||||
// password will work. Prevent asking by setting
|
||||
// run go get -d -f -u. An empty username and
|
||||
// password will work. Prevent asking by setting
|
||||
// GIT_ASKPASS.
|
||||
tg.creatingTemp("sink" + exeSuffix)
|
||||
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")
|
||||
}
|
||||
|
||||
// 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) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
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"
|
||||
tg.run("get", "-d", "-u", importPath)
|
||||
repoDir := tg.path("src/" + importPath)
|
||||
defer tg.resetReadOnlyFlagAll(repoDir)
|
||||
tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
|
||||
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) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
@ -1217,7 +1227,6 @@ func TestGetGitDefaultBranch(t *testing.T) {
|
||||
|
||||
tg.run("get", "-d", importPath)
|
||||
repoDir := tg.path("src/" + importPath)
|
||||
defer tg.resetReadOnlyFlagAll(repoDir)
|
||||
tg.runGit(repoDir, "branch", "--contains", "HEAD")
|
||||
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")
|
||||
}
|
||||
|
||||
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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1337,19 +1338,35 @@ func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
|
||||
tg.sleep()
|
||||
tg.run("test", "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")
|
||||
}
|
||||
|
||||
// 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
|
||||
func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
// Make sure the packages below are not stale.
|
||||
tg.run("install", "runtime", "os", "io")
|
||||
|
||||
goroot := runtime.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")
|
||||
tg.wantNotStale("io", "with trailing slash in GOROOT, io listed as stale")
|
||||
|
||||
want := ""
|
||||
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.
|
||||
@ -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")
|
||||
}
|
||||
|
||||
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) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
@ -1508,7 +1503,7 @@ func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
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")
|
||||
}
|
||||
}
|
||||
@ -1537,7 +1532,7 @@ func TestGoListCmdOnlyShowsCommands(t *testing.T) {
|
||||
tg.run("list", "cmd")
|
||||
out := strings.TrimSpace(tg.getStdout())
|
||||
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")
|
||||
break
|
||||
}
|
||||
@ -1657,8 +1652,8 @@ func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
|
||||
func main() {
|
||||
println(extern)
|
||||
}`)
|
||||
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.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
|
||||
tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
|
||||
}
|
||||
|
||||
func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
|
||||
@ -1726,7 +1721,6 @@ func TestSymlinksVendor(t *testing.T) {
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
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/vendor/v/v.go", "package v")
|
||||
@ -1879,7 +1873,9 @@ func TestShadowingLogic(t *testing.T) {
|
||||
}
|
||||
// The output will have makeImportValid applies, but we only
|
||||
// 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") + ")"
|
||||
if strings.TrimSpace(tg.getStdout()) != want {
|
||||
t.Error("shadowed math is not shadowed; looking for", want)
|
||||
@ -2001,6 +1997,27 @@ func TestCoverageUsesActualSettingToOverrideEvenForRace(t *testing.T) {
|
||||
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) {
|
||||
if !canCgo {
|
||||
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`)
|
||||
}
|
||||
|
||||
func TestListTemplateCanUseContextFunction(t *testing.T) {
|
||||
func TestListTemplateContextFunction(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
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
|
||||
@ -2123,7 +2163,7 @@ func TestIssue7108(t *testing.T) {
|
||||
// cmd/go: go test -a foo does not rebuild regexp.
|
||||
func TestIssue6844(t *testing.T) {
|
||||
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)
|
||||
@ -2295,8 +2335,7 @@ func TestGoVetWithExternalTests(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.run("get", "golang.org/x/tools/cmd/vet")
|
||||
tg.run("install", "cmd/vet")
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.runFail("vet", "vetpkg")
|
||||
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)
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.run("get", "golang.org/x/tools/cmd/vet")
|
||||
tg.run("install", "cmd/vet")
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
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")
|
||||
@ -2330,6 +2368,11 @@ func TestGoGetRscIoToolstash(t *testing.T) {
|
||||
// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS
|
||||
func TestGoGetHTTPS404(t *testing.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)
|
||||
defer tg.cleanup()
|
||||
@ -2338,7 +2381,7 @@ func TestGoGetHTTPS404(t *testing.T) {
|
||||
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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -2359,6 +2402,8 @@ func TestIssue4210(t *testing.T) {
|
||||
func TestGoGetInsecure(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
t.Skip("golang.org/issue/15410")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
@ -2414,22 +2459,6 @@ func TestGoGetInsecureCustomDomain(t *testing.T) {
|
||||
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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -2759,3 +2788,169 @@ func TestParallelTest(t *testing.T) {
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
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
|
||||
// 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
|
||||
// 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/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)
|
||||
|
||||
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
|
||||
direct path to the underlying code hosting site.
|
||||
|
||||
If vendoring is enabled (see 'go help gopath'), then import path checking is
|
||||
disabled for code found within vendor trees. This makes it possible to copy
|
||||
code into alternate locations in vendor trees without needing to update import
|
||||
comments.
|
||||
Import path checking is disabled for code found within vendor trees.
|
||||
This makes it possible to copy code into alternate locations in vendor trees
|
||||
without needing to update import comments.
|
||||
|
||||
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
|
||||
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.
|
||||
`,
|
||||
}
|
||||
@ -497,8 +482,6 @@ Special-purpose environment variables:
|
||||
installed in a location other than where it is built.
|
||||
File names in stack traces are rewritten from GOROOT to
|
||||
GOROOT_FINAL.
|
||||
GO15VENDOREXPERIMENT
|
||||
Set to 0 to disable vendoring semantics.
|
||||
GO_EXTLINK_ENABLED
|
||||
Whether the linker should use external linking mode
|
||||
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
|
||||
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
|
||||
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
|
||||
// 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
|
||||
// or might be using self-signed certificates.
|
||||
var impatientInsecureHTTPClient = &http.Client{
|
||||
Timeout: time.Duration(5 * time.Second),
|
||||
Timeout: 5 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
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
|
||||
// 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?
|
||||
Standard bool // is this package part of the standard Go library?
|
||||
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
|
||||
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
|
||||
// Source files
|
||||
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
|
||||
MFiles []string // .m 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
|
||||
SwigFiles []string // .swig 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
|
||||
CgoCPPFLAGS []string // cgo: flags for C preprocessor
|
||||
CgoCXXFLAGS []string // cgo: flags for C++ compiler
|
||||
CgoFFLAGS []string // cgo: flags for Fortran compiler
|
||||
CgoLDFLAGS []string // cgo: flags for linker
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -214,15 +214,7 @@ var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}
|
||||
{{end}}{{.Long | trim}}
|
||||
`
|
||||
|
||||
var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// 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}}
|
||||
var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
|
||||
|
||||
{{end}}{{if .Runnable}}Usage:
|
||||
|
||||
@ -231,9 +223,39 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
|
||||
{{end}}{{.Long | trim}}
|
||||
|
||||
|
||||
{{end}}*/
|
||||
package main
|
||||
`
|
||||
{{end}}`
|
||||
|
||||
// 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.
|
||||
type errWriter struct {
|
||||
@ -310,10 +332,18 @@ func help(args []string) {
|
||||
|
||||
// 'go help documentation' generates doc.go.
|
||||
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)
|
||||
printUsage(buf)
|
||||
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
|
||||
}
|
||||
|
||||
@ -339,7 +369,7 @@ func importPathsNoDotExpansion(args []string) []string {
|
||||
for _, a := range args {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// 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 == '\\' {
|
||||
a = strings.Replace(a, `\`, `/`, -1)
|
||||
}
|
||||
@ -403,8 +433,6 @@ func errorf(format string, args ...interface{}) {
|
||||
setExitStatus(1)
|
||||
}
|
||||
|
||||
var logf = log.Printf
|
||||
|
||||
func exitIfErrors() {
|
||||
if exitStatus != 0 {
|
||||
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
|
||||
// suitable for running in the given directory.
|
||||
// The environment is the current process's environment
|
||||
@ -472,7 +487,7 @@ NextVar:
|
||||
}
|
||||
|
||||
// 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
|
||||
// is no other special syntax.
|
||||
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
|
||||
// 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 {
|
||||
pkgs := matchPackagesInFS(pattern)
|
||||
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
|
||||
// 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
|
||||
// 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")
|
||||
|
||||
// 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.
|
||||
func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string, err error) {
|
||||
// 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
|
||||
// due to differences in note segment placement;
|
||||
// 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 {
|
||||
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
|
||||
// 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")
|
||||
case runtime.GOOS == "linux" && (runtime.GOARCH == "ppc64le" || runtime.GOARCH == "ppc64"):
|
||||
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":
|
||||
t.Skipf("skipping - external linking not supported, golang.org/issue/10619")
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -27,8 +27,8 @@ import (
|
||||
// A Package describes a single package found in a directory.
|
||||
type Package struct {
|
||||
// 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
|
||||
// remove existing ones. Keep in sync with list.go
|
||||
// See list.go. It is okay to add fields, but not to change or
|
||||
// remove existing ones. Keep in sync with list.go
|
||||
Dir string `json:",omitempty"` // directory containing package sources
|
||||
ImportPath string `json:",omitempty"` // import path of package in dir
|
||||
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?
|
||||
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?
|
||||
StaleReason string `json:",omitempty"` // why is Stale true?
|
||||
Root string `json:",omitempty"` // Go root or Go path dir containing this package
|
||||
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
|
||||
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||
|
||||
// Source files
|
||||
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
|
||||
MFiles []string `json:",omitempty"` // .m 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
|
||||
SwigFiles []string `json:",omitempty"` // .swig files
|
||||
SwigCXXFiles []string `json:",omitempty"` // .swigcxx files
|
||||
@ -59,6 +62,7 @@ type Package struct {
|
||||
CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler
|
||||
CgoCPPFLAGS []string `json:",omitempty"` // cgo: flags for C preprocessor
|
||||
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
|
||||
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)
|
||||
fake bool // synthesized 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")
|
||||
cmdline bool // defined by files listed on command line
|
||||
local bool // imported via local path (./ or ../)
|
||||
@ -151,6 +154,8 @@ func (p *Package) copyBuild(pp *build.Package) {
|
||||
p.Doc = pp.Doc
|
||||
p.Root = pp.Root
|
||||
p.ConflictDir = pp.ConflictDir
|
||||
p.BinaryOnly = pp.BinaryOnly
|
||||
|
||||
// TODO? Target
|
||||
p.Goroot = pp.Goroot
|
||||
if buildContext.Compiler == "gccgo" {
|
||||
@ -165,6 +170,7 @@ func (p *Package) copyBuild(pp *build.Package) {
|
||||
p.CXXFiles = pp.CXXFiles
|
||||
p.MFiles = pp.MFiles
|
||||
p.HFiles = pp.HFiles
|
||||
p.FFiles = pp.FFiles
|
||||
p.SFiles = pp.SFiles
|
||||
p.SwigFiles = pp.SwigFiles
|
||||
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 "))
|
||||
}
|
||||
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.
|
||||
return p.Pos + ": " + p.Err
|
||||
}
|
||||
@ -267,18 +273,9 @@ func reloadPackage(arg string, stk *importStack) *Package {
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
// the pseudo-import path is _/c_/home/gopher/my/pkg.
|
||||
// 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
|
||||
@ -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.
|
||||
// See issue 3268 for mistakes to avoid.
|
||||
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.
|
||||
buildMode |= build.IgnoreVendor
|
||||
}
|
||||
@ -375,7 +372,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
|
||||
bp.BinDir = gobin
|
||||
}
|
||||
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)
|
||||
}
|
||||
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.
|
||||
// vendoredImportPath returns the expanded path or, if no expansion is found, the original.
|
||||
func vendoredImportPath(parent *Package, path string) (found string) {
|
||||
if parent == nil || parent.Root == "" || !go15VendorExperiment {
|
||||
if parent == nil || parent.Root == "" {
|
||||
return path
|
||||
}
|
||||
|
||||
@ -445,6 +442,12 @@ func vendoredImportPath(parent *Package, path string) (found string) {
|
||||
}
|
||||
targ := filepath.Join(dir[:i], vpath)
|
||||
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 know the import path for parent's dir.
|
||||
// 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
|
||||
// and then append /vendor/path.
|
||||
chopped := len(dir) - i
|
||||
if chopped == len(parent.ImportPath)+1 {
|
||||
if chopped == len(importPath)+1 {
|
||||
// We walked up from c:\gopath\src\foo\bar
|
||||
// and found c:\gopath\src\vendor\path.
|
||||
// We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7).
|
||||
// Use "vendor/path" without any prefix.
|
||||
return vpath
|
||||
}
|
||||
return parent.ImportPath[:len(parent.ImportPath)-chopped] + "/" + vpath
|
||||
return importPath[:len(importPath)-chopped] + "/" + vpath
|
||||
}
|
||||
}
|
||||
return path
|
||||
@ -482,7 +485,7 @@ func hasGoFiles(dir string) bool {
|
||||
}
|
||||
|
||||
// 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.
|
||||
func reusePackage(p *Package, stk *importStack) *Package {
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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)
|
||||
if !ok {
|
||||
return p
|
||||
@ -565,7 +568,7 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
|
||||
// If there isn't one, findInternal returns ok=false.
|
||||
// Otherwise, findInternal returns ok=true and the index of the "internal".
|
||||
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,
|
||||
// because the final one produces the most restrictive requirement
|
||||
// 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 not, it returns a new package containing just an appropriate error.
|
||||
func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package {
|
||||
if !go15VendorExperiment {
|
||||
return p
|
||||
}
|
||||
|
||||
// The stack includes p.ImportPath.
|
||||
// If that's the only thing on the stack, we started
|
||||
// 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.
|
||||
// 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,
|
||||
// not the vendored copy of an import "" (the empty import path).
|
||||
@ -691,7 +690,6 @@ type targetDir int
|
||||
const (
|
||||
toRoot targetDir = iota // to bin dir inside package root (default)
|
||||
toTool // GOROOT/pkg/tool
|
||||
toBin // GOROOT/bin
|
||||
stalePath // the old import path; fail to build
|
||||
)
|
||||
|
||||
@ -715,7 +713,6 @@ var goTools = map[string]targetDir{
|
||||
"cmd/trace": toTool,
|
||||
"cmd/vet": 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/godoc": 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.
|
||||
// When printed in something like context: %v
|
||||
// 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.
|
||||
var buf bytes.Buffer
|
||||
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.
|
||||
elem = full
|
||||
}
|
||||
if p.build.BinDir != gobin && goTools[p.ImportPath] == toBin {
|
||||
// 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 != "" {
|
||||
if p.build.BinDir != "" {
|
||||
// Install to GOBIN or bin of GOPATH entry.
|
||||
p.target = filepath.Join(p.build.BinDir, elem)
|
||||
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.MFiles,
|
||||
p.HFiles,
|
||||
p.FFiles,
|
||||
p.SFiles,
|
||||
p.SysoFiles,
|
||||
p.SwigFiles,
|
||||
@ -1032,6 +1025,20 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
|
||||
}
|
||||
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.
|
||||
if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && buildContext.Compiler == "gc" {
|
||||
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
|
||||
}
|
||||
|
||||
@ -1094,7 +1109,7 @@ func packageList(roots []*Package) []*Package {
|
||||
// at the named pkgs (command-line arguments).
|
||||
func computeStale(pkgs ...*Package) {
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 'go build -tags netgo' work, among other things.
|
||||
|
||||
// isStale reports whether package p needs to be rebuilt.
|
||||
func isStale(p *Package) bool {
|
||||
// isStale reports whether package p needs to be rebuilt,
|
||||
// along with the reason why.
|
||||
func isStale(p *Package) (bool, string) {
|
||||
if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
|
||||
// fake, builtin package
|
||||
return false
|
||||
return false, "builtin package"
|
||||
}
|
||||
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
|
||||
// the installed .a file. Since we don't know how to rebuild
|
||||
// it, it can't be stale, even if -a is set. This enables binary-only
|
||||
// distributions of Go packages, although such binaries are
|
||||
// only useful with the specific version of the toolchain that
|
||||
// created them.
|
||||
if len(p.gofiles) == 0 && !p.usesSwig() {
|
||||
return false
|
||||
// If this is a package with no source code, it cannot be rebuilt.
|
||||
// If the binary is missing, we mark the package stale so that
|
||||
// if a rebuild is needed, that rebuild attempt will produce a useful error.
|
||||
// (Some commands, such as 'go list', do not attempt to rebuild.)
|
||||
if p.BinaryOnly {
|
||||
if p.target == "" {
|
||||
// Fail if a build is attempted.
|
||||
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 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 p.target == "" || p.Stale {
|
||||
return true
|
||||
// If there's no install target, we have to rebuild.
|
||||
if p.target == "" {
|
||||
return true, "no install target"
|
||||
}
|
||||
|
||||
// Package is stale if completely unbuilt.
|
||||
fi, err := os.Stat(p.target)
|
||||
if err != nil {
|
||||
return true
|
||||
return true, "cannot stat install target"
|
||||
}
|
||||
|
||||
// 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.
|
||||
targetBuildID, err := readBuildID(p)
|
||||
if err == nil && targetBuildID != p.buildID {
|
||||
return true
|
||||
return true, "build ID mismatch"
|
||||
}
|
||||
|
||||
// Package is stale if a dependency is.
|
||||
for _, p1 := range p.deps {
|
||||
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
|
||||
// before rebuilding.)
|
||||
if p.Standard && isGoRelease {
|
||||
return false
|
||||
return false, "standard package in Go release distribution"
|
||||
}
|
||||
|
||||
// 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.
|
||||
for _, p1 := range p.deps {
|
||||
if p1.target != "" && olderThan(p1.target) {
|
||||
return true
|
||||
return true, "newer dependency"
|
||||
}
|
||||
}
|
||||
|
||||
// As a courtesy to developers installing new versions of the compiler
|
||||
// frequently, define that packages are stale if they are
|
||||
// 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
|
||||
// a very common case.
|
||||
// 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).
|
||||
if p.Root != goroot {
|
||||
if olderThan(buildToolchain.compiler()) {
|
||||
return true
|
||||
return true, "newer compiler"
|
||||
}
|
||||
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
|
||||
// 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 {
|
||||
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.
|
||||
@ -1584,7 +1609,7 @@ var cwd, _ = os.Getwd()
|
||||
var cmdCache = map[string]*Package{}
|
||||
|
||||
// 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
|
||||
// in the Go command directory, as well as paths to those directories.
|
||||
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
|
||||
// cannot be loaded at all (for example, if the directory does not exist),
|
||||
// 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
|
||||
// package is still returned, with p.Incomplete = true
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -161,9 +161,12 @@ func TestSharedLibName(t *testing.T) {
|
||||
}
|
||||
oldGopath := buildContext.GOPATH
|
||||
defer func() {
|
||||
os.RemoveAll(tmpGopath)
|
||||
buildContext.GOPATH = oldGopath
|
||||
os.Chdir(cwd)
|
||||
err := os.RemoveAll(tmpGopath)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}()
|
||||
root := filepath.Join(tmpGopath, "src", data.rootedAt)
|
||||
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
|
||||
// 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
|
||||
// been compiled. We ignore exit status.
|
||||
// been compiled. We ignore exit status.
|
||||
func (b *builder) runProgram(a *action) error {
|
||||
cmdline := stringList(findExecCmd(), a.deps[0].target, a.args)
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
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
|
||||
with source in the current directory, including tests, and runs the tests.
|
||||
|
||||
@ -125,7 +128,10 @@ control the execution of any test:
|
||||
|
||||
const testFlag2 = `
|
||||
-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,
|
||||
use '-bench .' or '-bench=.'.
|
||||
|
||||
@ -213,8 +219,10 @@ const testFlag2 = `
|
||||
(see 'go help build').
|
||||
|
||||
-run regexp
|
||||
Run only those tests and examples matching the regular
|
||||
expression.
|
||||
Run only those tests and examples matching the regular 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
|
||||
Tell long-running tests to shorten their run time.
|
||||
@ -228,7 +236,6 @@ const testFlag2 = `
|
||||
|
||||
-trace trace.out
|
||||
Write an execution trace to the specified file before exiting.
|
||||
Writes test binary as -c would.
|
||||
|
||||
-v
|
||||
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
|
||||
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,
|
||||
it may be necessary to do the same when invoking a generated test
|
||||
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
|
||||
*testing.T to report success or failure, prints output to os.Stdout.
|
||||
That output is compared against the function's "Output:" comment, which
|
||||
must be the last comment in the function body (see example below). An
|
||||
example with no such comment, or with no text after "Output:" is compiled
|
||||
but not executed.
|
||||
If the last comment in the function starts with "Output:" then the output
|
||||
is compared exactly against the comment (see examples below). If the last
|
||||
comment begins with "Unordered output:" then the output is compared to the
|
||||
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
|
||||
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.
|
||||
}
|
||||
|
||||
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
|
||||
example function, at least one other function, type, variable, or constant
|
||||
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
|
||||
// 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
|
||||
// timer does not get a chance to fire.
|
||||
if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 {
|
||||
@ -495,7 +517,8 @@ func runTest(cmd *Command, args []string) {
|
||||
continue
|
||||
}
|
||||
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
|
||||
var coverFiles []string
|
||||
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
|
||||
// other tests will see it as the real package.
|
||||
// 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.
|
||||
//
|
||||
// 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.forceLibrary = true
|
||||
ptest.Stale = true
|
||||
ptest.StaleReason = "rebuild for test"
|
||||
ptest.build = new(build.Package)
|
||||
*ptest.build = *p.build
|
||||
m := map[string][]token.Position{}
|
||||
@ -1019,6 +1043,7 @@ func recompileForTest(pmain, preal, ptest *Package, testDir string) {
|
||||
p.target = ""
|
||||
p.fake = true
|
||||
p.Stale = true
|
||||
p.StaleReason = "depends on package being tested"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1218,11 +1243,11 @@ func (b *builder) notest(a *action) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// isTestMain tells whether fn is a TestMain(m *testing.M) function.
|
||||
func isTestMain(fn *ast.FuncDecl) bool {
|
||||
if fn.Name.String() != "TestMain" ||
|
||||
fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
|
||||
fn.Type.Params == nil ||
|
||||
// isTestFunc tells whether fn has the type of a testing function. arg
|
||||
// specifies the parameter type we look for: B, M or T.
|
||||
func isTestFunc(fn *ast.FuncDecl, arg string) bool {
|
||||
if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
|
||||
fn.Type.Params.List == nil ||
|
||||
len(fn.Type.Params.List) != 1 ||
|
||||
len(fn.Type.Params.List[0].Names) > 1 {
|
||||
return false
|
||||
@ -1234,10 +1259,11 @@ func isTestMain(fn *ast.FuncDecl) bool {
|
||||
// We can't easily check that the type is *testing.M
|
||||
// because we don't know how testing has been imported,
|
||||
// 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
|
||||
}
|
||||
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 false
|
||||
@ -1334,9 +1360,10 @@ func (t *testFuncs) Tested() string {
|
||||
}
|
||||
|
||||
type testFunc struct {
|
||||
Package string // imported package name (_test or _xtest)
|
||||
Name string // function name
|
||||
Output string // output, for examples
|
||||
Package string // imported package name (_test or _xtest)
|
||||
Name string // function name
|
||||
Output string // output, for examples
|
||||
Unordered bool // output is allowed to be unordered.
|
||||
}
|
||||
|
||||
var testFileSet = token.NewFileSet()
|
||||
@ -1356,17 +1383,25 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
|
||||
}
|
||||
name := n.Name.String()
|
||||
switch {
|
||||
case isTestMain(n):
|
||||
case name == "TestMain" && isTestFunc(n, "M"):
|
||||
if t.TestMain != nil {
|
||||
return errors.New("multiple definitions of TestMain")
|
||||
}
|
||||
t.TestMain = &testFunc{pkg, name, ""}
|
||||
t.TestMain = &testFunc{pkg, name, "", false}
|
||||
*doImport, *seen = true, true
|
||||
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
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -1378,12 +1413,21 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
|
||||
// Don't run examples with no output.
|
||||
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
|
||||
}
|
||||
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
|
||||
|
||||
func (x byOrder) Len() int { return len(x) }
|
||||
@ -1429,7 +1473,7 @@ var benchmarks = []testing.InternalBenchmark{
|
||||
|
||||
var examples = []testing.InternalExample{
|
||||
{{range .Examples}}
|
||||
{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}},
|
||||
{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
|
||||
{{end}}
|
||||
}
|
||||
|
||||
|
2
libgo/go/cmd/go/testdata/dep_test.go
vendored
2
libgo/go/cmd/go/testdata/dep_test.go
vendored
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
2
libgo/go/cmd/go/testdata/example1_test.go
vendored
2
libgo/go/cmd/go/testdata/example1_test.go
vendored
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
2
libgo/go/cmd/go/testdata/example2_test.go
vendored
2
libgo/go/cmd/go/testdata/example2_test.go
vendored
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
2
libgo/go/cmd/go/testdata/generate/test1.go
vendored
2
libgo/go/cmd/go/testdata/generate/test1.go
vendored
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
2
libgo/go/cmd/go/testdata/generate/test2.go
vendored
2
libgo/go/cmd/go/testdata/generate/test2.go
vendored
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
2
libgo/go/cmd/go/testdata/generate/test3.go
vendored
2
libgo/go/cmd/go/testdata/generate/test3.go
vendored
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
2
libgo/go/cmd/go/testdata/generate/test4.go
vendored
2
libgo/go/cmd/go/testdata/generate/test4.go
vendored
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
7
libgo/go/cmd/go/testdata/src/benchfatal/x_test.go
vendored
Normal file
7
libgo/go/cmd/go/testdata/src/benchfatal/x_test.go
vendored
Normal 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
|
||||
case "timeout":
|
||||
testTimeout = value
|
||||
case "blockprofile", "cpuprofile", "memprofile", "trace":
|
||||
case "blockprofile", "cpuprofile", "memprofile":
|
||||
testProfile = true
|
||||
testNeedBinary = true
|
||||
case "trace":
|
||||
testProfile = true
|
||||
case "coverpkg":
|
||||
testCover = true
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -93,7 +93,7 @@ var vcsHg = &vcsCmd{
|
||||
downloadCmd: []string{"pull"},
|
||||
|
||||
// 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
|
||||
// and make changes in both, without constantly
|
||||
// editing .hgtags.
|
||||
@ -171,10 +171,10 @@ func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error
|
||||
// Eg, "git@github.com:user/repo" becomes
|
||||
// "ssh://git@github.com/user/repo".
|
||||
repoURL = &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User(m[1]),
|
||||
Host: m[2],
|
||||
RawPath: m[3],
|
||||
Scheme: "ssh",
|
||||
User: url.User(m[1]),
|
||||
Host: m[2],
|
||||
Path: m[3],
|
||||
}
|
||||
} else {
|
||||
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")
|
||||
}
|
||||
out = out[:i]
|
||||
return strings.TrimSpace(string(out)), nil
|
||||
return strings.TrimSpace(out), nil
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
out = out[:i]
|
||||
return strings.TrimSpace(string(out)), nil
|
||||
return strings.TrimSpace(out), nil
|
||||
}
|
||||
|
||||
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.
|
||||
func (v *vcsCmd) create(dir, repo string) error {
|
||||
for _, cmd := range v.createCmd {
|
||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
||||
continue
|
||||
}
|
||||
if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -396,9 +393,6 @@ func (v *vcsCmd) create(dir, repo string) error {
|
||||
// download downloads any new changes for the repo in dir.
|
||||
func (v *vcsCmd) download(dir string) error {
|
||||
for _, cmd := range v.downloadCmd {
|
||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
||||
continue
|
||||
}
|
||||
if err := v.run(dir, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -445,9 +439,6 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
|
||||
|
||||
if tag == "" && v.tagSyncDefault != nil {
|
||||
for _, cmd := range v.tagSyncDefault {
|
||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
||||
continue
|
||||
}
|
||||
if err := v.run(dir, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -456,9 +447,6 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
|
||||
}
|
||||
|
||||
for _, cmd := range v.tagSyncCmd {
|
||||
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
|
||||
continue
|
||||
}
|
||||
if err := v.run(dir, cmd, "tag", tag); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -479,15 +467,14 @@ type vcsPath struct {
|
||||
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.
|
||||
// On return, root is the import path
|
||||
// corresponding to the root of the repository
|
||||
// (thus root is a prefix of importPath).
|
||||
func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) {
|
||||
// corresponding to the root of the repository.
|
||||
func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
|
||||
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
|
||||
dir := filepath.Clean(p.Dir)
|
||||
srcRoot := filepath.Clean(p.build.SrcRoot)
|
||||
dir = filepath.Clean(dir)
|
||||
srcRoot = filepath.Clean(srcRoot)
|
||||
if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
|
||||
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 _, vcs := range vcsList {
|
||||
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.
|
||||
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.
|
||||
// An error is returned if there are multiple matches.
|
||||
// errNoMatch is returned if none match.
|
||||
func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) {
|
||||
match := -1
|
||||
imp := strings.Split(importPath, "/")
|
||||
for i, im := range imports {
|
||||
if !strings.HasPrefix(importPath, im.Prefix) {
|
||||
pre := strings.Split(im.Prefix, "/")
|
||||
|
||||
if !splitPathHasPrefix(imp, pre) {
|
||||
continue
|
||||
}
|
||||
|
||||
if match != -1 {
|
||||
err = fmt.Errorf("multiple meta tags match import path %q", importPath)
|
||||
return
|
||||
@ -815,20 +818,6 @@ func expand(match map[string]string, s string) string {
|
||||
// and import paths referring to a fully-qualified importPath
|
||||
// containing a VCS type (foo.com/repo.git/dir)
|
||||
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
|
||||
{
|
||||
prefix: "github.com/",
|
||||
@ -863,6 +852,14 @@ var vcsPaths = []*vcsPath{
|
||||
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.
|
||||
// Must be last.
|
||||
{
|
||||
@ -911,45 +908,6 @@ func noVCSSuffix(match map[string]string) error {
|
||||
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
|
||||
// Bitbucket repository, by using the Bitbucket API.
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -18,20 +23,6 @@ func TestRepoRootForImportPath(t *testing.T) {
|
||||
path string
|
||||
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",
|
||||
&repoRoot{
|
||||
@ -96,6 +87,39 @@ func TestRepoRootForImportPath(t *testing.T) {
|
||||
"hub.jazz.net/git/USER/pkgname",
|
||||
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
|
||||
{
|
||||
"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) {
|
||||
tests := []struct {
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -20,7 +20,6 @@ func TestVendorImports(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...")
|
||||
want := `
|
||||
vend [vend/vendor/p r]
|
||||
@ -51,7 +50,6 @@ func TestVendorBuild(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.run("build", "vend/x")
|
||||
}
|
||||
|
||||
@ -59,7 +57,6 @@ func TestVendorRun(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
|
||||
tg.run("run", "hello.go")
|
||||
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)
|
||||
tg.setenv("GOPATH", gopath)
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
cd := changeVolume(filepath.Join(tg.pwd(), "testdata/src/vend/hello"), strings.ToUpper)
|
||||
tg.cd(cd)
|
||||
tg.run("run", "hello.go")
|
||||
@ -85,7 +81,6 @@ func TestVendorTest(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
|
||||
tg.run("test", "-v")
|
||||
tg.grepStdout("TestMsgInternal", "missing use in internal test")
|
||||
@ -96,7 +91,6 @@ func TestVendorInvalid(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
|
||||
tg.runFail("build", "vend/x/invalid")
|
||||
tg.grepStderr("must be imported as foo", "missing vendor import error")
|
||||
@ -106,7 +100,6 @@ func TestVendorImportError(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
|
||||
tg.runFail("build", "vend/x/vendor/p/p")
|
||||
|
||||
@ -173,7 +166,6 @@ func TestVendorGet(t *testing.T) {
|
||||
package p
|
||||
const C = 1`)
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.cd(tg.path("src/v"))
|
||||
tg.run("run", "m.go")
|
||||
tg.run("test")
|
||||
@ -192,7 +184,6 @@ func TestVendorGetUpdate(t *testing.T) {
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.run("get", "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()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.run("get", "-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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.runFail("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()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.run("get", "github.com/rsc/go-get-issue-11864")
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
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) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
@ -251,7 +266,6 @@ func TestVendorList(t *testing.T) {
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
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")
|
||||
@ -272,7 +286,6 @@ func TestVendor12156(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2"))
|
||||
tg.setenv("GO15VENDOREXPERIMENT", "1")
|
||||
tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p"))
|
||||
tg.runFail("build", "p.go")
|
||||
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
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -55,7 +55,6 @@ func report(err error) {
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func initParserMode() {
|
||||
@ -143,7 +142,9 @@ func visitFile(path string, f os.FileInfo, err error) error {
|
||||
if err == nil && isGoFile(f) {
|
||||
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)
|
||||
}
|
||||
return nil
|
||||
|
@ -159,7 +159,7 @@ func TestCRLF(t *testing.T) {
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ func TestCRLF(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if bytes.Index(data, []byte("\r")) >= 0 {
|
||||
if bytes.Contains(data, []byte("\r")) {
|
||||
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.
|
||||
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
|
||||
// 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'") {
|
||||
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
|
||||
// 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
|
||||
// in fsrc match the ones in src. Add an extra '\n' 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -158,7 +158,7 @@ func isWildcard(s string) bool {
|
||||
// recording wildcard submatches in m.
|
||||
// If m == nil, match checks whether pattern == val.
|
||||
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
|
||||
// each time.
|
||||
if m != nil && pattern.IsValid() && pattern.Type() == identType {
|
||||
|
@ -10,11 +10,9 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type simplifier struct {
|
||||
hasDotImport bool // package file contains: import . "some/import/path"
|
||||
}
|
||||
type simplifier struct{}
|
||||
|
||||
func (s *simplifier) Visit(node ast.Node) ast.Visitor {
|
||||
func (s simplifier) Visit(node ast.Node) ast.Visitor {
|
||||
switch n := node.(type) {
|
||||
case *ast.CompositeLit:
|
||||
// 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)]
|
||||
// can be simplified to: s[a:]
|
||||
// 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
|
||||
// - if dot imports are present, we cannot be certain that an
|
||||
// unresolved "len" identifier refers to the predefined len()
|
||||
break
|
||||
}
|
||||
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) {
|
||||
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
|
||||
removeEmptyDeclGroups(f)
|
||||
|
||||
ast.Walk(&s, f)
|
||||
var s simplifier
|
||||
ast.Walk(s, f)
|
||||
}
|
||||
|
||||
func removeEmptyDeclGroups(f *ast.File) {
|
||||
|
63
libgo/go/cmd/gofmt/testdata/slices2.golden
vendored
63
libgo/go/cmd/gofmt/testdata/slices2.golden
vendored
@ -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
|
||||
}
|
63
libgo/go/cmd/gofmt/testdata/slices2.input
vendored
63
libgo/go/cmd/gofmt/testdata/slices2.input
vendored
@ -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
|
||||
wantBlockCRC uint32
|
||||
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
|
||||
buf []byte // stores Burrows-Wheeler transformed data.
|
||||
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.
|
||||
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.blockSize = 100 * 1024 * (int(level) - '0')
|
||||
bz2.blockSize = 100 * 1000 * (level - '0')
|
||||
if bz2.blockSize > len(bz2.tt) {
|
||||
bz2.tt = make([]uint32, bz2.blockSize)
|
||||
}
|
||||
@ -294,7 +293,7 @@ func (bz2 *reader) readBlock() (err error) {
|
||||
if c >= numHuffmanTrees {
|
||||
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
|
||||
@ -319,6 +318,9 @@ func (bz2 *reader) readBlock() (err error) {
|
||||
length := br.ReadBits(5)
|
||||
for j := range lengths {
|
||||
for {
|
||||
if length < 1 || length > 20 {
|
||||
return StructuralError("Huffman length out of range")
|
||||
}
|
||||
if !br.ReadBit() {
|
||||
break
|
||||
}
|
||||
@ -328,9 +330,6 @@ func (bz2 *reader) readBlock() (err error) {
|
||||
length++
|
||||
}
|
||||
}
|
||||
if length < 0 || length > 20 {
|
||||
return StructuralError("Huffman length out of range")
|
||||
}
|
||||
lengths[j] = uint8(length)
|
||||
}
|
||||
huffmanTrees[i], err = newHuffmanTree(lengths)
|
||||
@ -400,7 +399,7 @@ func (bz2 *reader) readBlock() (err error) {
|
||||
return StructuralError("repeats past end of block")
|
||||
}
|
||||
for i := 0; i < repeat; i++ {
|
||||
b := byte(mtf.First())
|
||||
b := mtf.First()
|
||||
bz2.tt[bufIndex] = uint32(b)
|
||||
bz2.c[b]++
|
||||
bufIndex++
|
||||
@ -421,7 +420,7 @@ func (bz2 *reader) readBlock() (err error) {
|
||||
// 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
|
||||
// line.
|
||||
b := byte(mtf.Decode(int(v - 1)))
|
||||
b := mtf.Decode(int(v - 1))
|
||||
if bufIndex >= bz2.blockSize {
|
||||
return StructuralError("data exceeds block size")
|
||||
}
|
||||
|
@ -6,193 +6,221 @@ package bzip2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBitReader(t *testing.T) {
|
||||
buf := bytes.NewReader([]byte{0xaa})
|
||||
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)
|
||||
func mustDecodeHex(s string) []byte {
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic("readerFromHex: bad input")
|
||||
panic(err)
|
||||
}
|
||||
return bytes.NewReader(data)
|
||||
return b
|
||||
}
|
||||
|
||||
func decompressHex(s string) (out []byte, err error) {
|
||||
r := NewReader(readerFromHex(s))
|
||||
return ioutil.ReadAll(r)
|
||||
}
|
||||
|
||||
func TestHelloWorldBZ2(t *testing.T) {
|
||||
out, err := decompressHex(helloWorldBZ2Hex)
|
||||
func mustLoadFile(f string) []byte {
|
||||
b, err := ioutil.ReadFile(f)
|
||||
if err != nil {
|
||||
t.Errorf("error from Read: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(helloWorld, out) {
|
||||
t.Errorf("got %x, want %x", out, helloWorld)
|
||||
panic(err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestConcat(t *testing.T) {
|
||||
out, err := decompressHex(helloWorldBZ2Hex + helloWorldBZ2Hex)
|
||||
if err != nil {
|
||||
t.Errorf("error from Read: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
hello2 := bytes.Repeat(helloWorld, 2)
|
||||
if !bytes.Equal(hello2, out) {
|
||||
t.Errorf("got %x, want %x", out, hello2)
|
||||
func trim(b []byte) string {
|
||||
const limit = 1024
|
||||
if len(b) < limit {
|
||||
return fmt.Sprintf("%q", b)
|
||||
}
|
||||
return fmt.Sprintf("%q...", b[:limit])
|
||||
}
|
||||
|
||||
func testZeros(t *testing.T, inHex string, n int) {
|
||||
out, err := decompressHex(inHex)
|
||||
if err != nil {
|
||||
t.Errorf("error from Read: %s", err)
|
||||
return
|
||||
}
|
||||
func TestReader(t *testing.T) {
|
||||
var vectors = []struct {
|
||||
desc string
|
||||
input []byte
|
||||
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) {
|
||||
allZeros := true
|
||||
for _, b := range out {
|
||||
if b != 0 {
|
||||
allZeros = false
|
||||
break
|
||||
if fail := bool(err != nil); fail != v.fail {
|
||||
if fail {
|
||||
t.Errorf("test %d (%s), unexpected failure: %v", i, v.desc, err)
|
||||
} else {
|
||||
t.Errorf("test %d (%s), unexpected success", i, v.desc)
|
||||
}
|
||||
}
|
||||
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) {
|
||||
testZeros(t, thirtyTwoZerosBZ2Hex, 32)
|
||||
}
|
||||
|
||||
func Test1MBZeros(t *testing.T) {
|
||||
testZeros(t, oneMBZerosBZ2Hex, 1024*1024)
|
||||
}
|
||||
|
||||
func testRandomData(t *testing.T, compressedHex, uncompressedHex string) {
|
||||
out, err := decompressHex(compressedHex)
|
||||
if err != nil {
|
||||
t.Errorf("error from Read: %s", err)
|
||||
return
|
||||
func TestBitReader(t *testing.T) {
|
||||
var vectors = []struct {
|
||||
nbits uint // Number of bits to read
|
||||
value int // Expected output value (0 for error)
|
||||
fail bool // Expected operation failure?
|
||||
}{
|
||||
{nbits: 1, value: 1},
|
||||
{nbits: 1, value: 0},
|
||||
{nbits: 1, value: 1},
|
||||
{nbits: 5, value: 11},
|
||||
{nbits: 32, value: 0x12345678},
|
||||
{nbits: 15, value: 14495},
|
||||
{nbits: 3, value: 6},
|
||||
{nbits: 6, value: 13},
|
||||
{nbits: 1, fail: true},
|
||||
}
|
||||
|
||||
expected, _ := hex.DecodeString(uncompressedHex)
|
||||
|
||||
if !bytes.Equal(out, expected) {
|
||||
t.Errorf("incorrect result\ngot: %x\nwant: %x", out, expected)
|
||||
rd := bytes.NewReader([]byte{0xab, 0x12, 0x34, 0x56, 0x78, 0x71, 0x3f, 0x8d})
|
||||
br := newBitReader(rd)
|
||||
for i, v := range vectors {
|
||||
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) {
|
||||
testRandomData(t, randBZ2Hex, randHex)
|
||||
}
|
||||
|
||||
func TestRandomData2(t *testing.T) {
|
||||
// This test involves several repeated bytes in the output, but they
|
||||
// should trigger RLE decoding.
|
||||
testRandomData(t, rand2BZ2Hex, rand2Hex)
|
||||
}
|
||||
|
||||
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
|
||||
func TestMTF(t *testing.T) {
|
||||
var vectors = []struct {
|
||||
idx int // Input index
|
||||
sym uint8 // Expected output symbol
|
||||
}{
|
||||
{idx: 1, sym: 1}, // [1 0 2 3 4]
|
||||
{idx: 0, sym: 1}, // [1 0 2 3 4]
|
||||
{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]
|
||||
}
|
||||
|
||||
expected := make([]byte, 1024*1024)
|
||||
|
||||
for i := range expected {
|
||||
expected[i] = byte(i)
|
||||
}
|
||||
|
||||
if !bytes.Equal(out, expected) {
|
||||
t.Error("incorrect result")
|
||||
mtf := newMTFDecoderWithRange(5)
|
||||
for i, v := range vectors {
|
||||
sym := mtf.Decode(v.idx)
|
||||
t.Log(mtf)
|
||||
if sym != v.sym {
|
||||
t.Errorf("test %d, symbol mismatch: Decode(%d) = %d, want %d", i, v.idx, sym, v.sym)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const helloWorldBZ2Hex = "425a68393141592653594eece83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb9229c28482776741b0"
|
||||
|
||||
var helloWorld = []byte("hello world\n")
|
||||
|
||||
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 (
|
||||
digits = mustLoadFile("testdata/e.txt.bz2")
|
||||
twain = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.bz2")
|
||||
random = mustLoadFile("testdata/random.data.bz2")
|
||||
)
|
||||
|
||||
var testfiles = []string{
|
||||
// Digits is the digits of the irrational number e. Its decimal representation
|
||||
// does not repeat, but there are only 10 possible digits, so it should be
|
||||
// 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])
|
||||
func benchmarkDecode(b *testing.B, compressed []byte) {
|
||||
// Determine the uncompressed size of testfile.
|
||||
uncompressedSize, err := io.Copy(ioutil.Discard, NewReader(bytes.NewReader(compressed)))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.SetBytes(int64(len(compressed)))
|
||||
|
||||
b.SetBytes(uncompressedSize)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
r := bytes.NewReader(compressed)
|
||||
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 BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) }
|
||||
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.
BIN
libgo/go/compress/bzip2/testdata/fail-issue5747.bz2
vendored
Normal file
BIN
libgo/go/compress/bzip2/testdata/fail-issue5747.bz2
vendored
Normal file
Binary file not shown.
BIN
libgo/go/compress/bzip2/testdata/pass-random1.bin
vendored
Normal file
BIN
libgo/go/compress/bzip2/testdata/pass-random1.bin
vendored
Normal file
Binary file not shown.
BIN
libgo/go/compress/bzip2/testdata/pass-random1.bz2
vendored
Normal file
BIN
libgo/go/compress/bzip2/testdata/pass-random1.bz2
vendored
Normal file
Binary file not shown.
1
libgo/go/compress/bzip2/testdata/pass-random2.bin
vendored
Normal file
1
libgo/go/compress/bzip2/testdata/pass-random2.bin
vendored
Normal file
@ -0,0 +1 @@
|
||||
’Õe&¬DJJ¯Š9d¬ E
CÖÏ#;Ð23ôº’øqžl*+Ôõø<C3B5>°~Í
££;&4ƒÛ›,‡†cc¾5Ñs5º
|
BIN
libgo/go/compress/bzip2/testdata/pass-random2.bz2
vendored
Normal file
BIN
libgo/go/compress/bzip2/testdata/pass-random2.bz2
vendored
Normal file
Binary file not shown.
BIN
libgo/go/compress/bzip2/testdata/pass-sawtooth.bz2
vendored
Normal file
BIN
libgo/go/compress/bzip2/testdata/pass-sawtooth.bz2
vendored
Normal file
Binary file not shown.
BIN
libgo/go/compress/bzip2/testdata/random.data.bz2
vendored
Normal file
BIN
libgo/go/compress/bzip2/testdata/random.data.bz2
vendored
Normal file
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…
x
Reference in New Issue
Block a user