runtime: Remove now unnecessary pad field from ParFor.

It is not needed due to the removal of the ctx field.
    
    Reviewed-on: https://go-review.googlesource.com/16525

From-SVN: r229616
This commit is contained in:
Ian Lance Taylor 2015-10-31 00:59:47 +00:00
parent 725e1be340
commit af146490bb
1007 changed files with 86529 additions and 30520 deletions

View file

@ -1,4 +1,4 @@
16f69a4007a1903da4055a496882b514e05f45f3
4b6b496579225cdd897130f6d6fd18ecb100bf99
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View file

@ -1,4 +1,4 @@
883bc6ed0ea815293fe6309d66f967ea60630e87
bb03defe933c89fee44be675d7aa0fbd893ced30
The first line of this file holds the git revision number of the
last merge done from the master library sources.

View file

@ -233,12 +233,15 @@ toolexeclibgogodir = $(toolexeclibgodir)/go
toolexeclibgogo_DATA = \
go/ast.gox \
go/build.gox \
go/constant.gox \
go/doc.gox \
go/format.gox \
go/importer.gox \
go/parser.gox \
go/printer.gox \
go/scanner.gox \
go/token.gox
go/token.gox \
go/types.gox
toolexeclibgohashdir = $(toolexeclibgodir)/hash
@ -292,7 +295,8 @@ toolexeclibgomath_DATA = \
toolexeclibgomimedir = $(toolexeclibgodir)/mime
toolexeclibgomime_DATA = \
mime/multipart.gox
mime/multipart.gox \
mime/quotedprintable.gox
toolexeclibgonetdir = $(toolexeclibgodir)/net
@ -676,46 +680,74 @@ go_math_files = \
go/math/tanh.go \
go/math/unsafe.go
if LIBGO_IS_OPENBSD
go_mime_type_file = go/mime/type_openbsd.go
else
if LIBGO_IS_FREEBSD
go_mime_type_file = go/mime/type_freebsd.go
else
if LIBGO_IS_DRAGONFLY
go_mime_type_file = go/mime/type_dragonfly.go
else
go_mime_type_file =
endif
endif
endif
go_mime_files = \
go/mime/encodedword.go \
go/mime/grammar.go \
go/mime/mediatype.go \
go/mime/type.go \
go/mime/type_unix.go
go/mime/type_unix.go \
$(go_mime_type_file)
if LIBGO_IS_LINUX
go_net_cgo_file = go/net/cgo_linux.go
go_net_sock_file = go/net/sock_linux.go
go_net_sockopt_file = go/net/sockopt_linux.go
go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_socknew.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else
if LIBGO_IS_IRIX
go_net_cgo_file = go/net/cgo_linux.go
go_net_sock_file = go/net/sock_linux.go
go_net_sockopt_file = go/net/sockopt_linux.go
go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_socknew.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else
if LIBGO_IS_SOLARIS
go_net_cgo_file = go/net/cgo_linux.go
go_net_cgo_file = go/net/cgo_solaris.go
go_net_sock_file = go/net/sock_stub.go
go_net_sockopt_file = go/net/sockopt_solaris.go
go_net_sockoptip_file = go/net/sockoptip_stub.go
go_net_cgo_sock_file = go/net/cgo_socknew.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else
if LIBGO_IS_FREEBSD
go_net_cgo_file = go/net/cgo_bsd.go
go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go
go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_sockold.go
go_net_cgo_res_file = go/net/cgo_resold.go
else
if LIBGO_IS_NETBSD
go_net_cgo_file = go/net/cgo_netbsd.go
go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go
go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_sockold.go
go_net_cgo_res_file = go/net/cgo_resnew.go
else
go_net_cgo_file = go/net/cgo_bsd.go
go_net_sock_file = go/net/sock_bsd.go
go_net_sockopt_file = go/net/sockopt_bsd.go
go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
go_net_cgo_sock_file = go/net/cgo_sockold.go
go_net_cgo_res_file = go/net/cgo_resold.go
endif
endif
endif
@ -731,10 +763,14 @@ else
if LIBGO_IS_DRAGONFLY
go_net_sendfile_file = go/net/sendfile_dragonfly.go
else
if LIBGO_IS_SOLARIS
go_net_sendfile_file = go/net/sendfile_solaris.go
else
go_net_sendfile_file = go/net/sendfile_stub.go
endif
endif
endif
endif
if LIBGO_IS_LINUX
go_net_interface_file = go/net/interface_linux.go
@ -775,15 +811,22 @@ endif
endif
go_net_common_files = \
go/net/addrselect.go \
$(go_net_cloexec_file) \
go/net/conf.go \
go/net/dial.go \
go/net/dnsclient.go \
go/net/dnsclient_unix.go \
go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \
go/net/fd_mutex.go \
go/net/fd_posix.go \
go/net/fd_unix.go \
go/net/file.go \
go/net/file_unix.go \
go/net/hook.go \
go/net/hook_cloexec.go \
go/net/hook_unix.go \
go/net/hosts.go \
go/net/interface.go \
$(go_net_interface_file) \
@ -796,6 +839,7 @@ go_net_common_files = \
go/net/lookup_unix.go \
go/net/mac.go \
go/net/net.go \
go/net/nss.go \
go/net/parse.go \
go/net/pipe.go \
go/net/fd_poll_runtime.go \
@ -803,7 +847,6 @@ go_net_common_files = \
go/net/port_unix.go \
go/net/race0.go \
$(go_net_sendfile_file) \
go/net/singleflight.go \
go/net/sock_posix.go \
$(go_net_sock_file) \
go/net/sockopt_posix.go \
@ -821,6 +864,8 @@ go_net_common_files = \
go_net_files = \
go/net/cgo_unix.go \
$(go_net_cgo_file) \
$(go_net_cgo_res_file) \
$(go_net_cgo_sock_file) \
$(go_net_common_files)
go_netgo_files = \
@ -919,6 +964,32 @@ else
go_os_pipe_file = go/os/pipe_bsd.go
endif
if LIBGO_IS_DARWIN
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_DRAGONFLY
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_FREEBSD
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_NETBSD
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_OPENBSD
go_os_sticky_file = go/os/sticky_bsd.go
else
if LIBGO_IS_SOLARIS
go_os_sticky_file = go/os/sticky_bsd.go
else
go_os_sticky_file = go/os/sticky_notbsd.go
endif
endif
endif
endif
endif
endif
go_os_files = \
$(go_os_dir_file) \
go/os/dir.go \
@ -939,6 +1010,7 @@ go_os_files = \
$(go_os_pipe_file) \
go/os/proc.go \
$(go_os_stat_file) \
$(go_os_sticky_file) \
go/os/str.go \
$(go_os_sys_file) \
$(go_os_cloexec_file) \
@ -959,6 +1031,7 @@ go_reflect_makefunc_c_file = \
go/reflect/makefunc_ffi_c.c
go_regexp_files = \
go/regexp/backtrack.go \
go/regexp/exec.go \
go/regexp/onepass.go \
go/regexp/regexp.go
@ -974,7 +1047,6 @@ go_runtime_files = \
go/runtime/error.go \
go/runtime/extern.go \
go/runtime/mem.go \
go/runtime/softfloat64.go \
version.go
version.go: s-version; @true
@ -1012,6 +1084,7 @@ go_strconv_files = \
go/strconv/atof.go \
go/strconv/atoi.go \
go/strconv/decimal.go \
go/strconv/doc.go \
go/strconv/extfloat.go \
go/strconv/ftoa.go \
go/strconv/isprint.go \
@ -1019,6 +1092,7 @@ go_strconv_files = \
go/strconv/quote.go
go_strings_files = \
go/strings/compare.go \
go/strings/reader.go \
go/strings/replace.go \
go/strings/search.go \
@ -1048,6 +1122,7 @@ endif
endif
go_log_syslog_files = \
go/log/syslog/doc.go \
go/log/syslog/syslog.go \
$(go_syslog_file)
go_syslog_c_files = \
@ -1186,6 +1261,7 @@ crypto_rand_file =
endif
go_crypto_rand_files = \
go/crypto/rand/eagain.go \
go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go \
$(crypto_rand_file) \
@ -1222,6 +1298,37 @@ go_crypto_tls_files = \
go/crypto/tls/prf.go \
go/crypto/tls/ticket.go \
go/crypto/tls/tls.go
if LIBGO_IS_LINUX
go_crypto_x509_root_file = go/crypto/x509/root_linux.go
else
if LIBGO_IS_SOLARIS
go_crypto_x509_root_file = go/crypto/x509/root_solaris.go
else
if LIBGO_IS_DRAGONFLY
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_FREEBSD
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_NETBSD
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_OPENBSD
go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
else
if LIBGO_IS_DARWIN
go_crypto_x509_root_file = go/crypto/x509/root_darwin.go
else
go_crypto_x509_root_file =
endif
endif
endif
endif
endif
endif
endif
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
go/crypto/x509/pem_decrypt.go \
@ -1229,6 +1336,7 @@ go_crypto_x509_files = \
go/crypto/x509/pkcs8.go \
go/crypto/x509/root.go \
go/crypto/x509/root_unix.go \
$(go_crypto_x509_root_file) \
go/crypto/x509/sec1.go \
go/crypto/x509/verify.go \
go/crypto/x509/x509.go
@ -1246,6 +1354,7 @@ go_database_sql_driver_files = \
go_debug_dwarf_files = \
go/debug/dwarf/buf.go \
go/debug/dwarf/class_string.go \
go/debug/dwarf/const.go \
go/debug/dwarf/entry.go \
go/debug/dwarf/line.go \
@ -1337,6 +1446,9 @@ go_go_build_files = \
go/go/build/doc.go \
go/go/build/read.go \
go/go/build/syslist.go
go_go_constant_files = \
go/go/constant/go14.go \
go/go/constant/value.go
go_go_doc_files = \
go/go/doc/comment.go \
go/go/doc/doc.go \
@ -1347,6 +1459,8 @@ go_go_doc_files = \
go/go/doc/synopsis.go
go_go_format_files = \
go/go/format/format.go
go_go_importer_files = \
go/go/importer/importer.go
go_go_parser_files = \
go/go/parser/interface.go \
go/go/parser/parser.go
@ -1360,6 +1474,47 @@ go_go_token_files = \
go/go/token/position.go \
go/go/token/serialize.go \
go/go/token/token.go
go_go_types_files = \
go/go/types/api.go \
go/go/types/assignments.go \
go/go/types/builtins.go \
go/go/types/call.go \
go/go/types/check.go \
go/go/types/conversions.go \
go/go/types/decl.go \
go/go/types/errors.go \
go/go/types/eval.go \
go/go/types/expr.go \
go/go/types/exprstring.go \
go/go/types/go12.go \
go/go/types/initorder.go \
go/go/types/labels.go \
go/go/types/lookup.go \
go/go/types/methodset.go \
go/go/types/object.go \
go/go/types/objset.go \
go/go/types/operand.go \
go/go/types/ordering.go \
go/go/types/package.go \
go/go/types/predicates.go \
go/go/types/resolver.go \
go/go/types/return.go \
go/go/types/scope.go \
go/go/types/selection.go \
go/go/types/stmt.go \
go/go/types/sizes.go \
go/go/types/type.go \
go/go/types/typestring.go \
go/go/types/typexpr.go \
go/go/types/universe.go
go_go_internal_gcimporter_files = \
go/go/internal/gcimporter/exportdata.go \
go/go/internal/gcimporter/gcimporter.go
go_go_internal_gccgoimporter_files = \
go/go/internal/gccgoimporter/gccgoinstallation.go \
go/go/internal/gccgoimporter/importer.go \
go/go/internal/gccgoimporter/parser.go
go_hash_adler32_files = \
go/hash/adler32/adler32.go
@ -1399,6 +1554,10 @@ go_image_gif_files = \
go/image/gif/reader.go \
go/image/gif/writer.go
go_image_internal_imageutil_files = \
go/image/internal/imageutil/imageutil.go \
go/image/internal/imageutil/impl.go
go_image_jpeg_files = \
go/image/jpeg/fdct.go \
go/image/jpeg/huffman.go \
@ -1416,15 +1575,46 @@ go_index_suffixarray_files = \
go/index/suffixarray/qsufsort.go \
go/index/suffixarray/suffixarray.go
go_internal_format_files = \
go/internal/format/format.go
go_internal_singleflight_files = \
go/internal/singleflight/singleflight.go
if LIBGO_IS_LINUX
internal_syscall_unix_getrandom_file = go/internal/syscall/unix/getrandom_linux.go
else
internal_syscall_unix_getrandom_file =
endif
go_internal_syscall_unix_files = \
go/internal/syscall/unix/dummy.go \
$(internal_syscall_unix_getrandom_file)
go_internal_testenv_files = \
go/internal/testenv/testenv.go
go_internal_trace_files = \
go/internal/trace/goroutines.go \
go/internal/trace/parser.go
go_io_ioutil_files = \
go/io/ioutil/ioutil.go \
go/io/ioutil/tempfile.go
go_math_big_files = \
go/math/big/accuracy_string.go \
go/math/big/arith.go \
go/math/big/arith_decl_pure.go \
go/math/big/decimal.go \
go/math/big/float.go \
go/math/big/floatconv.go \
go/math/big/ftoa.go \
go/math/big/int.go \
go/math/big/intconv.go \
go/math/big/nat.go \
go/math/big/rat.go
go/math/big/natconv.go \
go/math/big/rat.go \
go/math/big/ratconv.go \
go/math/big/roundingmode_string.go
go_math_cmplx_files = \
go/math/cmplx/abs.go \
go/math/cmplx/asin.go \
@ -1450,9 +1640,12 @@ go_math_rand_files = \
go_mime_multipart_files = \
go/mime/multipart/formdata.go \
go/mime/multipart/multipart.go \
go/mime/multipart/quotedprintable.go \
go/mime/multipart/writer.go
go_mime_quotedprintable_files = \
go/mime/quotedprintable/reader.go \
go/mime/quotedprintable/writer.go
go_net_http_files = \
go/net/http/client.go \
go/net/http/cookie.go \
@ -1504,6 +1697,23 @@ go_net_http_httputil_files = \
go_net_http_internal_files = \
go/net/http/internal/chunked.go
if LIBGO_IS_LINUX
go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
else
if LIBGO_IS_FREEBSD
go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
else
go_net_internal_socktest_sys =
endif
endif
go_net_internal_socktest_files = \
go/net/internal/socktest/switch.go \
go/net/internal/socktest/switch_posix.go \
go/net/internal/socktest/switch_unix.go \
go/net/internal/socktest/sys_unix.go \
$(go_net_internal_socktest_sys)
go_old_regexp_files = \
go/old/regexp/regexp.go
go_old_template_files = \
@ -1514,6 +1724,7 @@ go_old_template_files = \
go_os_exec_files = \
go/os/exec/exec.go \
go/os/exec/exec_posix.go \
go/os/exec/lp_unix.go
go_os_signal_files = \
@ -1565,6 +1776,7 @@ go_text_template_files = \
go/text/template/exec.go \
go/text/template/funcs.go \
go/text/template/helper.go \
go/text/template/option.go \
go/text/template/template.go
go_text_template_parse_files = \
go/text/template/parse/lex.go \
@ -1767,6 +1979,12 @@ else
syscall_creds_test_file =
endif
if LIBGO_IS_LINUX
syscall_exec_test_file = go/syscall/exec_linux_test.go go/syscall/syscall_linux_test.go
else
syscall_exec_test_file =
endif
go_base_syscall_files = \
go/syscall/env_unix.go \
go/syscall/syscall_errno.go \
@ -1810,21 +2028,14 @@ go_syscall_c_files = \
go_syscall_test_files = \
$(syscall_creds_test_file) \
$(syscall_exec_test_file) \
go/syscall/exec_unix_test.go \
go/syscall/export_test.go \
go/syscall/export_unix_test.go \
go/syscall/mmap_unix_test.go \
go/syscall/syscall_test.go \
go/syscall/syscall_unix_test.go
if LIBGO_IS_LINUX
internal_syscall_getrandom_file = go/internal/syscall/getrandom_linux.go
else
internal_syscall_getrandom_file =
endif
go_internal_syscall_files = \
go/internal/syscall/dummy.go \
$(internal_syscall_getrandom_file)
libcalls.go: s-libcalls; @true
s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files)
rm -f libcalls.go.tmp
@ -1978,12 +2189,17 @@ libgo_go_objs = \
html/template.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 \
@ -1999,10 +2215,15 @@ libgo_go_objs = \
image/color/palette.lo \
image/draw.lo \
image/gif.lo \
image/internal/imageutil.lo \
image/jpeg.lo \
image/png.lo \
index/suffixarray.lo \
internal/syscall.lo \
internal/format.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 \
@ -2010,7 +2231,9 @@ libgo_go_objs = \
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 \
@ -2121,11 +2344,11 @@ CHECK = \
$(MKDIR_P) $(@D); \
rm -f $@-testsum $@-testlog; \
if test "$(USE_DEJAGNU)" = "yes"; then \
$(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
$(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
elif test "$(GOBENCH)" != ""; then \
$(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
$(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
else \
if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
if $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
echo "PASS: $(@D)" >> $@-testlog; \
echo "PASS: $(@D)"; \
echo "PASS: $(@D)" > $@-testsum; \
@ -2910,6 +3133,15 @@ go/build/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/build/check
@go_include@ go/constant.lo.dep
go/constant.lo.dep: $(go_go_constant_files)
$(BUILDDEPS)
go/constant.lo: $(go_go_constant_files)
$(BUILDPACKAGE)
go/constant/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/constant/check
@go_include@ go/doc.lo.dep
go/doc.lo.dep: $(go_go_doc_files)
$(BUILDDEPS)
@ -2928,6 +3160,15 @@ go/format/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/format/check
@go_include@ go/importer.lo.dep
go/importer.lo.dep: $(go_go_importer_files)
$(BUILDDEPS)
go/importer.lo: $(go_go_importer_files)
$(BUILDPACKAGE)
go/importer/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/importer/check
@go_include@ go/parser.lo.dep
go/parser.lo.dep: $(go_go_parser_files)
$(BUILDDEPS)
@ -2964,6 +3205,33 @@ go/token/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/token/check
@go_include@ go/types.lo.dep
go/types.lo.dep: $(go_go_types_files)
$(BUILDDEPS)
go/types.lo: $(go_go_types_files)
$(BUILDPACKAGE)
go/types/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/types/check
@go_include@ go/internal/gcimporter.lo.dep
go/internal/gcimporter.lo.dep: $(go_go_internal_gcimporter_files)
$(BUILDDEPS)
go/internal/gcimporter.lo: $(go_go_internal_gcimporter_files)
$(BUILDPACKAGE)
go/internal/gcimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gcimporter/check
@go_include@ go/internal/gccgoimporter.lo.dep
go/internal/gccgoimporter.lo.dep: $(go_go_internal_gccgoimporter_files)
$(BUILDDEPS)
go/internal/gccgoimporter.lo: $(go_go_internal_gccgoimporter_files)
$(BUILDPACKAGE)
go/internal/gccgoimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gccgoimporter/check
@go_include@ hash/adler32.lo.dep
hash/adler32.lo.dep: $(go_hash_adler32_files)
$(BUILDDEPS)
@ -3036,6 +3304,15 @@ image/gif/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/gif/check
@go_include@ image/internal/imageutil.lo.dep
image/internal/imageutil.lo.dep: $(go_image_internal_imageutil_files)
$(BUILDDEPS)
image/internal/imageutil.lo: $(go_image_internal_imageutil_files)
$(BUILDPACKAGE)
image/internal/imageutil/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/internal/imageutil/check
@go_include@ image/jpeg.lo.dep
image/jpeg.lo.dep: $(go_image_jpeg_files)
$(BUILDDEPS)
@ -3063,6 +3340,51 @@ index/suffixarray/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: index/suffixarray/check
@go_include@ internal/format.lo.dep
internal/format.lo.dep: $(go_internal_format_files)
$(BUILDDEPS)
internal/format.lo: $(go_internal_format_files)
$(BUILDPACKAGE)
internal/format/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/format/check
@go_include@ internal/singleflight.lo.dep
internal/singleflight.lo.dep: $(go_internal_singleflight_files)
$(BUILDDEPS)
internal/singleflight.lo: $(go_internal_singleflight_files)
$(BUILDPACKAGE)
internal/singleflight/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/singleflight/check
@go_include@ internal/syscall/unix.lo.dep
internal/syscall/unix.lo.dep: $(go_internal_syscall_unix_files)
$(BUILDDEPS)
internal/syscall/unix.lo: $(go_internal_syscall_unix_files)
$(BUILDPACKAGE)
internal/syscall/unix/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/unix/check
@go_include@ internal/testenv.lo.dep
internal/testenv.lo.dep: $(go_internal_testenv_files)
$(BUILDDEPS)
internal/testenv.lo: $(go_internal_testenv_files)
$(BUILDPACKAGE)
internal/testenv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/testenv/check
@go_include@ internal/trace.lo.dep
internal/trace.lo.dep: $(go_internal_trace_files)
$(BUILDDEPS)
internal/trace.lo: $(go_internal_trace_files)
$(BUILDPACKAGE)
internal/trace/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/trace/check
@go_include@ io/ioutil.lo.dep
io/ioutil.lo.dep: $(go_io_ioutil_files)
$(BUILDDEPS)
@ -3120,6 +3442,15 @@ mime/multipart/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/multipart/check
@go_include@ mime/quotedprintable.lo.dep
mime/quotedprintable.lo.dep: $(go_mime_quotedprintable_files)
$(BUILDDEPS)
mime/quotedprintable.lo: $(go_mime_quotedprintable_files)
$(BUILDPACKAGE)
mime/quotedprintable/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/quotedprintable/check
@go_include@ net/http.lo.dep
net/http.lo.dep: $(go_net_http_files)
$(BUILDDEPS)
@ -3237,6 +3568,15 @@ net/http/pprof/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/http/pprof/check
@go_include@ net/internal/socktest.lo.dep
net/internal/socktest.lo.dep: $(go_net_internal_socktest_files)
$(BUILDDEPS)
net/internal/socktest.lo: $(go_net_internal_socktest_files)
$(BUILDPACKAGE)
net/internal/socktest/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/internal/socktest/check
@go_include@ net/rpc/jsonrpc.lo.dep
net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files)
$(BUILDDEPS)
@ -3432,15 +3772,6 @@ syscall/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: syscall/check
@go_include@ internal/syscall.lo.dep
internal/syscall.lo.dep: $(go_internal_syscall_files)
$(BUILDDEPS)
internal/syscall.lo: $(go_internal_syscall_files)
$(BUILDPACKAGE)
internal/syscall/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/check
# How to build a .gox file from a .lo file.
BUILDGOX = \
f=`echo $< | sed -e 's/.lo$$/.o/'`; \
@ -3620,10 +3951,14 @@ go/ast.gox: go/ast.lo
$(BUILDGOX)
go/build.gox: go/build.lo
$(BUILDGOX)
go/constant.gox: go/constant.lo
$(BUILDGOX)
go/doc.gox: go/doc.lo
$(BUILDGOX)
go/format.gox: go/format.lo
$(BUILDGOX)
go/importer.gox: go/importer.lo
$(BUILDGOX)
go/parser.gox: go/parser.lo
$(BUILDGOX)
go/printer.gox: go/printer.lo
@ -3632,6 +3967,13 @@ go/scanner.gox: go/scanner.lo
$(BUILDGOX)
go/token.gox: go/token.lo
$(BUILDGOX)
go/types.gox: go/types.lo
$(BUILDGOX)
go/internal/gcimporter.gox: go/internal/gcimporter.lo
$(BUILDGOX)
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
$(BUILDGOX)
hash/adler32.gox: hash/adler32.lo
$(BUILDGOX)
@ -3648,6 +3990,8 @@ image/draw.gox: image/draw.lo
$(BUILDGOX)
image/gif.gox: image/gif.lo
$(BUILDGOX)
image/internal/imageutil.gox: image/internal/imageutil.lo
$(BUILDGOX)
image/jpeg.gox: image/jpeg.lo
$(BUILDGOX)
image/png.gox: image/png.lo
@ -3659,6 +4003,17 @@ image/color/palette.gox: image/color/palette.lo
index/suffixarray.gox: index/suffixarray.lo
$(BUILDGOX)
internal/format.gox: internal/format.lo
$(BUILDGOX)
internal/singleflight.gox: internal/singleflight.lo
$(BUILDGOX)
internal/syscall/unix.gox: internal/syscall/unix.lo
$(BUILDGOX)
internal/testenv.gox: internal/testenv.lo
$(BUILDGOX)
internal/trace.gox: internal/trace.lo
$(BUILDGOX)
io/ioutil.gox: io/ioutil.lo
$(BUILDGOX)
@ -3674,6 +4029,8 @@ math/rand.gox: math/rand.lo
mime/multipart.gox: mime/multipart.lo
$(BUILDGOX)
mime/quotedprintable.gox: mime/quotedprintable.lo
$(BUILDGOX)
net/http.gox: net/http.lo
$(BUILDGOX)
@ -3704,6 +4061,9 @@ net/http/pprof.gox: net/http/pprof.lo
net/http/internal.gox: net/http/internal.lo
$(BUILDGOX)
net/internal/socktest.gox: net/internal/socktest.lo
$(BUILDGOX)
net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo
$(BUILDGOX)
@ -3733,9 +4093,6 @@ runtime/pprof.gox: runtime/pprof.lo
sync/atomic.gox: sync/atomic.lo
$(BUILDGOX)
internal/syscall.gox: internal/syscall.lo
$(BUILDGOX)
text/scanner.gox: text/scanner.lo
$(BUILDGOX)
text/tabwriter.gox: text/tabwriter.lo
@ -3830,13 +4187,17 @@ TEST_PACKAGES = \
exp/terminal/check \
html/template/check \
go/ast/check \
$(go_build_check_omitted_since_it_calls_6g) \
go/build/check \
go/constant/check \
go/doc/check \
go/format/check \
go/internal/gcimporter/check \
go/internal/gccgoimporter/check \
go/parser/check \
go/printer/check \
go/scanner/check \
go/token/check \
go/types/check \
hash/adler32/check \
hash/crc32/check \
hash/crc64/check \
@ -3846,12 +4207,15 @@ TEST_PACKAGES = \
image/jpeg/check \
image/png/check \
index/suffixarray/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \
log/syslog/check \
math/big/check \
math/cmplx/check \
math/rand/check \
mime/multipart/check \
mime/quotedprintable/check \
net/http/check \
net/http/cgi/check \
net/http/cookiejar/check \
@ -3859,6 +4223,7 @@ TEST_PACKAGES = \
net/http/httptest/check \
net/http/httputil/check \
net/http/internal/check \
net/internal/socktest/check \
net/mail/check \
net/rpc/check \
net/smtp/check \

View file

@ -196,16 +196,21 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
encoding/binary.lo encoding/csv.lo encoding/gob.lo \
encoding/hex.lo encoding/json.lo encoding/pem.lo \
encoding/xml.lo exp/proxy.lo exp/terminal.lo html/template.lo \
go/ast.lo go/build.lo go/doc.lo go/format.lo go/parser.lo \
go/printer.lo go/scanner.lo go/token.lo hash/adler32.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 \
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/jpeg.lo image/png.lo index/suffixarray.lo \
internal/syscall.lo io/ioutil.lo log/syslog.lo \
log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \
mime/multipart.lo net/http.lo net/mail.lo net/rpc.lo \
image/gif.lo image/internal/imageutil.lo image/jpeg.lo \
image/png.lo index/suffixarray.lo internal/format.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 \
@ -681,12 +686,15 @@ toolexeclibgogodir = $(toolexeclibgodir)/go
toolexeclibgogo_DATA = \
go/ast.gox \
go/build.gox \
go/constant.gox \
go/doc.gox \
go/format.gox \
go/importer.gox \
go/parser.gox \
go/printer.gox \
go/scanner.gox \
go/token.gox
go/token.gox \
go/types.gox
toolexeclibgohashdir = $(toolexeclibgodir)/hash
toolexeclibgohash_DATA = \
@ -731,7 +739,8 @@ toolexeclibgomath_DATA = \
toolexeclibgomimedir = $(toolexeclibgodir)/mime
toolexeclibgomime_DATA = \
mime/multipart.gox
mime/multipart.gox \
mime/quotedprintable.gox
toolexeclibgonetdir = $(toolexeclibgodir)/net
toolexeclibgonet_DATA = \
@ -1023,16 +1032,22 @@ go_math_files = \
go/math/tanh.go \
go/math/unsafe.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@go_mime_type_file =
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@go_mime_type_file = go/mime/type_dragonfly.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_mime_type_file = go/mime/type_freebsd.go
@LIBGO_IS_OPENBSD_TRUE@go_mime_type_file = go/mime/type_openbsd.go
go_mime_files = \
go/mime/encodedword.go \
go/mime/grammar.go \
go/mime/mediatype.go \
go/mime/type.go \
go/mime/type_unix.go
go/mime/type_unix.go \
$(go_mime_type_file)
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_netbsd.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_file = go/net/cgo_linux.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_file = go/net/cgo_solaris.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_file = go/net/cgo_linux.go
@LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
@ -1053,7 +1068,20 @@ go_mime_files = \
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_stub.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
@LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_sock_file = go/net/cgo_sockold.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_sock_file = go/net/cgo_sockold.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_sock_file = go/net/cgo_sockold.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_sock_file = go/net/cgo_socknew.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_sock_file = go/net/cgo_socknew.go
@LIBGO_IS_LINUX_TRUE@go_net_cgo_sock_file = go/net/cgo_socknew.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_res_file = go/net/cgo_resold.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_res_file = go/net/cgo_resold.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_LINUX_TRUE@go_net_cgo_res_file = go/net/cgo_resnew.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sendfile_file = go/net/sendfile_solaris.go
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_dragonfly.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go
@LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
@ -1069,15 +1097,22 @@ go_mime_files = \
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go
@LIBGO_IS_OPENBSD_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go
go_net_common_files = \
go/net/addrselect.go \
$(go_net_cloexec_file) \
go/net/conf.go \
go/net/dial.go \
go/net/dnsclient.go \
go/net/dnsclient_unix.go \
go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \
go/net/fd_mutex.go \
go/net/fd_posix.go \
go/net/fd_unix.go \
go/net/file.go \
go/net/file_unix.go \
go/net/hook.go \
go/net/hook_cloexec.go \
go/net/hook_unix.go \
go/net/hosts.go \
go/net/interface.go \
$(go_net_interface_file) \
@ -1090,6 +1125,7 @@ go_net_common_files = \
go/net/lookup_unix.go \
go/net/mac.go \
go/net/net.go \
go/net/nss.go \
go/net/parse.go \
go/net/pipe.go \
go/net/fd_poll_runtime.go \
@ -1097,7 +1133,6 @@ go_net_common_files = \
go/net/port_unix.go \
go/net/race0.go \
$(go_net_sendfile_file) \
go/net/singleflight.go \
go/net/sock_posix.go \
$(go_net_sock_file) \
go/net/sockopt_posix.go \
@ -1115,6 +1150,8 @@ go_net_common_files = \
go_net_files = \
go/net/cgo_unix.go \
$(go_net_cgo_file) \
$(go_net_cgo_res_file) \
$(go_net_cgo_sock_file) \
$(go_net_common_files)
go_netgo_files = \
@ -1147,6 +1184,13 @@ go_netgo_files = \
@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atim.go
@LIBGO_IS_LINUX_FALSE@go_os_pipe_file = go/os/pipe_bsd.go
@LIBGO_IS_LINUX_TRUE@go_os_pipe_file = go/os/pipe_linux.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_sticky_file = go/os/sticky_notbsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_NETBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
@LIBGO_IS_DARWIN_TRUE@go_os_sticky_file = go/os/sticky_bsd.go
go_os_files = \
$(go_os_dir_file) \
go/os/dir.go \
@ -1167,6 +1211,7 @@ go_os_files = \
$(go_os_pipe_file) \
go/os/proc.go \
$(go_os_stat_file) \
$(go_os_sticky_file) \
go/os/str.go \
$(go_os_sys_file) \
$(go_os_cloexec_file) \
@ -1188,6 +1233,7 @@ go_reflect_makefunc_c_file = \
go/reflect/makefunc_ffi_c.c
go_regexp_files = \
go/regexp/backtrack.go \
go/regexp/exec.go \
go/regexp/onepass.go \
go/regexp/regexp.go
@ -1203,7 +1249,6 @@ go_runtime_files = \
go/runtime/error.go \
go/runtime/extern.go \
go/runtime/mem.go \
go/runtime/softfloat64.go \
version.go
noinst_DATA = zstdpkglist.go
@ -1216,6 +1261,7 @@ go_strconv_files = \
go/strconv/atof.go \
go/strconv/atoi.go \
go/strconv/decimal.go \
go/strconv/doc.go \
go/strconv/extfloat.go \
go/strconv/ftoa.go \
go/strconv/isprint.go \
@ -1223,6 +1269,7 @@ go_strconv_files = \
go/strconv/quote.go
go_strings_files = \
go/strings/compare.go \
go/strings/reader.go \
go/strings/replace.go \
go/strings/search.go \
@ -1246,6 +1293,7 @@ go_sync_files = \
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_syslog_file = go/log/syslog/syslog_libc.go
@LIBGO_IS_SOLARIS_TRUE@go_syslog_file = go/log/syslog/syslog_libc.go
go_log_syslog_files = \
go/log/syslog/doc.go \
go/log/syslog/syslog.go \
$(go_syslog_file)
@ -1375,6 +1423,7 @@ go_crypto_md5_files = \
@LIBGO_IS_LINUX_FALSE@crypto_rand_file =
@LIBGO_IS_LINUX_TRUE@crypto_rand_file = go/crypto/rand/rand_linux.go
go_crypto_rand_files = \
go/crypto/rand/eagain.go \
go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go \
$(crypto_rand_file) \
@ -1418,6 +1467,14 @@ go_crypto_tls_files = \
go/crypto/tls/ticket.go \
go/crypto/tls/tls.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file =
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_darwin.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_crypto_x509_root_file = go/crypto/x509/root_bsd.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_crypto_x509_root_file = go/crypto/x509/root_solaris.go
@LIBGO_IS_LINUX_TRUE@go_crypto_x509_root_file = go/crypto/x509/root_linux.go
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
go/crypto/x509/pem_decrypt.go \
@ -1425,6 +1482,7 @@ go_crypto_x509_files = \
go/crypto/x509/pkcs8.go \
go/crypto/x509/root.go \
go/crypto/x509/root_unix.go \
$(go_crypto_x509_root_file) \
go/crypto/x509/sec1.go \
go/crypto/x509/verify.go \
go/crypto/x509/x509.go
@ -1442,6 +1500,7 @@ go_database_sql_driver_files = \
go_debug_dwarf_files = \
go/debug/dwarf/buf.go \
go/debug/dwarf/class_string.go \
go/debug/dwarf/const.go \
go/debug/dwarf/entry.go \
go/debug/dwarf/line.go \
@ -1551,6 +1610,10 @@ go_go_build_files = \
go/go/build/read.go \
go/go/build/syslist.go
go_go_constant_files = \
go/go/constant/go14.go \
go/go/constant/value.go
go_go_doc_files = \
go/go/doc/comment.go \
go/go/doc/doc.go \
@ -1563,6 +1626,9 @@ go_go_doc_files = \
go_go_format_files = \
go/go/format/format.go
go_go_importer_files = \
go/go/importer/importer.go
go_go_parser_files = \
go/go/parser/interface.go \
go/go/parser/parser.go
@ -1580,6 +1646,49 @@ go_go_token_files = \
go/go/token/serialize.go \
go/go/token/token.go
go_go_types_files = \
go/go/types/api.go \
go/go/types/assignments.go \
go/go/types/builtins.go \
go/go/types/call.go \
go/go/types/check.go \
go/go/types/conversions.go \
go/go/types/decl.go \
go/go/types/errors.go \
go/go/types/eval.go \
go/go/types/expr.go \
go/go/types/exprstring.go \
go/go/types/go12.go \
go/go/types/initorder.go \
go/go/types/labels.go \
go/go/types/lookup.go \
go/go/types/methodset.go \
go/go/types/object.go \
go/go/types/objset.go \
go/go/types/operand.go \
go/go/types/ordering.go \
go/go/types/package.go \
go/go/types/predicates.go \
go/go/types/resolver.go \
go/go/types/return.go \
go/go/types/scope.go \
go/go/types/selection.go \
go/go/types/stmt.go \
go/go/types/sizes.go \
go/go/types/type.go \
go/go/types/typestring.go \
go/go/types/typexpr.go \
go/go/types/universe.go
go_go_internal_gcimporter_files = \
go/go/internal/gcimporter/exportdata.go \
go/go/internal/gcimporter/gcimporter.go
go_go_internal_gccgoimporter_files = \
go/go/internal/gccgoimporter/gccgoinstallation.go \
go/go/internal/gccgoimporter/importer.go \
go/go/internal/gccgoimporter/parser.go
go_hash_adler32_files = \
go/hash/adler32/adler32.go
@ -1621,6 +1730,10 @@ go_image_gif_files = \
go/image/gif/reader.go \
go/image/gif/writer.go
go_image_internal_imageutil_files = \
go/image/internal/imageutil/imageutil.go \
go/image/internal/imageutil/impl.go
go_image_jpeg_files = \
go/image/jpeg/fdct.go \
go/image/jpeg/huffman.go \
@ -1638,15 +1751,44 @@ go_index_suffixarray_files = \
go/index/suffixarray/qsufsort.go \
go/index/suffixarray/suffixarray.go
go_internal_format_files = \
go/internal/format/format.go
go_internal_singleflight_files = \
go/internal/singleflight/singleflight.go
@LIBGO_IS_LINUX_FALSE@internal_syscall_unix_getrandom_file =
@LIBGO_IS_LINUX_TRUE@internal_syscall_unix_getrandom_file = go/internal/syscall/unix/getrandom_linux.go
go_internal_syscall_unix_files = \
go/internal/syscall/unix/dummy.go \
$(internal_syscall_unix_getrandom_file)
go_internal_testenv_files = \
go/internal/testenv/testenv.go
go_internal_trace_files = \
go/internal/trace/goroutines.go \
go/internal/trace/parser.go
go_io_ioutil_files = \
go/io/ioutil/ioutil.go \
go/io/ioutil/tempfile.go
go_math_big_files = \
go/math/big/accuracy_string.go \
go/math/big/arith.go \
go/math/big/arith_decl_pure.go \
go/math/big/decimal.go \
go/math/big/float.go \
go/math/big/floatconv.go \
go/math/big/ftoa.go \
go/math/big/int.go \
go/math/big/intconv.go \
go/math/big/nat.go \
go/math/big/rat.go
go/math/big/natconv.go \
go/math/big/rat.go \
go/math/big/ratconv.go \
go/math/big/roundingmode_string.go
go_math_cmplx_files = \
go/math/cmplx/abs.go \
@ -1674,9 +1816,12 @@ go_math_rand_files = \
go_mime_multipart_files = \
go/mime/multipart/formdata.go \
go/mime/multipart/multipart.go \
go/mime/multipart/quotedprintable.go \
go/mime/multipart/writer.go
go_mime_quotedprintable_files = \
go/mime/quotedprintable/reader.go \
go/mime/quotedprintable/writer.go
go_net_http_files = \
go/net/http/client.go \
go/net/http/cookie.go \
@ -1738,6 +1883,16 @@ go_net_http_httputil_files = \
go_net_http_internal_files = \
go/net/http/internal/chunked.go
@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_internal_socktest_sys =
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
@LIBGO_IS_LINUX_TRUE@go_net_internal_socktest_sys = go/net/internal/socktest/sys_cloexec.go
go_net_internal_socktest_files = \
go/net/internal/socktest/switch.go \
go/net/internal/socktest/switch_posix.go \
go/net/internal/socktest/switch_unix.go \
go/net/internal/socktest/sys_unix.go \
$(go_net_internal_socktest_sys)
go_old_regexp_files = \
go/old/regexp/regexp.go
@ -1749,6 +1904,7 @@ go_old_template_files = \
go_os_exec_files = \
go/os/exec/exec.go \
go/os/exec/exec_posix.go \
go/os/exec/lp_unix.go
go_os_signal_files = \
@ -1798,6 +1954,7 @@ go_text_template_files = \
go/text/template/exec.go \
go/text/template/funcs.go \
go/text/template/helper.go \
go/text/template/option.go \
go/text/template/template.go
go_text_template_parse_files = \
@ -1917,6 +2074,8 @@ go_unicode_utf8_files = \
# Test files.
@LIBGO_IS_LINUX_TRUE@syscall_creds_test_file = go/syscall/creds_test.go
@LIBGO_IS_LINUX_FALSE@syscall_exec_test_file =
@LIBGO_IS_LINUX_TRUE@syscall_exec_test_file = go/syscall/exec_linux_test.go go/syscall/syscall_linux_test.go
go_base_syscall_files = \
go/syscall/env_unix.go \
go/syscall/syscall_errno.go \
@ -1961,17 +2120,14 @@ go_syscall_c_files = \
go_syscall_test_files = \
$(syscall_creds_test_file) \
$(syscall_exec_test_file) \
go/syscall/exec_unix_test.go \
go/syscall/export_test.go \
go/syscall/export_unix_test.go \
go/syscall/mmap_unix_test.go \
go/syscall/syscall_test.go \
go/syscall/syscall_unix_test.go
@LIBGO_IS_LINUX_FALSE@internal_syscall_getrandom_file =
@LIBGO_IS_LINUX_TRUE@internal_syscall_getrandom_file = go/internal/syscall/getrandom_linux.go
go_internal_syscall_files = \
go/internal/syscall/dummy.go \
$(internal_syscall_getrandom_file)
@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo =
# os_lib_inotify_lo = os/inotify.lo
@ -2064,12 +2220,17 @@ libgo_go_objs = \
html/template.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 \
@ -2085,10 +2246,15 @@ libgo_go_objs = \
image/color/palette.lo \
image/draw.lo \
image/gif.lo \
image/internal/imageutil.lo \
image/jpeg.lo \
image/png.lo \
index/suffixarray.lo \
internal/syscall.lo \
internal/format.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 \
@ -2096,7 +2262,9 @@ libgo_go_objs = \
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 \
@ -2203,11 +2371,11 @@ CHECK = \
$(MKDIR_P) $(@D); \
rm -f $@-testsum $@-testlog; \
if test "$(USE_DEJAGNU)" = "yes"; then \
$(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
$(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
elif test "$(GOBENCH)" != ""; then \
$(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
$(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \
else \
if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
if $(SHELL) $(srcdir)/testsuite/gotest --goarch=$(GOARCH) --goos=$(GOOS) --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \
echo "PASS: $(@D)" >> $@-testlog; \
echo "PASS: $(@D)"; \
echo "PASS: $(@D)" > $@-testsum; \
@ -2320,13 +2488,17 @@ TEST_PACKAGES = \
exp/terminal/check \
html/template/check \
go/ast/check \
$(go_build_check_omitted_since_it_calls_6g) \
go/build/check \
go/constant/check \
go/doc/check \
go/format/check \
go/internal/gcimporter/check \
go/internal/gccgoimporter/check \
go/parser/check \
go/printer/check \
go/scanner/check \
go/token/check \
go/types/check \
hash/adler32/check \
hash/crc32/check \
hash/crc64/check \
@ -2336,12 +2508,15 @@ TEST_PACKAGES = \
image/jpeg/check \
image/png/check \
index/suffixarray/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \
log/syslog/check \
math/big/check \
math/cmplx/check \
math/rand/check \
mime/multipart/check \
mime/quotedprintable/check \
net/http/check \
net/http/cgi/check \
net/http/cookiejar/check \
@ -2349,6 +2524,7 @@ TEST_PACKAGES = \
net/http/httptest/check \
net/http/httputil/check \
net/http/internal/check \
net/internal/socktest/check \
net/mail/check \
net/rpc/check \
net/smtp/check \
@ -5357,6 +5533,15 @@ go/build/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/build/check
@go_include@ go/constant.lo.dep
go/constant.lo.dep: $(go_go_constant_files)
$(BUILDDEPS)
go/constant.lo: $(go_go_constant_files)
$(BUILDPACKAGE)
go/constant/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/constant/check
@go_include@ go/doc.lo.dep
go/doc.lo.dep: $(go_go_doc_files)
$(BUILDDEPS)
@ -5375,6 +5560,15 @@ go/format/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/format/check
@go_include@ go/importer.lo.dep
go/importer.lo.dep: $(go_go_importer_files)
$(BUILDDEPS)
go/importer.lo: $(go_go_importer_files)
$(BUILDPACKAGE)
go/importer/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/importer/check
@go_include@ go/parser.lo.dep
go/parser.lo.dep: $(go_go_parser_files)
$(BUILDDEPS)
@ -5411,6 +5605,33 @@ go/token/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/token/check
@go_include@ go/types.lo.dep
go/types.lo.dep: $(go_go_types_files)
$(BUILDDEPS)
go/types.lo: $(go_go_types_files)
$(BUILDPACKAGE)
go/types/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/types/check
@go_include@ go/internal/gcimporter.lo.dep
go/internal/gcimporter.lo.dep: $(go_go_internal_gcimporter_files)
$(BUILDDEPS)
go/internal/gcimporter.lo: $(go_go_internal_gcimporter_files)
$(BUILDPACKAGE)
go/internal/gcimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gcimporter/check
@go_include@ go/internal/gccgoimporter.lo.dep
go/internal/gccgoimporter.lo.dep: $(go_go_internal_gccgoimporter_files)
$(BUILDDEPS)
go/internal/gccgoimporter.lo: $(go_go_internal_gccgoimporter_files)
$(BUILDPACKAGE)
go/internal/gccgoimporter/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/internal/gccgoimporter/check
@go_include@ hash/adler32.lo.dep
hash/adler32.lo.dep: $(go_hash_adler32_files)
$(BUILDDEPS)
@ -5483,6 +5704,15 @@ image/gif/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/gif/check
@go_include@ image/internal/imageutil.lo.dep
image/internal/imageutil.lo.dep: $(go_image_internal_imageutil_files)
$(BUILDDEPS)
image/internal/imageutil.lo: $(go_image_internal_imageutil_files)
$(BUILDPACKAGE)
image/internal/imageutil/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/internal/imageutil/check
@go_include@ image/jpeg.lo.dep
image/jpeg.lo.dep: $(go_image_jpeg_files)
$(BUILDDEPS)
@ -5510,6 +5740,51 @@ index/suffixarray/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: index/suffixarray/check
@go_include@ internal/format.lo.dep
internal/format.lo.dep: $(go_internal_format_files)
$(BUILDDEPS)
internal/format.lo: $(go_internal_format_files)
$(BUILDPACKAGE)
internal/format/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/format/check
@go_include@ internal/singleflight.lo.dep
internal/singleflight.lo.dep: $(go_internal_singleflight_files)
$(BUILDDEPS)
internal/singleflight.lo: $(go_internal_singleflight_files)
$(BUILDPACKAGE)
internal/singleflight/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/singleflight/check
@go_include@ internal/syscall/unix.lo.dep
internal/syscall/unix.lo.dep: $(go_internal_syscall_unix_files)
$(BUILDDEPS)
internal/syscall/unix.lo: $(go_internal_syscall_unix_files)
$(BUILDPACKAGE)
internal/syscall/unix/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/unix/check
@go_include@ internal/testenv.lo.dep
internal/testenv.lo.dep: $(go_internal_testenv_files)
$(BUILDDEPS)
internal/testenv.lo: $(go_internal_testenv_files)
$(BUILDPACKAGE)
internal/testenv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/testenv/check
@go_include@ internal/trace.lo.dep
internal/trace.lo.dep: $(go_internal_trace_files)
$(BUILDDEPS)
internal/trace.lo: $(go_internal_trace_files)
$(BUILDPACKAGE)
internal/trace/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/trace/check
@go_include@ io/ioutil.lo.dep
io/ioutil.lo.dep: $(go_io_ioutil_files)
$(BUILDDEPS)
@ -5567,6 +5842,15 @@ mime/multipart/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/multipart/check
@go_include@ mime/quotedprintable.lo.dep
mime/quotedprintable.lo.dep: $(go_mime_quotedprintable_files)
$(BUILDDEPS)
mime/quotedprintable.lo: $(go_mime_quotedprintable_files)
$(BUILDPACKAGE)
mime/quotedprintable/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/quotedprintable/check
@go_include@ net/http.lo.dep
net/http.lo.dep: $(go_net_http_files)
$(BUILDDEPS)
@ -5684,6 +5968,15 @@ net/http/pprof/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/http/pprof/check
@go_include@ net/internal/socktest.lo.dep
net/internal/socktest.lo.dep: $(go_net_internal_socktest_files)
$(BUILDDEPS)
net/internal/socktest.lo: $(go_net_internal_socktest_files)
$(BUILDPACKAGE)
net/internal/socktest/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/internal/socktest/check
@go_include@ net/rpc/jsonrpc.lo.dep
net/rpc/jsonrpc.lo.dep: $(go_net_rpc_jsonrpc_files)
$(BUILDDEPS)
@ -5875,15 +6168,6 @@ syscall/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: syscall/check
@go_include@ internal/syscall.lo.dep
internal/syscall.lo.dep: $(go_internal_syscall_files)
$(BUILDDEPS)
internal/syscall.lo: $(go_internal_syscall_files)
$(BUILDPACKAGE)
internal/syscall/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: internal/syscall/check
bufio.gox: bufio.lo
$(BUILDGOX)
bytes.gox: bytes.lo
@ -6058,10 +6342,14 @@ go/ast.gox: go/ast.lo
$(BUILDGOX)
go/build.gox: go/build.lo
$(BUILDGOX)
go/constant.gox: go/constant.lo
$(BUILDGOX)
go/doc.gox: go/doc.lo
$(BUILDGOX)
go/format.gox: go/format.lo
$(BUILDGOX)
go/importer.gox: go/importer.lo
$(BUILDGOX)
go/parser.gox: go/parser.lo
$(BUILDGOX)
go/printer.gox: go/printer.lo
@ -6070,6 +6358,13 @@ go/scanner.gox: go/scanner.lo
$(BUILDGOX)
go/token.gox: go/token.lo
$(BUILDGOX)
go/types.gox: go/types.lo
$(BUILDGOX)
go/internal/gcimporter.gox: go/internal/gcimporter.lo
$(BUILDGOX)
go/internal/gccgoimporter.gox: go/internal/gccgoimporter.lo
$(BUILDGOX)
hash/adler32.gox: hash/adler32.lo
$(BUILDGOX)
@ -6086,6 +6381,8 @@ image/draw.gox: image/draw.lo
$(BUILDGOX)
image/gif.gox: image/gif.lo
$(BUILDGOX)
image/internal/imageutil.gox: image/internal/imageutil.lo
$(BUILDGOX)
image/jpeg.gox: image/jpeg.lo
$(BUILDGOX)
image/png.gox: image/png.lo
@ -6097,6 +6394,17 @@ image/color/palette.gox: image/color/palette.lo
index/suffixarray.gox: index/suffixarray.lo
$(BUILDGOX)
internal/format.gox: internal/format.lo
$(BUILDGOX)
internal/singleflight.gox: internal/singleflight.lo
$(BUILDGOX)
internal/syscall/unix.gox: internal/syscall/unix.lo
$(BUILDGOX)
internal/testenv.gox: internal/testenv.lo
$(BUILDGOX)
internal/trace.gox: internal/trace.lo
$(BUILDGOX)
io/ioutil.gox: io/ioutil.lo
$(BUILDGOX)
@ -6112,6 +6420,8 @@ math/rand.gox: math/rand.lo
mime/multipart.gox: mime/multipart.lo
$(BUILDGOX)
mime/quotedprintable.gox: mime/quotedprintable.lo
$(BUILDGOX)
net/http.gox: net/http.lo
$(BUILDGOX)
@ -6142,6 +6452,9 @@ net/http/pprof.gox: net/http/pprof.lo
net/http/internal.gox: net/http/internal.lo
$(BUILDGOX)
net/internal/socktest.gox: net/internal/socktest.lo
$(BUILDGOX)
net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo
$(BUILDGOX)
@ -6171,9 +6484,6 @@ runtime/pprof.gox: runtime/pprof.lo
sync/atomic.gox: sync/atomic.lo
$(BUILDGOX)
internal/syscall.gox: internal/syscall.lo
$(BUILDGOX)
text/scanner.gox: text/scanner.lo
$(BUILDGOX)
text/tabwriter.gox: text/tabwriter.lo

View file

@ -1 +1 @@
go1.4.2
go1.5

View file

@ -139,8 +139,8 @@ func (fi headerFileInfo) Mode() (mode os.FileMode) {
}
switch fi.h.Typeflag {
case TypeLink, TypeSymlink:
// hard link, symbolic link
case TypeSymlink:
// symbolic link
mode |= os.ModeSymlink
case TypeChar:
// character device node
@ -249,6 +249,30 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
if fm&os.ModeSticky != 0 {
h.Mode |= c_ISVTX
}
// If possible, populate additional fields from OS-specific
// FileInfo fields.
if sys, ok := fi.Sys().(*Header); ok {
// This FileInfo came from a Header (not the OS). Use the
// original Header to populate all remaining fields.
h.Uid = sys.Uid
h.Gid = sys.Gid
h.Uname = sys.Uname
h.Gname = sys.Gname
h.AccessTime = sys.AccessTime
h.ChangeTime = sys.ChangeTime
if sys.Xattrs != nil {
h.Xattrs = make(map[string]string)
for k, v := range sys.Xattrs {
h.Xattrs[k] = v
}
}
if sys.Typeflag == TypeLink {
// hard link
h.Typeflag = TypeLink
h.Size = 0
h.Linkname = sys.Linkname
}
}
if sysStat != nil {
return h, sysStat(fi, h)
}

View file

@ -85,6 +85,8 @@ const (
func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
// Next advances to the next entry in the tar archive.
//
// io.EOF is returned at the end of the input.
func (tr *Reader) Next() (*Header, error) {
var hdr *Header
if tr.err == nil {
@ -108,7 +110,13 @@ func (tr *Reader) Next() (*Header, error) {
// We actually read the whole file,
// but this skips alignment padding
tr.skipUnread()
if tr.err != nil {
return nil, tr.err
}
hdr = tr.readHeader()
if hdr == nil {
return nil, tr.err
}
mergePAX(hdr, headers)
// Check for a PAX format sparse file
@ -331,7 +339,7 @@ func parsePAX(r io.Reader) (map[string]string, error) {
}
// Parse the first token as a decimal integer.
n, err := strconv.ParseInt(string(buf[:sp]), 10, 0)
if err != nil {
if err != nil || n < 5 || int64(len(buf)) < n {
return nil, ErrHeader
}
// Extract everything between the decimal and the n -1 on the
@ -461,6 +469,10 @@ func (tr *Reader) readHeader() *Header {
hdr.Uid = int(tr.octal(s.next(8)))
hdr.Gid = int(tr.octal(s.next(8)))
hdr.Size = tr.octal(s.next(12))
if hdr.Size < 0 {
tr.err = ErrHeader
return nil
}
hdr.ModTime = time.Unix(tr.octal(s.next(12)), 0)
s.next(8) // chksum
hdr.Typeflag = s.next(1)[0]
@ -785,6 +797,9 @@ func (sfr *sparseFileReader) Read(b []byte) (n int, err error) {
// Otherwise, we're at the end of the file
return 0, io.EOF
}
if sfr.tot < sfr.sp[0].offset {
return 0, io.ErrUnexpectedEOF
}
if sfr.pos < sfr.sp[0].offset {
// We're in a hole
n = sfr.readHole(b, sfr.sp[0].offset)

View file

@ -462,9 +462,14 @@ func TestParsePAXHeader(t *testing.T) {
t.Error("Buffer wasn't consumed")
}
}
badHeader := bytes.NewReader([]byte("3 somelongkey="))
if _, err := parsePAX(badHeader); err != ErrHeader {
t.Fatal("Unexpected success when parsing bad header")
badHeaderTests := [][]byte{
[]byte("3 somelongkey=\n"),
[]byte("50 tooshort=\n"),
}
for _, test := range badHeaderTests {
if _, err := parsePAX(bytes.NewReader(test)); err != ErrHeader {
t.Fatal("Unexpected success when parsing bad header")
}
}
}
@ -741,3 +746,53 @@ func TestUninitializedRead(t *testing.T) {
}
}
// Negative header size should not cause panic.
// Issues 10959 and 10960.
func TestNegativeHdrSize(t *testing.T) {
f, err := os.Open("testdata/neg-size.tar")
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := NewReader(f)
_, err = r.Next()
if err != ErrHeader {
t.Error("want ErrHeader, got", err)
}
io.Copy(ioutil.Discard, r)
}
// This used to hang in (*sparseFileReader).readHole due to missing
// verification of sparse offsets against file size.
func TestIssue10968(t *testing.T) {
f, err := os.Open("testdata/issue10968.tar")
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := NewReader(f)
_, err = r.Next()
if err != nil {
t.Fatal(err)
}
_, err = io.Copy(ioutil.Discard, r)
if err != io.ErrUnexpectedEOF {
t.Fatalf("expected %q, got %q", io.ErrUnexpectedEOF, err)
}
}
// Do not panic if there are errors in header blocks after the pax header.
// Issue 11169
func TestIssue11169(t *testing.T) {
f, err := os.Open("testdata/issue11169.tar")
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := NewReader(f)
_, err = r.Next()
if err == nil {
t.Fatal("Unexpected success")
}
}

View file

@ -147,17 +147,6 @@ func TestHeaderRoundTrip(t *testing.T) {
},
fm: 0644,
},
// hard link.
{
h: &Header{
Name: "hard.txt",
Mode: 0644 | c_ISLNK,
Size: 0,
ModTime: time.Unix(1360600916, 0),
Typeflag: TypeLink,
},
fm: 0644 | os.ModeSymlink,
},
// symbolic link.
{
h: &Header{
@ -246,6 +235,33 @@ func TestHeaderRoundTrip(t *testing.T) {
},
fm: 0600 | os.ModeSticky,
},
// hard link.
{
h: &Header{
Name: "hard.txt",
Mode: 0644 | c_ISREG,
Size: 0,
Linkname: "file.txt",
ModTime: time.Unix(1360600916, 0),
Typeflag: TypeLink,
},
fm: 0644,
},
// More information.
{
h: &Header{
Name: "info.txt",
Mode: 0600 | c_ISREG,
Size: 0,
Uid: 1000,
Gid: 1000,
ModTime: time.Unix(1360602540, 0),
Uname: "slartibartfast",
Gname: "users",
Typeflag: TypeReg,
},
fm: 0600,
},
}
for i, g := range golden {
@ -268,12 +284,37 @@ func TestHeaderRoundTrip(t *testing.T) {
if got, want := h2.Size, g.h.Size; got != want {
t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
}
if got, want := h2.Uid, g.h.Uid; got != want {
t.Errorf("i=%d: Uid: got %d, want %d", i, got, want)
}
if got, want := h2.Gid, g.h.Gid; got != want {
t.Errorf("i=%d: Gid: got %d, want %d", i, got, want)
}
if got, want := h2.Uname, g.h.Uname; got != want {
t.Errorf("i=%d: Uname: got %q, want %q", i, got, want)
}
if got, want := h2.Gname, g.h.Gname; got != want {
t.Errorf("i=%d: Gname: got %q, want %q", i, got, want)
}
if got, want := h2.Linkname, g.h.Linkname; got != want {
t.Errorf("i=%d: Linkname: got %v, want %v", i, got, want)
}
if got, want := h2.Typeflag, g.h.Typeflag; got != want {
t.Logf("%#v %#v", g.h, fi.Sys())
t.Errorf("i=%d: Typeflag: got %q, want %q", i, got, want)
}
if got, want := h2.Mode, g.h.Mode; got != want {
t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
}
if got, want := fi.Mode(), g.fm; got != want {
t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
}
if got, want := h2.AccessTime, g.h.AccessTime; got != want {
t.Errorf("i=%d: AccessTime: got %v, want %v", i, got, want)
}
if got, want := h2.ChangeTime, g.h.ChangeTime; got != want {
t.Errorf("i=%d: ChangeTime: got %v, want %v", i, got, want)
}
if got, want := h2.ModTime, g.h.ModTime; got != want {
t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -355,7 +355,7 @@ func paxHeader(msg string) string {
// hdr.Size bytes are written after WriteHeader.
func (tw *Writer) Write(b []byte) (n int, err error) {
if tw.closed {
err = ErrWriteTooLong
err = ErrWriteAfterClose
return
}
overwrite := false

View file

@ -147,6 +147,44 @@ var writerTests = []*writerTest{
},
},
},
// This file was produced using gnu tar 1.26
// echo "Slartibartfast" > file.txt
// ln file.txt hard.txt
// tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
{
file: "testdata/hardlink.tar",
entries: []*writerTestEntry{
{
header: &Header{
Name: "file.txt",
Mode: 0644,
Uid: 1000,
Gid: 100,
Size: 15,
ModTime: time.Unix(1425484303, 0),
Typeflag: '0',
Uname: "vbatts",
Gname: "users",
},
contents: "Slartibartfast\n",
},
{
header: &Header{
Name: "hard.txt",
Mode: 0644,
Uid: 1000,
Gid: 100,
Size: 0,
ModTime: time.Unix(1425484303, 0),
Typeflag: '1',
Linkname: "file.txt",
Uname: "vbatts",
Gname: "users",
},
// no contents
},
},
},
}
// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
@ -489,3 +527,20 @@ func TestValidTypeflagWithPAXHeader(t *testing.T) {
}
}
}
func TestWriteAfterClose(t *testing.T) {
var buffer bytes.Buffer
tw := NewWriter(&buffer)
hdr := &Header{
Name: "small.txt",
Size: 5,
}
if err := tw.WriteHeader(hdr); err != nil {
t.Fatalf("Failed to write header: %s", err)
}
tw.Close()
if _, err := tw.Write([]byte("Kilts")); err != ErrWriteAfterClose {
t.Fatalf("Write: got %v; want ErrWriteAfterClose", err)
}
}

View file

@ -8,6 +8,7 @@ import (
"bufio"
"encoding/binary"
"errors"
"fmt"
"hash"
"hash/crc32"
"io"
@ -77,6 +78,9 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
if err != nil {
return err
}
if end.directoryRecords > uint64(size)/fileHeaderLen {
return fmt.Errorf("archive/zip: TOC declares impossible %d files in %d byte zip", end.directoryRecords, size)
}
z.r = r
z.File = make([]*File, 0, end.directoryRecords)
z.Comment = end.comment
@ -146,16 +150,22 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
if f.hasDataDescriptor() {
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
}
rc = &checksumReader{rc, crc32.NewIEEE(), f, desr, nil}
rc = &checksumReader{
rc: rc,
hash: crc32.NewIEEE(),
f: f,
desr: desr,
}
return
}
type checksumReader struct {
rc io.ReadCloser
hash hash.Hash32
f *File
desr io.Reader // if non-nil, where to read the data descriptor
err error // sticky error
rc io.ReadCloser
hash hash.Hash32
nread uint64 // number of bytes read so far
f *File
desr io.Reader // if non-nil, where to read the data descriptor
err error // sticky error
}
func (r *checksumReader) Read(b []byte) (n int, err error) {
@ -164,13 +174,21 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
}
n, err = r.rc.Read(b)
r.hash.Write(b[:n])
r.nread += uint64(n)
if err == nil {
return
}
if err == io.EOF {
if r.nread != r.f.UncompressedSize64 {
return 0, io.ErrUnexpectedEOF
}
if r.desr != nil {
if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
err = err1
if err1 == io.EOF {
err = io.ErrUnexpectedEOF
} else {
err = err1
}
} else if r.hash.Sum32() != r.f.CRC32 {
err = ErrChecksum
}

View file

@ -531,3 +531,77 @@ func TestIssue8186(t *testing.T) {
}
}
}
// Verify we return ErrUnexpectedEOF when length is short.
func TestIssue10957(t *testing.T) {
data := []byte("PK\x03\x040000000PK\x01\x0200000" +
"0000000000000000000\x00" +
"\x00\x00\x00\x00\x00000000000000PK\x01" +
"\x020000000000000000000" +
"00000\v\x00\x00\x00\x00\x00000000000" +
"00000000000000PK\x01\x0200" +
"00000000000000000000" +
"00\v\x00\x00\x00\x00\x00000000000000" +
"00000000000PK\x01\x020000<" +
"0\x00\x0000000000000000\v\x00\v" +
"\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
"00000000PK\x01\x0200000000" +
"0000000000000000\v\x00\x00\x00" +
"\x00\x0000PK\x05\x06000000\x05\x000000" +
"\v\x00\x00\x00\x00\x00")
z, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
t.Fatal(err)
}
for i, f := range z.File {
r, err := f.Open()
if err != nil {
continue
}
if f.UncompressedSize64 < 1e6 {
n, err := io.Copy(ioutil.Discard, r)
if i == 3 && err != io.ErrUnexpectedEOF {
t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
}
if err == nil && uint64(n) != f.UncompressedSize64 {
t.Errorf("file %d: bad size: copied=%d; want=%d", i, n, f.UncompressedSize64)
}
}
r.Close()
}
}
// Verify the number of files is sane.
func TestIssue10956(t *testing.T) {
data := []byte("PK\x06\x06PK\x06\a0000\x00\x00\x00\x00\x00\x00\x00\x00" +
"0000PK\x05\x06000000000000" +
"0000\v\x00000\x00\x00\x00\x00\x00\x00\x000")
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
const want = "TOC declares impossible 3472328296227680304 files in 57 byte"
if err == nil && !strings.Contains(err.Error(), want) {
t.Errorf("error = %v; want %q", err, want)
}
}
// Verify we return ErrUnexpectedEOF when reading truncated data descriptor.
func TestIssue11146(t *testing.T) {
data := []byte("PK\x03\x040000000000000000" +
"000000\x01\x00\x00\x000\x01\x00\x00\xff\xff0000" +
"0000000000000000PK\x01\x02" +
"0000\b0\b\x00000000000000" +
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000PK\x05\x06\x00\x00" +
"\x00\x0000\x01\x0000008\x00\x00\x00\x00\x00")
z, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
t.Fatal(err)
}
r, err := z.File[0].Open()
if err != nil {
t.Fatal(err)
}
_, err = ioutil.ReadAll(r)
if err != io.ErrUnexpectedEOF {
t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
}
r.Close()
}

View file

@ -81,8 +81,8 @@ type FileHeader struct {
ModifiedTime uint16 // MS-DOS time
ModifiedDate uint16 // MS-DOS date
CRC32 uint32
CompressedSize uint32 // deprecated; use CompressedSize64
UncompressedSize uint32 // deprecated; use UncompressedSize64
CompressedSize uint32 // Deprecated: Use CompressedSize64 instead.
UncompressedSize uint32 // Deprecated: Use UncompressedSize64 instead.
CompressedSize64 uint64
UncompressedSize64 uint64
Extra []byte
@ -233,7 +233,7 @@ func (h *FileHeader) SetMode(mode os.FileMode) {
}
}
// isZip64 returns true if the file size exceeds the 32 bit limit
// isZip64 reports whether the file size exceeds the 32 bit limit
func (fh *FileHeader) isZip64() bool {
return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max
}

View file

@ -34,6 +34,17 @@ func NewWriter(w io.Writer) *Writer {
return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}}
}
// SetOffset sets the offset of the beginning of the zip data within the
// underlying writer. It should be used when the zip data is appended to an
// existing file, such as a binary executable.
// It must be called before any data is written.
func (w *Writer) SetOffset(n int64) {
if w.cw.count != 0 {
panic("zip: SetOffset called after data was written")
}
w.cw.count = n
}
// Flush flushes any buffered data to the underlying writer.
// Calling Flush is not normally necessary; calling Close is sufficient.
func (w *Writer) Flush() error {
@ -122,15 +133,15 @@ func (w *Writer) Close() error {
// zip64 end of central directory record
b.uint32(directory64EndSignature)
b.uint64(directory64EndLen)
b.uint16(zipVersion45) // version made by
b.uint16(zipVersion45) // version needed to extract
b.uint32(0) // number of this disk
b.uint32(0) // number of the disk with the start of the central directory
b.uint64(records) // total number of entries in the central directory on this disk
b.uint64(records) // total number of entries in the central directory
b.uint64(size) // size of the central directory
b.uint64(offset) // offset of start of central directory with respect to the starting disk number
b.uint64(directory64EndLen - 12) // length minus signature (uint32) and length fields (uint64)
b.uint16(zipVersion45) // version made by
b.uint16(zipVersion45) // version needed to extract
b.uint32(0) // number of this disk
b.uint32(0) // number of the disk with the start of the central directory
b.uint64(records) // total number of entries in the central directory on this disk
b.uint64(records) // total number of entries in the central directory
b.uint64(size) // size of the central directory
b.uint64(offset) // offset of start of central directory with respect to the starting disk number
// zip64 end of central directory locator
b.uint32(directory64LocSignature)
@ -184,14 +195,20 @@ func (w *Writer) Create(name string) (io.Writer, error) {
// CreateHeader adds a file to the zip file using the provided FileHeader
// for the file metadata.
// It returns a Writer to which the file contents should be written.
//
// The file's contents must be written to the io.Writer before the next
// call to Create, CreateHeader, or Close.
// call to Create, CreateHeader, or Close. The provided FileHeader fh
// must not be modified after a call to CreateHeader.
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
if w.last != nil && !w.last.closed {
if err := w.last.close(); err != nil {
return nil, err
}
}
if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
// See https://golang.org/issue/11144 confusion.
return nil, errors.New("archive/zip: invalid duplicate FileHeader")
}
fh.Flags |= 0x8 // we will write a data descriptor

View file

@ -87,6 +87,41 @@ func TestWriter(t *testing.T) {
}
}
func TestWriterOffset(t *testing.T) {
largeData := make([]byte, 1<<17)
for i := range largeData {
largeData[i] = byte(rand.Int())
}
writeTests[1].Data = largeData
defer func() {
writeTests[1].Data = nil
}()
// write a zip file
buf := new(bytes.Buffer)
existingData := []byte{1, 2, 3, 1, 2, 3, 1, 2, 3}
n, _ := buf.Write(existingData)
w := NewWriter(buf)
w.SetOffset(int64(n))
for _, wt := range writeTests {
testCreate(t, w, &wt)
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
// read it back
r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
if err != nil {
t.Fatal(err)
}
for i, wt := range writeTests {
testReadFile(t, r.File[i], &wt)
}
}
func TestWriterFlush(t *testing.T) {
var buf bytes.Buffer
w := NewWriter(struct{ io.Writer }{&buf})

View file

@ -229,10 +229,11 @@ func TestZip64(t *testing.T) {
t.Skip("slow test; skipping")
}
const size = 1 << 32 // before the "END\n" part
testZip64(t, size)
buf := testZip64(t, size)
testZip64DirectoryRecordLength(buf, t)
}
func testZip64(t testing.TB, size int64) {
func testZip64(t testing.TB, size int64) *rleBuffer {
const chunkSize = 1024
chunks := int(size / chunkSize)
// write 2^32 bytes plus "END\n" to a zip file
@ -302,6 +303,37 @@ func testZip64(t testing.TB, size int64) {
if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want {
t.Errorf("UncompressedSize64 %d, want %d", got, want)
}
return buf
}
// Issue 9857
func testZip64DirectoryRecordLength(buf *rleBuffer, t *testing.T) {
d := make([]byte, 1024)
if _, err := buf.ReadAt(d, buf.Size()-int64(len(d))); err != nil {
t.Fatal("read:", err)
}
sigOff := findSignatureInBlock(d)
dirOff, err := findDirectory64End(buf, buf.Size()-int64(len(d))+int64(sigOff))
if err != nil {
t.Fatal("findDirectory64End:", err)
}
d = make([]byte, directory64EndLen)
if _, err := buf.ReadAt(d, dirOff); err != nil {
t.Fatal("read:", err)
}
b := readBuf(d)
if sig := b.uint32(); sig != directory64EndSignature {
t.Fatalf("Expected directory64EndSignature (%d), got %d", directory64EndSignature, sig)
}
size := b.uint64()
if size != directory64EndLen-12 {
t.Fatalf("Expected length of %d, got %d", directory64EndLen-12, size)
}
}
func testInvalidHeader(h *FileHeader, t *testing.T) {

View file

@ -144,6 +144,39 @@ func (b *Reader) Peek(n int) ([]byte, error) {
return b.buf[b.r : b.r+n], err
}
// Discard skips the next n bytes, returning the number of bytes discarded.
//
// If Discard skips fewer than n bytes, it also returns an error.
// If 0 <= n <= b.Buffered(), Discard is guaranteed to succeed without
// reading from the underlying io.Reader.
func (b *Reader) Discard(n int) (discarded int, err error) {
if n < 0 {
return 0, ErrNegativeCount
}
if n == 0 {
return
}
remain := n
for {
skip := b.Buffered()
if skip == 0 {
b.fill()
skip = b.Buffered()
}
if skip > remain {
skip = remain
}
b.r += skip
remain -= skip
if remain == 0 {
return n, nil
}
if b.err != nil {
return n - remain, b.readErr()
}
}
}
// Read reads data into p.
// It returns the number of bytes read into p.
// It calls Read at most once on the underlying Reader,
@ -367,7 +400,6 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
// accumulating full buffers.
var frag []byte
var full [][]byte
err = nil
for {
var e error

View file

@ -1268,6 +1268,135 @@ func TestWriterReset(t *testing.T) {
}
}
func TestReaderDiscard(t *testing.T) {
tests := []struct {
name string
r io.Reader
bufSize int // 0 means 16
peekSize int
n int // input to Discard
want int // from Discard
wantErr error // from Discard
wantBuffered int
}{
{
name: "normal case",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
peekSize: 16,
n: 6,
want: 6,
wantBuffered: 10,
},
{
name: "discard causing read",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
n: 6,
want: 6,
wantBuffered: 10,
},
{
name: "discard all without peek",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
n: 26,
want: 26,
wantBuffered: 0,
},
{
name: "discard more than end",
r: strings.NewReader("abcdefghijklmnopqrstuvwxyz"),
n: 27,
want: 26,
wantErr: io.EOF,
wantBuffered: 0,
},
// Any error from filling shouldn't show up until we
// get past the valid bytes. Here we return we return 5 valid bytes at the same time
// as an error, but test that we don't see the error from Discard.
{
name: "fill error, discard less",
r: newScriptedReader(func(p []byte) (n int, err error) {
if len(p) < 5 {
panic("unexpected small read")
}
return 5, errors.New("5-then-error")
}),
n: 4,
want: 4,
wantErr: nil,
wantBuffered: 1,
},
{
name: "fill error, discard equal",
r: newScriptedReader(func(p []byte) (n int, err error) {
if len(p) < 5 {
panic("unexpected small read")
}
return 5, errors.New("5-then-error")
}),
n: 5,
want: 5,
wantErr: nil,
wantBuffered: 0,
},
{
name: "fill error, discard more",
r: newScriptedReader(func(p []byte) (n int, err error) {
if len(p) < 5 {
panic("unexpected small read")
}
return 5, errors.New("5-then-error")
}),
n: 6,
want: 5,
wantErr: errors.New("5-then-error"),
wantBuffered: 0,
},
// Discard of 0 shouldn't cause a read:
{
name: "discard zero",
r: newScriptedReader(), // will panic on Read
n: 0,
want: 0,
wantErr: nil,
wantBuffered: 0,
},
{
name: "discard negative",
r: newScriptedReader(), // will panic on Read
n: -1,
want: 0,
wantErr: ErrNegativeCount,
wantBuffered: 0,
},
}
for _, tt := range tests {
br := NewReaderSize(tt.r, tt.bufSize)
if tt.peekSize > 0 {
peekBuf, err := br.Peek(tt.peekSize)
if err != nil {
t.Errorf("%s: Peek(%d): %v", tt.name, tt.peekSize, err)
continue
}
if len(peekBuf) != tt.peekSize {
t.Errorf("%s: len(Peek(%d)) = %v; want %v", tt.name, tt.peekSize, len(peekBuf), tt.peekSize)
continue
}
}
discarded, err := br.Discard(tt.n)
if ge, we := fmt.Sprint(err), fmt.Sprint(tt.wantErr); discarded != tt.want || ge != we {
t.Errorf("%s: Discard(%d) = (%v, %v); want (%v, %v)", tt.name, tt.n, discarded, ge, tt.want, we)
continue
}
if bn := br.Buffered(); bn != tt.wantBuffered {
t.Errorf("%s: after Discard, Buffered = %d; want %d", tt.name, bn, tt.wantBuffered)
}
}
}
// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
type onlyReader struct {
io.Reader
@ -1278,6 +1407,23 @@ type onlyWriter struct {
io.Writer
}
// A scriptedReader is an io.Reader that executes its steps sequentially.
type scriptedReader []func(p []byte) (n int, err error)
func (sr *scriptedReader) Read(p []byte) (n int, err error) {
if len(*sr) == 0 {
panic("too many Read calls on scripted Reader. No steps remain.")
}
step := (*sr)[0]
*sr = (*sr)[1:]
return step(p)
}
func newScriptedReader(steps ...func(p []byte) (n int, err error)) io.Reader {
sr := scriptedReader(steps)
return &sr
}
func BenchmarkReaderCopyOptimal(b *testing.B) {
// Optimal case is where the underlying reader implements io.WriterTo
srcBuf := bytes.NewBuffer(make([]byte, 8192))

View file

@ -109,7 +109,7 @@ func (s *Scanner) Text() string {
// After Scan returns false, the Err method will return any error that
// occurred during scanning, except that if it was io.EOF, Err
// will return nil.
// Split panics if the split function returns 100 empty tokens without
// Scan panics if the split function returns 100 empty tokens without
// advancing the input. This is a common error mode for scanners.
func (s *Scanner) Scan() bool {
// Loop until we have a token.

View file

@ -236,14 +236,14 @@ func panic(v interface{})
// panicking.
func recover() interface{}
// The print built-in function formats its arguments in an implementation-
// specific way and writes the result to standard error.
// The print built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Print is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.
func print(args ...Type)
// The println built-in function formats its arguments in an implementation-
// specific way and writes the result to standard error.
// The println built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Spaces are always added between arguments and a newline is appended.
// Println is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.

View file

@ -56,6 +56,10 @@ func (b *Buffer) String() string {
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int { return len(b.buf) - b.off }
// Cap returns the capacity of the buffer's underlying byte slice, that is, the
// total space allocated for the buffer's data.
func (b *Buffer) Cap() int { return cap(b.buf) }
// Truncate discards all but the first n unread bytes from the buffer.
// It panics if n is negative or greater than the length of the buffer.
func (b *Buffer) Truncate(n int) {

View file

@ -231,6 +231,23 @@ func TestMixedReadsAndWrites(t *testing.T) {
empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len()))
}
func TestCapWithPreallocatedSlice(t *testing.T) {
buf := NewBuffer(make([]byte, 10))
n := buf.Cap()
if n != 10 {
t.Errorf("expected 10, got %d", n)
}
}
func TestCapWithSliceAndWrittenData(t *testing.T) {
buf := NewBuffer(make([]byte, 0, 10))
buf.Write([]byte("test"))
n := buf.Cap()
if n != 10 {
t.Errorf("expected 10, got %d", n)
}
}
func TestNil(t *testing.T) {
var b *Buffer
if b.String() != "<nil>" {

View file

@ -23,7 +23,7 @@ func equalPortable(a, b []byte) bool {
return true
}
// explode splits s into a slice of UTF-8 sequences, one per Unicode character (still slices of bytes),
// explode splits s into a slice of UTF-8 sequences, one per Unicode code point (still slices of bytes),
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
func explode(s []byte, n int) [][]byte {
if n <= 0 {
@ -47,6 +47,7 @@ func explode(s []byte, n int) [][]byte {
}
// Count counts the number of non-overlapping instances of sep in s.
// If sep is an empty slice, Count returns 1 + the number of Unicode code points in s.
func Count(s, sep []byte) int {
n := len(sep)
if n == 0 {
@ -137,6 +138,16 @@ func LastIndex(s, sep []byte) int {
return -1
}
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
func LastIndexByte(s []byte, c byte) int {
for i := len(s) - 1; i >= 0; i-- {
if s[i] == c {
return i
}
}
return -1
}
// IndexRune interprets s as a sequence of UTF-8-encoded Unicode code points.
// It returns the byte index of the first occurrence in s of the given rune.
// It returns -1 if rune is not present in s.
@ -442,7 +453,7 @@ func isSeparator(r rune) bool {
// Title returns a copy of s with all Unicode letters that begin words
// mapped to their title case.
//
// BUG: The rule Title uses for word boundaries does not handle Unicode punctuation properly.
// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
func Title(s []byte) []byte {
// Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling

View file

@ -21,4 +21,4 @@ func Equal(a, b []byte) bool // ../runtime/asm_$GOARCH.s
// Compare returns an integer comparing two byte slices lexicographically.
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
// A nil argument is equivalent to an empty slice.
func Compare(a, b []byte) int // ../runtime/noasm_arm.goc or ../runtime/asm_{386,amd64}.s
func Compare(a, b []byte) int // ../runtime/noasm.go or ../runtime/asm_{386,amd64}.s

View file

@ -265,6 +265,23 @@ func TestIndexByte(t *testing.T) {
}
}
func TestLastIndexByte(t *testing.T) {
testCases := []BinOpTest{
{"", "q", -1},
{"abcdef", "q", -1},
{"abcdefabcdef", "a", len("abcdef")}, // something in the middle
{"abcdefabcdef", "f", len("abcdefabcde")}, // last byte
{"zabcdefabcdef", "z", 0}, // first byte
{"a☺b☻c☹d", "b", len("a☺")}, // non-ascii
}
for _, test := range testCases {
actual := LastIndexByte([]byte(test.a), test.b[0])
if actual != test.i {
t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.a, test.b[0], actual, test.i)
}
}
}
// test a larger buffer with different sizes and alignments
func TestIndexByteBig(t *testing.T) {
var n = 1024

View file

@ -17,6 +17,8 @@ var compareTests = []struct {
{[]byte("a"), []byte(""), 1},
{[]byte(""), []byte("a"), -1},
{[]byte("abc"), []byte("abc"), 0},
{[]byte("abd"), []byte("abc"), 1},
{[]byte("abc"), []byte("abd"), -1},
{[]byte("ab"), []byte("abc"), -1},
{[]byte("abc"), []byte("ab"), 1},
{[]byte("x"), []byte("ab"), 1},
@ -27,6 +29,7 @@ var compareTests = []struct {
{[]byte("abcdefgh"), []byte("abcdefgh"), 0},
{[]byte("abcdefghi"), []byte("abcdefghi"), 0},
{[]byte("abcdefghi"), []byte("abcdefghj"), -1},
{[]byte("abcdefghj"), []byte("abcdefghi"), 1},
// nil tests
{nil, nil, 0},
{[]byte(""), nil, 0},

View file

@ -7,7 +7,3 @@ package bytes
// Export func for testing
var IndexBytePortable = indexBytePortable
var EqualPortable = equalPortable
func (b *Buffer) Cap() int {
return cap(b.buf)
}

View file

@ -29,6 +29,12 @@ func (r *Reader) Len() int {
return int(int64(len(r.s)) - r.i)
}
// Size returns the original length of the underlying byte slice.
// Size is the number of bytes available for reading via ReadAt.
// The returned value is always the same and is not affected by calls
// to any other method.
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

View file

@ -244,3 +244,15 @@ func TestReaderCopyNothing(t *testing.T) {
t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut)
}
}
// tests that Len is affected by reads, but Size is not.
func TestReaderLenSize(t *testing.T) {
r := NewReader([]byte("abc"))
io.CopyN(ioutil.Discard, r, 1)
if r.Len() != 2 {
t.Errorf("Len = %d; want 2", r.Len())
}
if r.Size() != 3 {
t.Errorf("Size = %d; want 3", r.Size())
}
}

View file

@ -235,9 +235,17 @@ func (f *File) saveExport(x interface{}, context string) {
error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
}
doc := ""
for _, c1 := range n.Doc.List {
if c1 != c {
doc += c1.Text + "\n"
}
}
f.ExpFunc = append(f.ExpFunc, &ExpFunc{
Func: n,
ExpName: name,
Doc: doc,
})
break
}

View file

@ -20,16 +20,23 @@ the C parts of the package. For example:
// #include <errno.h>
import "C"
The preamble may contain any C code, including function and variable
declarations and definitions. These may then be referred to from Go
code as though they were defined in the package "C". All names
declared in the preamble may be used, even if they start with a
lower-case letter. Exception: static variables in the preamble may
not be referenced from Go code; static functions are permitted.
See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See
"C? Go? Cgo!" for an introduction to using cgo:
http://golang.org/doc/articles/c_go_cgo.html.
https://golang.org/doc/articles/c_go_cgo.html.
CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo
directives within these comments to tweak the behavior of the C or C++
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 http://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
(see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
For example:
// #cgo CFLAGS: -DPNG_DEBUG=1
@ -60,6 +67,18 @@ 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
file. This allows pre-compiled static libraries to be included in the package
directory and linked properly.
For example if package foo is in the directory /go/src/foo:
// #cgo LDFLAGS: -L${SRCDIR}/libs -lfoo
Will be expanded to:
// #cgo LDFLAGS: -L/go/src/foo/libs -lfoo
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
@ -71,17 +90,19 @@ compilers may be changed by the CC and CXX environment variables,
respectively; those environment variables may include command line
options.
To enable cgo during cross compiling builds, set the CGO_ENABLED
environment variable to 1 when building the Go tools with make.bash.
Also, set CC_FOR_TARGET to the C cross compiler for the target. CC will
be used for compiling for the host.
The cgo tool is enabled by default for native builds on systems where
it is expected to work. It is disabled by default when
cross-compiling. You can control this by setting the CGO_ENABLED
environment variable when running the go tool: set it to 1 to enable
the use of cgo, and to 0 to disable it. The go tool will set the
build constraint "cgo" if cgo is enabled.
After the Go tools are built, when running the go command, CC_FOR_TARGET is
ignored. The value of CC_FOR_TARGET when running make.bash is the default
compiler. However, you can set the environment variable CC, not CC_FOR_TARGET,
to control the compiler when running the go tool.
CXX_FOR_TARGET works in a similar way for C++ code.
When cross-compiling, you must specify a C cross-compiler for cgo to
use. You can do this by setting the CC_FOR_TARGET environment
variable when building the toolchain using make.bash, or by setting
the CC environment variable any time you run the go tool. The
CXX_FOR_TARGET and CXX environment variables work in a similar way for
C++ code.
Go references to C
@ -195,16 +216,18 @@ Not all Go types can be mapped to C types in a useful way.
Using //export in a file places a restriction on the preamble:
since it is copied into two different C output files, it must not
contain any definitions, only declarations. Definitions must be
placed in preambles in other files, or in C source files.
contain any definitions, only declarations. If a file contains both
definitions and declarations, then the two output files will produce
duplicate symbols and the linker will fail. To avoid this, definitions
must be placed in preambles in other files, or in C source files.
Using cgo directly
Usage:
go tool cgo [cgo options] [-- compiler options] file.go
go tool cgo [cgo options] [-- compiler options] gofiles...
Cgo transforms the input file.go into four output files: two Go source
files, a C file for 6c (or 8c or 5c), and a C file for gcc.
Cgo transforms the specified input Go source files into several output
Go and C source files.
The compiler options are passed through uninterpreted when
invoking the C compiler to compile the C parts of the package.
@ -217,18 +240,23 @@ The following options are available when running cgo directly:
build when building a cgo package.
-dynout file
Write -dynimport output to file.
-dynpackage package
Set Go package for -dynimport output.
-dynlinker
Write dynamic linker as part of -dynimport output.
-godefs
Write out input file in Go syntax replacing C package
names with real values. Used to generate files in the
syscall package when bootstrapping a new target.
-cdefs
Like -godefs, but write file in C syntax.
Used to generate files in the runtime package when
bootstrapping a new target.
-objdir directory
Put all generated files in directory.
-importpath string
The import path for the Go package. Optional; used for
nicer comments in the generated files.
-exportheader file
If there are any exported functions, write the
generated export declarations to file.
C code can #include this to see the declarations.
-gccgo
Generate output for the gccgo compiler rather than the
gc compiler.
@ -363,9 +391,9 @@ the translation process.
Translating Go
[The rest of this comment refers to 6g and 6c, the Go and C compilers
that are part of the amd64 port of the gc Go toolchain. Everything here
applies to another architecture's compilers as well.]
[The rest of this comment refers to 6g, the Go compiler that is part
of the amd64 port of the gc Go toolchain. Everything here applies to
another architecture's compilers as well.]
Given the input Go files x.go and y.go, cgo generates these source
files:
@ -373,44 +401,41 @@ files:
x.cgo1.go # for 6g
y.cgo1.go # for 6g
_cgo_gotypes.go # for 6g
_cgo_defun.c # for 6c
_cgo_import.go # for 6g (if -dynout _cgo_import.go)
x.cgo2.c # for gcc
y.cgo2.c # for gcc
_cgo_defun.c # for gcc (if -gccgo)
_cgo_export.c # for gcc
_cgo_export.h # for gcc
_cgo_main.c # for gcc
_cgo_flags # for alternative build tools
The file x.cgo1.go is a copy of x.go with the import "C" removed and
references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx.
The definitions of those identifiers, written as Go functions, types,
or variables, are provided in _cgo_gotypes.go.
Here is a _cgo_gotypes.go containing definitions for C.flush (provided
in the preamble) and C.puts (from stdio):
Here is a _cgo_gotypes.go containing definitions for needed C types:
type _Ctype_char int8
type _Ctype_int int32
type _Ctype_void [0]byte
func _Cfunc_CString(string) *_Ctype_char
func _Cfunc_flush() _Ctype_void
func _Cfunc_puts(*_Ctype_char) _Ctype_int
For functions, cgo only writes an external declaration in the Go
output. The implementation is in a combination of C for 6c (meaning
any gc-toolchain compiler) and C for gcc.
The 6c file contains the definitions of the functions. They all have
similar bodies that invoke runtime·cgocall to make a switch from the
Go runtime world to the system C (GCC-based) world.
The _cgo_gotypes.go file also contains the definitions of the
functions. They all have similar bodies that invoke runtime·cgocall
to make a switch from the Go runtime world to the system C (GCC-based)
world.
For example, here is the definition of _Cfunc_puts:
void _cgo_be59f0f25121_Cfunc_puts(void*);
//go:cgo_import_static _cgo_be59f0f25121_Cfunc_puts
//go:linkname __cgofn__cgo_be59f0f25121_Cfunc_puts _cgo_be59f0f25121_Cfunc_puts
var __cgofn__cgo_be59f0f25121_Cfunc_puts byte
var _cgo_be59f0f25121_Cfunc_puts = unsafe.Pointer(&__cgofn__cgo_be59f0f25121_Cfunc_puts)
void
·_Cfunc_puts(struct{uint8 x[1];}p)
{
runtime·cgocall(_cgo_be59f0f25121_Cfunc_puts, &p);
func _Cfunc_puts(p0 *_Ctype_char) (r1 _Ctype_int) {
_cgo_runtime_cgocall(_cgo_be59f0f25121_Cfunc_puts, uintptr(unsafe.Pointer(&p0)))
return
}
The hexadecimal number is a hash of cgo's input, chosen to be
@ -421,6 +446,7 @@ 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;
@ -429,7 +455,8 @@ file compiled by gcc, the file x.cgo2.c:
a->r = puts((void*)a->p0);
}
It extracts the arguments from the pointer to _Cfunc_puts's argument
It waits for Go runtime to be initialized (required for shared libraries),
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.
@ -448,6 +475,7 @@ _cgo_main.c:
int main() { return 0; }
void crosscall2(void(*fn)(void*, int), void *a, int c) { }
void _cgo_wait_runtime_init_done() { }
void _cgo_allocate(void *a, int c) { }
void _cgo_panic(void *a, int c) { }
@ -456,23 +484,21 @@ code generated for gcc. The build process links this stub, along with
_cgo_export.c and *.cgo2.c, into a dynamic executable and then lets
cgo examine the executable. Cgo records the list of shared library
references and resolved names and writes them into a new file
_cgo_import.c, which looks like:
_cgo_import.go, which looks like:
#pragma cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2"
#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6"
#pragma cgo_import_dynamic _ _ "libpthread.so.0"
#pragma cgo_import_dynamic _ _ "libc.so.6"
//go:cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2"
//go:cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
//go:cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6"
//go:cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6"
//go:cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6"
//go:cgo_import_dynamic _ _ "libpthread.so.0"
//go:cgo_import_dynamic _ _ "libc.so.6"
In the end, the compiled Go package, which will eventually be
presented to 6l as part of a larger program, contains:
_go_.6 # 6g-compiled object for _cgo_gotypes.go *.cgo1.go
_cgo_defun.6 # 6c-compiled object for _cgo_defun.c
_go_.6 # 6g-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go
_all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c
_cgo_import.6 # 6c-compiled object for _cgo_import.c
The final program will be a dynamic executable, so that 6l can avoid
needing to process arbitrary .o files. It only needs to process the .o
@ -496,20 +522,21 @@ Runtime
When using cgo, Go must not assume that it owns all details of the
process. In particular it needs to coordinate with C in the use of
threads and thread-local storage. The runtime package, in its own
(6c-compiled) C code, declares a few uninitialized (default bss)
threads and thread-local storage. The runtime package declares a few
variables:
bool runtime·iscgo;
void (*libcgo_thread_start)(void*);
void (*initcgo)(G*);
var (
iscgo bool
_cgo_init unsafe.Pointer
_cgo_thread_start unsafe.Pointer
)
Any package using cgo imports "runtime/cgo", which provides
initializations for these variables. It sets iscgo to 1, initcgo to a
gcc-compiled function that can be called early during program startup,
and libcgo_thread_start to a gcc-compiled function that can be used to
create a new thread, in place of the runtime's usual direct system
calls.
initializations for these variables. It sets iscgo to true, _cgo_init
to a gcc-compiled function that can be called early during program
startup, and _cgo_thread_start to a gcc-compiled function that can be
used to create a new thread, in place of the runtime's usual direct
system calls.
Internal and External Linking
@ -522,12 +549,12 @@ code can only be used as a dynamic library). On the other hand, when
using internal linking, 6l can generate Go binaries by itself.
In order to allow linking arbitrary object files without requiring
dynamic libraries, cgo will soon support an "external" linking mode
too. In external linking mode, 6l does not process any host object
files. Instead, it collects all the Go code and writes a single go.o
object file containing it. Then it invokes the host linker (usually
gcc) to combine the go.o object file and any supporting non-Go code
into a final executable. External linking avoids the dynamic library
dynamic libraries, cgo supports an "external" linking mode too. In
external linking mode, 6l does not process any host object files.
Instead, it collects all the Go code and writes a single go.o object
file containing it. Then it invokes the host linker (usually gcc) to
combine the go.o object file and any supporting non-Go code into a
final executable. External linking avoids the dynamic library
requirement but introduces a requirement that the host linker be
present to create such a binary.
@ -555,13 +582,13 @@ to be made when linking the final binary.
Linking Directives
In either linking mode, package-specific directives must be passed
through to 6l. These are communicated by writing #pragma directives
in a C source file compiled by 6c. The directives are copied into the .6 object file
and then processed by the linker.
through to 6l. These are communicated by writing //go: directives in a
Go source file compiled by 6g. The directives are copied into the .6
object file and then processed by the linker.
The directives are:
#pragma cgo_import_dynamic <local> [<remote> ["<library>"]]
//go:cgo_import_dynamic <local> [<remote> ["<library>"]]
In internal linking mode, allow an unresolved reference to
<local>, assuming it will be resolved by a dynamic library
@ -572,9 +599,9 @@ The directives are:
In the <remote>, # or @ can be used to introduce a symbol version.
Examples:
#pragma cgo_import_dynamic puts
#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5
#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
//go:cgo_import_dynamic puts
//go:cgo_import_dynamic puts puts#GLIBC_2.2.5
//go:cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
A side effect of the cgo_import_dynamic directive with a
library is to make the final binary depend on that dynamic
@ -582,12 +609,12 @@ The directives are:
symbols, use _ for local and remote.
Example:
#pragma cgo_import_dynamic _ _ "libc.so.6"
//go:cgo_import_dynamic _ _ "libc.so.6"
For compatibility with current versions of SWIG,
#pragma dynimport is an alias for #pragma cgo_import_dynamic.
#pragma dynimport is an alias for //go:cgo_import_dynamic.
#pragma cgo_dynamic_linker "<path>"
//go:cgo_dynamic_linker "<path>"
In internal linking mode, use "<path>" as the dynamic linker
in the final binary. This directive is only needed from one
@ -595,9 +622,9 @@ The directives are:
supplied by runtime/cgo.
Example:
#pragma cgo_dynamic_linker "/lib/ld-linux.so.2"
//go:cgo_dynamic_linker "/lib/ld-linux.so.2"
#pragma cgo_export_dynamic <local> <remote>
//go:cgo_export_dynamic <local> <remote>
In internal linking mode, put the Go symbol
named <local> into the program's exported symbol table as
@ -606,9 +633,9 @@ The directives are:
to share Go's data.
For compatibility with current versions of SWIG,
#pragma dynexport is an alias for #pragma cgo_export_dynamic.
#pragma dynexport is an alias for //go:cgo_export_dynamic.
#pragma cgo_import_static <local>
//go:cgo_import_static <local>
In external linking mode, allow unresolved references to
<local> in the go.o object file prepared for the host linker,
@ -616,9 +643,9 @@ The directives are:
other object files that will be linked with go.o.
Example:
#pragma cgo_import_static puts_wrapper
//go:cgo_import_static puts_wrapper
#pragma cgo_export_static <local> <remote>
//go:cgo_export_static <local> <remote>
In external linking mode, put the Go symbol
named <local> into the program's exported symbol table as
@ -626,15 +653,15 @@ The directives are:
mechanism makes it possible for C code to call back into Go or
to share Go's data.
#pragma cgo_ldflag "<arg>"
//go:cgo_ldflag "<arg>"
In external linking mode, invoke the host linker (usually gcc)
with "<arg>" as a command-line argument following the .o files.
Note that the arguments are for "gcc", not "ld".
Example:
#pragma cgo_ldflag "-lpthread"
#pragma cgo_ldflag "-L/usr/local/sqlite3/lib"
//go:cgo_ldflag "-lpthread"
//go:cgo_ldflag "-L/usr/local/sqlite3/lib"
A package compiled with cgo will include directives for both
internal and external linking; the linker will select the appropriate
@ -647,22 +674,18 @@ The following code will be generated by cgo:
// compiled by 6g
//go:cgo_ldflag "-lm"
type _Ctype_double float64
func _Cfunc_sin(_Ctype_double) _Ctype_double
// compiled by 6c
//go:cgo_import_static _cgo_gcc_Cfunc_sin
//go:linkname __cgo_gcc_Cfunc_sin _cgo_gcc_Cfunc_sin
var __cgo_gcc_Cfunc_sin byte
var _cgo_gcc_Cfunc_sin = unsafe.Pointer(&__cgo_gcc_Cfunc_sin)
#pragma cgo_import_dynamic sin sin#GLIBC_2.2.5 "libm.so.6"
#pragma cgo_import_static _cgo_gcc_Cfunc_sin
#pragma cgo_ldflag "-lm"
void _cgo_gcc_Cfunc_sin(void*);
void
·_Cfunc_sin(struct{uint8 x[16];}p)
{
runtime·cgocall(_cgo_gcc_Cfunc_sin, &p);
func _Cfunc_sin(p0 _Ctype_double) (r1 _Ctype_double) {
_cgo_runtime_cgocall(_cgo_gcc_Cfunc_sin, uintptr(unsafe.Pointer(&p0)))
return
}
// compiled by gcc, into foo.cgo2.o
@ -682,8 +705,8 @@ using the internal or external mode. If other packages are compiled in
"external only" mode, then the final link will be an external one.
Otherwise the link will be an internal one.
The directives in the 6c-compiled file are used according to the kind
of final link used.
The linking directives are used according to the kind of final link
used.
In internal mode, 6l itself processes all the host object files, in
particular foo.cgo2.o. To do so, it uses the cgo_import_dynamic and
@ -694,10 +717,10 @@ symbol sin with version GLIBC_2.2.5 from the dynamic library
runtime dynamic linker.
In external mode, 6l does not process any host object files, in
particular foo.cgo2.o. It links together the 6g- and 6c-generated
object files, along with any other Go code, into a go.o file. While
doing that, 6l will discover that there is no definition for
_cgo_gcc_Cfunc_sin, referred to by the 6c-compiled source file. This
particular foo.cgo2.o. It links together the 6g-generated object
files, along with any other Go code, into a go.o file. While doing
that, 6l will discover that there is no definition for
_cgo_gcc_Cfunc_sin, referred to by the 6g-compiled source file. This
is okay, because 6l also processes the cgo_import_static directive and
knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host
object file, so 6l does not treat the missing symbol as an error when

View file

@ -154,20 +154,6 @@ func splitQuoted(s string) (r []string, err error) {
return args, err
}
var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
func safeName(s string) bool {
if s == "" {
return false
}
for i := 0; i < len(s); i++ {
if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
return false
}
}
return true
}
// Translate rewrites f.AST, the original Go input, to remove
// references to the imported package C, replacing them with
// references to the equivalent Go types, functions, and variables.
@ -213,6 +199,10 @@ func (p *Package) loadDefines(f *File) {
val = strings.TrimSpace(line[tabIndex:])
}
if key == "__clang__" {
p.GccIsClang = true
}
if n := f.Name[key]; n != nil {
if *debugDefine {
fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
@ -582,7 +572,7 @@ func (p *Package) mangleName(n *Name) {
// 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 or *cdefs 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
@ -673,6 +663,13 @@ func (p *Package) rewriteRef(f *File) {
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
}
case "selector":
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))
}
case "type":
if r.Name.Kind != "type" {
error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
@ -688,7 +685,7 @@ func (p *Package) rewriteRef(f *File) {
error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
}
}
if *godefs || *cdefs {
if *godefs {
// Substitute definition for mangled type name.
if id, ok := expr.(*ast.Ident); ok {
if t := typedef[id.Name]; t != nil {
@ -746,6 +743,10 @@ func (p *Package) gccMachine() []string {
return []string{"-m32"}
case "arm":
return []string{"-marm"} // not thumb
case "s390":
return []string{"-m31"}
case "s390x":
return []string{"-m64"}
}
return nil
}
@ -765,7 +766,7 @@ func (p *Package) gccCmd() []string {
"-c", // do not link
"-xc", // input language is C
)
if strings.Contains(c[0], "clang") {
if p.GccIsClang {
c = append(c,
"-ferror-limit=0",
// Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
@ -780,7 +781,7 @@ func (p *Package) gccCmd() []string {
// incorrectly typed unsigned long. We work around that
// by disabling the builtin functions (this is safe as
// it won't affect the actual compilation of the C code).
// See: http://golang.org/issue/6506.
// See: https://golang.org/issue/6506.
"-fno-builtin",
)
}
@ -992,8 +993,8 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
c.goVoid = c.Ident("_Ctype_void")
// Normally cgo translates void* to unsafe.Pointer,
// but for historical reasons -cdefs and -godefs use *byte instead.
if *cdefs || *godefs {
// but for historical reasons -godefs uses *byte instead.
if *godefs {
c.goVoidPtr = &ast.StarExpr{X: c.byte}
} else {
c.goVoidPtr = c.Ident("unsafe.Pointer")
@ -1045,7 +1046,7 @@ func (tr *TypeRepr) String() string {
return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
}
// Empty returns true if the result of String would be "".
// Empty reports whether the result of String would be "".
func (tr *TypeRepr) Empty() bool {
return len(tr.Repr) == 0
}
@ -1334,8 +1335,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
// If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
// use that as the Go form for this typedef too, so that the typedef will be interchangeable
// with the base type.
// In -godefs and -cdefs mode, do this for all typedefs.
if isStructUnionClass(sub.Go) || *godefs || *cdefs {
// In -godefs mode, do this for all typedefs.
if isStructUnionClass(sub.Go) || *godefs {
t.Go = sub.Go
if isStructUnionClass(sub.Go) {
@ -1397,7 +1398,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
name := c.Ident("_Ctype_" + s)
tt := *t
typedef[name.Name] = &tt
if !*godefs && !*cdefs {
if !*godefs {
t.Go = name
}
}
@ -1543,14 +1544,16 @@ func (c *typeConv) intExpr(n int64) ast.Expr {
}
// Add padding of given size to fld.
func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
n := len(fld)
fld = fld[0 : n+1]
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
return fld
sizes = sizes[0 : n+1]
sizes[n] = size
return fld, sizes
}
// Struct conversion: return Go and (6g) C syntax for type.
// Struct conversion: return Go and (gc) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
// Minimum alignment for a struct is 1 byte.
align = 1
@ -1558,6 +1561,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
var buf bytes.Buffer
buf.WriteString("struct {")
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
sizes := make([]int64, 0, 2*len(dt.Field)+1)
off := int64(0)
// Rename struct fields that happen to be named Go keywords into
@ -1573,7 +1577,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
used[f.Name] = true
}
if !*godefs && !*cdefs {
if !*godefs {
for cid, goid := range ident {
if token.Lookup(goid).IsKeyword() {
// Avoid keyword
@ -1593,19 +1597,19 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
anon := 0
for _, f := range dt.Field {
if f.ByteOffset > off {
fld = c.pad(fld, f.ByteOffset-off)
fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
off = f.ByteOffset
}
name := f.Name
ft := f.Type
// In godefs or cdefs mode, if this field is a C11
// In godefs mode, if this field is a C11
// anonymous union then treat the first field in the
// union as the field in the struct. This handles
// cases like the glibc <sys/resource.h> file; see
// issue 6677.
if *godefs || *cdefs {
if *godefs {
if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
name = st.Field[0].Name
ident[name] = name
@ -1635,14 +1639,12 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
talign = size
}
if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs {
if talign > 0 && f.ByteOffset%talign != 0 {
// Drop misaligned fields, the same way we drop integer bit fields.
// The goal is to make available what can be made available.
// Otherwise one bad and unneeded field in an otherwise okay struct
// makes the whole program not compile. Much of the time these
// structs are in system headers that cannot be corrected.
// Exception: In -cdefs mode, we use #pragma pack, so misaligned
// fields should still work.
continue
}
n := len(fld)
@ -1653,6 +1655,8 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
ident[name] = name
}
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
sizes = sizes[0 : n+1]
sizes[n] = size
off += size
buf.WriteString(t.C.String())
buf.WriteString(" ")
@ -1663,16 +1667,29 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
}
}
if off < dt.ByteSize {
fld = c.pad(fld, dt.ByteSize-off)
fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
off = dt.ByteSize
}
// If the last field in a non-zero-sized struct is zero-sized
// the compiler is going to pad it by one (see issue 9401).
// 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.
for off > 0 && sizes[len(sizes)-1] == 0 {
n := len(sizes)
fld = fld[0 : n-1]
sizes = sizes[0 : n-1]
}
if off != dt.ByteSize {
fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
}
buf.WriteString("}")
csyntax = buf.String()
if *godefs || *cdefs {
if *godefs {
godefsFields(fld)
}
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
@ -1707,9 +1724,7 @@ func godefsFields(fld []*ast.Field) {
n.Name = "Pad_cgo_" + strconv.Itoa(npad)
npad++
}
if !*cdefs {
n.Name = upper(n.Name)
}
n.Name = upper(n.Name)
}
}
}
@ -1721,9 +1736,6 @@ func godefsFields(fld []*ast.Field) {
// package syscall's data structures, we drop a common prefix
// (so sec, usec, which will get turned into Sec, Usec for exporting).
func fieldPrefix(fld []*ast.Field) string {
if *cdefs {
return ""
}
prefix := ""
for _, f := range fld {
for _, n := range f.Names {

View file

@ -114,173 +114,6 @@ func (p *Package) godefs(f *File, srcfile string) string {
return buf.String()
}
// cdefs returns the output for -cdefs mode.
// The easiest way to do this is to translate the godefs Go to C.
func (p *Package) cdefs(f *File, srcfile string) string {
godefsOutput := p.godefs(f, srcfile)
lines := strings.Split(godefsOutput, "\n")
lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"
for i, line := range lines {
lines[i] = strings.TrimSpace(line)
}
var out bytes.Buffer
printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) }
didTypedef := false
for i := 0; i < len(lines); i++ {
line := lines[i]
// Delete
// package x
if strings.HasPrefix(line, "package ") {
continue
}
// Convert
// const (
// A = 1
// B = 2
// )
//
// to
//
// enum {
// A = 1,
// B = 2,
// };
if line == "const (" {
printf("enum {\n")
for i++; i < len(lines) && lines[i] != ")"; i++ {
line = lines[i]
if line != "" {
printf("\t%s,", line)
}
printf("\n")
}
printf("};\n")
continue
}
// Convert
// const A = 1
// to
// enum { A = 1 };
if strings.HasPrefix(line, "const ") {
printf("enum { %s };\n", line[len("const "):])
continue
}
// On first type definition, typedef all the structs
// in case there are dependencies between them.
if !didTypedef && strings.HasPrefix(line, "type ") {
didTypedef = true
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {")
printf("typedef struct %s %s;\n", s, s)
}
}
printf("\n")
printf("#pragma pack on\n")
printf("\n")
}
// Convert
// type T struct {
// X int64
// Y *int32
// Z [4]byte
// }
//
// to
//
// struct T {
// int64 X;
// int32 *Y;
// byte Z[4];
// }
if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
if len(lines) > i+1 && lines[i+1] == "}" {
// do not output empty struct
i++
continue
}
s := line[len("type ") : len(line)-len(" struct {")]
printf("struct %s {\n", s)
for i++; i < len(lines) && lines[i] != "}"; i++ {
line := lines[i]
if line != "" {
f := strings.Fields(line)
if len(f) != 2 {
fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line)
nerrors++
continue
}
printf("\t%s;", cdecl(f[0], f[1]))
}
printf("\n")
}
printf("};\n")
continue
}
// Convert
// type T int
// to
// typedef int T;
if strings.HasPrefix(line, "type ") {
f := strings.Fields(line[len("type "):])
if len(f) != 2 {
fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line)
nerrors++
continue
}
printf("typedef\t%s;\n", cdecl(f[0], f[1]))
continue
}
printf("%s\n", line)
}
if didTypedef {
printf("\n")
printf("#pragma pack off\n")
}
return out.String()
}
// cdecl returns the C declaration for the given Go name and type.
// It only handles the specific cases necessary for converting godefs output.
func cdecl(name, typ string) string {
// X *[0]byte -> X *void
if strings.HasPrefix(typ, "*[0]") {
typ = "*void"
}
// X [4]byte -> X[4] byte
for strings.HasPrefix(typ, "[") {
i := strings.Index(typ, "]") + 1
name = name + typ[:i]
typ = typ[i:]
}
// X *byte -> *X byte
for strings.HasPrefix(typ, "*") {
name = "*" + name
typ = typ[1:]
}
// X T -> T X
// Handle the special case: 'unsafe.Pointer' is 'void *'
if typ == "unsafe.Pointer" {
typ = "void"
name = "*" + name
}
return typ + "\t" + name
}
var gofmtBuf bytes.Buffer
// gofmt returns the gofmt-formatted string for an AST node.

View file

@ -6,7 +6,7 @@
// TODO(rsc):
// Emit correct line number annotations.
// Make 6g understand the annotations.
// Make gc understand the annotations.
package main
@ -33,6 +33,7 @@ type Package struct {
PtrSize int64
IntSize int64
GccOptions []string
GccIsClang bool
CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS)
Written map[string]bool
Name map[string]*Name // accumulated Name from Files
@ -87,7 +88,7 @@ type Name struct {
Const string // constant definition
}
// IsVar returns true if Kind is either "var" or "fpvar"
// IsVar reports whether Kind is either "var" or "fpvar"
func (n *Name) IsVar() bool {
return n.Kind == "var" || n.Kind == "fpvar"
}
@ -98,6 +99,7 @@ func (n *Name) IsVar() bool {
type ExpFunc struct {
Func *ast.FuncDecl
ExpName string // name to use from C
Doc string
}
// A TypeRepr contains the string representation of a type.
@ -174,15 +176,18 @@ var cPrefix string
var fset = token.NewFileSet()
var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
var dynout = flag.String("dynout", "", "write -dynobj output to this file")
var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
var dynout = flag.String("dynout", "", "write -dynimport output to this file")
var dynpackage = flag.String("dynpackage", "main", "set Go package for -dynimport output")
var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in -dynimport mode")
// These flags are for bootstrapping a new Go implementation,
// to generate Go and C headers that match the data layout and
// This flag is for bootstrapping a new Go implementation,
// to generate Go types that match the data layout and
// constant values used in the host's C libraries and system calls.
var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output")
var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C file to standard output")
var objDir = flag.String("objdir", "", "object directory")
var importPath = flag.String("importpath", "", "import path of package being built (for comments in generated files)")
var exportHeader = flag.String("exportheader", "", "where to write export header if any exported functions")
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
@ -208,12 +213,7 @@ func main() {
return
}
if *godefs && *cdefs {
fmt.Fprintf(os.Stderr, "cgo: cannot use -cdefs and -godefs together\n")
os.Exit(2)
}
if *godefs || *cdefs {
if *godefs {
// Generating definitions pulled from header files,
// to be checked into Go repositories.
// Line numbers are just noise.
@ -305,14 +305,12 @@ func main() {
p.Record(f)
if *godefs {
os.Stdout.WriteString(p.godefs(f, input))
} else if *cdefs {
os.Stdout.WriteString(p.cdefs(f, input))
} else {
p.writeOutput(f, input)
}
}
if !*godefs && !*cdefs {
if !*godefs {
p.writeDefs()
}
if nerrors > 0 {

View file

@ -13,6 +13,7 @@ import (
"go/ast"
"go/printer"
"go/token"
"io"
"os"
"sort"
"strings"
@ -20,11 +21,17 @@ import (
var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
// writeDefs creates output files to be compiled by gc and gcc.
func (p *Package) writeDefs() {
fgo2 := creat(*objDir + "_cgo_gotypes.go")
fc := creat(*objDir + "_cgo_defun.c")
var fgo2, fc io.Writer
f := creat(*objDir + "_cgo_gotypes.go")
defer f.Close()
fgo2 = f
if *gccgo {
f := creat(*objDir + "_cgo_defun.c")
defer f.Close()
fc = f
}
fm := creat(*objDir + "_cgo_main.c")
var gccgoInit bytes.Buffer
@ -34,7 +41,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
if k == "LDFLAGS" && !*gccgo {
for _, arg := range v {
fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
}
}
}
@ -44,14 +51,17 @@ func (p *Package) writeDefs() {
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, "char* _cgo_topofstack(void) { return (char*)0; }\n")
} else {
// If we're not importing runtime/cgo, we *are* runtime/cgo,
// which provides crosscall2. We just need a prototype.
// which provides these functions. We just need a prototype.
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done();\n")
}
fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n")
// Write second Go output: definitions of _C_xxx.
// In a separate file so that the import of "unsafe" does not
@ -68,6 +78,13 @@ func (p *Package) writeDefs() {
}
fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
if !*gccgo {
fmt.Fprintf(fgo2, "//go:linkname _Cgo_always_false runtime.cgoAlwaysFalse\n")
fmt.Fprintf(fgo2, "var _Cgo_always_false bool\n")
fmt.Fprintf(fgo2, "//go:linkname _Cgo_use runtime.cgoUse\n")
fmt.Fprintf(fgo2, "func _Cgo_use(interface{})\n")
}
typedefNames := make([]string, 0, len(typedef))
for name := range typedef {
typedefNames = append(typedefNames, name)
@ -88,7 +105,6 @@ func (p *Package) writeDefs() {
if *gccgo {
fmt.Fprint(fc, p.cPrologGccgo())
} else {
fmt.Fprint(fc, cProlog)
fmt.Fprint(fgo2, goProlog)
}
@ -102,44 +118,44 @@ func (p *Package) writeDefs() {
}
if !cVars[n.C] {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
if !*gccgo {
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
if *gccgo {
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
} else {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
}
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
cVars[n.C] = true
}
var amp string
var node ast.Node
if n.Kind == "var" {
amp = "&"
node = &ast.StarExpr{X: n.Type.Go}
} else if n.Kind == "fpvar" {
node = n.Type.Go
if *gccgo {
amp = "&"
}
} else {
panic(fmt.Errorf("invalid var kind %q", n.Kind))
}
if *gccgo {
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
} else {
fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
fmt.Fprintf(fc, "\n")
}
fmt.Fprintf(fc, "\n")
fmt.Fprintf(fgo2, "var %s ", n.Mangle)
conf.Fprint(fgo2, fset, node)
if !*gccgo {
fmt.Fprintf(fgo2, " = (")
conf.Fprint(fgo2, fset, node)
fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
}
fmt.Fprintf(fgo2, "\n")
}
fmt.Fprintf(fc, "\n")
if *gccgo {
fmt.Fprintf(fc, "\n")
}
for _, key := range nameKeys(p.Name) {
n := p.Name[key]
@ -152,14 +168,37 @@ func (p *Package) writeDefs() {
for _, key := range nameKeys(p.Name) {
n := p.Name[key]
if n.FuncType != nil {
p.writeDefsFunc(fc, fgo2, n)
p.writeDefsFunc(fgo2, n)
}
}
fgcc := creat(*objDir + "_cgo_export.c")
fgcch := creat(*objDir + "_cgo_export.h")
if *gccgo {
p.writeGccgoExports(fgo2, fc, fm)
p.writeGccgoExports(fgo2, fm, fgcc, fgcch)
} else {
p.writeExports(fgo2, fc, fm)
p.writeExports(fgo2, fm, fgcc, fgcch)
}
if err := fgcc.Close(); err != nil {
fatalf("%s", err)
}
if err := fgcch.Close(); err != nil {
fatalf("%s", err)
}
if *exportHeader != "" && len(p.ExpFunc) > 0 {
fexp := creat(*exportHeader)
fgcch, err := os.Open(*objDir + "_cgo_export.h")
if err != nil {
fatalf("%s", err)
}
_, err = io.Copy(fexp, fgcch)
if err != nil {
fatalf("%s", err)
}
if err = fexp.Close(); err != nil {
fatalf("%s", err)
}
}
init := gccgoInit.String()
@ -169,9 +208,6 @@ func (p *Package) writeDefs() {
fmt.Fprint(fc, init)
fmt.Fprintln(fc, "}")
}
fgo2.Close()
fc.Close()
}
func dynimport(obj string) {
@ -184,13 +220,15 @@ func dynimport(obj string) {
stdout = f
}
fmt.Fprintf(stdout, "package %s\n", *dynpackage)
if f, err := elf.Open(obj); err == nil {
if *dynlinker {
// Emit the cgo_dynamic_linker line.
if sec := f.Section(".interp"); sec != nil {
if data, err := sec.Data(); err == nil && len(data) > 1 {
// skip trailing \0 in data
fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
}
}
}
@ -203,14 +241,14 @@ func dynimport(obj string) {
if s.Version != "" {
targ += "#" + s.Version
}
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
}
lib, err := f.ImportedLibraries()
if err != nil {
fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
}
for _, l := range lib {
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
}
return
}
@ -224,14 +262,14 @@ func dynimport(obj string) {
if len(s) > 0 && s[0] == '_' {
s = s[1:]
}
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
}
lib, err := f.ImportedLibraries()
if err != nil {
fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
}
for _, l := range lib {
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
}
return
}
@ -244,7 +282,7 @@ func dynimport(obj string) {
for _, s := range sym {
ss := strings.Split(s, ":")
name := strings.Split(ss[0], "@")[0]
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
}
return
}
@ -252,10 +290,10 @@ func dynimport(obj string) {
fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
}
// Construct a gcc struct matching the 6c argument frame.
// Construct a gcc struct matching the gc argument frame.
// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
// These assumptions are checked by the gccProlog.
// Also assumes that 6c convention is to word-align the
// Also assumes that gc convention is to word-align the
// input and output parameters.
func (p *Package) structType(n *Name) (string, int64) {
var buf bytes.Buffer
@ -304,7 +342,7 @@ func (p *Package) structType(n *Name) (string, int64) {
return buf.String(), off
}
func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
name := n.Go
gtype := n.FuncType.Go
void := gtype.Results == nil || len(gtype.Results.List) == 0
@ -396,11 +434,11 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
return
}
// C wrapper calls into gcc, passing a pointer to the argument frame.
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
fmt.Fprintf(fc, "void %s(void*);\n", cname)
fmt.Fprintf(fc, "#pragma dataflag NOPTR\n")
fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
// Wrapper calls into gcc, passing a pointer to the argument frame.
fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
nret := 0
if !void {
@ -412,7 +450,6 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
}
fmt.Fprint(fgo2, "\n")
fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
@ -428,16 +465,20 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
if n.AddError {
prefix = "errno := "
}
fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg)
fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall(%s, %s)\n", prefix, cname, arg)
if n.AddError {
fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
}
fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n")
for i := range d.Type.Params.List {
fmt.Fprintf(fgo2, "\t\t_Cgo_use(p%d)\n", i)
}
fmt.Fprintf(fgo2, "\t}\n")
fmt.Fprintf(fgo2, "\treturn\n")
fmt.Fprintf(fgo2, "}\n")
}
// writeOutput creates stubs for a specific source file to be compiled by 6g
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
// writeOutput creates stubs for a specific source file to be compiled by gc
func (p *Package) writeOutput(f *File, srcfile string) {
base := srcfile
if strings.HasSuffix(base, ".go") {
@ -454,7 +495,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
conf.Fprint(fgo1, fset, f.AST)
// While we process the vars and funcs, also write 6c and gcc output.
// While we process the vars and funcs, also write gcc output.
// Gcc output starts with the preamble.
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
fmt.Fprintf(fgcc, "%s\n", gccProlog)
@ -516,7 +557,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
if n.AddError {
fmt.Fprintf(fgcc, "\terrno = 0;\n")
}
// We're trying to write a gcc struct that matches 6c/8c/5c's layout.
// We're trying to write a gcc struct that matches gc's layout.
// Use packed attribute to force no padding in this struct in case
// gcc has different packing requirements.
fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
@ -612,13 +653,13 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
}
// packedAttribute returns host compiler struct attribute that will be
// used to match 6c/8c/5c's struct layout. For example, on 386 Windows,
// gcc wants to 8-align int64s, but 8c does not.
// used to match gc's struct layout. For example, on 386 Windows,
// gcc wants to 8-align int64s, but gc does not.
// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
// and http://golang.org/issue/5603.
// and https://golang.org/issue/5603.
func (p *Package) packedAttribute() string {
s := "__attribute__((__packed__"
if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
if !p.GccIsClang && (goarch == "amd64" || goarch == "386") {
s += ", __gcc_struct__"
}
return s + "))"
@ -626,23 +667,19 @@ func (p *Package) packedAttribute() string {
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fc, fm *os.File) {
fgcc := creat(*objDir + "_cgo_export.c")
fgcch := creat(*objDir + "_cgo_export.h")
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
fmt.Fprintf(fgcch, "%s\n", p.Preamble)
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
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 \"_cgo_export.h\"\n")
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\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")
for _, exp := range p.ExpFunc {
fn := exp.Func
// Construct a gcc struct matching the 6c argument and
// Construct a gcc struct matching the gc argument and
// result frame. The gcc struct will be compiled with
// __attribute__((packed)) so all padding must be accounted
// for explicitly.
@ -728,11 +765,16 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
})
s += ")"
if len(exp.Doc) > 0 {
fmt.Fprintf(fgcch, "\n%s", exp.Doc)
}
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
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%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)
@ -758,20 +800,21 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
}
fmt.Fprintf(fgcc, "}\n")
// Build the wrapper function compiled by 6c/8c
// Build the wrapper function compiled by gc.
goname := exp.Func.Name.Name
if fn.Recv != nil {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
fmt.Fprintf(fc, "void\n")
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "{\n")
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
fmt.Fprintf(fc, "}\n")
fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted
fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", 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, "}\n")
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
@ -814,23 +857,20 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgo2, "}\n")
}
}
fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
}
// Write out the C header allowing C code to call exported gccgo functions.
func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fgcc := creat(*objDir + "_cgo_export.c")
fgcch := creat(*objDir + "_cgo_export.h")
func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
gccgoSymbolPrefix := p.gccgoSymbolPrefix()
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
fmt.Fprintf(fgcch, "%s\n", p.Preamble)
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
p.writeExportHeader(fgcch)
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
for _, exp := range p.ExpFunc {
fn := exp.Func
@ -851,6 +891,7 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
})
default:
// Declare a result struct.
fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
forFieldList(fntype.Results,
func(i int, atype ast.Expr) {
@ -880,6 +921,10 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprintf(cdeclBuf, ")")
cParams := cdeclBuf.String()
if len(exp.Doc) > 0 {
fmt.Fprintf(fgcch, "\n%s", exp.Doc)
}
// We need to use a name that will be exported by the
// Go code; otherwise gccgo will make it static and we
// will not be able to link against it from the C
@ -900,6 +945,8 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgcc, "\n")
fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n")
fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n")
fmt.Fprint(fgcc, "\t")
if resultCount > 0 {
fmt.Fprint(fgcc, "return ")
@ -919,7 +966,8 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgcc, "}\n")
// Dummy declaration for _cgo_main.c
fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
fmt.Fprint(fm, "\n")
// For gccgo we use a wrapper function in Go, in order
// to call CgocallBack and CgocallBackDone.
@ -974,6 +1022,24 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgo2, ")\n")
fmt.Fprint(fgo2, "}\n")
}
fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
}
// writeExportHeader writes out the start of the _cgo_export.h file.
func (p *Package) writeExportHeader(fgcch io.Writer) {
fmt.Fprintf(fgcch, "/* Created by \"go tool cgo\" - DO NOT EDIT. */\n\n")
pkg := *importPath
if pkg == "" {
pkg = p.PackagePath
}
fmt.Fprintf(fgcch, "/* package %s */\n\n", pkg)
fmt.Fprintf(fgcch, "/* Start of preamble from import \"C\" comments. */\n\n")
fmt.Fprintf(fgcch, "%s\n", p.Preamble)
fmt.Fprintf(fgcch, "\n/* End of preamble from import \"C\" comments. */\n\n")
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
}
// Return the package prefix when using gccgo.
@ -1164,60 +1230,39 @@ char *CString(_GoString_);
void *_CMalloc(size_t);
`
const cProlog = `
#include "runtime.h"
#include "cgocall.h"
#include "textflag.h"
#pragma dataflag NOPTR
static void *cgocall_errno = runtime·cgocall_errno;
#pragma dataflag NOPTR
void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
#pragma dataflag NOPTR
static void *runtime_gostring = runtime·gostring;
#pragma dataflag NOPTR
void *·_cgo_runtime_gostring = &runtime_gostring;
#pragma dataflag NOPTR
static void *runtime_gostringn = runtime·gostringn;
#pragma dataflag NOPTR
void *·_cgo_runtime_gostringn = &runtime_gostringn;
#pragma dataflag NOPTR
static void *runtime_gobytes = runtime·gobytes;
#pragma dataflag NOPTR
void *·_cgo_runtime_gobytes = &runtime_gobytes;
#pragma dataflag NOPTR
static void *runtime_cmalloc = runtime·cmalloc;
#pragma dataflag NOPTR
void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
void ·_Cerrno(void*, int32);
`
const goProlog = `
var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32
var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer
//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)
`
const goStringDef = `
var _cgo_runtime_gostring func(*_Ctype_char) string
//go:linkname _cgo_runtime_gostring runtime.gostring
func _cgo_runtime_gostring(*_Ctype_char) string
func _Cfunc_GoString(p *_Ctype_char) string {
return _cgo_runtime_gostring(p)
}
`
const goStringNDef = `
var _cgo_runtime_gostringn func(*_Ctype_char, int) string
//go:linkname _cgo_runtime_gostringn runtime.gostringn
func _cgo_runtime_gostringn(*_Ctype_char, int) string
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
return _cgo_runtime_gostringn(p, int(l))
}
`
const goBytesDef = `
var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte
//go:linkname _cgo_runtime_gobytes runtime.gobytes
func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
return _cgo_runtime_gobytes(p, int(l))
}
@ -1310,6 +1355,11 @@ func (p *Package) gccExportHeaderProlog() string {
}
const gccExportHeaderProlog = `
/* Start of boilerplate cgo prologue. */
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
@ -1326,9 +1376,44 @@ typedef double GoFloat64;
typedef __complex float GoComplex64;
typedef __complex double GoComplex128;
// static assertion to make sure the file is being used on architecture
// at least with matching size of GoInt.
typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1];
typedef struct { char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
`
// gccExportHeaderEpilog goes at the end of the generated header file.
const gccExportHeaderEpilog = `
#ifdef __cplusplus
}
#endif
`
// gccgoExportFileProlog is written to the _cgo_export.c file when
// using gccgo.
// We use weak declarations, and test the addresses, so that this code
// works with older versions of gccgo.
const gccgoExportFileProlog = `
extern _Bool runtime_iscgo __attribute__ ((weak));
static void GoInit(void) __attribute__ ((constructor));
static void GoInit(void) {
if(&runtime_iscgo)
runtime_iscgo = 1;
}
extern void _cgo_wait_runtime_init_done() __attribute__ ((weak));
`

View file

@ -55,7 +55,7 @@ func error_(pos token.Pos, msg string, args ...interface{}) {
fmt.Fprintf(os.Stderr, "\n")
}
// isName returns true if s is a valid C identifier
// isName reports whether s is a valid C identifier
func isName(s string) bool {
for i, v := range s {
if v != '_' && (v < 'A' || v > 'Z') && (v < 'a' || v > 'z') && (v < '0' || v > '9') {

1482
libgo/go/cmd/go/alldocs.go Normal file

File diff suppressed because it is too large Load diff

View file

@ -17,11 +17,19 @@ import (
var errHTTP = errors.New("no http in bootstrap go command")
type httpError struct {
statusCode int
}
func (e *httpError) Error() string {
panic("unreachable")
}
func httpGET(url string) ([]byte, error) {
return nil, errHTTP
}
func httpsOrHTTP(importPath string) (string, io.ReadCloser, error) {
func httpsOrHTTP(importPath string, security securityMode) (string, io.ReadCloser, error) {
return "", nil, errHTTP
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,6 @@ func mkEnv() []envVar {
env := []envVar{
{"GOARCH", goarch},
{"GOBIN", gobin},
{"GOCHAR", archChar},
{"GOEXE", exeSuffix},
{"GOHOSTARCH", runtime.GOARCH},
{"GOHOSTOS", runtime.GOOS},
@ -45,6 +44,7 @@ func mkEnv() []envVar {
{"GORACE", os.Getenv("GORACE")},
{"GOROOT", goroot},
{"GOTOOLDIR", toolDir},
{"GO15VENDOREXPERIMENT", os.Getenv("GO15VENDOREXPERIMENT")},
// disable escape codes in clang errors
{"TERM", "dumb"},

View file

@ -11,7 +11,7 @@ var cmdFix = &Command{
Long: `
Fix runs the Go fix command on the packages named by the import paths.
For more about fix, see 'godoc fix'.
For more about fix, see 'go doc cmd/fix'.
For more about specifying packages, see 'go help packages'.
To run fix with specific options, run 'go tool fix'.
@ -25,6 +25,6 @@ func runFix(cmd *Command, args []string) {
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
run(stringList(tool("fix"), relPaths(pkg.allgofiles)))
run(stringList(buildToolExec, tool("fix"), relPaths(pkg.allgofiles)))
}
}

View file

@ -4,6 +4,11 @@
package main
import (
"os"
"path/filepath"
)
func init() {
addBuildFlagsNX(cmdFmt)
}
@ -16,7 +21,7 @@ var cmdFmt = &Command{
Fmt runs the command 'gofmt -l -w' on the packages named
by the import paths. It prints the names of the files that are modified.
For more about gofmt, see 'godoc gofmt'.
For more about gofmt, see 'go doc cmd/gofmt'.
For more about specifying packages, see 'go help packages'.
The -n flag prints commands that would be executed.
@ -29,10 +34,31 @@ See also: go fix, go vet.
}
func runFmt(cmd *Command, args []string) {
gofmt := gofmtPath()
for _, pkg := range packages(args) {
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
run(stringList("gofmt", "-l", "-w", relPaths(pkg.allgofiles)))
run(stringList(gofmt, "-l", "-w", relPaths(pkg.allgofiles)))
}
}
func gofmtPath() string {
gofmt := "gofmt"
if toolIsWindows {
gofmt += toolWindowsExtension
}
gofmtPath := filepath.Join(gobin, gofmt)
if _, err := os.Stat(gofmtPath); err == nil {
return gofmtPath
}
gofmtPath = filepath.Join(goroot, "bin", gofmt)
if _, err := os.Stat(gofmtPath); err == nil {
return gofmtPath
}
// fallback to looking for gofmt in $PATH
return "gofmt"
}

View file

@ -13,11 +13,11 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"unicode"
"unicode/utf8"
)
var cmdGenerate = &Command{
@ -62,8 +62,12 @@ Go generate sets several variables when it runs the generator:
The execution operating system (linux, windows, etc.)
$GOFILE
The base name of the file.
$GOLINE
The line number of the directive in the source file.
$GOPACKAGE
The name of the package of the file containing the directive.
$DOLLAR
A dollar sign.
Other than variable substitution and quoted-string evaluation, no
special processing such as "globbing" is performed on the command
@ -106,9 +110,10 @@ The generator is run in the package's source directory.
Go generate accepts one specific flag:
-run=""
TODO: This flag is unimplemented.
if non-empty, specifies a regular expression to
select directives whose command matches the expression.
if non-empty, specifies a regular expression to select
directives whose full original source text (excluding
any trailing spaces and final newline) matches the
expression.
It also accepts the standard build flags -v, -n, and -x.
The -v flag prints the names of packages and files as they are
@ -120,7 +125,10 @@ For more about specifying packages, see 'go help packages'.
`,
}
var generateRunFlag string // generate -run flag
var (
generateRunFlag string // generate -run flag
generateRunRE *regexp.Regexp // compiled expression for -run
)
func init() {
addBuildFlags(cmdGenerate)
@ -128,6 +136,13 @@ func init() {
}
func runGenerate(cmd *Command, args []string) {
if generateRunFlag != "" {
var err error
generateRunRE, err = regexp.Compile(generateRunFlag)
if err != nil {
log.Fatalf("generate: %s", err)
}
}
// Even if the arguments are .go files, this loop suffices.
for _, pkg := range packages(args) {
for _, file := range pkg.gofiles {
@ -163,7 +178,7 @@ type Generator struct {
file string // base name of file.
pkg string
commands map[string][]string
lineNum int
lineNum int // current line number.
}
// run runs the generators in the current file.
@ -221,6 +236,11 @@ func (g *Generator) run() (ok bool) {
if !isGoGenerate(buf) {
continue
}
if generateRunFlag != "" {
if !generateRunRE.Match(bytes.TrimSpace(buf)) {
continue
}
}
words := g.split(string(buf))
if len(words) == 0 {
@ -306,7 +326,7 @@ Words:
}
// Substitute environment variables.
for i, word := range words {
words[i] = g.expandEnv(word)
words[i] = os.Expand(word, g.expandVar)
}
return words
}
@ -322,38 +342,25 @@ func (g *Generator) errorf(format string, args ...interface{}) {
panic(stop)
}
// expandEnv expands any $XXX invocations in word.
func (g *Generator) expandEnv(word string) string {
if !strings.ContainsRune(word, '$') {
return word
// expandVar expands the $XXX invocation in word. It is called
// by os.Expand.
func (g *Generator) expandVar(word string) string {
switch word {
case "GOARCH":
return buildContext.GOARCH
case "GOOS":
return buildContext.GOOS
case "GOFILE":
return g.file
case "GOLINE":
return fmt.Sprint(g.lineNum)
case "GOPACKAGE":
return g.pkg
case "DOLLAR":
return "$"
default:
return os.Getenv(word)
}
var buf bytes.Buffer
var w int
var r rune
for i := 0; i < len(word); i += w {
r, w = utf8.DecodeRuneInString(word[i:])
if r != '$' {
buf.WriteRune(r)
continue
}
w += g.identLength(word[i+w:])
envVar := word[i+1 : i+w]
var sub string
switch envVar {
case "GOARCH":
sub = runtime.GOARCH
case "GOOS":
sub = runtime.GOOS
case "GOFILE":
sub = g.file
case "GOPACKAGE":
sub = g.pkg
default:
sub = os.Getenv(envVar)
}
buf.WriteString(sub)
}
return buf.String()
}
// identLength returns the length of the identifier beginning the string.
@ -395,7 +402,7 @@ func (g *Generator) exec(words []string) {
"GOFILE=" + g.file,
"GOPACKAGE=" + g.pkg,
}
cmd.Env = mergeEnvLists(env, os.Environ())
cmd.Env = mergeEnvLists(env, origEnv)
err := cmd.Run()
if err != nil {
g.errorf("running %q: %s", words[0], err)

View file

@ -26,6 +26,7 @@ var splitTests = []splitTest{
{"$GOPACKAGE", []string{"sys"}},
{"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}},
{"/$XXNOTDEFINED/", []string{"//"}},
{"/$DOLLAR/", []string{"/$/"}},
{"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}},
}

View file

@ -16,7 +16,7 @@ import (
)
var cmdGet = &Command{
UsageLine: "get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages]",
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,
@ -33,6 +33,9 @@ of the original.
The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code.
The -insecure flag permits fetching from repositories and resolving
custom domains using insecure schemes such as HTTP. Use with caution.
The -t flag instructs get to also download the packages required to build
the tests for the specified packages.
@ -48,6 +51,10 @@ 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.
If the vendoring experiment is enabled (see 'go help gopath'),
then when go get checks out or updates a Git repository,
it also updates any git submodules referenced by the repository.
For more about specifying packages, see 'go help packages'.
For more about how 'go get' finds source code to
@ -62,6 +69,7 @@ var getF = cmdGet.Flag.Bool("f", false, "")
var getT = cmdGet.Flag.Bool("t", false, "")
var getU = cmdGet.Flag.Bool("u", false, "")
var getFix = cmdGet.Flag.Bool("fix", false, "")
var getInsecure = cmdGet.Flag.Bool("insecure", false, "")
func init() {
addBuildFlags(cmdGet)
@ -73,10 +81,20 @@ func runGet(cmd *Command, args []string) {
fatalf("go get: cannot use -f flag without -u")
}
// Disable any prompting for passwords by Git.
// Only has an effect for 2.3.0 or later, but avoiding
// the prompt in earlier versions is just too hard.
// See golang.org/issue/9341.
os.Setenv("GIT_TERMINAL_PROMPT", "0")
// Phase 1. Download/update.
var stk importStack
mode := 0
if *getT {
mode |= getTestDeps
}
for _, arg := range downloadPaths(args) {
download(arg, &stk, *getT)
download(arg, nil, &stk, mode)
}
exitIfErrors()
@ -92,12 +110,13 @@ func runGet(cmd *Command, args []string) {
}
args = importPaths(args)
packagesForBuild(args)
// Phase 3. Install.
if *getD {
// Download only.
// Check delayed until now so that importPaths
// has a chance to print errors.
// and packagesForBuild have a chance to print errors.
return
}
@ -148,13 +167,30 @@ var downloadRootCache = map[string]bool{}
// download runs the download half of the get command
// for the package named by the argument.
func download(arg string, stk *importStack, getTestDeps bool) {
p := loadPackage(arg, stk)
func download(arg string, parent *Package, stk *importStack, mode int) {
load := func(path string, mode int) *Package {
if parent == nil {
return loadPackage(path, stk)
}
return loadImport(path, parent.Dir, parent, stk, nil, mode)
}
p := load(arg, mode)
if p.Error != nil && p.Error.hard {
errorf("%s", p.Error)
return
}
// loadPackage inferred the canonical ImportPath from arg.
// Use that in the following to prevent hysteresis effects
// in e.g. downloadCache and packageCache.
// This allows invocations such as:
// mkdir -p $GOPATH/src/github.com/user
// cd $GOPATH/src/github.com/user
// go get ./foo
// see: golang.org/issue/9767
arg = p.ImportPath
// There's nothing to do if this is a package in the standard library.
if p.Standard {
return
@ -163,7 +199,7 @@ func download(arg string, stk *importStack, getTestDeps bool) {
// Only process each package once.
// (Unless we're fetching test dependencies for this package,
// in which case we want to process it again.)
if downloadCache[arg] && !getTestDeps {
if downloadCache[arg] && mode&getTestDeps == 0 {
return
}
downloadCache[arg] = true
@ -175,7 +211,7 @@ func download(arg string, stk *importStack, getTestDeps bool) {
// Download if the package is missing, or update if we're using -u.
if p.Dir == "" || *getU {
// The actual download.
stk.push(p.ImportPath)
stk.push(arg)
err := downloadPackage(p)
if err != nil {
errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
@ -183,6 +219,17 @@ func download(arg string, stk *importStack, getTestDeps bool) {
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}
// If the argument has a wildcard in it, re-evaluate the wildcard.
// We delay this until after reloadPackage so that the old entry
@ -208,9 +255,10 @@ func download(arg string, stk *importStack, getTestDeps bool) {
pkgs = pkgs[:0]
for _, arg := range args {
stk.push(arg)
p := loadPackage(arg, stk)
stk.pop()
// Note: load calls loadPackage or loadImport,
// which push arg onto stk already.
// Do not push here too, or else stk will say arg imports arg.
p := load(arg, mode)
if p.Error != nil {
errorf("%s", p.Error)
continue
@ -223,7 +271,7 @@ func download(arg string, stk *importStack, getTestDeps bool) {
// due to wildcard expansion.
for _, p := range pkgs {
if *getFix {
run(stringList(tool("fix"), relPaths(p.allgofiles)))
run(buildToolExec, stringList(tool("fix"), relPaths(p.allgofiles)))
// The imports might have changed, so reload again.
p = reloadPackage(arg, stk)
@ -240,18 +288,31 @@ func download(arg string, stk *importStack, getTestDeps bool) {
}
// Process dependencies, now that we know what they are.
for _, dep := range p.deps {
for _, path := range p.Imports {
if path == "C" {
continue
}
// Don't get test dependencies recursively.
download(dep.ImportPath, stk, false)
// Imports is already vendor-expanded.
download(path, p, stk, 0)
}
if getTestDeps {
if mode&getTestDeps != 0 {
// Process test dependencies when -t is specified.
// (Don't get test dependencies for test dependencies.)
// We pass useVendor here because p.load does not
// vendor-expand TestImports and XTestImports.
// The call to loadImport inside download needs to do that.
for _, path := range p.TestImports {
download(path, stk, false)
if path == "C" {
continue
}
download(path, p, stk, useVendor)
}
for _, path := range p.XTestImports {
download(path, stk, false)
if path == "C" {
continue
}
download(path, p, stk, useVendor)
}
}
@ -269,6 +330,12 @@ func downloadPackage(p *Package) error {
repo, rootPath string
err error
)
security := secure
if *getInsecure {
security = insecure
}
if p.build.SrcRoot != "" {
// Directory exists. Look for checkout along path to src.
vcs, rootPath, err = vcsForDir(p)
@ -278,10 +345,15 @@ func downloadPackage(p *Package) error {
repo = "<local>" // should be unused; make distinctive
// Double-check where it came from.
if *getU && vcs.remoteRepo != nil && !*getF {
if *getU && vcs.remoteRepo != nil {
dir := filepath.Join(p.build.SrcRoot, rootPath)
if remote, err := vcs.remoteRepo(vcs, dir); err == nil {
if rr, err := repoRootForImportPath(p.ImportPath); err == nil {
remote, err := vcs.remoteRepo(vcs, dir)
if err != nil {
return err
}
repo = remote
if !*getF {
if rr, err := repoRootForImportPath(p.ImportPath, security); err == nil {
repo := rr.repo
if rr.vcs.resolveRepo != nil {
resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
@ -289,7 +361,7 @@ func downloadPackage(p *Package) error {
repo = resolved
}
}
if remote != repo {
if remote != repo && p.ImportComment != "" {
return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
}
}
@ -298,12 +370,15 @@ func downloadPackage(p *Package) error {
} else {
// Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository.
rr, err := repoRootForImportPath(p.ImportPath)
rr, err := repoRootForImportPath(p.ImportPath, security)
if err != nil {
return err
}
vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
}
if !vcs.isSecure(repo) && !*getInsecure {
return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
}
if p.build.SrcRoot == "" {
// Package not found. Put in first directory of $GOPATH.

2389
libgo/go/cmd/go/go_test.go Normal file

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,7 @@ var helpC = &Command{
There are two different ways to call between Go and C/C++ code.
The first is the cgo tool, which is part of the Go distribution. For
information on how to use it see the cgo documentation (godoc cmd/cgo).
information on how to use it see the cgo documentation (go doc cmd/cgo).
The second is the SWIG program, which is a general tool for
interfacing between languages. For information on SWIG see
@ -47,7 +47,7 @@ environment variable (see 'go help gopath').
If no import paths are given, the action applies to the
package in the current directory.
There are three reserved names for paths that should not be used
There are four reserved names for paths that should not be used
for packages to be built with the go tool:
- "main" denotes the top-level package in a stand-alone executable.
@ -59,6 +59,9 @@ system.
- "std" is like all but expands to just the packages in the standard
Go library.
- "cmd" expands to the Go repository's commands and their
internal libraries.
An import path is a pattern if it includes one or more "..." wildcards,
each of which can match any string, including the empty string and
strings containing slashes. Such a pattern expands to all package
@ -74,7 +77,7 @@ By convention, this is arranged by starting each path with a
unique prefix that belongs to you. For example, paths used
internally at Google all begin with 'google', and paths
denoting remote repositories begin with the path to the code,
such as 'code.google.com/p/project'.
such as 'github.com/user/repo'.
As a special case, if the package list is a list of .go files from a
single directory, the command is applied to a single synthesized
@ -192,7 +195,7 @@ example.org/repo or repo.git.
When a version control system supports multiple protocols,
each is tried in turn when downloading. For example, a Git
download tries git://, then https://, then http://.
download tries https://, then git+ssh://.
If the import path is not a known code hosting site and also lacks a
version control qualifier, the go tool attempts to fetch the import
@ -208,6 +211,10 @@ root. It must be a prefix or an exact match of the package being
fetched with "go get". If it's not an exact match, another http
request is made at the prefix to verify the <meta> tags match.
The meta tag should appear as early in the file as possible.
In particular, it should appear before any raw JavaScript or CSS,
to avoid confusing the go command's restricted parser.
The vcs is one of "git", "hg", "svn", etc,
The repo-root is the root of the version control system
@ -217,10 +224,10 @@ For example,
import "example.org/pkg/foo"
will result in the following request(s):
will result in the following requests:
https://example.org/pkg/foo?go-get=1 (preferred)
http://example.org/pkg/foo?go-get=1 (fallback)
http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure)
If that page contains the meta tag
@ -254,6 +261,11 @@ 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 the vendoring experiment 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.
See https://golang.org/s/go14customimport for details.
`,
}
@ -275,10 +287,10 @@ standard Go tree.
Each directory listed in GOPATH must have a prescribed structure:
The src/ directory holds source code. The path below 'src'
The src directory holds source code. The path below src
determines the import path or executable name.
The pkg/ directory holds installed package objects.
The pkg directory holds installed package objects.
As in the Go tree, each target operating system and
architecture pair has its own subdirectory of pkg
(pkg/GOOS_GOARCH).
@ -287,11 +299,11 @@ If DIR is a directory listed in the GOPATH, a package with
source in DIR/src/foo/bar can be imported as "foo/bar" and
has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
The bin/ directory holds compiled commands.
The bin directory holds compiled commands.
Each command is named for its source directory, but only
the final element, not the entire path. That is, the
command with source in DIR/src/foo/quux is installed into
DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped
DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped
so that you can add DIR/bin to your PATH to get at the
installed commands. If the GOBIN environment variable is
set, commands are installed to the directory it names instead
@ -318,6 +330,168 @@ Here's an example directory layout:
Go searches each directory listed in GOPATH to find source code,
but new packages are always downloaded into the first directory
in the list.
See https://golang.org/doc/code.html for an example.
Internal Directories
Code in or below a directory named "internal" is importable only
by code in the directory tree rooted at the parent of "internal".
Here's an extended version of the directory layout above:
/home/user/gocode/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
internal/
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
The code in z.go is imported as "foo/internal/baz", but that
import statement can only appear in source files in the subtree
rooted at foo. The source files foo/f.go, foo/bar/x.go, and
foo/quux/y.go can all import "foo/internal/baz", but the source file
crash/bang/b.go cannot.
See https://golang.org/s/go14internal for details.
Vendor Directories
Go 1.5 includes experimental support for using local copies
of external dependencies to satisfy imports of those dependencies,
often referred to as vendoring. Setting the environment variable
GO15VENDOREXPERIMENT=1 enables that experimental support.
When the vendor experiment is enabled,
code below a directory named "vendor" is importable only
by code in the directory tree rooted at the parent of "vendor",
and only using an import path that omits the prefix up to and
including the vendor element.
Here's the example from the previous section,
but with the "internal" directory renamed to "vendor"
and a new foo/vendor/crash/bang directory added:
/home/user/gocode/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
vendor/
crash/
bang/ (go code in package bang)
b.go
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
The same visibility rules apply as for internal, but the code
in z.go is imported as "baz", not as "foo/vendor/baz".
Code in vendor directories deeper in the source tree shadows
code in higher directories. Within the subtree rooted at foo, an import
of "crash/bang" resolves to "foo/vendor/crash/bang", not the
top-level "crash/bang".
Code in vendor directories is not subject to import path
checking (see 'go help importpath').
When the vendor experiment is enabled, 'go get' checks out
submodules when checking out or updating a git repository
(see 'go help get').
The vendoring semantics are an experiment, and they may change
in future releases. Once settled, they will be on by default.
See https://golang.org/s/go15vendor for details.
`,
}
var helpEnvironment = &Command{
UsageLine: "environment",
Short: "environment variables",
Long: `
The go command, and the tools it invokes, examine a few different
environment variables. For many of these, you can see the default
value of on your system by running 'go env NAME', where NAME is the
name of the variable.
General-purpose environment variables:
GCCGO
The gccgo command to run for 'go build -compiler=gccgo'.
GOARCH
The architecture, or processor, for which to compile code.
Examples are amd64, 386, arm, ppc64.
GOBIN
The directory where 'go install' will install a command.
GOOS
The operating system for which to compile code.
Examples are linux, darwin, windows, netbsd.
GOPATH
See 'go help gopath'.
GORACE
Options for the race detector.
See https://golang.org/doc/articles/race_detector.html.
GOROOT
The root of the go tree.
Environment variables for use with cgo:
CC
The command to use to compile C code.
CGO_ENABLED
Whether the cgo command is supported. Either 0 or 1.
CGO_CFLAGS
Flags that cgo will pass to the compiler when compiling
C code.
CGO_CPPFLAGS
Flags that cgo will pass to the compiler when compiling
C or C++ code.
CGO_CXXFLAGS
Flags that cgo will pass to the compiler when compiling
C++ code.
CGO_LDFLAGS
Flags that cgo will pass to the compiler when linking.
CXX
The command to use to compile C++ code.
Architecture-specific environment variables:
GOARM
For GOARCH=arm, the ARM architecture for which to compile.
Valid values are 5, 6, 7.
GO386
For GOARCH=386, the floating point instruction set.
Valid values are 387, sse2.
Special-purpose environment variables:
GOROOT_FINAL
The root of the installed Go tree, when it is
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 1 to enable the Go 1.5 vendoring experiment.
GO_EXTLINK_ENABLED
Whether the linker should use external linking mode
when using -linkmode=auto with code that uses cgo.
Set to 0 to disable external linking mode, 1 to enable it.
`,
}
@ -333,10 +507,9 @@ the extension of the file name. These extensions are:
Go source files.
.c, .h
C source files.
If the package uses cgo, these will be compiled with the
OS-native compiler (typically gcc); otherwise they will be
compiled with the Go-specific support compiler,
5c, 6c, or 8c, etc. as appropriate.
If the package uses cgo or SWIG, these will be compiled with the
OS-native compiler (typically gcc); otherwise they will
trigger an error.
.cc, .cpp, .cxx, .hh, .hpp, .hxx
C++ source files. Only useful with cgo or SWIG, and always
compiled with the OS-native compiler.
@ -345,10 +518,9 @@ the extension of the file name. These extensions are:
compiled with the OS-native compiler.
.s, .S
Assembler source files.
If the package uses cgo, these will be assembled with the
If the package uses cgo or SWIG, these will be assembled with the
OS-native assembler (typically gcc (sic)); otherwise they
will be assembled with the Go-specific support assembler,
5a, 6a, or 8a, etc., as appropriate.
will be assembled with the Go assembler.
.swig, .swigcxx
SWIG definition files.
.syso
@ -360,3 +532,43 @@ at the first item in the file that is not a blank line or //-style
line comment.
`,
}
var helpBuildmode = &Command{
UsageLine: "buildmode",
Short: "description of build modes",
Long: `
The 'go build' and 'go install' commands take a -buildmode argument which
indicates which kind of object file is to be built. Currently supported values
are:
-buildmode=archive
Build the listed non-main packages into .a files. Packages named
main are ignored.
-buildmode=c-archive
Build the listed main package, plus all packages it imports,
into a C archive file. The only callable symbols will be those
functions exported using a cgo //export comment. Requires
exactly one main package to be listed.
-buildmode=c-shared
Build the listed main packages, plus all packages that they
import, into C shared libraries. The only callable symbols will
be those functions exported using a cgo //export comment.
Non-main packages are ignored.
-buildmode=default
Listed main packages are built into executables and listed
non-main packages are built into .a files (the default
behavior).
-buildmode=shared
Combine all the listed non-main packages into a single shared
library that will be used when building with the -linkshared
option. Packages named main are ignored.
-buildmode=exe
Build the listed main packages and everything they import into
executables. Packages not named main are ignored.
`,
}

View file

@ -18,11 +18,25 @@ import (
"log"
"net/http"
"net/url"
"time"
)
// httpClient is the default HTTP client, but a variable so it can be
// changed by tests, without modifying http.DefaultClient.
var httpClient = http.DefaultClient
var impatientHTTPClient = &http.Client{
Timeout: time.Duration(5 * time.Second),
}
type httpError struct {
status string
statusCode int
url string
}
func (e *httpError) Error() string {
return fmt.Sprintf("%s: %s", e.url, e.status)
}
// httpGET returns the data from an HTTP GET request for the given URL.
func httpGET(url string) ([]byte, error) {
@ -32,7 +46,9 @@ func httpGET(url string) ([]byte, error) {
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("%s: %s", url, resp.Status)
err := &httpError{status: resp.Status, statusCode: resp.StatusCode, url: url}
return nil, err
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
@ -43,7 +59,7 @@ func httpGET(url string) ([]byte, error) {
// httpsOrHTTP returns the body of either the importPath's
// https resource or, if unavailable, the http resource.
func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err error) {
func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body io.ReadCloser, err error) {
fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
u, err := url.Parse(scheme + "://" + importPath)
if err != nil {
@ -54,7 +70,11 @@ func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err erro
if buildV {
log.Printf("Fetching %s", urlStr)
}
res, err = httpClient.Get(urlStr)
if security == insecure && scheme == "https" { // fail earlier
res, err = impatientHTTPClient.Get(urlStr)
} else {
res, err = httpClient.Get(urlStr)
}
return
}
closeBody := func(res *http.Response) {
@ -72,7 +92,9 @@ func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err erro
}
}
closeBody(res)
urlStr, res, err = fetch("http")
if security == insecure {
urlStr, res, err = fetch("http")
}
}
if err != nil {
closeBody(res)

View file

@ -21,9 +21,10 @@ List lists the packages named by the import paths, one per line.
The default output shows the package import path:
code.google.com/p/google-api-go-client/books/v1
code.google.com/p/goauth2/oauth
code.google.com/p/sqlite
bytes
encoding/json
github.com/gorilla/mux
golang.org/x/net/html
The -f flag specifies an alternate format for the list, using the
syntax of package template. The default output is equivalent to -f
@ -36,6 +37,7 @@ syntax of package template. The default output is equivalent to -f
Name string // package name
Doc string // package documentation string
Target string // install path
Shlib string // the shared library that contains this package (only set when -linkshared)
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?
@ -126,6 +128,7 @@ var listJson = cmdList.Flag.Bool("json", false, "")
var nl = []byte{'\n'}
func runList(cmd *Command, args []string) {
buildModeInit()
out := newTrackingWriter(os.Stdout)
defer out.w.Flush()
@ -173,6 +176,10 @@ func runList(cmd *Command, args []string) {
}
for _, pkg := range load(args) {
// Show vendor-expanded paths in listing
pkg.TestImports = pkg.vendored(pkg.TestImports)
pkg.XTestImports = pkg.vendored(pkg.XTestImports)
do(pkg)
}
}

View file

@ -5,6 +5,7 @@
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
@ -76,6 +77,7 @@ func (c *Command) Runnable() bool {
var commands = []*Command{
cmdBuild,
cmdClean,
cmdDoc,
cmdEnv,
cmdFix,
cmdFmt,
@ -90,8 +92,10 @@ var commands = []*Command{
cmdVet,
helpC,
helpBuildmode,
helpFileType,
helpGopath,
helpEnvironment,
helpImportPath,
helpPackages,
helpTestflag,
@ -109,6 +113,8 @@ func setExitStatus(n int) {
exitMu.Unlock()
}
var origEnv []string
func main() {
_ = go11tag
flag.Usage = usage
@ -139,7 +145,7 @@ func main() {
fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p)
os.Exit(2)
}
if build.IsLocalImport(p) {
if !filepath.IsAbs(p) {
fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p)
os.Exit(2)
}
@ -151,8 +157,20 @@ func main() {
os.Exit(2)
}
// Set environment (GOOS, GOARCH, etc) explicitly.
// In theory all the commands we invoke should have
// the same default computation of these as we do,
// but in practice there might be skew
// This makes sure we all agree.
origEnv = os.Environ()
for _, env := range mkEnv() {
if os.Getenv(env.name) != env.value {
os.Setenv(env.name, env.value)
}
}
for _, cmd := range commands {
if cmd.Name() == args[0] && cmd.Run != nil {
if cmd.Name() == args[0] && cmd.Runnable() {
cmd.Flag.Usage = func() { cmd.Usage() }
if cmd.CustomFlags {
args = args[1:]
@ -179,13 +197,13 @@ Usage:
The commands are:
{{range .}}{{if .Runnable}}
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
Use "go help [command]" for more information about a command.
Additional help topics:
{{range .}}{{if not .Runnable}}
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
Use "go help [topic]" for more information about that topic.
@ -200,8 +218,8 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
// 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 mkdoc.sh.
// Edit the documentation in other files and rerun mkdoc.sh to generate this one.
// 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}}
@ -217,12 +235,35 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
package main
`
// An errWriter wraps a writer, recording whether a write error occurred.
type errWriter struct {
w io.Writer
err error
}
func (w *errWriter) Write(b []byte) (int, error) {
n, err := w.w.Write(b)
if err != nil {
w.err = err
}
return n, err
}
// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
t := template.New("top")
t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
template.Must(t.Parse(text))
if err := t.Execute(w, data); err != nil {
ew := &errWriter{w: w}
err := t.Execute(ew, data)
if ew.err != nil {
// I/O error writing. Ignore write on closed pipe.
if strings.Contains(ew.err.Error(), "pipe") {
os.Exit(1)
}
fatalf("writing output: %v", ew.err)
}
if err != nil {
panic(err)
}
}
@ -236,13 +277,17 @@ func capitalize(s string) string {
}
func printUsage(w io.Writer) {
tmpl(w, usageTemplate, commands)
bw := bufio.NewWriter(w)
tmpl(bw, usageTemplate, commands)
bw.Flush()
}
func usage() {
// special case "go test -h"
if len(os.Args) > 1 && os.Args[1] == "test" {
help([]string{"testflag"})
os.Stdout.WriteString(testUsage + "\n\n" +
strings.TrimSpace(testFlag1) + "\n\n" +
strings.TrimSpace(testFlag2) + "\n")
os.Exit(2)
}
printUsage(os.Stderr)
@ -308,7 +353,7 @@ func importPathsNoDotExpansion(args []string) []string {
} else {
a = path.Clean(a)
}
if a == "all" || a == "std" {
if a == "all" || a == "std" || a == "cmd" {
out = append(out, allPackages(a)...)
continue
}
@ -401,11 +446,10 @@ func runOut(dir string, cmdargs ...interface{}) []byte {
// The environment is the current process's environment
// but with an updated $PWD, so that an os.Getwd in the
// child will be faster.
func envForDir(dir string) []string {
env := os.Environ()
func envForDir(dir string, base []string) []string {
// Internally we only use rooted paths, so dir is rooted.
// Even if dir is not rooted, no harm done.
return mergeEnvLists([]string{"PWD=" + dir}, env)
return mergeEnvLists([]string{"PWD=" + dir}, base)
}
// mergeEnvLists merges the two environment lists such that
@ -458,6 +502,28 @@ func hasPathPrefix(s, prefix string) bool {
}
}
// hasFilePathPrefix reports whether the filesystem path s begins with the
// elements in prefix.
func hasFilePathPrefix(s, prefix string) bool {
sv := strings.ToUpper(filepath.VolumeName(s))
pv := strings.ToUpper(filepath.VolumeName(prefix))
s = s[len(sv):]
prefix = prefix[len(pv):]
switch {
default:
return false
case sv != pv:
return false
case len(s) == len(prefix):
return s == prefix
case len(s) > len(prefix):
if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
return strings.HasPrefix(s, prefix)
}
return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
}
}
// treeCanMatchPattern(pattern)(name) reports whether
// name or children of name can possibly match pattern.
// Pattern is the same limited glob accepted by matchPattern.
@ -475,8 +541,8 @@ func treeCanMatchPattern(pattern string) func(name string) bool {
// allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT matching pattern.
// The pattern is either "all" (all packages), "std" (standard packages)
// or a path including "...".
// The pattern is either "all" (all packages), "std" (standard packages),
// "cmd" (standard commands), or a path including "...".
func allPackages(pattern string) []string {
pkgs := matchPackages(pattern)
if len(pkgs) == 0 {
@ -488,7 +554,7 @@ func allPackages(pattern string) []string {
func matchPackages(pattern string) []string {
match := func(string) bool { return true }
treeCanMatch := func(string) bool { return true }
if pattern != "all" && pattern != "std" {
if pattern != "all" && pattern != "std" && pattern != "cmd" {
match = matchPattern(pattern)
treeCanMatch = treeCanMatchPattern(pattern)
}
@ -501,47 +567,16 @@ func matchPackages(pattern string) []string {
}
var pkgs []string
// Commands
cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
if err != nil || !fi.IsDir() || path == cmd {
return nil
}
name := path[len(cmd):]
if !treeCanMatch(name) {
return filepath.SkipDir
}
// Commands are all in cmd/, not in subdirectories.
if strings.Contains(name, string(filepath.Separator)) {
return filepath.SkipDir
}
// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
name = "cmd/" + name
if have[name] {
return nil
}
have[name] = true
if !match(name) {
return nil
}
_, err = buildContext.ImportDir(path, 0)
if err != nil {
if _, noGo := err.(*build.NoGoError); !noGo {
log.Print(err)
}
return nil
}
pkgs = append(pkgs, name)
return nil
})
for _, src := range buildContext.SrcDirs() {
if pattern == "std" && src != gorootSrc {
if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
continue
}
src = filepath.Clean(src) + string(filepath.Separator)
filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
root := src
if pattern == "cmd" {
root += "cmd" + string(filepath.Separator)
}
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
if err != nil || !fi.IsDir() || path == src {
return nil
}
@ -553,7 +588,10 @@ func matchPackages(pattern string) []string {
}
name := filepath.ToSlash(path[len(src):])
if pattern == "std" && strings.Contains(name, ".") {
if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") {
// The name "std" is only the standard library.
// If the name has a dot, assume it's a domain name for go get,
// and if the name is cmd, it's the root of the command tree.
return filepath.SkipDir
}
if !treeCanMatch(name) {
@ -659,7 +697,7 @@ func stringList(args ...interface{}) []string {
case string:
x = append(x, arg)
default:
panic("stringList: invalid argument")
panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
}
}
return x

116
libgo/go/cmd/go/note.go Normal file
View file

@ -0,0 +1,116 @@
// 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.
package main
import (
"bytes"
"debug/elf"
"encoding/binary"
"fmt"
"io"
"os"
)
func readAligned4(r io.Reader, sz int32) ([]byte, error) {
full := (sz + 3) &^ 3
data := make([]byte, full)
_, err := io.ReadFull(r, data)
if err != nil {
return nil, err
}
data = data[:sz]
return data, nil
}
func readELFNote(filename, name string, typ int32) ([]byte, error) {
f, err := elf.Open(filename)
if err != nil {
return nil, err
}
for _, sect := range f.Sections {
if sect.Type != elf.SHT_NOTE {
continue
}
r := sect.Open()
for {
var namesize, descsize, noteType int32
err = binary.Read(r, f.ByteOrder, &namesize)
if err != nil {
if err == io.EOF {
break
}
return nil, fmt.Errorf("read namesize failed: %v", err)
}
err = binary.Read(r, f.ByteOrder, &descsize)
if err != nil {
return nil, fmt.Errorf("read descsize failed: %v", err)
}
err = binary.Read(r, f.ByteOrder, &noteType)
if err != nil {
return nil, fmt.Errorf("read type failed: %v", err)
}
noteName, err := readAligned4(r, namesize)
if err != nil {
return nil, fmt.Errorf("read name failed: %v", err)
}
desc, err := readAligned4(r, descsize)
if err != nil {
return nil, fmt.Errorf("read desc failed: %v", err)
}
if name == string(noteName) && typ == noteType {
return desc, nil
}
}
}
return nil, nil
}
var elfGoNote = []byte("Go\x00\x00")
// readELFGoBuildID the Go build ID string from an ELF binary.
// 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 the first 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 first 4 kB, already read.
// Rewrite the ELF header to set shnum to 0, so that we can pass
// the data to elf.NewFile and it will decode the Prog list but not
// try to read the section headers and the string table from disk.
// That's a waste of I/O when all we care about is the Prog list
// and the one ELF note.
switch elf.Class(data[elf.EI_CLASS]) {
case elf.ELFCLASS32:
data[48] = 0
data[49] = 0
case elf.ELFCLASS64:
data[60] = 0
data[61] = 0
}
const elfGoBuildIDTag = 4
ef, err := elf.NewFile(bytes.NewReader(data))
if err != nil {
return "", &os.PathError{Path: filename, Op: "parse", Err: err}
}
for _, p := range ef.Progs {
if p.Type != elf.PT_NOTE || p.Off >= uint64(len(data)) || p.Off+p.Filesz >= uint64(len(data)) || p.Filesz < 16 {
continue
}
note := data[p.Off : p.Off+p.Filesz]
nameSize := ef.ByteOrder.Uint32(note)
valSize := ef.ByteOrder.Uint32(note[4:])
tag := ef.ByteOrder.Uint32(note[8:])
name := note[12:16]
if nameSize != 4 || 16+valSize > uint32(len(note)) || tag != elfGoBuildIDTag || !bytes.Equal(name, elfGoNote) {
continue
}
return string(note[16 : 16+valSize]), nil
}
// No note. Treat as successful but build ID empty.
return "", nil
}

View file

@ -0,0 +1,49 @@
// 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.
package main_test
import (
main "cmd/go"
"runtime"
"testing"
)
func TestNoteReading(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.tempFile("hello.go", `package main; func main() { print("hello, world\n") }`)
const buildID = "TestNoteReading-Build-ID"
tg.run("build", "-ldflags", "-buildid="+buildID, "-o", tg.path("hello.exe"), tg.path("hello.go"))
id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe"))
if err != nil {
t.Fatalf("reading build ID from hello binary: %v", err)
}
if id != buildID {
t.Fatalf("buildID in hello binary = %q, want %q", id, buildID)
}
if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" {
t.Skipf("skipping - golang.org/issue/11184")
}
switch runtime.GOOS {
case "plan9":
// no external linking
t.Logf("no external linking - skipping linkmode=external test")
case "solaris":
t.Logf("skipping - golang.org/issue/12178")
default:
tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go"))
id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe"))
if err != nil {
t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err)
}
if id != buildID {
t.Fatalf("buildID in hello binary = %q, want %q (linkmode=external)", id, buildID)
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -37,7 +37,8 @@ Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix.
By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
If the -exec flag is given, 'go run' invokes the binary using xprog: 'xprog a.out arguments...'.
If the -exec flag is given, 'go run' invokes the binary using xprog:
'xprog a.out arguments...'.
If the -exec flag is not given, GOOS or GOARCH is different from the system
default, and a program named go_$GOOS_$GOARCH_exec can be found
on the current search path, 'go run' invokes the binary using that program,
@ -64,6 +65,7 @@ func printStderr(args ...interface{}) (int, error) {
func runRun(cmd *Command, args []string) {
raceInit()
buildModeInit()
var b builder
b.init()
b.print = printStderr
@ -136,6 +138,7 @@ func runStdin(cmdline []string) {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = origEnv
startSigHandlers()
if err := cmd.Run(); err != nil {
errorf("%v", err)

View file

@ -33,9 +33,11 @@ func init() {
cmdTest.Run = runTest
}
const testUsage = "test [-c] [-i] [build and test flags] [packages] [flags for test binary]"
var cmdTest = &Command{
CustomFlags: true,
UsageLine: "test [-c] [-i] [build and test flags] [packages] [flags for test binary]",
UsageLine: testUsage,
Short: "test packages",
Long: `
'Go test' automates testing the packages named by the import paths.
@ -64,6 +66,21 @@ with source in the current directory, including tests, and runs the tests.
The package is built in a temporary directory so it does not interfere with the
non-test installation.
` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details.
If the test binary needs any other flags, they should be presented after the
package names. The go tool treats as a flag the first argument that begins with
a minus sign that it does not recognize itself; that argument and all subsequent
arguments are passed as arguments to the test binary.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build, go vet.
`,
}
const testFlag1 = `
In addition to the build flags, the flags handled by 'go test' itself are:
-c
@ -83,21 +100,9 @@ In addition to the build flags, the flags handled by 'go test' itself are:
Compile the test binary to the named file.
The test still runs (unless -c or -i is specified).
The test binary also accepts flags that control execution of the test; these
flags are also accessible by 'go test'. See 'go help testflag' for details.
If the test binary needs any other flags, they should be presented after the
package names. The go tool treats as a flag the first argument that begins with
a minus sign that it does not recognize itself; that argument and all subsequent
arguments are passed as arguments to the test binary.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build, go vet.
`,
}
flags are also accessible by 'go test'.
`
var helpTestflag = &Command{
UsageLine: "testflag",
@ -107,13 +112,18 @@ The 'go test' command takes both flags that apply to 'go test' itself
and flags that apply to the resulting test binary.
Several of the flags control profiling and write an execution profile
suitable for "go tool pprof"; run "go tool pprof help" for more
suitable for "go tool pprof"; run "go tool pprof -h" for more
information. The --alloc_space, --alloc_objects, and --show_bytes
options of pprof control how the information is presented.
The following flags are recognized by the 'go test' command and
control the execution of any test:
` + strings.TrimSpace(testFlag2) + `
`,
}
const testFlag2 = `
-bench regexp
Run benchmarks matching the regular expression.
By default, no benchmarks run. To run all benchmarks,
@ -135,12 +145,17 @@ control the execution of any test:
-blockprofilerate n
Control the detail provided in goroutine blocking profiles by
calling runtime.SetBlockProfileRate with n.
See 'godoc runtime SetBlockProfileRate'.
See 'go doc runtime.SetBlockProfileRate'.
The profiler aims to sample, on average, one blocking event every
n nanoseconds the program spends blocked. By default,
if -test.blockprofile is set without this flag, all blocking events
are recorded, equivalent to -test.blockprofilerate=1.
-count n
Run each test and benchmark n times (default 1).
If -cpu is set, run n times for each GOMAXPROCS value.
Examples are always run once.
-cover
Enable coverage analysis.
@ -180,7 +195,7 @@ control the execution of any test:
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
runtime.MemProfileRate. See 'godoc runtime MemProfileRate'.
runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
To profile all memory allocations, use -test.memprofilerate=1
and pass --alloc_space flag to the pprof tool.
@ -205,6 +220,11 @@ control the execution of any test:
-timeout t
If a test runs longer than t, panic.
The default is 10 minutes (10m).
-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
@ -229,8 +249,7 @@ The test flags that generate profiles (other than for coverage) also
leave the test binary in pkg.test for use when analyzing the profiles.
Flags not recognized by 'go test' must be placed after any specified packages.
`,
}
`
var helpTestfunc = &Command{
UsageLine: "testfunc",
@ -310,6 +329,7 @@ func runTest(cmd *Command, args []string) {
findExecCmd() // initialize cached result
raceInit()
buildModeInit()
pkgs := packagesForBuild(pkgArgs)
if len(pkgs) == 0 {
fatalf("no packages to test")
@ -342,11 +362,11 @@ func runTest(cmd *Command, args []string) {
// been given on the command line (implicit current directory)
// or when benchmarking.
// Also stream if we're showing output anyway with a
// single package under test. In that case, streaming the
// output produces the same result as not streaming,
// just more immediately.
// single package under test or if parallelism is set to 1.
// In these cases, streaming the output produces the same result
// as not streaming, just more immediately.
testStreamOutput = len(pkgArgs) == 0 || testBench ||
(len(pkgs) <= 1 && testShowPass)
(testShowPass && (len(pkgs) == 1 || buildP == 1))
var b builder
b.init()
@ -364,10 +384,10 @@ func runTest(cmd *Command, args []string) {
for _, path := range p.Imports {
deps[path] = true
}
for _, path := range p.TestImports {
for _, path := range p.vendored(p.TestImports) {
deps[path] = true
}
for _, path := range p.XTestImports {
for _, path := range p.vendored(p.XTestImports) {
deps[path] = true
}
}
@ -376,7 +396,7 @@ func runTest(cmd *Command, args []string) {
if deps["C"] {
delete(deps, "C")
deps["runtime/cgo"] = true
if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH {
if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
deps["cmd/cgo"] = true
}
}
@ -428,6 +448,10 @@ func runTest(cmd *Command, args []string) {
// Mark all the coverage packages for rebuilding with coverage.
for _, p := range testCoverPkgs {
// There is nothing to cover in package unsafe; it comes from the compiler.
if p.ImportPath == "unsafe" {
continue
}
p.Stale = true // rebuild
p.fake = true // do not warn about rebuild
p.coverMode = testCoverMode
@ -562,15 +586,20 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
var imports, ximports []*Package
var stk importStack
stk.push(p.ImportPath + " (test)")
for _, path := range p.TestImports {
p1 := loadImport(path, p.Dir, &stk, p.build.TestImportPos[path])
for i, path := range p.TestImports {
p1 := loadImport(path, p.Dir, p, &stk, p.build.TestImportPos[path], useVendor)
if !reqStdPkgSrc && p1.Standard {
continue
}
if p1.Error != nil {
return nil, nil, nil, p1.Error
}
if contains(p1.Deps, p.ImportPath) {
if len(p1.DepsErrors) > 0 {
err := p1.DepsErrors[0]
err.Pos = "" // show full import stack
return nil, nil, nil, err
}
if contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
// Same error that loadPackage returns (via reusePackage) in pkg.go.
// Can't change that code, because that code is only for loading the
// non-test copy of a package.
@ -581,24 +610,31 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
}
return nil, nil, nil, err
}
p.TestImports[i] = p1.ImportPath
imports = append(imports, p1)
}
stk.pop()
stk.push(p.ImportPath + "_test")
pxtestNeedsPtest := false
for _, path := range p.XTestImports {
if path == p.ImportPath {
pxtestNeedsPtest = true
continue
}
p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path])
for i, path := range p.XTestImports {
p1 := loadImport(path, p.Dir, p, &stk, p.build.XTestImportPos[path], useVendor)
if !reqStdPkgSrc && p1.Standard {
continue
}
if p1.Error != nil {
return nil, nil, nil, p1.Error
}
ximports = append(ximports, p1)
if len(p1.DepsErrors) > 0 {
err := p1.DepsErrors[0]
err.Pos = "" // show full import stack
return nil, nil, nil, err
}
if p1.ImportPath == p.ImportPath {
pxtestNeedsPtest = true
} else {
ximports = append(ximports, p1)
}
p.XTestImports[i] = p1.ImportPath
}
stk.pop()
@ -723,7 +759,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
if dep == ptest.ImportPath {
pmain.imports = append(pmain.imports, ptest)
} else {
p1 := loadImport(dep, "", &stk, nil)
p1 := loadImport(dep, "", nil, &stk, nil, 0)
if !reqStdPkgSrc && p1.Standard {
continue
}
@ -781,6 +817,12 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
recompileForTest(pmain, p, ptest, testDir)
}
if buildContext.GOOS == "darwin" {
if buildContext.GOARCH == "arm" || buildContext.GOARCH == "arm64" {
t.NeedCgo = true
}
}
for _, cp := range pmain.imports {
if len(cp.coverVars) > 0 {
t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars})
@ -997,7 +1039,7 @@ func (b *builder) runTest(a *action) error {
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = a.p.Dir
cmd.Env = envForDir(cmd.Dir)
cmd.Env = envForDir(cmd.Dir, origEnv)
var buf bytes.Buffer
if testStreamOutput {
cmd.Stdout = os.Stdout
@ -1216,6 +1258,7 @@ type testFuncs struct {
NeedTest bool
ImportXtest bool
NeedXtest bool
NeedCgo bool
Cover []coverInfo
}
@ -1319,6 +1362,10 @@ import (
{{range $i, $p := .Cover}}
_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
{{end}}
{{if .NeedCgo}}
_ "runtime/cgo"
{{end}}
)
var tests = []testing.InternalTest{

View file

@ -4,6 +4,6 @@
// Test go generate variable substitution.
//go:generate echo $GOARCH $GOFILE $GOPACKAGE xyz$GOPACKAGE/$GOFILE/123
//go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123
package p

View file

@ -0,0 +1,10 @@
// 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.
// Test -run flag
//go:generate echo oh yes my man
//go:generate echo no, no, a thousand times no
package p

View file

@ -0,0 +1 @@
package main

1
libgo/go/cmd/go/testdata/rundir/x.go vendored Normal file
View file

@ -0,0 +1 @@
package main

View file

@ -0,0 +1 @@
package q1

View file

@ -0,0 +1,6 @@
package q1
import "testing"
import _ "testcycle/q1"
func Test(t *testing.T) {}

View file

@ -0,0 +1 @@
package p1

View file

@ -0,0 +1,3 @@
package p1
import _ "testdep/p2"

View file

@ -0,0 +1,3 @@
package p2
import _ "testdep/p3"

View file

@ -0,0 +1,3 @@
// +build ignore
package ignored

View file

@ -0,0 +1,3 @@
package vend
import _ "r"

View file

@ -0,0 +1,3 @@
package vend
import _ "p"

View file

@ -0,0 +1,10 @@
package main
import (
"fmt"
"strings" // really ../vendor/strings
)
func main() {
fmt.Printf("%s\n", strings.Msg)
}

View file

@ -0,0 +1,12 @@
package main
import (
"strings" // really ../vendor/strings
"testing"
)
func TestMsgInternal(t *testing.T) {
if strings.Msg != "hello, world" {
t.Fatal("unexpected msg: %v", strings.Msg)
}
}

View file

@ -0,0 +1,12 @@
package main_test
import (
"strings" // really ../vendor/strings
"testing"
)
func TestMsgExternal(t *testing.T) {
if strings.Msg != "hello, world" {
t.Fatal("unexpected msg: %v", strings.Msg)
}
}

View file

@ -0,0 +1,3 @@
package subdir
import _ "r"

View file

@ -0,0 +1,3 @@
package subdir
import _ "p"

View file

@ -0,0 +1 @@
package p

View file

@ -0,0 +1 @@
package q

View file

@ -0,0 +1,3 @@
package strings
var Msg = "hello, world"

View file

@ -0,0 +1,3 @@
package invalid
import "vend/x/invalid/vendor/foo"

View file

@ -0,0 +1 @@
package p

View file

@ -0,0 +1,3 @@
package p
import _ "notfound"

View file

@ -0,0 +1 @@
package r

View file

@ -0,0 +1,5 @@
package x
import _ "p"
import _ "q"
import _ "r"

View file

@ -0,0 +1,9 @@
// +build tagtest
package p
import "fmt"
func g() {
fmt.Printf("%d", 3, 4)
}

View file

@ -0,0 +1,3 @@
package t
import _ "internal/does-not-exist"

View file

@ -0,0 +1,6 @@
package p
import (
_ "q/internal/x"
_ "q/j"
)

View file

@ -0,0 +1 @@
package x

View file

@ -0,0 +1,3 @@
package j
import _ "q/internal/x"

View file

@ -0,0 +1,6 @@
package p
import (
_ "q/y"
_ "q/z"
)

View file

@ -0,0 +1 @@
package x

View file

@ -0,0 +1,3 @@
package y
import _ "x"

View file

@ -0,0 +1,3 @@
package z
import _ "q/vendor/x"

View file

@ -0,0 +1,3 @@
package p
import "x"

View file

@ -0,0 +1 @@
package x

View file

@ -5,6 +5,7 @@
package main
import (
"flag"
"fmt"
"os"
"strconv"
@ -16,46 +17,11 @@ import (
// our command line are for us, and some are for 6.out, and
// some are for both.
var usageMessage = `Usage of go test:
-c=false: compile but do not run the test binary
-file=file_test.go: specify file to use for tests;
use multiple times for multiple files
-p=n: build and test up to n packages in parallel
-x=false: print command lines as they are executed
// These flags can be passed with or without a "test." prefix: -v or -test.v.
-bench="": passes -test.bench to test
-benchmem=false: print memory allocation statistics for benchmarks
-benchtime=1s: passes -test.benchtime to test
-cover=false: enable coverage analysis
-covermode="set": specifies mode for coverage analysis
-coverpkg="": comma-separated list of packages for coverage analysis
-coverprofile="": passes -test.coverprofile to test if -cover
-cpu="": passes -test.cpu to test
-cpuprofile="": passes -test.cpuprofile to test
-memprofile="": passes -test.memprofile to test
-memprofilerate=0: passes -test.memprofilerate to test
-blockprofile="": pases -test.blockprofile to test
-blockprofilerate=0: passes -test.blockprofilerate to test
-outputdir=$PWD: passes -test.outputdir to test
-parallel=0: passes -test.parallel to test
-run="": passes -test.run to test
-short=false: passes -test.short to test
-timeout=0: passes -test.timeout to test
-v=false: passes -test.v to test
`
// usage prints a usage message and exits.
func testUsage() {
fmt.Fprint(os.Stderr, usageMessage)
setExitStatus(2)
exit()
}
// testFlagSpec defines a flag we know about.
type testFlagSpec struct {
name string
boolVar *bool
flagValue flag.Value
passToTest bool // pass to Test
multiOK bool // OK to have multiple instances
present bool // flag has been seen
@ -65,32 +31,18 @@ type testFlagSpec struct {
var testFlagDefn = []*testFlagSpec{
// local.
{name: "c", boolVar: &testC},
{name: "cover", boolVar: &testCover},
{name: "coverpkg"},
{name: "o"},
// build flags.
{name: "a", boolVar: &buildA},
{name: "n", boolVar: &buildN},
{name: "p"},
{name: "x", boolVar: &buildX},
{name: "i", boolVar: &buildI},
{name: "work", boolVar: &buildWork},
{name: "ccflags"},
{name: "gcflags"},
{name: "o"},
{name: "cover", boolVar: &testCover},
{name: "covermode"},
{name: "coverpkg"},
{name: "exec"},
{name: "ldflags"},
{name: "gccgoflags"},
{name: "tags"},
{name: "compiler"},
{name: "race", boolVar: &buildRace},
{name: "installsuffix"},
// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
{name: "bench", passToTest: true},
{name: "benchmem", boolVar: new(bool), passToTest: true},
{name: "benchtime", passToTest: true},
{name: "covermode"},
{name: "count", passToTest: true},
{name: "coverprofile", passToTest: true},
{name: "cpu", passToTest: true},
{name: "cpuprofile", passToTest: true},
@ -103,9 +55,26 @@ var testFlagDefn = []*testFlagSpec{
{name: "run", passToTest: true},
{name: "short", boolVar: new(bool), passToTest: true},
{name: "timeout", passToTest: true},
{name: "trace", passToTest: true},
{name: "v", boolVar: &testV, passToTest: true},
}
// add build flags to testFlagDefn
func init() {
var cmd Command
addBuildFlags(&cmd)
cmd.Flag.VisitAll(func(f *flag.Flag) {
if f.Name == "v" {
// test overrides the build -v flag
return
}
testFlagDefn = append(testFlagDefn, &testFlagSpec{
name: f.Name,
flagValue: f.Value,
})
})
}
// testFlags processes the command line, grabbing -x and -c, rewriting known flags
// to have "test" before them, and reading the command line for the 6.out.
// Unfortunately for us, we need to do our own flag processing because go test
@ -148,73 +117,55 @@ func testFlags(args []string) (packageNames, passToTest []string) {
passToTest = append(passToTest, args[i])
continue
}
var err error
switch f.name {
// bool flags.
case "a", "c", "i", "n", "x", "v", "race", "cover", "work":
setBoolFlag(f.boolVar, value)
case "o":
testO = value
testNeedBinary = true
case "p":
setIntFlag(&buildP, value)
case "exec":
execCmd, err = splitQuotedFields(value)
if err != nil {
if f.flagValue != nil {
if err := f.flagValue.Set(value); err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "ccflags":
buildCcflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
} else {
// Test-only flags.
// Arguably should be handled by f.flagValue, but aren't.
var err error
switch f.name {
// bool flags.
case "c", "i", "v", "cover":
setBoolFlag(f.boolVar, value)
case "o":
testO = value
testNeedBinary = true
case "exec":
execCmd, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "bench":
// record that we saw the flag; don't care about the value
testBench = true
case "timeout":
testTimeout = value
case "blockprofile", "cpuprofile", "memprofile", "trace":
testProfile = true
testNeedBinary = true
case "coverpkg":
testCover = true
if value == "" {
testCoverPaths = nil
} else {
testCoverPaths = strings.Split(value, ",")
}
case "coverprofile":
testCover = true
testProfile = true
case "covermode":
switch value {
case "set", "count", "atomic":
testCoverMode = value
default:
fatalf("invalid flag argument for -covermode: %q", value)
}
testCover = true
case "outputdir":
outputDir = value
}
case "gcflags":
buildGcflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "ldflags":
buildLdflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "gccgoflags":
buildGccgoflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "tags":
buildContext.BuildTags = strings.Fields(value)
case "compiler":
buildCompiler{}.Set(value)
case "bench":
// record that we saw the flag; don't care about the value
testBench = true
case "timeout":
testTimeout = value
case "blockprofile", "cpuprofile", "memprofile":
testProfile = true
testNeedBinary = true
case "coverpkg":
testCover = true
if value == "" {
testCoverPaths = nil
} else {
testCoverPaths = strings.Split(value, ",")
}
case "coverprofile":
testCover = true
testProfile = true
case "covermode":
switch value {
case "set", "count", "atomic":
testCoverMode = value
default:
fatalf("invalid flag argument for -cover: %q", value)
}
testCover = true
case "outputdir":
outputDir = value
}
if extraWord {
i++
@ -267,7 +218,7 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
for _, f = range testFlagDefn {
if name == f.name {
// Booleans are special because they have modes -x, -x=true, -x=false.
if f.boolVar != nil {
if f.boolVar != nil || isBoolFlag(f.flagValue) {
if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag
value = "true"
} else {
@ -294,6 +245,17 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
return
}
// isBoolFlag reports whether v is a bool flag.
func isBoolFlag(v flag.Value) bool {
vv, ok := v.(interface {
IsBoolFlag() bool
})
if ok {
return vv.IsBoolFlag()
}
return false
}
// setBoolFlag sets the addressed boolean to the value.
func setBoolFlag(flag *bool, value string) {
x, err := strconv.ParseBool(value)

View file

@ -50,6 +50,9 @@ func tool(toolName string) string {
if toolIsWindows {
toolPath += toolWindowsExtension
}
if len(buildToolExec) > 0 {
return toolPath
}
// Give a nice message if there is no tool with that name.
if _, err := os.Stat(toolPath); err != nil {
if isInGoToolsRepo(toolName) {
@ -64,10 +67,6 @@ func tool(toolName string) string {
}
func isInGoToolsRepo(toolName string) bool {
switch toolName {
case "cover", "vet":
return true
}
return false
}
@ -92,7 +91,11 @@ func runTool(cmd *Command, args []string) {
return
}
if toolN {
fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
cmd := toolPath
if len(args) > 1 {
cmd += " " + strings.Join(args[1:], " ")
}
fmt.Printf("%s\n", cmd)
return
}
toolCmd := &exec.Cmd{
@ -101,6 +104,8 @@ func runTool(cmd *Command, args []string) {
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
// Set $GOROOT, mainly for go tool dist.
Env: mergeEnvLists([]string{"GOROOT=" + goroot}, os.Environ()),
}
err := toolCmd.Run()
if err != nil {

View file

@ -9,12 +9,15 @@ import (
"encoding/json"
"errors"
"fmt"
"internal/singleflight"
"log"
"net/url"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"sync"
)
// A vcsCmd describes how to use a version control system
@ -23,13 +26,13 @@ type vcsCmd struct {
name string
cmd string // name of binary to invoke command
createCmd string // command to download a fresh copy of a repository
downloadCmd string // command to download updates into an existing repository
createCmd []string // commands to download a fresh copy of a repository
downloadCmd []string // commands to download updates into an existing repository
tagCmd []tagCmd // commands to list tags
tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd
tagSyncCmd string // command to sync to specific tag
tagSyncDefault string // command to sync to default tag
tagSyncCmd []string // commands to sync to specific tag
tagSyncDefault []string // commands to sync to default tag
scheme []string
pingCmd string
@ -38,6 +41,23 @@ type vcsCmd struct {
resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)
}
var isSecureScheme = map[string]bool{
"https": true,
"git+ssh": true,
"bzr+ssh": true,
"svn+ssh": true,
"ssh": true,
}
func (v *vcsCmd) isSecure(repo string) bool {
u, err := url.Parse(repo)
if err != nil {
// If repo is not a URL, it's not secure.
return false
}
return isSecureScheme[u.Scheme]
}
// A tagCmd describes a command to list available tags
// that can be passed to tagSyncCmd.
type tagCmd struct {
@ -69,8 +89,8 @@ var vcsHg = &vcsCmd{
name: "Mercurial",
cmd: "hg",
createCmd: "clone -U {repo} {dir}",
downloadCmd: "pull",
createCmd: []string{"clone -U {repo} {dir}"},
downloadCmd: []string{"pull"},
// We allow both tag and branch names as 'tags'
// for selecting a version. This lets people have
@ -81,8 +101,8 @@ var vcsHg = &vcsCmd{
{"tags", `^(\S+)`},
{"branches", `^(\S+)`},
},
tagSyncCmd: "update -r {tag}",
tagSyncDefault: "update default",
tagSyncCmd: []string{"update -r {tag}"},
tagSyncDefault: []string{"update default"},
scheme: []string{"https", "http", "ssh"},
pingCmd: "identify {scheme}://{repo}",
@ -102,8 +122,8 @@ var vcsGit = &vcsCmd{
name: "Git",
cmd: "git",
createCmd: "clone {repo} {dir}",
downloadCmd: "pull --ff-only",
createCmd: []string{"clone {repo} {dir}", "--git-dir={dir}/.git submodule update --init --recursive"},
downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
tagCmd: []tagCmd{
// tags/xxx matches a git tag named xxx
@ -113,41 +133,64 @@ var vcsGit = &vcsCmd{
tagLookupCmd: []tagCmd{
{"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
},
tagSyncCmd: "checkout {tag}",
tagSyncDefault: "checkout master",
tagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"},
// both createCmd and downloadCmd update the working dir.
// No need to do more here. We used to 'checkout master'
// but that doesn't work if the default branch is not named master.
// See golang.org/issue/9032.
tagSyncDefault: []string{"checkout master", "submodule update --init --recursive"},
scheme: []string{"git", "https", "http", "git+ssh"},
scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
pingCmd: "ls-remote {scheme}://{repo}",
remoteRepo: gitRemoteRepo,
}
// scpSyntaxRe matches the SCP-like addresses used by Git to access
// repositories by SSH.
var scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) {
outb, err := vcsGit.runOutput(rootDir, "remote -v")
cmd := "config remote.origin.url"
errParse := errors.New("unable to parse output of git " + cmd)
errRemoteOriginNotFound := errors.New("remote origin not found")
outb, err := vcsGit.run1(rootDir, cmd, nil, false)
if err != nil {
// if it doesn't output any message, it means the config argument is correct,
// but the config value itself doesn't exist
if outb != nil && len(outb) == 0 {
return "", errRemoteOriginNotFound
}
return "", err
}
out := string(outb)
out := strings.TrimSpace(string(outb))
// Expect:
// origin https://github.com/rsc/pdf (fetch)
// origin https://github.com/rsc/pdf (push)
// use first line only.
var repoURL *url.URL
if m := scpSyntaxRe.FindStringSubmatch(out); m != nil {
// Match SCP-like syntax and convert it to a URL.
// 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],
}
} else {
repoURL, err = url.Parse(out)
if err != nil {
return "", err
}
}
if !strings.HasPrefix(out, "origin\t") {
return "", fmt.Errorf("unable to parse output of git remote -v")
// Iterate over insecure schemes too, because this function simply
// reports the state of the repo. If we can't see insecure schemes then
// we can't report the actual repo URL.
for _, s := range vcsGit.scheme {
if repoURL.Scheme == s {
return repoURL.String(), nil
}
}
out = strings.TrimPrefix(out, "origin\t")
i := strings.Index(out, "\n")
if i < 0 {
return "", fmt.Errorf("unable to parse output of git remote -v")
}
out = out[:i]
i = strings.LastIndex(out, " ")
if i < 0 {
return "", fmt.Errorf("unable to parse output of git remote -v")
}
out = out[:i]
return strings.TrimSpace(string(out)), nil
return "", errParse
}
// vcsBzr describes how to use Bazaar.
@ -155,15 +198,15 @@ var vcsBzr = &vcsCmd{
name: "Bazaar",
cmd: "bzr",
createCmd: "branch {repo} {dir}",
createCmd: []string{"branch {repo} {dir}"},
// Without --overwrite bzr will not pull tags that changed.
// Replace by --overwrite-tags after http://pad.lv/681792 goes in.
downloadCmd: "pull --overwrite",
downloadCmd: []string{"pull --overwrite"},
tagCmd: []tagCmd{{"tags", `^(\S+)`}},
tagSyncCmd: "update -r {tag}",
tagSyncDefault: "update -r revno:-1",
tagSyncCmd: []string{"update -r {tag}"},
tagSyncDefault: []string{"update -r revno:-1"},
scheme: []string{"https", "http", "bzr", "bzr+ssh"},
pingCmd: "info {scheme}://{repo}",
@ -217,8 +260,8 @@ var vcsSvn = &vcsCmd{
name: "Subversion",
cmd: "svn",
createCmd: "checkout {repo} {dir}",
downloadCmd: "update",
createCmd: []string{"checkout {repo} {dir}"},
downloadCmd: []string{"update"},
// There is no tag command in subversion.
// The branch information is all in the path names.
@ -294,14 +337,14 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
_, err := exec.LookPath(v.cmd)
if err != nil {
fmt.Fprintf(os.Stderr,
"go: missing %s command. See http://golang.org/s/gogetcmd\n",
"go: missing %s command. See https://golang.org/s/gogetcmd\n",
v.name)
return nil, err
}
cmd := exec.Command(v.cmd, args...)
cmd.Dir = dir
cmd.Env = envForDir(cmd.Dir)
cmd.Env = envForDir(cmd.Dir, os.Environ())
if buildX {
fmt.Printf("cd %s\n", dir)
fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
@ -316,7 +359,7 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
os.Stderr.Write(out)
}
return nil, err
return out, err
}
return out, nil
}
@ -329,7 +372,15 @@ func (v *vcsCmd) ping(scheme, repo string) error {
// create creates a new copy of repo in dir.
// The parent of dir must exist; dir must not.
func (v *vcsCmd) create(dir, repo string) error {
return v.run(".", v.createCmd, "dir", dir, "repo", repo)
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
}
}
return nil
}
// download downloads any new changes for the repo in dir.
@ -337,7 +388,15 @@ func (v *vcsCmd) download(dir string) error {
if err := v.fixDetachedHead(dir); err != nil {
return err
}
return v.run(dir, v.downloadCmd)
for _, cmd := range v.downloadCmd {
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(dir, cmd); err != nil {
return err
}
}
return nil
}
// fixDetachedHead switches a Git repository in dir from a detached head to the master branch.
@ -383,7 +442,7 @@ func (v *vcsCmd) tags(dir string) ([]string, error) {
// tagSync syncs the repo in dir to the named tag,
// which either is a tag returned by tags or is v.tagDefault.
func (v *vcsCmd) tagSync(dir, tag string) error {
if v.tagSyncCmd == "" {
if v.tagSyncCmd == nil {
return nil
}
if tag != "" {
@ -400,10 +459,28 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
}
}
}
if tag == "" && v.tagSyncDefault != "" {
return v.run(dir, v.tagSyncDefault)
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
}
}
return nil
}
return v.run(dir, v.tagSyncCmd, "tag", tag)
for _, cmd := range v.tagSyncCmd {
if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(dir, cmd, "tag", tag); err != nil {
return err
}
}
return nil
}
// A vcsPath describes how to convert an import path into a
@ -467,10 +544,20 @@ type repoRoot struct {
var httpPrefixRE = regexp.MustCompile(`^https?:`)
// securityMode specifies whether a function should make network
// calls using insecure transports (eg, plain text HTTP).
// The zero value is "secure".
type securityMode int
const (
secure securityMode = iota
insecure
)
// repoRootForImportPath analyzes importPath to determine the
// version control system, and code repository to use.
func repoRootForImportPath(importPath string) (*repoRoot, error) {
rr, err := repoRootForImportPathStatic(importPath, "")
func repoRootForImportPath(importPath string, security securityMode) (*repoRoot, error) {
rr, err := repoRootFromVCSPaths(importPath, "", security, vcsPaths)
if err == errUnknownSite {
// If there are wildcards, look up the thing before the wildcard,
// hoping it applies to the wildcarded parts too.
@ -479,7 +566,7 @@ func repoRootForImportPath(importPath string) (*repoRoot, error) {
if i := strings.Index(lookup, "/.../"); i >= 0 {
lookup = lookup[:i]
}
rr, err = repoRootForImportDynamic(lookup)
rr, err = repoRootForImportDynamic(lookup, security)
// repoRootForImportDynamic returns error detail
// that is irrelevant if the user didn't intend to use a
@ -492,6 +579,13 @@ func repoRootForImportPath(importPath string) (*repoRoot, error) {
err = fmt.Errorf("unrecognized import path %q", importPath)
}
}
if err != nil {
rr1, err1 := repoRootFromVCSPaths(importPath, "", security, vcsPathsAfterDynamic)
if err1 == nil {
rr = rr1
err = nil
}
}
if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.root, "...") {
// Do not allow wildcards in the repo root.
@ -503,13 +597,10 @@ func repoRootForImportPath(importPath string) (*repoRoot, error) {
var errUnknownSite = errors.New("dynamic lookup required to find mapping")
// repoRootForImportPathStatic attempts to map importPath to a
// repoRoot using the commonly-used VCS hosting sites in vcsPaths
// (github.com/user/dir), or from a fully-qualified importPath already
// containing its VCS type (foo.com/repo.git/dir)
//
// repoRootFromVCSPaths attempts to map importPath to a repoRoot
// using the mappings defined in vcsPaths.
// If scheme is non-empty, that scheme is forced.
func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
func repoRootFromVCSPaths(importPath, scheme string, security securityMode, vcsPaths []*vcsPath) (*repoRoot, error) {
// A common error is to use https://packagepath because that's what
// hg and git require. Diagnose this helpfully.
if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil {
@ -559,6 +650,9 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
match["repo"] = scheme + "://" + match["repo"]
} else {
for _, scheme := range vcs.scheme {
if security == secure && !isSecureScheme[scheme] {
continue
}
if vcs.ping(scheme, match["repo"]) == nil {
match["repo"] = scheme + "://" + match["repo"]
break
@ -579,26 +673,31 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
// repoRootForImportDynamic finds a *repoRoot for a custom domain that's not
// statically known by repoRootForImportPathStatic.
//
// This handles "vanity import paths" like "name.tld/pkg/foo".
func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
// This handles custom import paths like "name.tld/pkg/foo" or just "name.tld".
func repoRootForImportDynamic(importPath string, security securityMode) (*repoRoot, error) {
slash := strings.Index(importPath, "/")
if slash < 0 {
return nil, errors.New("import path does not contain a slash")
slash = len(importPath)
}
host := importPath[:slash]
if !strings.Contains(host, ".") {
return nil, errors.New("import path does not begin with hostname")
}
urlStr, body, err := httpsOrHTTP(importPath)
urlStr, body, err := httpsOrHTTP(importPath, security)
if err != nil {
return nil, fmt.Errorf("http/https fetch: %v", err)
msg := "https fetch: %v"
if security == insecure {
msg = "http/" + msg
}
return nil, fmt.Errorf(msg, err)
}
defer body.Close()
imports, err := parseMetaGoImports(body)
if err != nil {
return nil, fmt.Errorf("parsing %s: %v", importPath, err)
}
metaImport, err := matchGoImport(imports, importPath)
// Find the matched meta import.
mmi, err := matchGoImport(imports, importPath)
if err != nil {
if err != errNoMatch {
return nil, fmt.Errorf("parse %s: %v", urlStr, err)
@ -606,7 +705,7 @@ func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr)
}
if buildV {
log.Printf("get %q: found meta tag %#v at %s", importPath, metaImport, urlStr)
log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, urlStr)
}
// If the import was "uni.edu/bob/project", which said the
// prefix was "uni.edu" and the RepoRoot was "evilroot.com",
@ -614,42 +713,89 @@ func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
// "uni.edu" yet (possibly overwriting/preempting another
// non-evil student). Instead, first verify the root and see
// if it matches Bob's claim.
if metaImport.Prefix != importPath {
if mmi.Prefix != importPath {
if buildV {
log.Printf("get %q: verifying non-authoritative meta tag", importPath)
}
urlStr0 := urlStr
urlStr, body, err = httpsOrHTTP(metaImport.Prefix)
var imports []metaImport
urlStr, imports, err = metaImportsForPrefix(mmi.Prefix, security)
if err != nil {
return nil, fmt.Errorf("fetch %s: %v", urlStr, err)
}
imports, err := parseMetaGoImports(body)
if err != nil {
return nil, fmt.Errorf("parsing %s: %v", importPath, err)
}
if len(imports) == 0 {
return nil, fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
return nil, err
}
metaImport2, err := matchGoImport(imports, importPath)
if err != nil || metaImport != metaImport2 {
return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, metaImport.Prefix)
if err != nil || mmi != metaImport2 {
return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, mmi.Prefix)
}
}
if !strings.Contains(metaImport.RepoRoot, "://") {
return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, metaImport.RepoRoot)
if !strings.Contains(mmi.RepoRoot, "://") {
return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, mmi.RepoRoot)
}
rr := &repoRoot{
vcs: vcsByCmd(metaImport.VCS),
repo: metaImport.RepoRoot,
root: metaImport.Prefix,
vcs: vcsByCmd(mmi.VCS),
repo: mmi.RepoRoot,
root: mmi.Prefix,
}
if rr.vcs == nil {
return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, metaImport.VCS)
return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, mmi.VCS)
}
return rr, nil
}
var fetchGroup singleflight.Group
var (
fetchCacheMu sync.Mutex
fetchCache = map[string]fetchResult{} // key is metaImportsForPrefix's importPrefix
)
// metaImportsForPrefix takes a package's root import path as declared in a <meta> tag
// and returns its HTML discovery URL and the parsed metaImport lines
// found on the page.
//
// The importPath is of the form "golang.org/x/tools".
// It is an error if no imports are found.
// urlStr will still be valid if err != nil.
// The returned urlStr will be of the form "https://golang.org/x/tools?go-get=1"
func metaImportsForPrefix(importPrefix string, security securityMode) (urlStr string, imports []metaImport, err error) {
setCache := func(res fetchResult) (fetchResult, error) {
fetchCacheMu.Lock()
defer fetchCacheMu.Unlock()
fetchCache[importPrefix] = res
return res, nil
}
resi, _, _ := fetchGroup.Do(importPrefix, func() (resi interface{}, err error) {
fetchCacheMu.Lock()
if res, ok := fetchCache[importPrefix]; ok {
fetchCacheMu.Unlock()
return res, nil
}
fetchCacheMu.Unlock()
urlStr, body, err := httpsOrHTTP(importPrefix, security)
if err != nil {
return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("fetch %s: %v", urlStr, err)})
}
imports, err := parseMetaGoImports(body)
if err != nil {
return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("parsing %s: %v", urlStr, err)})
}
if len(imports) == 0 {
err = fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
}
return setCache(fetchResult{urlStr: urlStr, imports: imports, err: err})
})
res := resi.(fetchResult)
return res.urlStr, res.imports, res.err
}
type fetchResult struct {
urlStr string // e.g. "https://foo.com/x/bar?go-get=1"
imports []metaImport
err error
}
// metaImport represents the parsed <meta name="go-import"
// content="prefix vcs reporoot" /> tags from HTML files.
type metaImport struct {
@ -689,7 +835,10 @@ func expand(match map[string]string, s string) string {
return s
}
// vcsPaths lists the known vcs paths.
// vcsPaths defines the meaning of import paths referring to
// commonly-used VCS hosting sites (github.com/user/dir)
// 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
{
@ -722,15 +871,6 @@ var vcsPaths = []*vcsPath{
check: bitbucketVCS,
},
// Launchpad
{
prefix: "launchpad.net/",
re: `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
vcs: "bzr",
repo: "https://{root}",
check: launchpadVCS,
},
// IBM DevOps Services (JazzHub)
{
prefix: "hub.jazz.net/git",
@ -740,13 +880,37 @@ var vcsPaths = []*vcsPath{
check: noVCSSuffix,
},
// Git at Apache
{
prefix: "git.apache.org",
re: `^(?P<root>git.apache.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`,
vcs: "git",
repo: "https://{root}",
},
// General syntax for any server.
// Must be last.
{
re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
ping: true,
},
}
// vcsPathsAfterDynamic gives additional vcsPaths entries
// to try after the dynamic HTML check.
// This gives those sites a chance to introduce <meta> tags
// as part of a graceful transition away from the hard-coded logic.
var vcsPathsAfterDynamic = []*vcsPath{
// Launchpad. See golang.org/issue/11436.
{
prefix: "launchpad.net/",
re: `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
vcs: "bzr",
repo: "https://{root}",
check: launchpadVCS,
},
}
func init() {
// fill in cached regexps.
// Doing this eagerly discovers invalid regexp syntax
@ -754,6 +918,9 @@ func init() {
for _, srv := range vcsPaths {
srv.regexp = regexp.MustCompile(srv.re)
}
for _, srv := range vcsPathsAfterDynamic {
srv.regexp = regexp.MustCompile(srv.re)
}
}
// noVCSSuffix checks that the repository name does not
@ -821,10 +988,25 @@ func bitbucketVCS(match map[string]string) error {
url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}")
data, err := httpGET(url)
if err != nil {
return err
}
if err := json.Unmarshal(data, &resp); err != nil {
return fmt.Errorf("decoding %s: %v", url, err)
if httpErr, ok := err.(*httpError); ok && httpErr.statusCode == 403 {
// this may be a private repository. If so, attempt to determine which
// VCS it uses. See issue 5375.
root := match["root"]
for _, vcs := range []string{"git", "hg"} {
if vcsByCmd(vcs).ping("https", root) == nil {
resp.SCM = vcs
break
}
}
}
if resp.SCM == "" {
return err
}
} else {
if err := json.Unmarshal(data, &resp); err != nil {
return fmt.Errorf("decoding %s: %v", url, err)
}
}
if vcsByCmd(resp.SCM) != nil {

Some files were not shown because too many files have changed in this diff Show more