From f154da9e12608589e8d5f0508f908a0c3e88a1bb Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 15 Jan 2015 11:54:00 -0700 Subject: Imported Upstream version 1.4 --- src/androidtest.bash | 55 + src/archive/tar/common.go | 305 + src/archive/tar/example_test.go | 79 + src/archive/tar/reader.go | 820 ++ src/archive/tar/reader_test.go | 743 + src/archive/tar/stat_atim.go | 20 + src/archive/tar/stat_atimespec.go | 20 + src/archive/tar/stat_unix.go | 32 + src/archive/tar/tar_test.go | 284 + src/archive/tar/testdata/gnu.tar | Bin 0 -> 3072 bytes src/archive/tar/testdata/nil-uid.tar | Bin 0 -> 1024 bytes src/archive/tar/testdata/pax.tar | Bin 0 -> 10240 bytes src/archive/tar/testdata/small.txt | 1 + src/archive/tar/testdata/small2.txt | 1 + src/archive/tar/testdata/sparse-formats.tar | Bin 0 -> 17920 bytes src/archive/tar/testdata/star.tar | Bin 0 -> 3072 bytes src/archive/tar/testdata/ustar.tar | Bin 0 -> 2048 bytes src/archive/tar/testdata/v7.tar | Bin 0 -> 3584 bytes src/archive/tar/testdata/writer-big-long.tar | Bin 0 -> 4096 bytes src/archive/tar/testdata/writer-big.tar | Bin 0 -> 4096 bytes src/archive/tar/testdata/writer.tar | Bin 0 -> 3584 bytes src/archive/tar/testdata/xattrs.tar | Bin 0 -> 5120 bytes src/archive/tar/writer.go | 396 + src/archive/tar/writer_test.go | 491 + src/archive/zip/example_test.go | 75 + src/archive/zip/reader.go | 453 + src/archive/zip/reader_test.go | 533 + src/archive/zip/register.go | 110 + src/archive/zip/struct.go | 313 + src/archive/zip/testdata/crc32-not-streamed.zip | Bin 0 -> 314 bytes src/archive/zip/testdata/dd.zip | Bin 0 -> 154 bytes src/archive/zip/testdata/go-no-datadesc-sig.zip | Bin 0 -> 330 bytes src/archive/zip/testdata/go-with-datadesc-sig.zip | Bin 0 -> 242 bytes src/archive/zip/testdata/gophercolor16x16.png | Bin 0 -> 785 bytes src/archive/zip/testdata/readme.notzip | Bin 0 -> 1905 bytes src/archive/zip/testdata/readme.zip | Bin 0 -> 1885 bytes src/archive/zip/testdata/symlink.zip | Bin 0 -> 173 bytes src/archive/zip/testdata/test-trailing-junk.zip | Bin 0 -> 1184 bytes src/archive/zip/testdata/test.zip | Bin 0 -> 1170 bytes src/archive/zip/testdata/unix.zip | Bin 0 -> 620 bytes src/archive/zip/testdata/winxp.zip | Bin 0 -> 412 bytes src/archive/zip/testdata/zip64-2.zip | Bin 0 -> 266 bytes src/archive/zip/testdata/zip64.zip | Bin 0 -> 242 bytes src/archive/zip/writer.go | 357 + src/archive/zip/writer_test.go | 164 + src/archive/zip/zip_test.go | 395 + src/bufio/bufio.go | 698 + src/bufio/bufio_test.go | 1426 ++ src/bufio/example_test.go | 82 + src/bufio/export_test.go | 27 + src/bufio/scan.go | 359 + src/bufio/scan_test.go | 524 + src/builtin/builtin.go | 256 + src/bytes/buffer.go | 412 + src/bytes/buffer_test.go | 527 + src/bytes/bytes.go | 703 + src/bytes/bytes_decl.go | 24 + src/bytes/bytes_test.go | 1240 ++ src/bytes/compare_test.go | 208 + src/bytes/equal_test.go | 47 + src/bytes/example_test.go | 85 + src/bytes/export_test.go | 13 + src/bytes/reader.go | 144 + src/bytes/reader_test.go | 246 + src/cmd/5a/a.y | 2 +- src/cmd/5a/lex.c | 5 +- src/cmd/5a/y.tab.c | 2 +- src/cmd/5c/cgen.c | 38 +- src/cmd/5c/gc.h | 5 +- src/cmd/5c/peep.c | 4 + src/cmd/5c/reg.c | 19 +- src/cmd/5c/sgen.c | 2 +- src/cmd/5c/swt.c | 11 +- src/cmd/5c/txt.c | 40 +- src/cmd/5g/cgen.c | 81 +- src/cmd/5g/galign.c | 8 +- src/cmd/5g/gg.h | 12 +- src/cmd/5g/ggen.c | 25 +- src/cmd/5g/gsubr.c | 27 +- src/cmd/5g/opt.h | 20 + src/cmd/5g/peep.c | 6 + src/cmd/5g/reg.c | 12 +- src/cmd/5l/5.out.h | 166 +- src/cmd/5l/asm.c | 75 +- src/cmd/5l/l.h | 76 - src/cmd/5l/mkenam | 45 - src/cmd/5l/noop.c | 43 - src/cmd/5l/obj.c | 13 +- src/cmd/6a/a.y | 2 +- src/cmd/6a/lex.c | 35 +- src/cmd/6a/y.tab.c | 2 +- src/cmd/6c/cgen.c | 36 +- src/cmd/6c/gc.h | 5 +- src/cmd/6c/reg.c | 14 +- src/cmd/6c/sgen.c | 9 +- src/cmd/6c/swt.c | 9 +- src/cmd/6c/txt.c | 40 +- src/cmd/6g/cgen.c | 10 +- src/cmd/6g/galign.c | 8 +- src/cmd/6g/gg.h | 2 - src/cmd/6g/ggen.c | 61 +- src/cmd/6g/gsubr.c | 29 +- src/cmd/6g/opt.h | 20 + src/cmd/6g/reg.c | 8 +- src/cmd/6l/6.out.h | 2 +- src/cmd/6l/asm.c | 17 +- src/cmd/6l/l.h | 10 - src/cmd/6l/mkenam | 45 - src/cmd/8a/a.y | 2 +- src/cmd/8a/lex.c | 35 +- src/cmd/8a/y.tab.c | 2 +- src/cmd/8c/cgen.c | 38 +- src/cmd/8c/gc.h | 5 +- src/cmd/8c/reg.c | 9 +- src/cmd/8c/sgen.c | 2 +- src/cmd/8c/swt.c | 9 +- src/cmd/8c/txt.c | 40 +- src/cmd/8g/cgen.c | 88 +- src/cmd/8g/galign.c | 8 +- src/cmd/8g/gg.h | 1 - src/cmd/8g/ggen.c | 49 +- src/cmd/8g/gsubr.c | 26 +- src/cmd/8g/opt.h | 20 + src/cmd/8g/peep.c | 4 +- src/cmd/8g/reg.c | 6 + src/cmd/8l/8.out.h | 2 +- src/cmd/8l/asm.c | 18 +- src/cmd/8l/l.h | 7 - src/cmd/8l/mkenam | 45 - src/cmd/addr2line/addr2line_test.go | 5 +- src/cmd/addr2line/main.go | 166 +- src/cmd/api/goapi.go | 158 +- src/cmd/api/goapi_test.go | 24 +- src/cmd/api/run.go | 9 +- src/cmd/cc/bv.c | 45 - src/cmd/cc/cc.h | 8 +- src/cmd/cc/cc.y | 1 + src/cmd/cc/dcl.c | 25 +- src/cmd/cc/godefs.c | 67 +- src/cmd/cc/lex.c | 3 + src/cmd/cc/pgen.c | 202 +- src/cmd/cc/y.tab.c | 1147 +- src/cmd/cc/y.tab.h | 68 +- src/cmd/cgo/ast.go | 5 +- src/cmd/cgo/doc.go | 2 +- src/cmd/cgo/gcc.go | 187 +- src/cmd/cgo/out.go | 243 +- src/cmd/dist/a.h | 4 +- src/cmd/dist/arm.c | 3 +- src/cmd/dist/buf.c | 2 +- src/cmd/dist/build.c | 267 +- src/cmd/dist/buildgc.c | 38 +- src/cmd/dist/buildruntime.c | 84 +- src/cmd/dist/goc2c.c | 833 -- src/cmd/dist/plan9.c | 6 +- src/cmd/dist/unix.c | 16 +- src/cmd/dist/windows.c | 6 +- src/cmd/fix/doc.go | 2 +- src/cmd/fix/fix.go | 2 +- src/cmd/gc/align.c | 4 +- src/cmd/gc/bisonerrors | 18 +- src/cmd/gc/builtin.c | 33 +- src/cmd/gc/bv.c | 5 +- src/cmd/gc/const.c | 9 +- src/cmd/gc/dcl.c | 14 + src/cmd/gc/esc.c | 3 +- src/cmd/gc/fmt.c | 36 +- src/cmd/gc/gen.c | 75 +- src/cmd/gc/go.h | 17 +- src/cmd/gc/go.y | 15 +- src/cmd/gc/lex.c | 363 +- src/cmd/gc/md5.c | 12 +- src/cmd/gc/mparith1.c | 2 +- src/cmd/gc/mparith2.c | 4 +- src/cmd/gc/mparith3.c | 4 +- src/cmd/gc/obj.c | 9 +- src/cmd/gc/order.c | 48 +- src/cmd/gc/pgen.c | 57 +- src/cmd/gc/plive.c | 34 +- src/cmd/gc/popt.c | 6 +- src/cmd/gc/racewalk.c | 26 +- src/cmd/gc/range.c | 48 +- src/cmd/gc/reflect.c | 591 +- src/cmd/gc/runtime.go | 40 +- src/cmd/gc/select.c | 65 +- src/cmd/gc/sinit.c | 32 +- src/cmd/gc/subr.c | 193 +- src/cmd/gc/swt.c | 1 + src/cmd/gc/typecheck.c | 122 +- src/cmd/gc/walk.c | 543 +- src/cmd/gc/y.tab.c | 2566 ++-- src/cmd/gc/yerr.h | 84 +- src/cmd/go/build.go | 226 +- src/cmd/go/doc.go | 206 +- src/cmd/go/generate.go | 398 + src/cmd/go/generate_test.go | 48 + src/cmd/go/get.go | 35 +- src/cmd/go/go_windows_test.go | 55 + src/cmd/go/help.go | 29 +- src/cmd/go/list.go | 39 +- src/cmd/go/main.go | 5 +- src/cmd/go/mkdoc.sh | 2 +- src/cmd/go/pkg.go | 180 +- src/cmd/go/test.bash | 405 +- src/cmd/go/test.go | 178 +- src/cmd/go/testdata/generate/test1.go | 13 + src/cmd/go/testdata/generate/test2.go | 10 + src/cmd/go/testdata/generate/test3.go | 9 + src/cmd/go/testdata/importcom/bad.go | 3 + src/cmd/go/testdata/importcom/conflict.go | 3 + src/cmd/go/testdata/importcom/src/bad/bad.go | 1 + src/cmd/go/testdata/importcom/src/conflict/a.go | 1 + src/cmd/go/testdata/importcom/src/conflict/b.go | 1 + src/cmd/go/testdata/importcom/src/works/x/x.go | 1 + src/cmd/go/testdata/importcom/src/works/x/x1.go | 1 + src/cmd/go/testdata/importcom/src/wrongplace/x.go | 1 + src/cmd/go/testdata/importcom/works.go | 3 + src/cmd/go/testdata/importcom/wrongplace.go | 3 + src/cmd/go/testdata/norunexample/example_test.go | 11 + src/cmd/go/testdata/norunexample/test_test.go | 10 + src/cmd/go/testdata/src/badc/x.c | 1 + src/cmd/go/testdata/src/badc/x.go | 1 + src/cmd/go/testdata/src/badtest/badexec/x_test.go | 5 + src/cmd/go/testdata/src/badtest/badsyntax/x.go | 1 + .../go/testdata/src/badtest/badsyntax/x_test.go | 3 + src/cmd/go/testdata/src/badtest/badvar/x.go | 1 + src/cmd/go/testdata/src/badtest/badvar/x_test.go | 5 + src/cmd/go/testdata/src/vetpkg/a_test.go | 1 + src/cmd/go/testdata/src/vetpkg/b.go | 7 + src/cmd/go/testdata/testinternal/p.go | 3 + src/cmd/go/testdata/testinternal2/p.go | 3 + .../testdata/testinternal2/x/y/z/internal/w/w.go | 1 + src/cmd/go/testflag.go | 7 +- src/cmd/go/testgo.go | 21 + src/cmd/go/tool.go | 14 +- src/cmd/go/vcs.go | 149 +- src/cmd/go/vcs_test.go | 124 + src/cmd/go/vet.go | 25 +- src/cmd/gofmt/doc.go | 2 +- src/cmd/gofmt/gofmt.go | 193 +- src/cmd/gofmt/gofmt_test.go | 121 +- src/cmd/gofmt/long_test.go | 4 +- src/cmd/gofmt/rewrite.go | 3 - src/cmd/gofmt/simplify.go | 50 +- src/cmd/gofmt/testdata/composites.golden | 2 + src/cmd/gofmt/testdata/composites.input | 2 + src/cmd/gofmt/testdata/crlf.golden | 1 + src/cmd/gofmt/testdata/crlf.input | 1 + src/cmd/gofmt/testdata/emptydecl.golden | 14 + src/cmd/gofmt/testdata/emptydecl.input | 16 + src/cmd/gofmt/testdata/ranges.golden | 30 + src/cmd/gofmt/testdata/ranges.input | 20 + src/cmd/gofmt/testdata/rewrite1.golden | 2 + src/cmd/gofmt/testdata/rewrite1.input | 2 + src/cmd/gofmt/testdata/rewrite2.golden | 2 + src/cmd/gofmt/testdata/rewrite2.input | 2 + src/cmd/gofmt/testdata/rewrite3.golden | 2 + src/cmd/gofmt/testdata/rewrite3.input | 2 + src/cmd/gofmt/testdata/rewrite4.golden | 2 + src/cmd/gofmt/testdata/rewrite4.input | 2 + src/cmd/gofmt/testdata/rewrite5.golden | 2 + src/cmd/gofmt/testdata/rewrite5.input | 2 + src/cmd/gofmt/testdata/rewrite6.golden | 2 + src/cmd/gofmt/testdata/rewrite6.input | 2 + src/cmd/gofmt/testdata/rewrite7.golden | 2 + src/cmd/gofmt/testdata/rewrite7.input | 2 + src/cmd/gofmt/testdata/rewrite8.golden | 2 + src/cmd/gofmt/testdata/rewrite8.input | 2 + src/cmd/gofmt/testdata/slices1.golden | 8 + src/cmd/gofmt/testdata/slices1.input | 8 + src/cmd/gofmt/testdata/slices2.golden | 2 + src/cmd/gofmt/testdata/slices2.input | 2 + src/cmd/gofmt/testdata/stdin1.golden | 2 + src/cmd/gofmt/testdata/stdin1.golden.gofmt | 3 - src/cmd/gofmt/testdata/stdin1.input | 2 + src/cmd/gofmt/testdata/stdin1.input.gofmt | 3 - src/cmd/gofmt/testdata/stdin2.golden | 2 +- src/cmd/gofmt/testdata/stdin2.golden.gofmt | 10 - src/cmd/gofmt/testdata/stdin2.input | 2 +- src/cmd/gofmt/testdata/stdin2.input.gofmt | 11 - src/cmd/gofmt/testdata/stdin3.golden | 1 + src/cmd/gofmt/testdata/stdin3.golden.gofmt | 7 - src/cmd/gofmt/testdata/stdin3.input | 1 + src/cmd/gofmt/testdata/stdin3.input.gofmt | 7 - src/cmd/gofmt/testdata/stdin4.golden | 2 + src/cmd/gofmt/testdata/stdin4.golden.gofmt | 3 - src/cmd/gofmt/testdata/stdin4.input | 2 + src/cmd/gofmt/testdata/stdin4.input.gofmt | 3 - src/cmd/gofmt/testdata/stdin5.golden | 3 + src/cmd/gofmt/testdata/stdin5.input | 3 + src/cmd/gofmt/testdata/stdin6.golden | 19 + src/cmd/gofmt/testdata/stdin6.input | 21 + src/cmd/gofmt/testdata/stdin7.golden | 19 + src/cmd/gofmt/testdata/stdin7.input | 21 + src/cmd/internal/goobj/read.go | 666 + src/cmd/internal/goobj/read_test.go | 28 + src/cmd/internal/objfile/disasm.go | 248 + src/cmd/internal/objfile/elf.go | 104 + src/cmd/internal/objfile/goobj.go | 93 + src/cmd/internal/objfile/macho.go | 116 + src/cmd/internal/objfile/objfile.go | 94 + src/cmd/internal/objfile/pe.go | 201 + src/cmd/internal/objfile/plan9obj.go | 146 + src/cmd/internal/rsc.io/arm/armasm/Makefile | 2 + src/cmd/internal/rsc.io/arm/armasm/decode.go | 567 + src/cmd/internal/rsc.io/arm/armasm/decode_test.go | 69 + src/cmd/internal/rsc.io/arm/armasm/ext_test.go | 614 + src/cmd/internal/rsc.io/arm/armasm/gnu.go | 164 + src/cmd/internal/rsc.io/arm/armasm/inst.go | 438 + src/cmd/internal/rsc.io/arm/armasm/objdump_test.go | 258 + .../internal/rsc.io/arm/armasm/objdumpext_test.go | 260 + src/cmd/internal/rsc.io/arm/armasm/plan9x.go | 211 + src/cmd/internal/rsc.io/arm/armasm/tables.go | 9448 +++++++++++++ .../internal/rsc.io/arm/armasm/testdata/Makefile | 5 + .../internal/rsc.io/arm/armasm/testdata/decode.txt | 306 + src/cmd/internal/rsc.io/x86/x86asm/Makefile | 3 + src/cmd/internal/rsc.io/x86/x86asm/decode.go | 1616 +++ src/cmd/internal/rsc.io/x86/x86asm/decode_test.go | 71 + src/cmd/internal/rsc.io/x86/x86asm/ext_test.go | 811 ++ src/cmd/internal/rsc.io/x86/x86asm/gnu.go | 926 ++ src/cmd/internal/rsc.io/x86/x86asm/inst.go | 641 + src/cmd/internal/rsc.io/x86/x86asm/inst_test.go | 20 + src/cmd/internal/rsc.io/x86/x86asm/intel.go | 518 + src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go | 383 + .../internal/rsc.io/x86/x86asm/objdumpext_test.go | 314 + .../internal/rsc.io/x86/x86asm/plan9ext_test.go | 120 + src/cmd/internal/rsc.io/x86/x86asm/plan9x.go | 346 + src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go | 54 + src/cmd/internal/rsc.io/x86/x86asm/tables.go | 9760 +++++++++++++ .../internal/rsc.io/x86/x86asm/testdata/Makefile | 12 + .../internal/rsc.io/x86/x86asm/testdata/decode.txt | 6731 +++++++++ src/cmd/internal/rsc.io/x86/x86asm/xed_test.go | 211 + src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go | 206 + src/cmd/ld/data.c | 357 +- src/cmd/ld/decodesym.c | 38 +- src/cmd/ld/doc.go | 6 +- src/cmd/ld/dwarf.c | 156 +- src/cmd/ld/elf.c | 3 +- src/cmd/ld/ldelf.c | 8 +- src/cmd/ld/ldmacho.c | 4 +- src/cmd/ld/ldpe.c | 32 +- src/cmd/ld/lib.c | 91 +- src/cmd/ld/lib.h | 14 +- src/cmd/ld/macho.c | 3 +- src/cmd/ld/pass.c | 104 - src/cmd/ld/pcln.c | 6 +- src/cmd/ld/pobj.c | 22 +- src/cmd/ld/symtab.c | 55 +- src/cmd/ld/textflag.h | 13 + src/cmd/nm/debug_goobj.go | 670 - src/cmd/nm/elf.go | 57 - src/cmd/nm/goobj.go | 67 - src/cmd/nm/macho.go | 69 - src/cmd/nm/nm.go | 57 +- src/cmd/nm/nm_test.go | 11 +- src/cmd/nm/pe.go | 98 - src/cmd/nm/plan9obj.go | 48 - src/cmd/objdump/Makefile | 10 - src/cmd/objdump/armasm.go | 10821 --------------- src/cmd/objdump/elf.go | 65 - src/cmd/objdump/macho.go | 77 - src/cmd/objdump/main.go | 456 +- src/cmd/objdump/objdump_test.go | 122 +- src/cmd/objdump/pe.go | 99 - src/cmd/objdump/plan9obj.go | 63 - src/cmd/objdump/x86.go | 13800 ------------------- src/cmd/pack/doc.go | 4 + src/cmd/pack/pack.go | 50 +- src/cmd/pack/pack_test.go | 33 +- src/cmd/pprof/README | 8 + src/cmd/pprof/doc.go | 12 + src/cmd/pprof/internal/commands/commands.go | 215 + src/cmd/pprof/internal/driver/driver.go | 1036 ++ src/cmd/pprof/internal/driver/interactive.go | 492 + src/cmd/pprof/internal/fetch/fetch.go | 82 + src/cmd/pprof/internal/plugin/plugin.go | 213 + src/cmd/pprof/internal/profile/encode.go | 470 + src/cmd/pprof/internal/profile/filter.go | 157 + src/cmd/pprof/internal/profile/legacy_profile.go | 1250 ++ src/cmd/pprof/internal/profile/profile.go | 567 + src/cmd/pprof/internal/profile/proto.go | 298 + src/cmd/pprof/internal/profile/prune.go | 97 + src/cmd/pprof/internal/report/report.go | 1718 +++ src/cmd/pprof/internal/report/source.go | 450 + src/cmd/pprof/internal/report/source_html.go | 77 + src/cmd/pprof/internal/svg/svg.go | 75 + src/cmd/pprof/internal/symbolizer/symbolizer.go | 195 + src/cmd/pprof/internal/symbolz/symbolz.go | 111 + src/cmd/pprof/internal/tempfile/tempfile.go | 45 + src/cmd/pprof/pprof.go | 237 + src/cmd/yacc/Makefile | 12 - src/cmd/yacc/doc.go | 5 +- src/cmd/yacc/expr.y | 205 - src/cmd/yacc/testdata/expr/README | 20 + src/cmd/yacc/testdata/expr/expr.y | 202 + src/cmd/yacc/testdata/expr/main.go | 15 + src/cmd/yacc/yacc.go | 90 +- src/compress/bzip2/bit_reader.go | 90 + src/compress/bzip2/bzip2.go | 503 + src/compress/bzip2/bzip2_test.go | 419 + src/compress/bzip2/huffman.go | 251 + src/compress/bzip2/move_to_front.go | 53 + .../bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 | Bin 0 -> 124744 bytes src/compress/bzip2/testdata/e.txt.bz2 | Bin 0 -> 43149 bytes src/compress/flate/copy.go | 32 + src/compress/flate/copy_test.go | 54 + src/compress/flate/deflate.go | 571 + src/compress/flate/deflate_test.go | 490 + src/compress/flate/fixedhuff.go | 78 + src/compress/flate/flate_test.go | 62 + src/compress/flate/gen.go | 190 + src/compress/flate/huffman_bit_writer.go | 517 + src/compress/flate/huffman_code.go | 323 + src/compress/flate/inflate.go | 739 + src/compress/flate/inflate_test.go | 39 + src/compress/flate/reader_test.go | 96 + src/compress/flate/reverse_bits.go | 48 + src/compress/flate/token.go | 102 + src/compress/flate/writer_test.go | 60 + src/compress/gzip/gunzip.go | 287 + src/compress/gzip/gunzip_test.go | 410 + src/compress/gzip/gzip.go | 272 + src/compress/gzip/gzip_test.go | 231 + src/compress/gzip/testdata/issue6550.gz | Bin 0 -> 65536 bytes src/compress/lzw/reader.go | 259 + src/compress/lzw/reader_test.go | 152 + src/compress/lzw/writer.go | 262 + src/compress/lzw/writer_test.go | 144 + src/compress/testdata/Mark.Twain-Tom.Sawyer.txt | 8858 ++++++++++++ src/compress/testdata/e.txt | 1 + src/compress/testdata/pi.txt | 1 + src/compress/zlib/example_test.go | 37 + src/compress/zlib/reader.go | 161 + src/compress/zlib/reader_test.go | 127 + src/compress/zlib/writer.go | 198 + src/compress/zlib/writer_test.go | 205 + src/container/heap/example_intheap_test.go | 47 + src/container/heap/example_pq_test.go | 97 + src/container/heap/heap.go | 117 + src/container/heap/heap_test.go | 213 + src/container/list/example_test.go | 30 + src/container/list/list.go | 216 + src/container/list/list_test.go | 343 + src/container/ring/ring.go | 141 + src/container/ring/ring_test.go | 228 + src/crypto/aes/aes_test.go | 421 + src/crypto/aes/asm_amd64.s | 289 + src/crypto/aes/block.go | 176 + src/crypto/aes/cipher.go | 66 + src/crypto/aes/cipher_asm.go | 48 + src/crypto/aes/cipher_generic.go | 19 + src/crypto/aes/const.go | 358 + src/crypto/cipher/benchmark_test.go | 139 + src/crypto/cipher/cbc.go | 133 + src/crypto/cipher/cbc_aes_test.go | 104 + src/crypto/cipher/cfb.go | 72 + src/crypto/cipher/cfb_test.go | 113 + src/crypto/cipher/cipher.go | 53 + src/crypto/cipher/cipher_test.go | 36 + src/crypto/cipher/common_test.go | 28 + src/crypto/cipher/ctr.go | 76 + src/crypto/cipher/ctr_aes_test.go | 102 + src/crypto/cipher/example_test.go | 283 + src/crypto/cipher/gcm.go | 343 + src/crypto/cipher/gcm_test.go | 159 + src/crypto/cipher/io.go | 55 + src/crypto/cipher/ofb.go | 66 + src/crypto/cipher/ofb_test.go | 102 + src/crypto/cipher/xor.go | 84 + src/crypto/cipher/xor_test.go | 28 + src/crypto/crypto.go | 126 + src/crypto/des/block.go | 223 + src/crypto/des/cipher.go | 73 + src/crypto/des/const.go | 139 + src/crypto/des/des_test.go | 1566 +++ src/crypto/des/example_test.go | 25 + src/crypto/dsa/dsa.go | 278 + src/crypto/dsa/dsa_test.go | 85 + src/crypto/ecdsa/ecdsa.go | 189 + src/crypto/ecdsa/ecdsa_test.go | 191 + src/crypto/ecdsa/testdata/SigVer.rsp.bz2 | Bin 0 -> 95485 bytes src/crypto/elliptic/elliptic.go | 373 + src/crypto/elliptic/elliptic_test.go | 458 + src/crypto/elliptic/p224.go | 765 + src/crypto/elliptic/p224_test.go | 47 + src/crypto/elliptic/p256.go | 1186 ++ src/crypto/hmac/hmac.go | 102 + src/crypto/hmac/hmac_test.go | 570 + src/crypto/md5/example_test.go | 25 + src/crypto/md5/gen.go | 331 + src/crypto/md5/md5.go | 136 + src/crypto/md5/md5_test.go | 163 + src/crypto/md5/md5block.go | 265 + src/crypto/md5/md5block_386.s | 182 + src/crypto/md5/md5block_amd64.s | 179 + src/crypto/md5/md5block_amd64p32.s | 184 + src/crypto/md5/md5block_arm.s | 299 + src/crypto/md5/md5block_decl.go | 11 + src/crypto/md5/md5block_generic.go | 9 + src/crypto/rand/example_test.go | 28 + src/crypto/rand/rand.go | 21 + src/crypto/rand/rand_linux.go | 39 + src/crypto/rand/rand_test.go | 43 + src/crypto/rand/rand_unix.go | 147 + src/crypto/rand/rand_windows.go | 47 + src/crypto/rand/util.go | 136 + src/crypto/rand/util_test.go | 65 + src/crypto/rc4/rc4.go | 69 + src/crypto/rc4/rc4_386.s | 53 + src/crypto/rc4/rc4_amd64.s | 179 + src/crypto/rc4/rc4_amd64p32.s | 192 + src/crypto/rc4/rc4_arm.s | 62 + src/crypto/rc4/rc4_asm.go | 18 + src/crypto/rc4/rc4_ref.go | 13 + src/crypto/rc4/rc4_test.go | 173 + src/crypto/rsa/pkcs1v15.go | 292 + src/crypto/rsa/pkcs1v15_test.go | 271 + src/crypto/rsa/pss.go | 297 + src/crypto/rsa/pss_test.go | 249 + src/crypto/rsa/rsa.go | 557 + src/crypto/rsa/rsa_test.go | 392 + src/crypto/rsa/testdata/pss-vect.txt.bz2 | Bin 0 -> 28526 bytes src/crypto/sha1/example_test.go | 25 + src/crypto/sha1/sha1.go | 130 + src/crypto/sha1/sha1_test.go | 129 + src/crypto/sha1/sha1block.go | 90 + src/crypto/sha1/sha1block_386.s | 233 + src/crypto/sha1/sha1block_amd64.s | 216 + src/crypto/sha1/sha1block_amd64p32.s | 216 + src/crypto/sha1/sha1block_arm.s | 217 + src/crypto/sha1/sha1block_decl.go | 11 + src/crypto/sha1/sha1block_generic.go | 9 + src/crypto/sha256/sha256.go | 193 + src/crypto/sha256/sha256_test.go | 176 + src/crypto/sha256/sha256block.go | 128 + src/crypto/sha256/sha256block_386.s | 283 + src/crypto/sha256/sha256block_amd64.s | 256 + src/crypto/sha256/sha256block_decl.go | 11 + src/crypto/sha512/sha512.go | 198 + src/crypto/sha512/sha512_test.go | 176 + src/crypto/sha512/sha512block.go | 144 + src/crypto/sha512/sha512block_amd64.s | 273 + src/crypto/sha512/sha512block_decl.go | 11 + src/crypto/subtle/constant_time.go | 73 + src/crypto/subtle/constant_time_test.go | 127 + src/crypto/tls/alert.go | 79 + src/crypto/tls/cipher_suites.go | 275 + src/crypto/tls/common.go | 621 + src/crypto/tls/conn.go | 1030 ++ src/crypto/tls/conn_test.go | 118 + src/crypto/tls/example_test.go | 57 + src/crypto/tls/generate_cert.go | 161 + src/crypto/tls/handshake_client.go | 638 + src/crypto/tls/handshake_client_test.go | 490 + src/crypto/tls/handshake_messages.go | 1438 ++ src/crypto/tls/handshake_messages_test.go | 251 + src/crypto/tls/handshake_server.go | 685 + src/crypto/tls/handshake_server_test.go | 868 ++ src/crypto/tls/handshake_test.go | 167 + src/crypto/tls/key_agreement.go | 413 + src/crypto/tls/prf.go | 291 + src/crypto/tls/prf_test.go | 126 + .../testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA | 129 + .../testdata/Client-TLSv10-ClientCert-ECDSA-RSA | 125 + .../testdata/Client-TLSv10-ClientCert-RSA-ECDSA | 128 + .../tls/testdata/Client-TLSv10-ClientCert-RSA-RSA | 124 + .../tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES | 87 + .../tls/testdata/Client-TLSv10-ECDHE-RSA-AES | 97 + src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 | 83 + .../tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES | 89 + .../tls/testdata/Client-TLSv11-ECDHE-RSA-AES | 99 + src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 | 83 + src/crypto/tls/testdata/Client-TLSv12-ALPN | 97 + src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch | 95 + .../testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA | 134 + .../testdata/Client-TLSv12-ClientCert-ECDSA-RSA | 127 + .../testdata/Client-TLSv12-ClientCert-RSA-ECDSA | 133 + .../tls/testdata/Client-TLSv12-ClientCert-RSA-RSA | 126 + .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES | 89 + .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM | 84 + .../tls/testdata/Client-TLSv12-ECDHE-RSA-AES | 99 + src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 | 83 + src/crypto/tls/testdata/Server-SSLv3-RSA-3DES | 83 + src/crypto/tls/testdata/Server-SSLv3-RSA-AES | 84 + src/crypto/tls/testdata/Server-SSLv3-RSA-RC4 | 79 + .../tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES | 84 + src/crypto/tls/testdata/Server-TLSv10-RSA-3DES | 79 + src/crypto/tls/testdata/Server-TLSv10-RSA-AES | 82 + src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 | 76 + src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV | 17 + src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 | 76 + src/crypto/tls/testdata/Server-TLSv12-ALPN | 122 + src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch | 121 + .../Server-TLSv12-CipherSuiteCertPreferenceECDSA | 91 + .../Server-TLSv12-CipherSuiteCertPreferenceRSA | 101 + .../Server-TLSv12-ClientAuthRequestedAndECDSAGiven | 122 + .../Server-TLSv12-ClientAuthRequestedAndGiven | 121 + .../Server-TLSv12-ClientAuthRequestedNotGiven | 81 + .../tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES | 89 + src/crypto/tls/testdata/Server-TLSv12-IssueTicket | 87 + .../testdata/Server-TLSv12-IssueTicketPreDisable | 87 + src/crypto/tls/testdata/Server-TLSv12-RSA-3DES | 83 + src/crypto/tls/testdata/Server-TLSv12-RSA-AES | 87 + src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM | 93 + src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 | 79 + src/crypto/tls/testdata/Server-TLSv12-Resume | 36 + .../tls/testdata/Server-TLSv12-ResumeDisabled | 87 + src/crypto/tls/testdata/Server-TLSv12-SNI | 76 + src/crypto/tls/ticket.go | 183 + src/crypto/tls/tls.go | 275 + src/crypto/tls/tls_test.go | 282 + src/crypto/x509/cert_pool.go | 116 + src/crypto/x509/example_test.go | 91 + src/crypto/x509/pem_decrypt.go | 233 + src/crypto/x509/pem_decrypt_test.go | 223 + src/crypto/x509/pkcs1.go | 122 + src/crypto/x509/pkcs8.go | 54 + src/crypto/x509/pkcs8_test.go | 28 + src/crypto/x509/pkix/pkix.go | 178 + src/crypto/x509/root.go | 17 + src/crypto/x509/root_cgo_darwin.go | 79 + src/crypto/x509/root_darwin.go | 23 + src/crypto/x509/root_darwin_test.go | 50 + src/crypto/x509/root_nocgo_darwin.go | 11 + src/crypto/x509/root_plan9.go | 33 + src/crypto/x509/root_unix.go | 64 + src/crypto/x509/root_windows.go | 229 + src/crypto/x509/sec1.go | 83 + src/crypto/x509/sec1_test.go | 30 + src/crypto/x509/verify.go | 476 + src/crypto/x509/verify_test.go | 1123 ++ src/crypto/x509/x509.go | 1916 +++ src/crypto/x509/x509_test.go | 1027 ++ src/crypto/x509/x509_test_import.go | 53 + src/database/sql/convert.go | 299 + src/database/sql/convert_test.go | 348 + src/database/sql/doc.txt | 46 + src/database/sql/driver/driver.go | 211 + src/database/sql/driver/types.go | 252 + src/database/sql/driver/types_test.go | 65 + src/database/sql/example_test.go | 46 + src/database/sql/fakedb_test.go | 829 ++ src/database/sql/sql.go | 1770 +++ src/database/sql/sql_test.go | 1987 +++ src/debug/dwarf/buf.go | 181 + src/debug/dwarf/const.go | 454 + src/debug/dwarf/entry.go | 401 + src/debug/dwarf/open.go | 87 + src/debug/dwarf/testdata/typedef.c | 85 + src/debug/dwarf/testdata/typedef.elf | Bin 0 -> 12448 bytes src/debug/dwarf/testdata/typedef.elf4 | Bin 0 -> 9496 bytes src/debug/dwarf/testdata/typedef.macho | Bin 0 -> 5024 bytes src/debug/dwarf/type.go | 696 + src/debug/dwarf/type_test.go | 122 + src/debug/dwarf/typeunit.go | 166 + src/debug/dwarf/unit.go | 90 + src/debug/elf/elf.go | 1773 +++ src/debug/elf/elf_test.go | 49 + src/debug/elf/file.go | 953 ++ src/debug/elf/file_test.go | 345 + src/debug/elf/symbols_test.go | 834 ++ src/debug/elf/testdata/gcc-386-freebsd-exec | Bin 0 -> 5742 bytes src/debug/elf/testdata/gcc-amd64-linux-exec | Bin 0 -> 8844 bytes .../testdata/gcc-amd64-openbsd-debug-with-rela.obj | Bin 0 -> 6544 bytes .../elf/testdata/go-relocation-test-clang-x86.obj | Bin 0 -> 1900 bytes .../testdata/go-relocation-test-gcc424-x86-64.obj | Bin 0 -> 3088 bytes .../testdata/go-relocation-test-gcc441-x86-64.obj | Bin 0 -> 2936 bytes .../elf/testdata/go-relocation-test-gcc441-x86.obj | Bin 0 -> 1884 bytes .../testdata/go-relocation-test-gcc482-aarch64.obj | Bin 0 -> 3392 bytes src/debug/elf/testdata/hello-world-core.gz | Bin 0 -> 12678 bytes src/debug/elf/testdata/hello.c | 7 + src/debug/gosym/pclinetest.asm | 58 + src/debug/gosym/pclinetest.h | 9 + src/debug/gosym/pclntab.go | 453 + src/debug/gosym/pclntab_test.go | 274 + src/debug/gosym/symtab.go | 710 + src/debug/macho/fat.go | 146 + src/debug/macho/file.go | 524 + src/debug/macho/file_test.go | 210 + src/debug/macho/macho.go | 316 + .../macho/testdata/fat-gcc-386-amd64-darwin-exec | Bin 0 -> 28992 bytes src/debug/macho/testdata/gcc-386-darwin-exec | Bin 0 -> 12588 bytes src/debug/macho/testdata/gcc-amd64-darwin-exec | Bin 0 -> 8512 bytes .../macho/testdata/gcc-amd64-darwin-exec-debug | Bin 0 -> 4540 bytes src/debug/macho/testdata/hello.c | 8 + src/debug/pe/file.go | 394 + src/debug/pe/file_test.go | 243 + src/debug/pe/pe.go | 134 + src/debug/pe/testdata/gcc-386-mingw-exec | Bin 0 -> 29941 bytes src/debug/pe/testdata/gcc-386-mingw-obj | Bin 0 -> 2372 bytes src/debug/pe/testdata/gcc-amd64-mingw-exec | Bin 0 -> 273083 bytes src/debug/pe/testdata/gcc-amd64-mingw-obj | Bin 0 -> 736 bytes src/debug/pe/testdata/hello.c | 8 + src/debug/plan9obj/file.go | 328 + src/debug/plan9obj/file_test.go | 81 + src/debug/plan9obj/plan9obj.go | 36 + src/debug/plan9obj/testdata/386-plan9-exec | Bin 0 -> 37232 bytes src/debug/plan9obj/testdata/amd64-plan9-exec | Bin 0 -> 34279 bytes src/debug/plan9obj/testdata/hello.c | 8 + src/encoding/ascii85/ascii85.go | 310 + src/encoding/ascii85/ascii85_test.go | 210 + src/encoding/asn1/asn1.go | 922 ++ src/encoding/asn1/asn1_test.go | 867 ++ src/encoding/asn1/common.go | 163 + src/encoding/asn1/marshal.go | 646 + src/encoding/asn1/marshal_test.go | 164 + src/encoding/base32/base32.go | 426 + src/encoding/base32/base32_test.go | 302 + src/encoding/base32/example_test.go | 45 + src/encoding/base64/base64.go | 391 + src/encoding/base64/base64_test.go | 360 + src/encoding/base64/example_test.go | 45 + src/encoding/binary/binary.go | 634 + src/encoding/binary/binary_test.go | 416 + src/encoding/binary/example_test.go | 52 + src/encoding/binary/varint.go | 133 + src/encoding/binary/varint_test.go | 168 + src/encoding/csv/reader.go | 337 + src/encoding/csv/reader_test.go | 284 + src/encoding/csv/writer.go | 139 + src/encoding/csv/writer_test.go | 85 + src/encoding/encoding.go | 48 + src/encoding/gob/codec_test.go | 1475 ++ src/encoding/gob/debug.go | 705 + src/encoding/gob/dec_helpers.go | 468 + src/encoding/gob/decgen.go | 240 + src/encoding/gob/decode.go | 1217 ++ src/encoding/gob/decoder.go | 218 + src/encoding/gob/doc.go | 386 + src/encoding/gob/dump.go | 29 + src/encoding/gob/enc_helpers.go | 414 + src/encoding/gob/encgen.go | 218 + src/encoding/gob/encode.go | 696 + src/encoding/gob/encoder.go | 248 + src/encoding/gob/encoder_test.go | 956 ++ src/encoding/gob/error.go | 43 + src/encoding/gob/example_encdec_test.go | 61 + src/encoding/gob/example_interface_test.go | 81 + src/encoding/gob/example_test.go | 60 + src/encoding/gob/gobencdec_test.go | 798 ++ src/encoding/gob/timing_test.go | 325 + src/encoding/gob/type.go | 923 ++ src/encoding/gob/type_test.go | 222 + src/encoding/hex/hex.go | 216 + src/encoding/hex/hex_test.go | 153 + src/encoding/json/bench_test.go | 189 + src/encoding/json/decode.go | 1084 ++ src/encoding/json/decode_test.go | 1373 ++ src/encoding/json/encode.go | 1183 ++ src/encoding/json/encode_test.go | 532 + src/encoding/json/example_test.go | 161 + src/encoding/json/fold.go | 143 + src/encoding/json/fold_test.go | 116 + src/encoding/json/indent.go | 137 + src/encoding/json/scanner.go | 623 + src/encoding/json/scanner_test.go | 315 + src/encoding/json/stream.go | 200 + src/encoding/json/stream_test.go | 206 + src/encoding/json/tagkey_test.go | 115 + src/encoding/json/tags.go | 44 + src/encoding/json/tags_test.go | 28 + src/encoding/json/testdata/code.json.gz | Bin 0 -> 120432 bytes src/encoding/pem/pem.go | 277 + src/encoding/pem/pem_test.go | 404 + src/encoding/xml/atom_test.go | 56 + src/encoding/xml/example_test.go | 151 + src/encoding/xml/marshal.go | 938 ++ src/encoding/xml/marshal_test.go | 1266 ++ src/encoding/xml/read.go | 692 + src/encoding/xml/read_test.go | 714 + src/encoding/xml/typeinfo.go | 363 + src/encoding/xml/xml.go | 1945 +++ src/encoding/xml/xml_test.go | 749 + src/errors/errors.go | 20 + src/errors/errors_test.go | 53 + src/errors/example_test.go | 34 + src/expvar/expvar.go | 336 + src/expvar/expvar_test.go | 167 + src/flag/example_test.go | 83 + src/flag/export_test.go | 17 + src/flag/flag.go | 858 ++ src/flag/flag_test.go | 379 + src/fmt/doc.go | 295 + src/fmt/export_test.go | 7 + src/fmt/fmt_test.go | 1310 ++ src/fmt/format.go | 524 + src/fmt/print.go | 1223 ++ src/fmt/scan.go | 1169 ++ src/fmt/scan_test.go | 992 ++ src/fmt/stringer_test.go | 61 + src/go/ast/ast.go | 995 ++ src/go/ast/ast_test.go | 50 + src/go/ast/commentmap.go | 332 + src/go/ast/commentmap_test.go | 143 + src/go/ast/example_test.go | 210 + src/go/ast/filter.go | 466 + src/go/ast/filter_test.go | 86 + src/go/ast/import.go | 196 + src/go/ast/print.go | 251 + src/go/ast/print_test.go | 97 + src/go/ast/resolve.go | 174 + src/go/ast/scope.go | 162 + src/go/ast/walk.go | 386 + src/go/build/build.go | 1391 ++ src/go/build/build_test.go | 224 + src/go/build/deps_test.go | 443 + src/go/build/doc.go | 139 + src/go/build/read.go | 238 + src/go/build/read_test.go | 226 + src/go/build/syslist.go | 8 + src/go/build/syslist_test.go | 62 + src/go/build/testdata/empty/dummy | 0 src/go/build/testdata/multi/file.go | 5 + src/go/build/testdata/multi/file_appengine.go | 5 + src/go/build/testdata/other/file/file.go | 5 + src/go/build/testdata/other/main.go | 11 + src/go/doc/Makefile | 7 + src/go/doc/comment.go | 480 + src/go/doc/comment_test.go | 207 + src/go/doc/doc.go | 111 + src/go/doc/doc_test.go | 146 + src/go/doc/example.go | 355 + src/go/doc/example_test.go | 191 + src/go/doc/exports.go | 205 + src/go/doc/filter.go | 105 + src/go/doc/headscan.go | 114 + src/go/doc/reader.go | 853 ++ src/go/doc/synopsis.go | 82 + src/go/doc/synopsis_test.go | 51 + src/go/doc/testdata/a.0.golden | 52 + src/go/doc/testdata/a.1.golden | 52 + src/go/doc/testdata/a.2.golden | 52 + src/go/doc/testdata/a0.go | 40 + src/go/doc/testdata/a1.go | 12 + src/go/doc/testdata/b.0.golden | 71 + src/go/doc/testdata/b.1.golden | 83 + src/go/doc/testdata/b.2.golden | 71 + src/go/doc/testdata/b.go | 58 + src/go/doc/testdata/benchmark.go | 293 + src/go/doc/testdata/blank.0.golden | 37 + src/go/doc/testdata/blank.1.golden | 46 + src/go/doc/testdata/blank.2.golden | 37 + src/go/doc/testdata/blank.go | 38 + src/go/doc/testdata/bugpara.0.golden | 20 + src/go/doc/testdata/bugpara.1.golden | 20 + src/go/doc/testdata/bugpara.2.golden | 20 + src/go/doc/testdata/bugpara.go | 5 + src/go/doc/testdata/c.0.golden | 48 + src/go/doc/testdata/c.1.golden | 48 + src/go/doc/testdata/c.2.golden | 48 + src/go/doc/testdata/c.go | 62 + src/go/doc/testdata/d.0.golden | 104 + src/go/doc/testdata/d.1.golden | 104 + src/go/doc/testdata/d.2.golden | 104 + src/go/doc/testdata/d1.go | 57 + src/go/doc/testdata/d2.go | 45 + src/go/doc/testdata/e.0.golden | 109 + src/go/doc/testdata/e.1.golden | 144 + src/go/doc/testdata/e.2.golden | 130 + src/go/doc/testdata/e.go | 147 + src/go/doc/testdata/error1.0.golden | 30 + src/go/doc/testdata/error1.1.golden | 32 + src/go/doc/testdata/error1.2.golden | 30 + src/go/doc/testdata/error1.go | 24 + src/go/doc/testdata/error2.0.golden | 27 + src/go/doc/testdata/error2.1.golden | 37 + src/go/doc/testdata/error2.2.golden | 27 + src/go/doc/testdata/error2.go | 29 + src/go/doc/testdata/example.go | 81 + src/go/doc/testdata/f.0.golden | 13 + src/go/doc/testdata/f.1.golden | 16 + src/go/doc/testdata/f.2.golden | 13 + src/go/doc/testdata/f.go | 14 + src/go/doc/testdata/template.txt | 68 + src/go/doc/testdata/testing.0.golden | 156 + src/go/doc/testdata/testing.1.golden | 298 + src/go/doc/testdata/testing.2.golden | 156 + src/go/doc/testdata/testing.go | 404 + src/go/format/format.go | 266 + src/go/format/format_test.go | 128 + src/go/parser/error_test.go | 182 + src/go/parser/example_test.go | 34 + src/go/parser/interface.go | 198 + src/go/parser/parser.go | 2462 ++++ src/go/parser/parser_test.go | 449 + src/go/parser/performance_test.go | 30 + src/go/parser/short_test.go | 104 + src/go/parser/testdata/commas.src | 19 + src/go/parser/testdata/issue3106.src | 46 + src/go/printer/example_test.go | 67 + src/go/printer/nodes.go | 1606 +++ src/go/printer/performance_test.go | 58 + src/go/printer/printer.go | 1292 ++ src/go/printer/printer_test.go | 562 + src/go/printer/testdata/comments.golden | 643 + src/go/printer/testdata/comments.input | 648 + src/go/printer/testdata/comments.x | 56 + src/go/printer/testdata/comments2.golden | 105 + src/go/printer/testdata/comments2.input | 105 + src/go/printer/testdata/declarations.golden | 978 ++ src/go/printer/testdata/declarations.input | 992 ++ src/go/printer/testdata/empty.golden | 5 + src/go/printer/testdata/empty.input | 5 + src/go/printer/testdata/expressions.golden | 686 + src/go/printer/testdata/expressions.input | 715 + src/go/printer/testdata/expressions.raw | 686 + src/go/printer/testdata/linebreaks.golden | 275 + src/go/printer/testdata/linebreaks.input | 271 + src/go/printer/testdata/parser.go | 2153 +++ src/go/printer/testdata/slow.golden | 85 + src/go/printer/testdata/slow.input | 85 + src/go/printer/testdata/statements.golden | 644 + src/go/printer/testdata/statements.input | 555 + src/go/scanner/errors.go | 126 + src/go/scanner/example_test.go | 46 + src/go/scanner/scanner.go | 760 + src/go/scanner/scanner_test.go | 775 ++ src/go/token/position.go | 485 + src/go/token/position_test.go | 297 + src/go/token/serialize.go | 56 + src/go/token/serialize_test.go | 111 + src/go/token/token.go | 308 + src/hash/adler32/adler32.go | 78 + src/hash/adler32/adler32_test.go | 105 + src/hash/crc32/crc32.go | 135 + src/hash/crc32/crc32_amd64.s | 64 + src/hash/crc32/crc32_amd64p32.s | 64 + src/hash/crc32/crc32_amd64x.go | 27 + src/hash/crc32/crc32_generic.go | 14 + src/hash/crc32/crc32_test.go | 99 + src/hash/crc64/crc64.go | 87 + src/hash/crc64/crc64_test.go | 81 + src/hash/fnv/fnv.go | 131 + src/hash/fnv/fnv_test.go | 165 + src/hash/hash.go | 43 + src/hash/test_cases.txt | 31 + src/hash/test_gen.awk | 14 + src/html/entity.go | 2253 +++ src/html/entity_test.go | 29 + src/html/escape.go | 250 + src/html/escape_test.go | 115 + src/html/template/attr.go | 175 + src/html/template/clone_test.go | 188 + src/html/template/content.go | 136 + src/html/template/content_test.go | 280 + src/html/template/context.go | 339 + src/html/template/css.go | 268 + src/html/template/css_test.go | 281 + src/html/template/doc.go | 191 + src/html/template/error.go | 205 + src/html/template/escape.go | 807 ++ src/html/template/escape_test.go | 1697 +++ src/html/template/html.go | 257 + src/html/template/html_test.go | 94 + src/html/template/js.go | 362 + src/html/template/js_test.go | 401 + src/html/template/template.go | 389 + src/html/template/transition.go | 550 + src/html/template/url.go | 105 + src/html/template/url_test.go | 112 + src/image/color/color.go | 297 + src/image/color/palette/gen.go | 121 + src/image/color/palette/generate.go | 8 + src/image/color/palette/palette.go | 503 + src/image/color/ycbcr.go | 99 + src/image/color/ycbcr_test.go | 33 + src/image/decode_example_test.go | 140 + src/image/decode_test.go | 120 + src/image/draw/bench_test.go | 206 + src/image/draw/clip_test.go | 193 + src/image/draw/draw.go | 673 + src/image/draw/draw_test.go | 429 + src/image/format.go | 100 + src/image/geom.go | 234 + src/image/gif/reader.go | 465 + src/image/gif/reader_test.go | 247 + src/image/gif/writer.go | 333 + src/image/gif/writer_test.go | 227 + src/image/image.go | 936 ++ src/image/image_test.go | 113 + src/image/jpeg/dct_test.go | 299 + src/image/jpeg/fdct.go | 190 + src/image/jpeg/huffman.go | 244 + src/image/jpeg/idct.go | 192 + src/image/jpeg/reader.go | 527 + src/image/jpeg/reader_test.go | 270 + src/image/jpeg/scan.go | 442 + src/image/jpeg/writer.go | 614 + src/image/jpeg/writer_test.go | 232 + src/image/names.go | 52 + src/image/png/paeth.go | 71 + src/image/png/paeth_test.go | 91 + src/image/png/reader.go | 820 ++ src/image/png/reader_test.go | 362 + src/image/png/testdata/benchGray.png | Bin 0 -> 14709 bytes src/image/png/testdata/benchNRGBA-gradient.png | Bin 0 -> 58831 bytes src/image/png/testdata/benchNRGBA-opaque.png | Bin 0 -> 44237 bytes src/image/png/testdata/benchPaletted.png | Bin 0 -> 13397 bytes src/image/png/testdata/benchRGB-interlace.png | Bin 0 -> 47483 bytes src/image/png/testdata/benchRGB.png | Bin 0 -> 39571 bytes src/image/png/testdata/invalid-crc32.png | Bin 0 -> 1289 bytes src/image/png/testdata/invalid-noend.png | Bin 0 -> 1277 bytes src/image/png/testdata/invalid-trunc.png | Bin 0 -> 1288 bytes src/image/png/testdata/invalid-zlib.png | Bin 0 -> 1289 bytes src/image/png/testdata/pngsuite/README | 21 + src/image/png/testdata/pngsuite/README.original | 85 + src/image/png/testdata/pngsuite/basn0g01-30.png | Bin 0 -> 162 bytes src/image/png/testdata/pngsuite/basn0g01-30.sng | 39 + src/image/png/testdata/pngsuite/basn0g01.png | Bin 0 -> 164 bytes src/image/png/testdata/pngsuite/basn0g01.sng | 41 + src/image/png/testdata/pngsuite/basn0g02-29.png | Bin 0 -> 110 bytes src/image/png/testdata/pngsuite/basn0g02-29.sng | 38 + src/image/png/testdata/pngsuite/basn0g02.png | Bin 0 -> 104 bytes src/image/png/testdata/pngsuite/basn0g02.sng | 41 + src/image/png/testdata/pngsuite/basn0g04-31.png | Bin 0 -> 153 bytes src/image/png/testdata/pngsuite/basn0g04-31.sng | 40 + src/image/png/testdata/pngsuite/basn0g04.png | Bin 0 -> 145 bytes src/image/png/testdata/pngsuite/basn0g04.sng | 41 + src/image/png/testdata/pngsuite/basn0g08.png | Bin 0 -> 138 bytes src/image/png/testdata/pngsuite/basn0g08.sng | 41 + src/image/png/testdata/pngsuite/basn0g16.png | Bin 0 -> 167 bytes src/image/png/testdata/pngsuite/basn0g16.sng | 41 + src/image/png/testdata/pngsuite/basn2c08.png | Bin 0 -> 145 bytes src/image/png/testdata/pngsuite/basn2c08.sng | 41 + src/image/png/testdata/pngsuite/basn2c16.png | Bin 0 -> 302 bytes src/image/png/testdata/pngsuite/basn2c16.sng | 41 + src/image/png/testdata/pngsuite/basn3p01.png | Bin 0 -> 112 bytes src/image/png/testdata/pngsuite/basn3p01.sng | 45 + src/image/png/testdata/pngsuite/basn3p02.png | Bin 0 -> 146 bytes src/image/png/testdata/pngsuite/basn3p02.sng | 47 + src/image/png/testdata/pngsuite/basn3p04-31i.png | Bin 0 -> 358 bytes src/image/png/testdata/pngsuite/basn3p04-31i.sng | 57 + src/image/png/testdata/pngsuite/basn3p04.png | Bin 0 -> 216 bytes src/image/png/testdata/pngsuite/basn3p04.sng | 58 + src/image/png/testdata/pngsuite/basn3p08-trns.png | Bin 0 -> 1538 bytes src/image/png/testdata/pngsuite/basn3p08-trns.sng | 301 + src/image/png/testdata/pngsuite/basn3p08.png | Bin 0 -> 1286 bytes src/image/png/testdata/pngsuite/basn3p08.sng | 299 + src/image/png/testdata/pngsuite/basn4a08.png | Bin 0 -> 126 bytes src/image/png/testdata/pngsuite/basn4a08.sng | 41 + src/image/png/testdata/pngsuite/basn4a16.png | Bin 0 -> 2206 bytes src/image/png/testdata/pngsuite/basn4a16.sng | 41 + src/image/png/testdata/pngsuite/basn6a08.png | Bin 0 -> 184 bytes src/image/png/testdata/pngsuite/basn6a08.sng | 41 + src/image/png/testdata/pngsuite/basn6a16.png | Bin 0 -> 3435 bytes src/image/png/testdata/pngsuite/basn6a16.sng | 41 + src/image/png/writer.go | 530 + src/image/png/writer_test.go | 210 + src/image/testdata/video-001.5bpp.gif | Bin 0 -> 6214 bytes src/image/testdata/video-001.gif | Bin 0 -> 13106 bytes src/image/testdata/video-001.interlaced.gif | Bin 0 -> 14142 bytes src/image/testdata/video-001.jpeg | Bin 0 -> 21459 bytes src/image/testdata/video-001.png | Bin 0 -> 29228 bytes src/image/testdata/video-001.progressive.jpeg | Bin 0 -> 20732 bytes src/image/testdata/video-001.q50.420.jpeg | Bin 0 -> 3407 bytes .../testdata/video-001.q50.420.progressive.jpeg | Bin 0 -> 3279 bytes src/image/testdata/video-001.q50.422.jpeg | Bin 0 -> 3608 bytes .../testdata/video-001.q50.422.progressive.jpeg | Bin 0 -> 3506 bytes src/image/testdata/video-001.q50.440.jpeg | Bin 0 -> 3662 bytes .../testdata/video-001.q50.440.progressive.jpeg | Bin 0 -> 3529 bytes src/image/testdata/video-001.q50.444.jpeg | Bin 0 -> 4032 bytes .../testdata/video-001.q50.444.progressive.jpeg | Bin 0 -> 3935 bytes .../video-001.separate.dc.progression.jpeg | Bin 0 -> 14288 bytes ...eo-001.separate.dc.progression.progressive.jpeg | Bin 0 -> 14312 bytes src/image/testdata/video-005.gray.gif | Bin 0 -> 14505 bytes src/image/testdata/video-005.gray.jpeg | Bin 0 -> 5618 bytes src/image/testdata/video-005.gray.png | Bin 0 -> 14974 bytes src/image/testdata/video-005.gray.q50.2x2.jpeg | Bin 0 -> 2782 bytes .../video-005.gray.q50.2x2.progressive.jpeg | Bin 0 -> 2699 bytes src/image/testdata/video-005.gray.q50.jpeg | Bin 0 -> 2782 bytes .../testdata/video-005.gray.q50.progressive.jpeg | Bin 0 -> 2699 bytes src/image/ycbcr.go | 157 + src/image/ycbcr_test.go | 107 + src/index/suffixarray/qsufsort.go | 168 + src/index/suffixarray/suffixarray.go | 307 + src/index/suffixarray/suffixarray_test.go | 304 + src/internal/syscall/getrandom_linux.go | 56 + src/io/io.go | 502 + src/io/io_test.go | 341 + src/io/ioutil/ioutil.go | 165 + src/io/ioutil/ioutil_test.go | 95 + src/io/ioutil/tempfile.go | 95 + src/io/ioutil/tempfile_test.go | 53 + src/io/multi.go | 61 + src/io/multi_test.go | 115 + src/io/pipe.go | 193 + src/io/pipe_test.go | 302 + src/lib9/fmt/dofmt.c | 6 - src/lib9/tempdir_windows.c | 19 +- src/liblink/asm5.c | 618 +- src/liblink/asm6.c | 1672 +-- src/liblink/asm8.c | 1074 +- src/liblink/data.c | 2 + src/liblink/ld.c | 36 +- src/liblink/list5.c | 17 + src/liblink/list6.c | 2 +- src/liblink/list8.c | 2 +- src/liblink/obj5.c | 250 +- src/liblink/obj6.c | 263 +- src/liblink/obj8.c | 129 +- src/liblink/objfile.c | 78 +- src/liblink/pcln.c | 2 +- src/liblink/sym.c | 43 +- src/log/example_test.go | 21 + src/log/log.go | 322 + src/log/log_test.go | 119 + src/log/syslog/syslog.go | 319 + src/log/syslog/syslog_plan9.go | 8 + src/log/syslog/syslog_test.go | 358 + src/log/syslog/syslog_unix.go | 31 + src/log/syslog/syslog_windows.go | 8 + src/make.bash | 2 +- src/make.bat | 3 +- src/make.rc | 2 +- src/math/abs.go | 22 + src/math/abs_386.s | 12 + src/math/abs_amd64.s | 14 + src/math/abs_amd64p32.s | 5 + src/math/abs_arm.s | 13 + src/math/acosh.go | 60 + src/math/all_test.go | 2992 ++++ src/math/asin.go | 55 + src/math/asin_386.s | 30 + src/math/asin_amd64.s | 11 + src/math/asin_amd64p32.s | 5 + src/math/asin_arm.s | 11 + src/math/asinh.go | 69 + src/math/atan.go | 105 + src/math/atan2.go | 71 + src/math/atan2_386.s | 13 + src/math/atan2_amd64.s | 8 + src/math/atan2_amd64p32.s | 5 + src/math/atan2_arm.s | 8 + src/math/atan_386.s | 13 + src/math/atan_amd64.s | 8 + src/math/atan_amd64p32.s | 5 + src/math/atan_arm.s | 8 + src/math/atanh.go | 77 + src/math/big/arith.go | 240 + src/math/big/arith_386.s | 278 + src/math/big/arith_amd64.s | 401 + src/math/big/arith_amd64p32.s | 41 + src/math/big/arith_arm.s | 300 + src/math/big/arith_decl.go | 19 + src/math/big/arith_test.go | 456 + src/math/big/calibrate_test.go | 88 + src/math/big/example_test.go | 51 + src/math/big/gcd_test.go | 47 + src/math/big/hilbert_test.go | 160 + src/math/big/int.go | 1031 ++ src/math/big/int_test.go | 1625 +++ src/math/big/nat.go | 1508 ++ src/math/big/nat_test.go | 771 ++ src/math/big/rat.go | 716 + src/math/big/rat_test.go | 1160 ++ src/math/bits.go | 59 + src/math/cbrt.go | 76 + src/math/cmplx/abs.go | 12 + src/math/cmplx/asin.go | 170 + src/math/cmplx/cmath_test.go | 866 ++ src/math/cmplx/conj.go | 8 + src/math/cmplx/exp.go | 55 + src/math/cmplx/isinf.go | 21 + src/math/cmplx/isnan.go | 25 + src/math/cmplx/log.go | 64 + src/math/cmplx/phase.go | 11 + src/math/cmplx/polar.go | 12 + src/math/cmplx/pow.go | 78 + src/math/cmplx/rect.go | 13 + src/math/cmplx/sin.go | 132 + src/math/cmplx/sqrt.go | 104 + src/math/cmplx/tan.go | 184 + src/math/const.go | 51 + src/math/copysign.go | 12 + src/math/dim.go | 72 + src/math/dim_386.s | 14 + src/math/dim_amd64.s | 144 + src/math/dim_amd64p32.s | 5 + src/math/dim_arm.s | 14 + src/math/erf.go | 335 + src/math/exp.go | 191 + src/math/exp2_386.s | 40 + src/math/exp2_amd64.s | 8 + src/math/exp2_amd64p32.s | 5 + src/math/exp2_arm.s | 8 + src/math/exp_386.s | 41 + src/math/exp_amd64.s | 114 + src/math/exp_amd64p32.s | 5 + src/math/exp_arm.s | 8 + src/math/expm1.go | 237 + src/math/expm1_386.s | 57 + src/math/expm1_amd64.s | 8 + src/math/expm1_amd64p32.s | 5 + src/math/expm1_arm.s | 8 + src/math/export_test.go | 11 + src/math/floor.go | 56 + src/math/floor_386.s | 46 + src/math/floor_amd64.s | 76 + src/math/floor_amd64p32.s | 5 + src/math/floor_arm.s | 14 + src/math/frexp.go | 33 + src/math/frexp_386.s | 25 + src/math/frexp_amd64.s | 8 + src/math/frexp_amd64p32.s | 5 + src/math/frexp_arm.s | 8 + src/math/gamma.go | 202 + src/math/hypot.go | 43 + src/math/hypot_386.s | 59 + src/math/hypot_amd64.s | 52 + src/math/hypot_amd64p32.s | 5 + src/math/hypot_arm.s | 8 + src/math/j0.go | 429 + src/math/j1.go | 422 + src/math/jn.go | 306 + src/math/ldexp.go | 45 + src/math/ldexp_386.s | 14 + src/math/ldexp_amd64.s | 8 + src/math/ldexp_amd64p32.s | 5 + src/math/ldexp_arm.s | 8 + src/math/lgamma.go | 365 + src/math/log.go | 123 + src/math/log10.go | 22 + src/math/log10_386.s | 21 + src/math/log10_amd64.s | 11 + src/math/log10_amd64p32.s | 5 + src/math/log10_arm.s | 11 + src/math/log1p.go | 200 + src/math/log1p_386.s | 27 + src/math/log1p_amd64.s | 8 + src/math/log1p_amd64p32.s | 5 + src/math/log1p_arm.s | 8 + src/math/log_386.s | 13 + src/math/log_amd64.s | 111 + src/math/log_amd64p32.s | 5 + src/math/log_arm.s | 8 + src/math/logb.go | 50 + src/math/mod.go | 50 + src/math/mod_386.s | 17 + src/math/mod_amd64.s | 8 + src/math/mod_amd64p32.s | 5 + src/math/mod_arm.s | 8 + src/math/modf.go | 34 + src/math/modf_386.s | 21 + src/math/modf_amd64.s | 8 + src/math/modf_amd64p32.s | 5 + src/math/modf_arm.s | 8 + src/math/nextafter.go | 47 + src/math/pow.go | 137 + src/math/pow10.go | 40 + src/math/rand/example_test.go | 97 + src/math/rand/exp.go | 222 + src/math/rand/normal.go | 157 + src/math/rand/rand.go | 246 + src/math/rand/rand_test.go | 398 + src/math/rand/regress_test.go | 355 + src/math/rand/rng.go | 246 + src/math/rand/zipf.go | 75 + src/math/remainder.go | 85 + src/math/remainder_386.s | 17 + src/math/remainder_amd64.s | 8 + src/math/remainder_amd64p32.s | 5 + src/math/remainder_arm.s | 8 + src/math/signbit.go | 10 + src/math/sin.go | 224 + src/math/sin_386.s | 47 + src/math/sin_amd64.s | 11 + src/math/sin_amd64p32.s | 5 + src/math/sin_arm.s | 11 + src/math/sincos.go | 69 + src/math/sincos_386.s | 28 + src/math/sincos_amd64.s | 142 + src/math/sincos_amd64p32.s | 5 + src/math/sincos_arm.s | 8 + src/math/sinh.go | 77 + src/math/sqrt.go | 143 + src/math/sqrt_386.s | 12 + src/math/sqrt_amd64.s | 11 + src/math/sqrt_amd64p32.s | 5 + src/math/sqrt_arm.s | 12 + src/math/tan.go | 130 + src/math/tan_386.s | 28 + src/math/tan_amd64.s | 8 + src/math/tan_amd64p32.s | 5 + src/math/tan_arm.s | 8 + src/math/tanh.go | 97 + src/math/unsafe.go | 21 + src/mime/grammar.go | 32 + src/mime/mediatype.go | 358 + src/mime/mediatype_test.go | 306 + src/mime/multipart/example_test.go | 53 + src/mime/multipart/formdata.go | 157 + src/mime/multipart/formdata_test.go | 90 + src/mime/multipart/multipart.go | 348 + src/mime/multipart/multipart_test.go | 634 + src/mime/multipart/quotedprintable.go | 118 + src/mime/multipart/quotedprintable_test.go | 204 + src/mime/multipart/testdata/nested-mime | 29 + src/mime/multipart/writer.go | 184 + src/mime/multipart/writer_test.go | 128 + src/mime/testdata/test.types | 8 + src/mime/testdata/test.types.plan9 | 8 + src/mime/type.go | 121 + src/mime/type_plan9.go | 53 + src/mime/type_test.go | 54 + src/mime/type_unix.go | 60 + src/mime/type_windows.go | 63 + src/nacltest.bash | 31 +- src/net/cgo_android.go | 14 + src/net/cgo_bsd.go | 17 + src/net/cgo_linux.go | 22 + src/net/cgo_netbsd.go | 16 + src/net/cgo_openbsd.go | 16 + src/net/cgo_stub.go | 25 + src/net/cgo_unix.go | 164 + src/net/cgo_unix_test.go | 24 + src/net/conn_test.go | 124 + src/net/dial.go | 302 + src/net/dial_gen.go | 46 + src/net/dial_gen_test.go | 11 + src/net/dial_test.go | 548 + src/net/dialgoogle_test.go | 209 + src/net/dnsclient.go | 249 + src/net/dnsclient_test.go | 69 + src/net/dnsclient_unix.go | 423 + src/net/dnsclient_unix_test.go | 246 + src/net/dnsconfig_unix.go | 96 + src/net/dnsconfig_unix_test.go | 69 + src/net/dnsmsg.go | 887 ++ src/net/dnsmsg_test.go | 113 + src/net/dnsname_test.go | 83 + src/net/example_test.go | 36 + src/net/fd_mutex.go | 184 + src/net/fd_mutex_test.go | 195 + src/net/fd_plan9.go | 232 + src/net/fd_poll_nacl.go | 94 + src/net/fd_poll_runtime.go | 144 + src/net/fd_unix.go | 518 + src/net/fd_unix_test.go | 58 + src/net/fd_windows.go | 656 + src/net/file_plan9.go | 157 + src/net/file_stub.go | 38 + src/net/file_test.go | 205 + src/net/file_unix.go | 139 + src/net/file_windows.go | 37 + src/net/hosts.go | 86 + src/net/hosts_test.go | 81 + src/net/http/cgi/child.go | 206 + src/net/http/cgi/child_test.go | 131 + src/net/http/cgi/host.go | 377 + src/net/http/cgi/host_test.go | 461 + src/net/http/cgi/matryoshka_test.go | 228 + src/net/http/cgi/plan9_test.go | 18 + src/net/http/cgi/posix_test.go | 21 + src/net/http/cgi/testdata/test.cgi | 91 + src/net/http/client.go | 511 + src/net/http/client_test.go | 1075 ++ src/net/http/cookie.go | 363 + src/net/http/cookie_test.go | 412 + src/net/http/cookiejar/jar.go | 497 + src/net/http/cookiejar/jar_test.go | 1267 ++ src/net/http/cookiejar/punycode.go | 159 + src/net/http/cookiejar/punycode_test.go | 161 + src/net/http/doc.go | 80 + src/net/http/example_test.go | 88 + src/net/http/export_test.go | 108 + src/net/http/fcgi/child.go | 305 + src/net/http/fcgi/fcgi.go | 274 + src/net/http/fcgi/fcgi_test.go | 150 + src/net/http/filetransport.go | 123 + src/net/http/filetransport_test.go | 65 + src/net/http/fs.go | 556 + src/net/http/fs_test.go | 917 ++ src/net/http/header.go | 211 + src/net/http/header_test.go | 212 + src/net/http/httptest/example_test.go | 50 + src/net/http/httptest/recorder.go | 72 + src/net/http/httptest/recorder_test.go | 90 + src/net/http/httptest/server.go | 228 + src/net/http/httptest/server_test.go | 29 + src/net/http/httputil/dump.go | 284 + src/net/http/httputil/dump_test.go | 291 + src/net/http/httputil/httputil.go | 39 + src/net/http/httputil/persist.go | 429 + src/net/http/httputil/reverseproxy.go | 225 + src/net/http/httputil/reverseproxy_test.go | 213 + src/net/http/internal/chunked.go | 202 + src/net/http/internal/chunked_test.go | 156 + src/net/http/jar.go | 27 + src/net/http/lex.go | 96 + src/net/http/lex_test.go | 31 + src/net/http/main_test.go | 109 + src/net/http/npn_test.go | 118 + src/net/http/pprof/pprof.go | 209 + src/net/http/proxy_test.go | 81 + src/net/http/race.go | 11 + src/net/http/range_test.go | 79 + src/net/http/readrequest_test.go | 358 + src/net/http/request.go | 921 ++ src/net/http/request_test.go | 680 + src/net/http/requestwrite_test.go | 623 + src/net/http/response.go | 291 + src/net/http/response_test.go | 674 + src/net/http/responsewrite_test.go | 226 + src/net/http/serve_test.go | 3094 +++++ src/net/http/server.go | 2096 +++ src/net/http/sniff.go | 214 + src/net/http/sniff_test.go | 171 + src/net/http/status.go | 120 + src/net/http/testdata/file | 1 + src/net/http/testdata/index.html | 1 + src/net/http/testdata/style.css | 1 + src/net/http/transfer.go | 737 + src/net/http/transfer_test.go | 64 + src/net/http/transport.go | 1275 ++ src/net/http/transport_test.go | 2324 ++++ src/net/http/triv.go | 141 + src/net/interface.go | 126 + src/net/interface_bsd.go | 182 + src/net/interface_bsd_test.go | 52 + src/net/interface_darwin.go | 63 + src/net/interface_dragonfly.go | 12 + src/net/interface_freebsd.go | 63 + src/net/interface_linux.go | 271 + src/net/interface_linux_test.go | 102 + src/net/interface_netbsd.go | 12 + src/net/interface_openbsd.go | 12 + src/net/interface_stub.go | 27 + src/net/interface_test.go | 211 + src/net/interface_unix_test.go | 151 + src/net/interface_windows.go | 158 + src/net/ip.go | 689 + src/net/ip_test.go | 465 + src/net/ipraw_test.go | 294 + src/net/iprawsock.go | 54 + src/net/iprawsock_plan9.go | 82 + src/net/iprawsock_posix.go | 227 + src/net/ipsock.go | 318 + src/net/ipsock_plan9.go | 228 + src/net/ipsock_posix.go | 177 + src/net/ipsock_test.go | 193 + src/net/lookup.go | 142 + src/net/lookup_plan9.go | 297 + src/net/lookup_stub.go | 49 + src/net/lookup_test.go | 231 + src/net/lookup_unix.go | 168 + src/net/lookup_windows.go | 381 + src/net/lookup_windows_test.go | 243 + src/net/mac.go | 86 + src/net/mac_test.go | 66 + src/net/mail/message.go | 556 + src/net/mail/message_test.go | 314 + src/net/mockicmp_test.go | 116 + src/net/mockserver_test.go | 82 + src/net/multicast_test.go | 188 + src/net/net.go | 425 + src/net/net_test.go | 263 + src/net/net_windows_test.go | 148 + src/net/netgo_unix_test.go | 24 + src/net/packetconn_test.go | 186 + src/net/parse.go | 247 + src/net/parse_test.go | 53 + src/net/pipe.go | 67 + src/net/pipe_test.go | 56 + src/net/port.go | 24 + src/net/port_test.go | 59 + src/net/port_unix.go | 73 + src/net/protoconn_test.go | 386 + src/net/race.go | 31 + src/net/race0.go | 26 + src/net/rpc/client.go | 317 + src/net/rpc/client_test.go | 91 + src/net/rpc/debug.go | 93 + src/net/rpc/jsonrpc/all_test.go | 296 + src/net/rpc/jsonrpc/client.go | 123 + src/net/rpc/jsonrpc/server.go | 134 + src/net/rpc/server.go | 709 + src/net/rpc/server_test.go | 683 + src/net/sendfile_dragonfly.go | 103 + src/net/sendfile_freebsd.go | 103 + src/net/sendfile_linux.go | 76 + src/net/sendfile_stub.go | 13 + src/net/sendfile_windows.go | 55 + src/net/server_test.go | 461 + src/net/singleflight.go | 109 + src/net/smtp/auth.go | 107 + src/net/smtp/example_test.go | 61 + src/net/smtp/smtp.go | 357 + src/net/smtp/smtp_test.go | 694 + src/net/sock_bsd.go | 37 + src/net/sock_cloexec.go | 78 + src/net/sock_linux.go | 31 + src/net/sock_plan9.go | 10 + src/net/sock_posix.go | 216 + src/net/sock_stub.go | 15 + src/net/sock_windows.go | 24 + src/net/sockopt_bsd.go | 54 + src/net/sockopt_linux.go | 32 + src/net/sockopt_plan9.go | 13 + src/net/sockopt_posix.go | 141 + src/net/sockopt_solaris.go | 32 + src/net/sockopt_stub.go | 37 + src/net/sockopt_windows.go | 38 + src/net/sockoptip_bsd.go | 34 + src/net/sockoptip_linux.go | 31 + src/net/sockoptip_posix.go | 57 + src/net/sockoptip_stub.go | 39 + src/net/sockoptip_windows.go | 33 + src/net/sys_cloexec.go | 54 + src/net/tcp_test.go | 611 + src/net/tcpsock.go | 54 + src/net/tcpsock_plan9.go | 198 + src/net/tcpsock_posix.go | 299 + src/net/tcpsockopt_darwin.go | 29 + src/net/tcpsockopt_dragonfly.go | 26 + src/net/tcpsockopt_openbsd.go | 16 + src/net/tcpsockopt_plan9.go | 18 + src/net/tcpsockopt_posix.go | 20 + src/net/tcpsockopt_stub.go | 20 + src/net/tcpsockopt_unix.go | 27 + src/net/tcpsockopt_windows.go | 32 + src/net/testdata/domain-resolv.conf | 5 + src/net/testdata/empty-resolv.conf | 1 + src/net/testdata/hosts | 12 + src/net/testdata/hosts_singleline | 1 + src/net/testdata/igmp | 24 + src/net/testdata/igmp6 | 18 + src/net/testdata/resolv.conf | 8 + src/net/testdata/search-resolv.conf | 5 + src/net/textproto/header.go | 43 + src/net/textproto/pipeline.go | 117 + src/net/textproto/reader.go | 637 + src/net/textproto/reader_test.go | 337 + src/net/textproto/textproto.go | 154 + src/net/textproto/writer.go | 118 + src/net/textproto/writer_test.go | 35 + src/net/timeout_test.go | 747 + src/net/udp_test.go | 298 + src/net/udpsock.go | 54 + src/net/udpsock_plan9.go | 203 + src/net/udpsock_posix.go | 268 + src/net/unicast_posix_test.go | 469 + src/net/unix_test.go | 333 + src/net/unixsock.go | 43 + src/net/unixsock_plan9.go | 143 + src/net/unixsock_posix.go | 362 + src/net/url/example_test.go | 71 + src/net/url/url.go | 719 + src/net/url/url_test.go | 961 ++ src/net/z_last_test.go | 99 + src/os/dir_plan9.go | 73 + src/os/dir_unix.go | 58 + src/os/dir_windows.go | 14 + src/os/doc.go | 135 + src/os/env.go | 108 + src/os/env_test.go | 96 + src/os/env_unix_test.go | 30 + src/os/error.go | 65 + src/os/error_plan9.go | 54 + src/os/error_test.go | 132 + src/os/error_unix.go | 45 + src/os/error_windows.go | 45 + src/os/error_windows_test.go | 47 + src/os/exec.go | 70 + src/os/exec/example_test.go | 75 + src/os/exec/exec.go | 500 + src/os/exec/exec_test.go | 719 + src/os/exec/lp_plan9.go | 53 + src/os/exec/lp_test.go | 33 + src/os/exec/lp_unix.go | 60 + src/os/exec/lp_unix_test.go | 55 + src/os/exec/lp_windows.go | 123 + src/os/exec/lp_windows_test.go | 573 + src/os/exec_plan9.go | 137 + src/os/exec_posix.go | 134 + src/os/exec_unix.go | 81 + src/os/exec_windows.go | 118 + src/os/export_test.go | 10 + src/os/file.go | 266 + src/os/file_plan9.go | 469 + src/os/file_posix.go | 149 + src/os/file_unix.go | 339 + src/os/file_windows.go | 596 + src/os/getwd.go | 123 + src/os/getwd_darwin.go | 15 + src/os/os_test.go | 1484 ++ src/os/os_unix_test.go | 76 + src/os/os_windows_test.go | 81 + src/os/path.go | 131 + src/os/path_plan9.go | 15 + src/os/path_test.go | 220 + src/os/path_unix.go | 17 + src/os/path_windows.go | 16 + src/os/pipe_bsd.go | 28 + src/os/pipe_linux.go | 33 + src/os/proc.go | 49 + src/os/signal/example_test.go | 23 + src/os/signal/sig.s | 23 + src/os/signal/signal.go | 131 + src/os/signal/signal_stub.go | 17 + src/os/signal/signal_test.go | 208 + src/os/signal/signal_unix.go | 53 + src/os/signal/signal_windows_test.go | 103 + src/os/stat_darwin.go | 61 + src/os/stat_dragonfly.go | 61 + src/os/stat_freebsd.go | 61 + src/os/stat_linux.go | 61 + src/os/stat_nacl.go | 62 + src/os/stat_netbsd.go | 61 + src/os/stat_openbsd.go | 61 + src/os/stat_plan9.go | 110 + src/os/stat_solaris.go | 61 + src/os/stat_windows.go | 170 + src/os/str.go | 22 + src/os/sys_bsd.go | 20 + src/os/sys_darwin.go | 31 + src/os/sys_freebsd.go | 23 + src/os/sys_linux.go | 26 + src/os/sys_nacl.go | 9 + src/os/sys_plan9.go | 26 + src/os/sys_solaris.go | 11 + src/os/sys_unix.go | 11 + src/os/sys_windows.go | 15 + src/os/types.go | 118 + src/os/types_notwin.go | 25 + src/os/types_windows.go | 107 + src/os/user/lookup.go | 22 + src/os/user/lookup_plan9.go | 46 + src/os/user/lookup_stubs.go | 28 + src/os/user/lookup_unix.go | 112 + src/os/user/lookup_windows.go | 149 + src/os/user/user.go | 43 + src/os/user/user_test.go | 89 + src/path/example_test.go | 63 + src/path/filepath/example_unix_test.go | 39 + src/path/filepath/export_test.go | 7 + src/path/filepath/match.go | 309 + src/path/filepath/match_test.go | 211 + src/path/filepath/path.go | 464 + src/path/filepath/path_plan9.go | 34 + src/path/filepath/path_test.go | 1028 ++ src/path/filepath/path_unix.go | 36 + src/path/filepath/path_windows.go | 110 + src/path/filepath/path_windows_test.go | 113 + src/path/filepath/symlink.go | 72 + src/path/filepath/symlink_unix.go | 7 + src/path/filepath/symlink_windows.go | 74 + src/path/match.go | 209 + src/path/match_test.go | 79 + src/path/path.go | 210 + src/path/path_test.go | 241 + src/pkg/archive/tar/common.go | 305 - src/pkg/archive/tar/example_test.go | 79 - src/pkg/archive/tar/reader.go | 817 -- src/pkg/archive/tar/reader_test.go | 743 - src/pkg/archive/tar/stat_atim.go | 20 - src/pkg/archive/tar/stat_atimespec.go | 20 - src/pkg/archive/tar/stat_unix.go | 32 - src/pkg/archive/tar/tar_test.go | 284 - src/pkg/archive/tar/testdata/gnu.tar | Bin 3072 -> 0 bytes src/pkg/archive/tar/testdata/nil-uid.tar | Bin 1024 -> 0 bytes src/pkg/archive/tar/testdata/pax.tar | Bin 10240 -> 0 bytes src/pkg/archive/tar/testdata/small.txt | 1 - src/pkg/archive/tar/testdata/small2.txt | 1 - src/pkg/archive/tar/testdata/sparse-formats.tar | Bin 17920 -> 0 bytes src/pkg/archive/tar/testdata/star.tar | Bin 3072 -> 0 bytes src/pkg/archive/tar/testdata/ustar.tar | Bin 2048 -> 0 bytes src/pkg/archive/tar/testdata/v7.tar | Bin 3584 -> 0 bytes src/pkg/archive/tar/testdata/writer-big-long.tar | Bin 4096 -> 0 bytes src/pkg/archive/tar/testdata/writer-big.tar | Bin 4096 -> 0 bytes src/pkg/archive/tar/testdata/writer.tar | Bin 3584 -> 0 bytes src/pkg/archive/tar/testdata/xattrs.tar | Bin 5120 -> 0 bytes src/pkg/archive/tar/writer.go | 383 - src/pkg/archive/tar/writer_test.go | 456 - src/pkg/archive/zip/example_test.go | 75 - src/pkg/archive/zip/reader.go | 448 - src/pkg/archive/zip/reader_test.go | 510 - src/pkg/archive/zip/register.go | 110 - src/pkg/archive/zip/struct.go | 313 - .../archive/zip/testdata/crc32-not-streamed.zip | Bin 314 -> 0 bytes src/pkg/archive/zip/testdata/dd.zip | Bin 154 -> 0 bytes .../archive/zip/testdata/go-no-datadesc-sig.zip | Bin 330 -> 0 bytes .../archive/zip/testdata/go-with-datadesc-sig.zip | Bin 242 -> 0 bytes src/pkg/archive/zip/testdata/gophercolor16x16.png | Bin 785 -> 0 bytes src/pkg/archive/zip/testdata/readme.notzip | Bin 1905 -> 0 bytes src/pkg/archive/zip/testdata/readme.zip | Bin 1885 -> 0 bytes src/pkg/archive/zip/testdata/symlink.zip | Bin 173 -> 0 bytes .../archive/zip/testdata/test-trailing-junk.zip | Bin 1184 -> 0 bytes src/pkg/archive/zip/testdata/test.zip | Bin 1170 -> 0 bytes src/pkg/archive/zip/testdata/unix.zip | Bin 620 -> 0 bytes src/pkg/archive/zip/testdata/winxp.zip | Bin 412 -> 0 bytes src/pkg/archive/zip/testdata/zip64-2.zip | Bin 266 -> 0 bytes src/pkg/archive/zip/testdata/zip64.zip | Bin 242 -> 0 bytes src/pkg/archive/zip/writer.go | 351 - src/pkg/archive/zip/writer_test.go | 145 - src/pkg/archive/zip/zip_test.go | 395 - src/pkg/bufio/bufio.go | 698 - src/pkg/bufio/bufio_test.go | 1417 -- src/pkg/bufio/example_test.go | 82 - src/pkg/bufio/export_test.go | 27 - src/pkg/bufio/scan.go | 346 - src/pkg/bufio/scan_test.go | 406 - src/pkg/builtin/builtin.go | 256 - src/pkg/bytes/buffer.go | 412 - src/pkg/bytes/buffer_test.go | 527 - src/pkg/bytes/bytes.go | 697 - src/pkg/bytes/bytes.s | 5 - src/pkg/bytes/bytes_decl.go | 24 - src/pkg/bytes/bytes_test.go | 1234 -- src/pkg/bytes/compare_test.go | 208 - src/pkg/bytes/equal_test.go | 47 - src/pkg/bytes/example_test.go | 85 - src/pkg/bytes/export_test.go | 13 - src/pkg/bytes/reader.go | 144 - src/pkg/bytes/reader_test.go | 246 - src/pkg/compress/bzip2/bit_reader.go | 90 - src/pkg/compress/bzip2/bzip2.go | 484 - src/pkg/compress/bzip2/bzip2_test.go | 363 - src/pkg/compress/bzip2/huffman.go | 251 - src/pkg/compress/bzip2/move_to_front.go | 98 - .../bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 | Bin 124744 -> 0 bytes src/pkg/compress/bzip2/testdata/e.txt.bz2 | Bin 43149 -> 0 bytes src/pkg/compress/flate/copy.go | 32 - src/pkg/compress/flate/copy_test.go | 54 - src/pkg/compress/flate/deflate.go | 571 - src/pkg/compress/flate/deflate_test.go | 490 - src/pkg/compress/flate/fixedhuff.go | 78 - src/pkg/compress/flate/flate_test.go | 62 - src/pkg/compress/flate/gen.go | 165 - src/pkg/compress/flate/huffman_bit_writer.go | 517 - src/pkg/compress/flate/huffman_code.go | 323 - src/pkg/compress/flate/inflate.go | 708 - src/pkg/compress/flate/reader_test.go | 96 - src/pkg/compress/flate/reverse_bits.go | 48 - src/pkg/compress/flate/token.go | 102 - src/pkg/compress/flate/writer_test.go | 60 - src/pkg/compress/gzip/gunzip.go | 255 - src/pkg/compress/gzip/gunzip_test.go | 369 - src/pkg/compress/gzip/gzip.go | 272 - src/pkg/compress/gzip/gzip_test.go | 231 - src/pkg/compress/gzip/testdata/issue6550.gz | Bin 65536 -> 0 bytes src/pkg/compress/lzw/reader.go | 253 - src/pkg/compress/lzw/reader_test.go | 152 - src/pkg/compress/lzw/writer.go | 262 - src/pkg/compress/lzw/writer_test.go | 144 - .../compress/testdata/Mark.Twain-Tom.Sawyer.txt | 8858 ------------ src/pkg/compress/testdata/e.txt | 1 - src/pkg/compress/testdata/pi.txt | 1 - src/pkg/compress/zlib/example_test.go | 37 - src/pkg/compress/zlib/reader.go | 132 - src/pkg/compress/zlib/reader_test.go | 127 - src/pkg/compress/zlib/writer.go | 198 - src/pkg/compress/zlib/writer_test.go | 205 - src/pkg/container/heap/example_intheap_test.go | 47 - src/pkg/container/heap/example_pq_test.go | 97 - src/pkg/container/heap/heap.go | 117 - src/pkg/container/heap/heap_test.go | 213 - src/pkg/container/list/example_test.go | 30 - src/pkg/container/list/list.go | 216 - src/pkg/container/list/list_test.go | 343 - src/pkg/container/ring/ring.go | 141 - src/pkg/container/ring/ring_test.go | 228 - src/pkg/crypto/aes/aes_test.go | 421 - src/pkg/crypto/aes/asm_amd64.s | 289 - src/pkg/crypto/aes/block.go | 176 - src/pkg/crypto/aes/cipher.go | 66 - src/pkg/crypto/aes/cipher_asm.go | 48 - src/pkg/crypto/aes/cipher_generic.go | 19 - src/pkg/crypto/aes/const.go | 358 - src/pkg/crypto/cipher/benchmark_test.go | 139 - src/pkg/crypto/cipher/cbc.go | 133 - src/pkg/crypto/cipher/cbc_aes_test.go | 104 - src/pkg/crypto/cipher/cfb.go | 72 - src/pkg/crypto/cipher/cfb_test.go | 38 - src/pkg/crypto/cipher/cipher.go | 53 - src/pkg/crypto/cipher/cipher_test.go | 36 - src/pkg/crypto/cipher/common_test.go | 28 - src/pkg/crypto/cipher/ctr.go | 76 - src/pkg/crypto/cipher/ctr_aes_test.go | 102 - src/pkg/crypto/cipher/example_test.go | 283 - src/pkg/crypto/cipher/gcm.go | 343 - src/pkg/crypto/cipher/gcm_test.go | 159 - src/pkg/crypto/cipher/io.go | 55 - src/pkg/crypto/cipher/ofb.go | 66 - src/pkg/crypto/cipher/ofb_test.go | 102 - src/pkg/crypto/cipher/xor.go | 84 - src/pkg/crypto/cipher/xor_test.go | 28 - src/pkg/crypto/crypto.go | 85 - src/pkg/crypto/des/block.go | 223 - src/pkg/crypto/des/cipher.go | 73 - src/pkg/crypto/des/const.go | 139 - src/pkg/crypto/des/des_test.go | 1566 --- src/pkg/crypto/des/example_test.go | 25 - src/pkg/crypto/dsa/dsa.go | 278 - src/pkg/crypto/dsa/dsa_test.go | 85 - src/pkg/crypto/ecdsa/ecdsa.go | 165 - src/pkg/crypto/ecdsa/ecdsa_test.go | 191 - src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 | Bin 95485 -> 0 bytes src/pkg/crypto/elliptic/elliptic.go | 373 - src/pkg/crypto/elliptic/elliptic_test.go | 458 - src/pkg/crypto/elliptic/p224.go | 765 - src/pkg/crypto/elliptic/p224_test.go | 47 - src/pkg/crypto/elliptic/p256.go | 1186 -- src/pkg/crypto/hmac/hmac.go | 102 - src/pkg/crypto/hmac/hmac_test.go | 570 - src/pkg/crypto/md5/example_test.go | 25 - src/pkg/crypto/md5/gen.go | 316 - src/pkg/crypto/md5/md5.go | 134 - src/pkg/crypto/md5/md5_test.go | 163 - src/pkg/crypto/md5/md5block.go | 265 - src/pkg/crypto/md5/md5block_386.s | 182 - src/pkg/crypto/md5/md5block_amd64.s | 179 - src/pkg/crypto/md5/md5block_amd64p32.s | 184 - src/pkg/crypto/md5/md5block_arm.s | 299 - src/pkg/crypto/md5/md5block_decl.go | 11 - src/pkg/crypto/md5/md5block_generic.go | 9 - src/pkg/crypto/rand/example_test.go | 28 - src/pkg/crypto/rand/rand.go | 21 - src/pkg/crypto/rand/rand_test.go | 43 - src/pkg/crypto/rand/rand_unix.go | 138 - src/pkg/crypto/rand/rand_windows.go | 47 - src/pkg/crypto/rand/util.go | 136 - src/pkg/crypto/rand/util_test.go | 65 - src/pkg/crypto/rc4/rc4.go | 69 - src/pkg/crypto/rc4/rc4_386.s | 53 - src/pkg/crypto/rc4/rc4_amd64.s | 179 - src/pkg/crypto/rc4/rc4_amd64p32.s | 192 - src/pkg/crypto/rc4/rc4_arm.s | 60 - src/pkg/crypto/rc4/rc4_asm.go | 18 - src/pkg/crypto/rc4/rc4_ref.go | 13 - src/pkg/crypto/rc4/rc4_test.go | 173 - src/pkg/crypto/rsa/pkcs1v15.go | 292 - src/pkg/crypto/rsa/pkcs1v15_test.go | 271 - src/pkg/crypto/rsa/pss.go | 282 - src/pkg/crypto/rsa/pss_test.go | 249 - src/pkg/crypto/rsa/rsa.go | 538 - src/pkg/crypto/rsa/rsa_test.go | 392 - src/pkg/crypto/rsa/testdata/pss-vect.txt.bz2 | Bin 28526 -> 0 bytes src/pkg/crypto/sha1/example_test.go | 25 - src/pkg/crypto/sha1/sha1.go | 130 - src/pkg/crypto/sha1/sha1_test.go | 129 - src/pkg/crypto/sha1/sha1block.go | 90 - src/pkg/crypto/sha1/sha1block_386.s | 233 - src/pkg/crypto/sha1/sha1block_amd64.s | 216 - src/pkg/crypto/sha1/sha1block_amd64p32.s | 216 - src/pkg/crypto/sha1/sha1block_arm.s | 217 - src/pkg/crypto/sha1/sha1block_decl.go | 11 - src/pkg/crypto/sha1/sha1block_generic.go | 9 - src/pkg/crypto/sha256/sha256.go | 193 - src/pkg/crypto/sha256/sha256_test.go | 176 - src/pkg/crypto/sha256/sha256block.go | 128 - src/pkg/crypto/sha256/sha256block_386.s | 283 - src/pkg/crypto/sha256/sha256block_amd64.s | 256 - src/pkg/crypto/sha256/sha256block_decl.go | 11 - src/pkg/crypto/sha512/sha512.go | 198 - src/pkg/crypto/sha512/sha512_test.go | 176 - src/pkg/crypto/sha512/sha512block.go | 144 - src/pkg/crypto/sha512/sha512block_amd64.s | 273 - src/pkg/crypto/sha512/sha512block_decl.go | 11 - src/pkg/crypto/subtle/constant_time.go | 74 - src/pkg/crypto/subtle/constant_time_test.go | 125 - src/pkg/crypto/tls/alert.go | 77 - src/pkg/crypto/tls/cipher_suites.go | 270 - src/pkg/crypto/tls/common.go | 568 - src/pkg/crypto/tls/conn.go | 1024 -- src/pkg/crypto/tls/conn_test.go | 106 - src/pkg/crypto/tls/example_test.go | 57 - src/pkg/crypto/tls/generate_cert.go | 115 - src/pkg/crypto/tls/handshake_client.go | 601 - src/pkg/crypto/tls/handshake_client_test.go | 439 - src/pkg/crypto/tls/handshake_messages.go | 1344 -- src/pkg/crypto/tls/handshake_messages_test.go | 246 - src/pkg/crypto/tls/handshake_server.go | 654 - src/pkg/crypto/tls/handshake_server_test.go | 726 - src/pkg/crypto/tls/handshake_test.go | 167 - src/pkg/crypto/tls/key_agreement.go | 407 - src/pkg/crypto/tls/prf.go | 291 - src/pkg/crypto/tls/prf_test.go | 126 - .../testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA | 129 - .../testdata/Client-TLSv10-ClientCert-ECDSA-RSA | 125 - .../testdata/Client-TLSv10-ClientCert-RSA-ECDSA | 128 - .../tls/testdata/Client-TLSv10-ClientCert-RSA-RSA | 124 - .../tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES | 87 - .../tls/testdata/Client-TLSv10-ECDHE-RSA-AES | 97 - src/pkg/crypto/tls/testdata/Client-TLSv10-RSA-RC4 | 83 - .../tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES | 89 - .../tls/testdata/Client-TLSv11-ECDHE-RSA-AES | 99 - src/pkg/crypto/tls/testdata/Client-TLSv11-RSA-RC4 | 83 - .../testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA | 134 - .../testdata/Client-TLSv12-ClientCert-ECDSA-RSA | 127 - .../testdata/Client-TLSv12-ClientCert-RSA-ECDSA | 133 - .../tls/testdata/Client-TLSv12-ClientCert-RSA-RSA | 126 - .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES | 89 - .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM | 84 - .../tls/testdata/Client-TLSv12-ECDHE-RSA-AES | 99 - src/pkg/crypto/tls/testdata/Client-TLSv12-RSA-RC4 | 83 - src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-3DES | 83 - src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-AES | 84 - src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-RC4 | 79 - .../tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES | 84 - src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-3DES | 79 - src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-AES | 82 - src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-RC4 | 76 - src/pkg/crypto/tls/testdata/Server-TLSv11-RSA-RC4 | 76 - .../Server-TLSv12-CipherSuiteCertPreferenceECDSA | 91 - .../Server-TLSv12-CipherSuiteCertPreferenceRSA | 101 - .../Server-TLSv12-ClientAuthRequestedAndECDSAGiven | 122 - .../Server-TLSv12-ClientAuthRequestedAndGiven | 121 - .../Server-TLSv12-ClientAuthRequestedNotGiven | 81 - .../tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES | 89 - .../crypto/tls/testdata/Server-TLSv12-IssueTicket | 87 - .../testdata/Server-TLSv12-IssueTicketPreDisable | 87 - src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-3DES | 83 - src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES | 87 - .../crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM | 93 - src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-RC4 | 79 - src/pkg/crypto/tls/testdata/Server-TLSv12-Resume | 36 - .../tls/testdata/Server-TLSv12-ResumeDisabled | 87 - src/pkg/crypto/tls/testdata/Server-TLSv12-SNI | 76 - src/pkg/crypto/tls/ticket.go | 183 - src/pkg/crypto/tls/tls.go | 275 - src/pkg/crypto/tls/tls_test.go | 237 - src/pkg/crypto/x509/cert_pool.go | 116 - src/pkg/crypto/x509/example_test.go | 91 - src/pkg/crypto/x509/pem_decrypt.go | 233 - src/pkg/crypto/x509/pem_decrypt_test.go | 223 - src/pkg/crypto/x509/pkcs1.go | 122 - src/pkg/crypto/x509/pkcs8.go | 54 - src/pkg/crypto/x509/pkcs8_test.go | 28 - src/pkg/crypto/x509/pkix/pkix.go | 178 - src/pkg/crypto/x509/root.go | 17 - src/pkg/crypto/x509/root_cgo_darwin.go | 79 - src/pkg/crypto/x509/root_darwin.go | 23 - src/pkg/crypto/x509/root_darwin_test.go | 50 - src/pkg/crypto/x509/root_nocgo_darwin.go | 11 - src/pkg/crypto/x509/root_plan9.go | 33 - src/pkg/crypto/x509/root_unix.go | 37 - src/pkg/crypto/x509/root_windows.go | 229 - src/pkg/crypto/x509/sec1.go | 83 - src/pkg/crypto/x509/sec1_test.go | 30 - src/pkg/crypto/x509/verify.go | 474 - src/pkg/crypto/x509/verify_test.go | 1123 -- src/pkg/crypto/x509/x509.go | 1903 --- src/pkg/crypto/x509/x509_test.go | 952 -- src/pkg/crypto/x509/x509_test_import.go | 53 - src/pkg/database/sql/convert.go | 299 - src/pkg/database/sql/convert_test.go | 337 - src/pkg/database/sql/doc.txt | 46 - src/pkg/database/sql/driver/driver.go | 211 - src/pkg/database/sql/driver/types.go | 252 - src/pkg/database/sql/driver/types_test.go | 65 - src/pkg/database/sql/example_test.go | 46 - src/pkg/database/sql/fakedb_test.go | 805 -- src/pkg/database/sql/sql.go | 1720 --- src/pkg/database/sql/sql_test.go | 1949 --- src/pkg/debug/dwarf/buf.go | 181 - src/pkg/debug/dwarf/const.go | 454 - src/pkg/debug/dwarf/entry.go | 401 - src/pkg/debug/dwarf/open.go | 87 - src/pkg/debug/dwarf/testdata/typedef.c | 85 - src/pkg/debug/dwarf/testdata/typedef.elf | Bin 12448 -> 0 bytes src/pkg/debug/dwarf/testdata/typedef.elf4 | Bin 9496 -> 0 bytes src/pkg/debug/dwarf/testdata/typedef.macho | Bin 5024 -> 0 bytes src/pkg/debug/dwarf/type.go | 659 - src/pkg/debug/dwarf/type_test.go | 122 - src/pkg/debug/dwarf/typeunit.go | 166 - src/pkg/debug/dwarf/unit.go | 90 - src/pkg/debug/elf/elf.go | 1521 -- src/pkg/debug/elf/elf_test.go | 49 - src/pkg/debug/elf/file.go | 881 -- src/pkg/debug/elf/file_test.go | 339 - src/pkg/debug/elf/testdata/gcc-386-freebsd-exec | Bin 5742 -> 0 bytes src/pkg/debug/elf/testdata/gcc-amd64-linux-exec | Bin 8844 -> 0 bytes .../testdata/gcc-amd64-openbsd-debug-with-rela.obj | Bin 6544 -> 0 bytes .../elf/testdata/go-relocation-test-clang-x86.obj | Bin 1900 -> 0 bytes .../testdata/go-relocation-test-gcc424-x86-64.obj | Bin 3088 -> 0 bytes .../testdata/go-relocation-test-gcc441-x86-64.obj | Bin 2936 -> 0 bytes .../elf/testdata/go-relocation-test-gcc441-x86.obj | Bin 1884 -> 0 bytes src/pkg/debug/elf/testdata/hello-world-core.gz | Bin 12678 -> 0 bytes src/pkg/debug/elf/testdata/hello.c | 7 - src/pkg/debug/gosym/pclinetest.asm | 58 - src/pkg/debug/gosym/pclinetest.h | 9 - src/pkg/debug/gosym/pclntab.go | 453 - src/pkg/debug/gosym/pclntab_test.go | 274 - src/pkg/debug/gosym/symtab.go | 710 - src/pkg/debug/macho/fat.go | 146 - src/pkg/debug/macho/file.go | 524 - src/pkg/debug/macho/file_test.go | 210 - src/pkg/debug/macho/macho.go | 316 - .../macho/testdata/fat-gcc-386-amd64-darwin-exec | Bin 28992 -> 0 bytes src/pkg/debug/macho/testdata/gcc-386-darwin-exec | Bin 12588 -> 0 bytes src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec | Bin 8512 -> 0 bytes .../macho/testdata/gcc-amd64-darwin-exec-debug | Bin 4540 -> 0 bytes src/pkg/debug/macho/testdata/hello.c | 8 - src/pkg/debug/pe/file.go | 390 - src/pkg/debug/pe/file_test.go | 236 - src/pkg/debug/pe/pe.go | 134 - src/pkg/debug/pe/testdata/gcc-386-mingw-exec | Bin 29941 -> 0 bytes src/pkg/debug/pe/testdata/gcc-386-mingw-obj | Bin 2372 -> 0 bytes src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec | Bin 37376 -> 0 bytes src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj | Bin 736 -> 0 bytes src/pkg/debug/pe/testdata/hello.c | 8 - src/pkg/debug/plan9obj/file.go | 325 - src/pkg/debug/plan9obj/file_test.go | 81 - src/pkg/debug/plan9obj/plan9obj.go | 36 - src/pkg/debug/plan9obj/testdata/386-plan9-exec | Bin 37232 -> 0 bytes src/pkg/debug/plan9obj/testdata/amd64-plan9-exec | Bin 34279 -> 0 bytes src/pkg/debug/plan9obj/testdata/hello.c | 8 - src/pkg/encoding/ascii85/ascii85.go | 311 - src/pkg/encoding/ascii85/ascii85_test.go | 210 - src/pkg/encoding/asn1/asn1.go | 908 -- src/pkg/encoding/asn1/asn1_test.go | 814 -- src/pkg/encoding/asn1/common.go | 163 - src/pkg/encoding/asn1/marshal.go | 632 - src/pkg/encoding/asn1/marshal_test.go | 157 - src/pkg/encoding/base32/base32.go | 428 - src/pkg/encoding/base32/base32_test.go | 286 - src/pkg/encoding/base32/example_test.go | 45 - src/pkg/encoding/base64/base64.go | 393 - src/pkg/encoding/base64/base64_test.go | 344 - src/pkg/encoding/base64/example_test.go | 45 - src/pkg/encoding/binary/binary.go | 639 - src/pkg/encoding/binary/binary_test.go | 397 - src/pkg/encoding/binary/example_test.go | 52 - src/pkg/encoding/binary/varint.go | 133 - src/pkg/encoding/binary/varint_test.go | 168 - src/pkg/encoding/csv/reader.go | 337 - src/pkg/encoding/csv/reader_test.go | 284 - src/pkg/encoding/csv/writer.go | 127 - src/pkg/encoding/csv/writer_test.go | 74 - src/pkg/encoding/encoding.go | 48 - src/pkg/encoding/gob/codec_test.go | 1506 -- src/pkg/encoding/gob/debug.go | 705 - src/pkg/encoding/gob/decode.go | 1317 -- src/pkg/encoding/gob/decoder.go | 237 - src/pkg/encoding/gob/doc.go | 386 - src/pkg/encoding/gob/dump.go | 29 - src/pkg/encoding/gob/encode.go | 760 - src/pkg/encoding/gob/encoder.go | 253 - src/pkg/encoding/gob/encoder_test.go | 862 -- src/pkg/encoding/gob/error.go | 43 - src/pkg/encoding/gob/example_encdec_test.go | 61 - src/pkg/encoding/gob/example_interface_test.go | 81 - src/pkg/encoding/gob/example_test.go | 60 - src/pkg/encoding/gob/gobencdec_test.go | 797 -- src/pkg/encoding/gob/timing_test.go | 109 - src/pkg/encoding/gob/type.go | 893 -- src/pkg/encoding/gob/type_test.go | 222 - src/pkg/encoding/hex/hex.go | 216 - src/pkg/encoding/hex/hex_test.go | 153 - src/pkg/encoding/json/bench_test.go | 189 - src/pkg/encoding/json/decode.go | 1050 -- src/pkg/encoding/json/decode_test.go | 1356 -- src/pkg/encoding/json/encode.go | 1175 -- src/pkg/encoding/json/encode_test.go | 454 - src/pkg/encoding/json/example_test.go | 161 - src/pkg/encoding/json/fold.go | 143 - src/pkg/encoding/json/fold_test.go | 116 - src/pkg/encoding/json/indent.go | 137 - src/pkg/encoding/json/scanner.go | 623 - src/pkg/encoding/json/scanner_test.go | 315 - src/pkg/encoding/json/stream.go | 201 - src/pkg/encoding/json/stream_test.go | 206 - src/pkg/encoding/json/tagkey_test.go | 115 - src/pkg/encoding/json/tags.go | 44 - src/pkg/encoding/json/tags_test.go | 28 - src/pkg/encoding/json/testdata/code.json.gz | Bin 120432 -> 0 bytes src/pkg/encoding/pem/pem.go | 277 - src/pkg/encoding/pem/pem_test.go | 404 - src/pkg/encoding/xml/atom_test.go | 56 - src/pkg/encoding/xml/example_test.go | 151 - src/pkg/encoding/xml/marshal.go | 938 -- src/pkg/encoding/xml/marshal_test.go | 1266 -- src/pkg/encoding/xml/read.go | 692 - src/pkg/encoding/xml/read_test.go | 714 - src/pkg/encoding/xml/typeinfo.go | 363 - src/pkg/encoding/xml/xml.go | 1935 --- src/pkg/encoding/xml/xml_test.go | 726 - src/pkg/errors/errors.go | 20 - src/pkg/errors/errors_test.go | 53 - src/pkg/errors/example_test.go | 34 - src/pkg/expvar/expvar.go | 336 - src/pkg/expvar/expvar_test.go | 167 - src/pkg/flag/example_test.go | 83 - src/pkg/flag/export_test.go | 17 - src/pkg/flag/flag.go | 849 -- src/pkg/flag/flag_test.go | 369 - src/pkg/fmt/doc.go | 272 - src/pkg/fmt/export_test.go | 7 - src/pkg/fmt/fmt_test.go | 1147 -- src/pkg/fmt/format.go | 492 - src/pkg/fmt/print.go | 1199 -- src/pkg/fmt/scan.go | 1168 -- src/pkg/fmt/scan_test.go | 960 -- src/pkg/fmt/stringer_test.go | 61 - src/pkg/go/ast/ast.go | 995 -- src/pkg/go/ast/ast_test.go | 50 - src/pkg/go/ast/commentmap.go | 332 - src/pkg/go/ast/commentmap_test.go | 143 - src/pkg/go/ast/example_test.go | 210 - src/pkg/go/ast/filter.go | 466 - src/pkg/go/ast/filter_test.go | 86 - src/pkg/go/ast/import.go | 196 - src/pkg/go/ast/print.go | 251 - src/pkg/go/ast/print_test.go | 97 - src/pkg/go/ast/resolve.go | 174 - src/pkg/go/ast/scope.go | 162 - src/pkg/go/ast/walk.go | 384 - src/pkg/go/build/build.go | 1219 -- src/pkg/go/build/build_test.go | 186 - src/pkg/go/build/deps_test.go | 442 - src/pkg/go/build/doc.go | 137 - src/pkg/go/build/read.go | 238 - src/pkg/go/build/read_test.go | 226 - src/pkg/go/build/syslist.go | 8 - src/pkg/go/build/syslist_test.go | 62 - src/pkg/go/build/testdata/other/file/file.go | 5 - src/pkg/go/build/testdata/other/main.go | 11 - src/pkg/go/doc/Makefile | 7 - src/pkg/go/doc/comment.go | 480 - src/pkg/go/doc/comment_test.go | 207 - src/pkg/go/doc/doc.go | 111 - src/pkg/go/doc/doc_test.go | 146 - src/pkg/go/doc/example.go | 355 - src/pkg/go/doc/example_test.go | 191 - src/pkg/go/doc/exports.go | 199 - src/pkg/go/doc/filter.go | 105 - src/pkg/go/doc/headscan.go | 113 - src/pkg/go/doc/reader.go | 853 -- src/pkg/go/doc/synopsis.go | 82 - src/pkg/go/doc/synopsis_test.go | 51 - src/pkg/go/doc/testdata/a.0.golden | 52 - src/pkg/go/doc/testdata/a.1.golden | 52 - src/pkg/go/doc/testdata/a.2.golden | 52 - src/pkg/go/doc/testdata/a0.go | 40 - src/pkg/go/doc/testdata/a1.go | 12 - src/pkg/go/doc/testdata/b.0.golden | 71 - src/pkg/go/doc/testdata/b.1.golden | 83 - src/pkg/go/doc/testdata/b.2.golden | 71 - src/pkg/go/doc/testdata/b.go | 58 - src/pkg/go/doc/testdata/benchmark.go | 293 - src/pkg/go/doc/testdata/bugpara.0.golden | 20 - src/pkg/go/doc/testdata/bugpara.1.golden | 20 - src/pkg/go/doc/testdata/bugpara.2.golden | 20 - src/pkg/go/doc/testdata/bugpara.go | 5 - src/pkg/go/doc/testdata/c.0.golden | 48 - src/pkg/go/doc/testdata/c.1.golden | 48 - src/pkg/go/doc/testdata/c.2.golden | 48 - src/pkg/go/doc/testdata/c.go | 62 - src/pkg/go/doc/testdata/d.0.golden | 104 - src/pkg/go/doc/testdata/d.1.golden | 104 - src/pkg/go/doc/testdata/d.2.golden | 104 - src/pkg/go/doc/testdata/d1.go | 57 - src/pkg/go/doc/testdata/d2.go | 45 - src/pkg/go/doc/testdata/e.0.golden | 109 - src/pkg/go/doc/testdata/e.1.golden | 144 - src/pkg/go/doc/testdata/e.2.golden | 130 - src/pkg/go/doc/testdata/e.go | 147 - src/pkg/go/doc/testdata/error1.0.golden | 30 - src/pkg/go/doc/testdata/error1.1.golden | 32 - src/pkg/go/doc/testdata/error1.2.golden | 30 - src/pkg/go/doc/testdata/error1.go | 24 - src/pkg/go/doc/testdata/error2.0.golden | 27 - src/pkg/go/doc/testdata/error2.1.golden | 37 - src/pkg/go/doc/testdata/error2.2.golden | 27 - src/pkg/go/doc/testdata/error2.go | 29 - src/pkg/go/doc/testdata/example.go | 81 - src/pkg/go/doc/testdata/f.0.golden | 13 - src/pkg/go/doc/testdata/f.1.golden | 16 - src/pkg/go/doc/testdata/f.2.golden | 13 - src/pkg/go/doc/testdata/f.go | 14 - src/pkg/go/doc/testdata/template.txt | 68 - src/pkg/go/doc/testdata/testing.0.golden | 156 - src/pkg/go/doc/testdata/testing.1.golden | 298 - src/pkg/go/doc/testdata/testing.2.golden | 156 - src/pkg/go/doc/testdata/testing.go | 404 - src/pkg/go/format/format.go | 199 - src/pkg/go/format/format_test.go | 124 - src/pkg/go/parser/error_test.go | 183 - src/pkg/go/parser/example_test.go | 34 - src/pkg/go/parser/interface.go | 198 - src/pkg/go/parser/parser.go | 2478 ---- src/pkg/go/parser/parser_test.go | 431 - src/pkg/go/parser/performance_test.go | 30 - src/pkg/go/parser/short_test.go | 98 - src/pkg/go/parser/testdata/commas.src | 19 - src/pkg/go/parser/testdata/issue3106.src | 46 - src/pkg/go/printer/example_test.go | 67 - src/pkg/go/printer/nodes.go | 1599 --- src/pkg/go/printer/performance_test.go | 58 - src/pkg/go/printer/printer.go | 1292 -- src/pkg/go/printer/printer_test.go | 569 - src/pkg/go/printer/testdata/comments.golden | 643 - src/pkg/go/printer/testdata/comments.input | 648 - src/pkg/go/printer/testdata/comments.x | 56 - src/pkg/go/printer/testdata/comments2.golden | 105 - src/pkg/go/printer/testdata/comments2.input | 105 - src/pkg/go/printer/testdata/declarations.golden | 955 -- src/pkg/go/printer/testdata/declarations.input | 967 -- src/pkg/go/printer/testdata/empty.golden | 5 - src/pkg/go/printer/testdata/empty.input | 5 - src/pkg/go/printer/testdata/expressions.golden | 681 - src/pkg/go/printer/testdata/expressions.input | 710 - src/pkg/go/printer/testdata/expressions.raw | 681 - src/pkg/go/printer/testdata/linebreaks.golden | 275 - src/pkg/go/printer/testdata/linebreaks.input | 271 - src/pkg/go/printer/testdata/parser.go | 2153 --- src/pkg/go/printer/testdata/slow.golden | 85 - src/pkg/go/printer/testdata/slow.input | 85 - src/pkg/go/printer/testdata/statements.golden | 635 - src/pkg/go/printer/testdata/statements.input | 550 - src/pkg/go/scanner/errors.go | 126 - src/pkg/go/scanner/example_test.go | 46 - src/pkg/go/scanner/scanner.go | 760 - src/pkg/go/scanner/scanner_test.go | 775 -- src/pkg/go/token/position.go | 464 - src/pkg/go/token/position_test.go | 238 - src/pkg/go/token/serialize.go | 56 - src/pkg/go/token/serialize_test.go | 111 - src/pkg/go/token/token.go | 308 - src/pkg/hash/adler32/adler32.go | 78 - src/pkg/hash/adler32/adler32_test.go | 105 - src/pkg/hash/crc32/crc32.go | 135 - src/pkg/hash/crc32/crc32_amd64.s | 64 - src/pkg/hash/crc32/crc32_amd64p32.s | 64 - src/pkg/hash/crc32/crc32_amd64x.go | 27 - src/pkg/hash/crc32/crc32_generic.go | 14 - src/pkg/hash/crc32/crc32_test.go | 99 - src/pkg/hash/crc64/crc64.go | 87 - src/pkg/hash/crc64/crc64_test.go | 81 - src/pkg/hash/fnv/fnv.go | 131 - src/pkg/hash/fnv/fnv_test.go | 165 - src/pkg/hash/hash.go | 43 - src/pkg/hash/test_cases.txt | 31 - src/pkg/hash/test_gen.awk | 14 - src/pkg/html/entity.go | 2253 --- src/pkg/html/entity_test.go | 29 - src/pkg/html/escape.go | 250 - src/pkg/html/escape_test.go | 115 - src/pkg/html/template/attr.go | 175 - src/pkg/html/template/clone_test.go | 188 - src/pkg/html/template/content.go | 136 - src/pkg/html/template/content_test.go | 280 - src/pkg/html/template/context.go | 339 - src/pkg/html/template/css.go | 268 - src/pkg/html/template/css_test.go | 281 - src/pkg/html/template/doc.go | 191 - src/pkg/html/template/error.go | 197 - src/pkg/html/template/escape.go | 815 -- src/pkg/html/template/escape_test.go | 1692 --- src/pkg/html/template/html.go | 257 - src/pkg/html/template/html_test.go | 94 - src/pkg/html/template/js.go | 362 - src/pkg/html/template/js_test.go | 401 - src/pkg/html/template/template.go | 381 - src/pkg/html/template/transition.go | 550 - src/pkg/html/template/url.go | 105 - src/pkg/html/template/url_test.go | 112 - src/pkg/image/color/color.go | 297 - src/pkg/image/color/palette/gen.go | 101 - src/pkg/image/color/palette/palette.go | 504 - src/pkg/image/color/ycbcr.go | 99 - src/pkg/image/color/ycbcr_test.go | 33 - src/pkg/image/decode_example_test.go | 140 - src/pkg/image/decode_test.go | 120 - src/pkg/image/draw/bench_test.go | 206 - src/pkg/image/draw/clip_test.go | 193 - src/pkg/image/draw/draw.go | 673 - src/pkg/image/draw/draw_test.go | 429 - src/pkg/image/format.go | 100 - src/pkg/image/geom.go | 234 - src/pkg/image/gif/reader.go | 460 - src/pkg/image/gif/reader_test.go | 201 - src/pkg/image/gif/writer.go | 323 - src/pkg/image/gif/writer_test.go | 204 - src/pkg/image/image.go | 904 -- src/pkg/image/image_test.go | 113 - src/pkg/image/jpeg/dct_test.go | 299 - src/pkg/image/jpeg/fdct.go | 190 - src/pkg/image/jpeg/huffman.go | 219 - src/pkg/image/jpeg/idct.go | 192 - src/pkg/image/jpeg/reader.go | 377 - src/pkg/image/jpeg/reader_test.go | 225 - src/pkg/image/jpeg/scan.go | 439 - src/pkg/image/jpeg/writer.go | 553 - src/pkg/image/jpeg/writer_test.go | 204 - src/pkg/image/names.go | 52 - src/pkg/image/png/paeth.go | 70 - src/pkg/image/png/paeth_test.go | 91 - src/pkg/image/png/reader.go | 699 - src/pkg/image/png/reader_test.go | 350 - src/pkg/image/png/testdata/benchGray.png | Bin 14709 -> 0 bytes src/pkg/image/png/testdata/benchNRGBA-gradient.png | Bin 58831 -> 0 bytes src/pkg/image/png/testdata/benchNRGBA-opaque.png | Bin 44237 -> 0 bytes src/pkg/image/png/testdata/benchPaletted.png | Bin 13397 -> 0 bytes src/pkg/image/png/testdata/benchRGB.png | Bin 39571 -> 0 bytes src/pkg/image/png/testdata/invalid-crc32.png | Bin 1289 -> 0 bytes src/pkg/image/png/testdata/invalid-noend.png | Bin 1277 -> 0 bytes src/pkg/image/png/testdata/invalid-trunc.png | Bin 1288 -> 0 bytes src/pkg/image/png/testdata/invalid-zlib.png | Bin 1289 -> 0 bytes src/pkg/image/png/testdata/pngsuite/README | 21 - .../image/png/testdata/pngsuite/README.original | 85 - .../image/png/testdata/pngsuite/basn0g01-30.png | Bin 162 -> 0 bytes .../image/png/testdata/pngsuite/basn0g01-30.sng | 39 - src/pkg/image/png/testdata/pngsuite/basn0g01.png | Bin 164 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn0g01.sng | 41 - .../image/png/testdata/pngsuite/basn0g02-29.png | Bin 110 -> 0 bytes .../image/png/testdata/pngsuite/basn0g02-29.sng | 38 - src/pkg/image/png/testdata/pngsuite/basn0g02.png | Bin 104 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn0g02.sng | 41 - .../image/png/testdata/pngsuite/basn0g04-31.png | Bin 153 -> 0 bytes .../image/png/testdata/pngsuite/basn0g04-31.sng | 40 - src/pkg/image/png/testdata/pngsuite/basn0g04.png | Bin 145 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn0g04.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn0g08.png | Bin 138 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn0g08.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn0g16.png | Bin 167 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn0g16.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn2c08.png | Bin 145 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn2c08.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn2c16.png | Bin 302 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn2c16.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn3p01.png | Bin 112 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn3p01.sng | 45 - src/pkg/image/png/testdata/pngsuite/basn3p02.png | Bin 146 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn3p02.sng | 47 - src/pkg/image/png/testdata/pngsuite/basn3p04.png | Bin 216 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn3p04.sng | 58 - .../image/png/testdata/pngsuite/basn3p08-trns.png | Bin 1538 -> 0 bytes .../image/png/testdata/pngsuite/basn3p08-trns.sng | 301 - src/pkg/image/png/testdata/pngsuite/basn3p08.png | Bin 1286 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn3p08.sng | 299 - src/pkg/image/png/testdata/pngsuite/basn4a08.png | Bin 126 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn4a08.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn4a16.png | Bin 2206 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn4a16.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn6a08.png | Bin 184 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn6a08.sng | 41 - src/pkg/image/png/testdata/pngsuite/basn6a16.png | Bin 3435 -> 0 bytes src/pkg/image/png/testdata/pngsuite/basn6a16.sng | 41 - src/pkg/image/png/writer.go | 482 - src/pkg/image/png/writer_test.go | 191 - src/pkg/image/testdata/video-001.5bpp.gif | Bin 6214 -> 0 bytes src/pkg/image/testdata/video-001.gif | Bin 13106 -> 0 bytes src/pkg/image/testdata/video-001.interlaced.gif | Bin 14142 -> 0 bytes src/pkg/image/testdata/video-001.jpeg | Bin 21459 -> 0 bytes src/pkg/image/testdata/video-001.png | Bin 29228 -> 0 bytes src/pkg/image/testdata/video-001.progressive.jpeg | Bin 20732 -> 0 bytes src/pkg/image/testdata/video-001.q50.420.jpeg | Bin 3407 -> 0 bytes .../testdata/video-001.q50.420.progressive.jpeg | Bin 3279 -> 0 bytes src/pkg/image/testdata/video-001.q50.422.jpeg | Bin 3608 -> 0 bytes .../testdata/video-001.q50.422.progressive.jpeg | Bin 3506 -> 0 bytes src/pkg/image/testdata/video-001.q50.440.jpeg | Bin 3662 -> 0 bytes .../testdata/video-001.q50.440.progressive.jpeg | Bin 3529 -> 0 bytes src/pkg/image/testdata/video-001.q50.444.jpeg | Bin 4032 -> 0 bytes .../testdata/video-001.q50.444.progressive.jpeg | Bin 3935 -> 0 bytes .../video-001.separate.dc.progression.jpeg | Bin 14288 -> 0 bytes ...eo-001.separate.dc.progression.progressive.jpeg | Bin 14312 -> 0 bytes src/pkg/image/testdata/video-005.gray.gif | Bin 14505 -> 0 bytes src/pkg/image/testdata/video-005.gray.jpeg | Bin 5618 -> 0 bytes src/pkg/image/testdata/video-005.gray.png | Bin 14974 -> 0 bytes src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg | Bin 2782 -> 0 bytes .../video-005.gray.q50.2x2.progressive.jpeg | Bin 2699 -> 0 bytes src/pkg/image/testdata/video-005.gray.q50.jpeg | Bin 2782 -> 0 bytes .../testdata/video-005.gray.q50.progressive.jpeg | Bin 2699 -> 0 bytes src/pkg/image/ycbcr.go | 153 - src/pkg/image/ycbcr_test.go | 107 - src/pkg/index/suffixarray/qsufsort.go | 168 - src/pkg/index/suffixarray/suffixarray.go | 307 - src/pkg/index/suffixarray/suffixarray_test.go | 304 - src/pkg/io/io.go | 493 - src/pkg/io/io_test.go | 341 - src/pkg/io/ioutil/ioutil.go | 165 - src/pkg/io/ioutil/ioutil_test.go | 95 - src/pkg/io/ioutil/tempfile.go | 95 - src/pkg/io/ioutil/tempfile_test.go | 53 - src/pkg/io/multi.go | 61 - src/pkg/io/multi_test.go | 115 - src/pkg/io/pipe.go | 193 - src/pkg/io/pipe_test.go | 302 - src/pkg/log/example_test.go | 21 - src/pkg/log/log.go | 322 - src/pkg/log/log_test.go | 119 - src/pkg/log/syslog/syslog.go | 319 - src/pkg/log/syslog/syslog_plan9.go | 8 - src/pkg/log/syslog/syslog_test.go | 358 - src/pkg/log/syslog/syslog_unix.go | 31 - src/pkg/log/syslog/syslog_windows.go | 8 - src/pkg/math/abs.go | 22 - src/pkg/math/abs_386.s | 12 - src/pkg/math/abs_amd64.s | 14 - src/pkg/math/abs_amd64p32.s | 5 - src/pkg/math/abs_arm.s | 13 - src/pkg/math/acosh.go | 60 - src/pkg/math/all_test.go | 2935 ---- src/pkg/math/asin.go | 55 - src/pkg/math/asin_386.s | 30 - src/pkg/math/asin_amd64.s | 11 - src/pkg/math/asin_amd64p32.s | 5 - src/pkg/math/asin_arm.s | 11 - src/pkg/math/asinh.go | 69 - src/pkg/math/atan.go | 105 - src/pkg/math/atan2.go | 71 - src/pkg/math/atan2_386.s | 13 - src/pkg/math/atan2_amd64.s | 8 - src/pkg/math/atan2_amd64p32.s | 5 - src/pkg/math/atan2_arm.s | 8 - src/pkg/math/atan_386.s | 13 - src/pkg/math/atan_amd64.s | 8 - src/pkg/math/atan_amd64p32.s | 5 - src/pkg/math/atan_arm.s | 8 - src/pkg/math/atanh.go | 77 - src/pkg/math/big/arith.go | 240 - src/pkg/math/big/arith_386.s | 278 - src/pkg/math/big/arith_amd64.s | 401 - src/pkg/math/big/arith_amd64p32.s | 41 - src/pkg/math/big/arith_arm.s | 300 - src/pkg/math/big/arith_decl.go | 19 - src/pkg/math/big/arith_test.go | 456 - src/pkg/math/big/calibrate_test.go | 88 - src/pkg/math/big/example_test.go | 51 - src/pkg/math/big/gcd_test.go | 47 - src/pkg/math/big/hilbert_test.go | 160 - src/pkg/math/big/int.go | 1011 -- src/pkg/math/big/int_test.go | 1601 --- src/pkg/math/big/nat.go | 1508 -- src/pkg/math/big/nat_test.go | 771 -- src/pkg/math/big/rat.go | 600 - src/pkg/math/big/rat_test.go | 994 -- src/pkg/math/bits.go | 59 - src/pkg/math/cbrt.go | 76 - src/pkg/math/cmplx/abs.go | 12 - src/pkg/math/cmplx/asin.go | 170 - src/pkg/math/cmplx/cmath_test.go | 866 -- src/pkg/math/cmplx/conj.go | 8 - src/pkg/math/cmplx/exp.go | 55 - src/pkg/math/cmplx/isinf.go | 21 - src/pkg/math/cmplx/isnan.go | 25 - src/pkg/math/cmplx/log.go | 64 - src/pkg/math/cmplx/phase.go | 11 - src/pkg/math/cmplx/polar.go | 12 - src/pkg/math/cmplx/pow.go | 78 - src/pkg/math/cmplx/rect.go | 13 - src/pkg/math/cmplx/sin.go | 132 - src/pkg/math/cmplx/sqrt.go | 104 - src/pkg/math/cmplx/tan.go | 184 - src/pkg/math/const.go | 51 - src/pkg/math/copysign.go | 12 - src/pkg/math/dim.go | 72 - src/pkg/math/dim_386.s | 14 - src/pkg/math/dim_amd64.s | 144 - src/pkg/math/dim_amd64p32.s | 5 - src/pkg/math/dim_arm.s | 14 - src/pkg/math/erf.go | 335 - src/pkg/math/exp.go | 191 - src/pkg/math/exp2_386.s | 40 - src/pkg/math/exp2_amd64.s | 8 - src/pkg/math/exp2_amd64p32.s | 5 - src/pkg/math/exp2_arm.s | 8 - src/pkg/math/exp_386.s | 41 - src/pkg/math/exp_amd64.s | 114 - src/pkg/math/exp_amd64p32.s | 5 - src/pkg/math/exp_arm.s | 8 - src/pkg/math/expm1.go | 237 - src/pkg/math/expm1_386.s | 57 - src/pkg/math/expm1_amd64.s | 8 - src/pkg/math/expm1_amd64p32.s | 5 - src/pkg/math/expm1_arm.s | 8 - src/pkg/math/export_test.go | 11 - src/pkg/math/floor.go | 56 - src/pkg/math/floor_386.s | 46 - src/pkg/math/floor_amd64.s | 76 - src/pkg/math/floor_amd64p32.s | 5 - src/pkg/math/floor_arm.s | 14 - src/pkg/math/frexp.go | 33 - src/pkg/math/frexp_386.s | 25 - src/pkg/math/frexp_amd64.s | 8 - src/pkg/math/frexp_amd64p32.s | 5 - src/pkg/math/frexp_arm.s | 8 - src/pkg/math/gamma.go | 202 - src/pkg/math/hypot.go | 43 - src/pkg/math/hypot_386.s | 59 - src/pkg/math/hypot_amd64.s | 52 - src/pkg/math/hypot_amd64p32.s | 5 - src/pkg/math/hypot_arm.s | 8 - src/pkg/math/j0.go | 429 - src/pkg/math/j1.go | 422 - src/pkg/math/jn.go | 306 - src/pkg/math/ldexp.go | 45 - src/pkg/math/ldexp_386.s | 14 - src/pkg/math/ldexp_amd64.s | 8 - src/pkg/math/ldexp_amd64p32.s | 5 - src/pkg/math/ldexp_arm.s | 8 - src/pkg/math/lgamma.go | 365 - src/pkg/math/log.go | 123 - src/pkg/math/log10.go | 22 - src/pkg/math/log10_386.s | 21 - src/pkg/math/log10_amd64.s | 11 - src/pkg/math/log10_amd64p32.s | 5 - src/pkg/math/log10_arm.s | 11 - src/pkg/math/log1p.go | 200 - src/pkg/math/log1p_386.s | 27 - src/pkg/math/log1p_amd64.s | 8 - src/pkg/math/log1p_amd64p32.s | 5 - src/pkg/math/log1p_arm.s | 8 - src/pkg/math/log_386.s | 13 - src/pkg/math/log_amd64.s | 111 - src/pkg/math/log_amd64p32.s | 5 - src/pkg/math/log_arm.s | 8 - src/pkg/math/logb.go | 50 - src/pkg/math/mod.go | 50 - src/pkg/math/mod_386.s | 17 - src/pkg/math/mod_amd64.s | 8 - src/pkg/math/mod_amd64p32.s | 5 - src/pkg/math/mod_arm.s | 8 - src/pkg/math/modf.go | 34 - src/pkg/math/modf_386.s | 21 - src/pkg/math/modf_amd64.s | 8 - src/pkg/math/modf_amd64p32.s | 5 - src/pkg/math/modf_arm.s | 8 - src/pkg/math/nextafter.go | 27 - src/pkg/math/pow.go | 137 - src/pkg/math/pow10.go | 40 - src/pkg/math/rand/example_test.go | 97 - src/pkg/math/rand/exp.go | 222 - src/pkg/math/rand/normal.go | 157 - src/pkg/math/rand/rand.go | 246 - src/pkg/math/rand/rand_test.go | 398 - src/pkg/math/rand/regress_test.go | 355 - src/pkg/math/rand/rng.go | 246 - src/pkg/math/rand/zipf.go | 75 - src/pkg/math/remainder.go | 85 - src/pkg/math/remainder_386.s | 17 - src/pkg/math/remainder_amd64.s | 8 - src/pkg/math/remainder_amd64p32.s | 5 - src/pkg/math/remainder_arm.s | 8 - src/pkg/math/signbit.go | 10 - src/pkg/math/sin.go | 224 - src/pkg/math/sin_386.s | 47 - src/pkg/math/sin_amd64.s | 11 - src/pkg/math/sin_amd64p32.s | 5 - src/pkg/math/sin_arm.s | 11 - src/pkg/math/sincos.go | 69 - src/pkg/math/sincos_386.s | 28 - src/pkg/math/sincos_amd64.s | 145 - src/pkg/math/sincos_amd64p32.s | 5 - src/pkg/math/sincos_arm.s | 8 - src/pkg/math/sinh.go | 77 - src/pkg/math/sqrt.go | 143 - src/pkg/math/sqrt_386.s | 12 - src/pkg/math/sqrt_amd64.s | 11 - src/pkg/math/sqrt_amd64p32.s | 5 - src/pkg/math/sqrt_arm.s | 12 - src/pkg/math/tan.go | 130 - src/pkg/math/tan_386.s | 28 - src/pkg/math/tan_amd64.s | 8 - src/pkg/math/tan_amd64p32.s | 5 - src/pkg/math/tan_arm.s | 8 - src/pkg/math/tanh.go | 97 - src/pkg/math/unsafe.go | 21 - src/pkg/mime/grammar.go | 32 - src/pkg/mime/mediatype.go | 358 - src/pkg/mime/mediatype_test.go | 306 - src/pkg/mime/multipart/example_test.go | 53 - src/pkg/mime/multipart/formdata.go | 157 - src/pkg/mime/multipart/formdata_test.go | 90 - src/pkg/mime/multipart/multipart.go | 349 - src/pkg/mime/multipart/multipart_test.go | 634 - src/pkg/mime/multipart/quotedprintable.go | 118 - src/pkg/mime/multipart/quotedprintable_test.go | 204 - src/pkg/mime/multipart/testdata/nested-mime | 29 - src/pkg/mime/multipart/writer.go | 184 - src/pkg/mime/multipart/writer_test.go | 113 - src/pkg/mime/testdata/test.types | 8 - src/pkg/mime/testdata/test.types.plan9 | 8 - src/pkg/mime/type.go | 77 - src/pkg/mime/type_plan9.go | 53 - src/pkg/mime/type_test.go | 29 - src/pkg/mime/type_unix.go | 60 - src/pkg/mime/type_windows.go | 63 - src/pkg/net/cgo_bsd.go | 17 - src/pkg/net/cgo_linux.go | 22 - src/pkg/net/cgo_netbsd.go | 16 - src/pkg/net/cgo_openbsd.go | 16 - src/pkg/net/cgo_stub.go | 25 - src/pkg/net/cgo_unix.go | 164 - src/pkg/net/cgo_unix_test.go | 24 - src/pkg/net/conn_test.go | 124 - src/pkg/net/dial.go | 305 - src/pkg/net/dial_gen.go | 46 - src/pkg/net/dial_gen_test.go | 11 - src/pkg/net/dial_test.go | 536 - src/pkg/net/dialgoogle_test.go | 209 - src/pkg/net/dnsclient.go | 251 - src/pkg/net/dnsclient_test.go | 69 - src/pkg/net/dnsclient_unix.go | 364 - src/pkg/net/dnsclient_unix_test.go | 159 - src/pkg/net/dnsconfig_unix.go | 109 - src/pkg/net/dnsconfig_unix_test.go | 46 - src/pkg/net/dnsmsg.go | 887 -- src/pkg/net/dnsmsg_test.go | 113 - src/pkg/net/dnsname_test.go | 83 - src/pkg/net/empty.c | 8 - src/pkg/net/example_test.go | 36 - src/pkg/net/fd_mutex.go | 184 - src/pkg/net/fd_mutex_test.go | 195 - src/pkg/net/fd_plan9.go | 232 - src/pkg/net/fd_poll_nacl.go | 94 - src/pkg/net/fd_poll_runtime.go | 144 - src/pkg/net/fd_unix.go | 518 - src/pkg/net/fd_unix_test.go | 58 - src/pkg/net/fd_windows.go | 644 - src/pkg/net/file_plan9.go | 157 - src/pkg/net/file_test.go | 205 - src/pkg/net/file_unix.go | 139 - src/pkg/net/file_windows.go | 37 - src/pkg/net/hosts.go | 86 - src/pkg/net/hosts_test.go | 81 - src/pkg/net/http/cgi/child.go | 206 - src/pkg/net/http/cgi/child_test.go | 131 - src/pkg/net/http/cgi/host.go | 377 - src/pkg/net/http/cgi/host_test.go | 461 - src/pkg/net/http/cgi/matryoshka_test.go | 228 - src/pkg/net/http/cgi/plan9_test.go | 18 - src/pkg/net/http/cgi/posix_test.go | 21 - src/pkg/net/http/cgi/testdata/test.cgi | 91 - src/pkg/net/http/chunked.go | 203 - src/pkg/net/http/chunked_test.go | 159 - src/pkg/net/http/client.go | 487 - src/pkg/net/http/client_test.go | 1038 -- src/pkg/net/http/cookie.go | 363 - src/pkg/net/http/cookie_test.go | 380 - src/pkg/net/http/cookiejar/jar.go | 497 - src/pkg/net/http/cookiejar/jar_test.go | 1267 -- src/pkg/net/http/cookiejar/punycode.go | 159 - src/pkg/net/http/cookiejar/punycode_test.go | 161 - src/pkg/net/http/doc.go | 80 - src/pkg/net/http/example_test.go | 88 - src/pkg/net/http/export_test.go | 72 - src/pkg/net/http/fcgi/child.go | 305 - src/pkg/net/http/fcgi/fcgi.go | 274 - src/pkg/net/http/fcgi/fcgi_test.go | 150 - src/pkg/net/http/filetransport.go | 123 - src/pkg/net/http/filetransport_test.go | 65 - src/pkg/net/http/fs.go | 549 - src/pkg/net/http/fs_test.go | 858 -- src/pkg/net/http/header.go | 211 - src/pkg/net/http/header_test.go | 212 - src/pkg/net/http/httptest/example_test.go | 50 - src/pkg/net/http/httptest/recorder.go | 72 - src/pkg/net/http/httptest/recorder_test.go | 90 - src/pkg/net/http/httptest/server.go | 228 - src/pkg/net/http/httptest/server_test.go | 53 - src/pkg/net/http/httputil/chunked.go | 203 - src/pkg/net/http/httputil/chunked_test.go | 159 - src/pkg/net/http/httputil/dump.go | 276 - src/pkg/net/http/httputil/dump_test.go | 263 - src/pkg/net/http/httputil/httputil.go | 32 - src/pkg/net/http/httputil/persist.go | 429 - src/pkg/net/http/httputil/reverseproxy.go | 211 - src/pkg/net/http/httputil/reverseproxy_test.go | 213 - src/pkg/net/http/jar.go | 27 - src/pkg/net/http/lex.go | 96 - src/pkg/net/http/lex_test.go | 31 - src/pkg/net/http/npn_test.go | 118 - src/pkg/net/http/pprof/pprof.go | 205 - src/pkg/net/http/proxy_test.go | 81 - src/pkg/net/http/race.go | 11 - src/pkg/net/http/range_test.go | 79 - src/pkg/net/http/readrequest_test.go | 331 - src/pkg/net/http/request.go | 875 -- src/pkg/net/http/request_test.go | 610 - src/pkg/net/http/requestwrite_test.go | 565 - src/pkg/net/http/response.go | 291 - src/pkg/net/http/response_test.go | 645 - src/pkg/net/http/responsewrite_test.go | 226 - src/pkg/net/http/serve_test.go | 2848 ---- src/pkg/net/http/server.go | 2052 --- src/pkg/net/http/sniff.go | 214 - src/pkg/net/http/sniff_test.go | 171 - src/pkg/net/http/status.go | 120 - src/pkg/net/http/testdata/file | 1 - src/pkg/net/http/testdata/index.html | 1 - src/pkg/net/http/testdata/style.css | 1 - src/pkg/net/http/transfer.go | 730 - src/pkg/net/http/transfer_test.go | 64 - src/pkg/net/http/transport.go | 1208 -- src/pkg/net/http/transport_test.go | 2173 --- src/pkg/net/http/triv.go | 141 - src/pkg/net/http/z_last_test.go | 97 - src/pkg/net/interface.go | 126 - src/pkg/net/interface_bsd.go | 182 - src/pkg/net/interface_bsd_test.go | 52 - src/pkg/net/interface_darwin.go | 63 - src/pkg/net/interface_dragonfly.go | 12 - src/pkg/net/interface_freebsd.go | 63 - src/pkg/net/interface_linux.go | 271 - src/pkg/net/interface_linux_test.go | 102 - src/pkg/net/interface_netbsd.go | 12 - src/pkg/net/interface_openbsd.go | 12 - src/pkg/net/interface_stub.go | 27 - src/pkg/net/interface_test.go | 211 - src/pkg/net/interface_unix_test.go | 151 - src/pkg/net/interface_windows.go | 158 - src/pkg/net/ip.go | 681 - src/pkg/net/ip_test.go | 439 - src/pkg/net/ipraw_test.go | 289 - src/pkg/net/iprawsock.go | 54 - src/pkg/net/iprawsock_plan9.go | 82 - src/pkg/net/iprawsock_posix.go | 227 - src/pkg/net/ipsock.go | 318 - src/pkg/net/ipsock_plan9.go | 228 - src/pkg/net/ipsock_posix.go | 177 - src/pkg/net/ipsock_test.go | 193 - src/pkg/net/lookup.go | 137 - src/pkg/net/lookup_plan9.go | 297 - src/pkg/net/lookup_test.go | 137 - src/pkg/net/lookup_unix.go | 168 - src/pkg/net/lookup_windows.go | 322 - src/pkg/net/mac.go | 86 - src/pkg/net/mac_test.go | 66 - src/pkg/net/mail/message.go | 545 - src/pkg/net/mail/message_test.go | 304 - src/pkg/net/mockicmp_test.go | 116 - src/pkg/net/mockserver_test.go | 82 - src/pkg/net/multicast_test.go | 188 - src/pkg/net/net.go | 426 - src/pkg/net/net_test.go | 263 - src/pkg/net/net_windows_test.go | 148 - src/pkg/net/netgo_unix_test.go | 24 - src/pkg/net/packetconn_test.go | 186 - src/pkg/net/parse.go | 247 - src/pkg/net/parse_test.go | 53 - src/pkg/net/pipe.go | 67 - src/pkg/net/pipe_test.go | 56 - src/pkg/net/port.go | 24 - src/pkg/net/port_test.go | 53 - src/pkg/net/port_unix.go | 73 - src/pkg/net/protoconn_test.go | 386 - src/pkg/net/race.go | 31 - src/pkg/net/race0.go | 26 - src/pkg/net/rpc/client.go | 317 - src/pkg/net/rpc/client_test.go | 36 - src/pkg/net/rpc/debug.go | 93 - src/pkg/net/rpc/jsonrpc/all_test.go | 296 - src/pkg/net/rpc/jsonrpc/client.go | 123 - src/pkg/net/rpc/jsonrpc/server.go | 134 - src/pkg/net/rpc/server.go | 686 - src/pkg/net/rpc/server_test.go | 683 - src/pkg/net/sendfile_dragonfly.go | 103 - src/pkg/net/sendfile_freebsd.go | 103 - src/pkg/net/sendfile_linux.go | 76 - src/pkg/net/sendfile_stub.go | 13 - src/pkg/net/sendfile_windows.go | 55 - src/pkg/net/server_test.go | 461 - src/pkg/net/singleflight.go | 53 - src/pkg/net/smtp/auth.go | 107 - src/pkg/net/smtp/example_test.go | 61 - src/pkg/net/smtp/smtp.go | 357 - src/pkg/net/smtp/smtp_test.go | 694 - src/pkg/net/sock_bsd.go | 37 - src/pkg/net/sock_cloexec.go | 78 - src/pkg/net/sock_linux.go | 31 - src/pkg/net/sock_plan9.go | 10 - src/pkg/net/sock_posix.go | 192 - src/pkg/net/sock_solaris.go | 13 - src/pkg/net/sock_windows.go | 24 - src/pkg/net/sockopt_bsd.go | 54 - src/pkg/net/sockopt_linux.go | 32 - src/pkg/net/sockopt_plan9.go | 13 - src/pkg/net/sockopt_posix.go | 141 - src/pkg/net/sockopt_solaris.go | 32 - src/pkg/net/sockopt_windows.go | 38 - src/pkg/net/sockoptip_bsd.go | 34 - src/pkg/net/sockoptip_linux.go | 31 - src/pkg/net/sockoptip_posix.go | 57 - src/pkg/net/sockoptip_stub.go | 39 - src/pkg/net/sockoptip_windows.go | 33 - src/pkg/net/sys_cloexec.go | 54 - src/pkg/net/tcp_test.go | 611 - src/pkg/net/tcpsock.go | 54 - src/pkg/net/tcpsock_plan9.go | 198 - src/pkg/net/tcpsock_posix.go | 299 - src/pkg/net/tcpsockopt_darwin.go | 27 - src/pkg/net/tcpsockopt_dragonfly.go | 29 - src/pkg/net/tcpsockopt_openbsd.go | 27 - src/pkg/net/tcpsockopt_plan9.go | 18 - src/pkg/net/tcpsockopt_posix.go | 20 - src/pkg/net/tcpsockopt_solaris.go | 27 - src/pkg/net/tcpsockopt_unix.go | 31 - src/pkg/net/tcpsockopt_windows.go | 34 - src/pkg/net/testdata/hosts | 12 - src/pkg/net/testdata/hosts_singleline | 1 - src/pkg/net/testdata/igmp | 24 - src/pkg/net/testdata/igmp6 | 18 - src/pkg/net/testdata/resolv.conf | 6 - src/pkg/net/textproto/header.go | 43 - src/pkg/net/textproto/pipeline.go | 117 - src/pkg/net/textproto/reader.go | 637 - src/pkg/net/textproto/reader_test.go | 337 - src/pkg/net/textproto/textproto.go | 154 - src/pkg/net/textproto/writer.go | 118 - src/pkg/net/textproto/writer_test.go | 35 - src/pkg/net/timeout_test.go | 747 - src/pkg/net/udp_test.go | 257 - src/pkg/net/udpsock.go | 54 - src/pkg/net/udpsock_plan9.go | 203 - src/pkg/net/udpsock_posix.go | 268 - src/pkg/net/unicast_posix_test.go | 466 - src/pkg/net/unix_test.go | 326 - src/pkg/net/unixsock.go | 43 - src/pkg/net/unixsock_plan9.go | 143 - src/pkg/net/unixsock_posix.go | 373 - src/pkg/net/url/example_test.go | 41 - src/pkg/net/url/url.go | 700 - src/pkg/net/url/url_test.go | 905 -- src/pkg/net/z_last_test.go | 37 - src/pkg/os/dir_plan9.go | 73 - src/pkg/os/dir_unix.go | 58 - src/pkg/os/dir_windows.go | 14 - src/pkg/os/doc.go | 135 - src/pkg/os/env.go | 103 - src/pkg/os/env_test.go | 70 - src/pkg/os/env_unix_test.go | 30 - src/pkg/os/error.go | 65 - src/pkg/os/error_plan9.go | 53 - src/pkg/os/error_test.go | 132 - src/pkg/os/error_unix.go | 45 - src/pkg/os/error_windows.go | 45 - src/pkg/os/error_windows_test.go | 47 - src/pkg/os/exec.go | 70 - src/pkg/os/exec/example_test.go | 75 - src/pkg/os/exec/exec.go | 493 - src/pkg/os/exec/exec_test.go | 726 - src/pkg/os/exec/lp_plan9.go | 53 - src/pkg/os/exec/lp_test.go | 33 - src/pkg/os/exec/lp_unix.go | 60 - src/pkg/os/exec/lp_unix_test.go | 55 - src/pkg/os/exec/lp_windows.go | 123 - src/pkg/os/exec/lp_windows_test.go | 573 - src/pkg/os/exec_plan9.go | 137 - src/pkg/os/exec_posix.go | 134 - src/pkg/os/exec_unix.go | 73 - src/pkg/os/exec_windows.go | 115 - src/pkg/os/export_test.go | 10 - src/pkg/os/file.go | 257 - src/pkg/os/file_plan9.go | 468 - src/pkg/os/file_posix.go | 169 - src/pkg/os/file_unix.go | 314 - src/pkg/os/file_windows.go | 495 - src/pkg/os/getwd.go | 119 - src/pkg/os/getwd_darwin.go | 15 - src/pkg/os/os_test.go | 1339 -- src/pkg/os/os_unix_test.go | 76 - src/pkg/os/path.go | 123 - src/pkg/os/path_plan9.go | 15 - src/pkg/os/path_test.go | 215 - src/pkg/os/path_unix.go | 17 - src/pkg/os/path_windows.go | 16 - src/pkg/os/pipe_bsd.go | 28 - src/pkg/os/pipe_linux.go | 33 - src/pkg/os/proc.go | 36 - src/pkg/os/signal/example_test.go | 23 - src/pkg/os/signal/sig.s | 23 - src/pkg/os/signal/signal.go | 131 - src/pkg/os/signal/signal_stub.go | 17 - src/pkg/os/signal/signal_test.go | 208 - src/pkg/os/signal/signal_unix.go | 53 - src/pkg/os/signal/signal_windows_test.go | 103 - src/pkg/os/stat_darwin.go | 61 - src/pkg/os/stat_dragonfly.go | 61 - src/pkg/os/stat_freebsd.go | 61 - src/pkg/os/stat_linux.go | 61 - src/pkg/os/stat_nacl.go | 62 - src/pkg/os/stat_netbsd.go | 61 - src/pkg/os/stat_openbsd.go | 61 - src/pkg/os/stat_plan9.go | 110 - src/pkg/os/stat_solaris.go | 61 - src/pkg/os/stat_windows.go | 160 - src/pkg/os/str.go | 22 - src/pkg/os/sys_bsd.go | 20 - src/pkg/os/sys_darwin.go | 31 - src/pkg/os/sys_freebsd.go | 23 - src/pkg/os/sys_linux.go | 26 - src/pkg/os/sys_nacl.go | 9 - src/pkg/os/sys_plan9.go | 26 - src/pkg/os/sys_solaris.go | 11 - src/pkg/os/sys_unix.go | 11 - src/pkg/os/sys_windows.go | 15 - src/pkg/os/types.go | 118 - src/pkg/os/types_notwin.go | 25 - src/pkg/os/types_windows.go | 104 - src/pkg/os/user/lookup.go | 22 - src/pkg/os/user/lookup_plan9.go | 46 - src/pkg/os/user/lookup_stubs.go | 28 - src/pkg/os/user/lookup_unix.go | 112 - src/pkg/os/user/lookup_windows.go | 149 - src/pkg/os/user/user.go | 43 - src/pkg/os/user/user_test.go | 89 - src/pkg/path/example_test.go | 63 - src/pkg/path/filepath/example_unix_test.go | 39 - src/pkg/path/filepath/export_test.go | 7 - src/pkg/path/filepath/match.go | 309 - src/pkg/path/filepath/match_test.go | 206 - src/pkg/path/filepath/path.go | 467 - src/pkg/path/filepath/path_plan9.go | 30 - src/pkg/path/filepath/path_test.go | 1017 -- src/pkg/path/filepath/path_unix.go | 32 - src/pkg/path/filepath/path_windows.go | 105 - src/pkg/path/filepath/path_windows_test.go | 93 - src/pkg/path/filepath/symlink.go | 67 - src/pkg/path/filepath/symlink_windows.go | 69 - src/pkg/path/match.go | 209 - src/pkg/path/match_test.go | 79 - src/pkg/path/path.go | 218 - src/pkg/path/path_test.go | 241 - src/pkg/reflect/all_test.go | 3841 ------ src/pkg/reflect/asm_386.s | 27 - src/pkg/reflect/asm_amd64.s | 27 - src/pkg/reflect/asm_amd64p32.s | 27 - src/pkg/reflect/asm_arm.s | 27 - src/pkg/reflect/deepequal.go | 145 - src/pkg/reflect/example_test.go | 66 - src/pkg/reflect/export_test.go | 19 - src/pkg/reflect/makefunc.go | 120 - src/pkg/reflect/set_test.go | 211 - src/pkg/reflect/tostring_test.go | 95 - src/pkg/reflect/type.go | 1926 --- src/pkg/reflect/value.go | 2684 ---- src/pkg/regexp/all_test.go | 645 - src/pkg/regexp/example_test.go | 148 - src/pkg/regexp/exec.go | 452 - src/pkg/regexp/exec2_test.go | 20 - src/pkg/regexp/exec_test.go | 715 - src/pkg/regexp/find_test.go | 498 - src/pkg/regexp/onepass.go | 582 - src/pkg/regexp/onepass_test.go | 208 - src/pkg/regexp/regexp.go | 1120 -- src/pkg/regexp/syntax/compile.go | 289 - src/pkg/regexp/syntax/doc.go | 131 - src/pkg/regexp/syntax/make_perl_groups.pl | 107 - src/pkg/regexp/syntax/parse.go | 1863 --- src/pkg/regexp/syntax/parse_test.go | 559 - src/pkg/regexp/syntax/perl_groups.go | 134 - src/pkg/regexp/syntax/prog.go | 345 - src/pkg/regexp/syntax/prog_test.go | 114 - src/pkg/regexp/syntax/regexp.go | 319 - src/pkg/regexp/syntax/simplify.go | 151 - src/pkg/regexp/syntax/simplify_test.go | 151 - src/pkg/regexp/testdata/README | 23 - src/pkg/regexp/testdata/basic.dat | 221 - src/pkg/regexp/testdata/nullsubexpr.dat | 79 - src/pkg/regexp/testdata/re2-exhaustive.txt.bz2 | Bin 394016 -> 0 bytes src/pkg/regexp/testdata/re2-search.txt | 3667 ----- src/pkg/regexp/testdata/repetition.dat | 163 - src/pkg/regexp/testdata/testregex.c | 2286 --- src/pkg/runtime/Makefile | 5 - src/pkg/runtime/alg.goc | 549 - src/pkg/runtime/append_test.go | 190 - src/pkg/runtime/arch_386.h | 16 - src/pkg/runtime/arch_amd64.h | 20 - src/pkg/runtime/arch_amd64p32.h | 16 - src/pkg/runtime/arch_arm.h | 12 - src/pkg/runtime/asm_386.s | 2166 --- src/pkg/runtime/asm_amd64.s | 2200 --- src/pkg/runtime/asm_amd64p32.s | 1073 -- src/pkg/runtime/asm_arm.s | 1179 -- src/pkg/runtime/atomic_386.c | 46 - src/pkg/runtime/atomic_amd64x.c | 29 - src/pkg/runtime/atomic_arm.c | 169 - src/pkg/runtime/callback_windows.c | 77 - src/pkg/runtime/cgo/asm_386.s | 31 - src/pkg/runtime/cgo/asm_amd64.s | 47 - src/pkg/runtime/cgo/asm_arm.s | 24 - src/pkg/runtime/cgo/asm_nacl_amd64p32.s | 13 - src/pkg/runtime/cgo/callbacks.c | 102 - src/pkg/runtime/cgo/cgo.go | 32 - src/pkg/runtime/cgo/dragonfly.c | 13 - src/pkg/runtime/cgo/freebsd.c | 13 - src/pkg/runtime/cgo/gcc_386.S | 45 - src/pkg/runtime/cgo/gcc_amd64.S | 48 - src/pkg/runtime/cgo/gcc_arm.S | 46 - src/pkg/runtime/cgo/gcc_darwin_386.c | 165 - src/pkg/runtime/cgo/gcc_darwin_amd64.c | 135 - src/pkg/runtime/cgo/gcc_dragonfly_386.c | 77 - src/pkg/runtime/cgo/gcc_dragonfly_amd64.c | 77 - src/pkg/runtime/cgo/gcc_freebsd_386.c | 77 - src/pkg/runtime/cgo/gcc_freebsd_amd64.c | 77 - src/pkg/runtime/cgo/gcc_freebsd_arm.c | 89 - src/pkg/runtime/cgo/gcc_linux_386.c | 80 - src/pkg/runtime/cgo/gcc_linux_amd64.c | 75 - src/pkg/runtime/cgo/gcc_linux_arm.c | 77 - src/pkg/runtime/cgo/gcc_netbsd_386.c | 76 - src/pkg/runtime/cgo/gcc_netbsd_amd64.c | 77 - src/pkg/runtime/cgo/gcc_netbsd_arm.c | 73 - src/pkg/runtime/cgo/gcc_openbsd_386.c | 165 - src/pkg/runtime/cgo/gcc_openbsd_amd64.c | 166 - src/pkg/runtime/cgo/gcc_setenv.c | 16 - src/pkg/runtime/cgo/gcc_util.c | 47 - src/pkg/runtime/cgo/gcc_windows_386.c | 62 - src/pkg/runtime/cgo/gcc_windows_amd64.c | 62 - src/pkg/runtime/cgo/iscgo.c | 15 - src/pkg/runtime/cgo/libcgo.h | 61 - src/pkg/runtime/cgo/netbsd.c | 13 - src/pkg/runtime/cgo/openbsd.c | 21 - src/pkg/runtime/cgo/setenv.c | 10 - src/pkg/runtime/cgocall.c | 322 - src/pkg/runtime/cgocall.h | 12 - src/pkg/runtime/chan.goc | 1155 -- src/pkg/runtime/chan.h | 75 - src/pkg/runtime/chan_test.go | 711 - src/pkg/runtime/closure_test.go | 53 - src/pkg/runtime/compiler.go | 13 - src/pkg/runtime/complex.goc | 58 - src/pkg/runtime/complex_test.go | 67 - src/pkg/runtime/cpuprof.goc | 433 - src/pkg/runtime/crash_cgo_test.go | 119 - src/pkg/runtime/crash_test.go | 366 - src/pkg/runtime/debug.go | 172 - src/pkg/runtime/debug/debug.c | 9 - src/pkg/runtime/debug/garbage.go | 153 - src/pkg/runtime/debug/garbage_test.go | 102 - src/pkg/runtime/debug/heapdump_test.go | 33 - src/pkg/runtime/debug/stack.go | 98 - src/pkg/runtime/debug/stack_test.go | 62 - src/pkg/runtime/defs.c | 14 - src/pkg/runtime/defs1_linux.go | 37 - src/pkg/runtime/defs2_linux.go | 146 - src/pkg/runtime/defs_arm_linux.go | 124 - src/pkg/runtime/defs_darwin.go | 179 - src/pkg/runtime/defs_darwin_386.h | 392 - src/pkg/runtime/defs_darwin_amd64.h | 395 - src/pkg/runtime/defs_dragonfly.go | 126 - src/pkg/runtime/defs_dragonfly_386.h | 198 - src/pkg/runtime/defs_dragonfly_amd64.h | 208 - src/pkg/runtime/defs_freebsd.go | 133 - src/pkg/runtime/defs_freebsd_386.h | 213 - src/pkg/runtime/defs_freebsd_amd64.h | 224 - src/pkg/runtime/defs_freebsd_arm.h | 186 - src/pkg/runtime/defs_linux.go | 123 - src/pkg/runtime/defs_linux_386.h | 211 - src/pkg/runtime/defs_linux_amd64.h | 254 - src/pkg/runtime/defs_linux_arm.h | 168 - src/pkg/runtime/defs_nacl_386.h | 63 - src/pkg/runtime/defs_nacl_amd64p32.h | 90 - src/pkg/runtime/defs_netbsd.go | 125 - src/pkg/runtime/defs_netbsd_386.go | 41 - src/pkg/runtime/defs_netbsd_386.h | 182 - src/pkg/runtime/defs_netbsd_amd64.go | 48 - src/pkg/runtime/defs_netbsd_amd64.h | 194 - src/pkg/runtime/defs_netbsd_arm.go | 39 - src/pkg/runtime/defs_netbsd_arm.h | 184 - src/pkg/runtime/defs_openbsd.go | 121 - src/pkg/runtime/defs_openbsd_386.h | 168 - src/pkg/runtime/defs_openbsd_amd64.h | 179 - src/pkg/runtime/defs_plan9_386.h | 29 - src/pkg/runtime/defs_plan9_amd64.h | 34 - src/pkg/runtime/defs_solaris.go | 156 - src/pkg/runtime/defs_solaris_amd64.go | 48 - src/pkg/runtime/defs_solaris_amd64.h | 254 - src/pkg/runtime/defs_windows.go | 70 - src/pkg/runtime/defs_windows_386.h | 113 - src/pkg/runtime/defs_windows_amd64.h | 128 - src/pkg/runtime/env_plan9.c | 42 - src/pkg/runtime/env_posix.c | 73 - src/pkg/runtime/error.go | 124 - src/pkg/runtime/export_futex_test.go | 13 - src/pkg/runtime/export_test.go | 92 - src/pkg/runtime/extern.go | 205 - src/pkg/runtime/float.c | 10 - src/pkg/runtime/funcdata.h | 24 - src/pkg/runtime/futex_test.go | 77 - src/pkg/runtime/gc_test.go | 236 - src/pkg/runtime/hash_test.go | 512 - src/pkg/runtime/hashmap.goc | 1078 -- src/pkg/runtime/hashmap.h | 147 - src/pkg/runtime/hashmap_fast.c | 233 - src/pkg/runtime/heapdump.c | 981 -- src/pkg/runtime/iface.goc | 620 - src/pkg/runtime/iface_test.go | 138 - src/pkg/runtime/lfstack.goc | 81 - src/pkg/runtime/lfstack_test.go | 136 - src/pkg/runtime/lock_futex.c | 201 - src/pkg/runtime/lock_sema.c | 266 - src/pkg/runtime/malloc.goc | 939 -- src/pkg/runtime/malloc.h | 643 - src/pkg/runtime/malloc1.go | 26 - src/pkg/runtime/malloc_test.go | 156 - src/pkg/runtime/mallocrand.go | 93 - src/pkg/runtime/mallocrep.go | 72 - src/pkg/runtime/mallocrep1.go | 144 - src/pkg/runtime/map_test.go | 477 - src/pkg/runtime/mapspeed_test.go | 300 - src/pkg/runtime/mcache.c | 130 - src/pkg/runtime/mcentral.c | 307 - src/pkg/runtime/mem.go | 75 - src/pkg/runtime/mem_darwin.c | 80 - src/pkg/runtime/mem_dragonfly.c | 103 - src/pkg/runtime/mem_freebsd.c | 98 - src/pkg/runtime/mem_linux.c | 160 - src/pkg/runtime/mem_nacl.c | 118 - src/pkg/runtime/mem_netbsd.c | 98 - src/pkg/runtime/mem_openbsd.c | 98 - src/pkg/runtime/mem_plan9.c | 82 - src/pkg/runtime/mem_solaris.c | 99 - src/pkg/runtime/mem_windows.c | 118 - src/pkg/runtime/memclr_386.s | 127 - src/pkg/runtime/memclr_amd64.s | 116 - src/pkg/runtime/memclr_arm.s | 87 - src/pkg/runtime/memclr_plan9_386.s | 50 - src/pkg/runtime/memclr_plan9_amd64.s | 48 - src/pkg/runtime/memmove_386.s | 175 - src/pkg/runtime/memmove_amd64.s | 207 - src/pkg/runtime/memmove_arm.s | 261 - src/pkg/runtime/memmove_linux_amd64_test.go | 61 - src/pkg/runtime/memmove_nacl_amd64p32.s | 46 - src/pkg/runtime/memmove_plan9_386.s | 127 - src/pkg/runtime/memmove_plan9_amd64.s | 126 - src/pkg/runtime/memmove_test.go | 243 - src/pkg/runtime/mfinal_test.go | 239 - src/pkg/runtime/mfixalloc.c | 64 - src/pkg/runtime/mgc0.c | 2892 ---- src/pkg/runtime/mgc0.go | 27 - src/pkg/runtime/mgc0.h | 87 - src/pkg/runtime/mheap.c | 932 -- src/pkg/runtime/mknacl.sh | 15 - src/pkg/runtime/mprof.goc | 527 - src/pkg/runtime/msize.c | 184 - src/pkg/runtime/netpoll.goc | 467 - src/pkg/runtime/netpoll_epoll.c | 102 - src/pkg/runtime/netpoll_kqueue.c | 111 - src/pkg/runtime/netpoll_nacl.c | 37 - src/pkg/runtime/netpoll_solaris.c | 268 - src/pkg/runtime/netpoll_stub.c | 18 - src/pkg/runtime/netpoll_windows.c | 163 - src/pkg/runtime/noasm_arm.goc | 74 - src/pkg/runtime/norace_test.go | 46 - src/pkg/runtime/os_darwin.c | 529 - src/pkg/runtime/os_darwin.h | 42 - src/pkg/runtime/os_dragonfly.c | 292 - src/pkg/runtime/os_dragonfly.h | 29 - src/pkg/runtime/os_freebsd.c | 300 - src/pkg/runtime/os_freebsd.h | 29 - src/pkg/runtime/os_freebsd_arm.c | 24 - src/pkg/runtime/os_linux.c | 342 - src/pkg/runtime/os_linux.h | 40 - src/pkg/runtime/os_linux_386.c | 38 - src/pkg/runtime/os_linux_arm.c | 80 - src/pkg/runtime/os_nacl.c | 278 - src/pkg/runtime/os_nacl.h | 162 - src/pkg/runtime/os_netbsd.c | 338 - src/pkg/runtime/os_netbsd.h | 30 - src/pkg/runtime/os_netbsd_386.c | 17 - src/pkg/runtime/os_netbsd_amd64.c | 18 - src/pkg/runtime/os_netbsd_arm.c | 34 - src/pkg/runtime/os_openbsd.c | 312 - src/pkg/runtime/os_openbsd.h | 25 - src/pkg/runtime/os_plan9.c | 418 - src/pkg/runtime/os_plan9.h | 89 - src/pkg/runtime/os_plan9_386.c | 150 - src/pkg/runtime/os_plan9_amd64.c | 158 - src/pkg/runtime/os_solaris.c | 583 - src/pkg/runtime/os_solaris.h | 51 - src/pkg/runtime/os_windows.c | 517 - src/pkg/runtime/os_windows.h | 36 - src/pkg/runtime/os_windows_386.c | 138 - src/pkg/runtime/os_windows_amd64.c | 144 - src/pkg/runtime/panic.c | 566 - src/pkg/runtime/parfor.c | 199 - src/pkg/runtime/parfor_test.go | 139 - src/pkg/runtime/pprof/pprof.go | 679 - src/pkg/runtime/pprof/pprof_test.go | 403 - src/pkg/runtime/print.c | 393 - src/pkg/runtime/proc.c | 3153 ----- src/pkg/runtime/proc_test.go | 476 - src/pkg/runtime/race.c | 292 - src/pkg/runtime/race.go | 31 - src/pkg/runtime/race.h | 34 - src/pkg/runtime/race/README | 12 - src/pkg/runtime/race/doc.go | 9 - src/pkg/runtime/race/output_test.go | 156 - src/pkg/runtime/race/race.go | 15 - src/pkg/runtime/race/race_darwin_amd64.syso | Bin 222964 -> 0 bytes src/pkg/runtime/race/race_linux_amd64.syso | Bin 243208 -> 0 bytes src/pkg/runtime/race/race_test.go | 172 - src/pkg/runtime/race/race_windows_amd64.syso | Bin 210859 -> 0 bytes src/pkg/runtime/race/testdata/atomic_test.go | 290 - src/pkg/runtime/race/testdata/cgo_test.go | 20 - src/pkg/runtime/race/testdata/cgo_test_main.go | 30 - src/pkg/runtime/race/testdata/chan_test.go | 659 - src/pkg/runtime/race/testdata/comp_test.go | 186 - src/pkg/runtime/race/testdata/finalizer_test.go | 67 - src/pkg/runtime/race/testdata/io_test.go | 69 - src/pkg/runtime/race/testdata/map_test.go | 240 - src/pkg/runtime/race/testdata/mop_test.go | 1957 --- src/pkg/runtime/race/testdata/mutex_test.go | 138 - src/pkg/runtime/race/testdata/regression_test.go | 194 - src/pkg/runtime/race/testdata/rwmutex_test.go | 134 - src/pkg/runtime/race/testdata/select_test.go | 286 - src/pkg/runtime/race/testdata/slice_test.go | 485 - src/pkg/runtime/race/testdata/sync_test.go | 216 - src/pkg/runtime/race/testdata/waitgroup_test.go | 352 - src/pkg/runtime/race0.c | 124 - src/pkg/runtime/race_amd64.s | 244 - src/pkg/runtime/rdebug.goc | 27 - src/pkg/runtime/rt0_darwin_386.s | 16 - src/pkg/runtime/rt0_darwin_amd64.s | 15 - src/pkg/runtime/rt0_dragonfly_386.s | 16 - src/pkg/runtime/rt0_dragonfly_amd64.s | 15 - src/pkg/runtime/rt0_freebsd_386.s | 16 - src/pkg/runtime/rt0_freebsd_amd64.s | 15 - src/pkg/runtime/rt0_freebsd_arm.s | 18 - src/pkg/runtime/rt0_linux_386.s | 25 - src/pkg/runtime/rt0_linux_amd64.s | 15 - src/pkg/runtime/rt0_linux_arm.s | 91 - src/pkg/runtime/rt0_nacl_386.s | 22 - src/pkg/runtime/rt0_nacl_amd64p32.s | 30 - src/pkg/runtime/rt0_netbsd_386.s | 16 - src/pkg/runtime/rt0_netbsd_amd64.s | 15 - src/pkg/runtime/rt0_netbsd_arm.s | 13 - src/pkg/runtime/rt0_openbsd_386.s | 16 - src/pkg/runtime/rt0_openbsd_amd64.s | 15 - src/pkg/runtime/rt0_plan9_386.s | 42 - src/pkg/runtime/rt0_plan9_amd64.s | 14 - src/pkg/runtime/rt0_solaris_amd64.s | 18 - src/pkg/runtime/rt0_windows_386.s | 20 - src/pkg/runtime/rt0_windows_amd64.s | 19 - src/pkg/runtime/rune.c | 231 - src/pkg/runtime/runtime-gdb.py | 478 - src/pkg/runtime/runtime.c | 396 - src/pkg/runtime/runtime.h | 1151 -- src/pkg/runtime/runtime1.goc | 128 - src/pkg/runtime/runtime_linux_test.go | 29 - src/pkg/runtime/runtime_test.go | 204 - src/pkg/runtime/runtime_unix_test.go | 56 - src/pkg/runtime/sema.goc | 294 - src/pkg/runtime/signal_386.c | 122 - src/pkg/runtime/signal_amd64x.c | 156 - src/pkg/runtime/signal_arm.c | 122 - src/pkg/runtime/signal_darwin_386.h | 23 - src/pkg/runtime/signal_darwin_amd64.h | 31 - src/pkg/runtime/signal_dragonfly_386.h | 23 - src/pkg/runtime/signal_dragonfly_amd64.h | 31 - src/pkg/runtime/signal_freebsd_386.h | 23 - src/pkg/runtime/signal_freebsd_amd64.h | 31 - src/pkg/runtime/signal_freebsd_arm.h | 28 - src/pkg/runtime/signal_linux_386.h | 24 - src/pkg/runtime/signal_linux_amd64.h | 32 - src/pkg/runtime/signal_linux_arm.h | 28 - src/pkg/runtime/signal_nacl_386.h | 23 - src/pkg/runtime/signal_nacl_amd64p32.h | 31 - src/pkg/runtime/signal_netbsd_386.h | 23 - src/pkg/runtime/signal_netbsd_amd64.h | 31 - src/pkg/runtime/signal_netbsd_arm.h | 30 - src/pkg/runtime/signal_openbsd_386.h | 23 - src/pkg/runtime/signal_openbsd_amd64.h | 31 - src/pkg/runtime/signal_solaris_amd64.h | 31 - src/pkg/runtime/signal_unix.c | 119 - src/pkg/runtime/signal_unix.h | 14 - src/pkg/runtime/signals_darwin.h | 50 - src/pkg/runtime/signals_dragonfly.h | 51 - src/pkg/runtime/signals_freebsd.h | 51 - src/pkg/runtime/signals_linux.h | 83 - src/pkg/runtime/signals_nacl.h | 50 - src/pkg/runtime/signals_netbsd.h | 51 - src/pkg/runtime/signals_openbsd.h | 51 - src/pkg/runtime/signals_plan9.h | 60 - src/pkg/runtime/signals_solaris.h | 94 - src/pkg/runtime/signals_windows.h | 3 - src/pkg/runtime/sigqueue.goc | 165 - src/pkg/runtime/slice.goc | 204 - src/pkg/runtime/softfloat64.go | 498 - src/pkg/runtime/softfloat64_test.go | 198 - src/pkg/runtime/softfloat_arm.c | 620 - src/pkg/runtime/sqrt.go | 150 - src/pkg/runtime/stack.c | 947 -- src/pkg/runtime/stack.h | 113 - src/pkg/runtime/stack_gen_test.go | 1473 -- src/pkg/runtime/stack_test.go | 283 - src/pkg/runtime/string.goc | 430 - src/pkg/runtime/string_test.go | 77 - src/pkg/runtime/symtab.goc | 332 - src/pkg/runtime/symtab_test.go | 47 - src/pkg/runtime/sys_arm.c | 35 - src/pkg/runtime/sys_darwin_386.s | 522 - src/pkg/runtime/sys_darwin_amd64.s | 480 - src/pkg/runtime/sys_dragonfly_386.s | 369 - src/pkg/runtime/sys_dragonfly_amd64.s | 330 - src/pkg/runtime/sys_freebsd_386.s | 381 - src/pkg/runtime/sys_freebsd_amd64.s | 345 - src/pkg/runtime/sys_freebsd_arm.s | 373 - src/pkg/runtime/sys_linux_386.s | 477 - src/pkg/runtime/sys_linux_amd64.s | 394 - src/pkg/runtime/sys_linux_arm.s | 448 - src/pkg/runtime/sys_nacl_386.s | 243 - src/pkg/runtime/sys_nacl_amd64p32.s | 413 - src/pkg/runtime/sys_netbsd_386.s | 374 - src/pkg/runtime/sys_netbsd_amd64.s | 344 - src/pkg/runtime/sys_netbsd_arm.s | 339 - src/pkg/runtime/sys_openbsd_386.s | 390 - src/pkg/runtime/sys_openbsd_amd64.s | 336 - src/pkg/runtime/sys_plan9_386.s | 199 - src/pkg/runtime/sys_plan9_amd64.s | 237 - src/pkg/runtime/sys_solaris_amd64.s | 267 - src/pkg/runtime/sys_windows_386.s | 363 - src/pkg/runtime/sys_windows_amd64.s | 377 - src/pkg/runtime/sys_x86.c | 57 - src/pkg/runtime/syscall_nacl.h | 71 - src/pkg/runtime/syscall_solaris.goc | 374 - src/pkg/runtime/syscall_windows.goc | 145 - src/pkg/runtime/syscall_windows_test.go | 451 - src/pkg/runtime/time.goc | 344 - src/pkg/runtime/time_plan9_386.c | 36 - src/pkg/runtime/traceback_arm.c | 357 - src/pkg/runtime/traceback_x86.c | 430 - src/pkg/runtime/type.go | 56 - src/pkg/runtime/type.h | 102 - src/pkg/runtime/typekind.h | 38 - src/pkg/runtime/vdso_linux_amd64.c | 337 - src/pkg/runtime/vlop_386.s | 54 - src/pkg/runtime/vlop_arm.s | 300 - src/pkg/runtime/vlop_arm_test.go | 70 - src/pkg/runtime/vlrt_386.c | 829 -- src/pkg/runtime/vlrt_arm.c | 807 -- src/pkg/sort/example_interface_test.go | 44 - src/pkg/sort/example_keys_test.go | 96 - src/pkg/sort/example_multi_test.go | 131 - src/pkg/sort/example_test.go | 24 - src/pkg/sort/example_wrapper_test.go | 77 - src/pkg/sort/export_test.go | 9 - src/pkg/sort/search.go | 112 - src/pkg/sort/search_test.go | 161 - src/pkg/sort/sort.go | 474 - src/pkg/sort/sort_test.go | 553 - src/pkg/strconv/atob.go | 35 - src/pkg/strconv/atob_test.go | 91 - src/pkg/strconv/atof.go | 540 - src/pkg/strconv/atof_test.go | 430 - src/pkg/strconv/atoi.go | 198 - src/pkg/strconv/atoi_test.go | 326 - src/pkg/strconv/decimal.go | 378 - src/pkg/strconv/decimal_test.go | 127 - src/pkg/strconv/extfloat.go | 668 - src/pkg/strconv/fp_test.go | 144 - src/pkg/strconv/ftoa.go | 475 - src/pkg/strconv/ftoa_test.go | 240 - src/pkg/strconv/internal_test.go | 19 - src/pkg/strconv/isprint.go | 562 - src/pkg/strconv/itoa.go | 131 - src/pkg/strconv/itoa_test.go | 160 - src/pkg/strconv/makeisprint.go | 165 - src/pkg/strconv/quote.go | 443 - src/pkg/strconv/quote_example_test.go | 35 - src/pkg/strconv/quote_test.go | 262 - src/pkg/strconv/strconv_test.go | 57 - src/pkg/strconv/testdata/testfp.txt | 181 - src/pkg/strings/example_test.go | 225 - src/pkg/strings/export_test.go | 45 - src/pkg/strings/reader.go | 144 - src/pkg/strings/reader_test.go | 159 - src/pkg/strings/replace.go | 549 - src/pkg/strings/replace_test.go | 506 - src/pkg/strings/search.go | 124 - src/pkg/strings/search_test.go | 90 - src/pkg/strings/strings.go | 725 - src/pkg/strings/strings.s | 5 - src/pkg/strings/strings_decl.go | 8 - src/pkg/strings/strings_test.go | 1176 -- src/pkg/sync/atomic/64bit_arm.go | 46 - src/pkg/sync/atomic/asm_386.s | 214 - src/pkg/sync/atomic/asm_amd64.s | 146 - src/pkg/sync/atomic/asm_amd64p32.s | 159 - src/pkg/sync/atomic/asm_arm.s | 197 - src/pkg/sync/atomic/asm_freebsd_arm.s | 109 - src/pkg/sync/atomic/asm_linux_arm.s | 236 - src/pkg/sync/atomic/asm_netbsd_arm.s | 109 - src/pkg/sync/atomic/atomic_linux_arm_test.go | 14 - src/pkg/sync/atomic/atomic_test.go | 1509 -- src/pkg/sync/atomic/doc.go | 151 - src/pkg/sync/atomic/export_linux_arm_test.go | 9 - src/pkg/sync/atomic/race.go | 276 - src/pkg/sync/cond.go | 118 - src/pkg/sync/cond_test.go | 255 - src/pkg/sync/example_test.go | 59 - src/pkg/sync/export_test.go | 9 - src/pkg/sync/mutex.go | 109 - src/pkg/sync/mutex_test.go | 136 - src/pkg/sync/once.go | 43 - src/pkg/sync/once_test.go | 70 - src/pkg/sync/pool.go | 223 - src/pkg/sync/pool_test.go | 151 - src/pkg/sync/race.go | 42 - src/pkg/sync/race0.go | 34 - src/pkg/sync/runtime.go | 36 - src/pkg/sync/runtime_sema_test.go | 72 - src/pkg/sync/rwmutex.go | 128 - src/pkg/sync/rwmutex_test.go | 212 - src/pkg/sync/waitgroup.go | 134 - src/pkg/sync/waitgroup_test.go | 148 - src/pkg/syscall/asm_darwin_386.s | 142 - src/pkg/syscall/asm_darwin_amd64.s | 106 - src/pkg/syscall/asm_dragonfly_386.s | 139 - src/pkg/syscall/asm_dragonfly_amd64.s | 133 - src/pkg/syscall/asm_freebsd_386.s | 142 - src/pkg/syscall/asm_freebsd_amd64.s | 141 - src/pkg/syscall/asm_freebsd_arm.s | 129 - src/pkg/syscall/asm_linux_386.s | 186 - src/pkg/syscall/asm_linux_amd64.s | 126 - src/pkg/syscall/asm_linux_arm.s | 155 - src/pkg/syscall/asm_nacl_386.s | 43 - src/pkg/syscall/asm_nacl_amd64p32.s | 41 - src/pkg/syscall/asm_netbsd_386.s | 142 - src/pkg/syscall/asm_netbsd_amd64.s | 135 - src/pkg/syscall/asm_netbsd_arm.s | 126 - src/pkg/syscall/asm_openbsd_386.s | 142 - src/pkg/syscall/asm_openbsd_amd64.s | 135 - src/pkg/syscall/asm_plan9_386.s | 164 - src/pkg/syscall/asm_plan9_amd64.s | 170 - src/pkg/syscall/asm_solaris_amd64.s | 7 - src/pkg/syscall/asm_windows_386.s | 7 - src/pkg/syscall/asm_windows_amd64.s | 7 - src/pkg/syscall/bpf_bsd.go | 169 - src/pkg/syscall/creds_test.go | 113 - src/pkg/syscall/dir_plan9.go | 212 - src/pkg/syscall/dll_windows.go | 279 - src/pkg/syscall/env_plan9.go | 142 - src/pkg/syscall/env_unix.go | 119 - src/pkg/syscall/env_windows.go | 82 - src/pkg/syscall/exec_bsd.go | 247 - src/pkg/syscall/exec_linux.go | 262 - src/pkg/syscall/exec_plan9.go | 650 - src/pkg/syscall/exec_solaris.go | 243 - src/pkg/syscall/exec_unix.go | 261 - src/pkg/syscall/exec_windows.go | 341 - src/pkg/syscall/fd_nacl.go | 326 - src/pkg/syscall/flock.go | 22 - src/pkg/syscall/flock_linux_32bit.go | 13 - src/pkg/syscall/fs_nacl.go | 815 -- src/pkg/syscall/lsf_linux.go | 78 - src/pkg/syscall/mkall.sh | 263 - src/pkg/syscall/mkall_windows.bat | 21 - src/pkg/syscall/mkerrors.sh | 433 - src/pkg/syscall/mksyscall.pl | 313 - src/pkg/syscall/mksyscall_solaris.pl | 279 - src/pkg/syscall/mksyscall_windows.go | 662 - src/pkg/syscall/mksysctl_openbsd.pl | 257 - src/pkg/syscall/mksysnum_darwin.pl | 32 - src/pkg/syscall/mksysnum_dragonfly.pl | 43 - src/pkg/syscall/mksysnum_freebsd.pl | 56 - src/pkg/syscall/mksysnum_linux.pl | 38 - src/pkg/syscall/mksysnum_netbsd.pl | 51 - src/pkg/syscall/mksysnum_openbsd.pl | 43 - src/pkg/syscall/mksysnum_plan9.sh | 25 - src/pkg/syscall/mmap_unix_test.go | 22 - src/pkg/syscall/net_nacl.go | 912 -- src/pkg/syscall/netlink_linux.go | 177 - src/pkg/syscall/race.go | 30 - src/pkg/syscall/race0.go | 25 - src/pkg/syscall/route_bsd.go | 224 - src/pkg/syscall/route_darwin.go | 61 - src/pkg/syscall/route_dragonfly.go | 72 - src/pkg/syscall/route_freebsd.go | 78 - src/pkg/syscall/route_freebsd_32bit.go | 24 - src/pkg/syscall/route_freebsd_64bit.go | 14 - src/pkg/syscall/route_netbsd.go | 35 - src/pkg/syscall/route_openbsd.go | 35 - src/pkg/syscall/security_windows.go | 384 - src/pkg/syscall/so_solaris.go | 260 - src/pkg/syscall/sockcmsg_linux.go | 36 - src/pkg/syscall/sockcmsg_unix.go | 103 - src/pkg/syscall/srpc_nacl.go | 822 -- src/pkg/syscall/str.go | 20 - src/pkg/syscall/syscall.go | 81 - src/pkg/syscall/syscall_bsd.go | 553 - src/pkg/syscall/syscall_bsd_test.go | 34 - src/pkg/syscall/syscall_darwin.go | 508 - src/pkg/syscall/syscall_darwin_386.go | 70 - src/pkg/syscall/syscall_darwin_amd64.go | 70 - src/pkg/syscall/syscall_dragonfly.go | 408 - src/pkg/syscall/syscall_dragonfly_386.go | 58 - src/pkg/syscall/syscall_dragonfly_amd64.go | 58 - src/pkg/syscall/syscall_freebsd.go | 430 - src/pkg/syscall/syscall_freebsd_386.go | 58 - src/pkg/syscall/syscall_freebsd_amd64.go | 58 - src/pkg/syscall/syscall_freebsd_arm.go | 58 - src/pkg/syscall/syscall_linux.go | 1025 -- src/pkg/syscall/syscall_linux_386.go | 356 - src/pkg/syscall/syscall_linux_amd64.go | 115 - src/pkg/syscall/syscall_linux_arm.go | 196 - src/pkg/syscall/syscall_nacl.go | 311 - src/pkg/syscall/syscall_nacl_386.go | 32 - src/pkg/syscall/syscall_nacl_amd64p32.go | 32 - src/pkg/syscall/syscall_netbsd.go | 489 - src/pkg/syscall/syscall_netbsd_386.go | 42 - src/pkg/syscall/syscall_netbsd_amd64.go | 42 - src/pkg/syscall/syscall_netbsd_arm.go | 42 - src/pkg/syscall/syscall_no_getwd.go | 11 - src/pkg/syscall/syscall_openbsd.go | 299 - src/pkg/syscall/syscall_openbsd_386.go | 42 - src/pkg/syscall/syscall_openbsd_amd64.go | 42 - src/pkg/syscall/syscall_plan9.go | 344 - src/pkg/syscall/syscall_plan9_386.go | 32 - src/pkg/syscall/syscall_plan9_amd64.go | 14 - src/pkg/syscall/syscall_solaris.go | 523 - src/pkg/syscall/syscall_solaris_amd64.go | 37 - src/pkg/syscall/syscall_test.go | 30 - src/pkg/syscall/syscall_unix.go | 299 - src/pkg/syscall/syscall_unix_test.go | 314 - src/pkg/syscall/syscall_windows.go | 936 -- src/pkg/syscall/syscall_windows_386.go | 5 - src/pkg/syscall/syscall_windows_amd64.go | 5 - src/pkg/syscall/syscall_windows_test.go | 72 - src/pkg/syscall/tables_nacl.go | 324 - src/pkg/syscall/time_nacl_386.s | 11 - src/pkg/syscall/time_nacl_amd64p32.s | 11 - src/pkg/syscall/types_darwin.go | 243 - src/pkg/syscall/types_dragonfly.go | 242 - src/pkg/syscall/types_freebsd.go | 342 - src/pkg/syscall/types_linux.go | 484 - src/pkg/syscall/types_netbsd.go | 232 - src/pkg/syscall/types_openbsd.go | 244 - src/pkg/syscall/types_plan9.c | 115 - src/pkg/syscall/types_solaris.go | 222 - src/pkg/syscall/unzip_nacl.go | 685 - src/pkg/syscall/zerrors_darwin_386.go | 1421 -- src/pkg/syscall/zerrors_darwin_amd64.go | 1421 -- src/pkg/syscall/zerrors_dragonfly_386.go | 1526 -- src/pkg/syscall/zerrors_dragonfly_amd64.go | 1526 -- src/pkg/syscall/zerrors_freebsd_386.go | 1715 --- src/pkg/syscall/zerrors_freebsd_amd64.go | 1716 --- src/pkg/syscall/zerrors_freebsd_arm.go | 1715 --- src/pkg/syscall/zerrors_linux_386.go | 1544 --- src/pkg/syscall/zerrors_linux_amd64.go | 1545 --- src/pkg/syscall/zerrors_linux_arm.go | 1558 --- src/pkg/syscall/zerrors_netbsd_386.go | 1708 --- src/pkg/syscall/zerrors_netbsd_amd64.go | 1698 --- src/pkg/syscall/zerrors_netbsd_arm.go | 1684 --- src/pkg/syscall/zerrors_openbsd_386.go | 1580 --- src/pkg/syscall/zerrors_openbsd_amd64.go | 1579 --- src/pkg/syscall/zerrors_plan9_386.go | 48 - src/pkg/syscall/zerrors_plan9_amd64.go | 48 - src/pkg/syscall/zerrors_solaris_amd64.go | 1414 -- src/pkg/syscall/zerrors_windows.go | 283 - src/pkg/syscall/zerrors_windows_386.go | 5 - src/pkg/syscall/zerrors_windows_amd64.go | 5 - src/pkg/syscall/zsyscall_darwin_386.go | 1387 -- src/pkg/syscall/zsyscall_darwin_amd64.go | 1387 -- src/pkg/syscall/zsyscall_dragonfly_386.go | 1287 -- src/pkg/syscall/zsyscall_dragonfly_amd64.go | 1287 -- src/pkg/syscall/zsyscall_freebsd_386.go | 1298 -- src/pkg/syscall/zsyscall_freebsd_amd64.go | 1298 -- src/pkg/syscall/zsyscall_freebsd_arm.go | 1298 -- src/pkg/syscall/zsyscall_linux_386.go | 1737 --- src/pkg/syscall/zsyscall_linux_amd64.go | 1930 --- src/pkg/syscall/zsyscall_linux_arm.go | 1885 --- src/pkg/syscall/zsyscall_nacl_386.go | 63 - src/pkg/syscall/zsyscall_nacl_amd64p32.go | 63 - src/pkg/syscall/zsyscall_netbsd_386.go | 1224 -- src/pkg/syscall/zsyscall_netbsd_amd64.go | 1224 -- src/pkg/syscall/zsyscall_netbsd_arm.go | 1224 -- src/pkg/syscall/zsyscall_openbsd_386.go | 1262 -- src/pkg/syscall/zsyscall_openbsd_amd64.go | 1262 -- src/pkg/syscall/zsyscall_plan9_386.go | 282 - src/pkg/syscall/zsyscall_plan9_amd64.go | 282 - src/pkg/syscall/zsyscall_solaris_amd64.go | 883 -- src/pkg/syscall/zsyscall_windows_386.go | 1760 --- src/pkg/syscall/zsyscall_windows_amd64.go | 1760 --- src/pkg/syscall/zsysctl_openbsd.go | 270 - src/pkg/syscall/zsysnum_darwin_386.go | 360 - src/pkg/syscall/zsysnum_darwin_amd64.go | 360 - src/pkg/syscall/zsysnum_dragonfly_386.go | 302 - src/pkg/syscall/zsysnum_dragonfly_amd64.go | 302 - src/pkg/syscall/zsysnum_freebsd_386.go | 348 - src/pkg/syscall/zsysnum_freebsd_amd64.go | 348 - src/pkg/syscall/zsysnum_freebsd_arm.go | 348 - src/pkg/syscall/zsysnum_linux_386.go | 345 - src/pkg/syscall/zsysnum_linux_amd64.go | 310 - src/pkg/syscall/zsysnum_linux_arm.go | 354 - src/pkg/syscall/zsysnum_netbsd_386.go | 271 - src/pkg/syscall/zsysnum_netbsd_amd64.go | 271 - src/pkg/syscall/zsysnum_netbsd_arm.go | 271 - src/pkg/syscall/zsysnum_openbsd_386.go | 205 - src/pkg/syscall/zsysnum_openbsd_amd64.go | 205 - src/pkg/syscall/zsysnum_plan9_386.go | 47 - src/pkg/syscall/zsysnum_plan9_amd64.go | 48 - src/pkg/syscall/zsysnum_solaris_amd64.go | 11 - src/pkg/syscall/zsysnum_windows_386.go | 3 - src/pkg/syscall/zsysnum_windows_amd64.go | 3 - src/pkg/syscall/ztypes_darwin_386.go | 446 - src/pkg/syscall/ztypes_darwin_amd64.go | 456 - src/pkg/syscall/ztypes_dragonfly_386.go | 435 - src/pkg/syscall/ztypes_dragonfly_amd64.go | 441 - src/pkg/syscall/ztypes_freebsd_386.go | 492 - src/pkg/syscall/ztypes_freebsd_amd64.go | 495 - src/pkg/syscall/ztypes_freebsd_arm.go | 495 - src/pkg/syscall/ztypes_linux_386.go | 690 - src/pkg/syscall/ztypes_linux_amd64.go | 708 - src/pkg/syscall/ztypes_linux_arm.go | 679 - src/pkg/syscall/ztypes_netbsd_386.go | 394 - src/pkg/syscall/ztypes_netbsd_amd64.go | 401 - src/pkg/syscall/ztypes_netbsd_arm.go | 399 - src/pkg/syscall/ztypes_openbsd_386.go | 439 - src/pkg/syscall/ztypes_openbsd_amd64.go | 446 - src/pkg/syscall/ztypes_plan9_386.go | 75 - src/pkg/syscall/ztypes_plan9_amd64.go | 75 - src/pkg/syscall/ztypes_solaris_amd64.go | 365 - src/pkg/syscall/ztypes_windows.go | 1044 -- src/pkg/syscall/ztypes_windows_386.go | 22 - src/pkg/syscall/ztypes_windows_amd64.go | 22 - src/pkg/testing/allocs.go | 45 - src/pkg/testing/benchmark.go | 444 - src/pkg/testing/benchmark_test.go | 111 - src/pkg/testing/cover.go | 86 - src/pkg/testing/example.go | 100 - src/pkg/testing/export_test.go | 10 - src/pkg/testing/iotest/logger.go | 54 - src/pkg/testing/iotest/reader.go | 88 - src/pkg/testing/iotest/writer.go | 35 - src/pkg/testing/quick/quick.go | 358 - src/pkg/testing/quick/quick_test.go | 249 - src/pkg/testing/testing.go | 657 - src/pkg/text/scanner/scanner.go | 674 - src/pkg/text/scanner/scanner_test.go | 596 - src/pkg/text/tabwriter/example_test.go | 38 - src/pkg/text/tabwriter/tabwriter.go | 558 - src/pkg/text/tabwriter/tabwriter_test.go | 652 - src/pkg/text/template/doc.go | 405 - src/pkg/text/template/example_test.go | 71 - src/pkg/text/template/examplefiles_test.go | 182 - src/pkg/text/template/examplefunc_test.go | 54 - src/pkg/text/template/exec.go | 838 -- src/pkg/text/template/exec_test.go | 989 -- src/pkg/text/template/funcs.go | 580 - src/pkg/text/template/helper.go | 108 - src/pkg/text/template/multi_test.go | 292 - src/pkg/text/template/parse/lex.go | 551 - src/pkg/text/template/parse/lex_test.go | 465 - src/pkg/text/template/parse/node.go | 722 - src/pkg/text/template/parse/parse.go | 671 - src/pkg/text/template/parse/parse_test.go | 420 - src/pkg/text/template/template.go | 217 - src/pkg/text/template/testdata/file1.tmpl | 2 - src/pkg/text/template/testdata/file2.tmpl | 2 - src/pkg/text/template/testdata/tmpl1.tmpl | 3 - src/pkg/text/template/testdata/tmpl2.tmpl | 3 - src/pkg/time/Makefile | 9 - src/pkg/time/example_test.go | 160 - src/pkg/time/export_test.go | 24 - src/pkg/time/export_windows_test.go | 10 - src/pkg/time/format.go | 1247 -- src/pkg/time/format_test.go | 517 - src/pkg/time/genzabbrs.go | 145 - src/pkg/time/internal_test.go | 92 - src/pkg/time/sleep.go | 122 - src/pkg/time/sleep_test.go | 393 - src/pkg/time/sys_plan9.go | 76 - src/pkg/time/sys_unix.go | 76 - src/pkg/time/sys_windows.go | 73 - src/pkg/time/tick.go | 56 - src/pkg/time/tick_test.go | 78 - src/pkg/time/time.go | 1206 -- src/pkg/time/time_test.go | 1081 -- src/pkg/time/zoneinfo.go | 287 - src/pkg/time/zoneinfo_abbrs_windows.go | 115 - src/pkg/time/zoneinfo_plan9.go | 160 - src/pkg/time/zoneinfo_read.go | 343 - src/pkg/time/zoneinfo_test.go | 63 - src/pkg/time/zoneinfo_unix.go | 84 - src/pkg/time/zoneinfo_windows.go | 270 - src/pkg/time/zoneinfo_windows_test.go | 35 - src/pkg/unicode/Makefile | 16 - src/pkg/unicode/casetables.go | 20 - src/pkg/unicode/digit.go | 13 - src/pkg/unicode/digit_test.go | 126 - src/pkg/unicode/graphic.go | 144 - src/pkg/unicode/graphic_test.go | 122 - src/pkg/unicode/letter.go | 354 - src/pkg/unicode/letter_test.go | 535 - src/pkg/unicode/maketables.go | 1320 -- src/pkg/unicode/script_test.go | 264 - src/pkg/unicode/tables.go | 6391 --------- src/pkg/unicode/utf16/export_test.go | 11 - src/pkg/unicode/utf16/utf16.go | 108 - src/pkg/unicode/utf16/utf16_test.go | 149 - src/pkg/unicode/utf8/example_test.go | 196 - src/pkg/unicode/utf8/utf8.go | 435 - src/pkg/unicode/utf8/utf8_test.go | 444 - src/pkg/unsafe/unsafe.go | 37 - src/race.bash | 7 +- src/reflect/all_test.go | 4158 ++++++ src/reflect/asm_386.s | 30 + src/reflect/asm_amd64.s | 30 + src/reflect/asm_amd64p32.s | 30 + src/reflect/asm_arm.s | 30 + src/reflect/deepequal.go | 145 + src/reflect/example_test.go | 66 + src/reflect/export_test.go | 38 + src/reflect/makefunc.go | 129 + src/reflect/set_test.go | 211 + src/reflect/tostring_test.go | 95 + src/reflect/type.go | 1929 +++ src/reflect/value.go | 2443 ++++ src/regexp/all_test.go | 656 + src/regexp/example_test.go | 148 + src/regexp/exec.go | 452 + src/regexp/exec2_test.go | 20 + src/regexp/exec_test.go | 715 + src/regexp/find_test.go | 498 + src/regexp/onepass.go | 581 + src/regexp/onepass_test.go | 208 + src/regexp/regexp.go | 1120 ++ src/regexp/syntax/compile.go | 289 + src/regexp/syntax/doc.go | 131 + src/regexp/syntax/make_perl_groups.pl | 107 + src/regexp/syntax/parse.go | 1902 +++ src/regexp/syntax/parse_test.go | 572 + src/regexp/syntax/perl_groups.go | 134 + src/regexp/syntax/prog.go | 345 + src/regexp/syntax/prog_test.go | 114 + src/regexp/syntax/regexp.go | 319 + src/regexp/syntax/simplify.go | 151 + src/regexp/syntax/simplify_test.go | 151 + src/regexp/testdata/README | 23 + src/regexp/testdata/basic.dat | 221 + src/regexp/testdata/nullsubexpr.dat | 79 + src/regexp/testdata/re2-exhaustive.txt.bz2 | Bin 0 -> 394016 bytes src/regexp/testdata/re2-search.txt | 3667 +++++ src/regexp/testdata/repetition.dat | 163 + src/regexp/testdata/testregex.c | 2286 +++ src/run.bash | 65 +- src/run.rc | 2 +- src/runtime/Makefile | 5 + src/runtime/alg.go | 352 + src/runtime/append_test.go | 190 + src/runtime/arch_386.go | 8 + src/runtime/arch_386.h | 17 + src/runtime/arch_amd64.go | 8 + src/runtime/arch_amd64.h | 25 + src/runtime/arch_amd64p32.go | 8 + src/runtime/arch_amd64p32.h | 17 + src/runtime/arch_arm.go | 8 + src/runtime/arch_arm.h | 17 + src/runtime/asm.s | 14 + src/runtime/asm_386.s | 2292 +++ src/runtime/asm_amd64.s | 2237 +++ src/runtime/asm_amd64p32.s | 1087 ++ src/runtime/asm_arm.s | 1328 ++ src/runtime/atomic.go | 51 + src/runtime/atomic_386.c | 46 + src/runtime/atomic_amd64x.c | 29 + src/runtime/atomic_arm.go | 155 + src/runtime/cgo/asm_386.s | 31 + src/runtime/cgo/asm_amd64.s | 47 + src/runtime/cgo/asm_arm.s | 24 + src/runtime/cgo/asm_nacl_amd64p32.s | 13 + src/runtime/cgo/callbacks.c | 83 + src/runtime/cgo/cgo.go | 26 + src/runtime/cgo/dragonfly.c | 19 + src/runtime/cgo/freebsd.c | 19 + src/runtime/cgo/gcc_386.S | 45 + src/runtime/cgo/gcc_amd64.S | 48 + src/runtime/cgo/gcc_android.c | 31 + src/runtime/cgo/gcc_android_arm.c | 43 + src/runtime/cgo/gcc_arm.S | 42 + src/runtime/cgo/gcc_darwin_386.c | 148 + src/runtime/cgo/gcc_darwin_amd64.c | 119 + src/runtime/cgo/gcc_dragonfly_386.c | 70 + src/runtime/cgo/gcc_dragonfly_amd64.c | 70 + src/runtime/cgo/gcc_fatalf.c | 23 + src/runtime/cgo/gcc_freebsd_386.c | 70 + src/runtime/cgo/gcc_freebsd_amd64.c | 70 + src/runtime/cgo/gcc_freebsd_arm.c | 82 + src/runtime/cgo/gcc_linux_386.c | 72 + src/runtime/cgo/gcc_linux_amd64.c | 67 + src/runtime/cgo/gcc_linux_arm.c | 73 + src/runtime/cgo/gcc_netbsd_386.c | 69 + src/runtime/cgo/gcc_netbsd_amd64.c | 70 + src/runtime/cgo/gcc_netbsd_arm.c | 66 + src/runtime/cgo/gcc_openbsd_386.c | 158 + src/runtime/cgo/gcc_openbsd_amd64.c | 159 + src/runtime/cgo/gcc_setenv.c | 23 + src/runtime/cgo/gcc_util.c | 47 + src/runtime/cgo/gcc_windows_386.c | 61 + src/runtime/cgo/gcc_windows_amd64.c | 61 + src/runtime/cgo/iscgo.c | 15 + src/runtime/cgo/libcgo.h | 65 + src/runtime/cgo/netbsd.c | 19 + src/runtime/cgo/openbsd.c | 27 + src/runtime/cgo/setenv.c | 13 + src/runtime/cgocall.go | 279 + src/runtime/cgocall.h | 13 + src/runtime/cgocallback.go | 40 + src/runtime/chan.go | 655 + src/runtime/chan.h | 68 + src/runtime/chan_test.go | 820 ++ src/runtime/closure_test.go | 53 + src/runtime/compiler.go | 13 + src/runtime/complex.go | 52 + src/runtime/complex_test.go | 67 + src/runtime/cpuprof.go | 425 + src/runtime/crash_cgo_test.go | 196 + src/runtime/crash_test.go | 515 + src/runtime/debug.go | 70 + src/runtime/debug/debug.s | 9 + src/runtime/debug/garbage.go | 159 + src/runtime/debug/garbage_test.go | 115 + src/runtime/debug/heapdump_test.go | 33 + src/runtime/debug/stack.go | 98 + src/runtime/debug/stack_test.go | 62 + src/runtime/debug/stubs.go | 20 + src/runtime/debug/stubs.s | 21 + src/runtime/defs.c | 15 + src/runtime/defs1_linux.go | 37 + src/runtime/defs2_linux.go | 146 + src/runtime/defs_android_arm.h | 3 + src/runtime/defs_arm_linux.go | 124 + src/runtime/defs_darwin.go | 179 + src/runtime/defs_darwin_386.h | 392 + src/runtime/defs_darwin_amd64.h | 395 + src/runtime/defs_dragonfly.go | 126 + src/runtime/defs_dragonfly_386.h | 198 + src/runtime/defs_dragonfly_amd64.h | 208 + src/runtime/defs_freebsd.go | 133 + src/runtime/defs_freebsd_386.h | 213 + src/runtime/defs_freebsd_amd64.h | 224 + src/runtime/defs_freebsd_arm.h | 186 + src/runtime/defs_linux.go | 124 + src/runtime/defs_linux_386.h | 211 + src/runtime/defs_linux_amd64.h | 254 + src/runtime/defs_linux_arm.h | 168 + src/runtime/defs_nacl_386.h | 63 + src/runtime/defs_nacl_amd64p32.h | 90 + src/runtime/defs_nacl_arm.h | 70 + src/runtime/defs_netbsd.go | 125 + src/runtime/defs_netbsd_386.go | 41 + src/runtime/defs_netbsd_386.h | 182 + src/runtime/defs_netbsd_amd64.go | 48 + src/runtime/defs_netbsd_amd64.h | 194 + src/runtime/defs_netbsd_arm.go | 39 + src/runtime/defs_netbsd_arm.h | 184 + src/runtime/defs_openbsd.go | 121 + src/runtime/defs_openbsd_386.h | 168 + src/runtime/defs_openbsd_amd64.h | 179 + src/runtime/defs_plan9_386.h | 26 + src/runtime/defs_plan9_amd64.h | 34 + src/runtime/defs_solaris.go | 156 + src/runtime/defs_solaris_amd64.go | 48 + src/runtime/defs_solaris_amd64.h | 254 + src/runtime/defs_windows.go | 73 + src/runtime/defs_windows_386.h | 116 + src/runtime/defs_windows_amd64.h | 131 + src/runtime/env_plan9.go | 56 + src/runtime/env_posix.go | 63 + src/runtime/error.go | 107 + src/runtime/export_futex_test.go | 10 + src/runtime/export_test.go | 165 + src/runtime/extern.go | 168 + src/runtime/float.c | 10 + src/runtime/funcdata.h | 60 + src/runtime/futex_test.go | 77 + src/runtime/gc_test.go | 292 + src/runtime/gcinfo_test.go | 193 + src/runtime/hash_test.go | 572 + src/runtime/hashmap.go | 953 ++ src/runtime/hashmap_fast.go | 379 + src/runtime/heapdump.c | 864 ++ src/runtime/iface.go | 439 + src/runtime/iface_test.go | 138 + src/runtime/lfstack.c | 87 + src/runtime/lfstack_test.go | 136 + src/runtime/lock_futex.go | 205 + src/runtime/lock_sema.go | 270 + src/runtime/malloc.c | 396 + src/runtime/malloc.go | 837 ++ src/runtime/malloc.h | 621 + src/runtime/malloc_test.go | 189 + src/runtime/map_test.go | 537 + src/runtime/mapspeed_test.go | 300 + src/runtime/mcache.c | 115 + src/runtime/mcentral.c | 214 + src/runtime/mem.go | 108 + src/runtime/mem_darwin.c | 82 + src/runtime/mem_dragonfly.c | 105 + src/runtime/mem_freebsd.c | 100 + src/runtime/mem_linux.c | 162 + src/runtime/mem_nacl.c | 120 + src/runtime/mem_netbsd.c | 100 + src/runtime/mem_openbsd.c | 100 + src/runtime/mem_plan9.c | 121 + src/runtime/mem_solaris.c | 101 + src/runtime/mem_windows.c | 132 + src/runtime/memclr_386.s | 130 + src/runtime/memclr_amd64.s | 119 + src/runtime/memclr_arm.s | 87 + src/runtime/memclr_plan9_386.s | 51 + src/runtime/memclr_plan9_amd64.s | 21 + src/runtime/memmove_386.s | 176 + src/runtime/memmove_amd64.s | 252 + src/runtime/memmove_arm.s | 261 + src/runtime/memmove_linux_amd64_test.go | 61 + src/runtime/memmove_nacl_amd64p32.s | 46 + src/runtime/memmove_plan9_386.s | 128 + src/runtime/memmove_plan9_amd64.s | 127 + src/runtime/memmove_test.go | 295 + src/runtime/mfinal_test.go | 246 + src/runtime/mfixalloc.c | 64 + src/runtime/mgc0.c | 2010 +++ src/runtime/mgc0.go | 152 + src/runtime/mgc0.h | 78 + src/runtime/mheap.c | 889 ++ src/runtime/mknacl.sh | 15 + src/runtime/mprof.go | 672 + src/runtime/msize.c | 184 + src/runtime/netpoll.go | 455 + src/runtime/netpoll_epoll.go | 97 + src/runtime/netpoll_kqueue.go | 101 + src/runtime/netpoll_nacl.go | 26 + src/runtime/netpoll_solaris.c | 264 + src/runtime/netpoll_stub.c | 18 + src/runtime/netpoll_windows.c | 163 + src/runtime/noasm_arm.go | 54 + src/runtime/norace_test.go | 46 + src/runtime/os_android.c | 16 + src/runtime/os_android.h | 1 + src/runtime/os_darwin.c | 567 + src/runtime/os_darwin.go | 24 + src/runtime/os_darwin.h | 43 + src/runtime/os_dragonfly.c | 312 + src/runtime/os_dragonfly.go | 20 + src/runtime/os_dragonfly.h | 30 + src/runtime/os_freebsd.c | 320 + src/runtime/os_freebsd.go | 17 + src/runtime/os_freebsd.h | 29 + src/runtime/os_freebsd_arm.c | 24 + src/runtime/os_linux.c | 342 + src/runtime/os_linux.go | 17 + src/runtime/os_linux.h | 41 + src/runtime/os_linux_386.c | 38 + src/runtime/os_linux_arm.c | 80 + src/runtime/os_nacl.c | 312 + src/runtime/os_nacl.go | 39 + src/runtime/os_nacl.h | 162 + src/runtime/os_nacl_arm.c | 24 + src/runtime/os_netbsd.c | 368 + src/runtime/os_netbsd.go | 20 + src/runtime/os_netbsd.h | 31 + src/runtime/os_netbsd_386.c | 17 + src/runtime/os_netbsd_amd64.c | 18 + src/runtime/os_netbsd_arm.c | 34 + src/runtime/os_openbsd.c | 309 + src/runtime/os_openbsd.go | 17 + src/runtime/os_openbsd.h | 26 + src/runtime/os_plan9.c | 362 + src/runtime/os_plan9.go | 103 + src/runtime/os_plan9.h | 93 + src/runtime/os_plan9_386.c | 150 + src/runtime/os_plan9_amd64.c | 158 + src/runtime/os_solaris.c | 557 + src/runtime/os_solaris.go | 100 + src/runtime/os_solaris.h | 55 + src/runtime/os_windows.c | 636 + src/runtime/os_windows.go | 58 + src/runtime/os_windows.h | 42 + src/runtime/os_windows_386.c | 128 + src/runtime/os_windows_386.go | 11 + src/runtime/os_windows_amd64.c | 150 + src/runtime/os_windows_amd64.go | 11 + src/runtime/panic.c | 200 + src/runtime/panic.go | 505 + src/runtime/parfor.c | 226 + src/runtime/parfor_test.go | 139 + src/runtime/pprof/mprof_test.go | 99 + src/runtime/pprof/pprof.go | 673 + src/runtime/pprof/pprof_test.go | 452 + src/runtime/print1.go | 323 + src/runtime/proc.c | 3521 +++++ src/runtime/proc.go | 246 + src/runtime/proc_test.go | 480 + src/runtime/race.c | 347 + src/runtime/race.go | 127 + src/runtime/race.h | 34 + src/runtime/race/README | 12 + src/runtime/race/doc.go | 9 + src/runtime/race/output_test.go | 156 + src/runtime/race/race.go | 15 + src/runtime/race/race_darwin_amd64.syso | Bin 0 -> 278328 bytes src/runtime/race/race_freebsd_amd64.syso | Bin 0 -> 294224 bytes src/runtime/race/race_linux_amd64.syso | Bin 0 -> 298064 bytes src/runtime/race/race_test.go | 172 + src/runtime/race/race_unix_test.go | 30 + src/runtime/race/race_windows_amd64.syso | Bin 0 -> 292311 bytes src/runtime/race/testdata/atomic_test.go | 288 + src/runtime/race/testdata/cgo_test.go | 20 + src/runtime/race/testdata/cgo_test_main.go | 30 + src/runtime/race/testdata/chan_test.go | 659 + src/runtime/race/testdata/comp_test.go | 186 + src/runtime/race/testdata/finalizer_test.go | 67 + src/runtime/race/testdata/io_test.go | 69 + src/runtime/race/testdata/map_test.go | 333 + src/runtime/race/testdata/mop_test.go | 1957 +++ src/runtime/race/testdata/mutex_test.go | 138 + src/runtime/race/testdata/regression_test.go | 194 + src/runtime/race/testdata/rwmutex_test.go | 134 + src/runtime/race/testdata/select_test.go | 286 + src/runtime/race/testdata/slice_test.go | 485 + src/runtime/race/testdata/sync_test.go | 216 + src/runtime/race/testdata/waitgroup_test.go | 352 + src/runtime/race0.go | 37 + src/runtime/race_amd64.s | 414 + src/runtime/rdebug.go | 37 + src/runtime/rt0_android_arm.s | 11 + src/runtime/rt0_darwin_386.s | 16 + src/runtime/rt0_darwin_amd64.s | 15 + src/runtime/rt0_dragonfly_386.s | 16 + src/runtime/rt0_dragonfly_amd64.s | 15 + src/runtime/rt0_freebsd_386.s | 16 + src/runtime/rt0_freebsd_amd64.s | 15 + src/runtime/rt0_freebsd_arm.s | 18 + src/runtime/rt0_linux_386.s | 25 + src/runtime/rt0_linux_amd64.s | 15 + src/runtime/rt0_linux_arm.s | 91 + src/runtime/rt0_nacl_386.s | 22 + src/runtime/rt0_nacl_amd64p32.s | 30 + src/runtime/rt0_nacl_arm.s | 20 + src/runtime/rt0_netbsd_386.s | 16 + src/runtime/rt0_netbsd_amd64.s | 15 + src/runtime/rt0_netbsd_arm.s | 13 + src/runtime/rt0_openbsd_386.s | 16 + src/runtime/rt0_openbsd_amd64.s | 15 + src/runtime/rt0_plan9_386.s | 23 + src/runtime/rt0_plan9_amd64.s | 21 + src/runtime/rt0_solaris_amd64.s | 18 + src/runtime/rt0_windows_386.s | 20 + src/runtime/rt0_windows_amd64.s | 19 + src/runtime/rune.go | 219 + src/runtime/runtime-gdb.py | 478 + src/runtime/runtime.c | 399 + src/runtime/runtime.go | 60 + src/runtime/runtime.h | 1132 ++ src/runtime/runtime_linux_test.go | 29 + src/runtime/runtime_test.go | 249 + src/runtime/runtime_unix_test.go | 56 + src/runtime/select.go | 651 + src/runtime/sema.go | 275 + src/runtime/signal.c | 25 + src/runtime/signal_386.c | 122 + src/runtime/signal_amd64x.c | 156 + src/runtime/signal_android_386.h | 1 + src/runtime/signal_android_arm.h | 1 + src/runtime/signal_arm.c | 121 + src/runtime/signal_darwin_386.h | 23 + src/runtime/signal_darwin_amd64.h | 31 + src/runtime/signal_dragonfly_386.h | 23 + src/runtime/signal_dragonfly_amd64.h | 31 + src/runtime/signal_freebsd_386.h | 23 + src/runtime/signal_freebsd_amd64.h | 31 + src/runtime/signal_freebsd_arm.h | 28 + src/runtime/signal_linux_386.h | 24 + src/runtime/signal_linux_amd64.h | 32 + src/runtime/signal_linux_arm.h | 28 + src/runtime/signal_nacl_386.h | 23 + src/runtime/signal_nacl_amd64p32.h | 31 + src/runtime/signal_nacl_arm.h | 28 + src/runtime/signal_netbsd_386.h | 23 + src/runtime/signal_netbsd_amd64.h | 31 + src/runtime/signal_netbsd_arm.h | 30 + src/runtime/signal_openbsd_386.h | 23 + src/runtime/signal_openbsd_amd64.h | 31 + src/runtime/signal_solaris_amd64.h | 31 + src/runtime/signal_unix.c | 119 + src/runtime/signal_unix.go | 13 + src/runtime/signal_unix.h | 14 + src/runtime/signals_android.h | 1 + src/runtime/signals_darwin.h | 53 + src/runtime/signals_dragonfly.h | 54 + src/runtime/signals_freebsd.h | 54 + src/runtime/signals_linux.h | 86 + src/runtime/signals_nacl.h | 53 + src/runtime/signals_netbsd.h | 54 + src/runtime/signals_openbsd.h | 54 + src/runtime/signals_plan9.h | 63 + src/runtime/signals_solaris.h | 97 + src/runtime/signals_windows.h | 3 + src/runtime/sigpanic_unix.go | 40 + src/runtime/sigqueue.go | 173 + src/runtime/slice.go | 139 + src/runtime/softfloat64.go | 498 + src/runtime/softfloat64_test.go | 198 + src/runtime/softfloat_arm.c | 687 + src/runtime/sqrt.go | 150 + src/runtime/stack.c | 892 ++ src/runtime/stack.go | 13 + src/runtime/stack.h | 118 + src/runtime/stack_test.go | 397 + src/runtime/string.c | 226 + src/runtime/string.go | 298 + src/runtime/string_test.go | 160 + src/runtime/stubs.go | 316 + src/runtime/symtab.go | 288 + src/runtime/symtab_test.go | 47 + src/runtime/sys_arm.c | 35 + src/runtime/sys_darwin_386.s | 541 + src/runtime/sys_darwin_amd64.s | 505 + src/runtime/sys_dragonfly_386.s | 381 + src/runtime/sys_dragonfly_amd64.s | 344 + src/runtime/sys_freebsd_386.s | 391 + src/runtime/sys_freebsd_amd64.s | 357 + src/runtime/sys_freebsd_arm.s | 382 + src/runtime/sys_linux_386.s | 489 + src/runtime/sys_linux_amd64.s | 410 + src/runtime/sys_linux_arm.s | 461 + src/runtime/sys_nacl_386.s | 363 + src/runtime/sys_nacl_amd64p32.s | 459 + src/runtime/sys_nacl_arm.s | 320 + src/runtime/sys_netbsd_386.s | 384 + src/runtime/sys_netbsd_amd64.s | 358 + src/runtime/sys_netbsd_arm.s | 351 + src/runtime/sys_openbsd_386.s | 398 + src/runtime/sys_openbsd_amd64.s | 350 + src/runtime/sys_plan9_386.s | 249 + src/runtime/sys_plan9_amd64.s | 254 + src/runtime/sys_solaris_amd64.s | 351 + src/runtime/sys_windows_386.s | 433 + src/runtime/sys_windows_amd64.s | 462 + src/runtime/sys_x86.c | 57 + src/runtime/syscall_nacl.h | 71 + src/runtime/syscall_solaris.c | 23 + src/runtime/syscall_solaris.go | 322 + src/runtime/syscall_windows.go | 170 + src/runtime/syscall_windows_test.go | 535 + src/runtime/thunk.s | 183 + src/runtime/thunk_solaris_amd64.s | 88 + src/runtime/thunk_windows.s | 30 + src/runtime/time.go | 289 + src/runtime/tls_arm.s | 69 + src/runtime/traceback.go | 659 + src/runtime/type.h | 113 + src/runtime/typekind.go | 44 + src/runtime/typekind.h | 38 + src/runtime/vdso_linux_amd64.c | 371 + src/runtime/vlop_386.s | 56 + src/runtime/vlop_arm.s | 317 + src/runtime/vlop_arm_test.go | 70 + src/runtime/vlrt.c | 914 ++ src/runtime/vlrt.go | 258 + src/sort/example_interface_test.go | 44 + src/sort/example_keys_test.go | 96 + src/sort/example_multi_test.go | 131 + src/sort/example_test.go | 24 + src/sort/example_wrapper_test.go | 77 + src/sort/export_test.go | 9 + src/sort/search.go | 112 + src/sort/search_test.go | 161 + src/sort/sort.go | 474 + src/sort/sort_test.go | 553 + src/strconv/atob.go | 35 + src/strconv/atob_test.go | 91 + src/strconv/atof.go | 540 + src/strconv/atof_test.go | 430 + src/strconv/atoi.go | 198 + src/strconv/atoi_test.go | 326 + src/strconv/decimal.go | 378 + src/strconv/decimal_test.go | 127 + src/strconv/extfloat.go | 668 + src/strconv/fp_test.go | 144 + src/strconv/ftoa.go | 475 + src/strconv/ftoa_test.go | 240 + src/strconv/internal_test.go | 19 + src/strconv/isprint.go | 624 + src/strconv/itoa.go | 131 + src/strconv/itoa_test.go | 160 + src/strconv/makeisprint.go | 187 + src/strconv/quote.go | 455 + src/strconv/quote_example_test.go | 35 + src/strconv/quote_test.go | 266 + src/strconv/strconv_test.go | 57 + src/strconv/testdata/testfp.txt | 181 + src/strings/example_test.go | 225 + src/strings/export_test.go | 45 + src/strings/reader.go | 144 + src/strings/reader_test.go | 159 + src/strings/replace.go | 518 + src/strings/replace_test.go | 542 + src/strings/search.go | 124 + src/strings/search_test.go | 90 + src/strings/strings.go | 762 + src/strings/strings.s | 5 + src/strings/strings_decl.go | 8 + src/strings/strings_test.go | 1204 ++ src/sync/atomic/64bit_arm.go | 58 + src/sync/atomic/asm_386.s | 214 + src/sync/atomic/asm_amd64.s | 146 + src/sync/atomic/asm_amd64p32.s | 159 + src/sync/atomic/asm_arm.s | 197 + src/sync/atomic/asm_freebsd_arm.s | 109 + src/sync/atomic/asm_linux_arm.s | 216 + src/sync/atomic/asm_nacl_arm.s | 109 + src/sync/atomic/asm_netbsd_arm.s | 109 + src/sync/atomic/atomic_linux_arm_test.go | 14 + src/sync/atomic/atomic_test.go | 1509 ++ src/sync/atomic/doc.go | 149 + src/sync/atomic/export_linux_arm_test.go | 7 + src/sync/atomic/race.s | 8 + src/sync/atomic/value.go | 85 + src/sync/atomic/value_test.go | 195 + src/sync/cond.go | 118 + src/sync/cond_test.go | 255 + src/sync/example_test.go | 59 + src/sync/export_test.go | 9 + src/sync/mutex.go | 109 + src/sync/mutex_test.go | 136 + src/sync/once.go | 46 + src/sync/once_test.go | 68 + src/sync/pool.go | 225 + src/sync/pool_test.go | 163 + src/sync/race.go | 42 + src/sync/race0.go | 34 + src/sync/runtime.go | 40 + src/sync/runtime_sema_test.go | 72 + src/sync/rwmutex.go | 136 + src/sync/rwmutex_test.go | 254 + src/sync/waitgroup.go | 137 + src/sync/waitgroup_test.go | 148 + src/syscall/asm.s | 8 + src/syscall/asm_darwin_386.s | 143 + src/syscall/asm_darwin_amd64.s | 107 + src/syscall/asm_dragonfly_386.s | 140 + src/syscall/asm_dragonfly_amd64.s | 134 + src/syscall/asm_freebsd_386.s | 143 + src/syscall/asm_freebsd_amd64.s | 142 + src/syscall/asm_freebsd_arm.s | 130 + src/syscall/asm_linux_386.s | 187 + src/syscall/asm_linux_amd64.s | 127 + src/syscall/asm_linux_arm.s | 159 + src/syscall/asm_nacl_386.s | 44 + src/syscall/asm_nacl_amd64p32.s | 42 + src/syscall/asm_nacl_arm.s | 44 + src/syscall/asm_netbsd_386.s | 143 + src/syscall/asm_netbsd_amd64.s | 136 + src/syscall/asm_netbsd_arm.s | 127 + src/syscall/asm_openbsd_386.s | 143 + src/syscall/asm_openbsd_amd64.s | 136 + src/syscall/asm_plan9_386.s | 166 + src/syscall/asm_plan9_amd64.s | 164 + src/syscall/asm_solaris_amd64.s | 81 + src/syscall/bpf_bsd.go | 169 + src/syscall/creds_test.go | 113 + src/syscall/dir_plan9.go | 212 + src/syscall/dll_windows.go | 280 + src/syscall/env_plan9.go | 108 + src/syscall/env_unix.go | 149 + src/syscall/env_windows.go | 90 + src/syscall/exec_bsd.go | 247 + src/syscall/exec_linux.go | 363 + src/syscall/exec_plan9.go | 650 + src/syscall/exec_solaris.go | 243 + src/syscall/exec_unix.go | 261 + src/syscall/exec_windows.go | 340 + src/syscall/export_test.go | 7 + src/syscall/fd_nacl.go | 326 + src/syscall/flock.go | 22 + src/syscall/flock_linux_32bit.go | 13 + src/syscall/fs_nacl.go | 838 ++ src/syscall/lsf_linux.go | 78 + src/syscall/mkall.sh | 263 + src/syscall/mkall_windows.bat | 15 + src/syscall/mkerrors.sh | 433 + src/syscall/mksyscall.pl | 319 + src/syscall/mksyscall_solaris.pl | 283 + src/syscall/mksyscall_windows.go | 759 + src/syscall/mksysctl_openbsd.pl | 257 + src/syscall/mksysnum_darwin.pl | 32 + src/syscall/mksysnum_dragonfly.pl | 43 + src/syscall/mksysnum_freebsd.pl | 56 + src/syscall/mksysnum_linux.pl | 38 + src/syscall/mksysnum_netbsd.pl | 51 + src/syscall/mksysnum_openbsd.pl | 43 + src/syscall/mksysnum_plan9.sh | 25 + src/syscall/mmap_unix_test.go | 22 + src/syscall/net_nacl.go | 913 ++ src/syscall/netlink_linux.go | 178 + src/syscall/race.go | 30 + src/syscall/race0.go | 25 + src/syscall/route_bsd.go | 224 + src/syscall/route_darwin.go | 61 + src/syscall/route_dragonfly.go | 72 + src/syscall/route_freebsd.go | 78 + src/syscall/route_freebsd_32bit.go | 24 + src/syscall/route_freebsd_64bit.go | 14 + src/syscall/route_netbsd.go | 35 + src/syscall/route_openbsd.go | 35 + src/syscall/security_windows.go | 384 + src/syscall/so_solaris.go | 262 + src/syscall/sockcmsg_linux.go | 36 + src/syscall/sockcmsg_unix.go | 103 + src/syscall/srpc_nacl.go | 822 ++ src/syscall/str.go | 24 + src/syscall/syscall.go | 95 + src/syscall/syscall_bsd.go | 588 + src/syscall/syscall_bsd_test.go | 34 + src/syscall/syscall_darwin.go | 509 + src/syscall/syscall_darwin_386.go | 70 + src/syscall/syscall_darwin_amd64.go | 70 + src/syscall/syscall_dragonfly.go | 408 + src/syscall/syscall_dragonfly_386.go | 58 + src/syscall/syscall_dragonfly_amd64.go | 58 + src/syscall/syscall_freebsd.go | 430 + src/syscall/syscall_freebsd_386.go | 58 + src/syscall/syscall_freebsd_amd64.go | 58 + src/syscall/syscall_freebsd_arm.go | 58 + src/syscall/syscall_linux.go | 1042 ++ src/syscall/syscall_linux_386.go | 356 + src/syscall/syscall_linux_amd64.go | 114 + src/syscall/syscall_linux_arm.go | 196 + src/syscall/syscall_nacl.go | 311 + src/syscall/syscall_nacl_386.go | 32 + src/syscall/syscall_nacl_amd64p32.go | 32 + src/syscall/syscall_nacl_arm.go | 32 + src/syscall/syscall_netbsd.go | 489 + src/syscall/syscall_netbsd_386.go | 42 + src/syscall/syscall_netbsd_amd64.go | 42 + src/syscall/syscall_netbsd_arm.go | 42 + src/syscall/syscall_no_getwd.go | 11 + src/syscall/syscall_openbsd.go | 299 + src/syscall/syscall_openbsd_386.go | 42 + src/syscall/syscall_openbsd_amd64.go | 42 + src/syscall/syscall_plan9.go | 341 + src/syscall/syscall_solaris.go | 523 + src/syscall/syscall_solaris_amd64.go | 37 + src/syscall/syscall_test.go | 47 + src/syscall/syscall_unix.go | 299 + src/syscall/syscall_unix_test.go | 314 + src/syscall/syscall_windows.go | 1013 ++ src/syscall/syscall_windows_386.go | 5 + src/syscall/syscall_windows_amd64.go | 5 + src/syscall/syscall_windows_test.go | 72 + src/syscall/tables_nacl.go | 324 + src/syscall/time_nacl_386.s | 11 + src/syscall/time_nacl_amd64p32.s | 11 + src/syscall/time_nacl_arm.s | 11 + src/syscall/types_darwin.go | 243 + src/syscall/types_dragonfly.go | 242 + src/syscall/types_freebsd.go | 342 + src/syscall/types_linux.go | 484 + src/syscall/types_netbsd.go | 232 + src/syscall/types_openbsd.go | 244 + src/syscall/types_plan9.c | 115 + src/syscall/types_solaris.go | 222 + src/syscall/unzip_nacl.go | 685 + src/syscall/zerrors_darwin_386.go | 1421 ++ src/syscall/zerrors_darwin_amd64.go | 1421 ++ src/syscall/zerrors_dragonfly_386.go | 1526 ++ src/syscall/zerrors_dragonfly_amd64.go | 1526 ++ src/syscall/zerrors_freebsd_386.go | 1715 +++ src/syscall/zerrors_freebsd_amd64.go | 1716 +++ src/syscall/zerrors_freebsd_arm.go | 1715 +++ src/syscall/zerrors_linux_386.go | 1544 +++ src/syscall/zerrors_linux_amd64.go | 1545 +++ src/syscall/zerrors_linux_arm.go | 1558 +++ src/syscall/zerrors_netbsd_386.go | 1708 +++ src/syscall/zerrors_netbsd_amd64.go | 1698 +++ src/syscall/zerrors_netbsd_arm.go | 1684 +++ src/syscall/zerrors_openbsd_386.go | 1580 +++ src/syscall/zerrors_openbsd_amd64.go | 1579 +++ src/syscall/zerrors_plan9_386.go | 48 + src/syscall/zerrors_plan9_amd64.go | 48 + src/syscall/zerrors_solaris_amd64.go | 1414 ++ src/syscall/zerrors_windows.go | 283 + src/syscall/zerrors_windows_386.go | 5 + src/syscall/zerrors_windows_amd64.go | 5 + src/syscall/zsyscall_darwin_386.go | 1419 ++ src/syscall/zsyscall_darwin_amd64.go | 1419 ++ src/syscall/zsyscall_dragonfly_386.go | 1317 ++ src/syscall/zsyscall_dragonfly_amd64.go | 1317 ++ src/syscall/zsyscall_freebsd_386.go | 1328 ++ src/syscall/zsyscall_freebsd_amd64.go | 1328 ++ src/syscall/zsyscall_freebsd_arm.go | 1328 ++ src/syscall/zsyscall_linux_386.go | 1767 +++ src/syscall/zsyscall_linux_amd64.go | 1961 +++ src/syscall/zsyscall_linux_arm.go | 1915 +++ src/syscall/zsyscall_nacl_386.go | 63 + src/syscall/zsyscall_nacl_amd64p32.go | 63 + src/syscall/zsyscall_nacl_arm.go | 63 + src/syscall/zsyscall_netbsd_386.go | 1251 ++ src/syscall/zsyscall_netbsd_amd64.go | 1251 ++ src/syscall/zsyscall_netbsd_arm.go | 1251 ++ src/syscall/zsyscall_openbsd_386.go | 1291 ++ src/syscall/zsyscall_openbsd_amd64.go | 1291 ++ src/syscall/zsyscall_plan9_386.go | 292 + src/syscall/zsyscall_plan9_amd64.go | 292 + src/syscall/zsyscall_solaris_amd64.go | 906 ++ src/syscall/zsyscall_windows.go | 1870 +++ src/syscall/zsysctl_openbsd.go | 270 + src/syscall/zsysnum_darwin_386.go | 360 + src/syscall/zsysnum_darwin_amd64.go | 360 + src/syscall/zsysnum_dragonfly_386.go | 302 + src/syscall/zsysnum_dragonfly_amd64.go | 302 + src/syscall/zsysnum_freebsd_386.go | 348 + src/syscall/zsysnum_freebsd_amd64.go | 348 + src/syscall/zsysnum_freebsd_arm.go | 348 + src/syscall/zsysnum_linux_386.go | 345 + src/syscall/zsysnum_linux_amd64.go | 310 + src/syscall/zsysnum_linux_arm.go | 354 + src/syscall/zsysnum_netbsd_386.go | 271 + src/syscall/zsysnum_netbsd_amd64.go | 271 + src/syscall/zsysnum_netbsd_arm.go | 271 + src/syscall/zsysnum_openbsd_386.go | 205 + src/syscall/zsysnum_openbsd_amd64.go | 205 + src/syscall/zsysnum_plan9_386.go | 49 + src/syscall/zsysnum_plan9_amd64.go | 49 + src/syscall/zsysnum_solaris_amd64.go | 11 + src/syscall/zsysnum_windows_386.go | 3 + src/syscall/zsysnum_windows_amd64.go | 3 + src/syscall/ztypes_darwin_386.go | 446 + src/syscall/ztypes_darwin_amd64.go | 456 + src/syscall/ztypes_dragonfly_386.go | 435 + src/syscall/ztypes_dragonfly_amd64.go | 441 + src/syscall/ztypes_freebsd_386.go | 492 + src/syscall/ztypes_freebsd_amd64.go | 495 + src/syscall/ztypes_freebsd_arm.go | 495 + src/syscall/ztypes_linux_386.go | 690 + src/syscall/ztypes_linux_amd64.go | 708 + src/syscall/ztypes_linux_arm.go | 679 + src/syscall/ztypes_netbsd_386.go | 394 + src/syscall/ztypes_netbsd_amd64.go | 401 + src/syscall/ztypes_netbsd_arm.go | 399 + src/syscall/ztypes_openbsd_386.go | 439 + src/syscall/ztypes_openbsd_amd64.go | 446 + src/syscall/ztypes_plan9_386.go | 75 + src/syscall/ztypes_plan9_amd64.go | 75 + src/syscall/ztypes_solaris_amd64.go | 365 + src/syscall/ztypes_windows.go | 1105 ++ src/syscall/ztypes_windows_386.go | 22 + src/syscall/ztypes_windows_amd64.go | 22 + src/testing/allocs.go | 45 + src/testing/allocs_test.go | 29 + src/testing/benchmark.go | 446 + src/testing/benchmark_test.go | 113 + src/testing/cover.go | 112 + src/testing/example.go | 100 + src/testing/export_test.go | 10 + src/testing/iotest/logger.go | 54 + src/testing/iotest/reader.go | 88 + src/testing/iotest/writer.go | 35 + src/testing/quick/quick.go | 358 + src/testing/quick/quick_test.go | 249 + src/testing/testing.go | 709 + src/testing/testing_test.go | 18 + src/text/scanner/scanner.go | 693 + src/text/scanner/scanner_test.go | 618 + src/text/tabwriter/example_test.go | 38 + src/text/tabwriter/tabwriter.go | 558 + src/text/tabwriter/tabwriter_test.go | 652 + src/text/template/doc.go | 406 + src/text/template/example_test.go | 71 + src/text/template/examplefiles_test.go | 182 + src/text/template/examplefunc_test.go | 54 + src/text/template/exec.go | 844 ++ src/text/template/exec_test.go | 1044 ++ src/text/template/funcs.go | 598 + src/text/template/helper.go | 108 + src/text/template/multi_test.go | 292 + src/text/template/parse/lex.go | 551 + src/text/template/parse/lex_test.go | 465 + src/text/template/parse/node.go | 834 ++ src/text/template/parse/parse.go | 677 + src/text/template/parse/parse_test.go | 423 + src/text/template/template.go | 217 + src/text/template/testdata/file1.tmpl | 2 + src/text/template/testdata/file2.tmpl | 2 + src/text/template/testdata/tmpl1.tmpl | 3 + src/text/template/testdata/tmpl2.tmpl | 3 + src/time/example_test.go | 160 + src/time/export_test.go | 24 + src/time/export_windows_test.go | 10 + src/time/format.go | 1248 ++ src/time/format_test.go | 518 + src/time/genzabbrs.go | 159 + src/time/internal_test.go | 59 + src/time/sleep.go | 130 + src/time/sleep_test.go | 430 + src/time/sys_plan9.go | 76 + src/time/sys_unix.go | 76 + src/time/sys_windows.go | 73 + src/time/tick.go | 56 + src/time/tick_test.go | 78 + src/time/time.go | 1203 ++ src/time/time_test.go | 1081 ++ src/time/zoneinfo.go | 287 + src/time/zoneinfo_abbrs_windows.go | 116 + src/time/zoneinfo_plan9.go | 160 + src/time/zoneinfo_read.go | 343 + src/time/zoneinfo_test.go | 63 + src/time/zoneinfo_unix.go | 84 + src/time/zoneinfo_windows.go | 272 + src/time/zoneinfo_windows_test.go | 35 + src/unicode/casetables.go | 20 + src/unicode/digit.go | 13 + src/unicode/digit_test.go | 126 + src/unicode/graphic.go | 144 + src/unicode/graphic_test.go | 122 + src/unicode/letter.go | 357 + src/unicode/letter_test.go | 535 + src/unicode/maketables.go | 1376 ++ src/unicode/script_test.go | 287 + src/unicode/tables.go | 7029 ++++++++++ src/unicode/utf16/export_test.go | 11 + src/unicode/utf16/utf16.go | 108 + src/unicode/utf16/utf16_test.go | 149 + src/unicode/utf8/example_test.go | 196 + src/unicode/utf8/utf8.go | 445 + src/unicode/utf8/utf8_test.go | 444 + src/unsafe/unsafe.go | 40 + 4512 files changed, 571575 insertions(+), 538955 deletions(-) create mode 100755 src/androidtest.bash create mode 100644 src/archive/tar/common.go create mode 100644 src/archive/tar/example_test.go create mode 100644 src/archive/tar/reader.go create mode 100644 src/archive/tar/reader_test.go create mode 100644 src/archive/tar/stat_atim.go create mode 100644 src/archive/tar/stat_atimespec.go create mode 100644 src/archive/tar/stat_unix.go create mode 100644 src/archive/tar/tar_test.go create mode 100644 src/archive/tar/testdata/gnu.tar create mode 100644 src/archive/tar/testdata/nil-uid.tar create mode 100644 src/archive/tar/testdata/pax.tar create mode 100644 src/archive/tar/testdata/small.txt create mode 100644 src/archive/tar/testdata/small2.txt create mode 100644 src/archive/tar/testdata/sparse-formats.tar create mode 100644 src/archive/tar/testdata/star.tar create mode 100644 src/archive/tar/testdata/ustar.tar create mode 100644 src/archive/tar/testdata/v7.tar create mode 100644 src/archive/tar/testdata/writer-big-long.tar create mode 100644 src/archive/tar/testdata/writer-big.tar create mode 100644 src/archive/tar/testdata/writer.tar create mode 100644 src/archive/tar/testdata/xattrs.tar create mode 100644 src/archive/tar/writer.go create mode 100644 src/archive/tar/writer_test.go create mode 100644 src/archive/zip/example_test.go create mode 100644 src/archive/zip/reader.go create mode 100644 src/archive/zip/reader_test.go create mode 100644 src/archive/zip/register.go create mode 100644 src/archive/zip/struct.go create mode 100644 src/archive/zip/testdata/crc32-not-streamed.zip create mode 100644 src/archive/zip/testdata/dd.zip create mode 100644 src/archive/zip/testdata/go-no-datadesc-sig.zip create mode 100644 src/archive/zip/testdata/go-with-datadesc-sig.zip create mode 100644 src/archive/zip/testdata/gophercolor16x16.png create mode 100644 src/archive/zip/testdata/readme.notzip create mode 100644 src/archive/zip/testdata/readme.zip create mode 100644 src/archive/zip/testdata/symlink.zip create mode 100644 src/archive/zip/testdata/test-trailing-junk.zip create mode 100644 src/archive/zip/testdata/test.zip create mode 100644 src/archive/zip/testdata/unix.zip create mode 100644 src/archive/zip/testdata/winxp.zip create mode 100644 src/archive/zip/testdata/zip64-2.zip create mode 100644 src/archive/zip/testdata/zip64.zip create mode 100644 src/archive/zip/writer.go create mode 100644 src/archive/zip/writer_test.go create mode 100644 src/archive/zip/zip_test.go create mode 100644 src/bufio/bufio.go create mode 100644 src/bufio/bufio_test.go create mode 100644 src/bufio/example_test.go create mode 100644 src/bufio/export_test.go create mode 100644 src/bufio/scan.go create mode 100644 src/bufio/scan_test.go create mode 100644 src/builtin/builtin.go create mode 100644 src/bytes/buffer.go create mode 100644 src/bytes/buffer_test.go create mode 100644 src/bytes/bytes.go create mode 100644 src/bytes/bytes_decl.go create mode 100644 src/bytes/bytes_test.go create mode 100644 src/bytes/compare_test.go create mode 100644 src/bytes/equal_test.go create mode 100644 src/bytes/example_test.go create mode 100644 src/bytes/export_test.go create mode 100644 src/bytes/reader.go create mode 100644 src/bytes/reader_test.go delete mode 100644 src/cmd/5l/mkenam delete mode 100644 src/cmd/5l/noop.c delete mode 100644 src/cmd/6l/mkenam delete mode 100644 src/cmd/8l/mkenam delete mode 100644 src/cmd/cc/bv.c delete mode 100644 src/cmd/dist/goc2c.c create mode 100644 src/cmd/go/generate.go create mode 100644 src/cmd/go/generate_test.go create mode 100644 src/cmd/go/go_windows_test.go create mode 100644 src/cmd/go/testdata/generate/test1.go create mode 100644 src/cmd/go/testdata/generate/test2.go create mode 100644 src/cmd/go/testdata/generate/test3.go create mode 100644 src/cmd/go/testdata/importcom/bad.go create mode 100644 src/cmd/go/testdata/importcom/conflict.go create mode 100644 src/cmd/go/testdata/importcom/src/bad/bad.go create mode 100644 src/cmd/go/testdata/importcom/src/conflict/a.go create mode 100644 src/cmd/go/testdata/importcom/src/conflict/b.go create mode 100644 src/cmd/go/testdata/importcom/src/works/x/x.go create mode 100644 src/cmd/go/testdata/importcom/src/works/x/x1.go create mode 100644 src/cmd/go/testdata/importcom/src/wrongplace/x.go create mode 100644 src/cmd/go/testdata/importcom/works.go create mode 100644 src/cmd/go/testdata/importcom/wrongplace.go create mode 100644 src/cmd/go/testdata/norunexample/example_test.go create mode 100644 src/cmd/go/testdata/norunexample/test_test.go create mode 100644 src/cmd/go/testdata/src/badc/x.c create mode 100644 src/cmd/go/testdata/src/badc/x.go create mode 100644 src/cmd/go/testdata/src/badtest/badexec/x_test.go create mode 100644 src/cmd/go/testdata/src/badtest/badsyntax/x.go create mode 100644 src/cmd/go/testdata/src/badtest/badsyntax/x_test.go create mode 100644 src/cmd/go/testdata/src/badtest/badvar/x.go create mode 100644 src/cmd/go/testdata/src/badtest/badvar/x_test.go create mode 100644 src/cmd/go/testdata/src/vetpkg/a_test.go create mode 100644 src/cmd/go/testdata/src/vetpkg/b.go create mode 100644 src/cmd/go/testdata/testinternal/p.go create mode 100644 src/cmd/go/testdata/testinternal2/p.go create mode 100644 src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go create mode 100644 src/cmd/go/testgo.go create mode 100644 src/cmd/go/vcs_test.go create mode 100644 src/cmd/gofmt/testdata/emptydecl.golden create mode 100644 src/cmd/gofmt/testdata/emptydecl.input create mode 100644 src/cmd/gofmt/testdata/ranges.golden create mode 100644 src/cmd/gofmt/testdata/ranges.input delete mode 100644 src/cmd/gofmt/testdata/stdin1.golden.gofmt delete mode 100644 src/cmd/gofmt/testdata/stdin1.input.gofmt delete mode 100644 src/cmd/gofmt/testdata/stdin2.golden.gofmt delete mode 100644 src/cmd/gofmt/testdata/stdin2.input.gofmt delete mode 100644 src/cmd/gofmt/testdata/stdin3.golden.gofmt delete mode 100644 src/cmd/gofmt/testdata/stdin3.input.gofmt delete mode 100644 src/cmd/gofmt/testdata/stdin4.golden.gofmt delete mode 100644 src/cmd/gofmt/testdata/stdin4.input.gofmt create mode 100644 src/cmd/gofmt/testdata/stdin5.golden create mode 100644 src/cmd/gofmt/testdata/stdin5.input create mode 100644 src/cmd/gofmt/testdata/stdin6.golden create mode 100644 src/cmd/gofmt/testdata/stdin6.input create mode 100644 src/cmd/gofmt/testdata/stdin7.golden create mode 100644 src/cmd/gofmt/testdata/stdin7.input create mode 100644 src/cmd/internal/goobj/read.go create mode 100644 src/cmd/internal/goobj/read_test.go create mode 100644 src/cmd/internal/objfile/disasm.go create mode 100644 src/cmd/internal/objfile/elf.go create mode 100644 src/cmd/internal/objfile/goobj.go create mode 100644 src/cmd/internal/objfile/macho.go create mode 100644 src/cmd/internal/objfile/objfile.go create mode 100644 src/cmd/internal/objfile/pe.go create mode 100644 src/cmd/internal/objfile/plan9obj.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/Makefile create mode 100644 src/cmd/internal/rsc.io/arm/armasm/decode.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/decode_test.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/ext_test.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/gnu.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/inst.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/objdump_test.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/plan9x.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/tables.go create mode 100644 src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile create mode 100644 src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/Makefile create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/decode.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/decode_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/ext_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/gnu.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/inst.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/inst_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/intel.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/objdumpext_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/plan9ext_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/plan9x.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/tables.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/xed_test.go create mode 100644 src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go delete mode 100644 src/cmd/ld/pass.c delete mode 100644 src/cmd/nm/debug_goobj.go delete mode 100644 src/cmd/nm/elf.go delete mode 100644 src/cmd/nm/goobj.go delete mode 100644 src/cmd/nm/macho.go delete mode 100644 src/cmd/nm/pe.go delete mode 100644 src/cmd/nm/plan9obj.go delete mode 100644 src/cmd/objdump/Makefile delete mode 100644 src/cmd/objdump/armasm.go delete mode 100644 src/cmd/objdump/elf.go delete mode 100644 src/cmd/objdump/macho.go delete mode 100644 src/cmd/objdump/pe.go delete mode 100644 src/cmd/objdump/plan9obj.go delete mode 100644 src/cmd/objdump/x86.go create mode 100644 src/cmd/pprof/README create mode 100644 src/cmd/pprof/doc.go create mode 100644 src/cmd/pprof/internal/commands/commands.go create mode 100644 src/cmd/pprof/internal/driver/driver.go create mode 100644 src/cmd/pprof/internal/driver/interactive.go create mode 100644 src/cmd/pprof/internal/fetch/fetch.go create mode 100644 src/cmd/pprof/internal/plugin/plugin.go create mode 100644 src/cmd/pprof/internal/profile/encode.go create mode 100644 src/cmd/pprof/internal/profile/filter.go create mode 100644 src/cmd/pprof/internal/profile/legacy_profile.go create mode 100644 src/cmd/pprof/internal/profile/profile.go create mode 100644 src/cmd/pprof/internal/profile/proto.go create mode 100644 src/cmd/pprof/internal/profile/prune.go create mode 100644 src/cmd/pprof/internal/report/report.go create mode 100644 src/cmd/pprof/internal/report/source.go create mode 100644 src/cmd/pprof/internal/report/source_html.go create mode 100644 src/cmd/pprof/internal/svg/svg.go create mode 100644 src/cmd/pprof/internal/symbolizer/symbolizer.go create mode 100644 src/cmd/pprof/internal/symbolz/symbolz.go create mode 100644 src/cmd/pprof/internal/tempfile/tempfile.go create mode 100644 src/cmd/pprof/pprof.go delete mode 100644 src/cmd/yacc/Makefile delete mode 100644 src/cmd/yacc/expr.y create mode 100644 src/cmd/yacc/testdata/expr/README create mode 100644 src/cmd/yacc/testdata/expr/expr.y create mode 100644 src/cmd/yacc/testdata/expr/main.go create mode 100644 src/compress/bzip2/bit_reader.go create mode 100644 src/compress/bzip2/bzip2.go create mode 100644 src/compress/bzip2/bzip2_test.go create mode 100644 src/compress/bzip2/huffman.go create mode 100644 src/compress/bzip2/move_to_front.go create mode 100644 src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 create mode 100644 src/compress/bzip2/testdata/e.txt.bz2 create mode 100644 src/compress/flate/copy.go create mode 100644 src/compress/flate/copy_test.go create mode 100644 src/compress/flate/deflate.go create mode 100644 src/compress/flate/deflate_test.go create mode 100644 src/compress/flate/fixedhuff.go create mode 100644 src/compress/flate/flate_test.go create mode 100644 src/compress/flate/gen.go create mode 100644 src/compress/flate/huffman_bit_writer.go create mode 100644 src/compress/flate/huffman_code.go create mode 100644 src/compress/flate/inflate.go create mode 100644 src/compress/flate/inflate_test.go create mode 100644 src/compress/flate/reader_test.go create mode 100644 src/compress/flate/reverse_bits.go create mode 100644 src/compress/flate/token.go create mode 100644 src/compress/flate/writer_test.go create mode 100644 src/compress/gzip/gunzip.go create mode 100644 src/compress/gzip/gunzip_test.go create mode 100644 src/compress/gzip/gzip.go create mode 100644 src/compress/gzip/gzip_test.go create mode 100644 src/compress/gzip/testdata/issue6550.gz create mode 100644 src/compress/lzw/reader.go create mode 100644 src/compress/lzw/reader_test.go create mode 100644 src/compress/lzw/writer.go create mode 100644 src/compress/lzw/writer_test.go create mode 100644 src/compress/testdata/Mark.Twain-Tom.Sawyer.txt create mode 100644 src/compress/testdata/e.txt create mode 100644 src/compress/testdata/pi.txt create mode 100644 src/compress/zlib/example_test.go create mode 100644 src/compress/zlib/reader.go create mode 100644 src/compress/zlib/reader_test.go create mode 100644 src/compress/zlib/writer.go create mode 100644 src/compress/zlib/writer_test.go create mode 100644 src/container/heap/example_intheap_test.go create mode 100644 src/container/heap/example_pq_test.go create mode 100644 src/container/heap/heap.go create mode 100644 src/container/heap/heap_test.go create mode 100644 src/container/list/example_test.go create mode 100644 src/container/list/list.go create mode 100644 src/container/list/list_test.go create mode 100644 src/container/ring/ring.go create mode 100644 src/container/ring/ring_test.go create mode 100644 src/crypto/aes/aes_test.go create mode 100644 src/crypto/aes/asm_amd64.s create mode 100644 src/crypto/aes/block.go create mode 100644 src/crypto/aes/cipher.go create mode 100644 src/crypto/aes/cipher_asm.go create mode 100644 src/crypto/aes/cipher_generic.go create mode 100644 src/crypto/aes/const.go create mode 100644 src/crypto/cipher/benchmark_test.go create mode 100644 src/crypto/cipher/cbc.go create mode 100644 src/crypto/cipher/cbc_aes_test.go create mode 100644 src/crypto/cipher/cfb.go create mode 100644 src/crypto/cipher/cfb_test.go create mode 100644 src/crypto/cipher/cipher.go create mode 100644 src/crypto/cipher/cipher_test.go create mode 100644 src/crypto/cipher/common_test.go create mode 100644 src/crypto/cipher/ctr.go create mode 100644 src/crypto/cipher/ctr_aes_test.go create mode 100644 src/crypto/cipher/example_test.go create mode 100644 src/crypto/cipher/gcm.go create mode 100644 src/crypto/cipher/gcm_test.go create mode 100644 src/crypto/cipher/io.go create mode 100644 src/crypto/cipher/ofb.go create mode 100644 src/crypto/cipher/ofb_test.go create mode 100644 src/crypto/cipher/xor.go create mode 100644 src/crypto/cipher/xor_test.go create mode 100644 src/crypto/crypto.go create mode 100644 src/crypto/des/block.go create mode 100644 src/crypto/des/cipher.go create mode 100644 src/crypto/des/const.go create mode 100644 src/crypto/des/des_test.go create mode 100644 src/crypto/des/example_test.go create mode 100644 src/crypto/dsa/dsa.go create mode 100644 src/crypto/dsa/dsa_test.go create mode 100644 src/crypto/ecdsa/ecdsa.go create mode 100644 src/crypto/ecdsa/ecdsa_test.go create mode 100644 src/crypto/ecdsa/testdata/SigVer.rsp.bz2 create mode 100644 src/crypto/elliptic/elliptic.go create mode 100644 src/crypto/elliptic/elliptic_test.go create mode 100644 src/crypto/elliptic/p224.go create mode 100644 src/crypto/elliptic/p224_test.go create mode 100644 src/crypto/elliptic/p256.go create mode 100644 src/crypto/hmac/hmac.go create mode 100644 src/crypto/hmac/hmac_test.go create mode 100644 src/crypto/md5/example_test.go create mode 100644 src/crypto/md5/gen.go create mode 100644 src/crypto/md5/md5.go create mode 100644 src/crypto/md5/md5_test.go create mode 100644 src/crypto/md5/md5block.go create mode 100644 src/crypto/md5/md5block_386.s create mode 100644 src/crypto/md5/md5block_amd64.s create mode 100644 src/crypto/md5/md5block_amd64p32.s create mode 100644 src/crypto/md5/md5block_arm.s create mode 100644 src/crypto/md5/md5block_decl.go create mode 100644 src/crypto/md5/md5block_generic.go create mode 100644 src/crypto/rand/example_test.go create mode 100644 src/crypto/rand/rand.go create mode 100644 src/crypto/rand/rand_linux.go create mode 100644 src/crypto/rand/rand_test.go create mode 100644 src/crypto/rand/rand_unix.go create mode 100644 src/crypto/rand/rand_windows.go create mode 100644 src/crypto/rand/util.go create mode 100644 src/crypto/rand/util_test.go create mode 100644 src/crypto/rc4/rc4.go create mode 100644 src/crypto/rc4/rc4_386.s create mode 100644 src/crypto/rc4/rc4_amd64.s create mode 100644 src/crypto/rc4/rc4_amd64p32.s create mode 100644 src/crypto/rc4/rc4_arm.s create mode 100644 src/crypto/rc4/rc4_asm.go create mode 100644 src/crypto/rc4/rc4_ref.go create mode 100644 src/crypto/rc4/rc4_test.go create mode 100644 src/crypto/rsa/pkcs1v15.go create mode 100644 src/crypto/rsa/pkcs1v15_test.go create mode 100644 src/crypto/rsa/pss.go create mode 100644 src/crypto/rsa/pss_test.go create mode 100644 src/crypto/rsa/rsa.go create mode 100644 src/crypto/rsa/rsa_test.go create mode 100644 src/crypto/rsa/testdata/pss-vect.txt.bz2 create mode 100644 src/crypto/sha1/example_test.go create mode 100644 src/crypto/sha1/sha1.go create mode 100644 src/crypto/sha1/sha1_test.go create mode 100644 src/crypto/sha1/sha1block.go create mode 100644 src/crypto/sha1/sha1block_386.s create mode 100644 src/crypto/sha1/sha1block_amd64.s create mode 100644 src/crypto/sha1/sha1block_amd64p32.s create mode 100644 src/crypto/sha1/sha1block_arm.s create mode 100644 src/crypto/sha1/sha1block_decl.go create mode 100644 src/crypto/sha1/sha1block_generic.go create mode 100644 src/crypto/sha256/sha256.go create mode 100644 src/crypto/sha256/sha256_test.go create mode 100644 src/crypto/sha256/sha256block.go create mode 100644 src/crypto/sha256/sha256block_386.s create mode 100644 src/crypto/sha256/sha256block_amd64.s create mode 100644 src/crypto/sha256/sha256block_decl.go create mode 100644 src/crypto/sha512/sha512.go create mode 100644 src/crypto/sha512/sha512_test.go create mode 100644 src/crypto/sha512/sha512block.go create mode 100644 src/crypto/sha512/sha512block_amd64.s create mode 100644 src/crypto/sha512/sha512block_decl.go create mode 100644 src/crypto/subtle/constant_time.go create mode 100644 src/crypto/subtle/constant_time_test.go create mode 100644 src/crypto/tls/alert.go create mode 100644 src/crypto/tls/cipher_suites.go create mode 100644 src/crypto/tls/common.go create mode 100644 src/crypto/tls/conn.go create mode 100644 src/crypto/tls/conn_test.go create mode 100644 src/crypto/tls/example_test.go create mode 100644 src/crypto/tls/generate_cert.go create mode 100644 src/crypto/tls/handshake_client.go create mode 100644 src/crypto/tls/handshake_client_test.go create mode 100644 src/crypto/tls/handshake_messages.go create mode 100644 src/crypto/tls/handshake_messages_test.go create mode 100644 src/crypto/tls/handshake_server.go create mode 100644 src/crypto/tls/handshake_server_test.go create mode 100644 src/crypto/tls/handshake_test.go create mode 100644 src/crypto/tls/key_agreement.go create mode 100644 src/crypto/tls/prf.go create mode 100644 src/crypto/tls/prf_test.go create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ALPN create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-SSLv3-RSA-3DES create mode 100644 src/crypto/tls/testdata/Server-SSLv3-RSA-AES create mode 100644 src/crypto/tls/testdata/Server-SSLv3-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv10-RSA-3DES create mode 100644 src/crypto/tls/testdata/Server-TLSv10-RSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV create mode 100644 src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ALPN create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch create mode 100644 src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA create mode 100644 src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv12-IssueTicket create mode 100644 src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-3DES create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-Resume create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled create mode 100644 src/crypto/tls/testdata/Server-TLSv12-SNI create mode 100644 src/crypto/tls/ticket.go create mode 100644 src/crypto/tls/tls.go create mode 100644 src/crypto/tls/tls_test.go create mode 100644 src/crypto/x509/cert_pool.go create mode 100644 src/crypto/x509/example_test.go create mode 100644 src/crypto/x509/pem_decrypt.go create mode 100644 src/crypto/x509/pem_decrypt_test.go create mode 100644 src/crypto/x509/pkcs1.go create mode 100644 src/crypto/x509/pkcs8.go create mode 100644 src/crypto/x509/pkcs8_test.go create mode 100644 src/crypto/x509/pkix/pkix.go create mode 100644 src/crypto/x509/root.go create mode 100644 src/crypto/x509/root_cgo_darwin.go create mode 100644 src/crypto/x509/root_darwin.go create mode 100644 src/crypto/x509/root_darwin_test.go create mode 100644 src/crypto/x509/root_nocgo_darwin.go create mode 100644 src/crypto/x509/root_plan9.go create mode 100644 src/crypto/x509/root_unix.go create mode 100644 src/crypto/x509/root_windows.go create mode 100644 src/crypto/x509/sec1.go create mode 100644 src/crypto/x509/sec1_test.go create mode 100644 src/crypto/x509/verify.go create mode 100644 src/crypto/x509/verify_test.go create mode 100644 src/crypto/x509/x509.go create mode 100644 src/crypto/x509/x509_test.go create mode 100644 src/crypto/x509/x509_test_import.go create mode 100644 src/database/sql/convert.go create mode 100644 src/database/sql/convert_test.go create mode 100644 src/database/sql/doc.txt create mode 100644 src/database/sql/driver/driver.go create mode 100644 src/database/sql/driver/types.go create mode 100644 src/database/sql/driver/types_test.go create mode 100644 src/database/sql/example_test.go create mode 100644 src/database/sql/fakedb_test.go create mode 100644 src/database/sql/sql.go create mode 100644 src/database/sql/sql_test.go create mode 100644 src/debug/dwarf/buf.go create mode 100644 src/debug/dwarf/const.go create mode 100644 src/debug/dwarf/entry.go create mode 100644 src/debug/dwarf/open.go create mode 100644 src/debug/dwarf/testdata/typedef.c create mode 100755 src/debug/dwarf/testdata/typedef.elf create mode 100644 src/debug/dwarf/testdata/typedef.elf4 create mode 100644 src/debug/dwarf/testdata/typedef.macho create mode 100644 src/debug/dwarf/type.go create mode 100644 src/debug/dwarf/type_test.go create mode 100644 src/debug/dwarf/typeunit.go create mode 100644 src/debug/dwarf/unit.go create mode 100644 src/debug/elf/elf.go create mode 100644 src/debug/elf/elf_test.go create mode 100644 src/debug/elf/file.go create mode 100644 src/debug/elf/file_test.go create mode 100644 src/debug/elf/symbols_test.go create mode 100755 src/debug/elf/testdata/gcc-386-freebsd-exec create mode 100755 src/debug/elf/testdata/gcc-amd64-linux-exec create mode 100644 src/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj create mode 100644 src/debug/elf/testdata/go-relocation-test-clang-x86.obj create mode 100644 src/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj create mode 100644 src/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj create mode 100644 src/debug/elf/testdata/go-relocation-test-gcc441-x86.obj create mode 100644 src/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj create mode 100644 src/debug/elf/testdata/hello-world-core.gz create mode 100644 src/debug/elf/testdata/hello.c create mode 100644 src/debug/gosym/pclinetest.asm create mode 100644 src/debug/gosym/pclinetest.h create mode 100644 src/debug/gosym/pclntab.go create mode 100644 src/debug/gosym/pclntab_test.go create mode 100644 src/debug/gosym/symtab.go create mode 100644 src/debug/macho/fat.go create mode 100644 src/debug/macho/file.go create mode 100644 src/debug/macho/file_test.go create mode 100644 src/debug/macho/macho.go create mode 100644 src/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec create mode 100755 src/debug/macho/testdata/gcc-386-darwin-exec create mode 100755 src/debug/macho/testdata/gcc-amd64-darwin-exec create mode 100644 src/debug/macho/testdata/gcc-amd64-darwin-exec-debug create mode 100644 src/debug/macho/testdata/hello.c create mode 100644 src/debug/pe/file.go create mode 100644 src/debug/pe/file_test.go create mode 100644 src/debug/pe/pe.go create mode 100644 src/debug/pe/testdata/gcc-386-mingw-exec create mode 100644 src/debug/pe/testdata/gcc-386-mingw-obj create mode 100644 src/debug/pe/testdata/gcc-amd64-mingw-exec create mode 100644 src/debug/pe/testdata/gcc-amd64-mingw-obj create mode 100644 src/debug/pe/testdata/hello.c create mode 100644 src/debug/plan9obj/file.go create mode 100644 src/debug/plan9obj/file_test.go create mode 100644 src/debug/plan9obj/plan9obj.go create mode 100755 src/debug/plan9obj/testdata/386-plan9-exec create mode 100755 src/debug/plan9obj/testdata/amd64-plan9-exec create mode 100644 src/debug/plan9obj/testdata/hello.c create mode 100644 src/encoding/ascii85/ascii85.go create mode 100644 src/encoding/ascii85/ascii85_test.go create mode 100644 src/encoding/asn1/asn1.go create mode 100644 src/encoding/asn1/asn1_test.go create mode 100644 src/encoding/asn1/common.go create mode 100644 src/encoding/asn1/marshal.go create mode 100644 src/encoding/asn1/marshal_test.go create mode 100644 src/encoding/base32/base32.go create mode 100644 src/encoding/base32/base32_test.go create mode 100644 src/encoding/base32/example_test.go create mode 100644 src/encoding/base64/base64.go create mode 100644 src/encoding/base64/base64_test.go create mode 100644 src/encoding/base64/example_test.go create mode 100644 src/encoding/binary/binary.go create mode 100644 src/encoding/binary/binary_test.go create mode 100644 src/encoding/binary/example_test.go create mode 100644 src/encoding/binary/varint.go create mode 100644 src/encoding/binary/varint_test.go create mode 100644 src/encoding/csv/reader.go create mode 100644 src/encoding/csv/reader_test.go create mode 100644 src/encoding/csv/writer.go create mode 100644 src/encoding/csv/writer_test.go create mode 100644 src/encoding/encoding.go create mode 100644 src/encoding/gob/codec_test.go create mode 100644 src/encoding/gob/debug.go create mode 100644 src/encoding/gob/dec_helpers.go create mode 100644 src/encoding/gob/decgen.go create mode 100644 src/encoding/gob/decode.go create mode 100644 src/encoding/gob/decoder.go create mode 100644 src/encoding/gob/doc.go create mode 100644 src/encoding/gob/dump.go create mode 100644 src/encoding/gob/enc_helpers.go create mode 100644 src/encoding/gob/encgen.go create mode 100644 src/encoding/gob/encode.go create mode 100644 src/encoding/gob/encoder.go create mode 100644 src/encoding/gob/encoder_test.go create mode 100644 src/encoding/gob/error.go create mode 100644 src/encoding/gob/example_encdec_test.go create mode 100644 src/encoding/gob/example_interface_test.go create mode 100644 src/encoding/gob/example_test.go create mode 100644 src/encoding/gob/gobencdec_test.go create mode 100644 src/encoding/gob/timing_test.go create mode 100644 src/encoding/gob/type.go create mode 100644 src/encoding/gob/type_test.go create mode 100644 src/encoding/hex/hex.go create mode 100644 src/encoding/hex/hex_test.go create mode 100644 src/encoding/json/bench_test.go create mode 100644 src/encoding/json/decode.go create mode 100644 src/encoding/json/decode_test.go create mode 100644 src/encoding/json/encode.go create mode 100644 src/encoding/json/encode_test.go create mode 100644 src/encoding/json/example_test.go create mode 100644 src/encoding/json/fold.go create mode 100644 src/encoding/json/fold_test.go create mode 100644 src/encoding/json/indent.go create mode 100644 src/encoding/json/scanner.go create mode 100644 src/encoding/json/scanner_test.go create mode 100644 src/encoding/json/stream.go create mode 100644 src/encoding/json/stream_test.go create mode 100644 src/encoding/json/tagkey_test.go create mode 100644 src/encoding/json/tags.go create mode 100644 src/encoding/json/tags_test.go create mode 100644 src/encoding/json/testdata/code.json.gz create mode 100644 src/encoding/pem/pem.go create mode 100644 src/encoding/pem/pem_test.go create mode 100644 src/encoding/xml/atom_test.go create mode 100644 src/encoding/xml/example_test.go create mode 100644 src/encoding/xml/marshal.go create mode 100644 src/encoding/xml/marshal_test.go create mode 100644 src/encoding/xml/read.go create mode 100644 src/encoding/xml/read_test.go create mode 100644 src/encoding/xml/typeinfo.go create mode 100644 src/encoding/xml/xml.go create mode 100644 src/encoding/xml/xml_test.go create mode 100644 src/errors/errors.go create mode 100644 src/errors/errors_test.go create mode 100644 src/errors/example_test.go create mode 100644 src/expvar/expvar.go create mode 100644 src/expvar/expvar_test.go create mode 100644 src/flag/example_test.go create mode 100644 src/flag/export_test.go create mode 100644 src/flag/flag.go create mode 100644 src/flag/flag_test.go create mode 100644 src/fmt/doc.go create mode 100644 src/fmt/export_test.go create mode 100644 src/fmt/fmt_test.go create mode 100644 src/fmt/format.go create mode 100644 src/fmt/print.go create mode 100644 src/fmt/scan.go create mode 100644 src/fmt/scan_test.go create mode 100644 src/fmt/stringer_test.go create mode 100644 src/go/ast/ast.go create mode 100644 src/go/ast/ast_test.go create mode 100644 src/go/ast/commentmap.go create mode 100644 src/go/ast/commentmap_test.go create mode 100644 src/go/ast/example_test.go create mode 100644 src/go/ast/filter.go create mode 100644 src/go/ast/filter_test.go create mode 100644 src/go/ast/import.go create mode 100644 src/go/ast/print.go create mode 100644 src/go/ast/print_test.go create mode 100644 src/go/ast/resolve.go create mode 100644 src/go/ast/scope.go create mode 100644 src/go/ast/walk.go create mode 100644 src/go/build/build.go create mode 100644 src/go/build/build_test.go create mode 100644 src/go/build/deps_test.go create mode 100644 src/go/build/doc.go create mode 100644 src/go/build/read.go create mode 100644 src/go/build/read_test.go create mode 100644 src/go/build/syslist.go create mode 100644 src/go/build/syslist_test.go create mode 100644 src/go/build/testdata/empty/dummy create mode 100644 src/go/build/testdata/multi/file.go create mode 100644 src/go/build/testdata/multi/file_appengine.go create mode 100644 src/go/build/testdata/other/file/file.go create mode 100644 src/go/build/testdata/other/main.go create mode 100644 src/go/doc/Makefile create mode 100644 src/go/doc/comment.go create mode 100644 src/go/doc/comment_test.go create mode 100644 src/go/doc/doc.go create mode 100644 src/go/doc/doc_test.go create mode 100644 src/go/doc/example.go create mode 100644 src/go/doc/example_test.go create mode 100644 src/go/doc/exports.go create mode 100644 src/go/doc/filter.go create mode 100644 src/go/doc/headscan.go create mode 100644 src/go/doc/reader.go create mode 100644 src/go/doc/synopsis.go create mode 100644 src/go/doc/synopsis_test.go create mode 100644 src/go/doc/testdata/a.0.golden create mode 100644 src/go/doc/testdata/a.1.golden create mode 100644 src/go/doc/testdata/a.2.golden create mode 100644 src/go/doc/testdata/a0.go create mode 100644 src/go/doc/testdata/a1.go create mode 100644 src/go/doc/testdata/b.0.golden create mode 100644 src/go/doc/testdata/b.1.golden create mode 100644 src/go/doc/testdata/b.2.golden create mode 100644 src/go/doc/testdata/b.go create mode 100644 src/go/doc/testdata/benchmark.go create mode 100644 src/go/doc/testdata/blank.0.golden create mode 100644 src/go/doc/testdata/blank.1.golden create mode 100644 src/go/doc/testdata/blank.2.golden create mode 100644 src/go/doc/testdata/blank.go create mode 100644 src/go/doc/testdata/bugpara.0.golden create mode 100644 src/go/doc/testdata/bugpara.1.golden create mode 100644 src/go/doc/testdata/bugpara.2.golden create mode 100644 src/go/doc/testdata/bugpara.go create mode 100644 src/go/doc/testdata/c.0.golden create mode 100644 src/go/doc/testdata/c.1.golden create mode 100644 src/go/doc/testdata/c.2.golden create mode 100644 src/go/doc/testdata/c.go create mode 100644 src/go/doc/testdata/d.0.golden create mode 100644 src/go/doc/testdata/d.1.golden create mode 100644 src/go/doc/testdata/d.2.golden create mode 100644 src/go/doc/testdata/d1.go create mode 100644 src/go/doc/testdata/d2.go create mode 100644 src/go/doc/testdata/e.0.golden create mode 100644 src/go/doc/testdata/e.1.golden create mode 100644 src/go/doc/testdata/e.2.golden create mode 100644 src/go/doc/testdata/e.go create mode 100644 src/go/doc/testdata/error1.0.golden create mode 100644 src/go/doc/testdata/error1.1.golden create mode 100644 src/go/doc/testdata/error1.2.golden create mode 100644 src/go/doc/testdata/error1.go create mode 100644 src/go/doc/testdata/error2.0.golden create mode 100644 src/go/doc/testdata/error2.1.golden create mode 100644 src/go/doc/testdata/error2.2.golden create mode 100644 src/go/doc/testdata/error2.go create mode 100644 src/go/doc/testdata/example.go create mode 100644 src/go/doc/testdata/f.0.golden create mode 100644 src/go/doc/testdata/f.1.golden create mode 100644 src/go/doc/testdata/f.2.golden create mode 100644 src/go/doc/testdata/f.go create mode 100644 src/go/doc/testdata/template.txt create mode 100644 src/go/doc/testdata/testing.0.golden create mode 100644 src/go/doc/testdata/testing.1.golden create mode 100644 src/go/doc/testdata/testing.2.golden create mode 100644 src/go/doc/testdata/testing.go create mode 100644 src/go/format/format.go create mode 100644 src/go/format/format_test.go create mode 100644 src/go/parser/error_test.go create mode 100644 src/go/parser/example_test.go create mode 100644 src/go/parser/interface.go create mode 100644 src/go/parser/parser.go create mode 100644 src/go/parser/parser_test.go create mode 100644 src/go/parser/performance_test.go create mode 100644 src/go/parser/short_test.go create mode 100644 src/go/parser/testdata/commas.src create mode 100644 src/go/parser/testdata/issue3106.src create mode 100644 src/go/printer/example_test.go create mode 100644 src/go/printer/nodes.go create mode 100644 src/go/printer/performance_test.go create mode 100644 src/go/printer/printer.go create mode 100644 src/go/printer/printer_test.go create mode 100644 src/go/printer/testdata/comments.golden create mode 100644 src/go/printer/testdata/comments.input create mode 100644 src/go/printer/testdata/comments.x create mode 100644 src/go/printer/testdata/comments2.golden create mode 100644 src/go/printer/testdata/comments2.input create mode 100644 src/go/printer/testdata/declarations.golden create mode 100644 src/go/printer/testdata/declarations.input create mode 100644 src/go/printer/testdata/empty.golden create mode 100644 src/go/printer/testdata/empty.input create mode 100644 src/go/printer/testdata/expressions.golden create mode 100644 src/go/printer/testdata/expressions.input create mode 100644 src/go/printer/testdata/expressions.raw create mode 100644 src/go/printer/testdata/linebreaks.golden create mode 100644 src/go/printer/testdata/linebreaks.input create mode 100644 src/go/printer/testdata/parser.go create mode 100644 src/go/printer/testdata/slow.golden create mode 100644 src/go/printer/testdata/slow.input create mode 100644 src/go/printer/testdata/statements.golden create mode 100644 src/go/printer/testdata/statements.input create mode 100644 src/go/scanner/errors.go create mode 100644 src/go/scanner/example_test.go create mode 100644 src/go/scanner/scanner.go create mode 100644 src/go/scanner/scanner_test.go create mode 100644 src/go/token/position.go create mode 100644 src/go/token/position_test.go create mode 100644 src/go/token/serialize.go create mode 100644 src/go/token/serialize_test.go create mode 100644 src/go/token/token.go create mode 100644 src/hash/adler32/adler32.go create mode 100644 src/hash/adler32/adler32_test.go create mode 100644 src/hash/crc32/crc32.go create mode 100644 src/hash/crc32/crc32_amd64.s create mode 100644 src/hash/crc32/crc32_amd64p32.s create mode 100644 src/hash/crc32/crc32_amd64x.go create mode 100644 src/hash/crc32/crc32_generic.go create mode 100644 src/hash/crc32/crc32_test.go create mode 100644 src/hash/crc64/crc64.go create mode 100644 src/hash/crc64/crc64_test.go create mode 100644 src/hash/fnv/fnv.go create mode 100644 src/hash/fnv/fnv_test.go create mode 100644 src/hash/hash.go create mode 100644 src/hash/test_cases.txt create mode 100644 src/hash/test_gen.awk create mode 100644 src/html/entity.go create mode 100644 src/html/entity_test.go create mode 100644 src/html/escape.go create mode 100644 src/html/escape_test.go create mode 100644 src/html/template/attr.go create mode 100644 src/html/template/clone_test.go create mode 100644 src/html/template/content.go create mode 100644 src/html/template/content_test.go create mode 100644 src/html/template/context.go create mode 100644 src/html/template/css.go create mode 100644 src/html/template/css_test.go create mode 100644 src/html/template/doc.go create mode 100644 src/html/template/error.go create mode 100644 src/html/template/escape.go create mode 100644 src/html/template/escape_test.go create mode 100644 src/html/template/html.go create mode 100644 src/html/template/html_test.go create mode 100644 src/html/template/js.go create mode 100644 src/html/template/js_test.go create mode 100644 src/html/template/template.go create mode 100644 src/html/template/transition.go create mode 100644 src/html/template/url.go create mode 100644 src/html/template/url_test.go create mode 100644 src/image/color/color.go create mode 100644 src/image/color/palette/gen.go create mode 100644 src/image/color/palette/generate.go create mode 100644 src/image/color/palette/palette.go create mode 100644 src/image/color/ycbcr.go create mode 100644 src/image/color/ycbcr_test.go create mode 100644 src/image/decode_example_test.go create mode 100644 src/image/decode_test.go create mode 100644 src/image/draw/bench_test.go create mode 100644 src/image/draw/clip_test.go create mode 100644 src/image/draw/draw.go create mode 100644 src/image/draw/draw_test.go create mode 100644 src/image/format.go create mode 100644 src/image/geom.go create mode 100644 src/image/gif/reader.go create mode 100644 src/image/gif/reader_test.go create mode 100644 src/image/gif/writer.go create mode 100644 src/image/gif/writer_test.go create mode 100644 src/image/image.go create mode 100644 src/image/image_test.go create mode 100644 src/image/jpeg/dct_test.go create mode 100644 src/image/jpeg/fdct.go create mode 100644 src/image/jpeg/huffman.go create mode 100644 src/image/jpeg/idct.go create mode 100644 src/image/jpeg/reader.go create mode 100644 src/image/jpeg/reader_test.go create mode 100644 src/image/jpeg/scan.go create mode 100644 src/image/jpeg/writer.go create mode 100644 src/image/jpeg/writer_test.go create mode 100644 src/image/names.go create mode 100644 src/image/png/paeth.go create mode 100644 src/image/png/paeth_test.go create mode 100644 src/image/png/reader.go create mode 100644 src/image/png/reader_test.go create mode 100644 src/image/png/testdata/benchGray.png create mode 100644 src/image/png/testdata/benchNRGBA-gradient.png create mode 100644 src/image/png/testdata/benchNRGBA-opaque.png create mode 100644 src/image/png/testdata/benchPaletted.png create mode 100644 src/image/png/testdata/benchRGB-interlace.png create mode 100644 src/image/png/testdata/benchRGB.png create mode 100644 src/image/png/testdata/invalid-crc32.png create mode 100644 src/image/png/testdata/invalid-noend.png create mode 100644 src/image/png/testdata/invalid-trunc.png create mode 100644 src/image/png/testdata/invalid-zlib.png create mode 100644 src/image/png/testdata/pngsuite/README create mode 100644 src/image/png/testdata/pngsuite/README.original create mode 100644 src/image/png/testdata/pngsuite/basn0g01-30.png create mode 100644 src/image/png/testdata/pngsuite/basn0g01-30.sng create mode 100644 src/image/png/testdata/pngsuite/basn0g01.png create mode 100644 src/image/png/testdata/pngsuite/basn0g01.sng create mode 100644 src/image/png/testdata/pngsuite/basn0g02-29.png create mode 100644 src/image/png/testdata/pngsuite/basn0g02-29.sng create mode 100644 src/image/png/testdata/pngsuite/basn0g02.png create mode 100644 src/image/png/testdata/pngsuite/basn0g02.sng create mode 100644 src/image/png/testdata/pngsuite/basn0g04-31.png create mode 100644 src/image/png/testdata/pngsuite/basn0g04-31.sng create mode 100644 src/image/png/testdata/pngsuite/basn0g04.png create mode 100644 src/image/png/testdata/pngsuite/basn0g04.sng create mode 100644 src/image/png/testdata/pngsuite/basn0g08.png create mode 100644 src/image/png/testdata/pngsuite/basn0g08.sng create mode 100644 src/image/png/testdata/pngsuite/basn0g16.png create mode 100644 src/image/png/testdata/pngsuite/basn0g16.sng create mode 100644 src/image/png/testdata/pngsuite/basn2c08.png create mode 100644 src/image/png/testdata/pngsuite/basn2c08.sng create mode 100644 src/image/png/testdata/pngsuite/basn2c16.png create mode 100644 src/image/png/testdata/pngsuite/basn2c16.sng create mode 100644 src/image/png/testdata/pngsuite/basn3p01.png create mode 100644 src/image/png/testdata/pngsuite/basn3p01.sng create mode 100644 src/image/png/testdata/pngsuite/basn3p02.png create mode 100644 src/image/png/testdata/pngsuite/basn3p02.sng create mode 100644 src/image/png/testdata/pngsuite/basn3p04-31i.png create mode 100644 src/image/png/testdata/pngsuite/basn3p04-31i.sng create mode 100644 src/image/png/testdata/pngsuite/basn3p04.png create mode 100644 src/image/png/testdata/pngsuite/basn3p04.sng create mode 100644 src/image/png/testdata/pngsuite/basn3p08-trns.png create mode 100644 src/image/png/testdata/pngsuite/basn3p08-trns.sng create mode 100644 src/image/png/testdata/pngsuite/basn3p08.png create mode 100644 src/image/png/testdata/pngsuite/basn3p08.sng create mode 100644 src/image/png/testdata/pngsuite/basn4a08.png create mode 100644 src/image/png/testdata/pngsuite/basn4a08.sng create mode 100644 src/image/png/testdata/pngsuite/basn4a16.png create mode 100644 src/image/png/testdata/pngsuite/basn4a16.sng create mode 100644 src/image/png/testdata/pngsuite/basn6a08.png create mode 100644 src/image/png/testdata/pngsuite/basn6a08.sng create mode 100644 src/image/png/testdata/pngsuite/basn6a16.png create mode 100644 src/image/png/testdata/pngsuite/basn6a16.sng create mode 100644 src/image/png/writer.go create mode 100644 src/image/png/writer_test.go create mode 100644 src/image/testdata/video-001.5bpp.gif create mode 100644 src/image/testdata/video-001.gif create mode 100644 src/image/testdata/video-001.interlaced.gif create mode 100644 src/image/testdata/video-001.jpeg create mode 100644 src/image/testdata/video-001.png create mode 100644 src/image/testdata/video-001.progressive.jpeg create mode 100644 src/image/testdata/video-001.q50.420.jpeg create mode 100644 src/image/testdata/video-001.q50.420.progressive.jpeg create mode 100644 src/image/testdata/video-001.q50.422.jpeg create mode 100644 src/image/testdata/video-001.q50.422.progressive.jpeg create mode 100644 src/image/testdata/video-001.q50.440.jpeg create mode 100644 src/image/testdata/video-001.q50.440.progressive.jpeg create mode 100644 src/image/testdata/video-001.q50.444.jpeg create mode 100644 src/image/testdata/video-001.q50.444.progressive.jpeg create mode 100644 src/image/testdata/video-001.separate.dc.progression.jpeg create mode 100644 src/image/testdata/video-001.separate.dc.progression.progressive.jpeg create mode 100644 src/image/testdata/video-005.gray.gif create mode 100644 src/image/testdata/video-005.gray.jpeg create mode 100644 src/image/testdata/video-005.gray.png create mode 100644 src/image/testdata/video-005.gray.q50.2x2.jpeg create mode 100644 src/image/testdata/video-005.gray.q50.2x2.progressive.jpeg create mode 100644 src/image/testdata/video-005.gray.q50.jpeg create mode 100644 src/image/testdata/video-005.gray.q50.progressive.jpeg create mode 100644 src/image/ycbcr.go create mode 100644 src/image/ycbcr_test.go create mode 100644 src/index/suffixarray/qsufsort.go create mode 100644 src/index/suffixarray/suffixarray.go create mode 100644 src/index/suffixarray/suffixarray_test.go create mode 100644 src/internal/syscall/getrandom_linux.go create mode 100644 src/io/io.go create mode 100644 src/io/io_test.go create mode 100644 src/io/ioutil/ioutil.go create mode 100644 src/io/ioutil/ioutil_test.go create mode 100644 src/io/ioutil/tempfile.go create mode 100644 src/io/ioutil/tempfile_test.go create mode 100644 src/io/multi.go create mode 100644 src/io/multi_test.go create mode 100644 src/io/pipe.go create mode 100644 src/io/pipe_test.go create mode 100644 src/log/example_test.go create mode 100644 src/log/log.go create mode 100644 src/log/log_test.go create mode 100644 src/log/syslog/syslog.go create mode 100644 src/log/syslog/syslog_plan9.go create mode 100644 src/log/syslog/syslog_test.go create mode 100644 src/log/syslog/syslog_unix.go create mode 100644 src/log/syslog/syslog_windows.go create mode 100644 src/math/abs.go create mode 100644 src/math/abs_386.s create mode 100644 src/math/abs_amd64.s create mode 100644 src/math/abs_amd64p32.s create mode 100644 src/math/abs_arm.s create mode 100644 src/math/acosh.go create mode 100644 src/math/all_test.go create mode 100644 src/math/asin.go create mode 100644 src/math/asin_386.s create mode 100644 src/math/asin_amd64.s create mode 100644 src/math/asin_amd64p32.s create mode 100644 src/math/asin_arm.s create mode 100644 src/math/asinh.go create mode 100644 src/math/atan.go create mode 100644 src/math/atan2.go create mode 100644 src/math/atan2_386.s create mode 100644 src/math/atan2_amd64.s create mode 100644 src/math/atan2_amd64p32.s create mode 100644 src/math/atan2_arm.s create mode 100644 src/math/atan_386.s create mode 100644 src/math/atan_amd64.s create mode 100644 src/math/atan_amd64p32.s create mode 100644 src/math/atan_arm.s create mode 100644 src/math/atanh.go create mode 100644 src/math/big/arith.go create mode 100644 src/math/big/arith_386.s create mode 100644 src/math/big/arith_amd64.s create mode 100644 src/math/big/arith_amd64p32.s create mode 100644 src/math/big/arith_arm.s create mode 100644 src/math/big/arith_decl.go create mode 100644 src/math/big/arith_test.go create mode 100644 src/math/big/calibrate_test.go create mode 100644 src/math/big/example_test.go create mode 100644 src/math/big/gcd_test.go create mode 100644 src/math/big/hilbert_test.go create mode 100644 src/math/big/int.go create mode 100644 src/math/big/int_test.go create mode 100644 src/math/big/nat.go create mode 100644 src/math/big/nat_test.go create mode 100644 src/math/big/rat.go create mode 100644 src/math/big/rat_test.go create mode 100644 src/math/bits.go create mode 100644 src/math/cbrt.go create mode 100644 src/math/cmplx/abs.go create mode 100644 src/math/cmplx/asin.go create mode 100644 src/math/cmplx/cmath_test.go create mode 100644 src/math/cmplx/conj.go create mode 100644 src/math/cmplx/exp.go create mode 100644 src/math/cmplx/isinf.go create mode 100644 src/math/cmplx/isnan.go create mode 100644 src/math/cmplx/log.go create mode 100644 src/math/cmplx/phase.go create mode 100644 src/math/cmplx/polar.go create mode 100644 src/math/cmplx/pow.go create mode 100644 src/math/cmplx/rect.go create mode 100644 src/math/cmplx/sin.go create mode 100644 src/math/cmplx/sqrt.go create mode 100644 src/math/cmplx/tan.go create mode 100644 src/math/const.go create mode 100644 src/math/copysign.go create mode 100644 src/math/dim.go create mode 100644 src/math/dim_386.s create mode 100644 src/math/dim_amd64.s create mode 100644 src/math/dim_amd64p32.s create mode 100644 src/math/dim_arm.s create mode 100644 src/math/erf.go create mode 100644 src/math/exp.go create mode 100644 src/math/exp2_386.s create mode 100644 src/math/exp2_amd64.s create mode 100644 src/math/exp2_amd64p32.s create mode 100644 src/math/exp2_arm.s create mode 100644 src/math/exp_386.s create mode 100644 src/math/exp_amd64.s create mode 100644 src/math/exp_amd64p32.s create mode 100644 src/math/exp_arm.s create mode 100644 src/math/expm1.go create mode 100644 src/math/expm1_386.s create mode 100644 src/math/expm1_amd64.s create mode 100644 src/math/expm1_amd64p32.s create mode 100644 src/math/expm1_arm.s create mode 100644 src/math/export_test.go create mode 100644 src/math/floor.go create mode 100644 src/math/floor_386.s create mode 100644 src/math/floor_amd64.s create mode 100644 src/math/floor_amd64p32.s create mode 100644 src/math/floor_arm.s create mode 100644 src/math/frexp.go create mode 100644 src/math/frexp_386.s create mode 100644 src/math/frexp_amd64.s create mode 100644 src/math/frexp_amd64p32.s create mode 100644 src/math/frexp_arm.s create mode 100644 src/math/gamma.go create mode 100644 src/math/hypot.go create mode 100644 src/math/hypot_386.s create mode 100644 src/math/hypot_amd64.s create mode 100644 src/math/hypot_amd64p32.s create mode 100644 src/math/hypot_arm.s create mode 100644 src/math/j0.go create mode 100644 src/math/j1.go create mode 100644 src/math/jn.go create mode 100644 src/math/ldexp.go create mode 100644 src/math/ldexp_386.s create mode 100644 src/math/ldexp_amd64.s create mode 100644 src/math/ldexp_amd64p32.s create mode 100644 src/math/ldexp_arm.s create mode 100644 src/math/lgamma.go create mode 100644 src/math/log.go create mode 100644 src/math/log10.go create mode 100644 src/math/log10_386.s create mode 100644 src/math/log10_amd64.s create mode 100644 src/math/log10_amd64p32.s create mode 100644 src/math/log10_arm.s create mode 100644 src/math/log1p.go create mode 100644 src/math/log1p_386.s create mode 100644 src/math/log1p_amd64.s create mode 100644 src/math/log1p_amd64p32.s create mode 100644 src/math/log1p_arm.s create mode 100644 src/math/log_386.s create mode 100644 src/math/log_amd64.s create mode 100644 src/math/log_amd64p32.s create mode 100644 src/math/log_arm.s create mode 100644 src/math/logb.go create mode 100644 src/math/mod.go create mode 100644 src/math/mod_386.s create mode 100644 src/math/mod_amd64.s create mode 100644 src/math/mod_amd64p32.s create mode 100644 src/math/mod_arm.s create mode 100644 src/math/modf.go create mode 100644 src/math/modf_386.s create mode 100644 src/math/modf_amd64.s create mode 100644 src/math/modf_amd64p32.s create mode 100644 src/math/modf_arm.s create mode 100644 src/math/nextafter.go create mode 100644 src/math/pow.go create mode 100644 src/math/pow10.go create mode 100644 src/math/rand/example_test.go create mode 100644 src/math/rand/exp.go create mode 100644 src/math/rand/normal.go create mode 100644 src/math/rand/rand.go create mode 100644 src/math/rand/rand_test.go create mode 100644 src/math/rand/regress_test.go create mode 100644 src/math/rand/rng.go create mode 100644 src/math/rand/zipf.go create mode 100644 src/math/remainder.go create mode 100644 src/math/remainder_386.s create mode 100644 src/math/remainder_amd64.s create mode 100644 src/math/remainder_amd64p32.s create mode 100644 src/math/remainder_arm.s create mode 100644 src/math/signbit.go create mode 100644 src/math/sin.go create mode 100644 src/math/sin_386.s create mode 100644 src/math/sin_amd64.s create mode 100644 src/math/sin_amd64p32.s create mode 100644 src/math/sin_arm.s create mode 100644 src/math/sincos.go create mode 100644 src/math/sincos_386.s create mode 100644 src/math/sincos_amd64.s create mode 100644 src/math/sincos_amd64p32.s create mode 100644 src/math/sincos_arm.s create mode 100644 src/math/sinh.go create mode 100644 src/math/sqrt.go create mode 100644 src/math/sqrt_386.s create mode 100644 src/math/sqrt_amd64.s create mode 100644 src/math/sqrt_amd64p32.s create mode 100644 src/math/sqrt_arm.s create mode 100644 src/math/tan.go create mode 100644 src/math/tan_386.s create mode 100644 src/math/tan_amd64.s create mode 100644 src/math/tan_amd64p32.s create mode 100644 src/math/tan_arm.s create mode 100644 src/math/tanh.go create mode 100644 src/math/unsafe.go create mode 100644 src/mime/grammar.go create mode 100644 src/mime/mediatype.go create mode 100644 src/mime/mediatype_test.go create mode 100644 src/mime/multipart/example_test.go create mode 100644 src/mime/multipart/formdata.go create mode 100644 src/mime/multipart/formdata_test.go create mode 100644 src/mime/multipart/multipart.go create mode 100644 src/mime/multipart/multipart_test.go create mode 100644 src/mime/multipart/quotedprintable.go create mode 100644 src/mime/multipart/quotedprintable_test.go create mode 100644 src/mime/multipart/testdata/nested-mime create mode 100644 src/mime/multipart/writer.go create mode 100644 src/mime/multipart/writer_test.go create mode 100644 src/mime/testdata/test.types create mode 100644 src/mime/testdata/test.types.plan9 create mode 100644 src/mime/type.go create mode 100644 src/mime/type_plan9.go create mode 100644 src/mime/type_test.go create mode 100644 src/mime/type_unix.go create mode 100644 src/mime/type_windows.go create mode 100644 src/net/cgo_android.go create mode 100644 src/net/cgo_bsd.go create mode 100644 src/net/cgo_linux.go create mode 100644 src/net/cgo_netbsd.go create mode 100644 src/net/cgo_openbsd.go create mode 100644 src/net/cgo_stub.go create mode 100644 src/net/cgo_unix.go create mode 100644 src/net/cgo_unix_test.go create mode 100644 src/net/conn_test.go create mode 100644 src/net/dial.go create mode 100644 src/net/dial_gen.go create mode 100644 src/net/dial_gen_test.go create mode 100644 src/net/dial_test.go create mode 100644 src/net/dialgoogle_test.go create mode 100644 src/net/dnsclient.go create mode 100644 src/net/dnsclient_test.go create mode 100644 src/net/dnsclient_unix.go create mode 100644 src/net/dnsclient_unix_test.go create mode 100644 src/net/dnsconfig_unix.go create mode 100644 src/net/dnsconfig_unix_test.go create mode 100644 src/net/dnsmsg.go create mode 100644 src/net/dnsmsg_test.go create mode 100644 src/net/dnsname_test.go create mode 100644 src/net/example_test.go create mode 100644 src/net/fd_mutex.go create mode 100644 src/net/fd_mutex_test.go create mode 100644 src/net/fd_plan9.go create mode 100644 src/net/fd_poll_nacl.go create mode 100644 src/net/fd_poll_runtime.go create mode 100644 src/net/fd_unix.go create mode 100644 src/net/fd_unix_test.go create mode 100644 src/net/fd_windows.go create mode 100644 src/net/file_plan9.go create mode 100644 src/net/file_stub.go create mode 100644 src/net/file_test.go create mode 100644 src/net/file_unix.go create mode 100644 src/net/file_windows.go create mode 100644 src/net/hosts.go create mode 100644 src/net/hosts_test.go create mode 100644 src/net/http/cgi/child.go create mode 100644 src/net/http/cgi/child_test.go create mode 100644 src/net/http/cgi/host.go create mode 100644 src/net/http/cgi/host_test.go create mode 100644 src/net/http/cgi/matryoshka_test.go create mode 100644 src/net/http/cgi/plan9_test.go create mode 100644 src/net/http/cgi/posix_test.go create mode 100755 src/net/http/cgi/testdata/test.cgi create mode 100644 src/net/http/client.go create mode 100644 src/net/http/client_test.go create mode 100644 src/net/http/cookie.go create mode 100644 src/net/http/cookie_test.go create mode 100644 src/net/http/cookiejar/jar.go create mode 100644 src/net/http/cookiejar/jar_test.go create mode 100644 src/net/http/cookiejar/punycode.go create mode 100644 src/net/http/cookiejar/punycode_test.go create mode 100644 src/net/http/doc.go create mode 100644 src/net/http/example_test.go create mode 100644 src/net/http/export_test.go create mode 100644 src/net/http/fcgi/child.go create mode 100644 src/net/http/fcgi/fcgi.go create mode 100644 src/net/http/fcgi/fcgi_test.go create mode 100644 src/net/http/filetransport.go create mode 100644 src/net/http/filetransport_test.go create mode 100644 src/net/http/fs.go create mode 100644 src/net/http/fs_test.go create mode 100644 src/net/http/header.go create mode 100644 src/net/http/header_test.go create mode 100644 src/net/http/httptest/example_test.go create mode 100644 src/net/http/httptest/recorder.go create mode 100644 src/net/http/httptest/recorder_test.go create mode 100644 src/net/http/httptest/server.go create mode 100644 src/net/http/httptest/server_test.go create mode 100644 src/net/http/httputil/dump.go create mode 100644 src/net/http/httputil/dump_test.go create mode 100644 src/net/http/httputil/httputil.go create mode 100644 src/net/http/httputil/persist.go create mode 100644 src/net/http/httputil/reverseproxy.go create mode 100644 src/net/http/httputil/reverseproxy_test.go create mode 100644 src/net/http/internal/chunked.go create mode 100644 src/net/http/internal/chunked_test.go create mode 100644 src/net/http/jar.go create mode 100644 src/net/http/lex.go create mode 100644 src/net/http/lex_test.go create mode 100644 src/net/http/main_test.go create mode 100644 src/net/http/npn_test.go create mode 100644 src/net/http/pprof/pprof.go create mode 100644 src/net/http/proxy_test.go create mode 100644 src/net/http/race.go create mode 100644 src/net/http/range_test.go create mode 100644 src/net/http/readrequest_test.go create mode 100644 src/net/http/request.go create mode 100644 src/net/http/request_test.go create mode 100644 src/net/http/requestwrite_test.go create mode 100644 src/net/http/response.go create mode 100644 src/net/http/response_test.go create mode 100644 src/net/http/responsewrite_test.go create mode 100644 src/net/http/serve_test.go create mode 100644 src/net/http/server.go create mode 100644 src/net/http/sniff.go create mode 100644 src/net/http/sniff_test.go create mode 100644 src/net/http/status.go create mode 100644 src/net/http/testdata/file create mode 100644 src/net/http/testdata/index.html create mode 100644 src/net/http/testdata/style.css create mode 100644 src/net/http/transfer.go create mode 100644 src/net/http/transfer_test.go create mode 100644 src/net/http/transport.go create mode 100644 src/net/http/transport_test.go create mode 100644 src/net/http/triv.go create mode 100644 src/net/interface.go create mode 100644 src/net/interface_bsd.go create mode 100644 src/net/interface_bsd_test.go create mode 100644 src/net/interface_darwin.go create mode 100644 src/net/interface_dragonfly.go create mode 100644 src/net/interface_freebsd.go create mode 100644 src/net/interface_linux.go create mode 100644 src/net/interface_linux_test.go create mode 100644 src/net/interface_netbsd.go create mode 100644 src/net/interface_openbsd.go create mode 100644 src/net/interface_stub.go create mode 100644 src/net/interface_test.go create mode 100644 src/net/interface_unix_test.go create mode 100644 src/net/interface_windows.go create mode 100644 src/net/ip.go create mode 100644 src/net/ip_test.go create mode 100644 src/net/ipraw_test.go create mode 100644 src/net/iprawsock.go create mode 100644 src/net/iprawsock_plan9.go create mode 100644 src/net/iprawsock_posix.go create mode 100644 src/net/ipsock.go create mode 100644 src/net/ipsock_plan9.go create mode 100644 src/net/ipsock_posix.go create mode 100644 src/net/ipsock_test.go create mode 100644 src/net/lookup.go create mode 100644 src/net/lookup_plan9.go create mode 100644 src/net/lookup_stub.go create mode 100644 src/net/lookup_test.go create mode 100644 src/net/lookup_unix.go create mode 100644 src/net/lookup_windows.go create mode 100644 src/net/lookup_windows_test.go create mode 100644 src/net/mac.go create mode 100644 src/net/mac_test.go create mode 100644 src/net/mail/message.go create mode 100644 src/net/mail/message_test.go create mode 100644 src/net/mockicmp_test.go create mode 100644 src/net/mockserver_test.go create mode 100644 src/net/multicast_test.go create mode 100644 src/net/net.go create mode 100644 src/net/net_test.go create mode 100644 src/net/net_windows_test.go create mode 100644 src/net/netgo_unix_test.go create mode 100644 src/net/packetconn_test.go create mode 100644 src/net/parse.go create mode 100644 src/net/parse_test.go create mode 100644 src/net/pipe.go create mode 100644 src/net/pipe_test.go create mode 100644 src/net/port.go create mode 100644 src/net/port_test.go create mode 100644 src/net/port_unix.go create mode 100644 src/net/protoconn_test.go create mode 100644 src/net/race.go create mode 100644 src/net/race0.go create mode 100644 src/net/rpc/client.go create mode 100644 src/net/rpc/client_test.go create mode 100644 src/net/rpc/debug.go create mode 100644 src/net/rpc/jsonrpc/all_test.go create mode 100644 src/net/rpc/jsonrpc/client.go create mode 100644 src/net/rpc/jsonrpc/server.go create mode 100644 src/net/rpc/server.go create mode 100644 src/net/rpc/server_test.go create mode 100644 src/net/sendfile_dragonfly.go create mode 100644 src/net/sendfile_freebsd.go create mode 100644 src/net/sendfile_linux.go create mode 100644 src/net/sendfile_stub.go create mode 100644 src/net/sendfile_windows.go create mode 100644 src/net/server_test.go create mode 100644 src/net/singleflight.go create mode 100644 src/net/smtp/auth.go create mode 100644 src/net/smtp/example_test.go create mode 100644 src/net/smtp/smtp.go create mode 100644 src/net/smtp/smtp_test.go create mode 100644 src/net/sock_bsd.go create mode 100644 src/net/sock_cloexec.go create mode 100644 src/net/sock_linux.go create mode 100644 src/net/sock_plan9.go create mode 100644 src/net/sock_posix.go create mode 100644 src/net/sock_stub.go create mode 100644 src/net/sock_windows.go create mode 100644 src/net/sockopt_bsd.go create mode 100644 src/net/sockopt_linux.go create mode 100644 src/net/sockopt_plan9.go create mode 100644 src/net/sockopt_posix.go create mode 100644 src/net/sockopt_solaris.go create mode 100644 src/net/sockopt_stub.go create mode 100644 src/net/sockopt_windows.go create mode 100644 src/net/sockoptip_bsd.go create mode 100644 src/net/sockoptip_linux.go create mode 100644 src/net/sockoptip_posix.go create mode 100644 src/net/sockoptip_stub.go create mode 100644 src/net/sockoptip_windows.go create mode 100644 src/net/sys_cloexec.go create mode 100644 src/net/tcp_test.go create mode 100644 src/net/tcpsock.go create mode 100644 src/net/tcpsock_plan9.go create mode 100644 src/net/tcpsock_posix.go create mode 100644 src/net/tcpsockopt_darwin.go create mode 100644 src/net/tcpsockopt_dragonfly.go create mode 100644 src/net/tcpsockopt_openbsd.go create mode 100644 src/net/tcpsockopt_plan9.go create mode 100644 src/net/tcpsockopt_posix.go create mode 100644 src/net/tcpsockopt_stub.go create mode 100644 src/net/tcpsockopt_unix.go create mode 100644 src/net/tcpsockopt_windows.go create mode 100644 src/net/testdata/domain-resolv.conf create mode 100644 src/net/testdata/empty-resolv.conf create mode 100644 src/net/testdata/hosts create mode 100644 src/net/testdata/hosts_singleline create mode 100644 src/net/testdata/igmp create mode 100644 src/net/testdata/igmp6 create mode 100644 src/net/testdata/resolv.conf create mode 100644 src/net/testdata/search-resolv.conf create mode 100644 src/net/textproto/header.go create mode 100644 src/net/textproto/pipeline.go create mode 100644 src/net/textproto/reader.go create mode 100644 src/net/textproto/reader_test.go create mode 100644 src/net/textproto/textproto.go create mode 100644 src/net/textproto/writer.go create mode 100644 src/net/textproto/writer_test.go create mode 100644 src/net/timeout_test.go create mode 100644 src/net/udp_test.go create mode 100644 src/net/udpsock.go create mode 100644 src/net/udpsock_plan9.go create mode 100644 src/net/udpsock_posix.go create mode 100644 src/net/unicast_posix_test.go create mode 100644 src/net/unix_test.go create mode 100644 src/net/unixsock.go create mode 100644 src/net/unixsock_plan9.go create mode 100644 src/net/unixsock_posix.go create mode 100644 src/net/url/example_test.go create mode 100644 src/net/url/url.go create mode 100644 src/net/url/url_test.go create mode 100644 src/net/z_last_test.go create mode 100644 src/os/dir_plan9.go create mode 100644 src/os/dir_unix.go create mode 100644 src/os/dir_windows.go create mode 100644 src/os/doc.go create mode 100644 src/os/env.go create mode 100644 src/os/env_test.go create mode 100644 src/os/env_unix_test.go create mode 100644 src/os/error.go create mode 100644 src/os/error_plan9.go create mode 100644 src/os/error_test.go create mode 100644 src/os/error_unix.go create mode 100644 src/os/error_windows.go create mode 100644 src/os/error_windows_test.go create mode 100644 src/os/exec.go create mode 100644 src/os/exec/example_test.go create mode 100644 src/os/exec/exec.go create mode 100644 src/os/exec/exec_test.go create mode 100644 src/os/exec/lp_plan9.go create mode 100644 src/os/exec/lp_test.go create mode 100644 src/os/exec/lp_unix.go create mode 100644 src/os/exec/lp_unix_test.go create mode 100644 src/os/exec/lp_windows.go create mode 100644 src/os/exec/lp_windows_test.go create mode 100644 src/os/exec_plan9.go create mode 100644 src/os/exec_posix.go create mode 100644 src/os/exec_unix.go create mode 100644 src/os/exec_windows.go create mode 100644 src/os/export_test.go create mode 100644 src/os/file.go create mode 100644 src/os/file_plan9.go create mode 100644 src/os/file_posix.go create mode 100644 src/os/file_unix.go create mode 100644 src/os/file_windows.go create mode 100644 src/os/getwd.go create mode 100644 src/os/getwd_darwin.go create mode 100644 src/os/os_test.go create mode 100644 src/os/os_unix_test.go create mode 100644 src/os/os_windows_test.go create mode 100644 src/os/path.go create mode 100644 src/os/path_plan9.go create mode 100644 src/os/path_test.go create mode 100644 src/os/path_unix.go create mode 100644 src/os/path_windows.go create mode 100644 src/os/pipe_bsd.go create mode 100644 src/os/pipe_linux.go create mode 100644 src/os/proc.go create mode 100644 src/os/signal/example_test.go create mode 100644 src/os/signal/sig.s create mode 100644 src/os/signal/signal.go create mode 100644 src/os/signal/signal_stub.go create mode 100644 src/os/signal/signal_test.go create mode 100644 src/os/signal/signal_unix.go create mode 100644 src/os/signal/signal_windows_test.go create mode 100644 src/os/stat_darwin.go create mode 100644 src/os/stat_dragonfly.go create mode 100644 src/os/stat_freebsd.go create mode 100644 src/os/stat_linux.go create mode 100644 src/os/stat_nacl.go create mode 100644 src/os/stat_netbsd.go create mode 100644 src/os/stat_openbsd.go create mode 100644 src/os/stat_plan9.go create mode 100644 src/os/stat_solaris.go create mode 100644 src/os/stat_windows.go create mode 100644 src/os/str.go create mode 100644 src/os/sys_bsd.go create mode 100644 src/os/sys_darwin.go create mode 100644 src/os/sys_freebsd.go create mode 100644 src/os/sys_linux.go create mode 100644 src/os/sys_nacl.go create mode 100644 src/os/sys_plan9.go create mode 100644 src/os/sys_solaris.go create mode 100644 src/os/sys_unix.go create mode 100644 src/os/sys_windows.go create mode 100644 src/os/types.go create mode 100644 src/os/types_notwin.go create mode 100644 src/os/types_windows.go create mode 100644 src/os/user/lookup.go create mode 100644 src/os/user/lookup_plan9.go create mode 100644 src/os/user/lookup_stubs.go create mode 100644 src/os/user/lookup_unix.go create mode 100644 src/os/user/lookup_windows.go create mode 100644 src/os/user/user.go create mode 100644 src/os/user/user_test.go create mode 100644 src/path/example_test.go create mode 100644 src/path/filepath/example_unix_test.go create mode 100644 src/path/filepath/export_test.go create mode 100644 src/path/filepath/match.go create mode 100644 src/path/filepath/match_test.go create mode 100644 src/path/filepath/path.go create mode 100644 src/path/filepath/path_plan9.go create mode 100644 src/path/filepath/path_test.go create mode 100644 src/path/filepath/path_unix.go create mode 100644 src/path/filepath/path_windows.go create mode 100644 src/path/filepath/path_windows_test.go create mode 100644 src/path/filepath/symlink.go create mode 100644 src/path/filepath/symlink_unix.go create mode 100644 src/path/filepath/symlink_windows.go create mode 100644 src/path/match.go create mode 100644 src/path/match_test.go create mode 100644 src/path/path.go create mode 100644 src/path/path_test.go delete mode 100644 src/pkg/archive/tar/common.go delete mode 100644 src/pkg/archive/tar/example_test.go delete mode 100644 src/pkg/archive/tar/reader.go delete mode 100644 src/pkg/archive/tar/reader_test.go delete mode 100644 src/pkg/archive/tar/stat_atim.go delete mode 100644 src/pkg/archive/tar/stat_atimespec.go delete mode 100644 src/pkg/archive/tar/stat_unix.go delete mode 100644 src/pkg/archive/tar/tar_test.go delete mode 100644 src/pkg/archive/tar/testdata/gnu.tar delete mode 100644 src/pkg/archive/tar/testdata/nil-uid.tar delete mode 100644 src/pkg/archive/tar/testdata/pax.tar delete mode 100644 src/pkg/archive/tar/testdata/small.txt delete mode 100644 src/pkg/archive/tar/testdata/small2.txt delete mode 100644 src/pkg/archive/tar/testdata/sparse-formats.tar delete mode 100644 src/pkg/archive/tar/testdata/star.tar delete mode 100644 src/pkg/archive/tar/testdata/ustar.tar delete mode 100644 src/pkg/archive/tar/testdata/v7.tar delete mode 100644 src/pkg/archive/tar/testdata/writer-big-long.tar delete mode 100644 src/pkg/archive/tar/testdata/writer-big.tar delete mode 100644 src/pkg/archive/tar/testdata/writer.tar delete mode 100644 src/pkg/archive/tar/testdata/xattrs.tar delete mode 100644 src/pkg/archive/tar/writer.go delete mode 100644 src/pkg/archive/tar/writer_test.go delete mode 100644 src/pkg/archive/zip/example_test.go delete mode 100644 src/pkg/archive/zip/reader.go delete mode 100644 src/pkg/archive/zip/reader_test.go delete mode 100644 src/pkg/archive/zip/register.go delete mode 100644 src/pkg/archive/zip/struct.go delete mode 100644 src/pkg/archive/zip/testdata/crc32-not-streamed.zip delete mode 100644 src/pkg/archive/zip/testdata/dd.zip delete mode 100644 src/pkg/archive/zip/testdata/go-no-datadesc-sig.zip delete mode 100644 src/pkg/archive/zip/testdata/go-with-datadesc-sig.zip delete mode 100644 src/pkg/archive/zip/testdata/gophercolor16x16.png delete mode 100644 src/pkg/archive/zip/testdata/readme.notzip delete mode 100644 src/pkg/archive/zip/testdata/readme.zip delete mode 100644 src/pkg/archive/zip/testdata/symlink.zip delete mode 100644 src/pkg/archive/zip/testdata/test-trailing-junk.zip delete mode 100644 src/pkg/archive/zip/testdata/test.zip delete mode 100644 src/pkg/archive/zip/testdata/unix.zip delete mode 100644 src/pkg/archive/zip/testdata/winxp.zip delete mode 100644 src/pkg/archive/zip/testdata/zip64-2.zip delete mode 100644 src/pkg/archive/zip/testdata/zip64.zip delete mode 100644 src/pkg/archive/zip/writer.go delete mode 100644 src/pkg/archive/zip/writer_test.go delete mode 100644 src/pkg/archive/zip/zip_test.go delete mode 100644 src/pkg/bufio/bufio.go delete mode 100644 src/pkg/bufio/bufio_test.go delete mode 100644 src/pkg/bufio/example_test.go delete mode 100644 src/pkg/bufio/export_test.go delete mode 100644 src/pkg/bufio/scan.go delete mode 100644 src/pkg/bufio/scan_test.go delete mode 100644 src/pkg/builtin/builtin.go delete mode 100644 src/pkg/bytes/buffer.go delete mode 100644 src/pkg/bytes/buffer_test.go delete mode 100644 src/pkg/bytes/bytes.go delete mode 100644 src/pkg/bytes/bytes.s delete mode 100644 src/pkg/bytes/bytes_decl.go delete mode 100644 src/pkg/bytes/bytes_test.go delete mode 100644 src/pkg/bytes/compare_test.go delete mode 100644 src/pkg/bytes/equal_test.go delete mode 100644 src/pkg/bytes/example_test.go delete mode 100644 src/pkg/bytes/export_test.go delete mode 100644 src/pkg/bytes/reader.go delete mode 100644 src/pkg/bytes/reader_test.go delete mode 100644 src/pkg/compress/bzip2/bit_reader.go delete mode 100644 src/pkg/compress/bzip2/bzip2.go delete mode 100644 src/pkg/compress/bzip2/bzip2_test.go delete mode 100644 src/pkg/compress/bzip2/huffman.go delete mode 100644 src/pkg/compress/bzip2/move_to_front.go delete mode 100644 src/pkg/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 delete mode 100644 src/pkg/compress/bzip2/testdata/e.txt.bz2 delete mode 100644 src/pkg/compress/flate/copy.go delete mode 100644 src/pkg/compress/flate/copy_test.go delete mode 100644 src/pkg/compress/flate/deflate.go delete mode 100644 src/pkg/compress/flate/deflate_test.go delete mode 100644 src/pkg/compress/flate/fixedhuff.go delete mode 100644 src/pkg/compress/flate/flate_test.go delete mode 100644 src/pkg/compress/flate/gen.go delete mode 100644 src/pkg/compress/flate/huffman_bit_writer.go delete mode 100644 src/pkg/compress/flate/huffman_code.go delete mode 100644 src/pkg/compress/flate/inflate.go delete mode 100644 src/pkg/compress/flate/reader_test.go delete mode 100644 src/pkg/compress/flate/reverse_bits.go delete mode 100644 src/pkg/compress/flate/token.go delete mode 100644 src/pkg/compress/flate/writer_test.go delete mode 100644 src/pkg/compress/gzip/gunzip.go delete mode 100644 src/pkg/compress/gzip/gunzip_test.go delete mode 100644 src/pkg/compress/gzip/gzip.go delete mode 100644 src/pkg/compress/gzip/gzip_test.go delete mode 100644 src/pkg/compress/gzip/testdata/issue6550.gz delete mode 100644 src/pkg/compress/lzw/reader.go delete mode 100644 src/pkg/compress/lzw/reader_test.go delete mode 100644 src/pkg/compress/lzw/writer.go delete mode 100644 src/pkg/compress/lzw/writer_test.go delete mode 100644 src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt delete mode 100644 src/pkg/compress/testdata/e.txt delete mode 100644 src/pkg/compress/testdata/pi.txt delete mode 100644 src/pkg/compress/zlib/example_test.go delete mode 100644 src/pkg/compress/zlib/reader.go delete mode 100644 src/pkg/compress/zlib/reader_test.go delete mode 100644 src/pkg/compress/zlib/writer.go delete mode 100644 src/pkg/compress/zlib/writer_test.go delete mode 100644 src/pkg/container/heap/example_intheap_test.go delete mode 100644 src/pkg/container/heap/example_pq_test.go delete mode 100644 src/pkg/container/heap/heap.go delete mode 100644 src/pkg/container/heap/heap_test.go delete mode 100644 src/pkg/container/list/example_test.go delete mode 100644 src/pkg/container/list/list.go delete mode 100644 src/pkg/container/list/list_test.go delete mode 100644 src/pkg/container/ring/ring.go delete mode 100644 src/pkg/container/ring/ring_test.go delete mode 100644 src/pkg/crypto/aes/aes_test.go delete mode 100644 src/pkg/crypto/aes/asm_amd64.s delete mode 100644 src/pkg/crypto/aes/block.go delete mode 100644 src/pkg/crypto/aes/cipher.go delete mode 100644 src/pkg/crypto/aes/cipher_asm.go delete mode 100644 src/pkg/crypto/aes/cipher_generic.go delete mode 100644 src/pkg/crypto/aes/const.go delete mode 100644 src/pkg/crypto/cipher/benchmark_test.go delete mode 100644 src/pkg/crypto/cipher/cbc.go delete mode 100644 src/pkg/crypto/cipher/cbc_aes_test.go delete mode 100644 src/pkg/crypto/cipher/cfb.go delete mode 100644 src/pkg/crypto/cipher/cfb_test.go delete mode 100644 src/pkg/crypto/cipher/cipher.go delete mode 100644 src/pkg/crypto/cipher/cipher_test.go delete mode 100644 src/pkg/crypto/cipher/common_test.go delete mode 100644 src/pkg/crypto/cipher/ctr.go delete mode 100644 src/pkg/crypto/cipher/ctr_aes_test.go delete mode 100644 src/pkg/crypto/cipher/example_test.go delete mode 100644 src/pkg/crypto/cipher/gcm.go delete mode 100644 src/pkg/crypto/cipher/gcm_test.go delete mode 100644 src/pkg/crypto/cipher/io.go delete mode 100644 src/pkg/crypto/cipher/ofb.go delete mode 100644 src/pkg/crypto/cipher/ofb_test.go delete mode 100644 src/pkg/crypto/cipher/xor.go delete mode 100644 src/pkg/crypto/cipher/xor_test.go delete mode 100644 src/pkg/crypto/crypto.go delete mode 100644 src/pkg/crypto/des/block.go delete mode 100644 src/pkg/crypto/des/cipher.go delete mode 100644 src/pkg/crypto/des/const.go delete mode 100644 src/pkg/crypto/des/des_test.go delete mode 100644 src/pkg/crypto/des/example_test.go delete mode 100644 src/pkg/crypto/dsa/dsa.go delete mode 100644 src/pkg/crypto/dsa/dsa_test.go delete mode 100644 src/pkg/crypto/ecdsa/ecdsa.go delete mode 100644 src/pkg/crypto/ecdsa/ecdsa_test.go delete mode 100644 src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 delete mode 100644 src/pkg/crypto/elliptic/elliptic.go delete mode 100644 src/pkg/crypto/elliptic/elliptic_test.go delete mode 100644 src/pkg/crypto/elliptic/p224.go delete mode 100644 src/pkg/crypto/elliptic/p224_test.go delete mode 100644 src/pkg/crypto/elliptic/p256.go delete mode 100644 src/pkg/crypto/hmac/hmac.go delete mode 100644 src/pkg/crypto/hmac/hmac_test.go delete mode 100644 src/pkg/crypto/md5/example_test.go delete mode 100644 src/pkg/crypto/md5/gen.go delete mode 100644 src/pkg/crypto/md5/md5.go delete mode 100644 src/pkg/crypto/md5/md5_test.go delete mode 100644 src/pkg/crypto/md5/md5block.go delete mode 100644 src/pkg/crypto/md5/md5block_386.s delete mode 100644 src/pkg/crypto/md5/md5block_amd64.s delete mode 100644 src/pkg/crypto/md5/md5block_amd64p32.s delete mode 100644 src/pkg/crypto/md5/md5block_arm.s delete mode 100644 src/pkg/crypto/md5/md5block_decl.go delete mode 100644 src/pkg/crypto/md5/md5block_generic.go delete mode 100644 src/pkg/crypto/rand/example_test.go delete mode 100644 src/pkg/crypto/rand/rand.go delete mode 100644 src/pkg/crypto/rand/rand_test.go delete mode 100644 src/pkg/crypto/rand/rand_unix.go delete mode 100644 src/pkg/crypto/rand/rand_windows.go delete mode 100644 src/pkg/crypto/rand/util.go delete mode 100644 src/pkg/crypto/rand/util_test.go delete mode 100644 src/pkg/crypto/rc4/rc4.go delete mode 100644 src/pkg/crypto/rc4/rc4_386.s delete mode 100644 src/pkg/crypto/rc4/rc4_amd64.s delete mode 100644 src/pkg/crypto/rc4/rc4_amd64p32.s delete mode 100644 src/pkg/crypto/rc4/rc4_arm.s delete mode 100644 src/pkg/crypto/rc4/rc4_asm.go delete mode 100644 src/pkg/crypto/rc4/rc4_ref.go delete mode 100644 src/pkg/crypto/rc4/rc4_test.go delete mode 100644 src/pkg/crypto/rsa/pkcs1v15.go delete mode 100644 src/pkg/crypto/rsa/pkcs1v15_test.go delete mode 100644 src/pkg/crypto/rsa/pss.go delete mode 100644 src/pkg/crypto/rsa/pss_test.go delete mode 100644 src/pkg/crypto/rsa/rsa.go delete mode 100644 src/pkg/crypto/rsa/rsa_test.go delete mode 100644 src/pkg/crypto/rsa/testdata/pss-vect.txt.bz2 delete mode 100644 src/pkg/crypto/sha1/example_test.go delete mode 100644 src/pkg/crypto/sha1/sha1.go delete mode 100644 src/pkg/crypto/sha1/sha1_test.go delete mode 100644 src/pkg/crypto/sha1/sha1block.go delete mode 100644 src/pkg/crypto/sha1/sha1block_386.s delete mode 100644 src/pkg/crypto/sha1/sha1block_amd64.s delete mode 100644 src/pkg/crypto/sha1/sha1block_amd64p32.s delete mode 100644 src/pkg/crypto/sha1/sha1block_arm.s delete mode 100644 src/pkg/crypto/sha1/sha1block_decl.go delete mode 100644 src/pkg/crypto/sha1/sha1block_generic.go delete mode 100644 src/pkg/crypto/sha256/sha256.go delete mode 100644 src/pkg/crypto/sha256/sha256_test.go delete mode 100644 src/pkg/crypto/sha256/sha256block.go delete mode 100644 src/pkg/crypto/sha256/sha256block_386.s delete mode 100644 src/pkg/crypto/sha256/sha256block_amd64.s delete mode 100644 src/pkg/crypto/sha256/sha256block_decl.go delete mode 100644 src/pkg/crypto/sha512/sha512.go delete mode 100644 src/pkg/crypto/sha512/sha512_test.go delete mode 100644 src/pkg/crypto/sha512/sha512block.go delete mode 100644 src/pkg/crypto/sha512/sha512block_amd64.s delete mode 100644 src/pkg/crypto/sha512/sha512block_decl.go delete mode 100644 src/pkg/crypto/subtle/constant_time.go delete mode 100644 src/pkg/crypto/subtle/constant_time_test.go delete mode 100644 src/pkg/crypto/tls/alert.go delete mode 100644 src/pkg/crypto/tls/cipher_suites.go delete mode 100644 src/pkg/crypto/tls/common.go delete mode 100644 src/pkg/crypto/tls/conn.go delete mode 100644 src/pkg/crypto/tls/conn_test.go delete mode 100644 src/pkg/crypto/tls/example_test.go delete mode 100644 src/pkg/crypto/tls/generate_cert.go delete mode 100644 src/pkg/crypto/tls/handshake_client.go delete mode 100644 src/pkg/crypto/tls/handshake_client_test.go delete mode 100644 src/pkg/crypto/tls/handshake_messages.go delete mode 100644 src/pkg/crypto/tls/handshake_messages_test.go delete mode 100644 src/pkg/crypto/tls/handshake_server.go delete mode 100644 src/pkg/crypto/tls/handshake_server_test.go delete mode 100644 src/pkg/crypto/tls/handshake_test.go delete mode 100644 src/pkg/crypto/tls/key_agreement.go delete mode 100644 src/pkg/crypto/tls/prf.go delete mode 100644 src/pkg/crypto/tls/prf_test.go delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv10-RSA-RC4 delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv11-RSA-RC4 delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Client-TLSv12-RSA-RC4 delete mode 100644 src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-3DES delete mode 100644 src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Server-SSLv3-RSA-RC4 delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-3DES delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv10-RSA-RC4 delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv11-RSA-RC4 delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicket delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-3DES delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-RSA-RC4 delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-Resume delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-ResumeDisabled delete mode 100644 src/pkg/crypto/tls/testdata/Server-TLSv12-SNI delete mode 100644 src/pkg/crypto/tls/ticket.go delete mode 100644 src/pkg/crypto/tls/tls.go delete mode 100644 src/pkg/crypto/tls/tls_test.go delete mode 100644 src/pkg/crypto/x509/cert_pool.go delete mode 100644 src/pkg/crypto/x509/example_test.go delete mode 100644 src/pkg/crypto/x509/pem_decrypt.go delete mode 100644 src/pkg/crypto/x509/pem_decrypt_test.go delete mode 100644 src/pkg/crypto/x509/pkcs1.go delete mode 100644 src/pkg/crypto/x509/pkcs8.go delete mode 100644 src/pkg/crypto/x509/pkcs8_test.go delete mode 100644 src/pkg/crypto/x509/pkix/pkix.go delete mode 100644 src/pkg/crypto/x509/root.go delete mode 100644 src/pkg/crypto/x509/root_cgo_darwin.go delete mode 100644 src/pkg/crypto/x509/root_darwin.go delete mode 100644 src/pkg/crypto/x509/root_darwin_test.go delete mode 100644 src/pkg/crypto/x509/root_nocgo_darwin.go delete mode 100644 src/pkg/crypto/x509/root_plan9.go delete mode 100644 src/pkg/crypto/x509/root_unix.go delete mode 100644 src/pkg/crypto/x509/root_windows.go delete mode 100644 src/pkg/crypto/x509/sec1.go delete mode 100644 src/pkg/crypto/x509/sec1_test.go delete mode 100644 src/pkg/crypto/x509/verify.go delete mode 100644 src/pkg/crypto/x509/verify_test.go delete mode 100644 src/pkg/crypto/x509/x509.go delete mode 100644 src/pkg/crypto/x509/x509_test.go delete mode 100644 src/pkg/crypto/x509/x509_test_import.go delete mode 100644 src/pkg/database/sql/convert.go delete mode 100644 src/pkg/database/sql/convert_test.go delete mode 100644 src/pkg/database/sql/doc.txt delete mode 100644 src/pkg/database/sql/driver/driver.go delete mode 100644 src/pkg/database/sql/driver/types.go delete mode 100644 src/pkg/database/sql/driver/types_test.go delete mode 100644 src/pkg/database/sql/example_test.go delete mode 100644 src/pkg/database/sql/fakedb_test.go delete mode 100644 src/pkg/database/sql/sql.go delete mode 100644 src/pkg/database/sql/sql_test.go delete mode 100644 src/pkg/debug/dwarf/buf.go delete mode 100644 src/pkg/debug/dwarf/const.go delete mode 100644 src/pkg/debug/dwarf/entry.go delete mode 100644 src/pkg/debug/dwarf/open.go delete mode 100644 src/pkg/debug/dwarf/testdata/typedef.c delete mode 100755 src/pkg/debug/dwarf/testdata/typedef.elf delete mode 100644 src/pkg/debug/dwarf/testdata/typedef.elf4 delete mode 100644 src/pkg/debug/dwarf/testdata/typedef.macho delete mode 100644 src/pkg/debug/dwarf/type.go delete mode 100644 src/pkg/debug/dwarf/type_test.go delete mode 100644 src/pkg/debug/dwarf/typeunit.go delete mode 100644 src/pkg/debug/dwarf/unit.go delete mode 100644 src/pkg/debug/elf/elf.go delete mode 100644 src/pkg/debug/elf/elf_test.go delete mode 100644 src/pkg/debug/elf/file.go delete mode 100644 src/pkg/debug/elf/file_test.go delete mode 100755 src/pkg/debug/elf/testdata/gcc-386-freebsd-exec delete mode 100755 src/pkg/debug/elf/testdata/gcc-amd64-linux-exec delete mode 100644 src/pkg/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj delete mode 100644 src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj delete mode 100644 src/pkg/debug/elf/testdata/go-relocation-test-gcc424-x86-64.obj delete mode 100644 src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86-64.obj delete mode 100644 src/pkg/debug/elf/testdata/go-relocation-test-gcc441-x86.obj delete mode 100644 src/pkg/debug/elf/testdata/hello-world-core.gz delete mode 100644 src/pkg/debug/elf/testdata/hello.c delete mode 100644 src/pkg/debug/gosym/pclinetest.asm delete mode 100644 src/pkg/debug/gosym/pclinetest.h delete mode 100644 src/pkg/debug/gosym/pclntab.go delete mode 100644 src/pkg/debug/gosym/pclntab_test.go delete mode 100644 src/pkg/debug/gosym/symtab.go delete mode 100644 src/pkg/debug/macho/fat.go delete mode 100644 src/pkg/debug/macho/file.go delete mode 100644 src/pkg/debug/macho/file_test.go delete mode 100644 src/pkg/debug/macho/macho.go delete mode 100644 src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec delete mode 100755 src/pkg/debug/macho/testdata/gcc-386-darwin-exec delete mode 100755 src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec delete mode 100644 src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug delete mode 100644 src/pkg/debug/macho/testdata/hello.c delete mode 100644 src/pkg/debug/pe/file.go delete mode 100644 src/pkg/debug/pe/file_test.go delete mode 100644 src/pkg/debug/pe/pe.go delete mode 100644 src/pkg/debug/pe/testdata/gcc-386-mingw-exec delete mode 100644 src/pkg/debug/pe/testdata/gcc-386-mingw-obj delete mode 100644 src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec delete mode 100644 src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj delete mode 100644 src/pkg/debug/pe/testdata/hello.c delete mode 100644 src/pkg/debug/plan9obj/file.go delete mode 100644 src/pkg/debug/plan9obj/file_test.go delete mode 100644 src/pkg/debug/plan9obj/plan9obj.go delete mode 100755 src/pkg/debug/plan9obj/testdata/386-plan9-exec delete mode 100755 src/pkg/debug/plan9obj/testdata/amd64-plan9-exec delete mode 100644 src/pkg/debug/plan9obj/testdata/hello.c delete mode 100644 src/pkg/encoding/ascii85/ascii85.go delete mode 100644 src/pkg/encoding/ascii85/ascii85_test.go delete mode 100644 src/pkg/encoding/asn1/asn1.go delete mode 100644 src/pkg/encoding/asn1/asn1_test.go delete mode 100644 src/pkg/encoding/asn1/common.go delete mode 100644 src/pkg/encoding/asn1/marshal.go delete mode 100644 src/pkg/encoding/asn1/marshal_test.go delete mode 100644 src/pkg/encoding/base32/base32.go delete mode 100644 src/pkg/encoding/base32/base32_test.go delete mode 100644 src/pkg/encoding/base32/example_test.go delete mode 100644 src/pkg/encoding/base64/base64.go delete mode 100644 src/pkg/encoding/base64/base64_test.go delete mode 100644 src/pkg/encoding/base64/example_test.go delete mode 100644 src/pkg/encoding/binary/binary.go delete mode 100644 src/pkg/encoding/binary/binary_test.go delete mode 100644 src/pkg/encoding/binary/example_test.go delete mode 100644 src/pkg/encoding/binary/varint.go delete mode 100644 src/pkg/encoding/binary/varint_test.go delete mode 100644 src/pkg/encoding/csv/reader.go delete mode 100644 src/pkg/encoding/csv/reader_test.go delete mode 100644 src/pkg/encoding/csv/writer.go delete mode 100644 src/pkg/encoding/csv/writer_test.go delete mode 100644 src/pkg/encoding/encoding.go delete mode 100644 src/pkg/encoding/gob/codec_test.go delete mode 100644 src/pkg/encoding/gob/debug.go delete mode 100644 src/pkg/encoding/gob/decode.go delete mode 100644 src/pkg/encoding/gob/decoder.go delete mode 100644 src/pkg/encoding/gob/doc.go delete mode 100644 src/pkg/encoding/gob/dump.go delete mode 100644 src/pkg/encoding/gob/encode.go delete mode 100644 src/pkg/encoding/gob/encoder.go delete mode 100644 src/pkg/encoding/gob/encoder_test.go delete mode 100644 src/pkg/encoding/gob/error.go delete mode 100644 src/pkg/encoding/gob/example_encdec_test.go delete mode 100644 src/pkg/encoding/gob/example_interface_test.go delete mode 100644 src/pkg/encoding/gob/example_test.go delete mode 100644 src/pkg/encoding/gob/gobencdec_test.go delete mode 100644 src/pkg/encoding/gob/timing_test.go delete mode 100644 src/pkg/encoding/gob/type.go delete mode 100644 src/pkg/encoding/gob/type_test.go delete mode 100644 src/pkg/encoding/hex/hex.go delete mode 100644 src/pkg/encoding/hex/hex_test.go delete mode 100644 src/pkg/encoding/json/bench_test.go delete mode 100644 src/pkg/encoding/json/decode.go delete mode 100644 src/pkg/encoding/json/decode_test.go delete mode 100644 src/pkg/encoding/json/encode.go delete mode 100644 src/pkg/encoding/json/encode_test.go delete mode 100644 src/pkg/encoding/json/example_test.go delete mode 100644 src/pkg/encoding/json/fold.go delete mode 100644 src/pkg/encoding/json/fold_test.go delete mode 100644 src/pkg/encoding/json/indent.go delete mode 100644 src/pkg/encoding/json/scanner.go delete mode 100644 src/pkg/encoding/json/scanner_test.go delete mode 100644 src/pkg/encoding/json/stream.go delete mode 100644 src/pkg/encoding/json/stream_test.go delete mode 100644 src/pkg/encoding/json/tagkey_test.go delete mode 100644 src/pkg/encoding/json/tags.go delete mode 100644 src/pkg/encoding/json/tags_test.go delete mode 100644 src/pkg/encoding/json/testdata/code.json.gz delete mode 100644 src/pkg/encoding/pem/pem.go delete mode 100644 src/pkg/encoding/pem/pem_test.go delete mode 100644 src/pkg/encoding/xml/atom_test.go delete mode 100644 src/pkg/encoding/xml/example_test.go delete mode 100644 src/pkg/encoding/xml/marshal.go delete mode 100644 src/pkg/encoding/xml/marshal_test.go delete mode 100644 src/pkg/encoding/xml/read.go delete mode 100644 src/pkg/encoding/xml/read_test.go delete mode 100644 src/pkg/encoding/xml/typeinfo.go delete mode 100644 src/pkg/encoding/xml/xml.go delete mode 100644 src/pkg/encoding/xml/xml_test.go delete mode 100644 src/pkg/errors/errors.go delete mode 100644 src/pkg/errors/errors_test.go delete mode 100644 src/pkg/errors/example_test.go delete mode 100644 src/pkg/expvar/expvar.go delete mode 100644 src/pkg/expvar/expvar_test.go delete mode 100644 src/pkg/flag/example_test.go delete mode 100644 src/pkg/flag/export_test.go delete mode 100644 src/pkg/flag/flag.go delete mode 100644 src/pkg/flag/flag_test.go delete mode 100644 src/pkg/fmt/doc.go delete mode 100644 src/pkg/fmt/export_test.go delete mode 100644 src/pkg/fmt/fmt_test.go delete mode 100644 src/pkg/fmt/format.go delete mode 100644 src/pkg/fmt/print.go delete mode 100644 src/pkg/fmt/scan.go delete mode 100644 src/pkg/fmt/scan_test.go delete mode 100644 src/pkg/fmt/stringer_test.go delete mode 100644 src/pkg/go/ast/ast.go delete mode 100644 src/pkg/go/ast/ast_test.go delete mode 100644 src/pkg/go/ast/commentmap.go delete mode 100644 src/pkg/go/ast/commentmap_test.go delete mode 100644 src/pkg/go/ast/example_test.go delete mode 100644 src/pkg/go/ast/filter.go delete mode 100644 src/pkg/go/ast/filter_test.go delete mode 100644 src/pkg/go/ast/import.go delete mode 100644 src/pkg/go/ast/print.go delete mode 100644 src/pkg/go/ast/print_test.go delete mode 100644 src/pkg/go/ast/resolve.go delete mode 100644 src/pkg/go/ast/scope.go delete mode 100644 src/pkg/go/ast/walk.go delete mode 100644 src/pkg/go/build/build.go delete mode 100644 src/pkg/go/build/build_test.go delete mode 100644 src/pkg/go/build/deps_test.go delete mode 100644 src/pkg/go/build/doc.go delete mode 100644 src/pkg/go/build/read.go delete mode 100644 src/pkg/go/build/read_test.go delete mode 100644 src/pkg/go/build/syslist.go delete mode 100644 src/pkg/go/build/syslist_test.go delete mode 100644 src/pkg/go/build/testdata/other/file/file.go delete mode 100644 src/pkg/go/build/testdata/other/main.go delete mode 100644 src/pkg/go/doc/Makefile delete mode 100644 src/pkg/go/doc/comment.go delete mode 100644 src/pkg/go/doc/comment_test.go delete mode 100644 src/pkg/go/doc/doc.go delete mode 100644 src/pkg/go/doc/doc_test.go delete mode 100644 src/pkg/go/doc/example.go delete mode 100644 src/pkg/go/doc/example_test.go delete mode 100644 src/pkg/go/doc/exports.go delete mode 100644 src/pkg/go/doc/filter.go delete mode 100644 src/pkg/go/doc/headscan.go delete mode 100644 src/pkg/go/doc/reader.go delete mode 100644 src/pkg/go/doc/synopsis.go delete mode 100644 src/pkg/go/doc/synopsis_test.go delete mode 100644 src/pkg/go/doc/testdata/a.0.golden delete mode 100644 src/pkg/go/doc/testdata/a.1.golden delete mode 100644 src/pkg/go/doc/testdata/a.2.golden delete mode 100644 src/pkg/go/doc/testdata/a0.go delete mode 100644 src/pkg/go/doc/testdata/a1.go delete mode 100644 src/pkg/go/doc/testdata/b.0.golden delete mode 100644 src/pkg/go/doc/testdata/b.1.golden delete mode 100644 src/pkg/go/doc/testdata/b.2.golden delete mode 100644 src/pkg/go/doc/testdata/b.go delete mode 100644 src/pkg/go/doc/testdata/benchmark.go delete mode 100644 src/pkg/go/doc/testdata/bugpara.0.golden delete mode 100644 src/pkg/go/doc/testdata/bugpara.1.golden delete mode 100644 src/pkg/go/doc/testdata/bugpara.2.golden delete mode 100644 src/pkg/go/doc/testdata/bugpara.go delete mode 100644 src/pkg/go/doc/testdata/c.0.golden delete mode 100644 src/pkg/go/doc/testdata/c.1.golden delete mode 100644 src/pkg/go/doc/testdata/c.2.golden delete mode 100644 src/pkg/go/doc/testdata/c.go delete mode 100644 src/pkg/go/doc/testdata/d.0.golden delete mode 100644 src/pkg/go/doc/testdata/d.1.golden delete mode 100644 src/pkg/go/doc/testdata/d.2.golden delete mode 100644 src/pkg/go/doc/testdata/d1.go delete mode 100644 src/pkg/go/doc/testdata/d2.go delete mode 100644 src/pkg/go/doc/testdata/e.0.golden delete mode 100644 src/pkg/go/doc/testdata/e.1.golden delete mode 100644 src/pkg/go/doc/testdata/e.2.golden delete mode 100644 src/pkg/go/doc/testdata/e.go delete mode 100644 src/pkg/go/doc/testdata/error1.0.golden delete mode 100644 src/pkg/go/doc/testdata/error1.1.golden delete mode 100644 src/pkg/go/doc/testdata/error1.2.golden delete mode 100644 src/pkg/go/doc/testdata/error1.go delete mode 100644 src/pkg/go/doc/testdata/error2.0.golden delete mode 100644 src/pkg/go/doc/testdata/error2.1.golden delete mode 100644 src/pkg/go/doc/testdata/error2.2.golden delete mode 100644 src/pkg/go/doc/testdata/error2.go delete mode 100644 src/pkg/go/doc/testdata/example.go delete mode 100644 src/pkg/go/doc/testdata/f.0.golden delete mode 100644 src/pkg/go/doc/testdata/f.1.golden delete mode 100644 src/pkg/go/doc/testdata/f.2.golden delete mode 100644 src/pkg/go/doc/testdata/f.go delete mode 100644 src/pkg/go/doc/testdata/template.txt delete mode 100644 src/pkg/go/doc/testdata/testing.0.golden delete mode 100644 src/pkg/go/doc/testdata/testing.1.golden delete mode 100644 src/pkg/go/doc/testdata/testing.2.golden delete mode 100644 src/pkg/go/doc/testdata/testing.go delete mode 100644 src/pkg/go/format/format.go delete mode 100644 src/pkg/go/format/format_test.go delete mode 100644 src/pkg/go/parser/error_test.go delete mode 100644 src/pkg/go/parser/example_test.go delete mode 100644 src/pkg/go/parser/interface.go delete mode 100644 src/pkg/go/parser/parser.go delete mode 100644 src/pkg/go/parser/parser_test.go delete mode 100644 src/pkg/go/parser/performance_test.go delete mode 100644 src/pkg/go/parser/short_test.go delete mode 100644 src/pkg/go/parser/testdata/commas.src delete mode 100644 src/pkg/go/parser/testdata/issue3106.src delete mode 100644 src/pkg/go/printer/example_test.go delete mode 100644 src/pkg/go/printer/nodes.go delete mode 100644 src/pkg/go/printer/performance_test.go delete mode 100644 src/pkg/go/printer/printer.go delete mode 100644 src/pkg/go/printer/printer_test.go delete mode 100644 src/pkg/go/printer/testdata/comments.golden delete mode 100644 src/pkg/go/printer/testdata/comments.input delete mode 100644 src/pkg/go/printer/testdata/comments.x delete mode 100644 src/pkg/go/printer/testdata/comments2.golden delete mode 100644 src/pkg/go/printer/testdata/comments2.input delete mode 100644 src/pkg/go/printer/testdata/declarations.golden delete mode 100644 src/pkg/go/printer/testdata/declarations.input delete mode 100644 src/pkg/go/printer/testdata/empty.golden delete mode 100644 src/pkg/go/printer/testdata/empty.input delete mode 100644 src/pkg/go/printer/testdata/expressions.golden delete mode 100644 src/pkg/go/printer/testdata/expressions.input delete mode 100644 src/pkg/go/printer/testdata/expressions.raw delete mode 100644 src/pkg/go/printer/testdata/linebreaks.golden delete mode 100644 src/pkg/go/printer/testdata/linebreaks.input delete mode 100644 src/pkg/go/printer/testdata/parser.go delete mode 100644 src/pkg/go/printer/testdata/slow.golden delete mode 100644 src/pkg/go/printer/testdata/slow.input delete mode 100644 src/pkg/go/printer/testdata/statements.golden delete mode 100644 src/pkg/go/printer/testdata/statements.input delete mode 100644 src/pkg/go/scanner/errors.go delete mode 100644 src/pkg/go/scanner/example_test.go delete mode 100644 src/pkg/go/scanner/scanner.go delete mode 100644 src/pkg/go/scanner/scanner_test.go delete mode 100644 src/pkg/go/token/position.go delete mode 100644 src/pkg/go/token/position_test.go delete mode 100644 src/pkg/go/token/serialize.go delete mode 100644 src/pkg/go/token/serialize_test.go delete mode 100644 src/pkg/go/token/token.go delete mode 100644 src/pkg/hash/adler32/adler32.go delete mode 100644 src/pkg/hash/adler32/adler32_test.go delete mode 100644 src/pkg/hash/crc32/crc32.go delete mode 100644 src/pkg/hash/crc32/crc32_amd64.s delete mode 100644 src/pkg/hash/crc32/crc32_amd64p32.s delete mode 100644 src/pkg/hash/crc32/crc32_amd64x.go delete mode 100644 src/pkg/hash/crc32/crc32_generic.go delete mode 100644 src/pkg/hash/crc32/crc32_test.go delete mode 100644 src/pkg/hash/crc64/crc64.go delete mode 100644 src/pkg/hash/crc64/crc64_test.go delete mode 100644 src/pkg/hash/fnv/fnv.go delete mode 100644 src/pkg/hash/fnv/fnv_test.go delete mode 100644 src/pkg/hash/hash.go delete mode 100644 src/pkg/hash/test_cases.txt delete mode 100644 src/pkg/hash/test_gen.awk delete mode 100644 src/pkg/html/entity.go delete mode 100644 src/pkg/html/entity_test.go delete mode 100644 src/pkg/html/escape.go delete mode 100644 src/pkg/html/escape_test.go delete mode 100644 src/pkg/html/template/attr.go delete mode 100644 src/pkg/html/template/clone_test.go delete mode 100644 src/pkg/html/template/content.go delete mode 100644 src/pkg/html/template/content_test.go delete mode 100644 src/pkg/html/template/context.go delete mode 100644 src/pkg/html/template/css.go delete mode 100644 src/pkg/html/template/css_test.go delete mode 100644 src/pkg/html/template/doc.go delete mode 100644 src/pkg/html/template/error.go delete mode 100644 src/pkg/html/template/escape.go delete mode 100644 src/pkg/html/template/escape_test.go delete mode 100644 src/pkg/html/template/html.go delete mode 100644 src/pkg/html/template/html_test.go delete mode 100644 src/pkg/html/template/js.go delete mode 100644 src/pkg/html/template/js_test.go delete mode 100644 src/pkg/html/template/template.go delete mode 100644 src/pkg/html/template/transition.go delete mode 100644 src/pkg/html/template/url.go delete mode 100644 src/pkg/html/template/url_test.go delete mode 100644 src/pkg/image/color/color.go delete mode 100644 src/pkg/image/color/palette/gen.go delete mode 100644 src/pkg/image/color/palette/palette.go delete mode 100644 src/pkg/image/color/ycbcr.go delete mode 100644 src/pkg/image/color/ycbcr_test.go delete mode 100644 src/pkg/image/decode_example_test.go delete mode 100644 src/pkg/image/decode_test.go delete mode 100644 src/pkg/image/draw/bench_test.go delete mode 100644 src/pkg/image/draw/clip_test.go delete mode 100644 src/pkg/image/draw/draw.go delete mode 100644 src/pkg/image/draw/draw_test.go delete mode 100644 src/pkg/image/format.go delete mode 100644 src/pkg/image/geom.go delete mode 100644 src/pkg/image/gif/reader.go delete mode 100644 src/pkg/image/gif/reader_test.go delete mode 100644 src/pkg/image/gif/writer.go delete mode 100644 src/pkg/image/gif/writer_test.go delete mode 100644 src/pkg/image/image.go delete mode 100644 src/pkg/image/image_test.go delete mode 100644 src/pkg/image/jpeg/dct_test.go delete mode 100644 src/pkg/image/jpeg/fdct.go delete mode 100644 src/pkg/image/jpeg/huffman.go delete mode 100644 src/pkg/image/jpeg/idct.go delete mode 100644 src/pkg/image/jpeg/reader.go delete mode 100644 src/pkg/image/jpeg/reader_test.go delete mode 100644 src/pkg/image/jpeg/scan.go delete mode 100644 src/pkg/image/jpeg/writer.go delete mode 100644 src/pkg/image/jpeg/writer_test.go delete mode 100644 src/pkg/image/names.go delete mode 100644 src/pkg/image/png/paeth.go delete mode 100644 src/pkg/image/png/paeth_test.go delete mode 100644 src/pkg/image/png/reader.go delete mode 100644 src/pkg/image/png/reader_test.go delete mode 100644 src/pkg/image/png/testdata/benchGray.png delete mode 100644 src/pkg/image/png/testdata/benchNRGBA-gradient.png delete mode 100644 src/pkg/image/png/testdata/benchNRGBA-opaque.png delete mode 100644 src/pkg/image/png/testdata/benchPaletted.png delete mode 100644 src/pkg/image/png/testdata/benchRGB.png delete mode 100644 src/pkg/image/png/testdata/invalid-crc32.png delete mode 100644 src/pkg/image/png/testdata/invalid-noend.png delete mode 100644 src/pkg/image/png/testdata/invalid-trunc.png delete mode 100644 src/pkg/image/png/testdata/invalid-zlib.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/README delete mode 100644 src/pkg/image/png/testdata/pngsuite/README.original delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g01-30.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g01-30.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g01.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g01.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g02-29.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g02-29.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g02.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g02.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g04-31.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g04-31.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g04.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g04.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g08.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g08.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g16.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn0g16.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn2c08.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn2c08.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn2c16.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn2c16.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p01.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p01.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p02.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p02.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p04.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p04.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p08-trns.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p08-trns.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p08.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn3p08.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn4a08.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn4a08.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn4a16.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn4a16.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn6a08.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn6a08.sng delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn6a16.png delete mode 100644 src/pkg/image/png/testdata/pngsuite/basn6a16.sng delete mode 100644 src/pkg/image/png/writer.go delete mode 100644 src/pkg/image/png/writer_test.go delete mode 100644 src/pkg/image/testdata/video-001.5bpp.gif delete mode 100644 src/pkg/image/testdata/video-001.gif delete mode 100644 src/pkg/image/testdata/video-001.interlaced.gif delete mode 100644 src/pkg/image/testdata/video-001.jpeg delete mode 100644 src/pkg/image/testdata/video-001.png delete mode 100644 src/pkg/image/testdata/video-001.progressive.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.420.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.420.progressive.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.422.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.422.progressive.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.440.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.440.progressive.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.444.jpeg delete mode 100644 src/pkg/image/testdata/video-001.q50.444.progressive.jpeg delete mode 100644 src/pkg/image/testdata/video-001.separate.dc.progression.jpeg delete mode 100644 src/pkg/image/testdata/video-001.separate.dc.progression.progressive.jpeg delete mode 100644 src/pkg/image/testdata/video-005.gray.gif delete mode 100644 src/pkg/image/testdata/video-005.gray.jpeg delete mode 100644 src/pkg/image/testdata/video-005.gray.png delete mode 100644 src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg delete mode 100644 src/pkg/image/testdata/video-005.gray.q50.2x2.progressive.jpeg delete mode 100644 src/pkg/image/testdata/video-005.gray.q50.jpeg delete mode 100644 src/pkg/image/testdata/video-005.gray.q50.progressive.jpeg delete mode 100644 src/pkg/image/ycbcr.go delete mode 100644 src/pkg/image/ycbcr_test.go delete mode 100644 src/pkg/index/suffixarray/qsufsort.go delete mode 100644 src/pkg/index/suffixarray/suffixarray.go delete mode 100644 src/pkg/index/suffixarray/suffixarray_test.go delete mode 100644 src/pkg/io/io.go delete mode 100644 src/pkg/io/io_test.go delete mode 100644 src/pkg/io/ioutil/ioutil.go delete mode 100644 src/pkg/io/ioutil/ioutil_test.go delete mode 100644 src/pkg/io/ioutil/tempfile.go delete mode 100644 src/pkg/io/ioutil/tempfile_test.go delete mode 100644 src/pkg/io/multi.go delete mode 100644 src/pkg/io/multi_test.go delete mode 100644 src/pkg/io/pipe.go delete mode 100644 src/pkg/io/pipe_test.go delete mode 100644 src/pkg/log/example_test.go delete mode 100644 src/pkg/log/log.go delete mode 100644 src/pkg/log/log_test.go delete mode 100644 src/pkg/log/syslog/syslog.go delete mode 100644 src/pkg/log/syslog/syslog_plan9.go delete mode 100644 src/pkg/log/syslog/syslog_test.go delete mode 100644 src/pkg/log/syslog/syslog_unix.go delete mode 100644 src/pkg/log/syslog/syslog_windows.go delete mode 100644 src/pkg/math/abs.go delete mode 100644 src/pkg/math/abs_386.s delete mode 100644 src/pkg/math/abs_amd64.s delete mode 100644 src/pkg/math/abs_amd64p32.s delete mode 100644 src/pkg/math/abs_arm.s delete mode 100644 src/pkg/math/acosh.go delete mode 100644 src/pkg/math/all_test.go delete mode 100644 src/pkg/math/asin.go delete mode 100644 src/pkg/math/asin_386.s delete mode 100644 src/pkg/math/asin_amd64.s delete mode 100644 src/pkg/math/asin_amd64p32.s delete mode 100644 src/pkg/math/asin_arm.s delete mode 100644 src/pkg/math/asinh.go delete mode 100644 src/pkg/math/atan.go delete mode 100644 src/pkg/math/atan2.go delete mode 100644 src/pkg/math/atan2_386.s delete mode 100644 src/pkg/math/atan2_amd64.s delete mode 100644 src/pkg/math/atan2_amd64p32.s delete mode 100644 src/pkg/math/atan2_arm.s delete mode 100644 src/pkg/math/atan_386.s delete mode 100644 src/pkg/math/atan_amd64.s delete mode 100644 src/pkg/math/atan_amd64p32.s delete mode 100644 src/pkg/math/atan_arm.s delete mode 100644 src/pkg/math/atanh.go delete mode 100644 src/pkg/math/big/arith.go delete mode 100644 src/pkg/math/big/arith_386.s delete mode 100644 src/pkg/math/big/arith_amd64.s delete mode 100644 src/pkg/math/big/arith_amd64p32.s delete mode 100644 src/pkg/math/big/arith_arm.s delete mode 100644 src/pkg/math/big/arith_decl.go delete mode 100644 src/pkg/math/big/arith_test.go delete mode 100644 src/pkg/math/big/calibrate_test.go delete mode 100644 src/pkg/math/big/example_test.go delete mode 100644 src/pkg/math/big/gcd_test.go delete mode 100644 src/pkg/math/big/hilbert_test.go delete mode 100644 src/pkg/math/big/int.go delete mode 100644 src/pkg/math/big/int_test.go delete mode 100644 src/pkg/math/big/nat.go delete mode 100644 src/pkg/math/big/nat_test.go delete mode 100644 src/pkg/math/big/rat.go delete mode 100644 src/pkg/math/big/rat_test.go delete mode 100644 src/pkg/math/bits.go delete mode 100644 src/pkg/math/cbrt.go delete mode 100644 src/pkg/math/cmplx/abs.go delete mode 100644 src/pkg/math/cmplx/asin.go delete mode 100644 src/pkg/math/cmplx/cmath_test.go delete mode 100644 src/pkg/math/cmplx/conj.go delete mode 100644 src/pkg/math/cmplx/exp.go delete mode 100644 src/pkg/math/cmplx/isinf.go delete mode 100644 src/pkg/math/cmplx/isnan.go delete mode 100644 src/pkg/math/cmplx/log.go delete mode 100644 src/pkg/math/cmplx/phase.go delete mode 100644 src/pkg/math/cmplx/polar.go delete mode 100644 src/pkg/math/cmplx/pow.go delete mode 100644 src/pkg/math/cmplx/rect.go delete mode 100644 src/pkg/math/cmplx/sin.go delete mode 100644 src/pkg/math/cmplx/sqrt.go delete mode 100644 src/pkg/math/cmplx/tan.go delete mode 100644 src/pkg/math/const.go delete mode 100644 src/pkg/math/copysign.go delete mode 100644 src/pkg/math/dim.go delete mode 100644 src/pkg/math/dim_386.s delete mode 100644 src/pkg/math/dim_amd64.s delete mode 100644 src/pkg/math/dim_amd64p32.s delete mode 100644 src/pkg/math/dim_arm.s delete mode 100644 src/pkg/math/erf.go delete mode 100644 src/pkg/math/exp.go delete mode 100644 src/pkg/math/exp2_386.s delete mode 100644 src/pkg/math/exp2_amd64.s delete mode 100644 src/pkg/math/exp2_amd64p32.s delete mode 100644 src/pkg/math/exp2_arm.s delete mode 100644 src/pkg/math/exp_386.s delete mode 100644 src/pkg/math/exp_amd64.s delete mode 100644 src/pkg/math/exp_amd64p32.s delete mode 100644 src/pkg/math/exp_arm.s delete mode 100644 src/pkg/math/expm1.go delete mode 100644 src/pkg/math/expm1_386.s delete mode 100644 src/pkg/math/expm1_amd64.s delete mode 100644 src/pkg/math/expm1_amd64p32.s delete mode 100644 src/pkg/math/expm1_arm.s delete mode 100644 src/pkg/math/export_test.go delete mode 100644 src/pkg/math/floor.go delete mode 100644 src/pkg/math/floor_386.s delete mode 100644 src/pkg/math/floor_amd64.s delete mode 100644 src/pkg/math/floor_amd64p32.s delete mode 100644 src/pkg/math/floor_arm.s delete mode 100644 src/pkg/math/frexp.go delete mode 100644 src/pkg/math/frexp_386.s delete mode 100644 src/pkg/math/frexp_amd64.s delete mode 100644 src/pkg/math/frexp_amd64p32.s delete mode 100644 src/pkg/math/frexp_arm.s delete mode 100644 src/pkg/math/gamma.go delete mode 100644 src/pkg/math/hypot.go delete mode 100644 src/pkg/math/hypot_386.s delete mode 100644 src/pkg/math/hypot_amd64.s delete mode 100644 src/pkg/math/hypot_amd64p32.s delete mode 100644 src/pkg/math/hypot_arm.s delete mode 100644 src/pkg/math/j0.go delete mode 100644 src/pkg/math/j1.go delete mode 100644 src/pkg/math/jn.go delete mode 100644 src/pkg/math/ldexp.go delete mode 100644 src/pkg/math/ldexp_386.s delete mode 100644 src/pkg/math/ldexp_amd64.s delete mode 100644 src/pkg/math/ldexp_amd64p32.s delete mode 100644 src/pkg/math/ldexp_arm.s delete mode 100644 src/pkg/math/lgamma.go delete mode 100644 src/pkg/math/log.go delete mode 100644 src/pkg/math/log10.go delete mode 100644 src/pkg/math/log10_386.s delete mode 100644 src/pkg/math/log10_amd64.s delete mode 100644 src/pkg/math/log10_amd64p32.s delete mode 100644 src/pkg/math/log10_arm.s delete mode 100644 src/pkg/math/log1p.go delete mode 100644 src/pkg/math/log1p_386.s delete mode 100644 src/pkg/math/log1p_amd64.s delete mode 100644 src/pkg/math/log1p_amd64p32.s delete mode 100644 src/pkg/math/log1p_arm.s delete mode 100644 src/pkg/math/log_386.s delete mode 100644 src/pkg/math/log_amd64.s delete mode 100644 src/pkg/math/log_amd64p32.s delete mode 100644 src/pkg/math/log_arm.s delete mode 100644 src/pkg/math/logb.go delete mode 100644 src/pkg/math/mod.go delete mode 100644 src/pkg/math/mod_386.s delete mode 100644 src/pkg/math/mod_amd64.s delete mode 100644 src/pkg/math/mod_amd64p32.s delete mode 100644 src/pkg/math/mod_arm.s delete mode 100644 src/pkg/math/modf.go delete mode 100644 src/pkg/math/modf_386.s delete mode 100644 src/pkg/math/modf_amd64.s delete mode 100644 src/pkg/math/modf_amd64p32.s delete mode 100644 src/pkg/math/modf_arm.s delete mode 100644 src/pkg/math/nextafter.go delete mode 100644 src/pkg/math/pow.go delete mode 100644 src/pkg/math/pow10.go delete mode 100644 src/pkg/math/rand/example_test.go delete mode 100644 src/pkg/math/rand/exp.go delete mode 100644 src/pkg/math/rand/normal.go delete mode 100644 src/pkg/math/rand/rand.go delete mode 100644 src/pkg/math/rand/rand_test.go delete mode 100644 src/pkg/math/rand/regress_test.go delete mode 100644 src/pkg/math/rand/rng.go delete mode 100644 src/pkg/math/rand/zipf.go delete mode 100644 src/pkg/math/remainder.go delete mode 100644 src/pkg/math/remainder_386.s delete mode 100644 src/pkg/math/remainder_amd64.s delete mode 100644 src/pkg/math/remainder_amd64p32.s delete mode 100644 src/pkg/math/remainder_arm.s delete mode 100644 src/pkg/math/signbit.go delete mode 100644 src/pkg/math/sin.go delete mode 100644 src/pkg/math/sin_386.s delete mode 100644 src/pkg/math/sin_amd64.s delete mode 100644 src/pkg/math/sin_amd64p32.s delete mode 100644 src/pkg/math/sin_arm.s delete mode 100644 src/pkg/math/sincos.go delete mode 100644 src/pkg/math/sincos_386.s delete mode 100644 src/pkg/math/sincos_amd64.s delete mode 100644 src/pkg/math/sincos_amd64p32.s delete mode 100644 src/pkg/math/sincos_arm.s delete mode 100644 src/pkg/math/sinh.go delete mode 100644 src/pkg/math/sqrt.go delete mode 100644 src/pkg/math/sqrt_386.s delete mode 100644 src/pkg/math/sqrt_amd64.s delete mode 100644 src/pkg/math/sqrt_amd64p32.s delete mode 100644 src/pkg/math/sqrt_arm.s delete mode 100644 src/pkg/math/tan.go delete mode 100644 src/pkg/math/tan_386.s delete mode 100644 src/pkg/math/tan_amd64.s delete mode 100644 src/pkg/math/tan_amd64p32.s delete mode 100644 src/pkg/math/tan_arm.s delete mode 100644 src/pkg/math/tanh.go delete mode 100644 src/pkg/math/unsafe.go delete mode 100644 src/pkg/mime/grammar.go delete mode 100644 src/pkg/mime/mediatype.go delete mode 100644 src/pkg/mime/mediatype_test.go delete mode 100644 src/pkg/mime/multipart/example_test.go delete mode 100644 src/pkg/mime/multipart/formdata.go delete mode 100644 src/pkg/mime/multipart/formdata_test.go delete mode 100644 src/pkg/mime/multipart/multipart.go delete mode 100644 src/pkg/mime/multipart/multipart_test.go delete mode 100644 src/pkg/mime/multipart/quotedprintable.go delete mode 100644 src/pkg/mime/multipart/quotedprintable_test.go delete mode 100644 src/pkg/mime/multipart/testdata/nested-mime delete mode 100644 src/pkg/mime/multipart/writer.go delete mode 100644 src/pkg/mime/multipart/writer_test.go delete mode 100644 src/pkg/mime/testdata/test.types delete mode 100644 src/pkg/mime/testdata/test.types.plan9 delete mode 100644 src/pkg/mime/type.go delete mode 100644 src/pkg/mime/type_plan9.go delete mode 100644 src/pkg/mime/type_test.go delete mode 100644 src/pkg/mime/type_unix.go delete mode 100644 src/pkg/mime/type_windows.go delete mode 100644 src/pkg/net/cgo_bsd.go delete mode 100644 src/pkg/net/cgo_linux.go delete mode 100644 src/pkg/net/cgo_netbsd.go delete mode 100644 src/pkg/net/cgo_openbsd.go delete mode 100644 src/pkg/net/cgo_stub.go delete mode 100644 src/pkg/net/cgo_unix.go delete mode 100644 src/pkg/net/cgo_unix_test.go delete mode 100644 src/pkg/net/conn_test.go delete mode 100644 src/pkg/net/dial.go delete mode 100644 src/pkg/net/dial_gen.go delete mode 100644 src/pkg/net/dial_gen_test.go delete mode 100644 src/pkg/net/dial_test.go delete mode 100644 src/pkg/net/dialgoogle_test.go delete mode 100644 src/pkg/net/dnsclient.go delete mode 100644 src/pkg/net/dnsclient_test.go delete mode 100644 src/pkg/net/dnsclient_unix.go delete mode 100644 src/pkg/net/dnsclient_unix_test.go delete mode 100644 src/pkg/net/dnsconfig_unix.go delete mode 100644 src/pkg/net/dnsconfig_unix_test.go delete mode 100644 src/pkg/net/dnsmsg.go delete mode 100644 src/pkg/net/dnsmsg_test.go delete mode 100644 src/pkg/net/dnsname_test.go delete mode 100644 src/pkg/net/empty.c delete mode 100644 src/pkg/net/example_test.go delete mode 100644 src/pkg/net/fd_mutex.go delete mode 100644 src/pkg/net/fd_mutex_test.go delete mode 100644 src/pkg/net/fd_plan9.go delete mode 100644 src/pkg/net/fd_poll_nacl.go delete mode 100644 src/pkg/net/fd_poll_runtime.go delete mode 100644 src/pkg/net/fd_unix.go delete mode 100644 src/pkg/net/fd_unix_test.go delete mode 100644 src/pkg/net/fd_windows.go delete mode 100644 src/pkg/net/file_plan9.go delete mode 100644 src/pkg/net/file_test.go delete mode 100644 src/pkg/net/file_unix.go delete mode 100644 src/pkg/net/file_windows.go delete mode 100644 src/pkg/net/hosts.go delete mode 100644 src/pkg/net/hosts_test.go delete mode 100644 src/pkg/net/http/cgi/child.go delete mode 100644 src/pkg/net/http/cgi/child_test.go delete mode 100644 src/pkg/net/http/cgi/host.go delete mode 100644 src/pkg/net/http/cgi/host_test.go delete mode 100644 src/pkg/net/http/cgi/matryoshka_test.go delete mode 100644 src/pkg/net/http/cgi/plan9_test.go delete mode 100644 src/pkg/net/http/cgi/posix_test.go delete mode 100755 src/pkg/net/http/cgi/testdata/test.cgi delete mode 100644 src/pkg/net/http/chunked.go delete mode 100644 src/pkg/net/http/chunked_test.go delete mode 100644 src/pkg/net/http/client.go delete mode 100644 src/pkg/net/http/client_test.go delete mode 100644 src/pkg/net/http/cookie.go delete mode 100644 src/pkg/net/http/cookie_test.go delete mode 100644 src/pkg/net/http/cookiejar/jar.go delete mode 100644 src/pkg/net/http/cookiejar/jar_test.go delete mode 100644 src/pkg/net/http/cookiejar/punycode.go delete mode 100644 src/pkg/net/http/cookiejar/punycode_test.go delete mode 100644 src/pkg/net/http/doc.go delete mode 100644 src/pkg/net/http/example_test.go delete mode 100644 src/pkg/net/http/export_test.go delete mode 100644 src/pkg/net/http/fcgi/child.go delete mode 100644 src/pkg/net/http/fcgi/fcgi.go delete mode 100644 src/pkg/net/http/fcgi/fcgi_test.go delete mode 100644 src/pkg/net/http/filetransport.go delete mode 100644 src/pkg/net/http/filetransport_test.go delete mode 100644 src/pkg/net/http/fs.go delete mode 100644 src/pkg/net/http/fs_test.go delete mode 100644 src/pkg/net/http/header.go delete mode 100644 src/pkg/net/http/header_test.go delete mode 100644 src/pkg/net/http/httptest/example_test.go delete mode 100644 src/pkg/net/http/httptest/recorder.go delete mode 100644 src/pkg/net/http/httptest/recorder_test.go delete mode 100644 src/pkg/net/http/httptest/server.go delete mode 100644 src/pkg/net/http/httptest/server_test.go delete mode 100644 src/pkg/net/http/httputil/chunked.go delete mode 100644 src/pkg/net/http/httputil/chunked_test.go delete mode 100644 src/pkg/net/http/httputil/dump.go delete mode 100644 src/pkg/net/http/httputil/dump_test.go delete mode 100644 src/pkg/net/http/httputil/httputil.go delete mode 100644 src/pkg/net/http/httputil/persist.go delete mode 100644 src/pkg/net/http/httputil/reverseproxy.go delete mode 100644 src/pkg/net/http/httputil/reverseproxy_test.go delete mode 100644 src/pkg/net/http/jar.go delete mode 100644 src/pkg/net/http/lex.go delete mode 100644 src/pkg/net/http/lex_test.go delete mode 100644 src/pkg/net/http/npn_test.go delete mode 100644 src/pkg/net/http/pprof/pprof.go delete mode 100644 src/pkg/net/http/proxy_test.go delete mode 100644 src/pkg/net/http/race.go delete mode 100644 src/pkg/net/http/range_test.go delete mode 100644 src/pkg/net/http/readrequest_test.go delete mode 100644 src/pkg/net/http/request.go delete mode 100644 src/pkg/net/http/request_test.go delete mode 100644 src/pkg/net/http/requestwrite_test.go delete mode 100644 src/pkg/net/http/response.go delete mode 100644 src/pkg/net/http/response_test.go delete mode 100644 src/pkg/net/http/responsewrite_test.go delete mode 100644 src/pkg/net/http/serve_test.go delete mode 100644 src/pkg/net/http/server.go delete mode 100644 src/pkg/net/http/sniff.go delete mode 100644 src/pkg/net/http/sniff_test.go delete mode 100644 src/pkg/net/http/status.go delete mode 100644 src/pkg/net/http/testdata/file delete mode 100644 src/pkg/net/http/testdata/index.html delete mode 100644 src/pkg/net/http/testdata/style.css delete mode 100644 src/pkg/net/http/transfer.go delete mode 100644 src/pkg/net/http/transfer_test.go delete mode 100644 src/pkg/net/http/transport.go delete mode 100644 src/pkg/net/http/transport_test.go delete mode 100644 src/pkg/net/http/triv.go delete mode 100644 src/pkg/net/http/z_last_test.go delete mode 100644 src/pkg/net/interface.go delete mode 100644 src/pkg/net/interface_bsd.go delete mode 100644 src/pkg/net/interface_bsd_test.go delete mode 100644 src/pkg/net/interface_darwin.go delete mode 100644 src/pkg/net/interface_dragonfly.go delete mode 100644 src/pkg/net/interface_freebsd.go delete mode 100644 src/pkg/net/interface_linux.go delete mode 100644 src/pkg/net/interface_linux_test.go delete mode 100644 src/pkg/net/interface_netbsd.go delete mode 100644 src/pkg/net/interface_openbsd.go delete mode 100644 src/pkg/net/interface_stub.go delete mode 100644 src/pkg/net/interface_test.go delete mode 100644 src/pkg/net/interface_unix_test.go delete mode 100644 src/pkg/net/interface_windows.go delete mode 100644 src/pkg/net/ip.go delete mode 100644 src/pkg/net/ip_test.go delete mode 100644 src/pkg/net/ipraw_test.go delete mode 100644 src/pkg/net/iprawsock.go delete mode 100644 src/pkg/net/iprawsock_plan9.go delete mode 100644 src/pkg/net/iprawsock_posix.go delete mode 100644 src/pkg/net/ipsock.go delete mode 100644 src/pkg/net/ipsock_plan9.go delete mode 100644 src/pkg/net/ipsock_posix.go delete mode 100644 src/pkg/net/ipsock_test.go delete mode 100644 src/pkg/net/lookup.go delete mode 100644 src/pkg/net/lookup_plan9.go delete mode 100644 src/pkg/net/lookup_test.go delete mode 100644 src/pkg/net/lookup_unix.go delete mode 100644 src/pkg/net/lookup_windows.go delete mode 100644 src/pkg/net/mac.go delete mode 100644 src/pkg/net/mac_test.go delete mode 100644 src/pkg/net/mail/message.go delete mode 100644 src/pkg/net/mail/message_test.go delete mode 100644 src/pkg/net/mockicmp_test.go delete mode 100644 src/pkg/net/mockserver_test.go delete mode 100644 src/pkg/net/multicast_test.go delete mode 100644 src/pkg/net/net.go delete mode 100644 src/pkg/net/net_test.go delete mode 100644 src/pkg/net/net_windows_test.go delete mode 100644 src/pkg/net/netgo_unix_test.go delete mode 100644 src/pkg/net/packetconn_test.go delete mode 100644 src/pkg/net/parse.go delete mode 100644 src/pkg/net/parse_test.go delete mode 100644 src/pkg/net/pipe.go delete mode 100644 src/pkg/net/pipe_test.go delete mode 100644 src/pkg/net/port.go delete mode 100644 src/pkg/net/port_test.go delete mode 100644 src/pkg/net/port_unix.go delete mode 100644 src/pkg/net/protoconn_test.go delete mode 100644 src/pkg/net/race.go delete mode 100644 src/pkg/net/race0.go delete mode 100644 src/pkg/net/rpc/client.go delete mode 100644 src/pkg/net/rpc/client_test.go delete mode 100644 src/pkg/net/rpc/debug.go delete mode 100644 src/pkg/net/rpc/jsonrpc/all_test.go delete mode 100644 src/pkg/net/rpc/jsonrpc/client.go delete mode 100644 src/pkg/net/rpc/jsonrpc/server.go delete mode 100644 src/pkg/net/rpc/server.go delete mode 100644 src/pkg/net/rpc/server_test.go delete mode 100644 src/pkg/net/sendfile_dragonfly.go delete mode 100644 src/pkg/net/sendfile_freebsd.go delete mode 100644 src/pkg/net/sendfile_linux.go delete mode 100644 src/pkg/net/sendfile_stub.go delete mode 100644 src/pkg/net/sendfile_windows.go delete mode 100644 src/pkg/net/server_test.go delete mode 100644 src/pkg/net/singleflight.go delete mode 100644 src/pkg/net/smtp/auth.go delete mode 100644 src/pkg/net/smtp/example_test.go delete mode 100644 src/pkg/net/smtp/smtp.go delete mode 100644 src/pkg/net/smtp/smtp_test.go delete mode 100644 src/pkg/net/sock_bsd.go delete mode 100644 src/pkg/net/sock_cloexec.go delete mode 100644 src/pkg/net/sock_linux.go delete mode 100644 src/pkg/net/sock_plan9.go delete mode 100644 src/pkg/net/sock_posix.go delete mode 100644 src/pkg/net/sock_solaris.go delete mode 100644 src/pkg/net/sock_windows.go delete mode 100644 src/pkg/net/sockopt_bsd.go delete mode 100644 src/pkg/net/sockopt_linux.go delete mode 100644 src/pkg/net/sockopt_plan9.go delete mode 100644 src/pkg/net/sockopt_posix.go delete mode 100644 src/pkg/net/sockopt_solaris.go delete mode 100644 src/pkg/net/sockopt_windows.go delete mode 100644 src/pkg/net/sockoptip_bsd.go delete mode 100644 src/pkg/net/sockoptip_linux.go delete mode 100644 src/pkg/net/sockoptip_posix.go delete mode 100644 src/pkg/net/sockoptip_stub.go delete mode 100644 src/pkg/net/sockoptip_windows.go delete mode 100644 src/pkg/net/sys_cloexec.go delete mode 100644 src/pkg/net/tcp_test.go delete mode 100644 src/pkg/net/tcpsock.go delete mode 100644 src/pkg/net/tcpsock_plan9.go delete mode 100644 src/pkg/net/tcpsock_posix.go delete mode 100644 src/pkg/net/tcpsockopt_darwin.go delete mode 100644 src/pkg/net/tcpsockopt_dragonfly.go delete mode 100644 src/pkg/net/tcpsockopt_openbsd.go delete mode 100644 src/pkg/net/tcpsockopt_plan9.go delete mode 100644 src/pkg/net/tcpsockopt_posix.go delete mode 100644 src/pkg/net/tcpsockopt_solaris.go delete mode 100644 src/pkg/net/tcpsockopt_unix.go delete mode 100644 src/pkg/net/tcpsockopt_windows.go delete mode 100644 src/pkg/net/testdata/hosts delete mode 100644 src/pkg/net/testdata/hosts_singleline delete mode 100644 src/pkg/net/testdata/igmp delete mode 100644 src/pkg/net/testdata/igmp6 delete mode 100644 src/pkg/net/testdata/resolv.conf delete mode 100644 src/pkg/net/textproto/header.go delete mode 100644 src/pkg/net/textproto/pipeline.go delete mode 100644 src/pkg/net/textproto/reader.go delete mode 100644 src/pkg/net/textproto/reader_test.go delete mode 100644 src/pkg/net/textproto/textproto.go delete mode 100644 src/pkg/net/textproto/writer.go delete mode 100644 src/pkg/net/textproto/writer_test.go delete mode 100644 src/pkg/net/timeout_test.go delete mode 100644 src/pkg/net/udp_test.go delete mode 100644 src/pkg/net/udpsock.go delete mode 100644 src/pkg/net/udpsock_plan9.go delete mode 100644 src/pkg/net/udpsock_posix.go delete mode 100644 src/pkg/net/unicast_posix_test.go delete mode 100644 src/pkg/net/unix_test.go delete mode 100644 src/pkg/net/unixsock.go delete mode 100644 src/pkg/net/unixsock_plan9.go delete mode 100644 src/pkg/net/unixsock_posix.go delete mode 100644 src/pkg/net/url/example_test.go delete mode 100644 src/pkg/net/url/url.go delete mode 100644 src/pkg/net/url/url_test.go delete mode 100644 src/pkg/net/z_last_test.go delete mode 100644 src/pkg/os/dir_plan9.go delete mode 100644 src/pkg/os/dir_unix.go delete mode 100644 src/pkg/os/dir_windows.go delete mode 100644 src/pkg/os/doc.go delete mode 100644 src/pkg/os/env.go delete mode 100644 src/pkg/os/env_test.go delete mode 100644 src/pkg/os/env_unix_test.go delete mode 100644 src/pkg/os/error.go delete mode 100644 src/pkg/os/error_plan9.go delete mode 100644 src/pkg/os/error_test.go delete mode 100644 src/pkg/os/error_unix.go delete mode 100644 src/pkg/os/error_windows.go delete mode 100644 src/pkg/os/error_windows_test.go delete mode 100644 src/pkg/os/exec.go delete mode 100644 src/pkg/os/exec/example_test.go delete mode 100644 src/pkg/os/exec/exec.go delete mode 100644 src/pkg/os/exec/exec_test.go delete mode 100644 src/pkg/os/exec/lp_plan9.go delete mode 100644 src/pkg/os/exec/lp_test.go delete mode 100644 src/pkg/os/exec/lp_unix.go delete mode 100644 src/pkg/os/exec/lp_unix_test.go delete mode 100644 src/pkg/os/exec/lp_windows.go delete mode 100644 src/pkg/os/exec/lp_windows_test.go delete mode 100644 src/pkg/os/exec_plan9.go delete mode 100644 src/pkg/os/exec_posix.go delete mode 100644 src/pkg/os/exec_unix.go delete mode 100644 src/pkg/os/exec_windows.go delete mode 100644 src/pkg/os/export_test.go delete mode 100644 src/pkg/os/file.go delete mode 100644 src/pkg/os/file_plan9.go delete mode 100644 src/pkg/os/file_posix.go delete mode 100644 src/pkg/os/file_unix.go delete mode 100644 src/pkg/os/file_windows.go delete mode 100644 src/pkg/os/getwd.go delete mode 100644 src/pkg/os/getwd_darwin.go delete mode 100644 src/pkg/os/os_test.go delete mode 100644 src/pkg/os/os_unix_test.go delete mode 100644 src/pkg/os/path.go delete mode 100644 src/pkg/os/path_plan9.go delete mode 100644 src/pkg/os/path_test.go delete mode 100644 src/pkg/os/path_unix.go delete mode 100644 src/pkg/os/path_windows.go delete mode 100644 src/pkg/os/pipe_bsd.go delete mode 100644 src/pkg/os/pipe_linux.go delete mode 100644 src/pkg/os/proc.go delete mode 100644 src/pkg/os/signal/example_test.go delete mode 100644 src/pkg/os/signal/sig.s delete mode 100644 src/pkg/os/signal/signal.go delete mode 100644 src/pkg/os/signal/signal_stub.go delete mode 100644 src/pkg/os/signal/signal_test.go delete mode 100644 src/pkg/os/signal/signal_unix.go delete mode 100644 src/pkg/os/signal/signal_windows_test.go delete mode 100644 src/pkg/os/stat_darwin.go delete mode 100644 src/pkg/os/stat_dragonfly.go delete mode 100644 src/pkg/os/stat_freebsd.go delete mode 100644 src/pkg/os/stat_linux.go delete mode 100644 src/pkg/os/stat_nacl.go delete mode 100644 src/pkg/os/stat_netbsd.go delete mode 100644 src/pkg/os/stat_openbsd.go delete mode 100644 src/pkg/os/stat_plan9.go delete mode 100644 src/pkg/os/stat_solaris.go delete mode 100644 src/pkg/os/stat_windows.go delete mode 100644 src/pkg/os/str.go delete mode 100644 src/pkg/os/sys_bsd.go delete mode 100644 src/pkg/os/sys_darwin.go delete mode 100644 src/pkg/os/sys_freebsd.go delete mode 100644 src/pkg/os/sys_linux.go delete mode 100644 src/pkg/os/sys_nacl.go delete mode 100644 src/pkg/os/sys_plan9.go delete mode 100644 src/pkg/os/sys_solaris.go delete mode 100644 src/pkg/os/sys_unix.go delete mode 100644 src/pkg/os/sys_windows.go delete mode 100644 src/pkg/os/types.go delete mode 100644 src/pkg/os/types_notwin.go delete mode 100644 src/pkg/os/types_windows.go delete mode 100644 src/pkg/os/user/lookup.go delete mode 100644 src/pkg/os/user/lookup_plan9.go delete mode 100644 src/pkg/os/user/lookup_stubs.go delete mode 100644 src/pkg/os/user/lookup_unix.go delete mode 100644 src/pkg/os/user/lookup_windows.go delete mode 100644 src/pkg/os/user/user.go delete mode 100644 src/pkg/os/user/user_test.go delete mode 100644 src/pkg/path/example_test.go delete mode 100644 src/pkg/path/filepath/example_unix_test.go delete mode 100644 src/pkg/path/filepath/export_test.go delete mode 100644 src/pkg/path/filepath/match.go delete mode 100644 src/pkg/path/filepath/match_test.go delete mode 100644 src/pkg/path/filepath/path.go delete mode 100644 src/pkg/path/filepath/path_plan9.go delete mode 100644 src/pkg/path/filepath/path_test.go delete mode 100644 src/pkg/path/filepath/path_unix.go delete mode 100644 src/pkg/path/filepath/path_windows.go delete mode 100644 src/pkg/path/filepath/path_windows_test.go delete mode 100644 src/pkg/path/filepath/symlink.go delete mode 100644 src/pkg/path/filepath/symlink_windows.go delete mode 100644 src/pkg/path/match.go delete mode 100644 src/pkg/path/match_test.go delete mode 100644 src/pkg/path/path.go delete mode 100644 src/pkg/path/path_test.go delete mode 100644 src/pkg/reflect/all_test.go delete mode 100644 src/pkg/reflect/asm_386.s delete mode 100644 src/pkg/reflect/asm_amd64.s delete mode 100644 src/pkg/reflect/asm_amd64p32.s delete mode 100644 src/pkg/reflect/asm_arm.s delete mode 100644 src/pkg/reflect/deepequal.go delete mode 100644 src/pkg/reflect/example_test.go delete mode 100644 src/pkg/reflect/export_test.go delete mode 100644 src/pkg/reflect/makefunc.go delete mode 100644 src/pkg/reflect/set_test.go delete mode 100644 src/pkg/reflect/tostring_test.go delete mode 100644 src/pkg/reflect/type.go delete mode 100644 src/pkg/reflect/value.go delete mode 100644 src/pkg/regexp/all_test.go delete mode 100644 src/pkg/regexp/example_test.go delete mode 100644 src/pkg/regexp/exec.go delete mode 100644 src/pkg/regexp/exec2_test.go delete mode 100644 src/pkg/regexp/exec_test.go delete mode 100644 src/pkg/regexp/find_test.go delete mode 100644 src/pkg/regexp/onepass.go delete mode 100644 src/pkg/regexp/onepass_test.go delete mode 100644 src/pkg/regexp/regexp.go delete mode 100644 src/pkg/regexp/syntax/compile.go delete mode 100644 src/pkg/regexp/syntax/doc.go delete mode 100755 src/pkg/regexp/syntax/make_perl_groups.pl delete mode 100644 src/pkg/regexp/syntax/parse.go delete mode 100644 src/pkg/regexp/syntax/parse_test.go delete mode 100644 src/pkg/regexp/syntax/perl_groups.go delete mode 100644 src/pkg/regexp/syntax/prog.go delete mode 100644 src/pkg/regexp/syntax/prog_test.go delete mode 100644 src/pkg/regexp/syntax/regexp.go delete mode 100644 src/pkg/regexp/syntax/simplify.go delete mode 100644 src/pkg/regexp/syntax/simplify_test.go delete mode 100644 src/pkg/regexp/testdata/README delete mode 100644 src/pkg/regexp/testdata/basic.dat delete mode 100644 src/pkg/regexp/testdata/nullsubexpr.dat delete mode 100644 src/pkg/regexp/testdata/re2-exhaustive.txt.bz2 delete mode 100644 src/pkg/regexp/testdata/re2-search.txt delete mode 100644 src/pkg/regexp/testdata/repetition.dat delete mode 100644 src/pkg/regexp/testdata/testregex.c delete mode 100644 src/pkg/runtime/Makefile delete mode 100644 src/pkg/runtime/alg.goc delete mode 100644 src/pkg/runtime/append_test.go delete mode 100644 src/pkg/runtime/arch_386.h delete mode 100644 src/pkg/runtime/arch_amd64.h delete mode 100644 src/pkg/runtime/arch_amd64p32.h delete mode 100644 src/pkg/runtime/arch_arm.h delete mode 100644 src/pkg/runtime/asm_386.s delete mode 100644 src/pkg/runtime/asm_amd64.s delete mode 100644 src/pkg/runtime/asm_amd64p32.s delete mode 100644 src/pkg/runtime/asm_arm.s delete mode 100644 src/pkg/runtime/atomic_386.c delete mode 100644 src/pkg/runtime/atomic_amd64x.c delete mode 100644 src/pkg/runtime/atomic_arm.c delete mode 100644 src/pkg/runtime/callback_windows.c delete mode 100644 src/pkg/runtime/cgo/asm_386.s delete mode 100644 src/pkg/runtime/cgo/asm_amd64.s delete mode 100644 src/pkg/runtime/cgo/asm_arm.s delete mode 100644 src/pkg/runtime/cgo/asm_nacl_amd64p32.s delete mode 100644 src/pkg/runtime/cgo/callbacks.c delete mode 100644 src/pkg/runtime/cgo/cgo.go delete mode 100644 src/pkg/runtime/cgo/dragonfly.c delete mode 100644 src/pkg/runtime/cgo/freebsd.c delete mode 100644 src/pkg/runtime/cgo/gcc_386.S delete mode 100644 src/pkg/runtime/cgo/gcc_amd64.S delete mode 100644 src/pkg/runtime/cgo/gcc_arm.S delete mode 100644 src/pkg/runtime/cgo/gcc_darwin_386.c delete mode 100644 src/pkg/runtime/cgo/gcc_darwin_amd64.c delete mode 100644 src/pkg/runtime/cgo/gcc_dragonfly_386.c delete mode 100644 src/pkg/runtime/cgo/gcc_dragonfly_amd64.c delete mode 100644 src/pkg/runtime/cgo/gcc_freebsd_386.c delete mode 100644 src/pkg/runtime/cgo/gcc_freebsd_amd64.c delete mode 100644 src/pkg/runtime/cgo/gcc_freebsd_arm.c delete mode 100644 src/pkg/runtime/cgo/gcc_linux_386.c delete mode 100644 src/pkg/runtime/cgo/gcc_linux_amd64.c delete mode 100644 src/pkg/runtime/cgo/gcc_linux_arm.c delete mode 100644 src/pkg/runtime/cgo/gcc_netbsd_386.c delete mode 100644 src/pkg/runtime/cgo/gcc_netbsd_amd64.c delete mode 100644 src/pkg/runtime/cgo/gcc_netbsd_arm.c delete mode 100644 src/pkg/runtime/cgo/gcc_openbsd_386.c delete mode 100644 src/pkg/runtime/cgo/gcc_openbsd_amd64.c delete mode 100644 src/pkg/runtime/cgo/gcc_setenv.c delete mode 100644 src/pkg/runtime/cgo/gcc_util.c delete mode 100644 src/pkg/runtime/cgo/gcc_windows_386.c delete mode 100644 src/pkg/runtime/cgo/gcc_windows_amd64.c delete mode 100644 src/pkg/runtime/cgo/iscgo.c delete mode 100644 src/pkg/runtime/cgo/libcgo.h delete mode 100644 src/pkg/runtime/cgo/netbsd.c delete mode 100644 src/pkg/runtime/cgo/openbsd.c delete mode 100644 src/pkg/runtime/cgo/setenv.c delete mode 100644 src/pkg/runtime/cgocall.c delete mode 100644 src/pkg/runtime/cgocall.h delete mode 100644 src/pkg/runtime/chan.goc delete mode 100644 src/pkg/runtime/chan.h delete mode 100644 src/pkg/runtime/chan_test.go delete mode 100644 src/pkg/runtime/closure_test.go delete mode 100644 src/pkg/runtime/compiler.go delete mode 100644 src/pkg/runtime/complex.goc delete mode 100644 src/pkg/runtime/complex_test.go delete mode 100644 src/pkg/runtime/cpuprof.goc delete mode 100644 src/pkg/runtime/crash_cgo_test.go delete mode 100644 src/pkg/runtime/crash_test.go delete mode 100644 src/pkg/runtime/debug.go delete mode 100644 src/pkg/runtime/debug/debug.c delete mode 100644 src/pkg/runtime/debug/garbage.go delete mode 100644 src/pkg/runtime/debug/garbage_test.go delete mode 100644 src/pkg/runtime/debug/heapdump_test.go delete mode 100644 src/pkg/runtime/debug/stack.go delete mode 100644 src/pkg/runtime/debug/stack_test.go delete mode 100644 src/pkg/runtime/defs.c delete mode 100644 src/pkg/runtime/defs1_linux.go delete mode 100644 src/pkg/runtime/defs2_linux.go delete mode 100644 src/pkg/runtime/defs_arm_linux.go delete mode 100644 src/pkg/runtime/defs_darwin.go delete mode 100644 src/pkg/runtime/defs_darwin_386.h delete mode 100644 src/pkg/runtime/defs_darwin_amd64.h delete mode 100644 src/pkg/runtime/defs_dragonfly.go delete mode 100644 src/pkg/runtime/defs_dragonfly_386.h delete mode 100644 src/pkg/runtime/defs_dragonfly_amd64.h delete mode 100644 src/pkg/runtime/defs_freebsd.go delete mode 100644 src/pkg/runtime/defs_freebsd_386.h delete mode 100644 src/pkg/runtime/defs_freebsd_amd64.h delete mode 100644 src/pkg/runtime/defs_freebsd_arm.h delete mode 100644 src/pkg/runtime/defs_linux.go delete mode 100644 src/pkg/runtime/defs_linux_386.h delete mode 100644 src/pkg/runtime/defs_linux_amd64.h delete mode 100644 src/pkg/runtime/defs_linux_arm.h delete mode 100644 src/pkg/runtime/defs_nacl_386.h delete mode 100644 src/pkg/runtime/defs_nacl_amd64p32.h delete mode 100644 src/pkg/runtime/defs_netbsd.go delete mode 100644 src/pkg/runtime/defs_netbsd_386.go delete mode 100644 src/pkg/runtime/defs_netbsd_386.h delete mode 100644 src/pkg/runtime/defs_netbsd_amd64.go delete mode 100644 src/pkg/runtime/defs_netbsd_amd64.h delete mode 100644 src/pkg/runtime/defs_netbsd_arm.go delete mode 100644 src/pkg/runtime/defs_netbsd_arm.h delete mode 100644 src/pkg/runtime/defs_openbsd.go delete mode 100644 src/pkg/runtime/defs_openbsd_386.h delete mode 100644 src/pkg/runtime/defs_openbsd_amd64.h delete mode 100644 src/pkg/runtime/defs_plan9_386.h delete mode 100644 src/pkg/runtime/defs_plan9_amd64.h delete mode 100644 src/pkg/runtime/defs_solaris.go delete mode 100644 src/pkg/runtime/defs_solaris_amd64.go delete mode 100644 src/pkg/runtime/defs_solaris_amd64.h delete mode 100644 src/pkg/runtime/defs_windows.go delete mode 100644 src/pkg/runtime/defs_windows_386.h delete mode 100644 src/pkg/runtime/defs_windows_amd64.h delete mode 100644 src/pkg/runtime/env_plan9.c delete mode 100644 src/pkg/runtime/env_posix.c delete mode 100644 src/pkg/runtime/error.go delete mode 100644 src/pkg/runtime/export_futex_test.go delete mode 100644 src/pkg/runtime/export_test.go delete mode 100644 src/pkg/runtime/extern.go delete mode 100644 src/pkg/runtime/float.c delete mode 100644 src/pkg/runtime/funcdata.h delete mode 100644 src/pkg/runtime/futex_test.go delete mode 100644 src/pkg/runtime/gc_test.go delete mode 100644 src/pkg/runtime/hash_test.go delete mode 100644 src/pkg/runtime/hashmap.goc delete mode 100644 src/pkg/runtime/hashmap.h delete mode 100644 src/pkg/runtime/hashmap_fast.c delete mode 100644 src/pkg/runtime/heapdump.c delete mode 100644 src/pkg/runtime/iface.goc delete mode 100644 src/pkg/runtime/iface_test.go delete mode 100644 src/pkg/runtime/lfstack.goc delete mode 100644 src/pkg/runtime/lfstack_test.go delete mode 100644 src/pkg/runtime/lock_futex.c delete mode 100644 src/pkg/runtime/lock_sema.c delete mode 100644 src/pkg/runtime/malloc.goc delete mode 100644 src/pkg/runtime/malloc.h delete mode 100644 src/pkg/runtime/malloc1.go delete mode 100644 src/pkg/runtime/malloc_test.go delete mode 100644 src/pkg/runtime/mallocrand.go delete mode 100644 src/pkg/runtime/mallocrep.go delete mode 100644 src/pkg/runtime/mallocrep1.go delete mode 100644 src/pkg/runtime/map_test.go delete mode 100644 src/pkg/runtime/mapspeed_test.go delete mode 100644 src/pkg/runtime/mcache.c delete mode 100644 src/pkg/runtime/mcentral.c delete mode 100644 src/pkg/runtime/mem.go delete mode 100644 src/pkg/runtime/mem_darwin.c delete mode 100644 src/pkg/runtime/mem_dragonfly.c delete mode 100644 src/pkg/runtime/mem_freebsd.c delete mode 100644 src/pkg/runtime/mem_linux.c delete mode 100644 src/pkg/runtime/mem_nacl.c delete mode 100644 src/pkg/runtime/mem_netbsd.c delete mode 100644 src/pkg/runtime/mem_openbsd.c delete mode 100644 src/pkg/runtime/mem_plan9.c delete mode 100644 src/pkg/runtime/mem_solaris.c delete mode 100644 src/pkg/runtime/mem_windows.c delete mode 100644 src/pkg/runtime/memclr_386.s delete mode 100644 src/pkg/runtime/memclr_amd64.s delete mode 100644 src/pkg/runtime/memclr_arm.s delete mode 100644 src/pkg/runtime/memclr_plan9_386.s delete mode 100644 src/pkg/runtime/memclr_plan9_amd64.s delete mode 100644 src/pkg/runtime/memmove_386.s delete mode 100644 src/pkg/runtime/memmove_amd64.s delete mode 100644 src/pkg/runtime/memmove_arm.s delete mode 100644 src/pkg/runtime/memmove_linux_amd64_test.go delete mode 100644 src/pkg/runtime/memmove_nacl_amd64p32.s delete mode 100644 src/pkg/runtime/memmove_plan9_386.s delete mode 100644 src/pkg/runtime/memmove_plan9_amd64.s delete mode 100644 src/pkg/runtime/memmove_test.go delete mode 100644 src/pkg/runtime/mfinal_test.go delete mode 100644 src/pkg/runtime/mfixalloc.c delete mode 100644 src/pkg/runtime/mgc0.c delete mode 100644 src/pkg/runtime/mgc0.go delete mode 100644 src/pkg/runtime/mgc0.h delete mode 100644 src/pkg/runtime/mheap.c delete mode 100644 src/pkg/runtime/mknacl.sh delete mode 100644 src/pkg/runtime/mprof.goc delete mode 100644 src/pkg/runtime/msize.c delete mode 100644 src/pkg/runtime/netpoll.goc delete mode 100644 src/pkg/runtime/netpoll_epoll.c delete mode 100644 src/pkg/runtime/netpoll_kqueue.c delete mode 100644 src/pkg/runtime/netpoll_nacl.c delete mode 100644 src/pkg/runtime/netpoll_solaris.c delete mode 100644 src/pkg/runtime/netpoll_stub.c delete mode 100644 src/pkg/runtime/netpoll_windows.c delete mode 100644 src/pkg/runtime/noasm_arm.goc delete mode 100644 src/pkg/runtime/norace_test.go delete mode 100644 src/pkg/runtime/os_darwin.c delete mode 100644 src/pkg/runtime/os_darwin.h delete mode 100644 src/pkg/runtime/os_dragonfly.c delete mode 100644 src/pkg/runtime/os_dragonfly.h delete mode 100644 src/pkg/runtime/os_freebsd.c delete mode 100644 src/pkg/runtime/os_freebsd.h delete mode 100644 src/pkg/runtime/os_freebsd_arm.c delete mode 100644 src/pkg/runtime/os_linux.c delete mode 100644 src/pkg/runtime/os_linux.h delete mode 100644 src/pkg/runtime/os_linux_386.c delete mode 100644 src/pkg/runtime/os_linux_arm.c delete mode 100644 src/pkg/runtime/os_nacl.c delete mode 100644 src/pkg/runtime/os_nacl.h delete mode 100644 src/pkg/runtime/os_netbsd.c delete mode 100644 src/pkg/runtime/os_netbsd.h delete mode 100644 src/pkg/runtime/os_netbsd_386.c delete mode 100644 src/pkg/runtime/os_netbsd_amd64.c delete mode 100644 src/pkg/runtime/os_netbsd_arm.c delete mode 100644 src/pkg/runtime/os_openbsd.c delete mode 100644 src/pkg/runtime/os_openbsd.h delete mode 100644 src/pkg/runtime/os_plan9.c delete mode 100644 src/pkg/runtime/os_plan9.h delete mode 100644 src/pkg/runtime/os_plan9_386.c delete mode 100644 src/pkg/runtime/os_plan9_amd64.c delete mode 100644 src/pkg/runtime/os_solaris.c delete mode 100644 src/pkg/runtime/os_solaris.h delete mode 100644 src/pkg/runtime/os_windows.c delete mode 100644 src/pkg/runtime/os_windows.h delete mode 100644 src/pkg/runtime/os_windows_386.c delete mode 100644 src/pkg/runtime/os_windows_amd64.c delete mode 100644 src/pkg/runtime/panic.c delete mode 100644 src/pkg/runtime/parfor.c delete mode 100644 src/pkg/runtime/parfor_test.go delete mode 100644 src/pkg/runtime/pprof/pprof.go delete mode 100644 src/pkg/runtime/pprof/pprof_test.go delete mode 100644 src/pkg/runtime/print.c delete mode 100644 src/pkg/runtime/proc.c delete mode 100644 src/pkg/runtime/proc_test.go delete mode 100644 src/pkg/runtime/race.c delete mode 100644 src/pkg/runtime/race.go delete mode 100644 src/pkg/runtime/race.h delete mode 100644 src/pkg/runtime/race/README delete mode 100644 src/pkg/runtime/race/doc.go delete mode 100644 src/pkg/runtime/race/output_test.go delete mode 100644 src/pkg/runtime/race/race.go delete mode 100644 src/pkg/runtime/race/race_darwin_amd64.syso delete mode 100644 src/pkg/runtime/race/race_linux_amd64.syso delete mode 100644 src/pkg/runtime/race/race_test.go delete mode 100644 src/pkg/runtime/race/race_windows_amd64.syso delete mode 100644 src/pkg/runtime/race/testdata/atomic_test.go delete mode 100644 src/pkg/runtime/race/testdata/cgo_test.go delete mode 100644 src/pkg/runtime/race/testdata/cgo_test_main.go delete mode 100644 src/pkg/runtime/race/testdata/chan_test.go delete mode 100644 src/pkg/runtime/race/testdata/comp_test.go delete mode 100644 src/pkg/runtime/race/testdata/finalizer_test.go delete mode 100644 src/pkg/runtime/race/testdata/io_test.go delete mode 100644 src/pkg/runtime/race/testdata/map_test.go delete mode 100644 src/pkg/runtime/race/testdata/mop_test.go delete mode 100644 src/pkg/runtime/race/testdata/mutex_test.go delete mode 100644 src/pkg/runtime/race/testdata/regression_test.go delete mode 100644 src/pkg/runtime/race/testdata/rwmutex_test.go delete mode 100644 src/pkg/runtime/race/testdata/select_test.go delete mode 100644 src/pkg/runtime/race/testdata/slice_test.go delete mode 100644 src/pkg/runtime/race/testdata/sync_test.go delete mode 100644 src/pkg/runtime/race/testdata/waitgroup_test.go delete mode 100644 src/pkg/runtime/race0.c delete mode 100644 src/pkg/runtime/race_amd64.s delete mode 100644 src/pkg/runtime/rdebug.goc delete mode 100644 src/pkg/runtime/rt0_darwin_386.s delete mode 100644 src/pkg/runtime/rt0_darwin_amd64.s delete mode 100644 src/pkg/runtime/rt0_dragonfly_386.s delete mode 100644 src/pkg/runtime/rt0_dragonfly_amd64.s delete mode 100644 src/pkg/runtime/rt0_freebsd_386.s delete mode 100644 src/pkg/runtime/rt0_freebsd_amd64.s delete mode 100644 src/pkg/runtime/rt0_freebsd_arm.s delete mode 100644 src/pkg/runtime/rt0_linux_386.s delete mode 100644 src/pkg/runtime/rt0_linux_amd64.s delete mode 100644 src/pkg/runtime/rt0_linux_arm.s delete mode 100644 src/pkg/runtime/rt0_nacl_386.s delete mode 100644 src/pkg/runtime/rt0_nacl_amd64p32.s delete mode 100644 src/pkg/runtime/rt0_netbsd_386.s delete mode 100644 src/pkg/runtime/rt0_netbsd_amd64.s delete mode 100644 src/pkg/runtime/rt0_netbsd_arm.s delete mode 100644 src/pkg/runtime/rt0_openbsd_386.s delete mode 100644 src/pkg/runtime/rt0_openbsd_amd64.s delete mode 100644 src/pkg/runtime/rt0_plan9_386.s delete mode 100644 src/pkg/runtime/rt0_plan9_amd64.s delete mode 100644 src/pkg/runtime/rt0_solaris_amd64.s delete mode 100644 src/pkg/runtime/rt0_windows_386.s delete mode 100644 src/pkg/runtime/rt0_windows_amd64.s delete mode 100644 src/pkg/runtime/rune.c delete mode 100644 src/pkg/runtime/runtime-gdb.py delete mode 100644 src/pkg/runtime/runtime.c delete mode 100644 src/pkg/runtime/runtime.h delete mode 100644 src/pkg/runtime/runtime1.goc delete mode 100644 src/pkg/runtime/runtime_linux_test.go delete mode 100644 src/pkg/runtime/runtime_test.go delete mode 100644 src/pkg/runtime/runtime_unix_test.go delete mode 100644 src/pkg/runtime/sema.goc delete mode 100644 src/pkg/runtime/signal_386.c delete mode 100644 src/pkg/runtime/signal_amd64x.c delete mode 100644 src/pkg/runtime/signal_arm.c delete mode 100644 src/pkg/runtime/signal_darwin_386.h delete mode 100644 src/pkg/runtime/signal_darwin_amd64.h delete mode 100644 src/pkg/runtime/signal_dragonfly_386.h delete mode 100644 src/pkg/runtime/signal_dragonfly_amd64.h delete mode 100644 src/pkg/runtime/signal_freebsd_386.h delete mode 100644 src/pkg/runtime/signal_freebsd_amd64.h delete mode 100644 src/pkg/runtime/signal_freebsd_arm.h delete mode 100644 src/pkg/runtime/signal_linux_386.h delete mode 100644 src/pkg/runtime/signal_linux_amd64.h delete mode 100644 src/pkg/runtime/signal_linux_arm.h delete mode 100644 src/pkg/runtime/signal_nacl_386.h delete mode 100644 src/pkg/runtime/signal_nacl_amd64p32.h delete mode 100644 src/pkg/runtime/signal_netbsd_386.h delete mode 100644 src/pkg/runtime/signal_netbsd_amd64.h delete mode 100644 src/pkg/runtime/signal_netbsd_arm.h delete mode 100644 src/pkg/runtime/signal_openbsd_386.h delete mode 100644 src/pkg/runtime/signal_openbsd_amd64.h delete mode 100644 src/pkg/runtime/signal_solaris_amd64.h delete mode 100644 src/pkg/runtime/signal_unix.c delete mode 100644 src/pkg/runtime/signal_unix.h delete mode 100644 src/pkg/runtime/signals_darwin.h delete mode 100644 src/pkg/runtime/signals_dragonfly.h delete mode 100644 src/pkg/runtime/signals_freebsd.h delete mode 100644 src/pkg/runtime/signals_linux.h delete mode 100644 src/pkg/runtime/signals_nacl.h delete mode 100644 src/pkg/runtime/signals_netbsd.h delete mode 100644 src/pkg/runtime/signals_openbsd.h delete mode 100644 src/pkg/runtime/signals_plan9.h delete mode 100644 src/pkg/runtime/signals_solaris.h delete mode 100644 src/pkg/runtime/signals_windows.h delete mode 100644 src/pkg/runtime/sigqueue.goc delete mode 100644 src/pkg/runtime/slice.goc delete mode 100644 src/pkg/runtime/softfloat64.go delete mode 100644 src/pkg/runtime/softfloat64_test.go delete mode 100644 src/pkg/runtime/softfloat_arm.c delete mode 100644 src/pkg/runtime/sqrt.go delete mode 100644 src/pkg/runtime/stack.c delete mode 100644 src/pkg/runtime/stack.h delete mode 100644 src/pkg/runtime/stack_gen_test.go delete mode 100644 src/pkg/runtime/stack_test.go delete mode 100644 src/pkg/runtime/string.goc delete mode 100644 src/pkg/runtime/string_test.go delete mode 100644 src/pkg/runtime/symtab.goc delete mode 100644 src/pkg/runtime/symtab_test.go delete mode 100644 src/pkg/runtime/sys_arm.c delete mode 100644 src/pkg/runtime/sys_darwin_386.s delete mode 100644 src/pkg/runtime/sys_darwin_amd64.s delete mode 100644 src/pkg/runtime/sys_dragonfly_386.s delete mode 100644 src/pkg/runtime/sys_dragonfly_amd64.s delete mode 100644 src/pkg/runtime/sys_freebsd_386.s delete mode 100644 src/pkg/runtime/sys_freebsd_amd64.s delete mode 100644 src/pkg/runtime/sys_freebsd_arm.s delete mode 100644 src/pkg/runtime/sys_linux_386.s delete mode 100644 src/pkg/runtime/sys_linux_amd64.s delete mode 100644 src/pkg/runtime/sys_linux_arm.s delete mode 100644 src/pkg/runtime/sys_nacl_386.s delete mode 100644 src/pkg/runtime/sys_nacl_amd64p32.s delete mode 100644 src/pkg/runtime/sys_netbsd_386.s delete mode 100644 src/pkg/runtime/sys_netbsd_amd64.s delete mode 100644 src/pkg/runtime/sys_netbsd_arm.s delete mode 100644 src/pkg/runtime/sys_openbsd_386.s delete mode 100644 src/pkg/runtime/sys_openbsd_amd64.s delete mode 100644 src/pkg/runtime/sys_plan9_386.s delete mode 100644 src/pkg/runtime/sys_plan9_amd64.s delete mode 100644 src/pkg/runtime/sys_solaris_amd64.s delete mode 100644 src/pkg/runtime/sys_windows_386.s delete mode 100644 src/pkg/runtime/sys_windows_amd64.s delete mode 100644 src/pkg/runtime/sys_x86.c delete mode 100644 src/pkg/runtime/syscall_nacl.h delete mode 100644 src/pkg/runtime/syscall_solaris.goc delete mode 100644 src/pkg/runtime/syscall_windows.goc delete mode 100644 src/pkg/runtime/syscall_windows_test.go delete mode 100644 src/pkg/runtime/time.goc delete mode 100644 src/pkg/runtime/time_plan9_386.c delete mode 100644 src/pkg/runtime/traceback_arm.c delete mode 100644 src/pkg/runtime/traceback_x86.c delete mode 100644 src/pkg/runtime/type.go delete mode 100644 src/pkg/runtime/type.h delete mode 100644 src/pkg/runtime/typekind.h delete mode 100644 src/pkg/runtime/vdso_linux_amd64.c delete mode 100644 src/pkg/runtime/vlop_386.s delete mode 100644 src/pkg/runtime/vlop_arm.s delete mode 100644 src/pkg/runtime/vlop_arm_test.go delete mode 100644 src/pkg/runtime/vlrt_386.c delete mode 100644 src/pkg/runtime/vlrt_arm.c delete mode 100644 src/pkg/sort/example_interface_test.go delete mode 100644 src/pkg/sort/example_keys_test.go delete mode 100644 src/pkg/sort/example_multi_test.go delete mode 100644 src/pkg/sort/example_test.go delete mode 100644 src/pkg/sort/example_wrapper_test.go delete mode 100644 src/pkg/sort/export_test.go delete mode 100644 src/pkg/sort/search.go delete mode 100644 src/pkg/sort/search_test.go delete mode 100644 src/pkg/sort/sort.go delete mode 100644 src/pkg/sort/sort_test.go delete mode 100644 src/pkg/strconv/atob.go delete mode 100644 src/pkg/strconv/atob_test.go delete mode 100644 src/pkg/strconv/atof.go delete mode 100644 src/pkg/strconv/atof_test.go delete mode 100644 src/pkg/strconv/atoi.go delete mode 100644 src/pkg/strconv/atoi_test.go delete mode 100644 src/pkg/strconv/decimal.go delete mode 100644 src/pkg/strconv/decimal_test.go delete mode 100644 src/pkg/strconv/extfloat.go delete mode 100644 src/pkg/strconv/fp_test.go delete mode 100644 src/pkg/strconv/ftoa.go delete mode 100644 src/pkg/strconv/ftoa_test.go delete mode 100644 src/pkg/strconv/internal_test.go delete mode 100644 src/pkg/strconv/isprint.go delete mode 100644 src/pkg/strconv/itoa.go delete mode 100644 src/pkg/strconv/itoa_test.go delete mode 100644 src/pkg/strconv/makeisprint.go delete mode 100644 src/pkg/strconv/quote.go delete mode 100644 src/pkg/strconv/quote_example_test.go delete mode 100644 src/pkg/strconv/quote_test.go delete mode 100644 src/pkg/strconv/strconv_test.go delete mode 100644 src/pkg/strconv/testdata/testfp.txt delete mode 100644 src/pkg/strings/example_test.go delete mode 100644 src/pkg/strings/export_test.go delete mode 100644 src/pkg/strings/reader.go delete mode 100644 src/pkg/strings/reader_test.go delete mode 100644 src/pkg/strings/replace.go delete mode 100644 src/pkg/strings/replace_test.go delete mode 100644 src/pkg/strings/search.go delete mode 100644 src/pkg/strings/search_test.go delete mode 100644 src/pkg/strings/strings.go delete mode 100644 src/pkg/strings/strings.s delete mode 100644 src/pkg/strings/strings_decl.go delete mode 100644 src/pkg/strings/strings_test.go delete mode 100644 src/pkg/sync/atomic/64bit_arm.go delete mode 100644 src/pkg/sync/atomic/asm_386.s delete mode 100644 src/pkg/sync/atomic/asm_amd64.s delete mode 100644 src/pkg/sync/atomic/asm_amd64p32.s delete mode 100644 src/pkg/sync/atomic/asm_arm.s delete mode 100644 src/pkg/sync/atomic/asm_freebsd_arm.s delete mode 100644 src/pkg/sync/atomic/asm_linux_arm.s delete mode 100644 src/pkg/sync/atomic/asm_netbsd_arm.s delete mode 100644 src/pkg/sync/atomic/atomic_linux_arm_test.go delete mode 100644 src/pkg/sync/atomic/atomic_test.go delete mode 100644 src/pkg/sync/atomic/doc.go delete mode 100644 src/pkg/sync/atomic/export_linux_arm_test.go delete mode 100644 src/pkg/sync/atomic/race.go delete mode 100644 src/pkg/sync/cond.go delete mode 100644 src/pkg/sync/cond_test.go delete mode 100644 src/pkg/sync/example_test.go delete mode 100644 src/pkg/sync/export_test.go delete mode 100644 src/pkg/sync/mutex.go delete mode 100644 src/pkg/sync/mutex_test.go delete mode 100644 src/pkg/sync/once.go delete mode 100644 src/pkg/sync/once_test.go delete mode 100644 src/pkg/sync/pool.go delete mode 100644 src/pkg/sync/pool_test.go delete mode 100644 src/pkg/sync/race.go delete mode 100644 src/pkg/sync/race0.go delete mode 100644 src/pkg/sync/runtime.go delete mode 100644 src/pkg/sync/runtime_sema_test.go delete mode 100644 src/pkg/sync/rwmutex.go delete mode 100644 src/pkg/sync/rwmutex_test.go delete mode 100644 src/pkg/sync/waitgroup.go delete mode 100644 src/pkg/sync/waitgroup_test.go delete mode 100644 src/pkg/syscall/asm_darwin_386.s delete mode 100644 src/pkg/syscall/asm_darwin_amd64.s delete mode 100644 src/pkg/syscall/asm_dragonfly_386.s delete mode 100644 src/pkg/syscall/asm_dragonfly_amd64.s delete mode 100644 src/pkg/syscall/asm_freebsd_386.s delete mode 100644 src/pkg/syscall/asm_freebsd_amd64.s delete mode 100644 src/pkg/syscall/asm_freebsd_arm.s delete mode 100644 src/pkg/syscall/asm_linux_386.s delete mode 100644 src/pkg/syscall/asm_linux_amd64.s delete mode 100644 src/pkg/syscall/asm_linux_arm.s delete mode 100644 src/pkg/syscall/asm_nacl_386.s delete mode 100644 src/pkg/syscall/asm_nacl_amd64p32.s delete mode 100644 src/pkg/syscall/asm_netbsd_386.s delete mode 100644 src/pkg/syscall/asm_netbsd_amd64.s delete mode 100644 src/pkg/syscall/asm_netbsd_arm.s delete mode 100644 src/pkg/syscall/asm_openbsd_386.s delete mode 100644 src/pkg/syscall/asm_openbsd_amd64.s delete mode 100644 src/pkg/syscall/asm_plan9_386.s delete mode 100644 src/pkg/syscall/asm_plan9_amd64.s delete mode 100644 src/pkg/syscall/asm_solaris_amd64.s delete mode 100644 src/pkg/syscall/asm_windows_386.s delete mode 100644 src/pkg/syscall/asm_windows_amd64.s delete mode 100644 src/pkg/syscall/bpf_bsd.go delete mode 100644 src/pkg/syscall/creds_test.go delete mode 100644 src/pkg/syscall/dir_plan9.go delete mode 100644 src/pkg/syscall/dll_windows.go delete mode 100644 src/pkg/syscall/env_plan9.go delete mode 100644 src/pkg/syscall/env_unix.go delete mode 100644 src/pkg/syscall/env_windows.go delete mode 100644 src/pkg/syscall/exec_bsd.go delete mode 100644 src/pkg/syscall/exec_linux.go delete mode 100644 src/pkg/syscall/exec_plan9.go delete mode 100644 src/pkg/syscall/exec_solaris.go delete mode 100644 src/pkg/syscall/exec_unix.go delete mode 100644 src/pkg/syscall/exec_windows.go delete mode 100644 src/pkg/syscall/fd_nacl.go delete mode 100644 src/pkg/syscall/flock.go delete mode 100644 src/pkg/syscall/flock_linux_32bit.go delete mode 100644 src/pkg/syscall/fs_nacl.go delete mode 100644 src/pkg/syscall/lsf_linux.go delete mode 100755 src/pkg/syscall/mkall.sh delete mode 100644 src/pkg/syscall/mkall_windows.bat delete mode 100755 src/pkg/syscall/mkerrors.sh delete mode 100755 src/pkg/syscall/mksyscall.pl delete mode 100755 src/pkg/syscall/mksyscall_solaris.pl delete mode 100644 src/pkg/syscall/mksyscall_windows.go delete mode 100755 src/pkg/syscall/mksysctl_openbsd.pl delete mode 100755 src/pkg/syscall/mksysnum_darwin.pl delete mode 100755 src/pkg/syscall/mksysnum_dragonfly.pl delete mode 100755 src/pkg/syscall/mksysnum_freebsd.pl delete mode 100755 src/pkg/syscall/mksysnum_linux.pl delete mode 100755 src/pkg/syscall/mksysnum_netbsd.pl delete mode 100755 src/pkg/syscall/mksysnum_openbsd.pl delete mode 100755 src/pkg/syscall/mksysnum_plan9.sh delete mode 100644 src/pkg/syscall/mmap_unix_test.go delete mode 100644 src/pkg/syscall/net_nacl.go delete mode 100644 src/pkg/syscall/netlink_linux.go delete mode 100644 src/pkg/syscall/race.go delete mode 100644 src/pkg/syscall/race0.go delete mode 100644 src/pkg/syscall/route_bsd.go delete mode 100644 src/pkg/syscall/route_darwin.go delete mode 100644 src/pkg/syscall/route_dragonfly.go delete mode 100644 src/pkg/syscall/route_freebsd.go delete mode 100644 src/pkg/syscall/route_freebsd_32bit.go delete mode 100644 src/pkg/syscall/route_freebsd_64bit.go delete mode 100644 src/pkg/syscall/route_netbsd.go delete mode 100644 src/pkg/syscall/route_openbsd.go delete mode 100644 src/pkg/syscall/security_windows.go delete mode 100644 src/pkg/syscall/so_solaris.go delete mode 100644 src/pkg/syscall/sockcmsg_linux.go delete mode 100644 src/pkg/syscall/sockcmsg_unix.go delete mode 100644 src/pkg/syscall/srpc_nacl.go delete mode 100644 src/pkg/syscall/str.go delete mode 100644 src/pkg/syscall/syscall.go delete mode 100644 src/pkg/syscall/syscall_bsd.go delete mode 100644 src/pkg/syscall/syscall_bsd_test.go delete mode 100644 src/pkg/syscall/syscall_darwin.go delete mode 100644 src/pkg/syscall/syscall_darwin_386.go delete mode 100644 src/pkg/syscall/syscall_darwin_amd64.go delete mode 100644 src/pkg/syscall/syscall_dragonfly.go delete mode 100644 src/pkg/syscall/syscall_dragonfly_386.go delete mode 100644 src/pkg/syscall/syscall_dragonfly_amd64.go delete mode 100644 src/pkg/syscall/syscall_freebsd.go delete mode 100644 src/pkg/syscall/syscall_freebsd_386.go delete mode 100644 src/pkg/syscall/syscall_freebsd_amd64.go delete mode 100644 src/pkg/syscall/syscall_freebsd_arm.go delete mode 100644 src/pkg/syscall/syscall_linux.go delete mode 100644 src/pkg/syscall/syscall_linux_386.go delete mode 100644 src/pkg/syscall/syscall_linux_amd64.go delete mode 100644 src/pkg/syscall/syscall_linux_arm.go delete mode 100644 src/pkg/syscall/syscall_nacl.go delete mode 100644 src/pkg/syscall/syscall_nacl_386.go delete mode 100644 src/pkg/syscall/syscall_nacl_amd64p32.go delete mode 100644 src/pkg/syscall/syscall_netbsd.go delete mode 100644 src/pkg/syscall/syscall_netbsd_386.go delete mode 100644 src/pkg/syscall/syscall_netbsd_amd64.go delete mode 100644 src/pkg/syscall/syscall_netbsd_arm.go delete mode 100644 src/pkg/syscall/syscall_no_getwd.go delete mode 100644 src/pkg/syscall/syscall_openbsd.go delete mode 100644 src/pkg/syscall/syscall_openbsd_386.go delete mode 100644 src/pkg/syscall/syscall_openbsd_amd64.go delete mode 100644 src/pkg/syscall/syscall_plan9.go delete mode 100644 src/pkg/syscall/syscall_plan9_386.go delete mode 100644 src/pkg/syscall/syscall_plan9_amd64.go delete mode 100644 src/pkg/syscall/syscall_solaris.go delete mode 100644 src/pkg/syscall/syscall_solaris_amd64.go delete mode 100644 src/pkg/syscall/syscall_test.go delete mode 100644 src/pkg/syscall/syscall_unix.go delete mode 100644 src/pkg/syscall/syscall_unix_test.go delete mode 100644 src/pkg/syscall/syscall_windows.go delete mode 100644 src/pkg/syscall/syscall_windows_386.go delete mode 100644 src/pkg/syscall/syscall_windows_amd64.go delete mode 100644 src/pkg/syscall/syscall_windows_test.go delete mode 100644 src/pkg/syscall/tables_nacl.go delete mode 100644 src/pkg/syscall/time_nacl_386.s delete mode 100644 src/pkg/syscall/time_nacl_amd64p32.s delete mode 100644 src/pkg/syscall/types_darwin.go delete mode 100644 src/pkg/syscall/types_dragonfly.go delete mode 100644 src/pkg/syscall/types_freebsd.go delete mode 100644 src/pkg/syscall/types_linux.go delete mode 100644 src/pkg/syscall/types_netbsd.go delete mode 100644 src/pkg/syscall/types_openbsd.go delete mode 100644 src/pkg/syscall/types_plan9.c delete mode 100644 src/pkg/syscall/types_solaris.go delete mode 100644 src/pkg/syscall/unzip_nacl.go delete mode 100644 src/pkg/syscall/zerrors_darwin_386.go delete mode 100644 src/pkg/syscall/zerrors_darwin_amd64.go delete mode 100644 src/pkg/syscall/zerrors_dragonfly_386.go delete mode 100644 src/pkg/syscall/zerrors_dragonfly_amd64.go delete mode 100644 src/pkg/syscall/zerrors_freebsd_386.go delete mode 100644 src/pkg/syscall/zerrors_freebsd_amd64.go delete mode 100644 src/pkg/syscall/zerrors_freebsd_arm.go delete mode 100644 src/pkg/syscall/zerrors_linux_386.go delete mode 100644 src/pkg/syscall/zerrors_linux_amd64.go delete mode 100644 src/pkg/syscall/zerrors_linux_arm.go delete mode 100644 src/pkg/syscall/zerrors_netbsd_386.go delete mode 100644 src/pkg/syscall/zerrors_netbsd_amd64.go delete mode 100644 src/pkg/syscall/zerrors_netbsd_arm.go delete mode 100644 src/pkg/syscall/zerrors_openbsd_386.go delete mode 100644 src/pkg/syscall/zerrors_openbsd_amd64.go delete mode 100644 src/pkg/syscall/zerrors_plan9_386.go delete mode 100644 src/pkg/syscall/zerrors_plan9_amd64.go delete mode 100644 src/pkg/syscall/zerrors_solaris_amd64.go delete mode 100644 src/pkg/syscall/zerrors_windows.go delete mode 100644 src/pkg/syscall/zerrors_windows_386.go delete mode 100644 src/pkg/syscall/zerrors_windows_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_darwin_386.go delete mode 100644 src/pkg/syscall/zsyscall_darwin_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_dragonfly_386.go delete mode 100644 src/pkg/syscall/zsyscall_dragonfly_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_freebsd_386.go delete mode 100644 src/pkg/syscall/zsyscall_freebsd_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_freebsd_arm.go delete mode 100644 src/pkg/syscall/zsyscall_linux_386.go delete mode 100644 src/pkg/syscall/zsyscall_linux_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_linux_arm.go delete mode 100644 src/pkg/syscall/zsyscall_nacl_386.go delete mode 100644 src/pkg/syscall/zsyscall_nacl_amd64p32.go delete mode 100644 src/pkg/syscall/zsyscall_netbsd_386.go delete mode 100644 src/pkg/syscall/zsyscall_netbsd_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_netbsd_arm.go delete mode 100644 src/pkg/syscall/zsyscall_openbsd_386.go delete mode 100644 src/pkg/syscall/zsyscall_openbsd_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_plan9_386.go delete mode 100644 src/pkg/syscall/zsyscall_plan9_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_solaris_amd64.go delete mode 100644 src/pkg/syscall/zsyscall_windows_386.go delete mode 100644 src/pkg/syscall/zsyscall_windows_amd64.go delete mode 100644 src/pkg/syscall/zsysctl_openbsd.go delete mode 100644 src/pkg/syscall/zsysnum_darwin_386.go delete mode 100644 src/pkg/syscall/zsysnum_darwin_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_dragonfly_386.go delete mode 100644 src/pkg/syscall/zsysnum_dragonfly_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_freebsd_386.go delete mode 100644 src/pkg/syscall/zsysnum_freebsd_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_freebsd_arm.go delete mode 100644 src/pkg/syscall/zsysnum_linux_386.go delete mode 100644 src/pkg/syscall/zsysnum_linux_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_linux_arm.go delete mode 100644 src/pkg/syscall/zsysnum_netbsd_386.go delete mode 100644 src/pkg/syscall/zsysnum_netbsd_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_netbsd_arm.go delete mode 100644 src/pkg/syscall/zsysnum_openbsd_386.go delete mode 100644 src/pkg/syscall/zsysnum_openbsd_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_plan9_386.go delete mode 100644 src/pkg/syscall/zsysnum_plan9_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_solaris_amd64.go delete mode 100644 src/pkg/syscall/zsysnum_windows_386.go delete mode 100644 src/pkg/syscall/zsysnum_windows_amd64.go delete mode 100644 src/pkg/syscall/ztypes_darwin_386.go delete mode 100644 src/pkg/syscall/ztypes_darwin_amd64.go delete mode 100644 src/pkg/syscall/ztypes_dragonfly_386.go delete mode 100644 src/pkg/syscall/ztypes_dragonfly_amd64.go delete mode 100644 src/pkg/syscall/ztypes_freebsd_386.go delete mode 100644 src/pkg/syscall/ztypes_freebsd_amd64.go delete mode 100644 src/pkg/syscall/ztypes_freebsd_arm.go delete mode 100644 src/pkg/syscall/ztypes_linux_386.go delete mode 100644 src/pkg/syscall/ztypes_linux_amd64.go delete mode 100644 src/pkg/syscall/ztypes_linux_arm.go delete mode 100644 src/pkg/syscall/ztypes_netbsd_386.go delete mode 100644 src/pkg/syscall/ztypes_netbsd_amd64.go delete mode 100644 src/pkg/syscall/ztypes_netbsd_arm.go delete mode 100644 src/pkg/syscall/ztypes_openbsd_386.go delete mode 100644 src/pkg/syscall/ztypes_openbsd_amd64.go delete mode 100644 src/pkg/syscall/ztypes_plan9_386.go delete mode 100644 src/pkg/syscall/ztypes_plan9_amd64.go delete mode 100644 src/pkg/syscall/ztypes_solaris_amd64.go delete mode 100644 src/pkg/syscall/ztypes_windows.go delete mode 100644 src/pkg/syscall/ztypes_windows_386.go delete mode 100644 src/pkg/syscall/ztypes_windows_amd64.go delete mode 100644 src/pkg/testing/allocs.go delete mode 100644 src/pkg/testing/benchmark.go delete mode 100644 src/pkg/testing/benchmark_test.go delete mode 100644 src/pkg/testing/cover.go delete mode 100644 src/pkg/testing/example.go delete mode 100644 src/pkg/testing/export_test.go delete mode 100644 src/pkg/testing/iotest/logger.go delete mode 100644 src/pkg/testing/iotest/reader.go delete mode 100644 src/pkg/testing/iotest/writer.go delete mode 100644 src/pkg/testing/quick/quick.go delete mode 100644 src/pkg/testing/quick/quick_test.go delete mode 100644 src/pkg/testing/testing.go delete mode 100644 src/pkg/text/scanner/scanner.go delete mode 100644 src/pkg/text/scanner/scanner_test.go delete mode 100644 src/pkg/text/tabwriter/example_test.go delete mode 100644 src/pkg/text/tabwriter/tabwriter.go delete mode 100644 src/pkg/text/tabwriter/tabwriter_test.go delete mode 100644 src/pkg/text/template/doc.go delete mode 100644 src/pkg/text/template/example_test.go delete mode 100644 src/pkg/text/template/examplefiles_test.go delete mode 100644 src/pkg/text/template/examplefunc_test.go delete mode 100644 src/pkg/text/template/exec.go delete mode 100644 src/pkg/text/template/exec_test.go delete mode 100644 src/pkg/text/template/funcs.go delete mode 100644 src/pkg/text/template/helper.go delete mode 100644 src/pkg/text/template/multi_test.go delete mode 100644 src/pkg/text/template/parse/lex.go delete mode 100644 src/pkg/text/template/parse/lex_test.go delete mode 100644 src/pkg/text/template/parse/node.go delete mode 100644 src/pkg/text/template/parse/parse.go delete mode 100644 src/pkg/text/template/parse/parse_test.go delete mode 100644 src/pkg/text/template/template.go delete mode 100644 src/pkg/text/template/testdata/file1.tmpl delete mode 100644 src/pkg/text/template/testdata/file2.tmpl delete mode 100644 src/pkg/text/template/testdata/tmpl1.tmpl delete mode 100644 src/pkg/text/template/testdata/tmpl2.tmpl delete mode 100644 src/pkg/time/Makefile delete mode 100644 src/pkg/time/example_test.go delete mode 100644 src/pkg/time/export_test.go delete mode 100644 src/pkg/time/export_windows_test.go delete mode 100644 src/pkg/time/format.go delete mode 100644 src/pkg/time/format_test.go delete mode 100644 src/pkg/time/genzabbrs.go delete mode 100644 src/pkg/time/internal_test.go delete mode 100644 src/pkg/time/sleep.go delete mode 100644 src/pkg/time/sleep_test.go delete mode 100644 src/pkg/time/sys_plan9.go delete mode 100644 src/pkg/time/sys_unix.go delete mode 100644 src/pkg/time/sys_windows.go delete mode 100644 src/pkg/time/tick.go delete mode 100644 src/pkg/time/tick_test.go delete mode 100644 src/pkg/time/time.go delete mode 100644 src/pkg/time/time_test.go delete mode 100644 src/pkg/time/zoneinfo.go delete mode 100644 src/pkg/time/zoneinfo_abbrs_windows.go delete mode 100644 src/pkg/time/zoneinfo_plan9.go delete mode 100644 src/pkg/time/zoneinfo_read.go delete mode 100644 src/pkg/time/zoneinfo_test.go delete mode 100644 src/pkg/time/zoneinfo_unix.go delete mode 100644 src/pkg/time/zoneinfo_windows.go delete mode 100644 src/pkg/time/zoneinfo_windows_test.go delete mode 100644 src/pkg/unicode/Makefile delete mode 100644 src/pkg/unicode/casetables.go delete mode 100644 src/pkg/unicode/digit.go delete mode 100644 src/pkg/unicode/digit_test.go delete mode 100644 src/pkg/unicode/graphic.go delete mode 100644 src/pkg/unicode/graphic_test.go delete mode 100644 src/pkg/unicode/letter.go delete mode 100644 src/pkg/unicode/letter_test.go delete mode 100644 src/pkg/unicode/maketables.go delete mode 100644 src/pkg/unicode/script_test.go delete mode 100644 src/pkg/unicode/tables.go delete mode 100644 src/pkg/unicode/utf16/export_test.go delete mode 100644 src/pkg/unicode/utf16/utf16.go delete mode 100644 src/pkg/unicode/utf16/utf16_test.go delete mode 100644 src/pkg/unicode/utf8/example_test.go delete mode 100644 src/pkg/unicode/utf8/utf8.go delete mode 100644 src/pkg/unicode/utf8/utf8_test.go delete mode 100644 src/pkg/unsafe/unsafe.go create mode 100644 src/reflect/all_test.go create mode 100644 src/reflect/asm_386.s create mode 100644 src/reflect/asm_amd64.s create mode 100644 src/reflect/asm_amd64p32.s create mode 100644 src/reflect/asm_arm.s create mode 100644 src/reflect/deepequal.go create mode 100644 src/reflect/example_test.go create mode 100644 src/reflect/export_test.go create mode 100644 src/reflect/makefunc.go create mode 100644 src/reflect/set_test.go create mode 100644 src/reflect/tostring_test.go create mode 100644 src/reflect/type.go create mode 100644 src/reflect/value.go create mode 100644 src/regexp/all_test.go create mode 100644 src/regexp/example_test.go create mode 100644 src/regexp/exec.go create mode 100644 src/regexp/exec2_test.go create mode 100644 src/regexp/exec_test.go create mode 100644 src/regexp/find_test.go create mode 100644 src/regexp/onepass.go create mode 100644 src/regexp/onepass_test.go create mode 100644 src/regexp/regexp.go create mode 100644 src/regexp/syntax/compile.go create mode 100644 src/regexp/syntax/doc.go create mode 100755 src/regexp/syntax/make_perl_groups.pl create mode 100644 src/regexp/syntax/parse.go create mode 100644 src/regexp/syntax/parse_test.go create mode 100644 src/regexp/syntax/perl_groups.go create mode 100644 src/regexp/syntax/prog.go create mode 100644 src/regexp/syntax/prog_test.go create mode 100644 src/regexp/syntax/regexp.go create mode 100644 src/regexp/syntax/simplify.go create mode 100644 src/regexp/syntax/simplify_test.go create mode 100644 src/regexp/testdata/README create mode 100644 src/regexp/testdata/basic.dat create mode 100644 src/regexp/testdata/nullsubexpr.dat create mode 100644 src/regexp/testdata/re2-exhaustive.txt.bz2 create mode 100644 src/regexp/testdata/re2-search.txt create mode 100644 src/regexp/testdata/repetition.dat create mode 100644 src/regexp/testdata/testregex.c create mode 100644 src/runtime/Makefile create mode 100644 src/runtime/alg.go create mode 100644 src/runtime/append_test.go create mode 100644 src/runtime/arch_386.go create mode 100644 src/runtime/arch_386.h create mode 100644 src/runtime/arch_amd64.go create mode 100644 src/runtime/arch_amd64.h create mode 100644 src/runtime/arch_amd64p32.go create mode 100644 src/runtime/arch_amd64p32.h create mode 100644 src/runtime/arch_arm.go create mode 100644 src/runtime/arch_arm.h create mode 100644 src/runtime/asm.s create mode 100644 src/runtime/asm_386.s create mode 100644 src/runtime/asm_amd64.s create mode 100644 src/runtime/asm_amd64p32.s create mode 100644 src/runtime/asm_arm.s create mode 100644 src/runtime/atomic.go create mode 100644 src/runtime/atomic_386.c create mode 100644 src/runtime/atomic_amd64x.c create mode 100644 src/runtime/atomic_arm.go create mode 100644 src/runtime/cgo/asm_386.s create mode 100644 src/runtime/cgo/asm_amd64.s create mode 100644 src/runtime/cgo/asm_arm.s create mode 100644 src/runtime/cgo/asm_nacl_amd64p32.s create mode 100644 src/runtime/cgo/callbacks.c create mode 100644 src/runtime/cgo/cgo.go create mode 100644 src/runtime/cgo/dragonfly.c create mode 100644 src/runtime/cgo/freebsd.c create mode 100644 src/runtime/cgo/gcc_386.S create mode 100644 src/runtime/cgo/gcc_amd64.S create mode 100644 src/runtime/cgo/gcc_android.c create mode 100644 src/runtime/cgo/gcc_android_arm.c create mode 100644 src/runtime/cgo/gcc_arm.S create mode 100644 src/runtime/cgo/gcc_darwin_386.c create mode 100644 src/runtime/cgo/gcc_darwin_amd64.c create mode 100644 src/runtime/cgo/gcc_dragonfly_386.c create mode 100644 src/runtime/cgo/gcc_dragonfly_amd64.c create mode 100644 src/runtime/cgo/gcc_fatalf.c create mode 100644 src/runtime/cgo/gcc_freebsd_386.c create mode 100644 src/runtime/cgo/gcc_freebsd_amd64.c create mode 100644 src/runtime/cgo/gcc_freebsd_arm.c create mode 100644 src/runtime/cgo/gcc_linux_386.c create mode 100644 src/runtime/cgo/gcc_linux_amd64.c create mode 100644 src/runtime/cgo/gcc_linux_arm.c create mode 100644 src/runtime/cgo/gcc_netbsd_386.c create mode 100644 src/runtime/cgo/gcc_netbsd_amd64.c create mode 100644 src/runtime/cgo/gcc_netbsd_arm.c create mode 100644 src/runtime/cgo/gcc_openbsd_386.c create mode 100644 src/runtime/cgo/gcc_openbsd_amd64.c create mode 100644 src/runtime/cgo/gcc_setenv.c create mode 100644 src/runtime/cgo/gcc_util.c create mode 100644 src/runtime/cgo/gcc_windows_386.c create mode 100644 src/runtime/cgo/gcc_windows_amd64.c create mode 100644 src/runtime/cgo/iscgo.c create mode 100644 src/runtime/cgo/libcgo.h create mode 100644 src/runtime/cgo/netbsd.c create mode 100644 src/runtime/cgo/openbsd.c create mode 100644 src/runtime/cgo/setenv.c create mode 100644 src/runtime/cgocall.go create mode 100644 src/runtime/cgocall.h create mode 100644 src/runtime/cgocallback.go create mode 100644 src/runtime/chan.go create mode 100644 src/runtime/chan.h create mode 100644 src/runtime/chan_test.go create mode 100644 src/runtime/closure_test.go create mode 100644 src/runtime/compiler.go create mode 100644 src/runtime/complex.go create mode 100644 src/runtime/complex_test.go create mode 100644 src/runtime/cpuprof.go create mode 100644 src/runtime/crash_cgo_test.go create mode 100644 src/runtime/crash_test.go create mode 100644 src/runtime/debug.go create mode 100644 src/runtime/debug/debug.s create mode 100644 src/runtime/debug/garbage.go create mode 100644 src/runtime/debug/garbage_test.go create mode 100644 src/runtime/debug/heapdump_test.go create mode 100644 src/runtime/debug/stack.go create mode 100644 src/runtime/debug/stack_test.go create mode 100644 src/runtime/debug/stubs.go create mode 100644 src/runtime/debug/stubs.s create mode 100644 src/runtime/defs.c create mode 100644 src/runtime/defs1_linux.go create mode 100644 src/runtime/defs2_linux.go create mode 100644 src/runtime/defs_android_arm.h create mode 100644 src/runtime/defs_arm_linux.go create mode 100644 src/runtime/defs_darwin.go create mode 100644 src/runtime/defs_darwin_386.h create mode 100644 src/runtime/defs_darwin_amd64.h create mode 100644 src/runtime/defs_dragonfly.go create mode 100644 src/runtime/defs_dragonfly_386.h create mode 100644 src/runtime/defs_dragonfly_amd64.h create mode 100644 src/runtime/defs_freebsd.go create mode 100644 src/runtime/defs_freebsd_386.h create mode 100644 src/runtime/defs_freebsd_amd64.h create mode 100644 src/runtime/defs_freebsd_arm.h create mode 100644 src/runtime/defs_linux.go create mode 100644 src/runtime/defs_linux_386.h create mode 100644 src/runtime/defs_linux_amd64.h create mode 100644 src/runtime/defs_linux_arm.h create mode 100644 src/runtime/defs_nacl_386.h create mode 100644 src/runtime/defs_nacl_amd64p32.h create mode 100644 src/runtime/defs_nacl_arm.h create mode 100644 src/runtime/defs_netbsd.go create mode 100644 src/runtime/defs_netbsd_386.go create mode 100644 src/runtime/defs_netbsd_386.h create mode 100644 src/runtime/defs_netbsd_amd64.go create mode 100644 src/runtime/defs_netbsd_amd64.h create mode 100644 src/runtime/defs_netbsd_arm.go create mode 100644 src/runtime/defs_netbsd_arm.h create mode 100644 src/runtime/defs_openbsd.go create mode 100644 src/runtime/defs_openbsd_386.h create mode 100644 src/runtime/defs_openbsd_amd64.h create mode 100644 src/runtime/defs_plan9_386.h create mode 100644 src/runtime/defs_plan9_amd64.h create mode 100644 src/runtime/defs_solaris.go create mode 100644 src/runtime/defs_solaris_amd64.go create mode 100644 src/runtime/defs_solaris_amd64.h create mode 100644 src/runtime/defs_windows.go create mode 100644 src/runtime/defs_windows_386.h create mode 100644 src/runtime/defs_windows_amd64.h create mode 100644 src/runtime/env_plan9.go create mode 100644 src/runtime/env_posix.go create mode 100644 src/runtime/error.go create mode 100644 src/runtime/export_futex_test.go create mode 100644 src/runtime/export_test.go create mode 100644 src/runtime/extern.go create mode 100644 src/runtime/float.c create mode 100644 src/runtime/funcdata.h create mode 100644 src/runtime/futex_test.go create mode 100644 src/runtime/gc_test.go create mode 100644 src/runtime/gcinfo_test.go create mode 100644 src/runtime/hash_test.go create mode 100644 src/runtime/hashmap.go create mode 100644 src/runtime/hashmap_fast.go create mode 100644 src/runtime/heapdump.c create mode 100644 src/runtime/iface.go create mode 100644 src/runtime/iface_test.go create mode 100644 src/runtime/lfstack.c create mode 100644 src/runtime/lfstack_test.go create mode 100644 src/runtime/lock_futex.go create mode 100644 src/runtime/lock_sema.go create mode 100644 src/runtime/malloc.c create mode 100644 src/runtime/malloc.go create mode 100644 src/runtime/malloc.h create mode 100644 src/runtime/malloc_test.go create mode 100644 src/runtime/map_test.go create mode 100644 src/runtime/mapspeed_test.go create mode 100644 src/runtime/mcache.c create mode 100644 src/runtime/mcentral.c create mode 100644 src/runtime/mem.go create mode 100644 src/runtime/mem_darwin.c create mode 100644 src/runtime/mem_dragonfly.c create mode 100644 src/runtime/mem_freebsd.c create mode 100644 src/runtime/mem_linux.c create mode 100644 src/runtime/mem_nacl.c create mode 100644 src/runtime/mem_netbsd.c create mode 100644 src/runtime/mem_openbsd.c create mode 100644 src/runtime/mem_plan9.c create mode 100644 src/runtime/mem_solaris.c create mode 100644 src/runtime/mem_windows.c create mode 100644 src/runtime/memclr_386.s create mode 100644 src/runtime/memclr_amd64.s create mode 100644 src/runtime/memclr_arm.s create mode 100644 src/runtime/memclr_plan9_386.s create mode 100644 src/runtime/memclr_plan9_amd64.s create mode 100644 src/runtime/memmove_386.s create mode 100644 src/runtime/memmove_amd64.s create mode 100644 src/runtime/memmove_arm.s create mode 100644 src/runtime/memmove_linux_amd64_test.go create mode 100644 src/runtime/memmove_nacl_amd64p32.s create mode 100644 src/runtime/memmove_plan9_386.s create mode 100644 src/runtime/memmove_plan9_amd64.s create mode 100644 src/runtime/memmove_test.go create mode 100644 src/runtime/mfinal_test.go create mode 100644 src/runtime/mfixalloc.c create mode 100644 src/runtime/mgc0.c create mode 100644 src/runtime/mgc0.go create mode 100644 src/runtime/mgc0.h create mode 100644 src/runtime/mheap.c create mode 100644 src/runtime/mknacl.sh create mode 100644 src/runtime/mprof.go create mode 100644 src/runtime/msize.c create mode 100644 src/runtime/netpoll.go create mode 100644 src/runtime/netpoll_epoll.go create mode 100644 src/runtime/netpoll_kqueue.go create mode 100644 src/runtime/netpoll_nacl.go create mode 100644 src/runtime/netpoll_solaris.c create mode 100644 src/runtime/netpoll_stub.c create mode 100644 src/runtime/netpoll_windows.c create mode 100644 src/runtime/noasm_arm.go create mode 100644 src/runtime/norace_test.go create mode 100644 src/runtime/os_android.c create mode 100644 src/runtime/os_android.h create mode 100644 src/runtime/os_darwin.c create mode 100644 src/runtime/os_darwin.go create mode 100644 src/runtime/os_darwin.h create mode 100644 src/runtime/os_dragonfly.c create mode 100644 src/runtime/os_dragonfly.go create mode 100644 src/runtime/os_dragonfly.h create mode 100644 src/runtime/os_freebsd.c create mode 100644 src/runtime/os_freebsd.go create mode 100644 src/runtime/os_freebsd.h create mode 100644 src/runtime/os_freebsd_arm.c create mode 100644 src/runtime/os_linux.c create mode 100644 src/runtime/os_linux.go create mode 100644 src/runtime/os_linux.h create mode 100644 src/runtime/os_linux_386.c create mode 100644 src/runtime/os_linux_arm.c create mode 100644 src/runtime/os_nacl.c create mode 100644 src/runtime/os_nacl.go create mode 100644 src/runtime/os_nacl.h create mode 100644 src/runtime/os_nacl_arm.c create mode 100644 src/runtime/os_netbsd.c create mode 100644 src/runtime/os_netbsd.go create mode 100644 src/runtime/os_netbsd.h create mode 100644 src/runtime/os_netbsd_386.c create mode 100644 src/runtime/os_netbsd_amd64.c create mode 100644 src/runtime/os_netbsd_arm.c create mode 100644 src/runtime/os_openbsd.c create mode 100644 src/runtime/os_openbsd.go create mode 100644 src/runtime/os_openbsd.h create mode 100644 src/runtime/os_plan9.c create mode 100644 src/runtime/os_plan9.go create mode 100644 src/runtime/os_plan9.h create mode 100644 src/runtime/os_plan9_386.c create mode 100644 src/runtime/os_plan9_amd64.c create mode 100644 src/runtime/os_solaris.c create mode 100644 src/runtime/os_solaris.go create mode 100644 src/runtime/os_solaris.h create mode 100644 src/runtime/os_windows.c create mode 100644 src/runtime/os_windows.go create mode 100644 src/runtime/os_windows.h create mode 100644 src/runtime/os_windows_386.c create mode 100644 src/runtime/os_windows_386.go create mode 100644 src/runtime/os_windows_amd64.c create mode 100644 src/runtime/os_windows_amd64.go create mode 100644 src/runtime/panic.c create mode 100644 src/runtime/panic.go create mode 100644 src/runtime/parfor.c create mode 100644 src/runtime/parfor_test.go create mode 100644 src/runtime/pprof/mprof_test.go create mode 100644 src/runtime/pprof/pprof.go create mode 100644 src/runtime/pprof/pprof_test.go create mode 100644 src/runtime/print1.go create mode 100644 src/runtime/proc.c create mode 100644 src/runtime/proc.go create mode 100644 src/runtime/proc_test.go create mode 100644 src/runtime/race.c create mode 100644 src/runtime/race.go create mode 100644 src/runtime/race.h create mode 100644 src/runtime/race/README create mode 100644 src/runtime/race/doc.go create mode 100644 src/runtime/race/output_test.go create mode 100644 src/runtime/race/race.go create mode 100644 src/runtime/race/race_darwin_amd64.syso create mode 100644 src/runtime/race/race_freebsd_amd64.syso create mode 100644 src/runtime/race/race_linux_amd64.syso create mode 100644 src/runtime/race/race_test.go create mode 100644 src/runtime/race/race_unix_test.go create mode 100644 src/runtime/race/race_windows_amd64.syso create mode 100644 src/runtime/race/testdata/atomic_test.go create mode 100644 src/runtime/race/testdata/cgo_test.go create mode 100644 src/runtime/race/testdata/cgo_test_main.go create mode 100644 src/runtime/race/testdata/chan_test.go create mode 100644 src/runtime/race/testdata/comp_test.go create mode 100644 src/runtime/race/testdata/finalizer_test.go create mode 100644 src/runtime/race/testdata/io_test.go create mode 100644 src/runtime/race/testdata/map_test.go create mode 100644 src/runtime/race/testdata/mop_test.go create mode 100644 src/runtime/race/testdata/mutex_test.go create mode 100644 src/runtime/race/testdata/regression_test.go create mode 100644 src/runtime/race/testdata/rwmutex_test.go create mode 100644 src/runtime/race/testdata/select_test.go create mode 100644 src/runtime/race/testdata/slice_test.go create mode 100644 src/runtime/race/testdata/sync_test.go create mode 100644 src/runtime/race/testdata/waitgroup_test.go create mode 100644 src/runtime/race0.go create mode 100644 src/runtime/race_amd64.s create mode 100644 src/runtime/rdebug.go create mode 100644 src/runtime/rt0_android_arm.s create mode 100644 src/runtime/rt0_darwin_386.s create mode 100644 src/runtime/rt0_darwin_amd64.s create mode 100644 src/runtime/rt0_dragonfly_386.s create mode 100644 src/runtime/rt0_dragonfly_amd64.s create mode 100644 src/runtime/rt0_freebsd_386.s create mode 100644 src/runtime/rt0_freebsd_amd64.s create mode 100644 src/runtime/rt0_freebsd_arm.s create mode 100644 src/runtime/rt0_linux_386.s create mode 100644 src/runtime/rt0_linux_amd64.s create mode 100644 src/runtime/rt0_linux_arm.s create mode 100644 src/runtime/rt0_nacl_386.s create mode 100644 src/runtime/rt0_nacl_amd64p32.s create mode 100644 src/runtime/rt0_nacl_arm.s create mode 100644 src/runtime/rt0_netbsd_386.s create mode 100644 src/runtime/rt0_netbsd_amd64.s create mode 100644 src/runtime/rt0_netbsd_arm.s create mode 100644 src/runtime/rt0_openbsd_386.s create mode 100644 src/runtime/rt0_openbsd_amd64.s create mode 100644 src/runtime/rt0_plan9_386.s create mode 100644 src/runtime/rt0_plan9_amd64.s create mode 100644 src/runtime/rt0_solaris_amd64.s create mode 100644 src/runtime/rt0_windows_386.s create mode 100644 src/runtime/rt0_windows_amd64.s create mode 100644 src/runtime/rune.go create mode 100644 src/runtime/runtime-gdb.py create mode 100644 src/runtime/runtime.c create mode 100644 src/runtime/runtime.go create mode 100644 src/runtime/runtime.h create mode 100644 src/runtime/runtime_linux_test.go create mode 100644 src/runtime/runtime_test.go create mode 100644 src/runtime/runtime_unix_test.go create mode 100644 src/runtime/select.go create mode 100644 src/runtime/sema.go create mode 100644 src/runtime/signal.c create mode 100644 src/runtime/signal_386.c create mode 100644 src/runtime/signal_amd64x.c create mode 100644 src/runtime/signal_android_386.h create mode 100644 src/runtime/signal_android_arm.h create mode 100644 src/runtime/signal_arm.c create mode 100644 src/runtime/signal_darwin_386.h create mode 100644 src/runtime/signal_darwin_amd64.h create mode 100644 src/runtime/signal_dragonfly_386.h create mode 100644 src/runtime/signal_dragonfly_amd64.h create mode 100644 src/runtime/signal_freebsd_386.h create mode 100644 src/runtime/signal_freebsd_amd64.h create mode 100644 src/runtime/signal_freebsd_arm.h create mode 100644 src/runtime/signal_linux_386.h create mode 100644 src/runtime/signal_linux_amd64.h create mode 100644 src/runtime/signal_linux_arm.h create mode 100644 src/runtime/signal_nacl_386.h create mode 100644 src/runtime/signal_nacl_amd64p32.h create mode 100644 src/runtime/signal_nacl_arm.h create mode 100644 src/runtime/signal_netbsd_386.h create mode 100644 src/runtime/signal_netbsd_amd64.h create mode 100644 src/runtime/signal_netbsd_arm.h create mode 100644 src/runtime/signal_openbsd_386.h create mode 100644 src/runtime/signal_openbsd_amd64.h create mode 100644 src/runtime/signal_solaris_amd64.h create mode 100644 src/runtime/signal_unix.c create mode 100644 src/runtime/signal_unix.go create mode 100644 src/runtime/signal_unix.h create mode 100644 src/runtime/signals_android.h create mode 100644 src/runtime/signals_darwin.h create mode 100644 src/runtime/signals_dragonfly.h create mode 100644 src/runtime/signals_freebsd.h create mode 100644 src/runtime/signals_linux.h create mode 100644 src/runtime/signals_nacl.h create mode 100644 src/runtime/signals_netbsd.h create mode 100644 src/runtime/signals_openbsd.h create mode 100644 src/runtime/signals_plan9.h create mode 100644 src/runtime/signals_solaris.h create mode 100644 src/runtime/signals_windows.h create mode 100644 src/runtime/sigpanic_unix.go create mode 100644 src/runtime/sigqueue.go create mode 100644 src/runtime/slice.go create mode 100644 src/runtime/softfloat64.go create mode 100644 src/runtime/softfloat64_test.go create mode 100644 src/runtime/softfloat_arm.c create mode 100644 src/runtime/sqrt.go create mode 100644 src/runtime/stack.c create mode 100644 src/runtime/stack.go create mode 100644 src/runtime/stack.h create mode 100644 src/runtime/stack_test.go create mode 100644 src/runtime/string.c create mode 100644 src/runtime/string.go create mode 100644 src/runtime/string_test.go create mode 100644 src/runtime/stubs.go create mode 100644 src/runtime/symtab.go create mode 100644 src/runtime/symtab_test.go create mode 100644 src/runtime/sys_arm.c create mode 100644 src/runtime/sys_darwin_386.s create mode 100644 src/runtime/sys_darwin_amd64.s create mode 100644 src/runtime/sys_dragonfly_386.s create mode 100644 src/runtime/sys_dragonfly_amd64.s create mode 100644 src/runtime/sys_freebsd_386.s create mode 100644 src/runtime/sys_freebsd_amd64.s create mode 100644 src/runtime/sys_freebsd_arm.s create mode 100644 src/runtime/sys_linux_386.s create mode 100644 src/runtime/sys_linux_amd64.s create mode 100644 src/runtime/sys_linux_arm.s create mode 100644 src/runtime/sys_nacl_386.s create mode 100644 src/runtime/sys_nacl_amd64p32.s create mode 100644 src/runtime/sys_nacl_arm.s create mode 100644 src/runtime/sys_netbsd_386.s create mode 100644 src/runtime/sys_netbsd_amd64.s create mode 100644 src/runtime/sys_netbsd_arm.s create mode 100644 src/runtime/sys_openbsd_386.s create mode 100644 src/runtime/sys_openbsd_amd64.s create mode 100644 src/runtime/sys_plan9_386.s create mode 100644 src/runtime/sys_plan9_amd64.s create mode 100644 src/runtime/sys_solaris_amd64.s create mode 100644 src/runtime/sys_windows_386.s create mode 100644 src/runtime/sys_windows_amd64.s create mode 100644 src/runtime/sys_x86.c create mode 100644 src/runtime/syscall_nacl.h create mode 100644 src/runtime/syscall_solaris.c create mode 100644 src/runtime/syscall_solaris.go create mode 100644 src/runtime/syscall_windows.go create mode 100644 src/runtime/syscall_windows_test.go create mode 100644 src/runtime/thunk.s create mode 100644 src/runtime/thunk_solaris_amd64.s create mode 100644 src/runtime/thunk_windows.s create mode 100644 src/runtime/time.go create mode 100644 src/runtime/tls_arm.s create mode 100644 src/runtime/traceback.go create mode 100644 src/runtime/type.h create mode 100644 src/runtime/typekind.go create mode 100644 src/runtime/typekind.h create mode 100644 src/runtime/vdso_linux_amd64.c create mode 100644 src/runtime/vlop_386.s create mode 100644 src/runtime/vlop_arm.s create mode 100644 src/runtime/vlop_arm_test.go create mode 100644 src/runtime/vlrt.c create mode 100644 src/runtime/vlrt.go create mode 100644 src/sort/example_interface_test.go create mode 100644 src/sort/example_keys_test.go create mode 100644 src/sort/example_multi_test.go create mode 100644 src/sort/example_test.go create mode 100644 src/sort/example_wrapper_test.go create mode 100644 src/sort/export_test.go create mode 100644 src/sort/search.go create mode 100644 src/sort/search_test.go create mode 100644 src/sort/sort.go create mode 100644 src/sort/sort_test.go create mode 100644 src/strconv/atob.go create mode 100644 src/strconv/atob_test.go create mode 100644 src/strconv/atof.go create mode 100644 src/strconv/atof_test.go create mode 100644 src/strconv/atoi.go create mode 100644 src/strconv/atoi_test.go create mode 100644 src/strconv/decimal.go create mode 100644 src/strconv/decimal_test.go create mode 100644 src/strconv/extfloat.go create mode 100644 src/strconv/fp_test.go create mode 100644 src/strconv/ftoa.go create mode 100644 src/strconv/ftoa_test.go create mode 100644 src/strconv/internal_test.go create mode 100644 src/strconv/isprint.go create mode 100644 src/strconv/itoa.go create mode 100644 src/strconv/itoa_test.go create mode 100644 src/strconv/makeisprint.go create mode 100644 src/strconv/quote.go create mode 100644 src/strconv/quote_example_test.go create mode 100644 src/strconv/quote_test.go create mode 100644 src/strconv/strconv_test.go create mode 100644 src/strconv/testdata/testfp.txt create mode 100644 src/strings/example_test.go create mode 100644 src/strings/export_test.go create mode 100644 src/strings/reader.go create mode 100644 src/strings/reader_test.go create mode 100644 src/strings/replace.go create mode 100644 src/strings/replace_test.go create mode 100644 src/strings/search.go create mode 100644 src/strings/search_test.go create mode 100644 src/strings/strings.go create mode 100644 src/strings/strings.s create mode 100644 src/strings/strings_decl.go create mode 100644 src/strings/strings_test.go create mode 100644 src/sync/atomic/64bit_arm.go create mode 100644 src/sync/atomic/asm_386.s create mode 100644 src/sync/atomic/asm_amd64.s create mode 100644 src/sync/atomic/asm_amd64p32.s create mode 100644 src/sync/atomic/asm_arm.s create mode 100644 src/sync/atomic/asm_freebsd_arm.s create mode 100644 src/sync/atomic/asm_linux_arm.s create mode 100644 src/sync/atomic/asm_nacl_arm.s create mode 100644 src/sync/atomic/asm_netbsd_arm.s create mode 100644 src/sync/atomic/atomic_linux_arm_test.go create mode 100644 src/sync/atomic/atomic_test.go create mode 100644 src/sync/atomic/doc.go create mode 100644 src/sync/atomic/export_linux_arm_test.go create mode 100644 src/sync/atomic/race.s create mode 100644 src/sync/atomic/value.go create mode 100644 src/sync/atomic/value_test.go create mode 100644 src/sync/cond.go create mode 100644 src/sync/cond_test.go create mode 100644 src/sync/example_test.go create mode 100644 src/sync/export_test.go create mode 100644 src/sync/mutex.go create mode 100644 src/sync/mutex_test.go create mode 100644 src/sync/once.go create mode 100644 src/sync/once_test.go create mode 100644 src/sync/pool.go create mode 100644 src/sync/pool_test.go create mode 100644 src/sync/race.go create mode 100644 src/sync/race0.go create mode 100644 src/sync/runtime.go create mode 100644 src/sync/runtime_sema_test.go create mode 100644 src/sync/rwmutex.go create mode 100644 src/sync/rwmutex_test.go create mode 100644 src/sync/waitgroup.go create mode 100644 src/sync/waitgroup_test.go create mode 100644 src/syscall/asm.s create mode 100644 src/syscall/asm_darwin_386.s create mode 100644 src/syscall/asm_darwin_amd64.s create mode 100644 src/syscall/asm_dragonfly_386.s create mode 100644 src/syscall/asm_dragonfly_amd64.s create mode 100644 src/syscall/asm_freebsd_386.s create mode 100644 src/syscall/asm_freebsd_amd64.s create mode 100644 src/syscall/asm_freebsd_arm.s create mode 100644 src/syscall/asm_linux_386.s create mode 100644 src/syscall/asm_linux_amd64.s create mode 100644 src/syscall/asm_linux_arm.s create mode 100644 src/syscall/asm_nacl_386.s create mode 100644 src/syscall/asm_nacl_amd64p32.s create mode 100644 src/syscall/asm_nacl_arm.s create mode 100644 src/syscall/asm_netbsd_386.s create mode 100644 src/syscall/asm_netbsd_amd64.s create mode 100644 src/syscall/asm_netbsd_arm.s create mode 100644 src/syscall/asm_openbsd_386.s create mode 100644 src/syscall/asm_openbsd_amd64.s create mode 100644 src/syscall/asm_plan9_386.s create mode 100644 src/syscall/asm_plan9_amd64.s create mode 100644 src/syscall/asm_solaris_amd64.s create mode 100644 src/syscall/bpf_bsd.go create mode 100644 src/syscall/creds_test.go create mode 100644 src/syscall/dir_plan9.go create mode 100644 src/syscall/dll_windows.go create mode 100644 src/syscall/env_plan9.go create mode 100644 src/syscall/env_unix.go create mode 100644 src/syscall/env_windows.go create mode 100644 src/syscall/exec_bsd.go create mode 100644 src/syscall/exec_linux.go create mode 100644 src/syscall/exec_plan9.go create mode 100644 src/syscall/exec_solaris.go create mode 100644 src/syscall/exec_unix.go create mode 100644 src/syscall/exec_windows.go create mode 100644 src/syscall/export_test.go create mode 100644 src/syscall/fd_nacl.go create mode 100644 src/syscall/flock.go create mode 100644 src/syscall/flock_linux_32bit.go create mode 100644 src/syscall/fs_nacl.go create mode 100644 src/syscall/lsf_linux.go create mode 100755 src/syscall/mkall.sh create mode 100644 src/syscall/mkall_windows.bat create mode 100755 src/syscall/mkerrors.sh create mode 100755 src/syscall/mksyscall.pl create mode 100755 src/syscall/mksyscall_solaris.pl create mode 100644 src/syscall/mksyscall_windows.go create mode 100755 src/syscall/mksysctl_openbsd.pl create mode 100755 src/syscall/mksysnum_darwin.pl create mode 100755 src/syscall/mksysnum_dragonfly.pl create mode 100755 src/syscall/mksysnum_freebsd.pl create mode 100755 src/syscall/mksysnum_linux.pl create mode 100755 src/syscall/mksysnum_netbsd.pl create mode 100755 src/syscall/mksysnum_openbsd.pl create mode 100755 src/syscall/mksysnum_plan9.sh create mode 100644 src/syscall/mmap_unix_test.go create mode 100644 src/syscall/net_nacl.go create mode 100644 src/syscall/netlink_linux.go create mode 100644 src/syscall/race.go create mode 100644 src/syscall/race0.go create mode 100644 src/syscall/route_bsd.go create mode 100644 src/syscall/route_darwin.go create mode 100644 src/syscall/route_dragonfly.go create mode 100644 src/syscall/route_freebsd.go create mode 100644 src/syscall/route_freebsd_32bit.go create mode 100644 src/syscall/route_freebsd_64bit.go create mode 100644 src/syscall/route_netbsd.go create mode 100644 src/syscall/route_openbsd.go create mode 100644 src/syscall/security_windows.go create mode 100644 src/syscall/so_solaris.go create mode 100644 src/syscall/sockcmsg_linux.go create mode 100644 src/syscall/sockcmsg_unix.go create mode 100644 src/syscall/srpc_nacl.go create mode 100644 src/syscall/str.go create mode 100644 src/syscall/syscall.go create mode 100644 src/syscall/syscall_bsd.go create mode 100644 src/syscall/syscall_bsd_test.go create mode 100644 src/syscall/syscall_darwin.go create mode 100644 src/syscall/syscall_darwin_386.go create mode 100644 src/syscall/syscall_darwin_amd64.go create mode 100644 src/syscall/syscall_dragonfly.go create mode 100644 src/syscall/syscall_dragonfly_386.go create mode 100644 src/syscall/syscall_dragonfly_amd64.go create mode 100644 src/syscall/syscall_freebsd.go create mode 100644 src/syscall/syscall_freebsd_386.go create mode 100644 src/syscall/syscall_freebsd_amd64.go create mode 100644 src/syscall/syscall_freebsd_arm.go create mode 100644 src/syscall/syscall_linux.go create mode 100644 src/syscall/syscall_linux_386.go create mode 100644 src/syscall/syscall_linux_amd64.go create mode 100644 src/syscall/syscall_linux_arm.go create mode 100644 src/syscall/syscall_nacl.go create mode 100644 src/syscall/syscall_nacl_386.go create mode 100644 src/syscall/syscall_nacl_amd64p32.go create mode 100644 src/syscall/syscall_nacl_arm.go create mode 100644 src/syscall/syscall_netbsd.go create mode 100644 src/syscall/syscall_netbsd_386.go create mode 100644 src/syscall/syscall_netbsd_amd64.go create mode 100644 src/syscall/syscall_netbsd_arm.go create mode 100644 src/syscall/syscall_no_getwd.go create mode 100644 src/syscall/syscall_openbsd.go create mode 100644 src/syscall/syscall_openbsd_386.go create mode 100644 src/syscall/syscall_openbsd_amd64.go create mode 100644 src/syscall/syscall_plan9.go create mode 100644 src/syscall/syscall_solaris.go create mode 100644 src/syscall/syscall_solaris_amd64.go create mode 100644 src/syscall/syscall_test.go create mode 100644 src/syscall/syscall_unix.go create mode 100644 src/syscall/syscall_unix_test.go create mode 100644 src/syscall/syscall_windows.go create mode 100644 src/syscall/syscall_windows_386.go create mode 100644 src/syscall/syscall_windows_amd64.go create mode 100644 src/syscall/syscall_windows_test.go create mode 100644 src/syscall/tables_nacl.go create mode 100644 src/syscall/time_nacl_386.s create mode 100644 src/syscall/time_nacl_amd64p32.s create mode 100644 src/syscall/time_nacl_arm.s create mode 100644 src/syscall/types_darwin.go create mode 100644 src/syscall/types_dragonfly.go create mode 100644 src/syscall/types_freebsd.go create mode 100644 src/syscall/types_linux.go create mode 100644 src/syscall/types_netbsd.go create mode 100644 src/syscall/types_openbsd.go create mode 100644 src/syscall/types_plan9.c create mode 100644 src/syscall/types_solaris.go create mode 100644 src/syscall/unzip_nacl.go create mode 100644 src/syscall/zerrors_darwin_386.go create mode 100644 src/syscall/zerrors_darwin_amd64.go create mode 100644 src/syscall/zerrors_dragonfly_386.go create mode 100644 src/syscall/zerrors_dragonfly_amd64.go create mode 100644 src/syscall/zerrors_freebsd_386.go create mode 100644 src/syscall/zerrors_freebsd_amd64.go create mode 100644 src/syscall/zerrors_freebsd_arm.go create mode 100644 src/syscall/zerrors_linux_386.go create mode 100644 src/syscall/zerrors_linux_amd64.go create mode 100644 src/syscall/zerrors_linux_arm.go create mode 100644 src/syscall/zerrors_netbsd_386.go create mode 100644 src/syscall/zerrors_netbsd_amd64.go create mode 100644 src/syscall/zerrors_netbsd_arm.go create mode 100644 src/syscall/zerrors_openbsd_386.go create mode 100644 src/syscall/zerrors_openbsd_amd64.go create mode 100644 src/syscall/zerrors_plan9_386.go create mode 100644 src/syscall/zerrors_plan9_amd64.go create mode 100644 src/syscall/zerrors_solaris_amd64.go create mode 100644 src/syscall/zerrors_windows.go create mode 100644 src/syscall/zerrors_windows_386.go create mode 100644 src/syscall/zerrors_windows_amd64.go create mode 100644 src/syscall/zsyscall_darwin_386.go create mode 100644 src/syscall/zsyscall_darwin_amd64.go create mode 100644 src/syscall/zsyscall_dragonfly_386.go create mode 100644 src/syscall/zsyscall_dragonfly_amd64.go create mode 100644 src/syscall/zsyscall_freebsd_386.go create mode 100644 src/syscall/zsyscall_freebsd_amd64.go create mode 100644 src/syscall/zsyscall_freebsd_arm.go create mode 100644 src/syscall/zsyscall_linux_386.go create mode 100644 src/syscall/zsyscall_linux_amd64.go create mode 100644 src/syscall/zsyscall_linux_arm.go create mode 100644 src/syscall/zsyscall_nacl_386.go create mode 100644 src/syscall/zsyscall_nacl_amd64p32.go create mode 100644 src/syscall/zsyscall_nacl_arm.go create mode 100644 src/syscall/zsyscall_netbsd_386.go create mode 100644 src/syscall/zsyscall_netbsd_amd64.go create mode 100644 src/syscall/zsyscall_netbsd_arm.go create mode 100644 src/syscall/zsyscall_openbsd_386.go create mode 100644 src/syscall/zsyscall_openbsd_amd64.go create mode 100644 src/syscall/zsyscall_plan9_386.go create mode 100644 src/syscall/zsyscall_plan9_amd64.go create mode 100644 src/syscall/zsyscall_solaris_amd64.go create mode 100644 src/syscall/zsyscall_windows.go create mode 100644 src/syscall/zsysctl_openbsd.go create mode 100644 src/syscall/zsysnum_darwin_386.go create mode 100644 src/syscall/zsysnum_darwin_amd64.go create mode 100644 src/syscall/zsysnum_dragonfly_386.go create mode 100644 src/syscall/zsysnum_dragonfly_amd64.go create mode 100644 src/syscall/zsysnum_freebsd_386.go create mode 100644 src/syscall/zsysnum_freebsd_amd64.go create mode 100644 src/syscall/zsysnum_freebsd_arm.go create mode 100644 src/syscall/zsysnum_linux_386.go create mode 100644 src/syscall/zsysnum_linux_amd64.go create mode 100644 src/syscall/zsysnum_linux_arm.go create mode 100644 src/syscall/zsysnum_netbsd_386.go create mode 100644 src/syscall/zsysnum_netbsd_amd64.go create mode 100644 src/syscall/zsysnum_netbsd_arm.go create mode 100644 src/syscall/zsysnum_openbsd_386.go create mode 100644 src/syscall/zsysnum_openbsd_amd64.go create mode 100644 src/syscall/zsysnum_plan9_386.go create mode 100644 src/syscall/zsysnum_plan9_amd64.go create mode 100644 src/syscall/zsysnum_solaris_amd64.go create mode 100644 src/syscall/zsysnum_windows_386.go create mode 100644 src/syscall/zsysnum_windows_amd64.go create mode 100644 src/syscall/ztypes_darwin_386.go create mode 100644 src/syscall/ztypes_darwin_amd64.go create mode 100644 src/syscall/ztypes_dragonfly_386.go create mode 100644 src/syscall/ztypes_dragonfly_amd64.go create mode 100644 src/syscall/ztypes_freebsd_386.go create mode 100644 src/syscall/ztypes_freebsd_amd64.go create mode 100644 src/syscall/ztypes_freebsd_arm.go create mode 100644 src/syscall/ztypes_linux_386.go create mode 100644 src/syscall/ztypes_linux_amd64.go create mode 100644 src/syscall/ztypes_linux_arm.go create mode 100644 src/syscall/ztypes_netbsd_386.go create mode 100644 src/syscall/ztypes_netbsd_amd64.go create mode 100644 src/syscall/ztypes_netbsd_arm.go create mode 100644 src/syscall/ztypes_openbsd_386.go create mode 100644 src/syscall/ztypes_openbsd_amd64.go create mode 100644 src/syscall/ztypes_plan9_386.go create mode 100644 src/syscall/ztypes_plan9_amd64.go create mode 100644 src/syscall/ztypes_solaris_amd64.go create mode 100644 src/syscall/ztypes_windows.go create mode 100644 src/syscall/ztypes_windows_386.go create mode 100644 src/syscall/ztypes_windows_amd64.go create mode 100644 src/testing/allocs.go create mode 100644 src/testing/allocs_test.go create mode 100644 src/testing/benchmark.go create mode 100644 src/testing/benchmark_test.go create mode 100644 src/testing/cover.go create mode 100644 src/testing/example.go create mode 100644 src/testing/export_test.go create mode 100644 src/testing/iotest/logger.go create mode 100644 src/testing/iotest/reader.go create mode 100644 src/testing/iotest/writer.go create mode 100644 src/testing/quick/quick.go create mode 100644 src/testing/quick/quick_test.go create mode 100644 src/testing/testing.go create mode 100644 src/testing/testing_test.go create mode 100644 src/text/scanner/scanner.go create mode 100644 src/text/scanner/scanner_test.go create mode 100644 src/text/tabwriter/example_test.go create mode 100644 src/text/tabwriter/tabwriter.go create mode 100644 src/text/tabwriter/tabwriter_test.go create mode 100644 src/text/template/doc.go create mode 100644 src/text/template/example_test.go create mode 100644 src/text/template/examplefiles_test.go create mode 100644 src/text/template/examplefunc_test.go create mode 100644 src/text/template/exec.go create mode 100644 src/text/template/exec_test.go create mode 100644 src/text/template/funcs.go create mode 100644 src/text/template/helper.go create mode 100644 src/text/template/multi_test.go create mode 100644 src/text/template/parse/lex.go create mode 100644 src/text/template/parse/lex_test.go create mode 100644 src/text/template/parse/node.go create mode 100644 src/text/template/parse/parse.go create mode 100644 src/text/template/parse/parse_test.go create mode 100644 src/text/template/template.go create mode 100644 src/text/template/testdata/file1.tmpl create mode 100644 src/text/template/testdata/file2.tmpl create mode 100644 src/text/template/testdata/tmpl1.tmpl create mode 100644 src/text/template/testdata/tmpl2.tmpl create mode 100644 src/time/example_test.go create mode 100644 src/time/export_test.go create mode 100644 src/time/export_windows_test.go create mode 100644 src/time/format.go create mode 100644 src/time/format_test.go create mode 100644 src/time/genzabbrs.go create mode 100644 src/time/internal_test.go create mode 100644 src/time/sleep.go create mode 100644 src/time/sleep_test.go create mode 100644 src/time/sys_plan9.go create mode 100644 src/time/sys_unix.go create mode 100644 src/time/sys_windows.go create mode 100644 src/time/tick.go create mode 100644 src/time/tick_test.go create mode 100644 src/time/time.go create mode 100644 src/time/time_test.go create mode 100644 src/time/zoneinfo.go create mode 100644 src/time/zoneinfo_abbrs_windows.go create mode 100644 src/time/zoneinfo_plan9.go create mode 100644 src/time/zoneinfo_read.go create mode 100644 src/time/zoneinfo_test.go create mode 100644 src/time/zoneinfo_unix.go create mode 100644 src/time/zoneinfo_windows.go create mode 100644 src/time/zoneinfo_windows_test.go create mode 100644 src/unicode/casetables.go create mode 100644 src/unicode/digit.go create mode 100644 src/unicode/digit_test.go create mode 100644 src/unicode/graphic.go create mode 100644 src/unicode/graphic_test.go create mode 100644 src/unicode/letter.go create mode 100644 src/unicode/letter_test.go create mode 100644 src/unicode/maketables.go create mode 100644 src/unicode/script_test.go create mode 100644 src/unicode/tables.go create mode 100644 src/unicode/utf16/export_test.go create mode 100644 src/unicode/utf16/utf16.go create mode 100644 src/unicode/utf16/utf16_test.go create mode 100644 src/unicode/utf8/example_test.go create mode 100644 src/unicode/utf8/utf8.go create mode 100644 src/unicode/utf8/utf8_test.go create mode 100644 src/unsafe/unsafe.go (limited to 'src') diff --git a/src/androidtest.bash b/src/androidtest.bash new file mode 100755 index 000000000..504d276c4 --- /dev/null +++ b/src/androidtest.bash @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Copyright 2014 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# For testing Android. +# The compiler runs locally, then a copy of the GOROOT is pushed to a +# target device using adb, and the tests are run there. + +set -e +ulimit -c 0 # no core files + +if [ ! -f make.bash ]; then + echo 'nacl.bash must be run from $GOROOT/src' 1>&2 + exit 1 +fi + +if [ -z $GOOS ]; then + export GOOS=android +fi +if [ "$GOOS" != "android" ]; then + echo "androidtest.bash requires GOOS=android, got GOOS=$GOOS" 1>&2 + exit 1 +fi + +export CGO_ENABLED=1 + +# Run the build for the host bootstrap, so we can build go_android_exec. +# Also lets us fail early before the (slow) adb push if the build is broken. +./make.bash +export GOROOT=$(dirname $(pwd)) +export PATH=$GOROOT/bin:$PATH +GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH go build \ + -o ../bin/go_android_${GOARCH}_exec \ + ../misc/android/go_android_exec.go + +# Push GOROOT to target device. +# +# The adb sync command will sync either the /system or /data +# directories of an android device from a similar directory +# on the host. So we fake one with symlinks to push the GOROOT +# into a subdirectory of /data. +export ANDROID_PRODUCT_OUT=/tmp/androidtest-$$ +FAKE_GOROOT=$ANDROID_PRODUCT_OUT/data/local/tmp/goroot +mkdir -p $FAKE_GOROOT +ln -s $GOROOT/src $FAKE_GOROOT/src +ln -s $GOROOT/test $FAKE_GOROOT/test +ln -s $GOROOT/lib $FAKE_GOROOT/lib +echo '# Syncing test files to android device' +time adb sync data &> /dev/null +echo '' +rm -rf "$ANDROID_PRODUCT_OUT" + +# Run standard build and tests. +./all.bash --no-clean diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go new file mode 100644 index 000000000..e363aa793 --- /dev/null +++ b/src/archive/tar/common.go @@ -0,0 +1,305 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tar implements access to tar archives. +// It aims to cover most of the variations, including those produced +// by GNU and BSD tars. +// +// References: +// http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 +// http://www.gnu.org/software/tar/manual/html_node/Standard.html +// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html +package tar + +import ( + "bytes" + "errors" + "fmt" + "os" + "path" + "time" +) + +const ( + blockSize = 512 + + // Types + TypeReg = '0' // regular file + TypeRegA = '\x00' // regular file + TypeLink = '1' // hard link + TypeSymlink = '2' // symbolic link + TypeChar = '3' // character device node + TypeBlock = '4' // block device node + TypeDir = '5' // directory + TypeFifo = '6' // fifo node + TypeCont = '7' // reserved + TypeXHeader = 'x' // extended header + TypeXGlobalHeader = 'g' // global extended header + TypeGNULongName = 'L' // Next file has a long name + TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name + TypeGNUSparse = 'S' // sparse file +) + +// A Header represents a single header in a tar archive. +// Some fields may not be populated. +type Header struct { + Name string // name of header file entry + Mode int64 // permission and mode bits + Uid int // user id of owner + Gid int // group id of owner + Size int64 // length in bytes + ModTime time.Time // modified time + Typeflag byte // type of header entry + Linkname string // target name of link + Uname string // user name of owner + Gname string // group name of owner + Devmajor int64 // major number of character or block device + Devminor int64 // minor number of character or block device + AccessTime time.Time // access time + ChangeTime time.Time // status change time + Xattrs map[string]string +} + +// File name constants from the tar spec. +const ( + fileNameSize = 100 // Maximum number of bytes in a standard tar name. + fileNamePrefixSize = 155 // Maximum number of ustar extension bytes. +) + +// FileInfo returns an os.FileInfo for the Header. +func (h *Header) FileInfo() os.FileInfo { + return headerFileInfo{h} +} + +// headerFileInfo implements os.FileInfo. +type headerFileInfo struct { + h *Header +} + +func (fi headerFileInfo) Size() int64 { return fi.h.Size } +func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } +func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime } +func (fi headerFileInfo) Sys() interface{} { return fi.h } + +// Name returns the base name of the file. +func (fi headerFileInfo) Name() string { + if fi.IsDir() { + return path.Base(path.Clean(fi.h.Name)) + } + return path.Base(fi.h.Name) +} + +// Mode returns the permission and mode bits for the headerFileInfo. +func (fi headerFileInfo) Mode() (mode os.FileMode) { + // Set file permission bits. + mode = os.FileMode(fi.h.Mode).Perm() + + // Set setuid, setgid and sticky bits. + if fi.h.Mode&c_ISUID != 0 { + // setuid + mode |= os.ModeSetuid + } + if fi.h.Mode&c_ISGID != 0 { + // setgid + mode |= os.ModeSetgid + } + if fi.h.Mode&c_ISVTX != 0 { + // sticky + mode |= os.ModeSticky + } + + // Set file mode bits. + // clear perm, setuid, setgid and sticky bits. + m := os.FileMode(fi.h.Mode) &^ 07777 + if m == c_ISDIR { + // directory + mode |= os.ModeDir + } + if m == c_ISFIFO { + // named pipe (FIFO) + mode |= os.ModeNamedPipe + } + if m == c_ISLNK { + // symbolic link + mode |= os.ModeSymlink + } + if m == c_ISBLK { + // device file + mode |= os.ModeDevice + } + if m == c_ISCHR { + // Unix character device + mode |= os.ModeDevice + mode |= os.ModeCharDevice + } + if m == c_ISSOCK { + // Unix domain socket + mode |= os.ModeSocket + } + + switch fi.h.Typeflag { + case TypeLink, TypeSymlink: + // hard link, symbolic link + mode |= os.ModeSymlink + case TypeChar: + // character device node + mode |= os.ModeDevice + mode |= os.ModeCharDevice + case TypeBlock: + // block device node + mode |= os.ModeDevice + case TypeDir: + // directory + mode |= os.ModeDir + case TypeFifo: + // fifo node + mode |= os.ModeNamedPipe + } + + return mode +} + +// sysStat, if non-nil, populates h from system-dependent fields of fi. +var sysStat func(fi os.FileInfo, h *Header) error + +// Mode constants from the tar spec. +const ( + c_ISUID = 04000 // Set uid + c_ISGID = 02000 // Set gid + c_ISVTX = 01000 // Save text (sticky bit) + c_ISDIR = 040000 // Directory + c_ISFIFO = 010000 // FIFO + c_ISREG = 0100000 // Regular file + c_ISLNK = 0120000 // Symbolic link + c_ISBLK = 060000 // Block special file + c_ISCHR = 020000 // Character special file + c_ISSOCK = 0140000 // Socket +) + +// Keywords for the PAX Extended Header +const ( + paxAtime = "atime" + paxCharset = "charset" + paxComment = "comment" + paxCtime = "ctime" // please note that ctime is not a valid pax header. + paxGid = "gid" + paxGname = "gname" + paxLinkpath = "linkpath" + paxMtime = "mtime" + paxPath = "path" + paxSize = "size" + paxUid = "uid" + paxUname = "uname" + paxXattr = "SCHILY.xattr." + paxNone = "" +) + +// FileInfoHeader creates a partially-populated Header from fi. +// If fi describes a symlink, FileInfoHeader records link as the link target. +// If fi describes a directory, a slash is appended to the name. +// Because os.FileInfo's Name method returns only the base name of +// the file it describes, it may be necessary to modify the Name field +// of the returned header to provide the full path name of the file. +func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { + if fi == nil { + return nil, errors.New("tar: FileInfo is nil") + } + fm := fi.Mode() + h := &Header{ + Name: fi.Name(), + ModTime: fi.ModTime(), + Mode: int64(fm.Perm()), // or'd with c_IS* constants later + } + switch { + case fm.IsRegular(): + h.Mode |= c_ISREG + h.Typeflag = TypeReg + h.Size = fi.Size() + case fi.IsDir(): + h.Typeflag = TypeDir + h.Mode |= c_ISDIR + h.Name += "/" + case fm&os.ModeSymlink != 0: + h.Typeflag = TypeSymlink + h.Mode |= c_ISLNK + h.Linkname = link + case fm&os.ModeDevice != 0: + if fm&os.ModeCharDevice != 0 { + h.Mode |= c_ISCHR + h.Typeflag = TypeChar + } else { + h.Mode |= c_ISBLK + h.Typeflag = TypeBlock + } + case fm&os.ModeNamedPipe != 0: + h.Typeflag = TypeFifo + h.Mode |= c_ISFIFO + case fm&os.ModeSocket != 0: + h.Mode |= c_ISSOCK + default: + return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm) + } + if fm&os.ModeSetuid != 0 { + h.Mode |= c_ISUID + } + if fm&os.ModeSetgid != 0 { + h.Mode |= c_ISGID + } + if fm&os.ModeSticky != 0 { + h.Mode |= c_ISVTX + } + if sysStat != nil { + return h, sysStat(fi, h) + } + return h, nil +} + +var zeroBlock = make([]byte, blockSize) + +// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values. +// We compute and return both. +func checksum(header []byte) (unsigned int64, signed int64) { + for i := 0; i < len(header); i++ { + if i == 148 { + // The chksum field (header[148:156]) is special: it should be treated as space bytes. + unsigned += ' ' * 8 + signed += ' ' * 8 + i += 7 + continue + } + unsigned += int64(header[i]) + signed += int64(int8(header[i])) + } + return +} + +type slicer []byte + +func (sp *slicer) next(n int) (b []byte) { + s := *sp + b, *sp = s[0:n], s[n:] + return +} + +func isASCII(s string) bool { + for _, c := range s { + if c >= 0x80 { + return false + } + } + return true +} + +func toASCII(s string) string { + if isASCII(s) { + return s + } + var buf bytes.Buffer + for _, c := range s { + if c < 0x80 { + buf.WriteByte(byte(c)) + } + } + return buf.String() +} diff --git a/src/archive/tar/example_test.go b/src/archive/tar/example_test.go new file mode 100644 index 000000000..351eaa0e6 --- /dev/null +++ b/src/archive/tar/example_test.go @@ -0,0 +1,79 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tar_test + +import ( + "archive/tar" + "bytes" + "fmt" + "io" + "log" + "os" +) + +func Example() { + // Create a buffer to write our archive to. + buf := new(bytes.Buffer) + + // Create a new tar archive. + tw := tar.NewWriter(buf) + + // Add some files to the archive. + var files = []struct { + Name, Body string + }{ + {"readme.txt", "This archive contains some text files."}, + {"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"}, + {"todo.txt", "Get animal handling licence."}, + } + for _, file := range files { + hdr := &tar.Header{ + Name: file.Name, + Size: int64(len(file.Body)), + } + if err := tw.WriteHeader(hdr); err != nil { + log.Fatalln(err) + } + if _, err := tw.Write([]byte(file.Body)); err != nil { + log.Fatalln(err) + } + } + // Make sure to check the error on Close. + if err := tw.Close(); err != nil { + log.Fatalln(err) + } + + // Open the tar archive for reading. + r := bytes.NewReader(buf.Bytes()) + tr := tar.NewReader(r) + + // Iterate through the files in the archive. + for { + hdr, err := tr.Next() + if err == io.EOF { + // end of tar archive + break + } + if err != nil { + log.Fatalln(err) + } + fmt.Printf("Contents of %s:\n", hdr.Name) + if _, err := io.Copy(os.Stdout, tr); err != nil { + log.Fatalln(err) + } + fmt.Println() + } + + // Output: + // Contents of readme.txt: + // This archive contains some text files. + // Contents of gopher.txt: + // Gopher names: + // George + // Geoffrey + // Gonzo + // Contents of todo.txt: + // Get animal handling licence. +} diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go new file mode 100644 index 000000000..a27559d0f --- /dev/null +++ b/src/archive/tar/reader.go @@ -0,0 +1,820 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tar + +// TODO(dsymonds): +// - pax extensions + +import ( + "bytes" + "errors" + "io" + "io/ioutil" + "os" + "strconv" + "strings" + "time" +) + +var ( + ErrHeader = errors.New("archive/tar: invalid tar header") +) + +const maxNanoSecondIntSize = 9 + +// A Reader provides sequential access to the contents of a tar archive. +// A tar archive consists of a sequence of files. +// The Next method advances to the next file in the archive (including the first), +// and then it can be treated as an io.Reader to access the file's data. +type Reader struct { + r io.Reader + err error + pad int64 // amount of padding (ignored) after current file entry + curr numBytesReader // reader for current file entry + hdrBuff [blockSize]byte // buffer to use in readHeader +} + +// A numBytesReader is an io.Reader with a numBytes method, returning the number +// of bytes remaining in the underlying encoded data. +type numBytesReader interface { + io.Reader + numBytes() int64 +} + +// A regFileReader is a numBytesReader for reading file data from a tar archive. +type regFileReader struct { + r io.Reader // underlying reader + nb int64 // number of unread bytes for current file entry +} + +// A sparseFileReader is a numBytesReader for reading sparse file data from a tar archive. +type sparseFileReader struct { + rfr *regFileReader // reads the sparse-encoded file data + sp []sparseEntry // the sparse map for the file + pos int64 // keeps track of file position + tot int64 // total size of the file +} + +// Keywords for GNU sparse files in a PAX extended header +const ( + paxGNUSparseNumBlocks = "GNU.sparse.numblocks" + paxGNUSparseOffset = "GNU.sparse.offset" + paxGNUSparseNumBytes = "GNU.sparse.numbytes" + paxGNUSparseMap = "GNU.sparse.map" + paxGNUSparseName = "GNU.sparse.name" + paxGNUSparseMajor = "GNU.sparse.major" + paxGNUSparseMinor = "GNU.sparse.minor" + paxGNUSparseSize = "GNU.sparse.size" + paxGNUSparseRealSize = "GNU.sparse.realsize" +) + +// Keywords for old GNU sparse headers +const ( + oldGNUSparseMainHeaderOffset = 386 + oldGNUSparseMainHeaderIsExtendedOffset = 482 + oldGNUSparseMainHeaderNumEntries = 4 + oldGNUSparseExtendedHeaderIsExtendedOffset = 504 + oldGNUSparseExtendedHeaderNumEntries = 21 + oldGNUSparseOffsetSize = 12 + oldGNUSparseNumBytesSize = 12 +) + +// NewReader creates a new Reader reading from r. +func NewReader(r io.Reader) *Reader { return &Reader{r: r} } + +// Next advances to the next entry in the tar archive. +func (tr *Reader) Next() (*Header, error) { + var hdr *Header + if tr.err == nil { + tr.skipUnread() + } + if tr.err != nil { + return hdr, tr.err + } + hdr = tr.readHeader() + if hdr == nil { + return hdr, tr.err + } + // Check for PAX/GNU header. + switch hdr.Typeflag { + case TypeXHeader: + // PAX extended header + headers, err := parsePAX(tr) + if err != nil { + return nil, err + } + // We actually read the whole file, + // but this skips alignment padding + tr.skipUnread() + hdr = tr.readHeader() + mergePAX(hdr, headers) + + // Check for a PAX format sparse file + sp, err := tr.checkForGNUSparsePAXHeaders(hdr, headers) + if err != nil { + tr.err = err + return nil, err + } + if sp != nil { + // Current file is a PAX format GNU sparse file. + // Set the current file reader to a sparse file reader. + tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size} + } + return hdr, nil + case TypeGNULongName: + // We have a GNU long name header. Its contents are the real file name. + realname, err := ioutil.ReadAll(tr) + if err != nil { + return nil, err + } + hdr, err := tr.Next() + hdr.Name = cString(realname) + return hdr, err + case TypeGNULongLink: + // We have a GNU long link header. + realname, err := ioutil.ReadAll(tr) + if err != nil { + return nil, err + } + hdr, err := tr.Next() + hdr.Linkname = cString(realname) + return hdr, err + } + return hdr, tr.err +} + +// checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then +// this function reads the sparse map and returns it. Unknown sparse formats are ignored, causing the file to +// be treated as a regular file. +func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]string) ([]sparseEntry, error) { + var sparseFormat string + + // Check for sparse format indicators + major, majorOk := headers[paxGNUSparseMajor] + minor, minorOk := headers[paxGNUSparseMinor] + sparseName, sparseNameOk := headers[paxGNUSparseName] + _, sparseMapOk := headers[paxGNUSparseMap] + sparseSize, sparseSizeOk := headers[paxGNUSparseSize] + sparseRealSize, sparseRealSizeOk := headers[paxGNUSparseRealSize] + + // Identify which, if any, sparse format applies from which PAX headers are set + if majorOk && minorOk { + sparseFormat = major + "." + minor + } else if sparseNameOk && sparseMapOk { + sparseFormat = "0.1" + } else if sparseSizeOk { + sparseFormat = "0.0" + } else { + // Not a PAX format GNU sparse file. + return nil, nil + } + + // Check for unknown sparse format + if sparseFormat != "0.0" && sparseFormat != "0.1" && sparseFormat != "1.0" { + return nil, nil + } + + // Update hdr from GNU sparse PAX headers + if sparseNameOk { + hdr.Name = sparseName + } + if sparseSizeOk { + realSize, err := strconv.ParseInt(sparseSize, 10, 0) + if err != nil { + return nil, ErrHeader + } + hdr.Size = realSize + } else if sparseRealSizeOk { + realSize, err := strconv.ParseInt(sparseRealSize, 10, 0) + if err != nil { + return nil, ErrHeader + } + hdr.Size = realSize + } + + // Set up the sparse map, according to the particular sparse format in use + var sp []sparseEntry + var err error + switch sparseFormat { + case "0.0", "0.1": + sp, err = readGNUSparseMap0x1(headers) + case "1.0": + sp, err = readGNUSparseMap1x0(tr.curr) + } + return sp, err +} + +// mergePAX merges well known headers according to PAX standard. +// In general headers with the same name as those found +// in the header struct overwrite those found in the header +// struct with higher precision or longer values. Esp. useful +// for name and linkname fields. +func mergePAX(hdr *Header, headers map[string]string) error { + for k, v := range headers { + switch k { + case paxPath: + hdr.Name = v + case paxLinkpath: + hdr.Linkname = v + case paxGname: + hdr.Gname = v + case paxUname: + hdr.Uname = v + case paxUid: + uid, err := strconv.ParseInt(v, 10, 0) + if err != nil { + return err + } + hdr.Uid = int(uid) + case paxGid: + gid, err := strconv.ParseInt(v, 10, 0) + if err != nil { + return err + } + hdr.Gid = int(gid) + case paxAtime: + t, err := parsePAXTime(v) + if err != nil { + return err + } + hdr.AccessTime = t + case paxMtime: + t, err := parsePAXTime(v) + if err != nil { + return err + } + hdr.ModTime = t + case paxCtime: + t, err := parsePAXTime(v) + if err != nil { + return err + } + hdr.ChangeTime = t + case paxSize: + size, err := strconv.ParseInt(v, 10, 0) + if err != nil { + return err + } + hdr.Size = int64(size) + default: + if strings.HasPrefix(k, paxXattr) { + if hdr.Xattrs == nil { + hdr.Xattrs = make(map[string]string) + } + hdr.Xattrs[k[len(paxXattr):]] = v + } + } + } + return nil +} + +// parsePAXTime takes a string of the form %d.%d as described in +// the PAX specification. +func parsePAXTime(t string) (time.Time, error) { + buf := []byte(t) + pos := bytes.IndexByte(buf, '.') + var seconds, nanoseconds int64 + var err error + if pos == -1 { + seconds, err = strconv.ParseInt(t, 10, 0) + if err != nil { + return time.Time{}, err + } + } else { + seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0) + if err != nil { + return time.Time{}, err + } + nano_buf := string(buf[pos+1:]) + // Pad as needed before converting to a decimal. + // For example .030 -> .030000000 -> 30000000 nanoseconds + if len(nano_buf) < maxNanoSecondIntSize { + // Right pad + nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf)) + } else if len(nano_buf) > maxNanoSecondIntSize { + // Right truncate + nano_buf = nano_buf[:maxNanoSecondIntSize] + } + nanoseconds, err = strconv.ParseInt(string(nano_buf), 10, 0) + if err != nil { + return time.Time{}, err + } + } + ts := time.Unix(seconds, nanoseconds) + return ts, nil +} + +// parsePAX parses PAX headers. +// If an extended header (type 'x') is invalid, ErrHeader is returned +func parsePAX(r io.Reader) (map[string]string, error) { + buf, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + + // For GNU PAX sparse format 0.0 support. + // This function transforms the sparse format 0.0 headers into sparse format 0.1 headers. + var sparseMap bytes.Buffer + + headers := make(map[string]string) + // Each record is constructed as + // "%d %s=%s\n", length, keyword, value + for len(buf) > 0 { + // or the header was empty to start with. + var sp int + // The size field ends at the first space. + sp = bytes.IndexByte(buf, ' ') + if sp == -1 { + return nil, ErrHeader + } + // Parse the first token as a decimal integer. + n, err := strconv.ParseInt(string(buf[:sp]), 10, 0) + if err != nil { + return nil, ErrHeader + } + // Extract everything between the decimal and the n -1 on the + // beginning to eat the ' ', -1 on the end to skip the newline. + var record []byte + record, buf = buf[sp+1:n-1], buf[n:] + // The first equals is guaranteed to mark the end of the key. + // Everything else is value. + eq := bytes.IndexByte(record, '=') + if eq == -1 { + return nil, ErrHeader + } + key, value := record[:eq], record[eq+1:] + + keyStr := string(key) + if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes { + // GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map. + sparseMap.Write(value) + sparseMap.Write([]byte{','}) + } else { + // Normal key. Set the value in the headers map. + headers[keyStr] = string(value) + } + } + if sparseMap.Len() != 0 { + // Add sparse info to headers, chopping off the extra comma + sparseMap.Truncate(sparseMap.Len() - 1) + headers[paxGNUSparseMap] = sparseMap.String() + } + return headers, nil +} + +// cString parses bytes as a NUL-terminated C-style string. +// If a NUL byte is not found then the whole slice is returned as a string. +func cString(b []byte) string { + n := 0 + for n < len(b) && b[n] != 0 { + n++ + } + return string(b[0:n]) +} + +func (tr *Reader) octal(b []byte) int64 { + // Check for binary format first. + if len(b) > 0 && b[0]&0x80 != 0 { + var x int64 + for i, c := range b { + if i == 0 { + c &= 0x7f // ignore signal bit in first byte + } + x = x<<8 | int64(c) + } + return x + } + + // Because unused fields are filled with NULs, we need + // to skip leading NULs. Fields may also be padded with + // spaces or NULs. + // So we remove leading and trailing NULs and spaces to + // be sure. + b = bytes.Trim(b, " \x00") + + if len(b) == 0 { + return 0 + } + x, err := strconv.ParseUint(cString(b), 8, 64) + if err != nil { + tr.err = err + } + return int64(x) +} + +// skipUnread skips any unread bytes in the existing file entry, as well as any alignment padding. +func (tr *Reader) skipUnread() { + nr := tr.numBytes() + tr.pad // number of bytes to skip + tr.curr, tr.pad = nil, 0 + if sr, ok := tr.r.(io.Seeker); ok { + if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil { + return + } + } + _, tr.err = io.CopyN(ioutil.Discard, tr.r, nr) +} + +func (tr *Reader) verifyChecksum(header []byte) bool { + if tr.err != nil { + return false + } + + given := tr.octal(header[148:156]) + unsigned, signed := checksum(header) + return given == unsigned || given == signed +} + +func (tr *Reader) readHeader() *Header { + header := tr.hdrBuff[:] + copy(header, zeroBlock) + + if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil { + return nil + } + + // Two blocks of zero bytes marks the end of the archive. + if bytes.Equal(header, zeroBlock[0:blockSize]) { + if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil { + return nil + } + if bytes.Equal(header, zeroBlock[0:blockSize]) { + tr.err = io.EOF + } else { + tr.err = ErrHeader // zero block and then non-zero block + } + return nil + } + + if !tr.verifyChecksum(header) { + tr.err = ErrHeader + return nil + } + + // Unpack + hdr := new(Header) + s := slicer(header) + + hdr.Name = cString(s.next(100)) + hdr.Mode = tr.octal(s.next(8)) + hdr.Uid = int(tr.octal(s.next(8))) + hdr.Gid = int(tr.octal(s.next(8))) + hdr.Size = tr.octal(s.next(12)) + hdr.ModTime = time.Unix(tr.octal(s.next(12)), 0) + s.next(8) // chksum + hdr.Typeflag = s.next(1)[0] + hdr.Linkname = cString(s.next(100)) + + // The remainder of the header depends on the value of magic. + // The original (v7) version of tar had no explicit magic field, + // so its magic bytes, like the rest of the block, are NULs. + magic := string(s.next(8)) // contains version field as well. + var format string + switch { + case magic[:6] == "ustar\x00": // POSIX tar (1003.1-1988) + if string(header[508:512]) == "tar\x00" { + format = "star" + } else { + format = "posix" + } + case magic == "ustar \x00": // old GNU tar + format = "gnu" + } + + switch format { + case "posix", "gnu", "star": + hdr.Uname = cString(s.next(32)) + hdr.Gname = cString(s.next(32)) + devmajor := s.next(8) + devminor := s.next(8) + if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock { + hdr.Devmajor = tr.octal(devmajor) + hdr.Devminor = tr.octal(devminor) + } + var prefix string + switch format { + case "posix", "gnu": + prefix = cString(s.next(155)) + case "star": + prefix = cString(s.next(131)) + hdr.AccessTime = time.Unix(tr.octal(s.next(12)), 0) + hdr.ChangeTime = time.Unix(tr.octal(s.next(12)), 0) + } + if len(prefix) > 0 { + hdr.Name = prefix + "/" + hdr.Name + } + } + + if tr.err != nil { + tr.err = ErrHeader + return nil + } + + // Maximum value of hdr.Size is 64 GB (12 octal digits), + // so there's no risk of int64 overflowing. + nb := int64(hdr.Size) + tr.pad = -nb & (blockSize - 1) // blockSize is a power of two + + // Set the current file reader. + tr.curr = ®FileReader{r: tr.r, nb: nb} + + // Check for old GNU sparse format entry. + if hdr.Typeflag == TypeGNUSparse { + // Get the real size of the file. + hdr.Size = tr.octal(header[483:495]) + + // Read the sparse map. + sp := tr.readOldGNUSparseMap(header) + if tr.err != nil { + return nil + } + // Current file is a GNU sparse file. Update the current file reader. + tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size} + } + + return hdr +} + +// A sparseEntry holds a single entry in a sparse file's sparse map. +// A sparse entry indicates the offset and size in a sparse file of a +// block of data. +type sparseEntry struct { + offset int64 + numBytes int64 +} + +// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format. +// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries, +// then one or more extension headers are used to store the rest of the sparse map. +func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry { + isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0 + spCap := oldGNUSparseMainHeaderNumEntries + if isExtended { + spCap += oldGNUSparseExtendedHeaderNumEntries + } + sp := make([]sparseEntry, 0, spCap) + s := slicer(header[oldGNUSparseMainHeaderOffset:]) + + // Read the four entries from the main tar header + for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ { + offset := tr.octal(s.next(oldGNUSparseOffsetSize)) + numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize)) + if tr.err != nil { + tr.err = ErrHeader + return nil + } + if offset == 0 && numBytes == 0 { + break + } + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + + for isExtended { + // There are more entries. Read an extension header and parse its entries. + sparseHeader := make([]byte, blockSize) + if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil { + return nil + } + isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0 + s = slicer(sparseHeader) + for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ { + offset := tr.octal(s.next(oldGNUSparseOffsetSize)) + numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize)) + if tr.err != nil { + tr.err = ErrHeader + return nil + } + if offset == 0 && numBytes == 0 { + break + } + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + } + return sp +} + +// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format version 1.0. +// The sparse map is stored just before the file data and padded out to the nearest block boundary. +func readGNUSparseMap1x0(r io.Reader) ([]sparseEntry, error) { + buf := make([]byte, 2*blockSize) + sparseHeader := buf[:blockSize] + + // readDecimal is a helper function to read a decimal integer from the sparse map + // while making sure to read from the file in blocks of size blockSize + readDecimal := func() (int64, error) { + // Look for newline + nl := bytes.IndexByte(sparseHeader, '\n') + if nl == -1 { + if len(sparseHeader) >= blockSize { + // This is an error + return 0, ErrHeader + } + oldLen := len(sparseHeader) + newLen := oldLen + blockSize + if cap(sparseHeader) < newLen { + // There's more header, but we need to make room for the next block + copy(buf, sparseHeader) + sparseHeader = buf[:newLen] + } else { + // There's more header, and we can just reslice + sparseHeader = sparseHeader[:newLen] + } + + // Now that sparseHeader is large enough, read next block + if _, err := io.ReadFull(r, sparseHeader[oldLen:newLen]); err != nil { + return 0, err + } + + // Look for a newline in the new data + nl = bytes.IndexByte(sparseHeader[oldLen:newLen], '\n') + if nl == -1 { + // This is an error + return 0, ErrHeader + } + nl += oldLen // We want the position from the beginning + } + // Now that we've found a newline, read a number + n, err := strconv.ParseInt(string(sparseHeader[:nl]), 10, 0) + if err != nil { + return 0, ErrHeader + } + + // Update sparseHeader to consume this number + sparseHeader = sparseHeader[nl+1:] + return n, nil + } + + // Read the first block + if _, err := io.ReadFull(r, sparseHeader); err != nil { + return nil, err + } + + // The first line contains the number of entries + numEntries, err := readDecimal() + if err != nil { + return nil, err + } + + // Read all the entries + sp := make([]sparseEntry, 0, numEntries) + for i := int64(0); i < numEntries; i++ { + // Read the offset + offset, err := readDecimal() + if err != nil { + return nil, err + } + // Read numBytes + numBytes, err := readDecimal() + if err != nil { + return nil, err + } + + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + + return sp, nil +} + +// readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format version 0.1. +// The sparse map is stored in the PAX headers. +func readGNUSparseMap0x1(headers map[string]string) ([]sparseEntry, error) { + // Get number of entries + numEntriesStr, ok := headers[paxGNUSparseNumBlocks] + if !ok { + return nil, ErrHeader + } + numEntries, err := strconv.ParseInt(numEntriesStr, 10, 0) + if err != nil { + return nil, ErrHeader + } + + sparseMap := strings.Split(headers[paxGNUSparseMap], ",") + + // There should be two numbers in sparseMap for each entry + if int64(len(sparseMap)) != 2*numEntries { + return nil, ErrHeader + } + + // Loop through the entries in the sparse map + sp := make([]sparseEntry, 0, numEntries) + for i := int64(0); i < numEntries; i++ { + offset, err := strconv.ParseInt(sparseMap[2*i], 10, 0) + if err != nil { + return nil, ErrHeader + } + numBytes, err := strconv.ParseInt(sparseMap[2*i+1], 10, 0) + if err != nil { + return nil, ErrHeader + } + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + + return sp, nil +} + +// numBytes returns the number of bytes left to read in the current file's entry +// in the tar archive, or 0 if there is no current file. +func (tr *Reader) numBytes() int64 { + if tr.curr == nil { + // No current file, so no bytes + return 0 + } + return tr.curr.numBytes() +} + +// Read reads from the current entry in the tar archive. +// It returns 0, io.EOF when it reaches the end of that entry, +// until Next is called to advance to the next entry. +func (tr *Reader) Read(b []byte) (n int, err error) { + if tr.curr == nil { + return 0, io.EOF + } + n, err = tr.curr.Read(b) + if err != nil && err != io.EOF { + tr.err = err + } + return +} + +func (rfr *regFileReader) Read(b []byte) (n int, err error) { + if rfr.nb == 0 { + // file consumed + return 0, io.EOF + } + if int64(len(b)) > rfr.nb { + b = b[0:rfr.nb] + } + n, err = rfr.r.Read(b) + rfr.nb -= int64(n) + + if err == io.EOF && rfr.nb > 0 { + err = io.ErrUnexpectedEOF + } + return +} + +// numBytes returns the number of bytes left to read in the file's data in the tar archive. +func (rfr *regFileReader) numBytes() int64 { + return rfr.nb +} + +// readHole reads a sparse file hole ending at offset toOffset +func (sfr *sparseFileReader) readHole(b []byte, toOffset int64) int { + n64 := toOffset - sfr.pos + if n64 > int64(len(b)) { + n64 = int64(len(b)) + } + n := int(n64) + for i := 0; i < n; i++ { + b[i] = 0 + } + sfr.pos += n64 + return n +} + +// Read reads the sparse file data in expanded form. +func (sfr *sparseFileReader) Read(b []byte) (n int, err error) { + if len(sfr.sp) == 0 { + // No more data fragments to read from. + if sfr.pos < sfr.tot { + // We're in the last hole + n = sfr.readHole(b, sfr.tot) + return + } + // Otherwise, we're at the end of the file + return 0, io.EOF + } + if sfr.pos < sfr.sp[0].offset { + // We're in a hole + n = sfr.readHole(b, sfr.sp[0].offset) + return + } + + // We're not in a hole, so we'll read from the next data fragment + posInFragment := sfr.pos - sfr.sp[0].offset + bytesLeft := sfr.sp[0].numBytes - posInFragment + if int64(len(b)) > bytesLeft { + b = b[0:bytesLeft] + } + + n, err = sfr.rfr.Read(b) + sfr.pos += int64(n) + + if int64(n) == bytesLeft { + // We're done with this fragment + sfr.sp = sfr.sp[1:] + } + + if err == io.EOF && sfr.pos < sfr.tot { + // We reached the end of the last fragment's data, but there's a final hole + err = nil + } + return +} + +// numBytes returns the number of bytes left to read in the sparse file's +// sparse-encoded data in the tar archive. +func (sfr *sparseFileReader) numBytes() int64 { + return sfr.rfr.nb +} diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go new file mode 100644 index 000000000..9601ffe45 --- /dev/null +++ b/src/archive/tar/reader_test.go @@ -0,0 +1,743 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tar + +import ( + "bytes" + "crypto/md5" + "fmt" + "io" + "io/ioutil" + "os" + "reflect" + "strings" + "testing" + "time" +) + +type untarTest struct { + file string + headers []*Header + cksums []string +} + +var gnuTarTest = &untarTest{ + file: "testdata/gnu.tar", + headers: []*Header{ + { + Name: "small.txt", + Mode: 0640, + Uid: 73025, + Gid: 5000, + Size: 5, + ModTime: time.Unix(1244428340, 0), + Typeflag: '0', + Uname: "dsymonds", + Gname: "eng", + }, + { + Name: "small2.txt", + Mode: 0640, + Uid: 73025, + Gid: 5000, + Size: 11, + ModTime: time.Unix(1244436044, 0), + Typeflag: '0', + Uname: "dsymonds", + Gname: "eng", + }, + }, + cksums: []string{ + "e38b27eaccb4391bdec553a7f3ae6b2f", + "c65bd2e50a56a2138bf1716f2fd56fe9", + }, +} + +var sparseTarTest = &untarTest{ + file: "testdata/sparse-formats.tar", + headers: []*Header{ + { + Name: "sparse-gnu", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392395740, 0), + Typeflag: 0x53, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "sparse-posix-0.0", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392342187, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "sparse-posix-0.1", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392340456, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "sparse-posix-1.0", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392337404, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "end", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 4, + ModTime: time.Unix(1392398319, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + }, + cksums: []string{ + "6f53234398c2449fe67c1812d993012f", + "6f53234398c2449fe67c1812d993012f", + "6f53234398c2449fe67c1812d993012f", + "6f53234398c2449fe67c1812d993012f", + "b0061974914468de549a2af8ced10316", + }, +} + +var untarTests = []*untarTest{ + gnuTarTest, + sparseTarTest, + { + file: "testdata/star.tar", + headers: []*Header{ + { + Name: "small.txt", + Mode: 0640, + Uid: 73025, + Gid: 5000, + Size: 5, + ModTime: time.Unix(1244592783, 0), + Typeflag: '0', + Uname: "dsymonds", + Gname: "eng", + AccessTime: time.Unix(1244592783, 0), + ChangeTime: time.Unix(1244592783, 0), + }, + { + Name: "small2.txt", + Mode: 0640, + Uid: 73025, + Gid: 5000, + Size: 11, + ModTime: time.Unix(1244592783, 0), + Typeflag: '0', + Uname: "dsymonds", + Gname: "eng", + AccessTime: time.Unix(1244592783, 0), + ChangeTime: time.Unix(1244592783, 0), + }, + }, + }, + { + file: "testdata/v7.tar", + headers: []*Header{ + { + Name: "small.txt", + Mode: 0444, + Uid: 73025, + Gid: 5000, + Size: 5, + ModTime: time.Unix(1244593104, 0), + Typeflag: '\x00', + }, + { + Name: "small2.txt", + Mode: 0444, + Uid: 73025, + Gid: 5000, + Size: 11, + ModTime: time.Unix(1244593104, 0), + Typeflag: '\x00', + }, + }, + }, + { + file: "testdata/pax.tar", + headers: []*Header{ + { + Name: "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100", + Mode: 0664, + Uid: 1000, + Gid: 1000, + Uname: "shane", + Gname: "shane", + Size: 7, + ModTime: time.Unix(1350244992, 23960108), + ChangeTime: time.Unix(1350244992, 23960108), + AccessTime: time.Unix(1350244992, 23960108), + Typeflag: TypeReg, + }, + { + Name: "a/b", + Mode: 0777, + Uid: 1000, + Gid: 1000, + Uname: "shane", + Gname: "shane", + Size: 0, + ModTime: time.Unix(1350266320, 910238425), + ChangeTime: time.Unix(1350266320, 910238425), + AccessTime: time.Unix(1350266320, 910238425), + Typeflag: TypeSymlink, + Linkname: "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100", + }, + }, + }, + { + file: "testdata/nil-uid.tar", // golang.org/issue/5290 + headers: []*Header{ + { + Name: "P1050238.JPG.log", + Mode: 0664, + Uid: 0, + Gid: 0, + Size: 14, + ModTime: time.Unix(1365454838, 0), + Typeflag: TypeReg, + Linkname: "", + Uname: "eyefi", + Gname: "eyefi", + Devmajor: 0, + Devminor: 0, + }, + }, + }, + { + file: "testdata/xattrs.tar", + headers: []*Header{ + { + Name: "small.txt", + Mode: 0644, + Uid: 1000, + Gid: 10, + Size: 5, + ModTime: time.Unix(1386065770, 448252320), + Typeflag: '0', + Uname: "alex", + Gname: "wheel", + AccessTime: time.Unix(1389782991, 419875220), + ChangeTime: time.Unix(1389782956, 794414986), + Xattrs: map[string]string{ + "user.key": "value", + "user.key2": "value2", + // Interestingly, selinux encodes the terminating null inside the xattr + "security.selinux": "unconfined_u:object_r:default_t:s0\x00", + }, + }, + { + Name: "small2.txt", + Mode: 0644, + Uid: 1000, + Gid: 10, + Size: 11, + ModTime: time.Unix(1386065770, 449252304), + Typeflag: '0', + Uname: "alex", + Gname: "wheel", + AccessTime: time.Unix(1389782991, 419875220), + ChangeTime: time.Unix(1386065770, 449252304), + Xattrs: map[string]string{ + "security.selinux": "unconfined_u:object_r:default_t:s0\x00", + }, + }, + }, + }, +} + +func TestReader(t *testing.T) { +testLoop: + for i, test := range untarTests { + f, err := os.Open(test.file) + if err != nil { + t.Errorf("test %d: Unexpected error: %v", i, err) + continue + } + defer f.Close() + tr := NewReader(f) + for j, header := range test.headers { + hdr, err := tr.Next() + if err != nil || hdr == nil { + t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err) + f.Close() + continue testLoop + } + if !reflect.DeepEqual(*hdr, *header) { + t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v", + i, j, *hdr, *header) + } + } + hdr, err := tr.Next() + if err == io.EOF { + continue testLoop + } + if hdr != nil || err != nil { + t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err) + } + } +} + +func TestPartialRead(t *testing.T) { + f, err := os.Open("testdata/gnu.tar") + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + defer f.Close() + + tr := NewReader(f) + + // Read the first four bytes; Next() should skip the last byte. + hdr, err := tr.Next() + if err != nil || hdr == nil { + t.Fatalf("Didn't get first file: %v", err) + } + buf := make([]byte, 4) + if _, err := io.ReadFull(tr, buf); err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if expected := []byte("Kilt"); !bytes.Equal(buf, expected) { + t.Errorf("Contents = %v, want %v", buf, expected) + } + + // Second file + hdr, err = tr.Next() + if err != nil || hdr == nil { + t.Fatalf("Didn't get second file: %v", err) + } + buf = make([]byte, 6) + if _, err := io.ReadFull(tr, buf); err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if expected := []byte("Google"); !bytes.Equal(buf, expected) { + t.Errorf("Contents = %v, want %v", buf, expected) + } +} + +func TestIncrementalRead(t *testing.T) { + test := gnuTarTest + f, err := os.Open(test.file) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + defer f.Close() + + tr := NewReader(f) + + headers := test.headers + cksums := test.cksums + nread := 0 + + // loop over all files + for ; ; nread++ { + hdr, err := tr.Next() + if hdr == nil || err == io.EOF { + break + } + + // check the header + if !reflect.DeepEqual(*hdr, *headers[nread]) { + t.Errorf("Incorrect header:\nhave %+v\nwant %+v", + *hdr, headers[nread]) + } + + // read file contents in little chunks EOF, + // checksumming all the way + h := md5.New() + rdbuf := make([]uint8, 8) + for { + nr, err := tr.Read(rdbuf) + if err == io.EOF { + break + } + if err != nil { + t.Errorf("Read: unexpected error %v\n", err) + break + } + h.Write(rdbuf[0:nr]) + } + // verify checksum + have := fmt.Sprintf("%x", h.Sum(nil)) + want := cksums[nread] + if want != have { + t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want) + } + } + if nread != len(headers) { + t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread) + } +} + +func TestNonSeekable(t *testing.T) { + test := gnuTarTest + f, err := os.Open(test.file) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + defer f.Close() + + type readerOnly struct { + io.Reader + } + tr := NewReader(readerOnly{f}) + nread := 0 + + for ; ; nread++ { + _, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + } + + if nread != len(test.headers) { + t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(test.headers), nread) + } +} + +func TestParsePAXHeader(t *testing.T) { + paxTests := [][3]string{ + {"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths + {"a", "a=name", "9 a=name\n"}, // Test case involving multiple acceptable length + {"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}} + for _, test := range paxTests { + key, expected, raw := test[0], test[1], test[2] + reader := bytes.NewReader([]byte(raw)) + headers, err := parsePAX(reader) + if err != nil { + t.Errorf("Couldn't parse correctly formatted headers: %v", err) + continue + } + if strings.EqualFold(headers[key], expected) { + t.Errorf("mtime header incorrectly parsed: got %s, wanted %s", headers[key], expected) + continue + } + trailer := make([]byte, 100) + n, err := reader.Read(trailer) + if err != io.EOF || n != 0 { + 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") + } +} + +func TestParsePAXTime(t *testing.T) { + // Some valid PAX time values + timestamps := map[string]time.Time{ + "1350244992.023960108": time.Unix(1350244992, 23960108), // The common case + "1350244992.02396010": time.Unix(1350244992, 23960100), // Lower precision value + "1350244992.0239601089": time.Unix(1350244992, 23960108), // Higher precision value + "1350244992": time.Unix(1350244992, 0), // Low precision value + } + for input, expected := range timestamps { + ts, err := parsePAXTime(input) + if err != nil { + t.Fatal(err) + } + if !ts.Equal(expected) { + t.Fatalf("Time parsing failure %s %s", ts, expected) + } + } +} + +func TestMergePAX(t *testing.T) { + hdr := new(Header) + // Test a string, integer, and time based value. + headers := map[string]string{ + "path": "a/b/c", + "uid": "1000", + "mtime": "1350244992.023960108", + } + err := mergePAX(hdr, headers) + if err != nil { + t.Fatal(err) + } + want := &Header{ + Name: "a/b/c", + Uid: 1000, + ModTime: time.Unix(1350244992, 23960108), + } + if !reflect.DeepEqual(hdr, want) { + t.Errorf("incorrect merge: got %+v, want %+v", hdr, want) + } +} + +func TestSparseEndToEnd(t *testing.T) { + test := sparseTarTest + f, err := os.Open(test.file) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + defer f.Close() + + tr := NewReader(f) + + headers := test.headers + cksums := test.cksums + nread := 0 + + // loop over all files + for ; ; nread++ { + hdr, err := tr.Next() + if hdr == nil || err == io.EOF { + break + } + + // check the header + if !reflect.DeepEqual(*hdr, *headers[nread]) { + t.Errorf("Incorrect header:\nhave %+v\nwant %+v", + *hdr, headers[nread]) + } + + // read and checksum the file data + h := md5.New() + _, err = io.Copy(h, tr) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + // verify checksum + have := fmt.Sprintf("%x", h.Sum(nil)) + want := cksums[nread] + if want != have { + t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want) + } + } + if nread != len(headers) { + t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread) + } +} + +type sparseFileReadTest struct { + sparseData []byte + sparseMap []sparseEntry + realSize int64 + expected []byte +} + +var sparseFileReadTests = []sparseFileReadTest{ + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 0, numBytes: 2}, + {offset: 5, numBytes: 3}, + }, + realSize: 8, + expected: []byte("ab\x00\x00\x00cde"), + }, + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 0, numBytes: 2}, + {offset: 5, numBytes: 3}, + }, + realSize: 10, + expected: []byte("ab\x00\x00\x00cde\x00\x00"), + }, + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 1, numBytes: 3}, + {offset: 6, numBytes: 2}, + }, + realSize: 8, + expected: []byte("\x00abc\x00\x00de"), + }, + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 1, numBytes: 3}, + {offset: 6, numBytes: 2}, + }, + realSize: 10, + expected: []byte("\x00abc\x00\x00de\x00\x00"), + }, + { + sparseData: []byte(""), + sparseMap: nil, + realSize: 2, + expected: []byte("\x00\x00"), + }, +} + +func TestSparseFileReader(t *testing.T) { + for i, test := range sparseFileReadTests { + r := bytes.NewReader(test.sparseData) + nb := int64(r.Len()) + sfr := &sparseFileReader{ + rfr: ®FileReader{r: r, nb: nb}, + sp: test.sparseMap, + pos: 0, + tot: test.realSize, + } + if sfr.numBytes() != nb { + t.Errorf("test %d: Before reading, sfr.numBytes() = %d, want %d", i, sfr.numBytes(), nb) + } + buf, err := ioutil.ReadAll(sfr) + if err != nil { + t.Errorf("test %d: Unexpected error: %v", i, err) + } + if e := test.expected; !bytes.Equal(buf, e) { + t.Errorf("test %d: Contents = %v, want %v", i, buf, e) + } + if sfr.numBytes() != 0 { + t.Errorf("test %d: After draining the reader, numBytes() was nonzero", i) + } + } +} + +func TestSparseIncrementalRead(t *testing.T) { + sparseMap := []sparseEntry{{10, 2}} + sparseData := []byte("Go") + expected := "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Go\x00\x00\x00\x00\x00\x00\x00\x00" + + r := bytes.NewReader(sparseData) + nb := int64(r.Len()) + sfr := &sparseFileReader{ + rfr: ®FileReader{r: r, nb: nb}, + sp: sparseMap, + pos: 0, + tot: int64(len(expected)), + } + + // We'll read the data 6 bytes at a time, with a hole of size 10 at + // the beginning and one of size 8 at the end. + var outputBuf bytes.Buffer + buf := make([]byte, 6) + for { + n, err := sfr.Read(buf) + if err == io.EOF { + break + } + if err != nil { + t.Errorf("Read: unexpected error %v\n", err) + } + if n > 0 { + _, err := outputBuf.Write(buf[:n]) + if err != nil { + t.Errorf("Write: unexpected error %v\n", err) + } + } + } + got := outputBuf.String() + if got != expected { + t.Errorf("Contents = %v, want %v", got, expected) + } +} + +func TestReadGNUSparseMap0x1(t *testing.T) { + headers := map[string]string{ + paxGNUSparseNumBlocks: "4", + paxGNUSparseMap: "0,5,10,5,20,5,30,5", + } + expected := []sparseEntry{ + {offset: 0, numBytes: 5}, + {offset: 10, numBytes: 5}, + {offset: 20, numBytes: 5}, + {offset: 30, numBytes: 5}, + } + + sp, err := readGNUSparseMap0x1(headers) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if !reflect.DeepEqual(sp, expected) { + t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected) + } +} + +func TestReadGNUSparseMap1x0(t *testing.T) { + // This test uses lots of holes so the sparse header takes up more than two blocks + numEntries := 100 + expected := make([]sparseEntry, 0, numEntries) + sparseMap := new(bytes.Buffer) + + fmt.Fprintf(sparseMap, "%d\n", numEntries) + for i := 0; i < numEntries; i++ { + offset := int64(2048 * i) + numBytes := int64(1024) + expected = append(expected, sparseEntry{offset: offset, numBytes: numBytes}) + fmt.Fprintf(sparseMap, "%d\n%d\n", offset, numBytes) + } + + // Make the header the smallest multiple of blockSize that fits the sparseMap + headerBlocks := (sparseMap.Len() + blockSize - 1) / blockSize + bufLen := blockSize * headerBlocks + buf := make([]byte, bufLen) + copy(buf, sparseMap.Bytes()) + + // Get an reader to read the sparse map + r := bytes.NewReader(buf) + + // Read the sparse map + sp, err := readGNUSparseMap1x0(r) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if !reflect.DeepEqual(sp, expected) { + t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected) + } +} + +func TestUninitializedRead(t *testing.T) { + test := gnuTarTest + f, err := os.Open(test.file) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + defer f.Close() + + tr := NewReader(f) + _, err = tr.Read([]byte{}) + if err == nil || err != io.EOF { + t.Errorf("Unexpected error: %v, wanted %v", err, io.EOF) + } + +} diff --git a/src/archive/tar/stat_atim.go b/src/archive/tar/stat_atim.go new file mode 100644 index 000000000..cf9cc79c5 --- /dev/null +++ b/src/archive/tar/stat_atim.go @@ -0,0 +1,20 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux dragonfly openbsd solaris + +package tar + +import ( + "syscall" + "time" +) + +func statAtime(st *syscall.Stat_t) time.Time { + return time.Unix(st.Atim.Unix()) +} + +func statCtime(st *syscall.Stat_t) time.Time { + return time.Unix(st.Ctim.Unix()) +} diff --git a/src/archive/tar/stat_atimespec.go b/src/archive/tar/stat_atimespec.go new file mode 100644 index 000000000..6f17dbe30 --- /dev/null +++ b/src/archive/tar/stat_atimespec.go @@ -0,0 +1,20 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin freebsd netbsd + +package tar + +import ( + "syscall" + "time" +) + +func statAtime(st *syscall.Stat_t) time.Time { + return time.Unix(st.Atimespec.Unix()) +} + +func statCtime(st *syscall.Stat_t) time.Time { + return time.Unix(st.Ctimespec.Unix()) +} diff --git a/src/archive/tar/stat_unix.go b/src/archive/tar/stat_unix.go new file mode 100644 index 000000000..cb843db4c --- /dev/null +++ b/src/archive/tar/stat_unix.go @@ -0,0 +1,32 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux darwin dragonfly freebsd openbsd netbsd solaris + +package tar + +import ( + "os" + "syscall" +) + +func init() { + sysStat = statUnix +} + +func statUnix(fi os.FileInfo, h *Header) error { + sys, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return nil + } + h.Uid = int(sys.Uid) + h.Gid = int(sys.Gid) + // TODO(bradfitz): populate username & group. os/user + // doesn't cache LookupId lookups, and lacks group + // lookup functions. + h.AccessTime = statAtime(sys) + h.ChangeTime = statCtime(sys) + // TODO(bradfitz): major/minor device numbers? + return nil +} diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go new file mode 100644 index 000000000..ed333f3ea --- /dev/null +++ b/src/archive/tar/tar_test.go @@ -0,0 +1,284 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tar + +import ( + "bytes" + "io/ioutil" + "os" + "path" + "reflect" + "strings" + "testing" + "time" +) + +func TestFileInfoHeader(t *testing.T) { + fi, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + h, err := FileInfoHeader(fi, "") + if err != nil { + t.Fatalf("FileInfoHeader: %v", err) + } + if g, e := h.Name, "small.txt"; g != e { + t.Errorf("Name = %q; want %q", g, e) + } + if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e { + t.Errorf("Mode = %#o; want %#o", g, e) + } + if g, e := h.Size, int64(5); g != e { + t.Errorf("Size = %v; want %v", g, e) + } + if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) { + t.Errorf("ModTime = %v; want %v", g, e) + } + // FileInfoHeader should error when passing nil FileInfo + if _, err := FileInfoHeader(nil, ""); err == nil { + t.Fatalf("Expected error when passing nil to FileInfoHeader") + } +} + +func TestFileInfoHeaderDir(t *testing.T) { + fi, err := os.Stat("testdata") + if err != nil { + t.Fatal(err) + } + h, err := FileInfoHeader(fi, "") + if err != nil { + t.Fatalf("FileInfoHeader: %v", err) + } + if g, e := h.Name, "testdata/"; g != e { + t.Errorf("Name = %q; want %q", g, e) + } + // Ignoring c_ISGID for golang.org/issue/4867 + if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm())|c_ISDIR; g != e { + t.Errorf("Mode = %#o; want %#o", g, e) + } + if g, e := h.Size, int64(0); g != e { + t.Errorf("Size = %v; want %v", g, e) + } + if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) { + t.Errorf("ModTime = %v; want %v", g, e) + } +} + +func TestFileInfoHeaderSymlink(t *testing.T) { + h, err := FileInfoHeader(symlink{}, "some-target") + if err != nil { + t.Fatal(err) + } + if g, e := h.Name, "some-symlink"; g != e { + t.Errorf("Name = %q; want %q", g, e) + } + if g, e := h.Linkname, "some-target"; g != e { + t.Errorf("Linkname = %q; want %q", g, e) + } +} + +type symlink struct{} + +func (symlink) Name() string { return "some-symlink" } +func (symlink) Size() int64 { return 0 } +func (symlink) Mode() os.FileMode { return os.ModeSymlink } +func (symlink) ModTime() time.Time { return time.Time{} } +func (symlink) IsDir() bool { return false } +func (symlink) Sys() interface{} { return nil } + +func TestRoundTrip(t *testing.T) { + data := []byte("some file contents") + + var b bytes.Buffer + tw := NewWriter(&b) + hdr := &Header{ + Name: "file.txt", + Uid: 1 << 21, // too big for 8 octal digits + Size: int64(len(data)), + ModTime: time.Now(), + } + // tar only supports second precision. + hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond) + if err := tw.WriteHeader(hdr); err != nil { + t.Fatalf("tw.WriteHeader: %v", err) + } + if _, err := tw.Write(data); err != nil { + t.Fatalf("tw.Write: %v", err) + } + if err := tw.Close(); err != nil { + t.Fatalf("tw.Close: %v", err) + } + + // Read it back. + tr := NewReader(&b) + rHdr, err := tr.Next() + if err != nil { + t.Fatalf("tr.Next: %v", err) + } + if !reflect.DeepEqual(rHdr, hdr) { + t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr) + } + rData, err := ioutil.ReadAll(tr) + if err != nil { + t.Fatalf("Read: %v", err) + } + if !bytes.Equal(rData, data) { + t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data) + } +} + +type headerRoundTripTest struct { + h *Header + fm os.FileMode +} + +func TestHeaderRoundTrip(t *testing.T) { + golden := []headerRoundTripTest{ + // regular file. + { + h: &Header{ + Name: "test.txt", + Mode: 0644 | c_ISREG, + Size: 12, + ModTime: time.Unix(1360600916, 0), + Typeflag: TypeReg, + }, + 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{ + Name: "link.txt", + Mode: 0777 | c_ISLNK, + Size: 0, + ModTime: time.Unix(1360600852, 0), + Typeflag: TypeSymlink, + }, + fm: 0777 | os.ModeSymlink, + }, + // character device node. + { + h: &Header{ + Name: "dev/null", + Mode: 0666 | c_ISCHR, + Size: 0, + ModTime: time.Unix(1360578951, 0), + Typeflag: TypeChar, + }, + fm: 0666 | os.ModeDevice | os.ModeCharDevice, + }, + // block device node. + { + h: &Header{ + Name: "dev/sda", + Mode: 0660 | c_ISBLK, + Size: 0, + ModTime: time.Unix(1360578954, 0), + Typeflag: TypeBlock, + }, + fm: 0660 | os.ModeDevice, + }, + // directory. + { + h: &Header{ + Name: "dir/", + Mode: 0755 | c_ISDIR, + Size: 0, + ModTime: time.Unix(1360601116, 0), + Typeflag: TypeDir, + }, + fm: 0755 | os.ModeDir, + }, + // fifo node. + { + h: &Header{ + Name: "dev/initctl", + Mode: 0600 | c_ISFIFO, + Size: 0, + ModTime: time.Unix(1360578949, 0), + Typeflag: TypeFifo, + }, + fm: 0600 | os.ModeNamedPipe, + }, + // setuid. + { + h: &Header{ + Name: "bin/su", + Mode: 0755 | c_ISREG | c_ISUID, + Size: 23232, + ModTime: time.Unix(1355405093, 0), + Typeflag: TypeReg, + }, + fm: 0755 | os.ModeSetuid, + }, + // setguid. + { + h: &Header{ + Name: "group.txt", + Mode: 0750 | c_ISREG | c_ISGID, + Size: 0, + ModTime: time.Unix(1360602346, 0), + Typeflag: TypeReg, + }, + fm: 0750 | os.ModeSetgid, + }, + // sticky. + { + h: &Header{ + Name: "sticky.txt", + Mode: 0600 | c_ISREG | c_ISVTX, + Size: 7, + ModTime: time.Unix(1360602540, 0), + Typeflag: TypeReg, + }, + fm: 0600 | os.ModeSticky, + }, + } + + for i, g := range golden { + fi := g.h.FileInfo() + h2, err := FileInfoHeader(fi, "") + if err != nil { + t.Error(err) + continue + } + if strings.Contains(fi.Name(), "/") { + t.Errorf("FileInfo of %q contains slash: %q", g.h.Name, fi.Name()) + } + name := path.Base(g.h.Name) + if fi.IsDir() { + name += "/" + } + if got, want := h2.Name, name; got != want { + t.Errorf("i=%d: Name: got %v, want %v", i, got, want) + } + 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.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.ModTime, g.h.ModTime; got != want { + t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want) + } + if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h { + t.Errorf("i=%d: Sys didn't return original *Header", i) + } + } +} diff --git a/src/archive/tar/testdata/gnu.tar b/src/archive/tar/testdata/gnu.tar new file mode 100644 index 000000000..fc899dc8d Binary files /dev/null and b/src/archive/tar/testdata/gnu.tar differ diff --git a/src/archive/tar/testdata/nil-uid.tar b/src/archive/tar/testdata/nil-uid.tar new file mode 100644 index 000000000..cc9cfaa33 Binary files /dev/null and b/src/archive/tar/testdata/nil-uid.tar differ diff --git a/src/archive/tar/testdata/pax.tar b/src/archive/tar/testdata/pax.tar new file mode 100644 index 000000000..9bc24b658 Binary files /dev/null and b/src/archive/tar/testdata/pax.tar differ diff --git a/src/archive/tar/testdata/small.txt b/src/archive/tar/testdata/small.txt new file mode 100644 index 000000000..b249bfc51 --- /dev/null +++ b/src/archive/tar/testdata/small.txt @@ -0,0 +1 @@ +Kilts \ No newline at end of file diff --git a/src/archive/tar/testdata/small2.txt b/src/archive/tar/testdata/small2.txt new file mode 100644 index 000000000..394ee3ecd --- /dev/null +++ b/src/archive/tar/testdata/small2.txt @@ -0,0 +1 @@ +Google.com diff --git a/src/archive/tar/testdata/sparse-formats.tar b/src/archive/tar/testdata/sparse-formats.tar new file mode 100644 index 000000000..8bd4e74d5 Binary files /dev/null and b/src/archive/tar/testdata/sparse-formats.tar differ diff --git a/src/archive/tar/testdata/star.tar b/src/archive/tar/testdata/star.tar new file mode 100644 index 000000000..59e2d4e60 Binary files /dev/null and b/src/archive/tar/testdata/star.tar differ diff --git a/src/archive/tar/testdata/ustar.tar b/src/archive/tar/testdata/ustar.tar new file mode 100644 index 000000000..29679d9a3 Binary files /dev/null and b/src/archive/tar/testdata/ustar.tar differ diff --git a/src/archive/tar/testdata/v7.tar b/src/archive/tar/testdata/v7.tar new file mode 100644 index 000000000..eb65fc941 Binary files /dev/null and b/src/archive/tar/testdata/v7.tar differ diff --git a/src/archive/tar/testdata/writer-big-long.tar b/src/archive/tar/testdata/writer-big-long.tar new file mode 100644 index 000000000..5960ee824 Binary files /dev/null and b/src/archive/tar/testdata/writer-big-long.tar differ diff --git a/src/archive/tar/testdata/writer-big.tar b/src/archive/tar/testdata/writer-big.tar new file mode 100644 index 000000000..753e883ce Binary files /dev/null and b/src/archive/tar/testdata/writer-big.tar differ diff --git a/src/archive/tar/testdata/writer.tar b/src/archive/tar/testdata/writer.tar new file mode 100644 index 000000000..e6d816ad0 Binary files /dev/null and b/src/archive/tar/testdata/writer.tar differ diff --git a/src/archive/tar/testdata/xattrs.tar b/src/archive/tar/testdata/xattrs.tar new file mode 100644 index 000000000..9701950ed Binary files /dev/null and b/src/archive/tar/testdata/xattrs.tar differ diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go new file mode 100644 index 000000000..dafb2cabf --- /dev/null +++ b/src/archive/tar/writer.go @@ -0,0 +1,396 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tar + +// TODO(dsymonds): +// - catch more errors (no first header, etc.) + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + "path" + "strconv" + "strings" + "time" +) + +var ( + ErrWriteTooLong = errors.New("archive/tar: write too long") + ErrFieldTooLong = errors.New("archive/tar: header field too long") + ErrWriteAfterClose = errors.New("archive/tar: write after close") + errNameTooLong = errors.New("archive/tar: name too long") + errInvalidHeader = errors.New("archive/tar: header field too long or contains invalid values") +) + +// A Writer provides sequential writing of a tar archive in POSIX.1 format. +// A tar archive consists of a sequence of files. +// Call WriteHeader to begin a new file, and then call Write to supply that file's data, +// writing at most hdr.Size bytes in total. +type Writer struct { + w io.Writer + err error + nb int64 // number of unwritten bytes for current file entry + pad int64 // amount of padding to write after current file entry + closed bool + usedBinary bool // whether the binary numeric field extension was used + preferPax bool // use pax header instead of binary numeric header + hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header + paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header +} + +// NewWriter creates a new Writer writing to w. +func NewWriter(w io.Writer) *Writer { return &Writer{w: w} } + +// Flush finishes writing the current file (optional). +func (tw *Writer) Flush() error { + if tw.nb > 0 { + tw.err = fmt.Errorf("archive/tar: missed writing %d bytes", tw.nb) + return tw.err + } + + n := tw.nb + tw.pad + for n > 0 && tw.err == nil { + nr := n + if nr > blockSize { + nr = blockSize + } + var nw int + nw, tw.err = tw.w.Write(zeroBlock[0:nr]) + n -= int64(nw) + } + tw.nb = 0 + tw.pad = 0 + return tw.err +} + +// Write s into b, terminating it with a NUL if there is room. +// If the value is too long for the field and allowPax is true add a paxheader record instead +func (tw *Writer) cString(b []byte, s string, allowPax bool, paxKeyword string, paxHeaders map[string]string) { + needsPaxHeader := allowPax && len(s) > len(b) || !isASCII(s) + if needsPaxHeader { + paxHeaders[paxKeyword] = s + return + } + if len(s) > len(b) { + if tw.err == nil { + tw.err = ErrFieldTooLong + } + return + } + ascii := toASCII(s) + copy(b, ascii) + if len(ascii) < len(b) { + b[len(ascii)] = 0 + } +} + +// Encode x as an octal ASCII string and write it into b with leading zeros. +func (tw *Writer) octal(b []byte, x int64) { + s := strconv.FormatInt(x, 8) + // leading zeros, but leave room for a NUL. + for len(s)+1 < len(b) { + s = "0" + s + } + tw.cString(b, s, false, paxNone, nil) +} + +// Write x into b, either as octal or as binary (GNUtar/star extension). +// If the value is too long for the field and writingPax is enabled both for the field and the add a paxheader record instead +func (tw *Writer) numeric(b []byte, x int64, allowPax bool, paxKeyword string, paxHeaders map[string]string) { + // Try octal first. + s := strconv.FormatInt(x, 8) + if len(s) < len(b) { + tw.octal(b, x) + return + } + + // If it is too long for octal, and pax is preferred, use a pax header + if allowPax && tw.preferPax { + tw.octal(b, 0) + s := strconv.FormatInt(x, 10) + paxHeaders[paxKeyword] = s + return + } + + // Too big: use binary (big-endian). + tw.usedBinary = true + for i := len(b) - 1; x > 0 && i >= 0; i-- { + b[i] = byte(x) + x >>= 8 + } + b[0] |= 0x80 // highest bit indicates binary format +} + +var ( + minTime = time.Unix(0, 0) + // There is room for 11 octal digits (33 bits) of mtime. + maxTime = minTime.Add((1<<33 - 1) * time.Second) +) + +// WriteHeader writes hdr and prepares to accept the file's contents. +// WriteHeader calls Flush if it is not the first header. +// Calling after a Close will return ErrWriteAfterClose. +func (tw *Writer) WriteHeader(hdr *Header) error { + return tw.writeHeader(hdr, true) +} + +// WriteHeader writes hdr and prepares to accept the file's contents. +// WriteHeader calls Flush if it is not the first header. +// Calling after a Close will return ErrWriteAfterClose. +// As this method is called internally by writePax header to allow it to +// suppress writing the pax header. +func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error { + if tw.closed { + return ErrWriteAfterClose + } + if tw.err == nil { + tw.Flush() + } + if tw.err != nil { + return tw.err + } + + // a map to hold pax header records, if any are needed + paxHeaders := make(map[string]string) + + // TODO(shanemhansen): we might want to use PAX headers for + // subsecond time resolution, but for now let's just capture + // too long fields or non ascii characters + + var header []byte + + // We need to select which scratch buffer to use carefully, + // since this method is called recursively to write PAX headers. + // If allowPax is true, this is the non-recursive call, and we will use hdrBuff. + // If allowPax is false, we are being called by writePAXHeader, and hdrBuff is + // already being used by the non-recursive call, so we must use paxHdrBuff. + header = tw.hdrBuff[:] + if !allowPax { + header = tw.paxHdrBuff[:] + } + copy(header, zeroBlock) + s := slicer(header) + + // keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax + pathHeaderBytes := s.next(fileNameSize) + + tw.cString(pathHeaderBytes, hdr.Name, true, paxPath, paxHeaders) + + // Handle out of range ModTime carefully. + var modTime int64 + if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) { + modTime = hdr.ModTime.Unix() + } + + tw.octal(s.next(8), hdr.Mode) // 100:108 + tw.numeric(s.next(8), int64(hdr.Uid), true, paxUid, paxHeaders) // 108:116 + tw.numeric(s.next(8), int64(hdr.Gid), true, paxGid, paxHeaders) // 116:124 + tw.numeric(s.next(12), hdr.Size, true, paxSize, paxHeaders) // 124:136 + tw.numeric(s.next(12), modTime, false, paxNone, nil) // 136:148 --- consider using pax for finer granularity + s.next(8) // chksum (148:156) + s.next(1)[0] = hdr.Typeflag // 156:157 + + tw.cString(s.next(100), hdr.Linkname, true, paxLinkpath, paxHeaders) + + copy(s.next(8), []byte("ustar\x0000")) // 257:265 + tw.cString(s.next(32), hdr.Uname, true, paxUname, paxHeaders) // 265:297 + tw.cString(s.next(32), hdr.Gname, true, paxGname, paxHeaders) // 297:329 + tw.numeric(s.next(8), hdr.Devmajor, false, paxNone, nil) // 329:337 + tw.numeric(s.next(8), hdr.Devminor, false, paxNone, nil) // 337:345 + + // keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax + prefixHeaderBytes := s.next(155) + tw.cString(prefixHeaderBytes, "", false, paxNone, nil) // 345:500 prefix + + // Use the GNU magic instead of POSIX magic if we used any GNU extensions. + if tw.usedBinary { + copy(header[257:265], []byte("ustar \x00")) + } + + _, paxPathUsed := paxHeaders[paxPath] + // try to use a ustar header when only the name is too long + if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed { + suffix := hdr.Name + prefix := "" + if len(hdr.Name) > fileNameSize && isASCII(hdr.Name) { + var err error + prefix, suffix, err = tw.splitUSTARLongName(hdr.Name) + if err == nil { + // ok we can use a ustar long name instead of pax, now correct the fields + + // remove the path field from the pax header. this will suppress the pax header + delete(paxHeaders, paxPath) + + // update the path fields + tw.cString(pathHeaderBytes, suffix, false, paxNone, nil) + tw.cString(prefixHeaderBytes, prefix, false, paxNone, nil) + + // Use the ustar magic if we used ustar long names. + if len(prefix) > 0 && !tw.usedBinary { + copy(header[257:265], []byte("ustar\x00")) + } + } + } + } + + // The chksum field is terminated by a NUL and a space. + // This is different from the other octal fields. + chksum, _ := checksum(header) + tw.octal(header[148:155], chksum) + header[155] = ' ' + + if tw.err != nil { + // problem with header; probably integer too big for a field. + return tw.err + } + + if allowPax { + for k, v := range hdr.Xattrs { + paxHeaders[paxXattr+k] = v + } + } + + if len(paxHeaders) > 0 { + if !allowPax { + return errInvalidHeader + } + if err := tw.writePAXHeader(hdr, paxHeaders); err != nil { + return err + } + } + tw.nb = int64(hdr.Size) + tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize + + _, tw.err = tw.w.Write(header) + return tw.err +} + +// writeUSTARLongName splits a USTAR long name hdr.Name. +// name must be < 256 characters. errNameTooLong is returned +// if hdr.Name can't be split. The splitting heuristic +// is compatible with gnu tar. +func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err error) { + length := len(name) + if length > fileNamePrefixSize+1 { + length = fileNamePrefixSize + 1 + } else if name[length-1] == '/' { + length-- + } + i := strings.LastIndex(name[:length], "/") + // nlen contains the resulting length in the name field. + // plen contains the resulting length in the prefix field. + nlen := len(name) - i - 1 + plen := i + if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize { + err = errNameTooLong + return + } + prefix, suffix = name[:i], name[i+1:] + return +} + +// writePaxHeader writes an extended pax header to the +// archive. +func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) error { + // Prepare extended header + ext := new(Header) + ext.Typeflag = TypeXHeader + // Setting ModTime is required for reader parsing to + // succeed, and seems harmless enough. + ext.ModTime = hdr.ModTime + // The spec asks that we namespace our pseudo files + // with the current pid. + pid := os.Getpid() + dir, file := path.Split(hdr.Name) + fullName := path.Join(dir, + fmt.Sprintf("PaxHeaders.%d", pid), file) + + ascii := toASCII(fullName) + if len(ascii) > 100 { + ascii = ascii[:100] + } + ext.Name = ascii + // Construct the body + var buf bytes.Buffer + + for k, v := range paxHeaders { + fmt.Fprint(&buf, paxHeader(k+"="+v)) + } + + ext.Size = int64(len(buf.Bytes())) + if err := tw.writeHeader(ext, false); err != nil { + return err + } + if _, err := tw.Write(buf.Bytes()); err != nil { + return err + } + if err := tw.Flush(); err != nil { + return err + } + return nil +} + +// paxHeader formats a single pax record, prefixing it with the appropriate length +func paxHeader(msg string) string { + const padding = 2 // Extra padding for space and newline + size := len(msg) + padding + size += len(strconv.Itoa(size)) + record := fmt.Sprintf("%d %s\n", size, msg) + if len(record) != size { + // Final adjustment if adding size increased + // the number of digits in size + size = len(record) + record = fmt.Sprintf("%d %s\n", size, msg) + } + return record +} + +// Write writes to the current entry in the tar archive. +// Write returns the error ErrWriteTooLong if more than +// hdr.Size bytes are written after WriteHeader. +func (tw *Writer) Write(b []byte) (n int, err error) { + if tw.closed { + err = ErrWriteTooLong + return + } + overwrite := false + if int64(len(b)) > tw.nb { + b = b[0:tw.nb] + overwrite = true + } + n, err = tw.w.Write(b) + tw.nb -= int64(n) + if err == nil && overwrite { + err = ErrWriteTooLong + return + } + tw.err = err + return +} + +// Close closes the tar archive, flushing any unwritten +// data to the underlying writer. +func (tw *Writer) Close() error { + if tw.err != nil || tw.closed { + return tw.err + } + tw.Flush() + tw.closed = true + if tw.err != nil { + return tw.err + } + + // trailer: two zero blocks + for i := 0; i < 2; i++ { + _, tw.err = tw.w.Write(zeroBlock) + if tw.err != nil { + break + } + } + return tw.err +} diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go new file mode 100644 index 000000000..5e42e322f --- /dev/null +++ b/src/archive/tar/writer_test.go @@ -0,0 +1,491 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tar + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "reflect" + "strings" + "testing" + "testing/iotest" + "time" +) + +type writerTestEntry struct { + header *Header + contents string +} + +type writerTest struct { + file string // filename of expected output + entries []*writerTestEntry +} + +var writerTests = []*writerTest{ + // The writer test file was produced with this command: + // tar (GNU tar) 1.26 + // ln -s small.txt link.txt + // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt + { + file: "testdata/writer.tar", + entries: []*writerTestEntry{ + { + header: &Header{ + Name: "small.txt", + Mode: 0640, + Uid: 73025, + Gid: 5000, + Size: 5, + ModTime: time.Unix(1246508266, 0), + Typeflag: '0', + Uname: "dsymonds", + Gname: "eng", + }, + contents: "Kilts", + }, + { + header: &Header{ + Name: "small2.txt", + Mode: 0640, + Uid: 73025, + Gid: 5000, + Size: 11, + ModTime: time.Unix(1245217492, 0), + Typeflag: '0', + Uname: "dsymonds", + Gname: "eng", + }, + contents: "Google.com\n", + }, + { + header: &Header{ + Name: "link.txt", + Mode: 0777, + Uid: 1000, + Gid: 1000, + Size: 0, + ModTime: time.Unix(1314603082, 0), + Typeflag: '2', + Linkname: "small.txt", + Uname: "strings", + Gname: "strings", + }, + // no contents + }, + }, + }, + // The truncated test file was produced using these commands: + // dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt + // tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar + { + file: "testdata/writer-big.tar", + entries: []*writerTestEntry{ + { + header: &Header{ + Name: "tmp/16gig.txt", + Mode: 0640, + Uid: 73025, + Gid: 5000, + Size: 16 << 30, + ModTime: time.Unix(1254699560, 0), + Typeflag: '0', + Uname: "dsymonds", + Gname: "eng", + }, + // fake contents + contents: strings.Repeat("\x00", 4<<10), + }, + }, + }, + // The truncated test file was produced using these commands: + // dd if=/dev/zero bs=1048576 count=16384 > (longname/)*15 /16gig.txt + // tar -b 1 -c -f- (longname/)*15 /16gig.txt | dd bs=512 count=8 > writer-big-long.tar + { + file: "testdata/writer-big-long.tar", + entries: []*writerTestEntry{ + { + header: &Header{ + Name: strings.Repeat("longname/", 15) + "16gig.txt", + Mode: 0644, + Uid: 1000, + Gid: 1000, + Size: 16 << 30, + ModTime: time.Unix(1399583047, 0), + Typeflag: '0', + Uname: "guillaume", + Gname: "guillaume", + }, + // fake contents + contents: strings.Repeat("\x00", 4<<10), + }, + }, + }, + // This file was produced using gnu tar 1.17 + // gnutar -b 4 --format=ustar (longname/)*15 + file.txt + { + file: "testdata/ustar.tar", + entries: []*writerTestEntry{ + { + header: &Header{ + Name: strings.Repeat("longname/", 15) + "file.txt", + Mode: 0644, + Uid: 0765, + Gid: 024, + Size: 06, + ModTime: time.Unix(1360135598, 0), + Typeflag: '0', + Uname: "shane", + Gname: "staff", + }, + contents: "hello\n", + }, + }, + }, +} + +// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection. +func bytestr(offset int, b []byte) string { + const rowLen = 32 + s := fmt.Sprintf("%04x ", offset) + for _, ch := range b { + switch { + case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z': + s += fmt.Sprintf(" %c", ch) + default: + s += fmt.Sprintf(" %02x", ch) + } + } + return s +} + +// Render a pseudo-diff between two blocks of bytes. +func bytediff(a []byte, b []byte) string { + const rowLen = 32 + s := fmt.Sprintf("(%d bytes vs. %d bytes)\n", len(a), len(b)) + for offset := 0; len(a)+len(b) > 0; offset += rowLen { + na, nb := rowLen, rowLen + if na > len(a) { + na = len(a) + } + if nb > len(b) { + nb = len(b) + } + sa := bytestr(offset, a[0:na]) + sb := bytestr(offset, b[0:nb]) + if sa != sb { + s += fmt.Sprintf("-%v\n+%v\n", sa, sb) + } + a = a[na:] + b = b[nb:] + } + return s +} + +func TestWriter(t *testing.T) { +testLoop: + for i, test := range writerTests { + expected, err := ioutil.ReadFile(test.file) + if err != nil { + t.Errorf("test %d: Unexpected error: %v", i, err) + continue + } + + buf := new(bytes.Buffer) + tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB + big := false + for j, entry := range test.entries { + big = big || entry.header.Size > 1<<10 + if err := tw.WriteHeader(entry.header); err != nil { + t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err) + continue testLoop + } + if _, err := io.WriteString(tw, entry.contents); err != nil { + t.Errorf("test %d, entry %d: Failed writing contents: %v", i, j, err) + continue testLoop + } + } + // Only interested in Close failures for the small tests. + if err := tw.Close(); err != nil && !big { + t.Errorf("test %d: Failed closing archive: %v", i, err) + continue testLoop + } + + actual := buf.Bytes() + if !bytes.Equal(expected, actual) { + t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v", + i, bytediff(expected, actual)) + } + if testing.Short() { // The second test is expensive. + break + } + } +} + +func TestPax(t *testing.T) { + // Create an archive with a large name + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + hdr, err := FileInfoHeader(fileinfo, "") + if err != nil { + t.Fatalf("os.Stat: %v", err) + } + // Force a PAX long name to be written + longName := strings.Repeat("ab", 100) + contents := strings.Repeat(" ", int(hdr.Size)) + hdr.Name = longName + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if _, err = writer.Write([]byte(contents)); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Simple test to make sure PAX extensions are in effect + if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) { + t.Fatal("Expected at least one PAX header to be written.") + } + // Test that we can get a long name back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if hdr.Name != longName { + t.Fatal("Couldn't recover long file name") + } +} + +func TestPaxSymlink(t *testing.T) { + // Create an archive with a large linkname + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + hdr, err := FileInfoHeader(fileinfo, "") + hdr.Typeflag = TypeSymlink + if err != nil { + t.Fatalf("os.Stat:1 %v", err) + } + // Force a PAX long linkname to be written + longLinkname := strings.Repeat("1234567890/1234567890", 10) + hdr.Linkname = longLinkname + + hdr.Size = 0 + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Simple test to make sure PAX extensions are in effect + if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) { + t.Fatal("Expected at least one PAX header to be written.") + } + // Test that we can get a long name back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if hdr.Linkname != longLinkname { + t.Fatal("Couldn't recover long link name") + } +} + +func TestPaxNonAscii(t *testing.T) { + // Create an archive with non ascii. These should trigger a pax header + // because pax headers have a defined utf-8 encoding. + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + + hdr, err := FileInfoHeader(fileinfo, "") + if err != nil { + t.Fatalf("os.Stat:1 %v", err) + } + + // some sample data + chineseFilename := "文件名" + chineseGroupname := "組" + chineseUsername := "用戶名" + + hdr.Name = chineseFilename + hdr.Gname = chineseGroupname + hdr.Uname = chineseUsername + + contents := strings.Repeat(" ", int(hdr.Size)) + + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if _, err = writer.Write([]byte(contents)); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Simple test to make sure PAX extensions are in effect + if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) { + t.Fatal("Expected at least one PAX header to be written.") + } + // Test that we can get a long name back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if hdr.Name != chineseFilename { + t.Fatal("Couldn't recover unicode name") + } + if hdr.Gname != chineseGroupname { + t.Fatal("Couldn't recover unicode group") + } + if hdr.Uname != chineseUsername { + t.Fatal("Couldn't recover unicode user") + } +} + +func TestPaxXattrs(t *testing.T) { + xattrs := map[string]string{ + "user.key": "value", + } + + // Create an archive with an xattr + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + hdr, err := FileInfoHeader(fileinfo, "") + if err != nil { + t.Fatalf("os.Stat: %v", err) + } + contents := "Kilts" + hdr.Xattrs = xattrs + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if _, err = writer.Write([]byte(contents)); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Test that we can get the xattrs back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(hdr.Xattrs, xattrs) { + t.Fatalf("xattrs did not survive round trip: got %+v, want %+v", + hdr.Xattrs, xattrs) + } +} + +func TestPAXHeader(t *testing.T) { + medName := strings.Repeat("CD", 50) + longName := strings.Repeat("AB", 100) + paxTests := [][2]string{ + {paxPath + "=/etc/hosts", "19 path=/etc/hosts\n"}, + {"a=b", "6 a=b\n"}, // Single digit length + {"a=names", "11 a=names\n"}, // Test case involving carries + {paxPath + "=" + longName, fmt.Sprintf("210 path=%s\n", longName)}, + {paxPath + "=" + medName, fmt.Sprintf("110 path=%s\n", medName)}} + + for _, test := range paxTests { + key, expected := test[0], test[1] + if result := paxHeader(key); result != expected { + t.Fatalf("paxHeader: got %s, expected %s", result, expected) + } + } +} + +func TestUSTARLongName(t *testing.T) { + // Create an archive with a path that failed to split with USTAR extension in previous versions. + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + hdr, err := FileInfoHeader(fileinfo, "") + hdr.Typeflag = TypeDir + if err != nil { + t.Fatalf("os.Stat:1 %v", err) + } + // Force a PAX long name to be written. The name was taken from a practical example + // that fails and replaced ever char through numbers to anonymize the sample. + longName := "/0000_0000000/00000-000000000/0000_0000000/00000-0000000000000/0000_0000000/00000-0000000-00000000/0000_0000000/00000000/0000_0000000/000/0000_0000000/00000000v00/0000_0000000/000000/0000_0000000/0000000/0000_0000000/00000y-00/0000/0000/00000000/0x000000/" + hdr.Name = longName + + hdr.Size = 0 + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Test that we can get a long name back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if hdr.Name != longName { + t.Fatal("Couldn't recover long name") + } +} + +func TestValidTypeflagWithPAXHeader(t *testing.T) { + var buffer bytes.Buffer + tw := NewWriter(&buffer) + + fileName := strings.Repeat("ab", 100) + + hdr := &Header{ + Name: fileName, + Size: 4, + Typeflag: 0, + } + if err := tw.WriteHeader(hdr); err != nil { + t.Fatalf("Failed to write header: %s", err) + } + if _, err := tw.Write([]byte("fooo")); err != nil { + t.Fatalf("Failed to write the file's data: %s", err) + } + tw.Close() + + tr := NewReader(&buffer) + + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("Failed to read header: %s", err) + } + if header.Typeflag != 0 { + t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag) + } + } +} diff --git a/src/archive/zip/example_test.go b/src/archive/zip/example_test.go new file mode 100644 index 000000000..c2ed9e79c --- /dev/null +++ b/src/archive/zip/example_test.go @@ -0,0 +1,75 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package zip_test + +import ( + "archive/zip" + "bytes" + "fmt" + "io" + "log" + "os" +) + +func ExampleWriter() { + // Create a buffer to write our archive to. + buf := new(bytes.Buffer) + + // Create a new zip archive. + w := zip.NewWriter(buf) + + // Add some files to the archive. + var files = []struct { + Name, Body string + }{ + {"readme.txt", "This archive contains some text files."}, + {"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"}, + {"todo.txt", "Get animal handling licence.\nWrite more examples."}, + } + for _, file := range files { + f, err := w.Create(file.Name) + if err != nil { + log.Fatal(err) + } + _, err = f.Write([]byte(file.Body)) + if err != nil { + log.Fatal(err) + } + } + + // Make sure to check the error on Close. + err := w.Close() + if err != nil { + log.Fatal(err) + } +} + +func ExampleReader() { + // Open a zip archive for reading. + r, err := zip.OpenReader("testdata/readme.zip") + if err != nil { + log.Fatal(err) + } + defer r.Close() + + // Iterate through the files in the archive, + // printing some of their contents. + for _, f := range r.File { + fmt.Printf("Contents of %s:\n", f.Name) + rc, err := f.Open() + if err != nil { + log.Fatal(err) + } + _, err = io.CopyN(os.Stdout, rc, 68) + if err != nil { + log.Fatal(err) + } + rc.Close() + fmt.Println() + } + // Output: + // Contents of README: + // This is the source code repository for the Go programming language. +} diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go new file mode 100644 index 000000000..8136b840d --- /dev/null +++ b/src/archive/zip/reader.go @@ -0,0 +1,453 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package zip + +import ( + "bufio" + "encoding/binary" + "errors" + "hash" + "hash/crc32" + "io" + "os" +) + +var ( + ErrFormat = errors.New("zip: not a valid zip file") + ErrAlgorithm = errors.New("zip: unsupported compression algorithm") + ErrChecksum = errors.New("zip: checksum error") +) + +type Reader struct { + r io.ReaderAt + File []*File + Comment string +} + +type ReadCloser struct { + f *os.File + Reader +} + +type File struct { + FileHeader + zipr io.ReaderAt + zipsize int64 + headerOffset int64 +} + +func (f *File) hasDataDescriptor() bool { + return f.Flags&0x8 != 0 +} + +// OpenReader will open the Zip file specified by name and return a ReadCloser. +func OpenReader(name string) (*ReadCloser, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + fi, err := f.Stat() + if err != nil { + f.Close() + return nil, err + } + r := new(ReadCloser) + if err := r.init(f, fi.Size()); err != nil { + f.Close() + return nil, err + } + r.f = f + return r, nil +} + +// NewReader returns a new Reader reading from r, which is assumed to +// have the given size in bytes. +func NewReader(r io.ReaderAt, size int64) (*Reader, error) { + zr := new(Reader) + if err := zr.init(r, size); err != nil { + return nil, err + } + return zr, nil +} + +func (z *Reader) init(r io.ReaderAt, size int64) error { + end, err := readDirectoryEnd(r, size) + if err != nil { + return err + } + z.r = r + z.File = make([]*File, 0, end.directoryRecords) + z.Comment = end.comment + rs := io.NewSectionReader(r, 0, size) + if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil { + return err + } + buf := bufio.NewReader(rs) + + // The count of files inside a zip is truncated to fit in a uint16. + // Gloss over this by reading headers until we encounter + // a bad one, and then only report a ErrFormat or UnexpectedEOF if + // the file count modulo 65536 is incorrect. + for { + f := &File{zipr: r, zipsize: size} + err = readDirectoryHeader(f, buf) + if err == ErrFormat || err == io.ErrUnexpectedEOF { + break + } + if err != nil { + return err + } + z.File = append(z.File, f) + } + if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here + // Return the readDirectoryHeader error if we read + // the wrong number of directory entries. + return err + } + return nil +} + +// Close closes the Zip file, rendering it unusable for I/O. +func (rc *ReadCloser) Close() error { + return rc.f.Close() +} + +// DataOffset returns the offset of the file's possibly-compressed +// data, relative to the beginning of the zip file. +// +// Most callers should instead use Open, which transparently +// decompresses data and verifies checksums. +func (f *File) DataOffset() (offset int64, err error) { + bodyOffset, err := f.findBodyOffset() + if err != nil { + return + } + return f.headerOffset + bodyOffset, nil +} + +// Open returns a ReadCloser that provides access to the File's contents. +// Multiple files may be read concurrently. +func (f *File) Open() (rc io.ReadCloser, err error) { + bodyOffset, err := f.findBodyOffset() + if err != nil { + return + } + size := int64(f.CompressedSize64) + r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size) + dcomp := decompressor(f.Method) + if dcomp == nil { + err = ErrAlgorithm + return + } + rc = dcomp(r) + var desr io.Reader + if f.hasDataDescriptor() { + desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen) + } + rc = &checksumReader{rc, crc32.NewIEEE(), f, desr, nil} + 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 +} + +func (r *checksumReader) Read(b []byte) (n int, err error) { + if r.err != nil { + return 0, r.err + } + n, err = r.rc.Read(b) + r.hash.Write(b[:n]) + if err == nil { + return + } + if err == io.EOF { + if r.desr != nil { + if err1 := readDataDescriptor(r.desr, r.f); err1 != nil { + err = err1 + } else if r.hash.Sum32() != r.f.CRC32 { + err = ErrChecksum + } + } else { + // If there's not a data descriptor, we still compare + // the CRC32 of what we've read against the file header + // or TOC's CRC32, if it seems like it was set. + if r.f.CRC32 != 0 && r.hash.Sum32() != r.f.CRC32 { + err = ErrChecksum + } + } + } + r.err = err + return +} + +func (r *checksumReader) Close() error { return r.rc.Close() } + +// findBodyOffset does the minimum work to verify the file has a header +// and returns the file body offset. +func (f *File) findBodyOffset() (int64, error) { + var buf [fileHeaderLen]byte + if _, err := f.zipr.ReadAt(buf[:], f.headerOffset); err != nil { + return 0, err + } + b := readBuf(buf[:]) + if sig := b.uint32(); sig != fileHeaderSignature { + return 0, ErrFormat + } + b = b[22:] // skip over most of the header + filenameLen := int(b.uint16()) + extraLen := int(b.uint16()) + return int64(fileHeaderLen + filenameLen + extraLen), nil +} + +// readDirectoryHeader attempts to read a directory header from r. +// It returns io.ErrUnexpectedEOF if it cannot read a complete header, +// and ErrFormat if it doesn't find a valid header signature. +func readDirectoryHeader(f *File, r io.Reader) error { + var buf [directoryHeaderLen]byte + if _, err := io.ReadFull(r, buf[:]); err != nil { + return err + } + b := readBuf(buf[:]) + if sig := b.uint32(); sig != directoryHeaderSignature { + return ErrFormat + } + f.CreatorVersion = b.uint16() + f.ReaderVersion = b.uint16() + f.Flags = b.uint16() + f.Method = b.uint16() + f.ModifiedTime = b.uint16() + f.ModifiedDate = b.uint16() + f.CRC32 = b.uint32() + f.CompressedSize = b.uint32() + f.UncompressedSize = b.uint32() + f.CompressedSize64 = uint64(f.CompressedSize) + f.UncompressedSize64 = uint64(f.UncompressedSize) + filenameLen := int(b.uint16()) + extraLen := int(b.uint16()) + commentLen := int(b.uint16()) + b = b[4:] // skipped start disk number and internal attributes (2x uint16) + f.ExternalAttrs = b.uint32() + f.headerOffset = int64(b.uint32()) + d := make([]byte, filenameLen+extraLen+commentLen) + if _, err := io.ReadFull(r, d); err != nil { + return err + } + f.Name = string(d[:filenameLen]) + f.Extra = d[filenameLen : filenameLen+extraLen] + f.Comment = string(d[filenameLen+extraLen:]) + + if len(f.Extra) > 0 { + b := readBuf(f.Extra) + for len(b) >= 4 { // need at least tag and size + tag := b.uint16() + size := b.uint16() + if int(size) > len(b) { + return ErrFormat + } + if tag == zip64ExtraId { + // update directory values from the zip64 extra block + eb := readBuf(b[:size]) + if len(eb) >= 8 { + f.UncompressedSize64 = eb.uint64() + } + if len(eb) >= 8 { + f.CompressedSize64 = eb.uint64() + } + if len(eb) >= 8 { + f.headerOffset = int64(eb.uint64()) + } + } + b = b[size:] + } + // Should have consumed the whole header. + // But popular zip & JAR creation tools are broken and + // may pad extra zeros at the end, so accept those + // too. See golang.org/issue/8186. + for _, v := range b { + if v != 0 { + return ErrFormat + } + } + } + return nil +} + +func readDataDescriptor(r io.Reader, f *File) error { + var buf [dataDescriptorLen]byte + + // The spec says: "Although not originally assigned a + // signature, the value 0x08074b50 has commonly been adopted + // as a signature value for the data descriptor record. + // Implementers should be aware that ZIP files may be + // encountered with or without this signature marking data + // descriptors and should account for either case when reading + // ZIP files to ensure compatibility." + // + // dataDescriptorLen includes the size of the signature but + // first read just those 4 bytes to see if it exists. + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + off := 0 + maybeSig := readBuf(buf[:4]) + if maybeSig.uint32() != dataDescriptorSignature { + // No data descriptor signature. Keep these four + // bytes. + off += 4 + } + if _, err := io.ReadFull(r, buf[off:12]); err != nil { + return err + } + b := readBuf(buf[:12]) + if b.uint32() != f.CRC32 { + return ErrChecksum + } + + // The two sizes that follow here can be either 32 bits or 64 bits + // but the spec is not very clear on this and different + // interpretations has been made causing incompatibilities. We + // already have the sizes from the central directory so we can + // just ignore these. + + return nil +} + +func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) { + // look for directoryEndSignature in the last 1k, then in the last 65k + var buf []byte + var directoryEndOffset int64 + for i, bLen := range []int64{1024, 65 * 1024} { + if bLen > size { + bLen = size + } + buf = make([]byte, int(bLen)) + if _, err := r.ReadAt(buf, size-bLen); err != nil && err != io.EOF { + return nil, err + } + if p := findSignatureInBlock(buf); p >= 0 { + buf = buf[p:] + directoryEndOffset = size - bLen + int64(p) + break + } + if i == 1 || bLen == size { + return nil, ErrFormat + } + } + + // read header into struct + b := readBuf(buf[4:]) // skip signature + d := &directoryEnd{ + diskNbr: uint32(b.uint16()), + dirDiskNbr: uint32(b.uint16()), + dirRecordsThisDisk: uint64(b.uint16()), + directoryRecords: uint64(b.uint16()), + directorySize: uint64(b.uint32()), + directoryOffset: uint64(b.uint32()), + commentLen: b.uint16(), + } + l := int(d.commentLen) + if l > len(b) { + return nil, errors.New("zip: invalid comment length") + } + d.comment = string(b[:l]) + + p, err := findDirectory64End(r, directoryEndOffset) + if err == nil && p >= 0 { + err = readDirectory64End(r, p, d) + } + if err != nil { + return nil, err + } + + // Make sure directoryOffset points to somewhere in our file. + if o := int64(d.directoryOffset); o < 0 || o >= size { + return nil, ErrFormat + } + return d, nil +} + +// findDirectory64End tries to read the zip64 locator just before the +// directory end and returns the offset of the zip64 directory end if +// found. +func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error) { + locOffset := directoryEndOffset - directory64LocLen + if locOffset < 0 { + return -1, nil // no need to look for a header outside the file + } + buf := make([]byte, directory64LocLen) + if _, err := r.ReadAt(buf, locOffset); err != nil { + return -1, err + } + b := readBuf(buf) + if sig := b.uint32(); sig != directory64LocSignature { + return -1, nil + } + b = b[4:] // skip number of the disk with the start of the zip64 end of central directory + p := b.uint64() // relative offset of the zip64 end of central directory record + return int64(p), nil +} + +// readDirectory64End reads the zip64 directory end and updates the +// directory end with the zip64 directory end values. +func readDirectory64End(r io.ReaderAt, offset int64, d *directoryEnd) (err error) { + buf := make([]byte, directory64EndLen) + if _, err := r.ReadAt(buf, offset); err != nil { + return err + } + + b := readBuf(buf) + if sig := b.uint32(); sig != directory64EndSignature { + return ErrFormat + } + + b = b[12:] // skip dir size, version and version needed (uint64 + 2x uint16) + d.diskNbr = b.uint32() // number of this disk + d.dirDiskNbr = b.uint32() // number of the disk with the start of the central directory + d.dirRecordsThisDisk = b.uint64() // total number of entries in the central directory on this disk + d.directoryRecords = b.uint64() // total number of entries in the central directory + d.directorySize = b.uint64() // size of the central directory + d.directoryOffset = b.uint64() // offset of start of central directory with respect to the starting disk number + + return nil +} + +func findSignatureInBlock(b []byte) int { + for i := len(b) - directoryEndLen; i >= 0; i-- { + // defined from directoryEndSignature in struct.go + if b[i] == 'P' && b[i+1] == 'K' && b[i+2] == 0x05 && b[i+3] == 0x06 { + // n is length of comment + n := int(b[i+directoryEndLen-2]) | int(b[i+directoryEndLen-1])<<8 + if n+directoryEndLen+i <= len(b) { + return i + } + } + } + return -1 +} + +type readBuf []byte + +func (b *readBuf) uint16() uint16 { + v := binary.LittleEndian.Uint16(*b) + *b = (*b)[2:] + return v +} + +func (b *readBuf) uint32() uint32 { + v := binary.LittleEndian.Uint32(*b) + *b = (*b)[4:] + return v +} + +func (b *readBuf) uint64() uint64 { + v := binary.LittleEndian.Uint64(*b) + *b = (*b)[8:] + return v +} diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go new file mode 100644 index 000000000..29d0652dc --- /dev/null +++ b/src/archive/zip/reader_test.go @@ -0,0 +1,533 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package zip + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "io" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" + "testing" + "time" +) + +type ZipTest struct { + Name string + Source func() (r io.ReaderAt, size int64) // if non-nil, used instead of testdata/ file + Comment string + File []ZipTestFile + Error error // the error that Opening this file should return +} + +type ZipTestFile struct { + Name string + Content []byte // if blank, will attempt to compare against File + ContentErr error + File string // name of file to compare to (relative to testdata/) + Mtime string // modified time in format "mm-dd-yy hh:mm:ss" + Mode os.FileMode +} + +// Caution: The Mtime values found for the test files should correspond to +// the values listed with unzip -l . However, the values +// listed by unzip appear to be off by some hours. When creating +// fresh test files and testing them, this issue is not present. +// The test files were created in Sydney, so there might be a time +// zone issue. The time zone information does have to be encoded +// somewhere, because otherwise unzip -l could not provide a different +// time from what the archive/zip package provides, but there appears +// to be no documentation about this. + +var tests = []ZipTest{ + { + Name: "test.zip", + Comment: "This is a zipfile comment.", + File: []ZipTestFile{ + { + Name: "test.txt", + Content: []byte("This is a test text file.\n"), + Mtime: "09-05-10 12:12:02", + Mode: 0644, + }, + { + Name: "gophercolor16x16.png", + File: "gophercolor16x16.png", + Mtime: "09-05-10 15:52:58", + Mode: 0644, + }, + }, + }, + { + Name: "test-trailing-junk.zip", + Comment: "This is a zipfile comment.", + File: []ZipTestFile{ + { + Name: "test.txt", + Content: []byte("This is a test text file.\n"), + Mtime: "09-05-10 12:12:02", + Mode: 0644, + }, + { + Name: "gophercolor16x16.png", + File: "gophercolor16x16.png", + Mtime: "09-05-10 15:52:58", + Mode: 0644, + }, + }, + }, + { + Name: "r.zip", + Source: returnRecursiveZip, + File: []ZipTestFile{ + { + Name: "r/r.zip", + Content: rZipBytes(), + Mtime: "03-04-10 00:24:16", + Mode: 0666, + }, + }, + }, + { + Name: "symlink.zip", + File: []ZipTestFile{ + { + Name: "symlink", + Content: []byte("../target"), + Mode: 0777 | os.ModeSymlink, + }, + }, + }, + { + Name: "readme.zip", + }, + { + Name: "readme.notzip", + Error: ErrFormat, + }, + { + Name: "dd.zip", + File: []ZipTestFile{ + { + Name: "filename", + Content: []byte("This is a test textfile.\n"), + Mtime: "02-02-11 13:06:20", + Mode: 0666, + }, + }, + }, + { + // created in windows XP file manager. + Name: "winxp.zip", + File: crossPlatform, + }, + { + // created by Zip 3.0 under Linux + Name: "unix.zip", + File: crossPlatform, + }, + { + // created by Go, before we wrote the "optional" data + // descriptor signatures (which are required by OS X) + Name: "go-no-datadesc-sig.zip", + File: []ZipTestFile{ + { + Name: "foo.txt", + Content: []byte("foo\n"), + Mtime: "03-08-12 16:59:10", + Mode: 0644, + }, + { + Name: "bar.txt", + Content: []byte("bar\n"), + Mtime: "03-08-12 16:59:12", + Mode: 0644, + }, + }, + }, + { + // created by Go, after we wrote the "optional" data + // descriptor signatures (which are required by OS X) + Name: "go-with-datadesc-sig.zip", + File: []ZipTestFile{ + { + Name: "foo.txt", + Content: []byte("foo\n"), + Mode: 0666, + }, + { + Name: "bar.txt", + Content: []byte("bar\n"), + Mode: 0666, + }, + }, + }, + { + Name: "Bad-CRC32-in-data-descriptor", + Source: returnCorruptCRC32Zip, + File: []ZipTestFile{ + { + Name: "foo.txt", + Content: []byte("foo\n"), + Mode: 0666, + ContentErr: ErrChecksum, + }, + { + Name: "bar.txt", + Content: []byte("bar\n"), + Mode: 0666, + }, + }, + }, + // Tests that we verify (and accept valid) crc32s on files + // with crc32s in their file header (not in data descriptors) + { + Name: "crc32-not-streamed.zip", + File: []ZipTestFile{ + { + Name: "foo.txt", + Content: []byte("foo\n"), + Mtime: "03-08-12 16:59:10", + Mode: 0644, + }, + { + Name: "bar.txt", + Content: []byte("bar\n"), + Mtime: "03-08-12 16:59:12", + Mode: 0644, + }, + }, + }, + // Tests that we verify (and reject invalid) crc32s on files + // with crc32s in their file header (not in data descriptors) + { + Name: "crc32-not-streamed.zip", + Source: returnCorruptNotStreamedZip, + File: []ZipTestFile{ + { + Name: "foo.txt", + Content: []byte("foo\n"), + Mtime: "03-08-12 16:59:10", + Mode: 0644, + ContentErr: ErrChecksum, + }, + { + Name: "bar.txt", + Content: []byte("bar\n"), + Mtime: "03-08-12 16:59:12", + Mode: 0644, + }, + }, + }, + { + Name: "zip64.zip", + File: []ZipTestFile{ + { + Name: "README", + Content: []byte("This small file is in ZIP64 format.\n"), + Mtime: "08-10-12 14:33:32", + Mode: 0644, + }, + }, + }, + // Another zip64 file with different Extras fields. (golang.org/issue/7069) + { + Name: "zip64-2.zip", + File: []ZipTestFile{ + { + Name: "README", + Content: []byte("This small file is in ZIP64 format.\n"), + Mtime: "08-10-12 14:33:32", + Mode: 0644, + }, + }, + }, +} + +var crossPlatform = []ZipTestFile{ + { + Name: "hello", + Content: []byte("world \r\n"), + Mode: 0666, + }, + { + Name: "dir/bar", + Content: []byte("foo \r\n"), + Mode: 0666, + }, + { + Name: "dir/empty/", + Content: []byte{}, + Mode: os.ModeDir | 0777, + }, + { + Name: "readonly", + Content: []byte("important \r\n"), + Mode: 0444, + }, +} + +func TestReader(t *testing.T) { + for _, zt := range tests { + readTestZip(t, zt) + } +} + +func readTestZip(t *testing.T, zt ZipTest) { + var z *Reader + var err error + if zt.Source != nil { + rat, size := zt.Source() + z, err = NewReader(rat, size) + } else { + var rc *ReadCloser + rc, err = OpenReader(filepath.Join("testdata", zt.Name)) + if err == nil { + defer rc.Close() + z = &rc.Reader + } + } + if err != zt.Error { + t.Errorf("%s: error=%v, want %v", zt.Name, err, zt.Error) + return + } + + // bail if file is not zip + if err == ErrFormat { + return + } + + // bail here if no Files expected to be tested + // (there may actually be files in the zip, but we don't care) + if zt.File == nil { + return + } + + if z.Comment != zt.Comment { + t.Errorf("%s: comment=%q, want %q", zt.Name, z.Comment, zt.Comment) + } + if len(z.File) != len(zt.File) { + t.Fatalf("%s: file count=%d, want %d", zt.Name, len(z.File), len(zt.File)) + } + + // test read of each file + for i, ft := range zt.File { + readTestFile(t, zt, ft, z.File[i]) + } + + // test simultaneous reads + n := 0 + done := make(chan bool) + for i := 0; i < 5; i++ { + for j, ft := range zt.File { + go func(j int, ft ZipTestFile) { + readTestFile(t, zt, ft, z.File[j]) + done <- true + }(j, ft) + n++ + } + } + for ; n > 0; n-- { + <-done + } +} + +func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { + if f.Name != ft.Name { + t.Errorf("%s: name=%q, want %q", zt.Name, f.Name, ft.Name) + } + + if ft.Mtime != "" { + mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime) + if err != nil { + t.Error(err) + return + } + if ft := f.ModTime(); !ft.Equal(mtime) { + t.Errorf("%s: %s: mtime=%s, want %s", zt.Name, f.Name, ft, mtime) + } + } + + testFileMode(t, zt.Name, f, ft.Mode) + + var b bytes.Buffer + r, err := f.Open() + if err != nil { + t.Errorf("%s: %v", zt.Name, err) + return + } + + _, err = io.Copy(&b, r) + if err != ft.ContentErr { + t.Errorf("%s: copying contents: %v (want %v)", zt.Name, err, ft.ContentErr) + } + if err != nil { + return + } + r.Close() + + size := uint64(f.UncompressedSize) + if size == uint32max { + size = f.UncompressedSize64 + } + if g := uint64(b.Len()); g != size { + t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size) + } + + var c []byte + if ft.Content != nil { + c = ft.Content + } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil { + t.Error(err) + return + } + + if b.Len() != len(c) { + t.Errorf("%s: len=%d, want %d", f.Name, b.Len(), len(c)) + return + } + + for i, b := range b.Bytes() { + if b != c[i] { + t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i]) + return + } + } +} + +func testFileMode(t *testing.T, zipName string, f *File, want os.FileMode) { + mode := f.Mode() + if want == 0 { + t.Errorf("%s: %s mode: got %v, want none", zipName, f.Name, mode) + } else if mode != want { + t.Errorf("%s: %s mode: want %v, got %v", zipName, f.Name, want, mode) + } +} + +func TestInvalidFiles(t *testing.T) { + const size = 1024 * 70 // 70kb + b := make([]byte, size) + + // zeroes + _, err := NewReader(bytes.NewReader(b), size) + if err != ErrFormat { + t.Errorf("zeroes: error=%v, want %v", err, ErrFormat) + } + + // repeated directoryEndSignatures + sig := make([]byte, 4) + binary.LittleEndian.PutUint32(sig, directoryEndSignature) + for i := 0; i < size-4; i += 4 { + copy(b[i:i+4], sig) + } + _, err = NewReader(bytes.NewReader(b), size) + if err != ErrFormat { + t.Errorf("sigs: error=%v, want %v", err, ErrFormat) + } +} + +func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) { + data, err := ioutil.ReadFile(filepath.Join("testdata", fileName)) + if err != nil { + panic("Error reading " + fileName + ": " + err.Error()) + } + corrupter(data) + return bytes.NewReader(data), int64(len(data)) +} + +func returnCorruptCRC32Zip() (r io.ReaderAt, size int64) { + return messWith("go-with-datadesc-sig.zip", func(b []byte) { + // Corrupt one of the CRC32s in the data descriptor: + b[0x2d]++ + }) +} + +func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) { + return messWith("crc32-not-streamed.zip", func(b []byte) { + // Corrupt foo.txt's final crc32 byte, in both + // the file header and TOC. (0x7e -> 0x7f) + b[0x11]++ + b[0x9d]++ + + // TODO(bradfitz): add a new test that only corrupts + // one of these values, and verify that that's also an + // error. Currently, the reader code doesn't verify the + // fileheader and TOC's crc32 match if they're both + // non-zero and only the second line above, the TOC, + // is what matters. + }) +} + +// rZipBytes returns the bytes of a recursive zip file, without +// putting it on disk and triggering certain virus scanners. +func rZipBytes() []byte { + s := ` +0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4 +0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f +0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00 +0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 +0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 +0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00 +0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8 +0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f +0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e +0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb +00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff +00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 +00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14 +00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21 +00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb +00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff +0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a +0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3 +0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06 +0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00 +0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf +0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06 +0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01 +0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89 +0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00 +0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a +00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00 +00001b0 00 00 6d 01 00 00 00 00` + s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "") + s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "") + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +func returnRecursiveZip() (r io.ReaderAt, size int64) { + b := rZipBytes() + return bytes.NewReader(b), int64(len(b)) +} + +func TestIssue8186(t *testing.T) { + // Directory headers & data found in the TOC of a JAR file. + dirEnts := []string{ + "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\xaa\x1b\x06\xf0\x81\x02\x00\x00\x81\x02\x00\x00-\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00res/drawable-xhdpi-v4/ic_actionbar_accept.png\xfe\xca\x00\x00\x00", + "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\x90K\x89\xc7t\n\x00\x00t\n\x00\x00\x0e\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x02\x00\x00resources.arsc\x00\x00\x00", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xff$\x18\xed3\x03\x00\x00\xb4\b\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\r\x00\x00AndroidManifest.xml", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\x14\xc5K\xab\x192\x02\x00\xc8\xcd\x04\x00\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x10\x00\x00classes.dex", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?E\x96\nD\xac\x01\x00\x00P\x03\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:C\x02\x00res/layout/actionbar_set_wallpaper.xml", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?Ļ\x14\xe3\xd8\x01\x00\x00\xd8\x03\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:E\x02\x00res/layout/wallpaper_cropper.xml", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?}\xc1\x15\x9eZ\x01\x00\x00!\x02\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`G\x02\x00META-INF/MANIFEST.MF", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xe6\x98Ьo\x01\x00\x00\x84\x02\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfcH\x02\x00META-INF/CERT.SF", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xbfP\x96b\x86\x04\x00\x00\xb2\x06\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9J\x02\x00META-INF/CERT.RSA", + } + for i, s := range dirEnts { + var f File + err := readDirectoryHeader(&f, strings.NewReader(s)) + if err != nil { + t.Errorf("error reading #%d: %v", i, err) + } + } +} diff --git a/src/archive/zip/register.go b/src/archive/zip/register.go new file mode 100644 index 000000000..4211ec7af --- /dev/null +++ b/src/archive/zip/register.go @@ -0,0 +1,110 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package zip + +import ( + "compress/flate" + "errors" + "io" + "io/ioutil" + "sync" +) + +// A Compressor returns a compressing writer, writing to the +// provided writer. On Close, any pending data should be flushed. +type Compressor func(io.Writer) (io.WriteCloser, error) + +// Decompressor is a function that wraps a Reader with a decompressing Reader. +// The decompressed ReadCloser is returned to callers who open files from +// within the archive. These callers are responsible for closing this reader +// when they're finished reading. +type Decompressor func(io.Reader) io.ReadCloser + +var flateWriterPool sync.Pool + +func newFlateWriter(w io.Writer) io.WriteCloser { + fw, ok := flateWriterPool.Get().(*flate.Writer) + if ok { + fw.Reset(w) + } else { + fw, _ = flate.NewWriter(w, 5) + } + return &pooledFlateWriter{fw: fw} +} + +type pooledFlateWriter struct { + mu sync.Mutex // guards Close and Write + fw *flate.Writer +} + +func (w *pooledFlateWriter) Write(p []byte) (n int, err error) { + w.mu.Lock() + defer w.mu.Unlock() + if w.fw == nil { + return 0, errors.New("Write after Close") + } + return w.fw.Write(p) +} + +func (w *pooledFlateWriter) Close() error { + w.mu.Lock() + defer w.mu.Unlock() + var err error + if w.fw != nil { + err = w.fw.Close() + flateWriterPool.Put(w.fw) + w.fw = nil + } + return err +} + +var ( + mu sync.RWMutex // guards compressor and decompressor maps + + compressors = map[uint16]Compressor{ + Store: func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }, + Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }, + } + + decompressors = map[uint16]Decompressor{ + Store: ioutil.NopCloser, + Deflate: flate.NewReader, + } +) + +// RegisterDecompressor allows custom decompressors for a specified method ID. +func RegisterDecompressor(method uint16, d Decompressor) { + mu.Lock() + defer mu.Unlock() + + if _, ok := decompressors[method]; ok { + panic("decompressor already registered") + } + decompressors[method] = d +} + +// RegisterCompressor registers custom compressors for a specified method ID. +// The common methods Store and Deflate are built in. +func RegisterCompressor(method uint16, comp Compressor) { + mu.Lock() + defer mu.Unlock() + + if _, ok := compressors[method]; ok { + panic("compressor already registered") + } + compressors[method] = comp +} + +func compressor(method uint16) Compressor { + mu.RLock() + defer mu.RUnlock() + return compressors[method] +} + +func decompressor(method uint16) Decompressor { + mu.RLock() + defer mu.RUnlock() + return decompressors[method] +} diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go new file mode 100644 index 000000000..cb28e8324 --- /dev/null +++ b/src/archive/zip/struct.go @@ -0,0 +1,313 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package zip provides support for reading and writing ZIP archives. + +See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT + +This package does not support disk spanning. + +A note about ZIP64: + +To be backwards compatible the FileHeader has both 32 and 64 bit Size +fields. The 64 bit fields will always contain the correct value and +for normal archives both fields will be the same. For files requiring +the ZIP64 format the 32 bit fields will be 0xffffffff and the 64 bit +fields must be used instead. +*/ +package zip + +import ( + "os" + "path" + "time" +) + +// Compression methods. +const ( + Store uint16 = 0 + Deflate uint16 = 8 +) + +const ( + fileHeaderSignature = 0x04034b50 + directoryHeaderSignature = 0x02014b50 + directoryEndSignature = 0x06054b50 + directory64LocSignature = 0x07064b50 + directory64EndSignature = 0x06064b50 + dataDescriptorSignature = 0x08074b50 // de-facto standard; required by OS X Finder + fileHeaderLen = 30 // + filename + extra + directoryHeaderLen = 46 // + filename + extra + comment + directoryEndLen = 22 // + comment + dataDescriptorLen = 16 // four uint32: descriptor signature, crc32, compressed size, size + dataDescriptor64Len = 24 // descriptor with 8 byte sizes + directory64LocLen = 20 // + directory64EndLen = 56 // + extra + + // Constants for the first byte in CreatorVersion + creatorFAT = 0 + creatorUnix = 3 + creatorNTFS = 11 + creatorVFAT = 14 + creatorMacOSX = 19 + + // version numbers + zipVersion20 = 20 // 2.0 + zipVersion45 = 45 // 4.5 (reads and writes zip64 archives) + + // limits for non zip64 files + uint16max = (1 << 16) - 1 + uint32max = (1 << 32) - 1 + + // extra header id's + zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field +) + +// FileHeader describes a file within a zip file. +// See the zip spec for details. +type FileHeader struct { + // Name is the name of the file. + // It must be a relative path: it must not start with a drive + // letter (e.g. C:) or leading slash, and only forward slashes + // are allowed. + Name string + + CreatorVersion uint16 + ReaderVersion uint16 + Flags uint16 + Method uint16 + ModifiedTime uint16 // MS-DOS time + ModifiedDate uint16 // MS-DOS date + CRC32 uint32 + CompressedSize uint32 // deprecated; use CompressedSize64 + UncompressedSize uint32 // deprecated; use UncompressedSize64 + CompressedSize64 uint64 + UncompressedSize64 uint64 + Extra []byte + ExternalAttrs uint32 // Meaning depends on CreatorVersion + Comment string +} + +// FileInfo returns an os.FileInfo for the FileHeader. +func (h *FileHeader) FileInfo() os.FileInfo { + return headerFileInfo{h} +} + +// headerFileInfo implements os.FileInfo. +type headerFileInfo struct { + fh *FileHeader +} + +func (fi headerFileInfo) Name() string { return path.Base(fi.fh.Name) } +func (fi headerFileInfo) Size() int64 { + if fi.fh.UncompressedSize64 > 0 { + return int64(fi.fh.UncompressedSize64) + } + return int64(fi.fh.UncompressedSize) +} +func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } +func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() } +func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() } +func (fi headerFileInfo) Sys() interface{} { return fi.fh } + +// FileInfoHeader creates a partially-populated FileHeader from an +// os.FileInfo. +// Because os.FileInfo's Name method returns only the base name of +// the file it describes, it may be necessary to modify the Name field +// of the returned header to provide the full path name of the file. +func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) { + size := fi.Size() + fh := &FileHeader{ + Name: fi.Name(), + UncompressedSize64: uint64(size), + } + fh.SetModTime(fi.ModTime()) + fh.SetMode(fi.Mode()) + if fh.UncompressedSize64 > uint32max { + fh.UncompressedSize = uint32max + } else { + fh.UncompressedSize = uint32(fh.UncompressedSize64) + } + return fh, nil +} + +type directoryEnd struct { + diskNbr uint32 // unused + dirDiskNbr uint32 // unused + dirRecordsThisDisk uint64 // unused + directoryRecords uint64 + directorySize uint64 + directoryOffset uint64 // relative to file + commentLen uint16 + comment string +} + +// msDosTimeToTime converts an MS-DOS date and time into a time.Time. +// The resolution is 2s. +// See: http://msdn.microsoft.com/en-us/library/ms724247(v=VS.85).aspx +func msDosTimeToTime(dosDate, dosTime uint16) time.Time { + return time.Date( + // date bits 0-4: day of month; 5-8: month; 9-15: years since 1980 + int(dosDate>>9+1980), + time.Month(dosDate>>5&0xf), + int(dosDate&0x1f), + + // time bits 0-4: second/2; 5-10: minute; 11-15: hour + int(dosTime>>11), + int(dosTime>>5&0x3f), + int(dosTime&0x1f*2), + 0, // nanoseconds + + time.UTC, + ) +} + +// timeToMsDosTime converts a time.Time to an MS-DOS date and time. +// The resolution is 2s. +// See: http://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx +func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) { + t = t.In(time.UTC) + fDate = uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9) + fTime = uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11) + return +} + +// ModTime returns the modification time in UTC. +// The resolution is 2s. +func (h *FileHeader) ModTime() time.Time { + return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime) +} + +// SetModTime sets the ModifiedTime and ModifiedDate fields to the given time in UTC. +// The resolution is 2s. +func (h *FileHeader) SetModTime(t time.Time) { + h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t) +} + +const ( + // Unix constants. The specification doesn't mention them, + // but these seem to be the values agreed on by tools. + s_IFMT = 0xf000 + s_IFSOCK = 0xc000 + s_IFLNK = 0xa000 + s_IFREG = 0x8000 + s_IFBLK = 0x6000 + s_IFDIR = 0x4000 + s_IFCHR = 0x2000 + s_IFIFO = 0x1000 + s_ISUID = 0x800 + s_ISGID = 0x400 + s_ISVTX = 0x200 + + msdosDir = 0x10 + msdosReadOnly = 0x01 +) + +// Mode returns the permission and mode bits for the FileHeader. +func (h *FileHeader) Mode() (mode os.FileMode) { + switch h.CreatorVersion >> 8 { + case creatorUnix, creatorMacOSX: + mode = unixModeToFileMode(h.ExternalAttrs >> 16) + case creatorNTFS, creatorVFAT, creatorFAT: + mode = msdosModeToFileMode(h.ExternalAttrs) + } + if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' { + mode |= os.ModeDir + } + return mode +} + +// SetMode changes the permission and mode bits for the FileHeader. +func (h *FileHeader) SetMode(mode os.FileMode) { + h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8 + h.ExternalAttrs = fileModeToUnixMode(mode) << 16 + + // set MSDOS attributes too, as the original zip does. + if mode&os.ModeDir != 0 { + h.ExternalAttrs |= msdosDir + } + if mode&0200 == 0 { + h.ExternalAttrs |= msdosReadOnly + } +} + +// isZip64 returns true if the file size exceeds the 32 bit limit +func (fh *FileHeader) isZip64() bool { + return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max +} + +func msdosModeToFileMode(m uint32) (mode os.FileMode) { + if m&msdosDir != 0 { + mode = os.ModeDir | 0777 + } else { + mode = 0666 + } + if m&msdosReadOnly != 0 { + mode &^= 0222 + } + return mode +} + +func fileModeToUnixMode(mode os.FileMode) uint32 { + var m uint32 + switch mode & os.ModeType { + default: + m = s_IFREG + case os.ModeDir: + m = s_IFDIR + case os.ModeSymlink: + m = s_IFLNK + case os.ModeNamedPipe: + m = s_IFIFO + case os.ModeSocket: + m = s_IFSOCK + case os.ModeDevice: + if mode&os.ModeCharDevice != 0 { + m = s_IFCHR + } else { + m = s_IFBLK + } + } + if mode&os.ModeSetuid != 0 { + m |= s_ISUID + } + if mode&os.ModeSetgid != 0 { + m |= s_ISGID + } + if mode&os.ModeSticky != 0 { + m |= s_ISVTX + } + return m | uint32(mode&0777) +} + +func unixModeToFileMode(m uint32) os.FileMode { + mode := os.FileMode(m & 0777) + switch m & s_IFMT { + case s_IFBLK: + mode |= os.ModeDevice + case s_IFCHR: + mode |= os.ModeDevice | os.ModeCharDevice + case s_IFDIR: + mode |= os.ModeDir + case s_IFIFO: + mode |= os.ModeNamedPipe + case s_IFLNK: + mode |= os.ModeSymlink + case s_IFREG: + // nothing to do + case s_IFSOCK: + mode |= os.ModeSocket + } + if m&s_ISGID != 0 { + mode |= os.ModeSetgid + } + if m&s_ISUID != 0 { + mode |= os.ModeSetuid + } + if m&s_ISVTX != 0 { + mode |= os.ModeSticky + } + return mode +} diff --git a/src/archive/zip/testdata/crc32-not-streamed.zip b/src/archive/zip/testdata/crc32-not-streamed.zip new file mode 100644 index 000000000..f268d8873 Binary files /dev/null and b/src/archive/zip/testdata/crc32-not-streamed.zip differ diff --git a/src/archive/zip/testdata/dd.zip b/src/archive/zip/testdata/dd.zip new file mode 100644 index 000000000..e53378b0b Binary files /dev/null and b/src/archive/zip/testdata/dd.zip differ diff --git a/src/archive/zip/testdata/go-no-datadesc-sig.zip b/src/archive/zip/testdata/go-no-datadesc-sig.zip new file mode 100644 index 000000000..c3d593f44 Binary files /dev/null and b/src/archive/zip/testdata/go-no-datadesc-sig.zip differ diff --git a/src/archive/zip/testdata/go-with-datadesc-sig.zip b/src/archive/zip/testdata/go-with-datadesc-sig.zip new file mode 100644 index 000000000..bcfe121bb Binary files /dev/null and b/src/archive/zip/testdata/go-with-datadesc-sig.zip differ diff --git a/src/archive/zip/testdata/gophercolor16x16.png b/src/archive/zip/testdata/gophercolor16x16.png new file mode 100644 index 000000000..48854ff3b Binary files /dev/null and b/src/archive/zip/testdata/gophercolor16x16.png differ diff --git a/src/archive/zip/testdata/readme.notzip b/src/archive/zip/testdata/readme.notzip new file mode 100644 index 000000000..06668c4c1 Binary files /dev/null and b/src/archive/zip/testdata/readme.notzip differ diff --git a/src/archive/zip/testdata/readme.zip b/src/archive/zip/testdata/readme.zip new file mode 100644 index 000000000..db3bb900e Binary files /dev/null and b/src/archive/zip/testdata/readme.zip differ diff --git a/src/archive/zip/testdata/symlink.zip b/src/archive/zip/testdata/symlink.zip new file mode 100644 index 000000000..af846938c Binary files /dev/null and b/src/archive/zip/testdata/symlink.zip differ diff --git a/src/archive/zip/testdata/test-trailing-junk.zip b/src/archive/zip/testdata/test-trailing-junk.zip new file mode 100644 index 000000000..42281b4e3 Binary files /dev/null and b/src/archive/zip/testdata/test-trailing-junk.zip differ diff --git a/src/archive/zip/testdata/test.zip b/src/archive/zip/testdata/test.zip new file mode 100644 index 000000000..03890c05d Binary files /dev/null and b/src/archive/zip/testdata/test.zip differ diff --git a/src/archive/zip/testdata/unix.zip b/src/archive/zip/testdata/unix.zip new file mode 100644 index 000000000..ce1a981b2 Binary files /dev/null and b/src/archive/zip/testdata/unix.zip differ diff --git a/src/archive/zip/testdata/winxp.zip b/src/archive/zip/testdata/winxp.zip new file mode 100644 index 000000000..3919322f0 Binary files /dev/null and b/src/archive/zip/testdata/winxp.zip differ diff --git a/src/archive/zip/testdata/zip64-2.zip b/src/archive/zip/testdata/zip64-2.zip new file mode 100644 index 000000000..f844e3537 Binary files /dev/null and b/src/archive/zip/testdata/zip64-2.zip differ diff --git a/src/archive/zip/testdata/zip64.zip b/src/archive/zip/testdata/zip64.zip new file mode 100644 index 000000000..a2ee1fa33 Binary files /dev/null and b/src/archive/zip/testdata/zip64.zip differ diff --git a/src/archive/zip/writer.go b/src/archive/zip/writer.go new file mode 100644 index 000000000..170beec0e --- /dev/null +++ b/src/archive/zip/writer.go @@ -0,0 +1,357 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package zip + +import ( + "bufio" + "encoding/binary" + "errors" + "hash" + "hash/crc32" + "io" +) + +// TODO(adg): support zip file comments +// TODO(adg): support specifying deflate level + +// Writer implements a zip file writer. +type Writer struct { + cw *countWriter + dir []*header + last *fileWriter + closed bool +} + +type header struct { + *FileHeader + offset uint64 +} + +// NewWriter returns a new Writer writing a zip file to w. +func NewWriter(w io.Writer) *Writer { + return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}} +} + +// Flush flushes any buffered data to the underlying writer. +// Calling Flush is not normally necessary; calling Close is sufficient. +func (w *Writer) Flush() error { + return w.cw.w.(*bufio.Writer).Flush() +} + +// Close finishes writing the zip file by writing the central directory. +// It does not (and can not) close the underlying writer. +func (w *Writer) Close() error { + if w.last != nil && !w.last.closed { + if err := w.last.close(); err != nil { + return err + } + w.last = nil + } + if w.closed { + return errors.New("zip: writer closed twice") + } + w.closed = true + + // write central directory + start := w.cw.count + for _, h := range w.dir { + var buf [directoryHeaderLen]byte + b := writeBuf(buf[:]) + b.uint32(uint32(directoryHeaderSignature)) + b.uint16(h.CreatorVersion) + b.uint16(h.ReaderVersion) + b.uint16(h.Flags) + b.uint16(h.Method) + b.uint16(h.ModifiedTime) + b.uint16(h.ModifiedDate) + b.uint32(h.CRC32) + if h.isZip64() || h.offset > uint32max { + // the file needs a zip64 header. store maxint in both + // 32 bit size fields (and offset later) to signal that the + // zip64 extra header should be used. + b.uint32(uint32max) // compressed size + b.uint32(uint32max) // uncompressed size + + // append a zip64 extra block to Extra + var buf [28]byte // 2x uint16 + 3x uint64 + eb := writeBuf(buf[:]) + eb.uint16(zip64ExtraId) + eb.uint16(24) // size = 3x uint64 + eb.uint64(h.UncompressedSize64) + eb.uint64(h.CompressedSize64) + eb.uint64(h.offset) + h.Extra = append(h.Extra, buf[:]...) + } else { + b.uint32(h.CompressedSize) + b.uint32(h.UncompressedSize) + } + b.uint16(uint16(len(h.Name))) + b.uint16(uint16(len(h.Extra))) + b.uint16(uint16(len(h.Comment))) + b = b[4:] // skip disk number start and internal file attr (2x uint16) + b.uint32(h.ExternalAttrs) + if h.offset > uint32max { + b.uint32(uint32max) + } else { + b.uint32(uint32(h.offset)) + } + if _, err := w.cw.Write(buf[:]); err != nil { + return err + } + if _, err := io.WriteString(w.cw, h.Name); err != nil { + return err + } + if _, err := w.cw.Write(h.Extra); err != nil { + return err + } + if _, err := io.WriteString(w.cw, h.Comment); err != nil { + return err + } + } + end := w.cw.count + + records := uint64(len(w.dir)) + size := uint64(end - start) + offset := uint64(start) + + if records > uint16max || size > uint32max || offset > uint32max { + var buf [directory64EndLen + directory64LocLen]byte + b := writeBuf(buf[:]) + + // 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 + + // zip64 end of central directory locator + b.uint32(directory64LocSignature) + b.uint32(0) // number of the disk with the start of the zip64 end of central directory + b.uint64(uint64(end)) // relative offset of the zip64 end of central directory record + b.uint32(1) // total number of disks + + if _, err := w.cw.Write(buf[:]); err != nil { + return err + } + + // store max values in the regular end record to signal that + // that the zip64 values should be used instead + records = uint16max + size = uint32max + offset = uint32max + } + + // write end record + var buf [directoryEndLen]byte + b := writeBuf(buf[:]) + b.uint32(uint32(directoryEndSignature)) + b = b[4:] // skip over disk number and first disk number (2x uint16) + b.uint16(uint16(records)) // number of entries this disk + b.uint16(uint16(records)) // number of entries total + b.uint32(uint32(size)) // size of directory + b.uint32(uint32(offset)) // start of directory + // skipped size of comment (always zero) + if _, err := w.cw.Write(buf[:]); err != nil { + return err + } + + return w.cw.w.(*bufio.Writer).Flush() +} + +// Create adds a file to the zip file using the provided name. +// It returns a Writer to which the file contents should be written. +// The name must be a relative path: it must not start with a drive +// letter (e.g. C:) or leading slash, and only forward slashes are +// allowed. +// The file's contents must be written to the io.Writer before the next +// call to Create, CreateHeader, or Close. +func (w *Writer) Create(name string) (io.Writer, error) { + header := &FileHeader{ + Name: name, + Method: Deflate, + } + return w.CreateHeader(header) +} + +// 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. +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 + } + } + + fh.Flags |= 0x8 // we will write a data descriptor + + fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte + fh.ReaderVersion = zipVersion20 + + fw := &fileWriter{ + zipw: w.cw, + compCount: &countWriter{w: w.cw}, + crc32: crc32.NewIEEE(), + } + comp := compressor(fh.Method) + if comp == nil { + return nil, ErrAlgorithm + } + var err error + fw.comp, err = comp(fw.compCount) + if err != nil { + return nil, err + } + fw.rawCount = &countWriter{w: fw.comp} + + h := &header{ + FileHeader: fh, + offset: uint64(w.cw.count), + } + w.dir = append(w.dir, h) + fw.header = h + + if err := writeHeader(w.cw, fh); err != nil { + return nil, err + } + + w.last = fw + return fw, nil +} + +func writeHeader(w io.Writer, h *FileHeader) error { + var buf [fileHeaderLen]byte + b := writeBuf(buf[:]) + b.uint32(uint32(fileHeaderSignature)) + b.uint16(h.ReaderVersion) + b.uint16(h.Flags) + b.uint16(h.Method) + b.uint16(h.ModifiedTime) + b.uint16(h.ModifiedDate) + b.uint32(0) // since we are writing a data descriptor crc32, + b.uint32(0) // compressed size, + b.uint32(0) // and uncompressed size should be zero + b.uint16(uint16(len(h.Name))) + b.uint16(uint16(len(h.Extra))) + if _, err := w.Write(buf[:]); err != nil { + return err + } + if _, err := io.WriteString(w, h.Name); err != nil { + return err + } + _, err := w.Write(h.Extra) + return err +} + +type fileWriter struct { + *header + zipw io.Writer + rawCount *countWriter + comp io.WriteCloser + compCount *countWriter + crc32 hash.Hash32 + closed bool +} + +func (w *fileWriter) Write(p []byte) (int, error) { + if w.closed { + return 0, errors.New("zip: write to closed file") + } + w.crc32.Write(p) + return w.rawCount.Write(p) +} + +func (w *fileWriter) close() error { + if w.closed { + return errors.New("zip: file closed twice") + } + w.closed = true + if err := w.comp.Close(); err != nil { + return err + } + + // update FileHeader + fh := w.header.FileHeader + fh.CRC32 = w.crc32.Sum32() + fh.CompressedSize64 = uint64(w.compCount.count) + fh.UncompressedSize64 = uint64(w.rawCount.count) + + if fh.isZip64() { + fh.CompressedSize = uint32max + fh.UncompressedSize = uint32max + fh.ReaderVersion = zipVersion45 // requires 4.5 - File uses ZIP64 format extensions + } else { + fh.CompressedSize = uint32(fh.CompressedSize64) + fh.UncompressedSize = uint32(fh.UncompressedSize64) + } + + // Write data descriptor. This is more complicated than one would + // think, see e.g. comments in zipfile.c:putextended() and + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588. + // The approach here is to write 8 byte sizes if needed without + // adding a zip64 extra in the local header (too late anyway). + var buf []byte + if fh.isZip64() { + buf = make([]byte, dataDescriptor64Len) + } else { + buf = make([]byte, dataDescriptorLen) + } + b := writeBuf(buf) + b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X + b.uint32(fh.CRC32) + if fh.isZip64() { + b.uint64(fh.CompressedSize64) + b.uint64(fh.UncompressedSize64) + } else { + b.uint32(fh.CompressedSize) + b.uint32(fh.UncompressedSize) + } + _, err := w.zipw.Write(buf) + return err +} + +type countWriter struct { + w io.Writer + count int64 +} + +func (w *countWriter) Write(p []byte) (int, error) { + n, err := w.w.Write(p) + w.count += int64(n) + return n, err +} + +type nopCloser struct { + io.Writer +} + +func (w nopCloser) Close() error { + return nil +} + +type writeBuf []byte + +func (b *writeBuf) uint16(v uint16) { + binary.LittleEndian.PutUint16(*b, v) + *b = (*b)[2:] +} + +func (b *writeBuf) uint32(v uint32) { + binary.LittleEndian.PutUint32(*b, v) + *b = (*b)[4:] +} + +func (b *writeBuf) uint64(v uint64) { + binary.LittleEndian.PutUint64(*b, v) + *b = (*b)[8:] +} diff --git a/src/archive/zip/writer_test.go b/src/archive/zip/writer_test.go new file mode 100644 index 000000000..184a7d96a --- /dev/null +++ b/src/archive/zip/writer_test.go @@ -0,0 +1,164 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package zip + +import ( + "bytes" + "io" + "io/ioutil" + "math/rand" + "os" + "testing" +) + +// TODO(adg): a more sophisticated test suite + +type WriteTest struct { + Name string + Data []byte + Method uint16 + Mode os.FileMode +} + +var writeTests = []WriteTest{ + { + Name: "foo", + Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."), + Method: Store, + Mode: 0666, + }, + { + Name: "bar", + Data: nil, // large data set in the test + Method: Deflate, + Mode: 0644, + }, + { + Name: "setuid", + Data: []byte("setuid file"), + Method: Deflate, + Mode: 0755 | os.ModeSetuid, + }, + { + Name: "setgid", + Data: []byte("setgid file"), + Method: Deflate, + Mode: 0755 | os.ModeSetgid, + }, + { + Name: "symlink", + Data: []byte("../link/target"), + Method: Deflate, + Mode: 0755 | os.ModeSymlink, + }, +} + +func TestWriter(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) + w := NewWriter(buf) + + 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}) + _, err := w.Create("foo") + if err != nil { + t.Fatal(err) + } + if buf.Len() > 0 { + t.Fatalf("Unexpected %d bytes already in buffer", buf.Len()) + } + if err := w.Flush(); err != nil { + t.Fatal(err) + } + if buf.Len() == 0 { + t.Fatal("No bytes written after Flush") + } +} + +func testCreate(t *testing.T, w *Writer, wt *WriteTest) { + header := &FileHeader{ + Name: wt.Name, + Method: wt.Method, + } + if wt.Mode != 0 { + header.SetMode(wt.Mode) + } + f, err := w.CreateHeader(header) + if err != nil { + t.Fatal(err) + } + _, err = f.Write(wt.Data) + if err != nil { + t.Fatal(err) + } +} + +func testReadFile(t *testing.T, f *File, wt *WriteTest) { + if f.Name != wt.Name { + t.Fatalf("File name: got %q, want %q", f.Name, wt.Name) + } + testFileMode(t, wt.Name, f, wt.Mode) + rc, err := f.Open() + if err != nil { + t.Fatal("opening:", err) + } + b, err := ioutil.ReadAll(rc) + if err != nil { + t.Fatal("reading:", err) + } + err = rc.Close() + if err != nil { + t.Fatal("closing:", err) + } + if !bytes.Equal(b, wt.Data) { + t.Errorf("File contents %q, want %q", b, wt.Data) + } +} + +func BenchmarkCompressedZipGarbage(b *testing.B) { + b.ReportAllocs() + var buf bytes.Buffer + bigBuf := bytes.Repeat([]byte("a"), 1<<20) + for i := 0; i < b.N; i++ { + buf.Reset() + zw := NewWriter(&buf) + for j := 0; j < 3; j++ { + w, _ := zw.CreateHeader(&FileHeader{ + Name: "foo", + Method: Deflate, + }) + w.Write(bigBuf) + } + zw.Close() + } +} diff --git a/src/archive/zip/zip_test.go b/src/archive/zip/zip_test.go new file mode 100644 index 000000000..32a16a79e --- /dev/null +++ b/src/archive/zip/zip_test.go @@ -0,0 +1,395 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests that involve both reading and writing. + +package zip + +import ( + "bytes" + "fmt" + "hash" + "io" + "io/ioutil" + "sort" + "strings" + "testing" + "time" +) + +func TestOver65kFiles(t *testing.T) { + buf := new(bytes.Buffer) + w := NewWriter(buf) + const nFiles = (1 << 16) + 42 + for i := 0; i < nFiles; i++ { + _, err := w.CreateHeader(&FileHeader{ + Name: fmt.Sprintf("%d.dat", i), + Method: Store, // avoid Issue 6136 and Issue 6138 + }) + if err != nil { + t.Fatalf("creating file %d: %v", i, err) + } + } + if err := w.Close(); err != nil { + t.Fatalf("Writer.Close: %v", err) + } + s := buf.String() + zr, err := NewReader(strings.NewReader(s), int64(len(s))) + if err != nil { + t.Fatalf("NewReader: %v", err) + } + if got := len(zr.File); got != nFiles { + t.Fatalf("File contains %d files, want %d", got, nFiles) + } + for i := 0; i < nFiles; i++ { + want := fmt.Sprintf("%d.dat", i) + if zr.File[i].Name != want { + t.Fatalf("File(%d) = %q, want %q", i, zr.File[i].Name, want) + } + } +} + +func TestModTime(t *testing.T) { + var testTime = time.Date(2009, time.November, 10, 23, 45, 58, 0, time.UTC) + fh := new(FileHeader) + fh.SetModTime(testTime) + outTime := fh.ModTime() + if !outTime.Equal(testTime) { + t.Errorf("times don't match: got %s, want %s", outTime, testTime) + } +} + +func testHeaderRoundTrip(fh *FileHeader, wantUncompressedSize uint32, wantUncompressedSize64 uint64, t *testing.T) { + fi := fh.FileInfo() + fh2, err := FileInfoHeader(fi) + if err != nil { + t.Fatal(err) + } + if got, want := fh2.Name, fh.Name; got != want { + t.Errorf("Name: got %s, want %s\n", got, want) + } + if got, want := fh2.UncompressedSize, wantUncompressedSize; got != want { + t.Errorf("UncompressedSize: got %d, want %d\n", got, want) + } + if got, want := fh2.UncompressedSize64, wantUncompressedSize64; got != want { + t.Errorf("UncompressedSize64: got %d, want %d\n", got, want) + } + if got, want := fh2.ModifiedTime, fh.ModifiedTime; got != want { + t.Errorf("ModifiedTime: got %d, want %d\n", got, want) + } + if got, want := fh2.ModifiedDate, fh.ModifiedDate; got != want { + t.Errorf("ModifiedDate: got %d, want %d\n", got, want) + } + + if sysfh, ok := fi.Sys().(*FileHeader); !ok && sysfh != fh { + t.Errorf("Sys didn't return original *FileHeader") + } +} + +func TestFileHeaderRoundTrip(t *testing.T) { + fh := &FileHeader{ + Name: "foo.txt", + UncompressedSize: 987654321, + ModifiedTime: 1234, + ModifiedDate: 5678, + } + testHeaderRoundTrip(fh, fh.UncompressedSize, uint64(fh.UncompressedSize), t) +} + +func TestFileHeaderRoundTrip64(t *testing.T) { + fh := &FileHeader{ + Name: "foo.txt", + UncompressedSize64: 9876543210, + ModifiedTime: 1234, + ModifiedDate: 5678, + } + testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t) +} + +type repeatedByte struct { + off int64 + b byte + n int64 +} + +// rleBuffer is a run-length-encoded byte buffer. +// It's an io.Writer (like a bytes.Buffer) and also an io.ReaderAt, +// allowing random-access reads. +type rleBuffer struct { + buf []repeatedByte +} + +func (r *rleBuffer) Size() int64 { + if len(r.buf) == 0 { + return 0 + } + last := &r.buf[len(r.buf)-1] + return last.off + last.n +} + +func (r *rleBuffer) Write(p []byte) (n int, err error) { + var rp *repeatedByte + if len(r.buf) > 0 { + rp = &r.buf[len(r.buf)-1] + // Fast path, if p is entirely the same byte repeated. + if lastByte := rp.b; len(p) > 0 && p[0] == lastByte { + all := true + for _, b := range p { + if b != lastByte { + all = false + break + } + } + if all { + rp.n += int64(len(p)) + return len(p), nil + } + } + } + + for _, b := range p { + if rp == nil || rp.b != b { + r.buf = append(r.buf, repeatedByte{r.Size(), b, 1}) + rp = &r.buf[len(r.buf)-1] + } else { + rp.n++ + } + } + return len(p), nil +} + +func (r *rleBuffer) ReadAt(p []byte, off int64) (n int, err error) { + if len(p) == 0 { + return + } + skipParts := sort.Search(len(r.buf), func(i int) bool { + part := &r.buf[i] + return part.off+part.n > off + }) + parts := r.buf[skipParts:] + if len(parts) > 0 { + skipBytes := off - parts[0].off + for len(parts) > 0 { + part := parts[0] + for i := skipBytes; i < part.n; i++ { + if n == len(p) { + return + } + p[n] = part.b + n++ + } + parts = parts[1:] + skipBytes = 0 + } + } + if n != len(p) { + err = io.ErrUnexpectedEOF + } + return +} + +// Just testing the rleBuffer used in the Zip64 test above. Not used by the zip code. +func TestRLEBuffer(t *testing.T) { + b := new(rleBuffer) + var all []byte + writes := []string{"abcdeee", "eeeeeee", "eeeefghaaiii"} + for _, w := range writes { + b.Write([]byte(w)) + all = append(all, w...) + } + if len(b.buf) != 10 { + t.Fatalf("len(b.buf) = %d; want 10", len(b.buf)) + } + + for i := 0; i < len(all); i++ { + for j := 0; j < len(all)-i; j++ { + buf := make([]byte, j) + n, err := b.ReadAt(buf, int64(i)) + if err != nil || n != len(buf) { + t.Errorf("ReadAt(%d, %d) = %d, %v; want %d, nil", i, j, n, err, len(buf)) + } + if !bytes.Equal(buf, all[i:i+j]) { + t.Errorf("ReadAt(%d, %d) = %q; want %q", i, j, buf, all[i:i+j]) + } + } + } +} + +// fakeHash32 is a dummy Hash32 that always returns 0. +type fakeHash32 struct { + hash.Hash32 +} + +func (fakeHash32) Write(p []byte) (int, error) { return len(p), nil } +func (fakeHash32) Sum32() uint32 { return 0 } + +func TestZip64(t *testing.T) { + if testing.Short() { + t.Skip("slow test; skipping") + } + const size = 1 << 32 // before the "END\n" part + testZip64(t, size) +} + +func testZip64(t testing.TB, size int64) { + const chunkSize = 1024 + chunks := int(size / chunkSize) + // write 2^32 bytes plus "END\n" to a zip file + buf := new(rleBuffer) + w := NewWriter(buf) + f, err := w.CreateHeader(&FileHeader{ + Name: "huge.txt", + Method: Store, + }) + if err != nil { + t.Fatal(err) + } + f.(*fileWriter).crc32 = fakeHash32{} + chunk := make([]byte, chunkSize) + for i := range chunk { + chunk[i] = '.' + } + for i := 0; i < chunks; i++ { + _, err := f.Write(chunk) + if err != nil { + t.Fatal("write chunk:", err) + } + } + end := []byte("END\n") + _, err = f.Write(end) + if err != nil { + t.Fatal("write end:", err) + } + if err := w.Close(); err != nil { + t.Fatal(err) + } + + // read back zip file and check that we get to the end of it + r, err := NewReader(buf, int64(buf.Size())) + if err != nil { + t.Fatal("reader:", err) + } + f0 := r.File[0] + rc, err := f0.Open() + if err != nil { + t.Fatal("opening:", err) + } + rc.(*checksumReader).hash = fakeHash32{} + for i := 0; i < chunks; i++ { + _, err := io.ReadFull(rc, chunk) + if err != nil { + t.Fatal("read:", err) + } + } + gotEnd, err := ioutil.ReadAll(rc) + if err != nil { + t.Fatal("read end:", err) + } + if !bytes.Equal(gotEnd, end) { + t.Errorf("End of zip64 archive %q, want %q", gotEnd, end) + } + err = rc.Close() + if err != nil { + t.Fatal("closing:", err) + } + if size == 1<<32 { + if got, want := f0.UncompressedSize, uint32(uint32max); got != want { + t.Errorf("UncompressedSize %d, want %d", got, want) + } + } + + if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want { + t.Errorf("UncompressedSize64 %d, want %d", got, want) + } +} + +func testInvalidHeader(h *FileHeader, t *testing.T) { + var buf bytes.Buffer + z := NewWriter(&buf) + + f, err := z.CreateHeader(h) + if err != nil { + t.Fatalf("error creating header: %v", err) + } + if _, err := f.Write([]byte("hi")); err != nil { + t.Fatalf("error writing content: %v", err) + } + if err := z.Close(); err != nil { + t.Fatalf("error closing zip writer: %v", err) + } + + b := buf.Bytes() + if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != ErrFormat { + t.Fatalf("got %v, expected ErrFormat", err) + } +} + +func testValidHeader(h *FileHeader, t *testing.T) { + var buf bytes.Buffer + z := NewWriter(&buf) + + f, err := z.CreateHeader(h) + if err != nil { + t.Fatalf("error creating header: %v", err) + } + if _, err := f.Write([]byte("hi")); err != nil { + t.Fatalf("error writing content: %v", err) + } + if err := z.Close(); err != nil { + t.Fatalf("error closing zip writer: %v", err) + } + + b := buf.Bytes() + if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != nil { + t.Fatalf("got %v, expected nil", err) + } +} + +// Issue 4302. +func TestHeaderInvalidTagAndSize(t *testing.T) { + const timeFormat = "20060102T150405.000.txt" + + ts := time.Now() + filename := ts.Format(timeFormat) + + h := FileHeader{ + Name: filename, + Method: Deflate, + Extra: []byte(ts.Format(time.RFC3339Nano)), // missing tag and len + } + h.SetModTime(ts) + + testInvalidHeader(&h, t) +} + +func TestHeaderTooShort(t *testing.T) { + h := FileHeader{ + Name: "foo.txt", + Method: Deflate, + Extra: []byte{zip64ExtraId}, // missing size + } + testInvalidHeader(&h, t) +} + +// Issue 4393. It is valid to have an extra data header +// which contains no body. +func TestZeroLengthHeader(t *testing.T) { + h := FileHeader{ + Name: "extadata.txt", + Method: Deflate, + Extra: []byte{ + 85, 84, 5, 0, 3, 154, 144, 195, 77, // tag 21589 size 5 + 85, 120, 0, 0, // tag 30805 size 0 + }, + } + testValidHeader(&h, t) +} + +// Just benchmarking how fast the Zip64 test above is. Not related to +// our zip performance, since the test above disabled CRC32 and flate. +func BenchmarkZip64Test(b *testing.B) { + for i := 0; i < b.N; i++ { + testZip64(b, 1<<26) + } +} diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go new file mode 100644 index 000000000..d3c68fe6f --- /dev/null +++ b/src/bufio/bufio.go @@ -0,0 +1,698 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer +// object, creating another object (Reader or Writer) that also implements +// the interface but provides buffering and some help for textual I/O. +package bufio + +import ( + "bytes" + "errors" + "io" + "unicode/utf8" +) + +const ( + defaultBufSize = 4096 +) + +var ( + ErrInvalidUnreadByte = errors.New("bufio: invalid use of UnreadByte") + ErrInvalidUnreadRune = errors.New("bufio: invalid use of UnreadRune") + ErrBufferFull = errors.New("bufio: buffer full") + ErrNegativeCount = errors.New("bufio: negative count") +) + +// Buffered input. + +// Reader implements buffering for an io.Reader object. +type Reader struct { + buf []byte + rd io.Reader // reader provided by the client + r, w int // buf read and write positions + err error + lastByte int + lastRuneSize int +} + +const minReadBufferSize = 16 +const maxConsecutiveEmptyReads = 100 + +// NewReaderSize returns a new Reader whose buffer has at least the specified +// size. If the argument io.Reader is already a Reader with large enough +// size, it returns the underlying Reader. +func NewReaderSize(rd io.Reader, size int) *Reader { + // Is it already a Reader? + b, ok := rd.(*Reader) + if ok && len(b.buf) >= size { + return b + } + if size < minReadBufferSize { + size = minReadBufferSize + } + r := new(Reader) + r.reset(make([]byte, size), rd) + return r +} + +// NewReader returns a new Reader whose buffer has the default size. +func NewReader(rd io.Reader) *Reader { + return NewReaderSize(rd, defaultBufSize) +} + +// Reset discards any buffered data, resets all state, and switches +// the buffered reader to read from r. +func (b *Reader) Reset(r io.Reader) { + b.reset(b.buf, r) +} + +func (b *Reader) reset(buf []byte, r io.Reader) { + *b = Reader{ + buf: buf, + rd: r, + lastByte: -1, + lastRuneSize: -1, + } +} + +var errNegativeRead = errors.New("bufio: reader returned negative count from Read") + +// fill reads a new chunk into the buffer. +func (b *Reader) fill() { + // Slide existing data to beginning. + if b.r > 0 { + copy(b.buf, b.buf[b.r:b.w]) + b.w -= b.r + b.r = 0 + } + + if b.w >= len(b.buf) { + panic("bufio: tried to fill full buffer") + } + + // Read new data: try a limited number of times. + for i := maxConsecutiveEmptyReads; i > 0; i-- { + n, err := b.rd.Read(b.buf[b.w:]) + if n < 0 { + panic(errNegativeRead) + } + b.w += n + if err != nil { + b.err = err + return + } + if n > 0 { + return + } + } + b.err = io.ErrNoProgress +} + +func (b *Reader) readErr() error { + err := b.err + b.err = nil + return err +} + +// Peek returns the next n bytes without advancing the reader. The bytes stop +// being valid at the next read call. If Peek returns fewer than n bytes, it +// also returns an error explaining why the read is short. The error is +// ErrBufferFull if n is larger than b's buffer size. +func (b *Reader) Peek(n int) ([]byte, error) { + if n < 0 { + return nil, ErrNegativeCount + } + if n > len(b.buf) { + return nil, ErrBufferFull + } + // 0 <= n <= len(b.buf) + for b.w-b.r < n && b.err == nil { + b.fill() // b.w-b.r < len(b.buf) => buffer is not full + } + + var err error + if avail := b.w - b.r; avail < n { + // not enough data in buffer + n = avail + err = b.readErr() + if err == nil { + err = ErrBufferFull + } + } + return b.buf[b.r : b.r+n], err +} + +// Read reads data into p. +// It returns the number of bytes read into p. +// It calls Read at most once on the underlying Reader, +// hence n may be less than len(p). +// At EOF, the count will be zero and err will be io.EOF. +func (b *Reader) Read(p []byte) (n int, err error) { + n = len(p) + if n == 0 { + return 0, b.readErr() + } + if b.r == b.w { + if b.err != nil { + return 0, b.readErr() + } + if len(p) >= len(b.buf) { + // Large read, empty buffer. + // Read directly into p to avoid copy. + n, b.err = b.rd.Read(p) + if n < 0 { + panic(errNegativeRead) + } + if n > 0 { + b.lastByte = int(p[n-1]) + b.lastRuneSize = -1 + } + return n, b.readErr() + } + b.fill() // buffer is empty + if b.r == b.w { + return 0, b.readErr() + } + } + + // copy as much as we can + n = copy(p, b.buf[b.r:b.w]) + b.r += n + b.lastByte = int(b.buf[b.r-1]) + b.lastRuneSize = -1 + return n, nil +} + +// ReadByte reads and returns a single byte. +// If no byte is available, returns an error. +func (b *Reader) ReadByte() (c byte, err error) { + b.lastRuneSize = -1 + for b.r == b.w { + if b.err != nil { + return 0, b.readErr() + } + b.fill() // buffer is empty + } + c = b.buf[b.r] + b.r++ + b.lastByte = int(c) + return c, nil +} + +// UnreadByte unreads the last byte. Only the most recently read byte can be unread. +func (b *Reader) UnreadByte() error { + if b.lastByte < 0 || b.r == 0 && b.w > 0 { + return ErrInvalidUnreadByte + } + // b.r > 0 || b.w == 0 + if b.r > 0 { + b.r-- + } else { + // b.r == 0 && b.w == 0 + b.w = 1 + } + b.buf[b.r] = byte(b.lastByte) + b.lastByte = -1 + b.lastRuneSize = -1 + return nil +} + +// ReadRune reads a single UTF-8 encoded Unicode character and returns the +// rune and its size in bytes. If the encoded rune is invalid, it consumes one byte +// and returns unicode.ReplacementChar (U+FFFD) with a size of 1. +func (b *Reader) ReadRune() (r rune, size int, err error) { + for b.r+utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil && b.w-b.r < len(b.buf) { + b.fill() // b.w-b.r < len(buf) => buffer is not full + } + b.lastRuneSize = -1 + if b.r == b.w { + return 0, 0, b.readErr() + } + r, size = rune(b.buf[b.r]), 1 + if r >= 0x80 { + r, size = utf8.DecodeRune(b.buf[b.r:b.w]) + } + b.r += size + b.lastByte = int(b.buf[b.r-1]) + b.lastRuneSize = size + return r, size, nil +} + +// UnreadRune unreads the last rune. If the most recent read operation on +// the buffer was not a ReadRune, UnreadRune returns an error. (In this +// regard it is stricter than UnreadByte, which will unread the last byte +// from any read operation.) +func (b *Reader) UnreadRune() error { + if b.lastRuneSize < 0 || b.r < b.lastRuneSize { + return ErrInvalidUnreadRune + } + b.r -= b.lastRuneSize + b.lastByte = -1 + b.lastRuneSize = -1 + return nil +} + +// Buffered returns the number of bytes that can be read from the current buffer. +func (b *Reader) Buffered() int { return b.w - b.r } + +// ReadSlice reads until the first occurrence of delim in the input, +// returning a slice pointing at the bytes in the buffer. +// The bytes stop being valid at the next read. +// If ReadSlice encounters an error before finding a delimiter, +// it returns all the data in the buffer and the error itself (often io.EOF). +// ReadSlice fails with error ErrBufferFull if the buffer fills without a delim. +// Because the data returned from ReadSlice will be overwritten +// by the next I/O operation, most clients should use +// ReadBytes or ReadString instead. +// ReadSlice returns err != nil if and only if line does not end in delim. +func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { + for { + // Search buffer. + if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 { + line = b.buf[b.r : b.r+i+1] + b.r += i + 1 + break + } + + // Pending error? + if b.err != nil { + line = b.buf[b.r:b.w] + b.r = b.w + err = b.readErr() + break + } + + // Buffer full? + if b.Buffered() >= len(b.buf) { + b.r = b.w + line = b.buf + err = ErrBufferFull + break + } + + b.fill() // buffer is not full + } + + // Handle last byte, if any. + if i := len(line) - 1; i >= 0 { + b.lastByte = int(line[i]) + b.lastRuneSize = -1 + } + + return +} + +// ReadLine is a low-level line-reading primitive. Most callers should use +// ReadBytes('\n') or ReadString('\n') instead or use a Scanner. +// +// ReadLine tries to return a single line, not including the end-of-line bytes. +// If the line was too long for the buffer then isPrefix is set and the +// beginning of the line is returned. The rest of the line will be returned +// from future calls. isPrefix will be false when returning the last fragment +// of the line. The returned buffer is only valid until the next call to +// ReadLine. ReadLine either returns a non-nil line or it returns an error, +// never both. +// +// The text returned from ReadLine does not include the line end ("\r\n" or "\n"). +// No indication or error is given if the input ends without a final line end. +// Calling UnreadByte after ReadLine will always unread the last byte read +// (possibly a character belonging to the line end) even if that byte is not +// part of the line returned by ReadLine. +func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { + line, err = b.ReadSlice('\n') + if err == ErrBufferFull { + // Handle the case where "\r\n" straddles the buffer. + if len(line) > 0 && line[len(line)-1] == '\r' { + // Put the '\r' back on buf and drop it from line. + // Let the next call to ReadLine check for "\r\n". + if b.r == 0 { + // should be unreachable + panic("bufio: tried to rewind past start of buffer") + } + b.r-- + line = line[:len(line)-1] + } + return line, true, nil + } + + if len(line) == 0 { + if err != nil { + line = nil + } + return + } + err = nil + + if line[len(line)-1] == '\n' { + drop := 1 + if len(line) > 1 && line[len(line)-2] == '\r' { + drop = 2 + } + line = line[:len(line)-drop] + } + return +} + +// ReadBytes reads until the first occurrence of delim in the input, +// returning a slice containing the data up to and including the delimiter. +// If ReadBytes encounters an error before finding a delimiter, +// it returns the data read before the error and the error itself (often io.EOF). +// ReadBytes returns err != nil if and only if the returned data does not end in +// delim. +// For simple uses, a Scanner may be more convenient. +func (b *Reader) ReadBytes(delim byte) (line []byte, err error) { + // Use ReadSlice to look for array, + // accumulating full buffers. + var frag []byte + var full [][]byte + err = nil + + for { + var e error + frag, e = b.ReadSlice(delim) + if e == nil { // got final fragment + break + } + if e != ErrBufferFull { // unexpected error + err = e + break + } + + // Make a copy of the buffer. + buf := make([]byte, len(frag)) + copy(buf, frag) + full = append(full, buf) + } + + // Allocate new buffer to hold the full pieces and the fragment. + n := 0 + for i := range full { + n += len(full[i]) + } + n += len(frag) + + // Copy full pieces and fragment in. + buf := make([]byte, n) + n = 0 + for i := range full { + n += copy(buf[n:], full[i]) + } + copy(buf[n:], frag) + return buf, err +} + +// ReadString reads until the first occurrence of delim in the input, +// returning a string containing the data up to and including the delimiter. +// If ReadString encounters an error before finding a delimiter, +// it returns the data read before the error and the error itself (often io.EOF). +// ReadString returns err != nil if and only if the returned data does not end in +// delim. +// For simple uses, a Scanner may be more convenient. +func (b *Reader) ReadString(delim byte) (line string, err error) { + bytes, err := b.ReadBytes(delim) + line = string(bytes) + return line, err +} + +// WriteTo implements io.WriterTo. +func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { + n, err = b.writeBuf(w) + if err != nil { + return + } + + if r, ok := b.rd.(io.WriterTo); ok { + m, err := r.WriteTo(w) + n += m + return n, err + } + + if w, ok := w.(io.ReaderFrom); ok { + m, err := w.ReadFrom(b.rd) + n += m + return n, err + } + + if b.w-b.r < len(b.buf) { + b.fill() // buffer not full + } + + for b.r < b.w { + // b.r < b.w => buffer is not empty + m, err := b.writeBuf(w) + n += m + if err != nil { + return n, err + } + b.fill() // buffer is empty + } + + if b.err == io.EOF { + b.err = nil + } + + return n, b.readErr() +} + +var errNegativeWrite = errors.New("bufio: writer returned negative count from Write") + +// writeBuf writes the Reader's buffer to the writer. +func (b *Reader) writeBuf(w io.Writer) (int64, error) { + n, err := w.Write(b.buf[b.r:b.w]) + if n < 0 { + panic(errNegativeWrite) + } + b.r += n + return int64(n), err +} + +// buffered output + +// Writer implements buffering for an io.Writer object. +// If an error occurs writing to a Writer, no more data will be +// accepted and all subsequent writes will return the error. +// After all data has been written, the client should call the +// Flush method to guarantee all data has been forwarded to +// the underlying io.Writer. +type Writer struct { + err error + buf []byte + n int + wr io.Writer +} + +// NewWriterSize returns a new Writer whose buffer has at least the specified +// size. If the argument io.Writer is already a Writer with large enough +// size, it returns the underlying Writer. +func NewWriterSize(w io.Writer, size int) *Writer { + // Is it already a Writer? + b, ok := w.(*Writer) + if ok && len(b.buf) >= size { + return b + } + if size <= 0 { + size = defaultBufSize + } + return &Writer{ + buf: make([]byte, size), + wr: w, + } +} + +// NewWriter returns a new Writer whose buffer has the default size. +func NewWriter(w io.Writer) *Writer { + return NewWriterSize(w, defaultBufSize) +} + +// Reset discards any unflushed buffered data, clears any error, and +// resets b to write its output to w. +func (b *Writer) Reset(w io.Writer) { + b.err = nil + b.n = 0 + b.wr = w +} + +// Flush writes any buffered data to the underlying io.Writer. +func (b *Writer) Flush() error { + err := b.flush() + return err +} + +func (b *Writer) flush() error { + if b.err != nil { + return b.err + } + if b.n == 0 { + return nil + } + n, err := b.wr.Write(b.buf[0:b.n]) + if n < b.n && err == nil { + err = io.ErrShortWrite + } + if err != nil { + if n > 0 && n < b.n { + copy(b.buf[0:b.n-n], b.buf[n:b.n]) + } + b.n -= n + b.err = err + return err + } + b.n = 0 + return nil +} + +// Available returns how many bytes are unused in the buffer. +func (b *Writer) Available() int { return len(b.buf) - b.n } + +// Buffered returns the number of bytes that have been written into the current buffer. +func (b *Writer) Buffered() int { return b.n } + +// Write writes the contents of p into the buffer. +// It returns the number of bytes written. +// If nn < len(p), it also returns an error explaining +// why the write is short. +func (b *Writer) Write(p []byte) (nn int, err error) { + for len(p) > b.Available() && b.err == nil { + var n int + if b.Buffered() == 0 { + // Large write, empty buffer. + // Write directly from p to avoid copy. + n, b.err = b.wr.Write(p) + } else { + n = copy(b.buf[b.n:], p) + b.n += n + b.flush() + } + nn += n + p = p[n:] + } + if b.err != nil { + return nn, b.err + } + n := copy(b.buf[b.n:], p) + b.n += n + nn += n + return nn, nil +} + +// WriteByte writes a single byte. +func (b *Writer) WriteByte(c byte) error { + if b.err != nil { + return b.err + } + if b.Available() <= 0 && b.flush() != nil { + return b.err + } + b.buf[b.n] = c + b.n++ + return nil +} + +// WriteRune writes a single Unicode code point, returning +// the number of bytes written and any error. +func (b *Writer) WriteRune(r rune) (size int, err error) { + if r < utf8.RuneSelf { + err = b.WriteByte(byte(r)) + if err != nil { + return 0, err + } + return 1, nil + } + if b.err != nil { + return 0, b.err + } + n := b.Available() + if n < utf8.UTFMax { + if b.flush(); b.err != nil { + return 0, b.err + } + n = b.Available() + if n < utf8.UTFMax { + // Can only happen if buffer is silly small. + return b.WriteString(string(r)) + } + } + size = utf8.EncodeRune(b.buf[b.n:], r) + b.n += size + return size, nil +} + +// WriteString writes a string. +// It returns the number of bytes written. +// If the count is less than len(s), it also returns an error explaining +// why the write is short. +func (b *Writer) WriteString(s string) (int, error) { + nn := 0 + for len(s) > b.Available() && b.err == nil { + n := copy(b.buf[b.n:], s) + b.n += n + nn += n + s = s[n:] + b.flush() + } + if b.err != nil { + return nn, b.err + } + n := copy(b.buf[b.n:], s) + b.n += n + nn += n + return nn, nil +} + +// ReadFrom implements io.ReaderFrom. +func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { + if b.Buffered() == 0 { + if w, ok := b.wr.(io.ReaderFrom); ok { + return w.ReadFrom(r) + } + } + var m int + for { + if b.Available() == 0 { + if err1 := b.flush(); err1 != nil { + return n, err1 + } + } + nr := 0 + for nr < maxConsecutiveEmptyReads { + m, err = r.Read(b.buf[b.n:]) + if m != 0 || err != nil { + break + } + nr++ + } + if nr == maxConsecutiveEmptyReads { + return n, io.ErrNoProgress + } + b.n += m + n += int64(m) + if err != nil { + break + } + } + if err == io.EOF { + // If we filled the buffer exactly, flush pre-emptively. + if b.Available() == 0 { + err = b.flush() + } else { + err = nil + } + } + return n, err +} + +// buffered input and output + +// ReadWriter stores pointers to a Reader and a Writer. +// It implements io.ReadWriter. +type ReadWriter struct { + *Reader + *Writer +} + +// NewReadWriter allocates a new ReadWriter that dispatches to r and w. +func NewReadWriter(r *Reader, w *Writer) *ReadWriter { + return &ReadWriter{r, w} +} diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go new file mode 100644 index 000000000..550dac917 --- /dev/null +++ b/src/bufio/bufio_test.go @@ -0,0 +1,1426 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bufio_test + +import ( + . "bufio" + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "strings" + "testing" + "testing/iotest" + "time" + "unicode/utf8" +) + +// Reads from a reader and rot13s the result. +type rot13Reader struct { + r io.Reader +} + +func newRot13Reader(r io.Reader) *rot13Reader { + r13 := new(rot13Reader) + r13.r = r + return r13 +} + +func (r13 *rot13Reader) Read(p []byte) (int, error) { + n, err := r13.r.Read(p) + for i := 0; i < n; i++ { + c := p[i] | 0x20 // lowercase byte + if 'a' <= c && c <= 'm' { + p[i] += 13 + } else if 'n' <= c && c <= 'z' { + p[i] -= 13 + } + } + return n, err +} + +// Call ReadByte to accumulate the text of a file +func readBytes(buf *Reader) string { + var b [1000]byte + nb := 0 + for { + c, err := buf.ReadByte() + if err == io.EOF { + break + } + if err == nil { + b[nb] = c + nb++ + } else if err != iotest.ErrTimeout { + panic("Data: " + err.Error()) + } + } + return string(b[0:nb]) +} + +func TestReaderSimple(t *testing.T) { + data := "hello world" + b := NewReader(strings.NewReader(data)) + if s := readBytes(b); s != "hello world" { + t.Errorf("simple hello world test failed: got %q", s) + } + + b = NewReader(newRot13Reader(strings.NewReader(data))) + if s := readBytes(b); s != "uryyb jbeyq" { + t.Errorf("rot13 hello world test failed: got %q", s) + } +} + +type readMaker struct { + name string + fn func(io.Reader) io.Reader +} + +var readMakers = []readMaker{ + {"full", func(r io.Reader) io.Reader { return r }}, + {"byte", iotest.OneByteReader}, + {"half", iotest.HalfReader}, + {"data+err", iotest.DataErrReader}, + {"timeout", iotest.TimeoutReader}, +} + +// Call ReadString (which ends up calling everything else) +// to accumulate the text of a file. +func readLines(b *Reader) string { + s := "" + for { + s1, err := b.ReadString('\n') + if err == io.EOF { + break + } + if err != nil && err != iotest.ErrTimeout { + panic("GetLines: " + err.Error()) + } + s += s1 + } + return s +} + +// Call Read to accumulate the text of a file +func reads(buf *Reader, m int) string { + var b [1000]byte + nb := 0 + for { + n, err := buf.Read(b[nb : nb+m]) + nb += n + if err == io.EOF { + break + } + } + return string(b[0:nb]) +} + +type bufReader struct { + name string + fn func(*Reader) string +} + +var bufreaders = []bufReader{ + {"1", func(b *Reader) string { return reads(b, 1) }}, + {"2", func(b *Reader) string { return reads(b, 2) }}, + {"3", func(b *Reader) string { return reads(b, 3) }}, + {"4", func(b *Reader) string { return reads(b, 4) }}, + {"5", func(b *Reader) string { return reads(b, 5) }}, + {"7", func(b *Reader) string { return reads(b, 7) }}, + {"bytes", readBytes}, + {"lines", readLines}, +} + +const minReadBufferSize = 16 + +var bufsizes = []int{ + 0, minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096, +} + +func TestReader(t *testing.T) { + var texts [31]string + str := "" + all := "" + for i := 0; i < len(texts)-1; i++ { + texts[i] = str + "\n" + all += texts[i] + str += string(i%26 + 'a') + } + texts[len(texts)-1] = all + + for h := 0; h < len(texts); h++ { + text := texts[h] + for i := 0; i < len(readMakers); i++ { + for j := 0; j < len(bufreaders); j++ { + for k := 0; k < len(bufsizes); k++ { + readmaker := readMakers[i] + bufreader := bufreaders[j] + bufsize := bufsizes[k] + read := readmaker.fn(strings.NewReader(text)) + buf := NewReaderSize(read, bufsize) + s := bufreader.fn(buf) + if s != text { + t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q", + readmaker.name, bufreader.name, bufsize, text, s) + } + } + } + } + } +} + +type zeroReader struct{} + +func (zeroReader) Read(p []byte) (int, error) { + return 0, nil +} + +func TestZeroReader(t *testing.T) { + var z zeroReader + r := NewReader(z) + + c := make(chan error) + go func() { + _, err := r.ReadByte() + c <- err + }() + + select { + case err := <-c: + if err == nil { + t.Error("error expected") + } else if err != io.ErrNoProgress { + t.Error("unexpected error:", err) + } + case <-time.After(time.Second): + t.Error("test timed out (endless loop in ReadByte?)") + } +} + +// A StringReader delivers its data one string segment at a time via Read. +type StringReader struct { + data []string + step int +} + +func (r *StringReader) Read(p []byte) (n int, err error) { + if r.step < len(r.data) { + s := r.data[r.step] + n = copy(p, s) + r.step++ + } else { + err = io.EOF + } + return +} + +func readRuneSegments(t *testing.T, segments []string) { + got := "" + want := strings.Join(segments, "") + r := NewReader(&StringReader{data: segments}) + for { + r, _, err := r.ReadRune() + if err != nil { + if err != io.EOF { + return + } + break + } + got += string(r) + } + if got != want { + t.Errorf("segments=%v got=%s want=%s", segments, got, want) + } +} + +var segmentList = [][]string{ + {}, + {""}, + {"日", "本語"}, + {"\u65e5", "\u672c", "\u8a9e"}, + {"\U000065e5", "\U0000672c", "\U00008a9e"}, + {"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"}, + {"Hello", ", ", "World", "!"}, + {"Hello", ", ", "", "World", "!"}, +} + +func TestReadRune(t *testing.T) { + for _, s := range segmentList { + readRuneSegments(t, s) + } +} + +func TestUnreadRune(t *testing.T) { + segments := []string{"Hello, world:", "日本語"} + r := NewReader(&StringReader{data: segments}) + got := "" + want := strings.Join(segments, "") + // Normal execution. + for { + r1, _, err := r.ReadRune() + if err != nil { + if err != io.EOF { + t.Error("unexpected error on ReadRune:", err) + } + break + } + got += string(r1) + // Put it back and read it again. + if err = r.UnreadRune(); err != nil { + t.Fatal("unexpected error on UnreadRune:", err) + } + r2, _, err := r.ReadRune() + if err != nil { + t.Fatal("unexpected error reading after unreading:", err) + } + if r1 != r2 { + t.Fatalf("incorrect rune after unread: got %c, want %c", r1, r2) + } + } + if got != want { + t.Errorf("got %q, want %q", got, want) + } +} + +func TestUnreadByte(t *testing.T) { + segments := []string{"Hello, ", "world"} + r := NewReader(&StringReader{data: segments}) + got := "" + want := strings.Join(segments, "") + // Normal execution. + for { + b1, err := r.ReadByte() + if err != nil { + if err != io.EOF { + t.Error("unexpected error on ReadByte:", err) + } + break + } + got += string(b1) + // Put it back and read it again. + if err = r.UnreadByte(); err != nil { + t.Fatal("unexpected error on UnreadByte:", err) + } + b2, err := r.ReadByte() + if err != nil { + t.Fatal("unexpected error reading after unreading:", err) + } + if b1 != b2 { + t.Fatalf("incorrect byte after unread: got %q, want %q", b1, b2) + } + } + if got != want { + t.Errorf("got %q, want %q", got, want) + } +} + +func TestUnreadByteMultiple(t *testing.T) { + segments := []string{"Hello, ", "world"} + data := strings.Join(segments, "") + for n := 0; n <= len(data); n++ { + r := NewReader(&StringReader{data: segments}) + // Read n bytes. + for i := 0; i < n; i++ { + b, err := r.ReadByte() + if err != nil { + t.Fatalf("n = %d: unexpected error on ReadByte: %v", n, err) + } + if b != data[i] { + t.Fatalf("n = %d: incorrect byte returned from ReadByte: got %q, want %q", n, b, data[i]) + } + } + // Unread one byte if there is one. + if n > 0 { + if err := r.UnreadByte(); err != nil { + t.Errorf("n = %d: unexpected error on UnreadByte: %v", n, err) + } + } + // Test that we cannot unread any further. + if err := r.UnreadByte(); err == nil { + t.Errorf("n = %d: expected error on UnreadByte", n) + } + } +} + +func TestUnreadByteOthers(t *testing.T) { + // A list of readers to use in conjunction with UnreadByte. + var readers = []func(*Reader, byte) ([]byte, error){ + (*Reader).ReadBytes, + (*Reader).ReadSlice, + func(r *Reader, delim byte) ([]byte, error) { + data, err := r.ReadString(delim) + return []byte(data), err + }, + // ReadLine doesn't fit the data/pattern easily + // so we leave it out. It should be covered via + // the ReadSlice test since ReadLine simply calls + // ReadSlice, and it's that function that handles + // the last byte. + } + + // Try all readers with UnreadByte. + for rno, read := range readers { + // Some input data that is longer than the minimum reader buffer size. + const n = 10 + var buf bytes.Buffer + for i := 0; i < n; i++ { + buf.WriteString("abcdefg") + } + + r := NewReaderSize(&buf, minReadBufferSize) + readTo := func(delim byte, want string) { + data, err := read(r, delim) + if err != nil { + t.Fatalf("#%d: unexpected error reading to %c: %v", rno, delim, err) + } + if got := string(data); got != want { + t.Fatalf("#%d: got %q, want %q", rno, got, want) + } + } + + // Read the data with occasional UnreadByte calls. + for i := 0; i < n; i++ { + readTo('d', "abcd") + for j := 0; j < 3; j++ { + if err := r.UnreadByte(); err != nil { + t.Fatalf("#%d: unexpected error on UnreadByte: %v", rno, err) + } + readTo('d', "d") + } + readTo('g', "efg") + } + + // All data should have been read. + _, err := r.ReadByte() + if err != io.EOF { + t.Errorf("#%d: got error %v; want EOF", rno, err) + } + } +} + +// Test that UnreadRune fails if the preceding operation was not a ReadRune. +func TestUnreadRuneError(t *testing.T) { + buf := make([]byte, 3) // All runes in this test are 3 bytes long + r := NewReader(&StringReader{data: []string{"日本語日本語日本語"}}) + if r.UnreadRune() == nil { + t.Error("expected error on UnreadRune from fresh buffer") + } + _, _, err := r.ReadRune() + if err != nil { + t.Error("unexpected error on ReadRune (1):", err) + } + if err = r.UnreadRune(); err != nil { + t.Error("unexpected error on UnreadRune (1):", err) + } + if r.UnreadRune() == nil { + t.Error("expected error after UnreadRune (1)") + } + // Test error after Read. + _, _, err = r.ReadRune() // reset state + if err != nil { + t.Error("unexpected error on ReadRune (2):", err) + } + _, err = r.Read(buf) + if err != nil { + t.Error("unexpected error on Read (2):", err) + } + if r.UnreadRune() == nil { + t.Error("expected error after Read (2)") + } + // Test error after ReadByte. + _, _, err = r.ReadRune() // reset state + if err != nil { + t.Error("unexpected error on ReadRune (2):", err) + } + for range buf { + _, err = r.ReadByte() + if err != nil { + t.Error("unexpected error on ReadByte (2):", err) + } + } + if r.UnreadRune() == nil { + t.Error("expected error after ReadByte") + } + // Test error after UnreadByte. + _, _, err = r.ReadRune() // reset state + if err != nil { + t.Error("unexpected error on ReadRune (3):", err) + } + _, err = r.ReadByte() + if err != nil { + t.Error("unexpected error on ReadByte (3):", err) + } + err = r.UnreadByte() + if err != nil { + t.Error("unexpected error on UnreadByte (3):", err) + } + if r.UnreadRune() == nil { + t.Error("expected error after UnreadByte (3)") + } + // Test error after ReadSlice. + _, _, err = r.ReadRune() // reset state + if err != nil { + t.Error("unexpected error on ReadRune (4):", err) + } + _, err = r.ReadSlice(0) + if err != io.EOF { + t.Error("unexpected error on ReadSlice (4):", err) + } + if r.UnreadRune() == nil { + t.Error("expected error after ReadSlice (4)") + } +} + +func TestUnreadRuneAtEOF(t *testing.T) { + // UnreadRune/ReadRune should error at EOF (was a bug; used to panic) + r := NewReader(strings.NewReader("x")) + r.ReadRune() + r.ReadRune() + r.UnreadRune() + _, _, err := r.ReadRune() + if err == nil { + t.Error("expected error at EOF") + } else if err != io.EOF { + t.Error("expected EOF; got", err) + } +} + +func TestReadWriteRune(t *testing.T) { + const NRune = 1000 + byteBuf := new(bytes.Buffer) + w := NewWriter(byteBuf) + // Write the runes out using WriteRune + buf := make([]byte, utf8.UTFMax) + for r := rune(0); r < NRune; r++ { + size := utf8.EncodeRune(buf, r) + nbytes, err := w.WriteRune(r) + if err != nil { + t.Fatalf("WriteRune(0x%x) error: %s", r, err) + } + if nbytes != size { + t.Fatalf("WriteRune(0x%x) expected %d, got %d", r, size, nbytes) + } + } + w.Flush() + + r := NewReader(byteBuf) + // Read them back with ReadRune + for r1 := rune(0); r1 < NRune; r1++ { + size := utf8.EncodeRune(buf, r1) + nr, nbytes, err := r.ReadRune() + if nr != r1 || nbytes != size || err != nil { + t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r1, nr, nbytes, r1, size, err) + } + } +} + +func TestWriter(t *testing.T) { + var data [8192]byte + + for i := 0; i < len(data); i++ { + data[i] = byte(' ' + i%('~'-' ')) + } + w := new(bytes.Buffer) + for i := 0; i < len(bufsizes); i++ { + for j := 0; j < len(bufsizes); j++ { + nwrite := bufsizes[i] + bs := bufsizes[j] + + // Write nwrite bytes using buffer size bs. + // Check that the right amount makes it out + // and that the data is correct. + + w.Reset() + buf := NewWriterSize(w, bs) + context := fmt.Sprintf("nwrite=%d bufsize=%d", nwrite, bs) + n, e1 := buf.Write(data[0:nwrite]) + if e1 != nil || n != nwrite { + t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1) + continue + } + if e := buf.Flush(); e != nil { + t.Errorf("%s: buf.Flush = %v", context, e) + } + + written := w.Bytes() + if len(written) != nwrite { + t.Errorf("%s: %d bytes written", context, len(written)) + } + for l := 0; l < len(written); l++ { + if written[i] != data[i] { + t.Errorf("wrong bytes written") + t.Errorf("want=%q", data[0:len(written)]) + t.Errorf("have=%q", written) + } + } + } + } +} + +// Check that write errors are returned properly. + +type errorWriterTest struct { + n, m int + err error + expect error +} + +func (w errorWriterTest) Write(p []byte) (int, error) { + return len(p) * w.n / w.m, w.err +} + +var errorWriterTests = []errorWriterTest{ + {0, 1, nil, io.ErrShortWrite}, + {1, 2, nil, io.ErrShortWrite}, + {1, 1, nil, nil}, + {0, 1, io.ErrClosedPipe, io.ErrClosedPipe}, + {1, 2, io.ErrClosedPipe, io.ErrClosedPipe}, + {1, 1, io.ErrClosedPipe, io.ErrClosedPipe}, +} + +func TestWriteErrors(t *testing.T) { + for _, w := range errorWriterTests { + buf := NewWriter(w) + _, e := buf.Write([]byte("hello world")) + if e != nil { + t.Errorf("Write hello to %v: %v", w, e) + continue + } + // Two flushes, to verify the error is sticky. + for i := 0; i < 2; i++ { + e = buf.Flush() + if e != w.expect { + t.Errorf("Flush %d/2 %v: got %v, wanted %v", i+1, w, e, w.expect) + } + } + } +} + +func TestNewReaderSizeIdempotent(t *testing.T) { + const BufSize = 1000 + b := NewReaderSize(strings.NewReader("hello world"), BufSize) + // Does it recognize itself? + b1 := NewReaderSize(b, BufSize) + if b1 != b { + t.Error("NewReaderSize did not detect underlying Reader") + } + // Does it wrap if existing buffer is too small? + b2 := NewReaderSize(b, 2*BufSize) + if b2 == b { + t.Error("NewReaderSize did not enlarge buffer") + } +} + +func TestNewWriterSizeIdempotent(t *testing.T) { + const BufSize = 1000 + b := NewWriterSize(new(bytes.Buffer), BufSize) + // Does it recognize itself? + b1 := NewWriterSize(b, BufSize) + if b1 != b { + t.Error("NewWriterSize did not detect underlying Writer") + } + // Does it wrap if existing buffer is too small? + b2 := NewWriterSize(b, 2*BufSize) + if b2 == b { + t.Error("NewWriterSize did not enlarge buffer") + } +} + +func TestWriteString(t *testing.T) { + const BufSize = 8 + buf := new(bytes.Buffer) + b := NewWriterSize(buf, BufSize) + b.WriteString("0") // easy + b.WriteString("123456") // still easy + b.WriteString("7890") // easy after flush + b.WriteString("abcdefghijklmnopqrstuvwxy") // hard + b.WriteString("z") + if err := b.Flush(); err != nil { + t.Error("WriteString", err) + } + s := "01234567890abcdefghijklmnopqrstuvwxyz" + if string(buf.Bytes()) != s { + t.Errorf("WriteString wants %q gets %q", s, string(buf.Bytes())) + } +} + +func TestBufferFull(t *testing.T) { + const longString = "And now, hello, world! It is the time for all good men to come to the aid of their party" + buf := NewReaderSize(strings.NewReader(longString), minReadBufferSize) + line, err := buf.ReadSlice('!') + if string(line) != "And now, hello, " || err != ErrBufferFull { + t.Errorf("first ReadSlice(,) = %q, %v", line, err) + } + line, err = buf.ReadSlice('!') + if string(line) != "world!" || err != nil { + t.Errorf("second ReadSlice(,) = %q, %v", line, err) + } +} + +func TestPeek(t *testing.T) { + p := make([]byte, 10) + // string is 16 (minReadBufferSize) long. + buf := NewReaderSize(strings.NewReader("abcdefghijklmnop"), minReadBufferSize) + if s, err := buf.Peek(1); string(s) != "a" || err != nil { + t.Fatalf("want %q got %q, err=%v", "a", string(s), err) + } + if s, err := buf.Peek(4); string(s) != "abcd" || err != nil { + t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err) + } + if _, err := buf.Peek(-1); err != ErrNegativeCount { + t.Fatalf("want ErrNegativeCount got %v", err) + } + if _, err := buf.Peek(32); err != ErrBufferFull { + t.Fatalf("want ErrBufFull got %v", err) + } + if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil { + t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err) + } + if s, err := buf.Peek(1); string(s) != "d" || err != nil { + t.Fatalf("want %q got %q, err=%v", "d", string(s), err) + } + if s, err := buf.Peek(2); string(s) != "de" || err != nil { + t.Fatalf("want %q got %q, err=%v", "de", string(s), err) + } + if _, err := buf.Read(p[0:3]); string(p[0:3]) != "def" || err != nil { + t.Fatalf("want %q got %q, err=%v", "def", string(p[0:3]), err) + } + if s, err := buf.Peek(4); string(s) != "ghij" || err != nil { + t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err) + } + if _, err := buf.Read(p[0:]); string(p[0:]) != "ghijklmnop" || err != nil { + t.Fatalf("want %q got %q, err=%v", "ghijklmnop", string(p[0:minReadBufferSize]), err) + } + if s, err := buf.Peek(0); string(s) != "" || err != nil { + t.Fatalf("want %q got %q, err=%v", "", string(s), err) + } + if _, err := buf.Peek(1); err != io.EOF { + t.Fatalf("want EOF got %v", err) + } + + // Test for issue 3022, not exposing a reader's error on a successful Peek. + buf = NewReaderSize(dataAndEOFReader("abcd"), 32) + if s, err := buf.Peek(2); string(s) != "ab" || err != nil { + t.Errorf(`Peek(2) on "abcd", EOF = %q, %v; want "ab", nil`, string(s), err) + } + if s, err := buf.Peek(4); string(s) != "abcd" || err != nil { + t.Errorf(`Peek(4) on "abcd", EOF = %q, %v; want "abcd", nil`, string(s), err) + } + if n, err := buf.Read(p[0:5]); string(p[0:n]) != "abcd" || err != nil { + t.Fatalf("Read after peek = %q, %v; want abcd, EOF", p[0:n], err) + } + if n, err := buf.Read(p[0:1]); string(p[0:n]) != "" || err != io.EOF { + t.Fatalf(`second Read after peek = %q, %v; want "", EOF`, p[0:n], err) + } +} + +type dataAndEOFReader string + +func (r dataAndEOFReader) Read(p []byte) (int, error) { + return copy(p, r), io.EOF +} + +func TestPeekThenUnreadRune(t *testing.T) { + // This sequence used to cause a crash. + r := NewReader(strings.NewReader("x")) + r.ReadRune() + r.Peek(1) + r.UnreadRune() + r.ReadRune() // Used to panic here +} + +var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy") +var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy") +var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n") + +// TestReader wraps a []byte and returns reads of a specific length. +type testReader struct { + data []byte + stride int +} + +func (t *testReader) Read(buf []byte) (n int, err error) { + n = t.stride + if n > len(t.data) { + n = len(t.data) + } + if n > len(buf) { + n = len(buf) + } + copy(buf, t.data) + t.data = t.data[n:] + if len(t.data) == 0 { + err = io.EOF + } + return +} + +func testReadLine(t *testing.T, input []byte) { + //for stride := 1; stride < len(input); stride++ { + for stride := 1; stride < 2; stride++ { + done := 0 + reader := testReader{input, stride} + l := NewReaderSize(&reader, len(input)+1) + for { + line, isPrefix, err := l.ReadLine() + if len(line) > 0 && err != nil { + t.Errorf("ReadLine returned both data and error: %s", err) + } + if isPrefix { + t.Errorf("ReadLine returned prefix") + } + if err != nil { + if err != io.EOF { + t.Fatalf("Got unknown error: %s", err) + } + break + } + if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) { + t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line) + } + done += len(line) + } + if done != len(testOutput) { + t.Errorf("ReadLine didn't return everything: got: %d, want: %d (stride: %d)", done, len(testOutput), stride) + } + } +} + +func TestReadLine(t *testing.T) { + testReadLine(t, testInput) + testReadLine(t, testInputrn) +} + +func TestLineTooLong(t *testing.T) { + data := make([]byte, 0) + for i := 0; i < minReadBufferSize*5/2; i++ { + data = append(data, '0'+byte(i%10)) + } + buf := bytes.NewReader(data) + l := NewReaderSize(buf, minReadBufferSize) + line, isPrefix, err := l.ReadLine() + if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil { + t.Errorf("bad result for first line: got %q want %q %v", line, data[:minReadBufferSize], err) + } + data = data[len(line):] + line, isPrefix, err = l.ReadLine() + if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil { + t.Errorf("bad result for second line: got %q want %q %v", line, data[:minReadBufferSize], err) + } + data = data[len(line):] + line, isPrefix, err = l.ReadLine() + if isPrefix || !bytes.Equal(line, data[:minReadBufferSize/2]) || err != nil { + t.Errorf("bad result for third line: got %q want %q %v", line, data[:minReadBufferSize/2], err) + } + line, isPrefix, err = l.ReadLine() + if isPrefix || err == nil { + t.Errorf("expected no more lines: %x %s", line, err) + } +} + +func TestReadAfterLines(t *testing.T) { + line1 := "this is line1" + restData := "this is line2\nthis is line 3\n" + inbuf := bytes.NewReader([]byte(line1 + "\n" + restData)) + outbuf := new(bytes.Buffer) + maxLineLength := len(line1) + len(restData)/2 + l := NewReaderSize(inbuf, maxLineLength) + line, isPrefix, err := l.ReadLine() + if isPrefix || err != nil || string(line) != line1 { + t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line)) + } + n, err := io.Copy(outbuf, l) + if int(n) != len(restData) || err != nil { + t.Errorf("bad result for Read: n=%d err=%v", n, err) + } + if outbuf.String() != restData { + t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData) + } +} + +func TestReadEmptyBuffer(t *testing.T) { + l := NewReaderSize(new(bytes.Buffer), minReadBufferSize) + line, isPrefix, err := l.ReadLine() + if err != io.EOF { + t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err) + } +} + +func TestLinesAfterRead(t *testing.T) { + l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize) + _, err := ioutil.ReadAll(l) + if err != nil { + t.Error(err) + return + } + + line, isPrefix, err := l.ReadLine() + if err != io.EOF { + t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err) + } +} + +func TestReadLineNonNilLineOrError(t *testing.T) { + r := NewReader(strings.NewReader("line 1\n")) + for i := 0; i < 2; i++ { + l, _, err := r.ReadLine() + if l != nil && err != nil { + t.Fatalf("on line %d/2; ReadLine=%#v, %v; want non-nil line or Error, but not both", + i+1, l, err) + } + } +} + +type readLineResult struct { + line []byte + isPrefix bool + err error +} + +var readLineNewlinesTests = []struct { + input string + expect []readLineResult +}{ + {"012345678901234\r\n012345678901234\r\n", []readLineResult{ + {[]byte("012345678901234"), true, nil}, + {nil, false, nil}, + {[]byte("012345678901234"), true, nil}, + {nil, false, nil}, + {nil, false, io.EOF}, + }}, + {"0123456789012345\r012345678901234\r", []readLineResult{ + {[]byte("0123456789012345"), true, nil}, + {[]byte("\r012345678901234"), true, nil}, + {[]byte("\r"), false, nil}, + {nil, false, io.EOF}, + }}, +} + +func TestReadLineNewlines(t *testing.T) { + for _, e := range readLineNewlinesTests { + testReadLineNewlines(t, e.input, e.expect) + } +} + +func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) { + b := NewReaderSize(strings.NewReader(input), minReadBufferSize) + for i, e := range expect { + line, isPrefix, err := b.ReadLine() + if !bytes.Equal(line, e.line) { + t.Errorf("%q call %d, line == %q, want %q", input, i, line, e.line) + return + } + if isPrefix != e.isPrefix { + t.Errorf("%q call %d, isPrefix == %v, want %v", input, i, isPrefix, e.isPrefix) + return + } + if err != e.err { + t.Errorf("%q call %d, err == %v, want %v", input, i, err, e.err) + return + } + } +} + +func createTestInput(n int) []byte { + input := make([]byte, n) + for i := range input { + // 101 and 251 are arbitrary prime numbers. + // The idea is to create an input sequence + // which doesn't repeat too frequently. + input[i] = byte(i % 251) + if i%101 == 0 { + input[i] ^= byte(i / 101) + } + } + return input +} + +func TestReaderWriteTo(t *testing.T) { + input := createTestInput(8192) + r := NewReader(onlyReader{bytes.NewReader(input)}) + w := new(bytes.Buffer) + if n, err := r.WriteTo(w); err != nil || n != int64(len(input)) { + t.Fatalf("r.WriteTo(w) = %d, %v, want %d, nil", n, err, len(input)) + } + + for i, val := range w.Bytes() { + if val != input[i] { + t.Errorf("after write: out[%d] = %#x, want %#x", i, val, input[i]) + } + } +} + +type errorWriterToTest struct { + rn, wn int + rerr, werr error + expected error +} + +func (r errorWriterToTest) Read(p []byte) (int, error) { + return len(p) * r.rn, r.rerr +} + +func (w errorWriterToTest) Write(p []byte) (int, error) { + return len(p) * w.wn, w.werr +} + +var errorWriterToTests = []errorWriterToTest{ + {1, 0, nil, io.ErrClosedPipe, io.ErrClosedPipe}, + {0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe}, + {0, 0, io.ErrUnexpectedEOF, io.ErrClosedPipe, io.ErrClosedPipe}, + {0, 1, io.EOF, nil, nil}, +} + +func TestReaderWriteToErrors(t *testing.T) { + for i, rw := range errorWriterToTests { + r := NewReader(rw) + if _, err := r.WriteTo(rw); err != rw.expected { + t.Errorf("r.WriteTo(errorWriterToTests[%d]) = _, %v, want _,%v", i, err, rw.expected) + } + } +} + +func TestWriterReadFrom(t *testing.T) { + ws := []func(io.Writer) io.Writer{ + func(w io.Writer) io.Writer { return onlyWriter{w} }, + func(w io.Writer) io.Writer { return w }, + } + + rs := []func(io.Reader) io.Reader{ + iotest.DataErrReader, + func(r io.Reader) io.Reader { return r }, + } + + for ri, rfunc := range rs { + for wi, wfunc := range ws { + input := createTestInput(8192) + b := new(bytes.Buffer) + w := NewWriter(wfunc(b)) + r := rfunc(bytes.NewReader(input)) + if n, err := w.ReadFrom(r); err != nil || n != int64(len(input)) { + t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input)) + continue + } + if err := w.Flush(); err != nil { + t.Errorf("Flush returned %v", err) + continue + } + if got, want := b.String(), string(input); got != want { + t.Errorf("ws[%d], rs[%d]:\ngot %q\nwant %q\n", wi, ri, got, want) + } + } + } +} + +type errorReaderFromTest struct { + rn, wn int + rerr, werr error + expected error +} + +func (r errorReaderFromTest) Read(p []byte) (int, error) { + return len(p) * r.rn, r.rerr +} + +func (w errorReaderFromTest) Write(p []byte) (int, error) { + return len(p) * w.wn, w.werr +} + +var errorReaderFromTests = []errorReaderFromTest{ + {0, 1, io.EOF, nil, nil}, + {1, 1, io.EOF, nil, nil}, + {0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe}, + {0, 0, io.ErrClosedPipe, io.ErrShortWrite, io.ErrClosedPipe}, + {1, 0, nil, io.ErrShortWrite, io.ErrShortWrite}, +} + +func TestWriterReadFromErrors(t *testing.T) { + for i, rw := range errorReaderFromTests { + w := NewWriter(rw) + if _, err := w.ReadFrom(rw); err != rw.expected { + t.Errorf("w.ReadFrom(errorReaderFromTests[%d]) = _, %v, want _,%v", i, err, rw.expected) + } + } +} + +// TestWriterReadFromCounts tests that using io.Copy to copy into a +// bufio.Writer does not prematurely flush the buffer. For example, when +// buffering writes to a network socket, excessive network writes should be +// avoided. +func TestWriterReadFromCounts(t *testing.T) { + var w0 writeCountingDiscard + b0 := NewWriterSize(&w0, 1234) + b0.WriteString(strings.Repeat("x", 1000)) + if w0 != 0 { + t.Fatalf("write 1000 'x's: got %d writes, want 0", w0) + } + b0.WriteString(strings.Repeat("x", 200)) + if w0 != 0 { + t.Fatalf("write 1200 'x's: got %d writes, want 0", w0) + } + io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 30))}) + if w0 != 0 { + t.Fatalf("write 1230 'x's: got %d writes, want 0", w0) + } + io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 9))}) + if w0 != 1 { + t.Fatalf("write 1239 'x's: got %d writes, want 1", w0) + } + + var w1 writeCountingDiscard + b1 := NewWriterSize(&w1, 1234) + b1.WriteString(strings.Repeat("x", 1200)) + b1.Flush() + if w1 != 1 { + t.Fatalf("flush 1200 'x's: got %d writes, want 1", w1) + } + b1.WriteString(strings.Repeat("x", 89)) + if w1 != 1 { + t.Fatalf("write 1200 + 89 'x's: got %d writes, want 1", w1) + } + io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 700))}) + if w1 != 1 { + t.Fatalf("write 1200 + 789 'x's: got %d writes, want 1", w1) + } + io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 600))}) + if w1 != 2 { + t.Fatalf("write 1200 + 1389 'x's: got %d writes, want 2", w1) + } + b1.Flush() + if w1 != 3 { + t.Fatalf("flush 1200 + 1389 'x's: got %d writes, want 3", w1) + } +} + +// A writeCountingDiscard is like ioutil.Discard and counts the number of times +// Write is called on it. +type writeCountingDiscard int + +func (w *writeCountingDiscard) Write(p []byte) (int, error) { + *w++ + return len(p), nil +} + +type negativeReader int + +func (r *negativeReader) Read([]byte) (int, error) { return -1, nil } + +func TestNegativeRead(t *testing.T) { + // should panic with a description pointing at the reader, not at itself. + // (should NOT panic with slice index error, for example.) + b := NewReader(new(negativeReader)) + defer func() { + switch err := recover().(type) { + case nil: + t.Fatal("read did not panic") + case error: + if !strings.Contains(err.Error(), "reader returned negative count from Read") { + t.Fatalf("wrong panic: %v", err) + } + default: + t.Fatalf("unexpected panic value: %T(%v)", err, err) + } + }() + b.Read(make([]byte, 100)) +} + +var errFake = errors.New("fake error") + +type errorThenGoodReader struct { + didErr bool + nread int +} + +func (r *errorThenGoodReader) Read(p []byte) (int, error) { + r.nread++ + if !r.didErr { + r.didErr = true + return 0, errFake + } + return len(p), nil +} + +func TestReaderClearError(t *testing.T) { + r := &errorThenGoodReader{} + b := NewReader(r) + buf := make([]byte, 1) + if _, err := b.Read(nil); err != nil { + t.Fatalf("1st nil Read = %v; want nil", err) + } + if _, err := b.Read(buf); err != errFake { + t.Fatalf("1st Read = %v; want errFake", err) + } + if _, err := b.Read(nil); err != nil { + t.Fatalf("2nd nil Read = %v; want nil", err) + } + if _, err := b.Read(buf); err != nil { + t.Fatalf("3rd Read with buffer = %v; want nil", err) + } + if r.nread != 2 { + t.Errorf("num reads = %d; want 2", r.nread) + } +} + +// Test for golang.org/issue/5947 +func TestWriterReadFromWhileFull(t *testing.T) { + buf := new(bytes.Buffer) + w := NewWriterSize(buf, 10) + + // Fill buffer exactly. + n, err := w.Write([]byte("0123456789")) + if n != 10 || err != nil { + t.Fatalf("Write returned (%v, %v), want (10, nil)", n, err) + } + + // Use ReadFrom to read in some data. + n2, err := w.ReadFrom(strings.NewReader("abcdef")) + if n2 != 6 || err != nil { + t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n2, err) + } +} + +type emptyThenNonEmptyReader struct { + r io.Reader + n int +} + +func (r *emptyThenNonEmptyReader) Read(p []byte) (int, error) { + if r.n <= 0 { + return r.r.Read(p) + } + r.n-- + return 0, nil +} + +// Test for golang.org/issue/7611 +func TestWriterReadFromUntilEOF(t *testing.T) { + buf := new(bytes.Buffer) + w := NewWriterSize(buf, 5) + + // Partially fill buffer + n, err := w.Write([]byte("0123")) + if n != 4 || err != nil { + t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err) + } + + // Use ReadFrom to read in some data. + r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 3} + n2, err := w.ReadFrom(r) + if n2 != 4 || err != nil { + t.Fatalf("ReadFrom returned (%v, %v), want (4, nil)", n2, err) + } + w.Flush() + if got, want := string(buf.Bytes()), "0123abcd"; got != want { + t.Fatalf("buf.Bytes() returned %q, want %q", got, want) + } +} + +func TestWriterReadFromErrNoProgress(t *testing.T) { + buf := new(bytes.Buffer) + w := NewWriterSize(buf, 5) + + // Partially fill buffer + n, err := w.Write([]byte("0123")) + if n != 4 || err != nil { + t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err) + } + + // Use ReadFrom to read in some data. + r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 100} + n2, err := w.ReadFrom(r) + if n2 != 0 || err != io.ErrNoProgress { + t.Fatalf("buf.Bytes() returned (%v, %v), want (0, io.ErrNoProgress)", n2, err) + } +} + +func TestReaderReset(t *testing.T) { + r := NewReader(strings.NewReader("foo foo")) + buf := make([]byte, 3) + r.Read(buf) + if string(buf) != "foo" { + t.Errorf("buf = %q; want foo", buf) + } + r.Reset(strings.NewReader("bar bar")) + all, err := ioutil.ReadAll(r) + if err != nil { + t.Fatal(err) + } + if string(all) != "bar bar" { + t.Errorf("ReadAll = %q; want bar bar", all) + } +} + +func TestWriterReset(t *testing.T) { + var buf1, buf2 bytes.Buffer + w := NewWriter(&buf1) + w.WriteString("foo") + w.Reset(&buf2) // and not flushed + w.WriteString("bar") + w.Flush() + if buf1.String() != "" { + t.Errorf("buf1 = %q; want empty", buf1.String()) + } + if buf2.String() != "bar" { + t.Errorf("buf2 = %q; want bar", buf2.String()) + } +} + +// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have. +type onlyReader struct { + io.Reader +} + +// An onlyWriter only implements io.Writer, no matter what other methods the underlying implementation may have. +type onlyWriter struct { + io.Writer +} + +func BenchmarkReaderCopyOptimal(b *testing.B) { + // Optimal case is where the underlying reader implements io.WriterTo + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := NewReader(srcBuf) + dstBuf := new(bytes.Buffer) + dst := onlyWriter{dstBuf} + for i := 0; i < b.N; i++ { + srcBuf.Reset() + src.Reset(srcBuf) + dstBuf.Reset() + io.Copy(dst, src) + } +} + +func BenchmarkReaderCopyUnoptimal(b *testing.B) { + // Unoptimal case is where the underlying reader doesn't implement io.WriterTo + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := NewReader(onlyReader{srcBuf}) + dstBuf := new(bytes.Buffer) + dst := onlyWriter{dstBuf} + for i := 0; i < b.N; i++ { + srcBuf.Reset() + src.Reset(onlyReader{srcBuf}) + dstBuf.Reset() + io.Copy(dst, src) + } +} + +func BenchmarkReaderCopyNoWriteTo(b *testing.B) { + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + srcReader := NewReader(srcBuf) + src := onlyReader{srcReader} + dstBuf := new(bytes.Buffer) + dst := onlyWriter{dstBuf} + for i := 0; i < b.N; i++ { + srcBuf.Reset() + srcReader.Reset(srcBuf) + dstBuf.Reset() + io.Copy(dst, src) + } +} + +func BenchmarkReaderWriteToOptimal(b *testing.B) { + const bufSize = 16 << 10 + buf := make([]byte, bufSize) + r := bytes.NewReader(buf) + srcReader := NewReaderSize(onlyReader{r}, 1<<10) + if _, ok := ioutil.Discard.(io.ReaderFrom); !ok { + b.Fatal("ioutil.Discard doesn't support ReaderFrom") + } + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + srcReader.Reset(onlyReader{r}) + n, err := srcReader.WriteTo(ioutil.Discard) + if err != nil { + b.Fatal(err) + } + if n != bufSize { + b.Fatalf("n = %d; want %d", n, bufSize) + } + } +} + +func BenchmarkWriterCopyOptimal(b *testing.B) { + // Optimal case is where the underlying writer implements io.ReaderFrom + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := onlyReader{srcBuf} + dstBuf := new(bytes.Buffer) + dst := NewWriter(dstBuf) + for i := 0; i < b.N; i++ { + srcBuf.Reset() + dstBuf.Reset() + dst.Reset(dstBuf) + io.Copy(dst, src) + } +} + +func BenchmarkWriterCopyUnoptimal(b *testing.B) { + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := onlyReader{srcBuf} + dstBuf := new(bytes.Buffer) + dst := NewWriter(onlyWriter{dstBuf}) + for i := 0; i < b.N; i++ { + srcBuf.Reset() + dstBuf.Reset() + dst.Reset(onlyWriter{dstBuf}) + io.Copy(dst, src) + } +} + +func BenchmarkWriterCopyNoReadFrom(b *testing.B) { + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := onlyReader{srcBuf} + dstBuf := new(bytes.Buffer) + dstWriter := NewWriter(dstBuf) + dst := onlyWriter{dstWriter} + for i := 0; i < b.N; i++ { + srcBuf.Reset() + dstBuf.Reset() + dstWriter.Reset(dstBuf) + io.Copy(dst, src) + } +} + +func BenchmarkReaderEmpty(b *testing.B) { + b.ReportAllocs() + str := strings.Repeat("x", 16<<10) + for i := 0; i < b.N; i++ { + br := NewReader(strings.NewReader(str)) + n, err := io.Copy(ioutil.Discard, br) + if err != nil { + b.Fatal(err) + } + if n != int64(len(str)) { + b.Fatal("wrong length") + } + } +} + +func BenchmarkWriterEmpty(b *testing.B) { + b.ReportAllocs() + str := strings.Repeat("x", 1<<10) + bs := []byte(str) + for i := 0; i < b.N; i++ { + bw := NewWriter(ioutil.Discard) + bw.Flush() + bw.WriteByte('a') + bw.Flush() + bw.WriteRune('B') + bw.Flush() + bw.Write(bs) + bw.Flush() + bw.WriteString(str) + bw.Flush() + } +} + +func BenchmarkWriterFlush(b *testing.B) { + b.ReportAllocs() + bw := NewWriter(ioutil.Discard) + str := strings.Repeat("x", 50) + for i := 0; i < b.N; i++ { + bw.WriteString(str) + bw.Flush() + } +} diff --git a/src/bufio/example_test.go b/src/bufio/example_test.go new file mode 100644 index 000000000..3da914142 --- /dev/null +++ b/src/bufio/example_test.go @@ -0,0 +1,82 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bufio_test + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func ExampleWriter() { + w := bufio.NewWriter(os.Stdout) + fmt.Fprint(w, "Hello, ") + fmt.Fprint(w, "world!") + w.Flush() // Don't forget to flush! + // Output: Hello, world! +} + +// The simplest use of a Scanner, to read standard input as a set of lines. +func ExampleScanner_lines() { + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + fmt.Println(scanner.Text()) // Println will add back the final '\n' + } + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "reading standard input:", err) + } +} + +// Use a Scanner to implement a simple word-count utility by scanning the +// input as a sequence of space-delimited tokens. +func ExampleScanner_words() { + // An artificial input source. + const input = "Now is the winter of our discontent,\nMade glorious summer by this sun of York.\n" + scanner := bufio.NewScanner(strings.NewReader(input)) + // Set the split function for the scanning operation. + scanner.Split(bufio.ScanWords) + // Count the words. + count := 0 + for scanner.Scan() { + count++ + } + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "reading input:", err) + } + fmt.Printf("%d\n", count) + // Output: 15 +} + +// Use a Scanner with a custom split function (built by wrapping ScanWords) to validate +// 32-bit decimal input. +func ExampleScanner_custom() { + // An artificial input source. + const input = "1234 5678 1234567901234567890" + scanner := bufio.NewScanner(strings.NewReader(input)) + // Create a custom split function by wrapping the existing ScanWords function. + split := func(data []byte, atEOF bool) (advance int, token []byte, err error) { + advance, token, err = bufio.ScanWords(data, atEOF) + if err == nil && token != nil { + _, err = strconv.ParseInt(string(token), 10, 32) + } + return + } + // Set the split function for the scanning operation. + scanner.Split(split) + // Validate the input + for scanner.Scan() { + fmt.Printf("%s\n", scanner.Text()) + } + + if err := scanner.Err(); err != nil { + fmt.Printf("Invalid input: %s", err) + } + // Output: + // 1234 + // 5678 + // Invalid input: strconv.ParseInt: parsing "1234567901234567890": value out of range +} diff --git a/src/bufio/export_test.go b/src/bufio/export_test.go new file mode 100644 index 000000000..3d3bb27d8 --- /dev/null +++ b/src/bufio/export_test.go @@ -0,0 +1,27 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bufio + +// Exported for testing only. +import ( + "unicode/utf8" +) + +var IsSpace = isSpace + +func (s *Scanner) MaxTokenSize(n int) { + if n < utf8.UTFMax || n > 1e9 { + panic("bad max token size") + } + if n < len(s.buf) { + s.buf = make([]byte, n) + } + s.maxTokenSize = n +} + +// ErrOrEOF is like Err, but returns EOF. Used to test a corner case. +func (s *Scanner) ErrOrEOF() error { + return s.err +} diff --git a/src/bufio/scan.go b/src/bufio/scan.go new file mode 100644 index 000000000..364d15961 --- /dev/null +++ b/src/bufio/scan.go @@ -0,0 +1,359 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bufio + +import ( + "bytes" + "errors" + "io" + "unicode/utf8" +) + +// Scanner provides a convenient interface for reading data such as +// a file of newline-delimited lines of text. Successive calls to +// the Scan method will step through the 'tokens' of a file, skipping +// the bytes between the tokens. The specification of a token is +// defined by a split function of type SplitFunc; the default split +// function breaks the input into lines with line termination stripped. Split +// functions are defined in this package for scanning a file into +// lines, bytes, UTF-8-encoded runes, and space-delimited words. The +// client may instead provide a custom split function. +// +// Scanning stops unrecoverably at EOF, the first I/O error, or a token too +// large to fit in the buffer. When a scan stops, the reader may have +// advanced arbitrarily far past the last token. Programs that need more +// control over error handling or large tokens, or must run sequential scans +// on a reader, should use bufio.Reader instead. +// +type Scanner struct { + r io.Reader // The reader provided by the client. + split SplitFunc // The function to split the tokens. + maxTokenSize int // Maximum size of a token; modified by tests. + token []byte // Last token returned by split. + buf []byte // Buffer used as argument to split. + start int // First non-processed byte in buf. + end int // End of data in buf. + err error // Sticky error. + empties int // Count of successive empty tokens. +} + +// SplitFunc is the signature of the split function used to tokenize the +// input. The arguments are an initial substring of the remaining unprocessed +// data and a flag, atEOF, that reports whether the Reader has no more data +// to give. The return values are the number of bytes to advance the input +// and the next token to return to the user, plus an error, if any. If the +// data does not yet hold a complete token, for instance if it has no newline +// while scanning lines, SplitFunc can return (0, nil, nil) to signal the +// Scanner to read more data into the slice and try again with a longer slice +// starting at the same point in the input. +// +// If the returned error is non-nil, scanning stops and the error +// is returned to the client. +// +// The function is never called with an empty data slice unless atEOF +// is true. If atEOF is true, however, data may be non-empty and, +// as always, holds unprocessed text. +type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error) + +// Errors returned by Scanner. +var ( + ErrTooLong = errors.New("bufio.Scanner: token too long") + ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count") + ErrAdvanceTooFar = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input") +) + +const ( + // MaxScanTokenSize is the maximum size used to buffer a token. + // The actual maximum token size may be smaller as the buffer + // may need to include, for instance, a newline. + MaxScanTokenSize = 64 * 1024 +) + +// NewScanner returns a new Scanner to read from r. +// The split function defaults to ScanLines. +func NewScanner(r io.Reader) *Scanner { + return &Scanner{ + r: r, + split: ScanLines, + maxTokenSize: MaxScanTokenSize, + buf: make([]byte, 4096), // Plausible starting size; needn't be large. + } +} + +// Err returns the first non-EOF error that was encountered by the Scanner. +func (s *Scanner) Err() error { + if s.err == io.EOF { + return nil + } + return s.err +} + +// Bytes returns the most recent token generated by a call to Scan. +// The underlying array may point to data that will be overwritten +// by a subsequent call to Scan. It does no allocation. +func (s *Scanner) Bytes() []byte { + return s.token +} + +// Text returns the most recent token generated by a call to Scan +// as a newly allocated string holding its bytes. +func (s *Scanner) Text() string { + return string(s.token) +} + +// Scan advances the Scanner to the next token, which will then be +// available through the Bytes or Text method. It returns false when the +// scan stops, either by reaching the end of the input or an error. +// 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 +// advancing the input. This is a common error mode for scanners. +func (s *Scanner) Scan() bool { + // Loop until we have a token. + for { + // See if we can get a token with what we already have. + // If we've run out of data but have an error, give the split function + // a chance to recover any remaining, possibly empty token. + if s.end > s.start || s.err != nil { + advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil) + if err != nil { + s.setErr(err) + return false + } + if !s.advance(advance) { + return false + } + s.token = token + if token != nil { + if s.err == nil || advance > 0 { + s.empties = 0 + } else { + // Returning tokens not advancing input at EOF. + s.empties++ + if s.empties > 100 { + panic("bufio.Scan: 100 empty tokens without progressing") + } + } + return true + } + } + // We cannot generate a token with what we are holding. + // If we've already hit EOF or an I/O error, we are done. + if s.err != nil { + // Shut it down. + s.start = 0 + s.end = 0 + return false + } + // Must read more data. + // First, shift data to beginning of buffer if there's lots of empty space + // or space is needed. + if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) { + copy(s.buf, s.buf[s.start:s.end]) + s.end -= s.start + s.start = 0 + } + // Is the buffer full? If so, resize. + if s.end == len(s.buf) { + if len(s.buf) >= s.maxTokenSize { + s.setErr(ErrTooLong) + return false + } + newSize := len(s.buf) * 2 + if newSize > s.maxTokenSize { + newSize = s.maxTokenSize + } + newBuf := make([]byte, newSize) + copy(newBuf, s.buf[s.start:s.end]) + s.buf = newBuf + s.end -= s.start + s.start = 0 + continue + } + // Finally we can read some input. Make sure we don't get stuck with + // a misbehaving Reader. Officially we don't need to do this, but let's + // be extra careful: Scanner is for safe, simple jobs. + for loop := 0; ; { + n, err := s.r.Read(s.buf[s.end:len(s.buf)]) + s.end += n + if err != nil { + s.setErr(err) + break + } + if n > 0 { + s.empties = 0 + break + } + loop++ + if loop > maxConsecutiveEmptyReads { + s.setErr(io.ErrNoProgress) + break + } + } + } +} + +// advance consumes n bytes of the buffer. It reports whether the advance was legal. +func (s *Scanner) advance(n int) bool { + if n < 0 { + s.setErr(ErrNegativeAdvance) + return false + } + if n > s.end-s.start { + s.setErr(ErrAdvanceTooFar) + return false + } + s.start += n + return true +} + +// setErr records the first error encountered. +func (s *Scanner) setErr(err error) { + if s.err == nil || s.err == io.EOF { + s.err = err + } +} + +// Split sets the split function for the Scanner. If called, it must be +// called before Scan. The default split function is ScanLines. +func (s *Scanner) Split(split SplitFunc) { + s.split = split +} + +// Split functions + +// ScanBytes is a split function for a Scanner that returns each byte as a token. +func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + return 1, data[0:1], nil +} + +var errorRune = []byte(string(utf8.RuneError)) + +// ScanRunes is a split function for a Scanner that returns each +// UTF-8-encoded rune as a token. The sequence of runes returned is +// equivalent to that from a range loop over the input as a string, which +// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd". +// Because of the Scan interface, this makes it impossible for the client to +// distinguish correctly encoded replacement runes from encoding errors. +func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + + // Fast path 1: ASCII. + if data[0] < utf8.RuneSelf { + return 1, data[0:1], nil + } + + // Fast path 2: Correct UTF-8 decode without error. + _, width := utf8.DecodeRune(data) + if width > 1 { + // It's a valid encoding. Width cannot be one for a correctly encoded + // non-ASCII rune. + return width, data[0:width], nil + } + + // We know it's an error: we have width==1 and implicitly r==utf8.RuneError. + // Is the error because there wasn't a full rune to be decoded? + // FullRune distinguishes correctly between erroneous and incomplete encodings. + if !atEOF && !utf8.FullRune(data) { + // Incomplete; get more bytes. + return 0, nil, nil + } + + // We have a real UTF-8 encoding error. Return a properly encoded error rune + // but advance only one byte. This matches the behavior of a range loop over + // an incorrectly encoded string. + return 1, errorRune, nil +} + +// dropCR drops a terminal \r from the data. +func dropCR(data []byte) []byte { + if len(data) > 0 && data[len(data)-1] == '\r' { + return data[0 : len(data)-1] + } + return data +} + +// ScanLines is a split function for a Scanner that returns each line of +// text, stripped of any trailing end-of-line marker. The returned line may +// be empty. The end-of-line marker is one optional carriage return followed +// by one mandatory newline. In regular expression notation, it is `\r?\n`. +// The last non-empty line of input will be returned even if it has no +// newline. +func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + if i := bytes.IndexByte(data, '\n'); i >= 0 { + // We have a full newline-terminated line. + return i + 1, dropCR(data[0:i]), nil + } + // If we're at EOF, we have a final, non-terminated line. Return it. + if atEOF { + return len(data), dropCR(data), nil + } + // Request more data. + return 0, nil, nil +} + +// isSpace reports whether the character is a Unicode white space character. +// We avoid dependency on the unicode package, but check validity of the implementation +// in the tests. +func isSpace(r rune) bool { + if r <= '\u00FF' { + // Obvious ASCII ones: \t through \r plus space. Plus two Latin-1 oddballs. + switch r { + case ' ', '\t', '\n', '\v', '\f', '\r': + return true + case '\u0085', '\u00A0': + return true + } + return false + } + // High-valued ones. + if '\u2000' <= r && r <= '\u200a' { + return true + } + switch r { + case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000': + return true + } + return false +} + +// ScanWords is a split function for a Scanner that returns each +// space-separated word of text, with surrounding spaces deleted. It will +// never return an empty string. The definition of space is set by +// unicode.IsSpace. +func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) { + // Skip leading spaces. + start := 0 + for width := 0; start < len(data); start += width { + var r rune + r, width = utf8.DecodeRune(data[start:]) + if !isSpace(r) { + break + } + } + // Scan until space, marking end of word. + for width, i := 0, start; i < len(data); i += width { + var r rune + r, width = utf8.DecodeRune(data[i:]) + if isSpace(r) { + return i + width, data[start:i], nil + } + } + // If we're at EOF, we have a final, non-empty, non-terminated word. Return it. + if atEOF && len(data) > start { + return len(data), data[start:], nil + } + // Request more data. + return start, nil, nil +} diff --git a/src/bufio/scan_test.go b/src/bufio/scan_test.go new file mode 100644 index 000000000..eea87cbf7 --- /dev/null +++ b/src/bufio/scan_test.go @@ -0,0 +1,524 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bufio_test + +import ( + . "bufio" + "bytes" + "errors" + "io" + "strings" + "testing" + "unicode" + "unicode/utf8" +) + +const smallMaxTokenSize = 256 // Much smaller for more efficient testing. + +// Test white space table matches the Unicode definition. +func TestSpace(t *testing.T) { + for r := rune(0); r <= utf8.MaxRune; r++ { + if IsSpace(r) != unicode.IsSpace(r) { + t.Fatalf("white space property disagrees: %#U should be %t", r, unicode.IsSpace(r)) + } + } +} + +var scanTests = []string{ + "", + "a", + "¼", + "☹", + "\x81", // UTF-8 error + "\uFFFD", // correctly encoded RuneError + "abcdefgh", + "abc def\n\t\tgh ", + "abc¼☹\x81\uFFFD日本語\x82abc", +} + +func TestScanByte(t *testing.T) { + for n, test := range scanTests { + buf := strings.NewReader(test) + s := NewScanner(buf) + s.Split(ScanBytes) + var i int + for i = 0; s.Scan(); i++ { + if b := s.Bytes(); len(b) != 1 || b[0] != test[i] { + t.Errorf("#%d: %d: expected %q got %q", n, i, test, b) + } + } + if i != len(test) { + t.Errorf("#%d: termination expected at %d; got %d", n, len(test), i) + } + err := s.Err() + if err != nil { + t.Errorf("#%d: %v", n, err) + } + } +} + +// Test that the rune splitter returns same sequence of runes (not bytes) as for range string. +func TestScanRune(t *testing.T) { + for n, test := range scanTests { + buf := strings.NewReader(test) + s := NewScanner(buf) + s.Split(ScanRunes) + var i, runeCount int + var expect rune + // Use a string range loop to validate the sequence of runes. + for i, expect = range string(test) { + if !s.Scan() { + break + } + runeCount++ + got, _ := utf8.DecodeRune(s.Bytes()) + if got != expect { + t.Errorf("#%d: %d: expected %q got %q", n, i, expect, got) + } + } + if s.Scan() { + t.Errorf("#%d: scan ran too long, got %q", n, s.Text()) + } + testRuneCount := utf8.RuneCountInString(test) + if runeCount != testRuneCount { + t.Errorf("#%d: termination expected at %d; got %d", n, testRuneCount, runeCount) + } + err := s.Err() + if err != nil { + t.Errorf("#%d: %v", n, err) + } + } +} + +var wordScanTests = []string{ + "", + " ", + "\n", + "a", + " a ", + "abc def", + " abc def ", + " abc\tdef\nghi\rjkl\fmno\vpqr\u0085stu\u00a0\n", +} + +// Test that the word splitter returns the same data as strings.Fields. +func TestScanWords(t *testing.T) { + for n, test := range wordScanTests { + buf := strings.NewReader(test) + s := NewScanner(buf) + s.Split(ScanWords) + words := strings.Fields(test) + var wordCount int + for wordCount = 0; wordCount < len(words); wordCount++ { + if !s.Scan() { + break + } + got := s.Text() + if got != words[wordCount] { + t.Errorf("#%d: %d: expected %q got %q", n, wordCount, words[wordCount], got) + } + } + if s.Scan() { + t.Errorf("#%d: scan ran too long, got %q", n, s.Text()) + } + if wordCount != len(words) { + t.Errorf("#%d: termination expected at %d; got %d", n, len(words), wordCount) + } + err := s.Err() + if err != nil { + t.Errorf("#%d: %v", n, err) + } + } +} + +// slowReader is a reader that returns only a few bytes at a time, to test the incremental +// reads in Scanner.Scan. +type slowReader struct { + max int + buf io.Reader +} + +func (sr *slowReader) Read(p []byte) (n int, err error) { + if len(p) > sr.max { + p = p[0:sr.max] + } + return sr.buf.Read(p) +} + +// genLine writes to buf a predictable but non-trivial line of text of length +// n, including the terminal newline and an occasional carriage return. +// If addNewline is false, the \r and \n are not emitted. +func genLine(buf *bytes.Buffer, lineNum, n int, addNewline bool) { + buf.Reset() + doCR := lineNum%5 == 0 + if doCR { + n-- + } + for i := 0; i < n-1; i++ { // Stop early for \n. + c := 'a' + byte(lineNum+i) + if c == '\n' || c == '\r' { // Don't confuse us. + c = 'N' + } + buf.WriteByte(c) + } + if addNewline { + if doCR { + buf.WriteByte('\r') + } + buf.WriteByte('\n') + } + return +} + +// Test the line splitter, including some carriage returns but no long lines. +func TestScanLongLines(t *testing.T) { + // Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize. + tmp := new(bytes.Buffer) + buf := new(bytes.Buffer) + lineNum := 0 + j := 0 + for i := 0; i < 2*smallMaxTokenSize; i++ { + genLine(tmp, lineNum, j, true) + if j < smallMaxTokenSize { + j++ + } else { + j-- + } + buf.Write(tmp.Bytes()) + lineNum++ + } + s := NewScanner(&slowReader{1, buf}) + s.Split(ScanLines) + s.MaxTokenSize(smallMaxTokenSize) + j = 0 + for lineNum := 0; s.Scan(); lineNum++ { + genLine(tmp, lineNum, j, false) + if j < smallMaxTokenSize { + j++ + } else { + j-- + } + line := tmp.String() // We use the string-valued token here, for variety. + if s.Text() != line { + t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Text(), line) + } + } + err := s.Err() + if err != nil { + t.Fatal(err) + } +} + +// Test that the line splitter errors out on a long line. +func TestScanLineTooLong(t *testing.T) { + const smallMaxTokenSize = 256 // Much smaller for more efficient testing. + // Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize. + tmp := new(bytes.Buffer) + buf := new(bytes.Buffer) + lineNum := 0 + j := 0 + for i := 0; i < 2*smallMaxTokenSize; i++ { + genLine(tmp, lineNum, j, true) + j++ + buf.Write(tmp.Bytes()) + lineNum++ + } + s := NewScanner(&slowReader{3, buf}) + s.Split(ScanLines) + s.MaxTokenSize(smallMaxTokenSize) + j = 0 + for lineNum := 0; s.Scan(); lineNum++ { + genLine(tmp, lineNum, j, false) + if j < smallMaxTokenSize { + j++ + } else { + j-- + } + line := tmp.Bytes() + if !bytes.Equal(s.Bytes(), line) { + t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line) + } + } + err := s.Err() + if err != ErrTooLong { + t.Fatalf("expected ErrTooLong; got %s", err) + } +} + +// Test that the line splitter handles a final line without a newline. +func testNoNewline(text string, lines []string, t *testing.T) { + buf := strings.NewReader(text) + s := NewScanner(&slowReader{7, buf}) + s.Split(ScanLines) + for lineNum := 0; s.Scan(); lineNum++ { + line := lines[lineNum] + if s.Text() != line { + t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line) + } + } + err := s.Err() + if err != nil { + t.Fatal(err) + } +} + +var noNewlineLines = []string{ + "abcdefghijklmn\nopqrstuvwxyz", +} + +// Test that the line splitter handles a final line without a newline. +func TestScanLineNoNewline(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + } + testNoNewline(text, lines, t) +} + +// Test that the line splitter handles a final line with a carriage return but no newline. +func TestScanLineReturnButNoNewline(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz\r" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + } + testNoNewline(text, lines, t) +} + +// Test that the line splitter handles a final empty line. +func TestScanLineEmptyFinalLine(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz\n\n" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + "", + } + testNoNewline(text, lines, t) +} + +// Test that the line splitter handles a final empty line with a carriage return but no newline. +func TestScanLineEmptyFinalLineWithCR(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz\n\r" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + "", + } + testNoNewline(text, lines, t) +} + +var testError = errors.New("testError") + +// Test the correct error is returned when the split function errors out. +func TestSplitError(t *testing.T) { + // Create a split function that delivers a little data, then a predictable error. + numSplits := 0 + const okCount = 7 + errorSplit := func(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF { + panic("didn't get enough data") + } + if numSplits >= okCount { + return 0, nil, testError + } + numSplits++ + return 1, data[0:1], nil + } + // Read the data. + const text = "abcdefghijklmnopqrstuvwxyz" + buf := strings.NewReader(text) + s := NewScanner(&slowReader{1, buf}) + s.Split(errorSplit) + var i int + for i = 0; s.Scan(); i++ { + if len(s.Bytes()) != 1 || text[i] != s.Bytes()[0] { + t.Errorf("#%d: expected %q got %q", i, text[i], s.Bytes()[0]) + } + } + // Check correct termination location and error. + if i != okCount { + t.Errorf("unexpected termination; expected %d tokens got %d", okCount, i) + } + err := s.Err() + if err != testError { + t.Fatalf("expected %q got %v", testError, err) + } +} + +// Test that an EOF is overridden by a user-generated scan error. +func TestErrAtEOF(t *testing.T) { + s := NewScanner(strings.NewReader("1 2 33")) + // This spitter will fail on last entry, after s.err==EOF. + split := func(data []byte, atEOF bool) (advance int, token []byte, err error) { + advance, token, err = ScanWords(data, atEOF) + if len(token) > 1 { + if s.ErrOrEOF() != io.EOF { + t.Fatal("not testing EOF") + } + err = testError + } + return + } + s.Split(split) + for s.Scan() { + } + if s.Err() != testError { + t.Fatal("wrong error:", s.Err()) + } +} + +// Test for issue 5268. +type alwaysError struct{} + +func (alwaysError) Read(p []byte) (int, error) { + return 0, io.ErrUnexpectedEOF +} + +func TestNonEOFWithEmptyRead(t *testing.T) { + scanner := NewScanner(alwaysError{}) + for scanner.Scan() { + t.Fatal("read should fail") + } + err := scanner.Err() + if err != io.ErrUnexpectedEOF { + t.Errorf("unexpected error: %v", err) + } +} + +// Test that Scan finishes if we have endless empty reads. +type endlessZeros struct{} + +func (endlessZeros) Read(p []byte) (int, error) { + return 0, nil +} + +func TestBadReader(t *testing.T) { + scanner := NewScanner(endlessZeros{}) + for scanner.Scan() { + t.Fatal("read should fail") + } + err := scanner.Err() + if err != io.ErrNoProgress { + t.Errorf("unexpected error: %v", err) + } +} + +func TestScanWordsExcessiveWhiteSpace(t *testing.T) { + const word = "ipsum" + s := strings.Repeat(" ", 4*smallMaxTokenSize) + word + scanner := NewScanner(strings.NewReader(s)) + scanner.MaxTokenSize(smallMaxTokenSize) + scanner.Split(ScanWords) + if !scanner.Scan() { + t.Fatalf("scan failed: %v", scanner.Err()) + } + if token := scanner.Text(); token != word { + t.Fatalf("unexpected token: %v", token) + } +} + +// Test that empty tokens, including at end of line or end of file, are found by the scanner. +// Issue 8672: Could miss final empty token. + +func commaSplit(data []byte, atEOF bool) (advance int, token []byte, err error) { + for i := 0; i < len(data); i++ { + if data[i] == ',' { + return i + 1, data[:i], nil + } + } + if !atEOF { + return 0, nil, nil + } + return 0, data, nil +} + +func TestEmptyTokens(t *testing.T) { + s := NewScanner(strings.NewReader("1,2,3,")) + values := []string{"1", "2", "3", ""} + s.Split(commaSplit) + var i int + for i = 0; i < len(values); i++ { + if !s.Scan() { + break + } + if s.Text() != values[i] { + t.Errorf("%d: expected %q got %q", i, values[i], s.Text()) + } + } + if i != len(values) { + t.Errorf("got %d fields, expected %d", i, len(values)) + } + if err := s.Err(); err != nil { + t.Fatal(err) + } +} + +func loopAtEOFSplit(data []byte, atEOF bool) (advance int, token []byte, err error) { + if len(data) > 0 { + return 1, data[:1], nil + } + return 0, data, nil +} + +func TestDontLoopForever(t *testing.T) { + s := NewScanner(strings.NewReader("abc")) + s.Split(loopAtEOFSplit) + // Expect a panic + defer func() { + err := recover() + if err == nil { + t.Fatal("should have panicked") + } + if msg, ok := err.(string); !ok || !strings.Contains(msg, "empty tokens") { + panic(err) + } + }() + for count := 0; s.Scan(); count++ { + if count > 1000 { + t.Fatal("looping") + } + } + if s.Err() != nil { + t.Fatal("after scan:", s.Err()) + } +} + +func TestBlankLines(t *testing.T) { + s := NewScanner(strings.NewReader(strings.Repeat("\n", 1000))) + for count := 0; s.Scan(); count++ { + if count > 2000 { + t.Fatal("looping") + } + } + if s.Err() != nil { + t.Fatal("after scan:", s.Err()) + } +} + +type countdown int + +func (c *countdown) split(data []byte, atEOF bool) (advance int, token []byte, err error) { + if *c > 0 { + *c-- + return 1, data[:1], nil + } + return 0, nil, nil +} + +// Check that the looping-at-EOF check doesn't trigger for merely empty tokens. +func TestEmptyLinesOK(t *testing.T) { + c := countdown(10000) + s := NewScanner(strings.NewReader(strings.Repeat("\n", 10000))) + s.Split(c.split) + for s.Scan() { + } + if s.Err() != nil { + t.Fatal("after scan:", s.Err()) + } + if c != 0 { + t.Fatalf("stopped with %d left to process", c) + } +} diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go new file mode 100644 index 000000000..51550a459 --- /dev/null +++ b/src/builtin/builtin.go @@ -0,0 +1,256 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + Package builtin provides documentation for Go's predeclared identifiers. + The items documented here are not actually in package builtin + but their descriptions here allow godoc to present documentation + for the language's special identifiers. +*/ +package builtin + +// bool is the set of boolean values, true and false. +type bool bool + +// true and false are the two untyped boolean values. +const ( + true = 0 == 0 // Untyped bool. + false = 0 != 0 // Untyped bool. +) + +// uint8 is the set of all unsigned 8-bit integers. +// Range: 0 through 255. +type uint8 uint8 + +// uint16 is the set of all unsigned 16-bit integers. +// Range: 0 through 65535. +type uint16 uint16 + +// uint32 is the set of all unsigned 32-bit integers. +// Range: 0 through 4294967295. +type uint32 uint32 + +// uint64 is the set of all unsigned 64-bit integers. +// Range: 0 through 18446744073709551615. +type uint64 uint64 + +// int8 is the set of all signed 8-bit integers. +// Range: -128 through 127. +type int8 int8 + +// int16 is the set of all signed 16-bit integers. +// Range: -32768 through 32767. +type int16 int16 + +// int32 is the set of all signed 32-bit integers. +// Range: -2147483648 through 2147483647. +type int32 int32 + +// int64 is the set of all signed 64-bit integers. +// Range: -9223372036854775808 through 9223372036854775807. +type int64 int64 + +// float32 is the set of all IEEE-754 32-bit floating-point numbers. +type float32 float32 + +// float64 is the set of all IEEE-754 64-bit floating-point numbers. +type float64 float64 + +// complex64 is the set of all complex numbers with float32 real and +// imaginary parts. +type complex64 complex64 + +// complex128 is the set of all complex numbers with float64 real and +// imaginary parts. +type complex128 complex128 + +// string is the set of all strings of 8-bit bytes, conventionally but not +// necessarily representing UTF-8-encoded text. A string may be empty, but +// not nil. Values of string type are immutable. +type string string + +// int is a signed integer type that is at least 32 bits in size. It is a +// distinct type, however, and not an alias for, say, int32. +type int int + +// uint is an unsigned integer type that is at least 32 bits in size. It is a +// distinct type, however, and not an alias for, say, uint32. +type uint uint + +// uintptr is an integer type that is large enough to hold the bit pattern of +// any pointer. +type uintptr uintptr + +// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is +// used, by convention, to distinguish byte values from 8-bit unsigned +// integer values. +type byte byte + +// rune is an alias for int32 and is equivalent to int32 in all ways. It is +// used, by convention, to distinguish character values from integer values. +type rune rune + +// iota is a predeclared identifier representing the untyped integer ordinal +// number of the current const specification in a (usually parenthesized) +// const declaration. It is zero-indexed. +const iota = 0 // Untyped int. + +// nil is a predeclared identifier representing the zero value for a +// pointer, channel, func, interface, map, or slice type. +var nil Type // Type must be a pointer, channel, func, interface, map, or slice type + +// Type is here for the purposes of documentation only. It is a stand-in +// for any Go type, but represents the same type for any given function +// invocation. +type Type int + +// Type1 is here for the purposes of documentation only. It is a stand-in +// for any Go type, but represents the same type for any given function +// invocation. +type Type1 int + +// IntegerType is here for the purposes of documentation only. It is a stand-in +// for any integer type: int, uint, int8 etc. +type IntegerType int + +// FloatType is here for the purposes of documentation only. It is a stand-in +// for either float type: float32 or float64. +type FloatType float32 + +// ComplexType is here for the purposes of documentation only. It is a +// stand-in for either complex type: complex64 or complex128. +type ComplexType complex64 + +// The append built-in function appends elements to the end of a slice. If +// it has sufficient capacity, the destination is resliced to accommodate the +// new elements. If it does not, a new underlying array will be allocated. +// Append returns the updated slice. It is therefore necessary to store the +// result of append, often in the variable holding the slice itself: +// slice = append(slice, elem1, elem2) +// slice = append(slice, anotherSlice...) +// As a special case, it is legal to append a string to a byte slice, like this: +// slice = append([]byte("hello "), "world"...) +func append(slice []Type, elems ...Type) []Type + +// The copy built-in function copies elements from a source slice into a +// destination slice. (As a special case, it also will copy bytes from a +// string to a slice of bytes.) The source and destination may overlap. Copy +// returns the number of elements copied, which will be the minimum of +// len(src) and len(dst). +func copy(dst, src []Type) int + +// The delete built-in function deletes the element with the specified key +// (m[key]) from the map. If m is nil or there is no such element, delete +// is a no-op. +func delete(m map[Type]Type1, key Type) + +// The len built-in function returns the length of v, according to its type: +// Array: the number of elements in v. +// Pointer to array: the number of elements in *v (even if v is nil). +// Slice, or map: the number of elements in v; if v is nil, len(v) is zero. +// String: the number of bytes in v. +// Channel: the number of elements queued (unread) in the channel buffer; +// if v is nil, len(v) is zero. +func len(v Type) int + +// The cap built-in function returns the capacity of v, according to its type: +// Array: the number of elements in v (same as len(v)). +// Pointer to array: the number of elements in *v (same as len(v)). +// Slice: the maximum length the slice can reach when resliced; +// if v is nil, cap(v) is zero. +// Channel: the channel buffer capacity, in units of elements; +// if v is nil, cap(v) is zero. +func cap(v Type) int + +// The make built-in function allocates and initializes an object of type +// slice, map, or chan (only). Like new, the first argument is a type, not a +// value. Unlike new, make's return type is the same as the type of its +// argument, not a pointer to it. The specification of the result depends on +// the type: +// Slice: The size specifies the length. The capacity of the slice is +// equal to its length. A second integer argument may be provided to +// specify a different capacity; it must be no smaller than the +// length, so make([]int, 0, 10) allocates a slice of length 0 and +// capacity 10. +// Map: An initial allocation is made according to the size but the +// resulting map has length 0. The size may be omitted, in which case +// a small starting size is allocated. +// Channel: The channel's buffer is initialized with the specified +// buffer capacity. If zero, or the size is omitted, the channel is +// unbuffered. +func make(Type, size IntegerType) Type + +// The new built-in function allocates memory. The first argument is a type, +// not a value, and the value returned is a pointer to a newly +// allocated zero value of that type. +func new(Type) *Type + +// The complex built-in function constructs a complex value from two +// floating-point values. The real and imaginary parts must be of the same +// size, either float32 or float64 (or assignable to them), and the return +// value will be the corresponding complex type (complex64 for float32, +// complex128 for float64). +func complex(r, i FloatType) ComplexType + +// The real built-in function returns the real part of the complex number c. +// The return value will be floating point type corresponding to the type of c. +func real(c ComplexType) FloatType + +// The imag built-in function returns the imaginary part of the complex +// number c. The return value will be floating point type corresponding to +// the type of c. +func imag(c ComplexType) FloatType + +// The close built-in function closes a channel, which must be either +// bidirectional or send-only. It should be executed only by the sender, +// never the receiver, and has the effect of shutting down the channel after +// the last sent value is received. After the last value has been received +// from a closed channel c, any receive from c will succeed without +// blocking, returning the zero value for the channel element. The form +// x, ok := <-c +// will also set ok to false for a closed channel. +func close(c chan<- Type) + +// The panic built-in function stops normal execution of the current +// goroutine. When a function F calls panic, normal execution of F stops +// immediately. Any functions whose execution was deferred by F are run in +// the usual way, and then F returns to its caller. To the caller G, the +// invocation of F then behaves like a call to panic, terminating G's +// execution and running any deferred functions. This continues until all +// functions in the executing goroutine have stopped, in reverse order. At +// that point, the program is terminated and the error condition is reported, +// including the value of the argument to panic. This termination sequence +// is called panicking and can be controlled by the built-in function +// recover. +func panic(v interface{}) + +// The recover built-in function allows a program to manage behavior of a +// panicking goroutine. Executing a call to recover inside a deferred +// function (but not any function called by it) stops the panicking sequence +// by restoring normal execution and retrieves the error value passed to the +// call of panic. If recover is called outside the deferred function it will +// not stop a panicking sequence. In this case, or when the goroutine is not +// panicking, or if the argument supplied to panic was nil, recover returns +// nil. Thus the return value from recover reports whether the goroutine is +// panicking. +func recover() interface{} + +// 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. +// 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. +func println(args ...Type) + +// The error built-in interface type is the conventional interface for +// representing an error condition, with the nil value representing no error. +type error interface { + Error() string +} diff --git a/src/bytes/buffer.go b/src/bytes/buffer.go new file mode 100644 index 000000000..46ca1d5ad --- /dev/null +++ b/src/bytes/buffer.go @@ -0,0 +1,412 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes + +// Simple byte buffer for marshaling data. + +import ( + "errors" + "io" + "unicode/utf8" +) + +// A Buffer is a variable-sized buffer of bytes with Read and Write methods. +// The zero value for Buffer is an empty buffer ready to use. +type Buffer struct { + buf []byte // contents are the bytes buf[off : len(buf)] + off int // read at &buf[off], write at &buf[len(buf)] + runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune + bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation. + lastRead readOp // last read operation, so that Unread* can work correctly. +} + +// The readOp constants describe the last action performed on +// the buffer, so that UnreadRune and UnreadByte can +// check for invalid usage. +type readOp int + +const ( + opInvalid readOp = iota // Non-read operation. + opReadRune // Read rune. + opRead // Any other read operation. +) + +// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer. +var ErrTooLarge = errors.New("bytes.Buffer: too large") + +// Bytes returns a slice of the contents of the unread portion of the buffer; +// len(b.Bytes()) == b.Len(). If the caller changes the contents of the +// returned slice, the contents of the buffer will change provided there +// are no intervening method calls on the Buffer. +func (b *Buffer) Bytes() []byte { return b.buf[b.off:] } + +// String returns the contents of the unread portion of the buffer +// as a string. If the Buffer is a nil pointer, it returns "". +func (b *Buffer) String() string { + if b == nil { + // Special case, useful in debugging. + return "" + } + return string(b.buf[b.off:]) +} + +// Len returns the number of bytes of the unread portion of the buffer; +// b.Len() == len(b.Bytes()). +func (b *Buffer) Len() int { return len(b.buf) - b.off } + +// 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) { + b.lastRead = opInvalid + switch { + case n < 0 || n > b.Len(): + panic("bytes.Buffer: truncation out of range") + case n == 0: + // Reuse buffer space. + b.off = 0 + } + b.buf = b.buf[0 : b.off+n] +} + +// Reset resets the buffer so it has no content. +// b.Reset() is the same as b.Truncate(0). +func (b *Buffer) Reset() { b.Truncate(0) } + +// grow grows the buffer to guarantee space for n more bytes. +// It returns the index where bytes should be written. +// If the buffer can't grow it will panic with ErrTooLarge. +func (b *Buffer) grow(n int) int { + m := b.Len() + // If buffer is empty, reset to recover space. + if m == 0 && b.off != 0 { + b.Truncate(0) + } + if len(b.buf)+n > cap(b.buf) { + var buf []byte + if b.buf == nil && n <= len(b.bootstrap) { + buf = b.bootstrap[0:] + } else if m+n <= cap(b.buf)/2 { + // We can slide things down instead of allocating a new + // slice. We only need m+n <= cap(b.buf) to slide, but + // we instead let capacity get twice as large so we + // don't spend all our time copying. + copy(b.buf[:], b.buf[b.off:]) + buf = b.buf[:m] + } else { + // not enough space anywhere + buf = makeSlice(2*cap(b.buf) + n) + copy(buf, b.buf[b.off:]) + } + b.buf = buf + b.off = 0 + } + b.buf = b.buf[0 : b.off+m+n] + return b.off + m +} + +// Grow grows the buffer's capacity, if necessary, to guarantee space for +// another n bytes. After Grow(n), at least n bytes can be written to the +// buffer without another allocation. +// If n is negative, Grow will panic. +// If the buffer can't grow it will panic with ErrTooLarge. +func (b *Buffer) Grow(n int) { + if n < 0 { + panic("bytes.Buffer.Grow: negative count") + } + m := b.grow(n) + b.buf = b.buf[0:m] +} + +// Write appends the contents of p to the buffer, growing the buffer as +// needed. The return value n is the length of p; err is always nil. If the +// buffer becomes too large, Write will panic with ErrTooLarge. +func (b *Buffer) Write(p []byte) (n int, err error) { + b.lastRead = opInvalid + m := b.grow(len(p)) + return copy(b.buf[m:], p), nil +} + +// WriteString appends the contents of s to the buffer, growing the buffer as +// needed. The return value n is the length of s; err is always nil. If the +// buffer becomes too large, WriteString will panic with ErrTooLarge. +func (b *Buffer) WriteString(s string) (n int, err error) { + b.lastRead = opInvalid + m := b.grow(len(s)) + return copy(b.buf[m:], s), nil +} + +// MinRead is the minimum slice size passed to a Read call by +// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond +// what is required to hold the contents of r, ReadFrom will not grow the +// underlying buffer. +const MinRead = 512 + +// ReadFrom reads data from r until EOF and appends it to the buffer, growing +// the buffer as needed. The return value n is the number of bytes read. Any +// error except io.EOF encountered during the read is also returned. If the +// buffer becomes too large, ReadFrom will panic with ErrTooLarge. +func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) { + b.lastRead = opInvalid + // If buffer is empty, reset to recover space. + if b.off >= len(b.buf) { + b.Truncate(0) + } + for { + if free := cap(b.buf) - len(b.buf); free < MinRead { + // not enough space at end + newBuf := b.buf + if b.off+free < MinRead { + // not enough space using beginning of buffer; + // double buffer capacity + newBuf = makeSlice(2*cap(b.buf) + MinRead) + } + copy(newBuf, b.buf[b.off:]) + b.buf = newBuf[:len(b.buf)-b.off] + b.off = 0 + } + m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]) + b.buf = b.buf[0 : len(b.buf)+m] + n += int64(m) + if e == io.EOF { + break + } + if e != nil { + return n, e + } + } + return n, nil // err is EOF, so return nil explicitly +} + +// makeSlice allocates a slice of size n. If the allocation fails, it panics +// with ErrTooLarge. +func makeSlice(n int) []byte { + // If the make fails, give a known error. + defer func() { + if recover() != nil { + panic(ErrTooLarge) + } + }() + return make([]byte, n) +} + +// WriteTo writes data to w until the buffer is drained or an error occurs. +// The return value n is the number of bytes written; it always fits into an +// int, but it is int64 to match the io.WriterTo interface. Any error +// encountered during the write is also returned. +func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) { + b.lastRead = opInvalid + if b.off < len(b.buf) { + nBytes := b.Len() + m, e := w.Write(b.buf[b.off:]) + if m > nBytes { + panic("bytes.Buffer.WriteTo: invalid Write count") + } + b.off += m + n = int64(m) + if e != nil { + return n, e + } + // all bytes should have been written, by definition of + // Write method in io.Writer + if m != nBytes { + return n, io.ErrShortWrite + } + } + // Buffer is now empty; reset. + b.Truncate(0) + return +} + +// WriteByte appends the byte c to the buffer, growing the buffer as needed. +// The returned error is always nil, but is included to match bufio.Writer's +// WriteByte. If the buffer becomes too large, WriteByte will panic with +// ErrTooLarge. +func (b *Buffer) WriteByte(c byte) error { + b.lastRead = opInvalid + m := b.grow(1) + b.buf[m] = c + return nil +} + +// WriteRune appends the UTF-8 encoding of Unicode code point r to the +// buffer, returning its length and an error, which is always nil but is +// included to match bufio.Writer's WriteRune. The buffer is grown as needed; +// if it becomes too large, WriteRune will panic with ErrTooLarge. +func (b *Buffer) WriteRune(r rune) (n int, err error) { + if r < utf8.RuneSelf { + b.WriteByte(byte(r)) + return 1, nil + } + n = utf8.EncodeRune(b.runeBytes[0:], r) + b.Write(b.runeBytes[0:n]) + return n, nil +} + +// Read reads the next len(p) bytes from the buffer or until the buffer +// is drained. The return value n is the number of bytes read. If the +// buffer has no data to return, err is io.EOF (unless len(p) is zero); +// otherwise it is nil. +func (b *Buffer) Read(p []byte) (n int, err error) { + b.lastRead = opInvalid + if b.off >= len(b.buf) { + // Buffer is empty, reset to recover space. + b.Truncate(0) + if len(p) == 0 { + return + } + return 0, io.EOF + } + n = copy(p, b.buf[b.off:]) + b.off += n + if n > 0 { + b.lastRead = opRead + } + return +} + +// Next returns a slice containing the next n bytes from the buffer, +// advancing the buffer as if the bytes had been returned by Read. +// If there are fewer than n bytes in the buffer, Next returns the entire buffer. +// The slice is only valid until the next call to a read or write method. +func (b *Buffer) Next(n int) []byte { + b.lastRead = opInvalid + m := b.Len() + if n > m { + n = m + } + data := b.buf[b.off : b.off+n] + b.off += n + if n > 0 { + b.lastRead = opRead + } + return data +} + +// ReadByte reads and returns the next byte from the buffer. +// If no byte is available, it returns error io.EOF. +func (b *Buffer) ReadByte() (c byte, err error) { + b.lastRead = opInvalid + if b.off >= len(b.buf) { + // Buffer is empty, reset to recover space. + b.Truncate(0) + return 0, io.EOF + } + c = b.buf[b.off] + b.off++ + b.lastRead = opRead + return c, nil +} + +// ReadRune reads and returns the next UTF-8-encoded +// Unicode code point from the buffer. +// If no bytes are available, the error returned is io.EOF. +// If the bytes are an erroneous UTF-8 encoding, it +// consumes one byte and returns U+FFFD, 1. +func (b *Buffer) ReadRune() (r rune, size int, err error) { + b.lastRead = opInvalid + if b.off >= len(b.buf) { + // Buffer is empty, reset to recover space. + b.Truncate(0) + return 0, 0, io.EOF + } + b.lastRead = opReadRune + c := b.buf[b.off] + if c < utf8.RuneSelf { + b.off++ + return rune(c), 1, nil + } + r, n := utf8.DecodeRune(b.buf[b.off:]) + b.off += n + return r, n, nil +} + +// UnreadRune unreads the last rune returned by ReadRune. +// If the most recent read or write operation on the buffer was +// not a ReadRune, UnreadRune returns an error. (In this regard +// it is stricter than UnreadByte, which will unread the last byte +// from any read operation.) +func (b *Buffer) UnreadRune() error { + if b.lastRead != opReadRune { + return errors.New("bytes.Buffer: UnreadRune: previous operation was not ReadRune") + } + b.lastRead = opInvalid + if b.off > 0 { + _, n := utf8.DecodeLastRune(b.buf[0:b.off]) + b.off -= n + } + return nil +} + +// UnreadByte unreads the last byte returned by the most recent +// read operation. If write has happened since the last read, UnreadByte +// returns an error. +func (b *Buffer) UnreadByte() error { + if b.lastRead != opReadRune && b.lastRead != opRead { + return errors.New("bytes.Buffer: UnreadByte: previous operation was not a read") + } + b.lastRead = opInvalid + if b.off > 0 { + b.off-- + } + return nil +} + +// ReadBytes reads until the first occurrence of delim in the input, +// returning a slice containing the data up to and including the delimiter. +// If ReadBytes encounters an error before finding a delimiter, +// it returns the data read before the error and the error itself (often io.EOF). +// ReadBytes returns err != nil if and only if the returned data does not end in +// delim. +func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) { + slice, err := b.readSlice(delim) + // return a copy of slice. The buffer's backing array may + // be overwritten by later calls. + line = append(line, slice...) + return +} + +// readSlice is like ReadBytes but returns a reference to internal buffer data. +func (b *Buffer) readSlice(delim byte) (line []byte, err error) { + i := IndexByte(b.buf[b.off:], delim) + end := b.off + i + 1 + if i < 0 { + end = len(b.buf) + err = io.EOF + } + line = b.buf[b.off:end] + b.off = end + b.lastRead = opRead + return line, err +} + +// ReadString reads until the first occurrence of delim in the input, +// returning a string containing the data up to and including the delimiter. +// If ReadString encounters an error before finding a delimiter, +// it returns the data read before the error and the error itself (often io.EOF). +// ReadString returns err != nil if and only if the returned data does not end +// in delim. +func (b *Buffer) ReadString(delim byte) (line string, err error) { + slice, err := b.readSlice(delim) + return string(slice), err +} + +// NewBuffer creates and initializes a new Buffer using buf as its initial +// contents. It is intended to prepare a Buffer to read existing data. It +// can also be used to size the internal buffer for writing. To do that, +// buf should have the desired capacity but a length of zero. +// +// In most cases, new(Buffer) (or just declaring a Buffer variable) is +// sufficient to initialize a Buffer. +func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} } + +// NewBufferString creates and initializes a new Buffer using string s as its +// initial contents. It is intended to prepare a buffer to read an existing +// string. +// +// In most cases, new(Buffer) (or just declaring a Buffer variable) is +// sufficient to initialize a Buffer. +func NewBufferString(s string) *Buffer { + return &Buffer{buf: []byte(s)} +} diff --git a/src/bytes/buffer_test.go b/src/bytes/buffer_test.go new file mode 100644 index 000000000..75145b05e --- /dev/null +++ b/src/bytes/buffer_test.go @@ -0,0 +1,527 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes_test + +import ( + . "bytes" + "io" + "math/rand" + "runtime" + "testing" + "unicode/utf8" +) + +const N = 10000 // make this bigger for a larger (and slower) test +var data string // test data for write tests +var testBytes []byte // test data; same as data but as a slice. + +func init() { + testBytes = make([]byte, N) + for i := 0; i < N; i++ { + testBytes[i] = 'a' + byte(i%26) + } + data = string(testBytes) +} + +// Verify that contents of buf match the string s. +func check(t *testing.T, testname string, buf *Buffer, s string) { + bytes := buf.Bytes() + str := buf.String() + if buf.Len() != len(bytes) { + t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes)) + } + + if buf.Len() != len(str) { + t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str)) + } + + if buf.Len() != len(s) { + t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s)) + } + + if string(bytes) != s { + t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s) + } +} + +// Fill buf through n writes of string fus. +// The initial contents of buf corresponds to the string s; +// the result is the final contents of buf returned as a string. +func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus string) string { + check(t, testname+" (fill 1)", buf, s) + for ; n > 0; n-- { + m, err := buf.WriteString(fus) + if m != len(fus) { + t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fus)) + } + if err != nil { + t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) + } + s += fus + check(t, testname+" (fill 4)", buf, s) + } + return s +} + +// Fill buf through n writes of byte slice fub. +// The initial contents of buf corresponds to the string s; +// the result is the final contents of buf returned as a string. +func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string { + check(t, testname+" (fill 1)", buf, s) + for ; n > 0; n-- { + m, err := buf.Write(fub) + if m != len(fub) { + t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub)) + } + if err != nil { + t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) + } + s += string(fub) + check(t, testname+" (fill 4)", buf, s) + } + return s +} + +func TestNewBuffer(t *testing.T) { + buf := NewBuffer(testBytes) + check(t, "NewBuffer", buf, data) +} + +func TestNewBufferString(t *testing.T) { + buf := NewBufferString(data) + check(t, "NewBufferString", buf, data) +} + +// Empty buf through repeated reads into fub. +// The initial contents of buf corresponds to the string s. +func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) { + check(t, testname+" (empty 1)", buf, s) + + for { + n, err := buf.Read(fub) + if n == 0 { + break + } + if err != nil { + t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err) + } + s = s[n:] + check(t, testname+" (empty 3)", buf, s) + } + + check(t, testname+" (empty 4)", buf, "") +} + +func TestBasicOperations(t *testing.T) { + var buf Buffer + + for i := 0; i < 5; i++ { + check(t, "TestBasicOperations (1)", &buf, "") + + buf.Reset() + check(t, "TestBasicOperations (2)", &buf, "") + + buf.Truncate(0) + check(t, "TestBasicOperations (3)", &buf, "") + + n, err := buf.Write([]byte(data[0:1])) + if n != 1 { + t.Errorf("wrote 1 byte, but n == %d", n) + } + if err != nil { + t.Errorf("err should always be nil, but err == %s", err) + } + check(t, "TestBasicOperations (4)", &buf, "a") + + buf.WriteByte(data[1]) + check(t, "TestBasicOperations (5)", &buf, "ab") + + n, err = buf.Write([]byte(data[2:26])) + if n != 24 { + t.Errorf("wrote 25 bytes, but n == %d", n) + } + check(t, "TestBasicOperations (6)", &buf, string(data[0:26])) + + buf.Truncate(26) + check(t, "TestBasicOperations (7)", &buf, string(data[0:26])) + + buf.Truncate(20) + check(t, "TestBasicOperations (8)", &buf, string(data[0:20])) + + empty(t, "TestBasicOperations (9)", &buf, string(data[0:20]), make([]byte, 5)) + empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100)) + + buf.WriteByte(data[1]) + c, err := buf.ReadByte() + if err != nil { + t.Error("ReadByte unexpected eof") + } + if c != data[1] { + t.Errorf("ReadByte wrong value c=%v", c) + } + c, err = buf.ReadByte() + if err == nil { + t.Error("ReadByte unexpected not eof") + } + } +} + +func TestLargeStringWrites(t *testing.T) { + var buf Buffer + limit := 30 + if testing.Short() { + limit = 9 + } + for i := 3; i < limit; i += 3 { + s := fillString(t, "TestLargeWrites (1)", &buf, "", 5, data) + empty(t, "TestLargeStringWrites (2)", &buf, s, make([]byte, len(data)/i)) + } + check(t, "TestLargeStringWrites (3)", &buf, "") +} + +func TestLargeByteWrites(t *testing.T) { + var buf Buffer + limit := 30 + if testing.Short() { + limit = 9 + } + for i := 3; i < limit; i += 3 { + s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes) + empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i)) + } + check(t, "TestLargeByteWrites (3)", &buf, "") +} + +func TestLargeStringReads(t *testing.T) { + var buf Buffer + for i := 3; i < 30; i += 3 { + s := fillString(t, "TestLargeReads (1)", &buf, "", 5, data[0:len(data)/i]) + empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) + } + check(t, "TestLargeStringReads (3)", &buf, "") +} + +func TestLargeByteReads(t *testing.T) { + var buf Buffer + for i := 3; i < 30; i += 3 { + s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) + empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) + } + check(t, "TestLargeByteReads (3)", &buf, "") +} + +func TestMixedReadsAndWrites(t *testing.T) { + var buf Buffer + s := "" + for i := 0; i < 50; i++ { + wlen := rand.Intn(len(data)) + if i%2 == 0 { + s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen]) + } else { + s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen]) + } + + rlen := rand.Intn(len(data)) + fub := make([]byte, rlen) + n, _ := buf.Read(fub) + s = s[n:] + } + empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len())) +} + +func TestNil(t *testing.T) { + var b *Buffer + if b.String() != "" { + t.Errorf("expected ; got %q", b.String()) + } +} + +func TestReadFrom(t *testing.T) { + var buf Buffer + for i := 3; i < 30; i += 3 { + s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) + var b Buffer + b.ReadFrom(&buf) + empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data))) + } +} + +func TestWriteTo(t *testing.T) { + var buf Buffer + for i := 3; i < 30; i += 3 { + s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) + var b Buffer + buf.WriteTo(&b) + empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(data))) + } +} + +func TestRuneIO(t *testing.T) { + const NRune = 1000 + // Built a test slice while we write the data + b := make([]byte, utf8.UTFMax*NRune) + var buf Buffer + n := 0 + for r := rune(0); r < NRune; r++ { + size := utf8.EncodeRune(b[n:], r) + nbytes, err := buf.WriteRune(r) + if err != nil { + t.Fatalf("WriteRune(%U) error: %s", r, err) + } + if nbytes != size { + t.Fatalf("WriteRune(%U) expected %d, got %d", r, size, nbytes) + } + n += size + } + b = b[0:n] + + // Check the resulting bytes + if !Equal(buf.Bytes(), b) { + t.Fatalf("incorrect result from WriteRune: %q not %q", buf.Bytes(), b) + } + + p := make([]byte, utf8.UTFMax) + // Read it back with ReadRune + for r := rune(0); r < NRune; r++ { + size := utf8.EncodeRune(p, r) + nr, nbytes, err := buf.ReadRune() + if nr != r || nbytes != size || err != nil { + t.Fatalf("ReadRune(%U) got %U,%d not %U,%d (err=%s)", r, nr, nbytes, r, size, err) + } + } + + // Check that UnreadRune works + buf.Reset() + buf.Write(b) + for r := rune(0); r < NRune; r++ { + r1, size, _ := buf.ReadRune() + if err := buf.UnreadRune(); err != nil { + t.Fatalf("UnreadRune(%U) got error %q", r, err) + } + r2, nbytes, err := buf.ReadRune() + if r1 != r2 || r1 != r || nbytes != size || err != nil { + t.Fatalf("ReadRune(%U) after UnreadRune got %U,%d not %U,%d (err=%s)", r, r2, nbytes, r, size, err) + } + } +} + +func TestNext(t *testing.T) { + b := []byte{0, 1, 2, 3, 4} + tmp := make([]byte, 5) + for i := 0; i <= 5; i++ { + for j := i; j <= 5; j++ { + for k := 0; k <= 6; k++ { + // 0 <= i <= j <= 5; 0 <= k <= 6 + // Check that if we start with a buffer + // of length j at offset i and ask for + // Next(k), we get the right bytes. + buf := NewBuffer(b[0:j]) + n, _ := buf.Read(tmp[0:i]) + if n != i { + t.Fatalf("Read %d returned %d", i, n) + } + bb := buf.Next(k) + want := k + if want > j-i { + want = j - i + } + if len(bb) != want { + t.Fatalf("in %d,%d: len(Next(%d)) == %d", i, j, k, len(bb)) + } + for l, v := range bb { + if v != byte(l+i) { + t.Fatalf("in %d,%d: Next(%d)[%d] = %d, want %d", i, j, k, l, v, l+i) + } + } + } + } + } +} + +var readBytesTests = []struct { + buffer string + delim byte + expected []string + err error +}{ + {"", 0, []string{""}, io.EOF}, + {"a\x00", 0, []string{"a\x00"}, nil}, + {"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil}, + {"hello\x01world", 1, []string{"hello\x01"}, nil}, + {"foo\nbar", 0, []string{"foo\nbar"}, io.EOF}, + {"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil}, + {"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, io.EOF}, +} + +func TestReadBytes(t *testing.T) { + for _, test := range readBytesTests { + buf := NewBufferString(test.buffer) + var err error + for _, expected := range test.expected { + var bytes []byte + bytes, err = buf.ReadBytes(test.delim) + if string(bytes) != expected { + t.Errorf("expected %q, got %q", expected, bytes) + } + if err != nil { + break + } + } + if err != test.err { + t.Errorf("expected error %v, got %v", test.err, err) + } + } +} + +func TestReadString(t *testing.T) { + for _, test := range readBytesTests { + buf := NewBufferString(test.buffer) + var err error + for _, expected := range test.expected { + var s string + s, err = buf.ReadString(test.delim) + if s != expected { + t.Errorf("expected %q, got %q", expected, s) + } + if err != nil { + break + } + } + if err != test.err { + t.Errorf("expected error %v, got %v", test.err, err) + } + } +} + +func BenchmarkReadString(b *testing.B) { + const n = 32 << 10 + + data := make([]byte, n) + data[n-1] = 'x' + b.SetBytes(int64(n)) + for i := 0; i < b.N; i++ { + buf := NewBuffer(data) + _, err := buf.ReadString('x') + if err != nil { + b.Fatal(err) + } + } +} + +func TestGrow(t *testing.T) { + x := []byte{'x'} + y := []byte{'y'} + tmp := make([]byte, 72) + for _, startLen := range []int{0, 100, 1000, 10000, 100000} { + xBytes := Repeat(x, startLen) + for _, growLen := range []int{0, 100, 1000, 10000, 100000} { + buf := NewBuffer(xBytes) + // If we read, this affects buf.off, which is good to test. + readBytes, _ := buf.Read(tmp) + buf.Grow(growLen) + yBytes := Repeat(y, growLen) + // Check no allocation occurs in write, as long as we're single-threaded. + var m1, m2 runtime.MemStats + runtime.ReadMemStats(&m1) + buf.Write(yBytes) + runtime.ReadMemStats(&m2) + if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs { + t.Errorf("allocation occurred during write") + } + // Check that buffer has correct data. + if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) { + t.Errorf("bad initial data at %d %d", startLen, growLen) + } + if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) { + t.Errorf("bad written data at %d %d", startLen, growLen) + } + } + } +} + +// Was a bug: used to give EOF reading empty slice at EOF. +func TestReadEmptyAtEOF(t *testing.T) { + b := new(Buffer) + slice := make([]byte, 0) + n, err := b.Read(slice) + if err != nil { + t.Errorf("read error: %v", err) + } + if n != 0 { + t.Errorf("wrong count; got %d want 0", n) + } +} + +func TestUnreadByte(t *testing.T) { + b := new(Buffer) + b.WriteString("abcdefghijklmnopqrstuvwxyz") + + _, err := b.ReadBytes('m') + if err != nil { + t.Fatalf("ReadBytes: %v", err) + } + + err = b.UnreadByte() + if err != nil { + t.Fatalf("UnreadByte: %v", err) + } + c, err := b.ReadByte() + if err != nil { + t.Fatalf("ReadByte: %v", err) + } + if c != 'm' { + t.Errorf("ReadByte = %q; want %q", c, 'm') + } +} + +// Tests that we occasionally compact. Issue 5154. +func TestBufferGrowth(t *testing.T) { + var b Buffer + buf := make([]byte, 1024) + b.Write(buf[0:1]) + var cap0 int + for i := 0; i < 5<<10; i++ { + b.Write(buf) + b.Read(buf) + if i == 0 { + cap0 = b.Cap() + } + } + cap1 := b.Cap() + // (*Buffer).grow allows for 2x capacity slop before sliding, + // so set our error threshold at 3x. + if cap1 > cap0*3 { + t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0) + } +} + +// From Issue 5154. +func BenchmarkBufferNotEmptyWriteRead(b *testing.B) { + buf := make([]byte, 1024) + for i := 0; i < b.N; i++ { + var b Buffer + b.Write(buf[0:1]) + for i := 0; i < 5<<10; i++ { + b.Write(buf) + b.Read(buf) + } + } +} + +// Check that we don't compact too often. From Issue 5154. +func BenchmarkBufferFullSmallReads(b *testing.B) { + buf := make([]byte, 1024) + for i := 0; i < b.N; i++ { + var b Buffer + b.Write(buf) + for b.Len()+20 < b.Cap() { + b.Write(buf[:10]) + } + for i := 0; i < 5<<10; i++ { + b.Read(buf[:1]) + b.Write(buf[:1]) + } + } +} diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go new file mode 100644 index 000000000..7634707b3 --- /dev/null +++ b/src/bytes/bytes.go @@ -0,0 +1,703 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bytes implements functions for the manipulation of byte slices. +// It is analogous to the facilities of the strings package. +package bytes + +import ( + "unicode" + "unicode/utf8" +) + +func equalPortable(a, b []byte) bool { + if len(a) != len(b) { + return false + } + for i, c := range a { + if c != b[i] { + return false + } + } + return true +} + +// explode splits s into a slice of UTF-8 sequences, one per Unicode character (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 { + n = len(s) + } + a := make([][]byte, n) + var size int + na := 0 + for len(s) > 0 { + if na+1 >= n { + a[na] = s + na++ + break + } + _, size = utf8.DecodeRune(s) + a[na] = s[0:size] + s = s[size:] + na++ + } + return a[0:na] +} + +// Count counts the number of non-overlapping instances of sep in s. +func Count(s, sep []byte) int { + n := len(sep) + if n == 0 { + return utf8.RuneCount(s) + 1 + } + if n > len(s) { + return 0 + } + count := 0 + c := sep[0] + i := 0 + t := s[:len(s)-n+1] + for i < len(t) { + if t[i] != c { + o := IndexByte(t[i:], c) + if o < 0 { + break + } + i += o + } + if n == 1 || Equal(s[i:i+n], sep) { + count++ + i += n + continue + } + i++ + } + return count +} + +// Contains reports whether subslice is within b. +func Contains(b, subslice []byte) bool { + return Index(b, subslice) != -1 +} + +// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. +func Index(s, sep []byte) int { + n := len(sep) + if n == 0 { + return 0 + } + if n > len(s) { + return -1 + } + c := sep[0] + if n == 1 { + return IndexByte(s, c) + } + i := 0 + t := s[:len(s)-n+1] + for i < len(t) { + if t[i] != c { + o := IndexByte(t[i:], c) + if o < 0 { + break + } + i += o + } + if Equal(s[i:i+n], sep) { + return i + } + i++ + } + return -1 +} + +func indexBytePortable(s []byte, c byte) int { + for i, b := range s { + if b == c { + return i + } + } + return -1 +} + +// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s. +func LastIndex(s, sep []byte) int { + n := len(sep) + if n == 0 { + return len(s) + } + c := sep[0] + for i := len(s) - n; i >= 0; i-- { + if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) { + 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. +func IndexRune(s []byte, r rune) int { + for i := 0; i < len(s); { + r1, size := utf8.DecodeRune(s[i:]) + if r == r1 { + return i + } + i += size + } + return -1 +} + +// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points. +// It returns the byte index of the first occurrence in s of any of the Unicode +// code points in chars. It returns -1 if chars is empty or if there is no code +// point in common. +func IndexAny(s []byte, chars string) int { + if len(chars) > 0 { + var r rune + var width int + for i := 0; i < len(s); i += width { + r = rune(s[i]) + if r < utf8.RuneSelf { + width = 1 + } else { + r, width = utf8.DecodeRune(s[i:]) + } + for _, ch := range chars { + if r == ch { + return i + } + } + } + } + return -1 +} + +// LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code +// points. It returns the byte index of the last occurrence in s of any of +// the Unicode code points in chars. It returns -1 if chars is empty or if +// there is no code point in common. +func LastIndexAny(s []byte, chars string) int { + if len(chars) > 0 { + for i := len(s); i > 0; { + r, size := utf8.DecodeLastRune(s[0:i]) + i -= size + for _, ch := range chars { + if r == ch { + return i + } + } + } + } + return -1 +} + +// Generic split: splits after each instance of sep, +// including sepSave bytes of sep in the subslices. +func genSplit(s, sep []byte, sepSave, n int) [][]byte { + if n == 0 { + return nil + } + if len(sep) == 0 { + return explode(s, n) + } + if n < 0 { + n = Count(s, sep) + 1 + } + c := sep[0] + start := 0 + a := make([][]byte, n) + na := 0 + for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ { + if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) { + a[na] = s[start : i+sepSave] + na++ + start = i + len(sep) + i += len(sep) - 1 + } + } + a[na] = s[start:] + return a[0 : na+1] +} + +// SplitN slices s into subslices separated by sep and returns a slice of +// the subslices between those separators. +// If sep is empty, SplitN splits after each UTF-8 sequence. +// The count determines the number of subslices to return: +// n > 0: at most n subslices; the last subslice will be the unsplit remainder. +// n == 0: the result is nil (zero subslices) +// n < 0: all subslices +func SplitN(s, sep []byte, n int) [][]byte { return genSplit(s, sep, 0, n) } + +// SplitAfterN slices s into subslices after each instance of sep and +// returns a slice of those subslices. +// If sep is empty, SplitAfterN splits after each UTF-8 sequence. +// The count determines the number of subslices to return: +// n > 0: at most n subslices; the last subslice will be the unsplit remainder. +// n == 0: the result is nil (zero subslices) +// n < 0: all subslices +func SplitAfterN(s, sep []byte, n int) [][]byte { + return genSplit(s, sep, len(sep), n) +} + +// Split slices s into all subslices separated by sep and returns a slice of +// the subslices between those separators. +// If sep is empty, Split splits after each UTF-8 sequence. +// It is equivalent to SplitN with a count of -1. +func Split(s, sep []byte) [][]byte { return genSplit(s, sep, 0, -1) } + +// SplitAfter slices s into all subslices after each instance of sep and +// returns a slice of those subslices. +// If sep is empty, SplitAfter splits after each UTF-8 sequence. +// It is equivalent to SplitAfterN with a count of -1. +func SplitAfter(s, sep []byte) [][]byte { + return genSplit(s, sep, len(sep), -1) +} + +// Fields splits the slice s around each instance of one or more consecutive white space +// characters, returning a slice of subslices of s or an empty list if s contains only white space. +func Fields(s []byte) [][]byte { + return FieldsFunc(s, unicode.IsSpace) +} + +// FieldsFunc interprets s as a sequence of UTF-8-encoded Unicode code points. +// It splits the slice s at each run of code points c satisfying f(c) and +// returns a slice of subslices of s. If all code points in s satisfy f(c), or +// len(s) == 0, an empty slice is returned. +// FieldsFunc makes no guarantees about the order in which it calls f(c). +// If f does not return consistent results for a given c, FieldsFunc may crash. +func FieldsFunc(s []byte, f func(rune) bool) [][]byte { + n := 0 + inField := false + for i := 0; i < len(s); { + r, size := utf8.DecodeRune(s[i:]) + wasInField := inField + inField = !f(r) + if inField && !wasInField { + n++ + } + i += size + } + + a := make([][]byte, n) + na := 0 + fieldStart := -1 + for i := 0; i <= len(s) && na < n; { + r, size := utf8.DecodeRune(s[i:]) + if fieldStart < 0 && size > 0 && !f(r) { + fieldStart = i + i += size + continue + } + if fieldStart >= 0 && (size == 0 || f(r)) { + a[na] = s[fieldStart:i] + na++ + fieldStart = -1 + } + if size == 0 { + break + } + i += size + } + return a[0:na] +} + +// Join concatenates the elements of s to create a new byte slice. The separator +// sep is placed between elements in the resulting slice. +func Join(s [][]byte, sep []byte) []byte { + if len(s) == 0 { + return []byte{} + } + if len(s) == 1 { + // Just return a copy. + return append([]byte(nil), s[0]...) + } + n := len(sep) * (len(s) - 1) + for _, v := range s { + n += len(v) + } + + b := make([]byte, n) + bp := copy(b, s[0]) + for _, v := range s[1:] { + bp += copy(b[bp:], sep) + bp += copy(b[bp:], v) + } + return b +} + +// HasPrefix tests whether the byte slice s begins with prefix. +func HasPrefix(s, prefix []byte) bool { + return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix) +} + +// HasSuffix tests whether the byte slice s ends with suffix. +func HasSuffix(s, suffix []byte) bool { + return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):], suffix) +} + +// Map returns a copy of the byte slice s with all its characters modified +// according to the mapping function. If mapping returns a negative value, the character is +// dropped from the string with no replacement. The characters in s and the +// output are interpreted as UTF-8-encoded Unicode code points. +func Map(mapping func(r rune) rune, s []byte) []byte { + // In the worst case, the slice can grow when mapped, making + // things unpleasant. But it's so rare we barge in assuming it's + // fine. It could also shrink but that falls out naturally. + maxbytes := len(s) // length of b + nbytes := 0 // number of bytes encoded in b + b := make([]byte, maxbytes) + for i := 0; i < len(s); { + wid := 1 + r := rune(s[i]) + if r >= utf8.RuneSelf { + r, wid = utf8.DecodeRune(s[i:]) + } + r = mapping(r) + if r >= 0 { + rl := utf8.RuneLen(r) + if rl < 0 { + rl = len(string(utf8.RuneError)) + } + if nbytes+rl > maxbytes { + // Grow the buffer. + maxbytes = maxbytes*2 + utf8.UTFMax + nb := make([]byte, maxbytes) + copy(nb, b[0:nbytes]) + b = nb + } + nbytes += utf8.EncodeRune(b[nbytes:maxbytes], r) + } + i += wid + } + return b[0:nbytes] +} + +// Repeat returns a new byte slice consisting of count copies of b. +func Repeat(b []byte, count int) []byte { + nb := make([]byte, len(b)*count) + bp := copy(nb, b) + for bp < len(nb) { + copy(nb[bp:], nb[:bp]) + bp *= 2 + } + return nb +} + +// ToUpper returns a copy of the byte slice s with all Unicode letters mapped to their upper case. +func ToUpper(s []byte) []byte { return Map(unicode.ToUpper, s) } + +// ToLower returns a copy of the byte slice s with all Unicode letters mapped to their lower case. +func ToLower(s []byte) []byte { return Map(unicode.ToLower, s) } + +// ToTitle returns a copy of the byte slice s with all Unicode letters mapped to their title case. +func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) } + +// ToUpperSpecial returns a copy of the byte slice s with all Unicode letters mapped to their +// upper case, giving priority to the special casing rules. +func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte { + return Map(func(r rune) rune { return _case.ToUpper(r) }, s) +} + +// ToLowerSpecial returns a copy of the byte slice s with all Unicode letters mapped to their +// lower case, giving priority to the special casing rules. +func ToLowerSpecial(_case unicode.SpecialCase, s []byte) []byte { + return Map(func(r rune) rune { return _case.ToLower(r) }, s) +} + +// ToTitleSpecial returns a copy of the byte slice s with all Unicode letters mapped to their +// title case, giving priority to the special casing rules. +func ToTitleSpecial(_case unicode.SpecialCase, s []byte) []byte { + return Map(func(r rune) rune { return _case.ToTitle(r) }, s) +} + +// isSeparator reports whether the rune could mark a word boundary. +// TODO: update when package unicode captures more of the properties. +func isSeparator(r rune) bool { + // ASCII alphanumerics and underscore are not separators + if r <= 0x7F { + switch { + case '0' <= r && r <= '9': + return false + case 'a' <= r && r <= 'z': + return false + case 'A' <= r && r <= 'Z': + return false + case r == '_': + return false + } + return true + } + // Letters and digits are not separators + if unicode.IsLetter(r) || unicode.IsDigit(r) { + return false + } + // Otherwise, all we can do for now is treat spaces as separators. + return unicode.IsSpace(r) +} + +// 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. +func Title(s []byte) []byte { + // Use a closure here to remember state. + // Hackish but effective. Depends on Map scanning in order and calling + // the closure once per rune. + prev := ' ' + return Map( + func(r rune) rune { + if isSeparator(prev) { + prev = r + return unicode.ToTitle(r) + } + prev = r + return r + }, + s) +} + +// TrimLeftFunc returns a subslice of s by slicing off all leading UTF-8-encoded +// Unicode code points c that satisfy f(c). +func TrimLeftFunc(s []byte, f func(r rune) bool) []byte { + i := indexFunc(s, f, false) + if i == -1 { + return nil + } + return s[i:] +} + +// TrimRightFunc returns a subslice of s by slicing off all trailing UTF-8 +// encoded Unicode code points c that satisfy f(c). +func TrimRightFunc(s []byte, f func(r rune) bool) []byte { + i := lastIndexFunc(s, f, false) + if i >= 0 && s[i] >= utf8.RuneSelf { + _, wid := utf8.DecodeRune(s[i:]) + i += wid + } else { + i++ + } + return s[0:i] +} + +// TrimFunc returns a subslice of s by slicing off all leading and trailing +// UTF-8-encoded Unicode code points c that satisfy f(c). +func TrimFunc(s []byte, f func(r rune) bool) []byte { + return TrimRightFunc(TrimLeftFunc(s, f), f) +} + +// TrimPrefix returns s without the provided leading prefix string. +// If s doesn't start with prefix, s is returned unchanged. +func TrimPrefix(s, prefix []byte) []byte { + if HasPrefix(s, prefix) { + return s[len(prefix):] + } + return s +} + +// TrimSuffix returns s without the provided trailing suffix string. +// If s doesn't end with suffix, s is returned unchanged. +func TrimSuffix(s, suffix []byte) []byte { + if HasSuffix(s, suffix) { + return s[:len(s)-len(suffix)] + } + return s +} + +// IndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points. +// It returns the byte index in s of the first Unicode +// code point satisfying f(c), or -1 if none do. +func IndexFunc(s []byte, f func(r rune) bool) int { + return indexFunc(s, f, true) +} + +// LastIndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points. +// It returns the byte index in s of the last Unicode +// code point satisfying f(c), or -1 if none do. +func LastIndexFunc(s []byte, f func(r rune) bool) int { + return lastIndexFunc(s, f, true) +} + +// indexFunc is the same as IndexFunc except that if +// truth==false, the sense of the predicate function is +// inverted. +func indexFunc(s []byte, f func(r rune) bool, truth bool) int { + start := 0 + for start < len(s) { + wid := 1 + r := rune(s[start]) + if r >= utf8.RuneSelf { + r, wid = utf8.DecodeRune(s[start:]) + } + if f(r) == truth { + return start + } + start += wid + } + return -1 +} + +// lastIndexFunc is the same as LastIndexFunc except that if +// truth==false, the sense of the predicate function is +// inverted. +func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int { + for i := len(s); i > 0; { + r, size := rune(s[i-1]), 1 + if r >= utf8.RuneSelf { + r, size = utf8.DecodeLastRune(s[0:i]) + } + i -= size + if f(r) == truth { + return i + } + } + return -1 +} + +func makeCutsetFunc(cutset string) func(r rune) bool { + return func(r rune) bool { + for _, c := range cutset { + if c == r { + return true + } + } + return false + } +} + +// Trim returns a subslice of s by slicing off all leading and +// trailing UTF-8-encoded Unicode code points contained in cutset. +func Trim(s []byte, cutset string) []byte { + return TrimFunc(s, makeCutsetFunc(cutset)) +} + +// TrimLeft returns a subslice of s by slicing off all leading +// UTF-8-encoded Unicode code points contained in cutset. +func TrimLeft(s []byte, cutset string) []byte { + return TrimLeftFunc(s, makeCutsetFunc(cutset)) +} + +// TrimRight returns a subslice of s by slicing off all trailing +// UTF-8-encoded Unicode code points that are contained in cutset. +func TrimRight(s []byte, cutset string) []byte { + return TrimRightFunc(s, makeCutsetFunc(cutset)) +} + +// TrimSpace returns a subslice of s by slicing off all leading and +// trailing white space, as defined by Unicode. +func TrimSpace(s []byte) []byte { + return TrimFunc(s, unicode.IsSpace) +} + +// Runes returns a slice of runes (Unicode code points) equivalent to s. +func Runes(s []byte) []rune { + t := make([]rune, utf8.RuneCount(s)) + i := 0 + for len(s) > 0 { + r, l := utf8.DecodeRune(s) + t[i] = r + i++ + s = s[l:] + } + return t +} + +// Replace returns a copy of the slice s with the first n +// non-overlapping instances of old replaced by new. +// If old is empty, it matches at the beginning of the slice +// and after each UTF-8 sequence, yielding up to k+1 replacements +// for a k-rune slice. +// If n < 0, there is no limit on the number of replacements. +func Replace(s, old, new []byte, n int) []byte { + m := 0 + if n != 0 { + // Compute number of replacements. + m = Count(s, old) + } + if m == 0 { + // Just return a copy. + return append([]byte(nil), s...) + } + if n < 0 || m < n { + n = m + } + + // Apply replacements to buffer. + t := make([]byte, len(s)+n*(len(new)-len(old))) + w := 0 + start := 0 + for i := 0; i < n; i++ { + j := start + if len(old) == 0 { + if i > 0 { + _, wid := utf8.DecodeRune(s[start:]) + j += wid + } + } else { + j += Index(s[start:], old) + } + w += copy(t[w:], s[start:j]) + w += copy(t[w:], new) + start = j + len(old) + } + w += copy(t[w:], s[start:]) + return t[0:w] +} + +// EqualFold reports whether s and t, interpreted as UTF-8 strings, +// are equal under Unicode case-folding. +func EqualFold(s, t []byte) bool { + for len(s) != 0 && len(t) != 0 { + // Extract first rune from each. + var sr, tr rune + if s[0] < utf8.RuneSelf { + sr, s = rune(s[0]), s[1:] + } else { + r, size := utf8.DecodeRune(s) + sr, s = r, s[size:] + } + if t[0] < utf8.RuneSelf { + tr, t = rune(t[0]), t[1:] + } else { + r, size := utf8.DecodeRune(t) + tr, t = r, t[size:] + } + + // If they match, keep going; if not, return false. + + // Easy case. + if tr == sr { + continue + } + + // Make sr < tr to simplify what follows. + if tr < sr { + tr, sr = sr, tr + } + // Fast check for ASCII. + if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' { + // ASCII, and sr is upper case. tr must be lower case. + if tr == sr+'a'-'A' { + continue + } + return false + } + + // General case. SimpleFold(x) returns the next equivalent rune > x + // or wraps around to smaller values. + r := unicode.SimpleFold(sr) + for r != sr && r < tr { + r = unicode.SimpleFold(r) + } + if r == tr { + continue + } + return false + } + + // One string is empty. Are both? + return len(s) == len(t) +} diff --git a/src/bytes/bytes_decl.go b/src/bytes/bytes_decl.go new file mode 100644 index 000000000..617d7489a --- /dev/null +++ b/src/bytes/bytes_decl.go @@ -0,0 +1,24 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes + +//go:noescape + +// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s. +func IndexByte(s []byte, c byte) int // ../runtime/asm_$GOARCH.s + +//go:noescape + +// Equal returns a boolean reporting whether a and b +// are the same length and contain the same bytes. +// A nil argument is equivalent to an empty slice. +func Equal(a, b []byte) bool // ../runtime/asm_$GOARCH.s + +//go:noescape + +// 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 diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go new file mode 100644 index 000000000..980c41d75 --- /dev/null +++ b/src/bytes/bytes_test.go @@ -0,0 +1,1240 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes_test + +import ( + . "bytes" + "math/rand" + "reflect" + "testing" + "unicode" + "unicode/utf8" +) + +func eq(a, b []string) bool { + if len(a) != len(b) { + return false + } + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + return true +} + +func sliceOfString(s [][]byte) []string { + result := make([]string, len(s)) + for i, v := range s { + result[i] = string(v) + } + return result +} + +// For ease of reading, the test cases use strings that are converted to byte +// slices before invoking the functions. + +var abcd = "abcd" +var faces = "☺☻☹" +var commas = "1,2,3,4" +var dots = "1....2....3....4" + +type BinOpTest struct { + a string + b string + i int +} + +var equalTests = []struct { + a, b []byte + i int +}{ + {[]byte(""), []byte(""), 0}, + {[]byte("a"), []byte(""), 1}, + {[]byte(""), []byte("a"), -1}, + {[]byte("abc"), []byte("abc"), 0}, + {[]byte("ab"), []byte("abc"), -1}, + {[]byte("abc"), []byte("ab"), 1}, + {[]byte("x"), []byte("ab"), 1}, + {[]byte("ab"), []byte("x"), -1}, + {[]byte("x"), []byte("a"), 1}, + {[]byte("b"), []byte("x"), -1}, + // test runtime·memeq's chunked implementation + {[]byte("abcdefgh"), []byte("abcdefgh"), 0}, + {[]byte("abcdefghi"), []byte("abcdefghi"), 0}, + {[]byte("abcdefghi"), []byte("abcdefghj"), -1}, + // nil tests + {nil, nil, 0}, + {[]byte(""), nil, 0}, + {nil, []byte(""), 0}, + {[]byte("a"), nil, 1}, + {nil, []byte("a"), -1}, +} + +func TestEqual(t *testing.T) { + for _, tt := range compareTests { + eql := Equal(tt.a, tt.b) + if eql != (tt.i == 0) { + t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql) + } + eql = EqualPortable(tt.a, tt.b) + if eql != (tt.i == 0) { + t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql) + } + } +} + +func TestEqualExhaustive(t *testing.T) { + var size = 128 + if testing.Short() { + size = 32 + } + a := make([]byte, size) + b := make([]byte, size) + b_init := make([]byte, size) + // randomish but deterministic data + for i := 0; i < size; i++ { + a[i] = byte(17 * i) + b_init[i] = byte(23*i + 100) + } + + for len := 0; len <= size; len++ { + for x := 0; x <= size-len; x++ { + for y := 0; y <= size-len; y++ { + copy(b, b_init) + copy(b[y:y+len], a[x:x+len]) + if !Equal(a[x:x+len], b[y:y+len]) || !Equal(b[y:y+len], a[x:x+len]) { + t.Errorf("Equal(%d, %d, %d) = false", len, x, y) + } + } + } + } +} + +// make sure Equal returns false for minimally different strings. The data +// is all zeros except for a single one in one location. +func TestNotEqual(t *testing.T) { + var size = 128 + if testing.Short() { + size = 32 + } + a := make([]byte, size) + b := make([]byte, size) + + for len := 0; len <= size; len++ { + for x := 0; x <= size-len; x++ { + for y := 0; y <= size-len; y++ { + for diffpos := x; diffpos < x+len; diffpos++ { + a[diffpos] = 1 + if Equal(a[x:x+len], b[y:y+len]) || Equal(b[y:y+len], a[x:x+len]) { + t.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x, y, diffpos) + } + a[diffpos] = 0 + } + } + } + } +} + +var indexTests = []BinOpTest{ + {"", "", 0}, + {"", "a", -1}, + {"", "foo", -1}, + {"fo", "foo", -1}, + {"foo", "baz", -1}, + {"foo", "foo", 0}, + {"oofofoofooo", "f", 2}, + {"oofofoofooo", "foo", 4}, + {"barfoobarfoo", "foo", 3}, + {"foo", "", 0}, + {"foo", "o", 1}, + {"abcABCabc", "A", 3}, + // cases with one byte strings - test IndexByte and special case in Index() + {"", "a", -1}, + {"x", "a", -1}, + {"x", "x", 0}, + {"abc", "a", 0}, + {"abc", "b", 1}, + {"abc", "c", 2}, + {"abc", "x", -1}, + {"barfoobarfooyyyzzzyyyzzzyyyzzzyyyxxxzzzyyy", "x", 33}, + {"foofyfoobarfoobar", "y", 4}, + {"oooooooooooooooooooooo", "r", -1}, +} + +var lastIndexTests = []BinOpTest{ + {"", "", 0}, + {"", "a", -1}, + {"", "foo", -1}, + {"fo", "foo", -1}, + {"foo", "foo", 0}, + {"foo", "f", 0}, + {"oofofoofooo", "f", 7}, + {"oofofoofooo", "foo", 7}, + {"barfoobarfoo", "foo", 9}, + {"foo", "", 3}, + {"foo", "o", 2}, + {"abcABCabc", "A", 3}, + {"abcABCabc", "a", 6}, +} + +var indexAnyTests = []BinOpTest{ + {"", "", -1}, + {"", "a", -1}, + {"", "abc", -1}, + {"a", "", -1}, + {"a", "a", 0}, + {"aaa", "a", 0}, + {"abc", "xyz", -1}, + {"abc", "xcz", 2}, + {"ab☺c", "x☺yz", 2}, + {"aRegExp*", ".(|)*+?^$[]", 7}, + {dots + dots + dots, " ", -1}, +} + +var lastIndexAnyTests = []BinOpTest{ + {"", "", -1}, + {"", "a", -1}, + {"", "abc", -1}, + {"a", "", -1}, + {"a", "a", 0}, + {"aaa", "a", 2}, + {"abc", "xyz", -1}, + {"abc", "ab", 1}, + {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, + {"a.RegExp*", ".(|)*+?^$[]", 8}, + {dots + dots + dots, " ", -1}, +} + +var indexRuneTests = []BinOpTest{ + {"", "a", -1}, + {"", "☺", -1}, + {"foo", "☹", -1}, + {"foo", "o", 1}, + {"foo☺bar", "☺", 3}, + {"foo☺☻☹bar", "☹", 9}, +} + +// Execute f on each test case. funcName should be the name of f; it's used +// in failure reports. +func runIndexTests(t *testing.T, f func(s, sep []byte) int, funcName string, testCases []BinOpTest) { + for _, test := range testCases { + a := []byte(test.a) + b := []byte(test.b) + actual := f(a, b) + if actual != test.i { + t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, b, actual, test.i) + } + } +} + +func runIndexAnyTests(t *testing.T, f func(s []byte, chars string) int, funcName string, testCases []BinOpTest) { + for _, test := range testCases { + a := []byte(test.a) + actual := f(a, test.b) + if actual != test.i { + t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, test.b, actual, test.i) + } + } +} + +func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) } +func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) } +func TestIndexAny(t *testing.T) { runIndexAnyTests(t, IndexAny, "IndexAny", indexAnyTests) } +func TestLastIndexAny(t *testing.T) { + runIndexAnyTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) +} + +func TestIndexByte(t *testing.T) { + for _, tt := range indexTests { + if len(tt.b) != 1 { + continue + } + a := []byte(tt.a) + b := tt.b[0] + pos := IndexByte(a, b) + if pos != tt.i { + t.Errorf(`IndexByte(%q, '%c') = %v`, tt.a, b, pos) + } + posp := IndexBytePortable(a, b) + if posp != tt.i { + t.Errorf(`indexBytePortable(%q, '%c') = %v`, tt.a, b, posp) + } + } +} + +// test a larger buffer with different sizes and alignments +func TestIndexByteBig(t *testing.T) { + var n = 1024 + if testing.Short() { + n = 128 + } + b := make([]byte, n) + for i := 0; i < n; i++ { + // different start alignments + b1 := b[i:] + for j := 0; j < len(b1); j++ { + b1[j] = 'x' + pos := IndexByte(b1, 'x') + if pos != j { + t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) + } + b1[j] = 0 + pos = IndexByte(b1, 'x') + if pos != -1 { + t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) + } + } + // different end alignments + b1 = b[:i] + for j := 0; j < len(b1); j++ { + b1[j] = 'x' + pos := IndexByte(b1, 'x') + if pos != j { + t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) + } + b1[j] = 0 + pos = IndexByte(b1, 'x') + if pos != -1 { + t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) + } + } + // different start and end alignments + b1 = b[i/2 : n-(i+1)/2] + for j := 0; j < len(b1); j++ { + b1[j] = 'x' + pos := IndexByte(b1, 'x') + if pos != j { + t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) + } + b1[j] = 0 + pos = IndexByte(b1, 'x') + if pos != -1 { + t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) + } + } + } +} + +func TestIndexRune(t *testing.T) { + for _, tt := range indexRuneTests { + a := []byte(tt.a) + r, _ := utf8.DecodeRuneInString(tt.b) + pos := IndexRune(a, r) + if pos != tt.i { + t.Errorf(`IndexRune(%q, '%c') = %v`, tt.a, r, pos) + } + } +} + +var bmbuf []byte + +func BenchmarkIndexByte32(b *testing.B) { bmIndexByte(b, IndexByte, 32) } +func BenchmarkIndexByte4K(b *testing.B) { bmIndexByte(b, IndexByte, 4<<10) } +func BenchmarkIndexByte4M(b *testing.B) { bmIndexByte(b, IndexByte, 4<<20) } +func BenchmarkIndexByte64M(b *testing.B) { bmIndexByte(b, IndexByte, 64<<20) } +func BenchmarkIndexBytePortable32(b *testing.B) { bmIndexByte(b, IndexBytePortable, 32) } +func BenchmarkIndexBytePortable4K(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<10) } +func BenchmarkIndexBytePortable4M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<20) } +func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) } + +func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) { + if len(bmbuf) < n { + bmbuf = make([]byte, n) + } + b.SetBytes(int64(n)) + buf := bmbuf[0:n] + buf[n-1] = 'x' + for i := 0; i < b.N; i++ { + j := index(buf, 'x') + if j != n-1 { + b.Fatal("bad index", j) + } + } + buf[n-1] = '\x00' +} + +func BenchmarkEqual0(b *testing.B) { + var buf [4]byte + buf1 := buf[0:0] + buf2 := buf[1:1] + for i := 0; i < b.N; i++ { + eq := Equal(buf1, buf2) + if !eq { + b.Fatal("bad equal") + } + } +} + +func BenchmarkEqual1(b *testing.B) { bmEqual(b, Equal, 1) } +func BenchmarkEqual6(b *testing.B) { bmEqual(b, Equal, 6) } +func BenchmarkEqual9(b *testing.B) { bmEqual(b, Equal, 9) } +func BenchmarkEqual15(b *testing.B) { bmEqual(b, Equal, 15) } +func BenchmarkEqual16(b *testing.B) { bmEqual(b, Equal, 16) } +func BenchmarkEqual20(b *testing.B) { bmEqual(b, Equal, 20) } +func BenchmarkEqual32(b *testing.B) { bmEqual(b, Equal, 32) } +func BenchmarkEqual4K(b *testing.B) { bmEqual(b, Equal, 4<<10) } +func BenchmarkEqual4M(b *testing.B) { bmEqual(b, Equal, 4<<20) } +func BenchmarkEqual64M(b *testing.B) { bmEqual(b, Equal, 64<<20) } +func BenchmarkEqualPort1(b *testing.B) { bmEqual(b, EqualPortable, 1) } +func BenchmarkEqualPort6(b *testing.B) { bmEqual(b, EqualPortable, 6) } +func BenchmarkEqualPort32(b *testing.B) { bmEqual(b, EqualPortable, 32) } +func BenchmarkEqualPort4K(b *testing.B) { bmEqual(b, EqualPortable, 4<<10) } +func BenchmarkEqualPortable4M(b *testing.B) { bmEqual(b, EqualPortable, 4<<20) } +func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) } + +func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) { + if len(bmbuf) < 2*n { + bmbuf = make([]byte, 2*n) + } + b.SetBytes(int64(n)) + buf1 := bmbuf[0:n] + buf2 := bmbuf[n : 2*n] + buf1[n-1] = 'x' + buf2[n-1] = 'x' + for i := 0; i < b.N; i++ { + eq := equal(buf1, buf2) + if !eq { + b.Fatal("bad equal") + } + } + buf1[n-1] = '\x00' + buf2[n-1] = '\x00' +} + +func BenchmarkIndex32(b *testing.B) { bmIndex(b, Index, 32) } +func BenchmarkIndex4K(b *testing.B) { bmIndex(b, Index, 4<<10) } +func BenchmarkIndex4M(b *testing.B) { bmIndex(b, Index, 4<<20) } +func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) } + +func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) { + if len(bmbuf) < n { + bmbuf = make([]byte, n) + } + b.SetBytes(int64(n)) + buf := bmbuf[0:n] + buf[n-1] = 'x' + for i := 0; i < b.N; i++ { + j := index(buf, buf[n-7:]) + if j != n-7 { + b.Fatal("bad index", j) + } + } + buf[n-1] = '\x00' +} + +func BenchmarkIndexEasy32(b *testing.B) { bmIndexEasy(b, Index, 32) } +func BenchmarkIndexEasy4K(b *testing.B) { bmIndexEasy(b, Index, 4<<10) } +func BenchmarkIndexEasy4M(b *testing.B) { bmIndexEasy(b, Index, 4<<20) } +func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) } + +func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) { + if len(bmbuf) < n { + bmbuf = make([]byte, n) + } + b.SetBytes(int64(n)) + buf := bmbuf[0:n] + buf[n-1] = 'x' + buf[n-7] = 'x' + for i := 0; i < b.N; i++ { + j := index(buf, buf[n-7:]) + if j != n-7 { + b.Fatal("bad index", j) + } + } + buf[n-1] = '\x00' + buf[n-7] = '\x00' +} + +func BenchmarkCount32(b *testing.B) { bmCount(b, Count, 32) } +func BenchmarkCount4K(b *testing.B) { bmCount(b, Count, 4<<10) } +func BenchmarkCount4M(b *testing.B) { bmCount(b, Count, 4<<20) } +func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) } + +func bmCount(b *testing.B, count func([]byte, []byte) int, n int) { + if len(bmbuf) < n { + bmbuf = make([]byte, n) + } + b.SetBytes(int64(n)) + buf := bmbuf[0:n] + buf[n-1] = 'x' + for i := 0; i < b.N; i++ { + j := count(buf, buf[n-7:]) + if j != 1 { + b.Fatal("bad count", j) + } + } + buf[n-1] = '\x00' +} + +func BenchmarkCountEasy32(b *testing.B) { bmCountEasy(b, Count, 32) } +func BenchmarkCountEasy4K(b *testing.B) { bmCountEasy(b, Count, 4<<10) } +func BenchmarkCountEasy4M(b *testing.B) { bmCountEasy(b, Count, 4<<20) } +func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) } + +func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) { + if len(bmbuf) < n { + bmbuf = make([]byte, n) + } + b.SetBytes(int64(n)) + buf := bmbuf[0:n] + buf[n-1] = 'x' + buf[n-7] = 'x' + for i := 0; i < b.N; i++ { + j := count(buf, buf[n-7:]) + if j != 1 { + b.Fatal("bad count", j) + } + } + buf[n-1] = '\x00' + buf[n-7] = '\x00' +} + +type ExplodeTest struct { + s string + n int + a []string +} + +var explodetests = []ExplodeTest{ + {"", -1, []string{}}, + {abcd, -1, []string{"a", "b", "c", "d"}}, + {faces, -1, []string{"☺", "☻", "☹"}}, + {abcd, 2, []string{"a", "bcd"}}, +} + +func TestExplode(t *testing.T) { + for _, tt := range explodetests { + a := SplitN([]byte(tt.s), nil, tt.n) + result := sliceOfString(a) + if !eq(result, tt.a) { + t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a) + continue + } + s := Join(a, []byte{}) + if string(s) != tt.s { + t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s) + } + } +} + +type SplitTest struct { + s string + sep string + n int + a []string +} + +var splittests = []SplitTest{ + {abcd, "a", 0, nil}, + {abcd, "a", -1, []string{"", "bcd"}}, + {abcd, "z", -1, []string{"abcd"}}, + {abcd, "", -1, []string{"a", "b", "c", "d"}}, + {commas, ",", -1, []string{"1", "2", "3", "4"}}, + {dots, "...", -1, []string{"1", ".2", ".3", ".4"}}, + {faces, "☹", -1, []string{"☺☻", ""}}, + {faces, "~", -1, []string{faces}}, + {faces, "", -1, []string{"☺", "☻", "☹"}}, + {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}}, + {"1 2", " ", 3, []string{"1", "2"}}, + {"123", "", 2, []string{"1", "23"}}, + {"123", "", 17, []string{"1", "2", "3"}}, +} + +func TestSplit(t *testing.T) { + for _, tt := range splittests { + a := SplitN([]byte(tt.s), []byte(tt.sep), tt.n) + result := sliceOfString(a) + if !eq(result, tt.a) { + t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a) + continue + } + if tt.n == 0 { + continue + } + s := Join(a, []byte(tt.sep)) + if string(s) != tt.s { + t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) + } + if tt.n < 0 { + b := Split([]byte(tt.s), []byte(tt.sep)) + if !reflect.DeepEqual(a, b) { + t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) + } + } + if len(a) > 0 { + in, out := a[0], s + if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] { + t.Errorf("Join(%#v, %q) didn't copy", a, tt.sep) + } + } + } +} + +var splitaftertests = []SplitTest{ + {abcd, "a", -1, []string{"a", "bcd"}}, + {abcd, "z", -1, []string{"abcd"}}, + {abcd, "", -1, []string{"a", "b", "c", "d"}}, + {commas, ",", -1, []string{"1,", "2,", "3,", "4"}}, + {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}}, + {faces, "☹", -1, []string{"☺☻☹", ""}}, + {faces, "~", -1, []string{faces}}, + {faces, "", -1, []string{"☺", "☻", "☹"}}, + {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}}, + {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}}, + {"1 2", " ", 3, []string{"1 ", "2"}}, + {"123", "", 2, []string{"1", "23"}}, + {"123", "", 17, []string{"1", "2", "3"}}, +} + +func TestSplitAfter(t *testing.T) { + for _, tt := range splitaftertests { + a := SplitAfterN([]byte(tt.s), []byte(tt.sep), tt.n) + result := sliceOfString(a) + if !eq(result, tt.a) { + t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a) + continue + } + s := Join(a, nil) + if string(s) != tt.s { + t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) + } + if tt.n < 0 { + b := SplitAfter([]byte(tt.s), []byte(tt.sep)) + if !reflect.DeepEqual(a, b) { + t.Errorf("SplitAfter disagrees withSplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) + } + } + } +} + +type FieldsTest struct { + s string + a []string +} + +var fieldstests = []FieldsTest{ + {"", []string{}}, + {" ", []string{}}, + {" \t ", []string{}}, + {" abc ", []string{"abc"}}, + {"1 2 3 4", []string{"1", "2", "3", "4"}}, + {"1 2 3 4", []string{"1", "2", "3", "4"}}, + {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}}, + {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}}, + {"\u2000\u2001\u2002", []string{}}, + {"\n™\t™\n", []string{"™", "™"}}, + {faces, []string{faces}}, +} + +func TestFields(t *testing.T) { + for _, tt := range fieldstests { + a := Fields([]byte(tt.s)) + result := sliceOfString(a) + if !eq(result, tt.a) { + t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a) + continue + } + } +} + +func TestFieldsFunc(t *testing.T) { + for _, tt := range fieldstests { + a := FieldsFunc([]byte(tt.s), unicode.IsSpace) + result := sliceOfString(a) + if !eq(result, tt.a) { + t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a) + continue + } + } + pred := func(c rune) bool { return c == 'X' } + var fieldsFuncTests = []FieldsTest{ + {"", []string{}}, + {"XX", []string{}}, + {"XXhiXXX", []string{"hi"}}, + {"aXXbXXXcX", []string{"a", "b", "c"}}, + } + for _, tt := range fieldsFuncTests { + a := FieldsFunc([]byte(tt.s), pred) + result := sliceOfString(a) + if !eq(result, tt.a) { + t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a) + } + } +} + +// Test case for any function which accepts and returns a byte slice. +// For ease of creation, we write the byte slices as strings. +type StringTest struct { + in, out string +} + +var upperTests = []StringTest{ + {"", ""}, + {"abc", "ABC"}, + {"AbC123", "ABC123"}, + {"azAZ09_", "AZAZ09_"}, + {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char +} + +var lowerTests = []StringTest{ + {"", ""}, + {"abc", "abc"}, + {"AbC123", "abc123"}, + {"azAZ09_", "azaz09_"}, + {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char +} + +const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" + +var trimSpaceTests = []StringTest{ + {"", ""}, + {"abc", "abc"}, + {space + "abc" + space, "abc"}, + {" ", ""}, + {" \t\r\n \t\t\r\r\n\n ", ""}, + {" \t\r\n x\t\t\r\r\n\n ", "x"}, + {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"}, + {"1 \t\r\n2", "1 \t\r\n2"}, + {" x\x80", "x\x80"}, + {" x\xc0", "x\xc0"}, + {"x \xc0\xc0 ", "x \xc0\xc0"}, + {"x \xc0", "x \xc0"}, + {"x \xc0 ", "x \xc0"}, + {"x \xc0\xc0 ", "x \xc0\xc0"}, + {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"}, + {"x ☺ ", "x ☺"}, +} + +// Execute f on each test case. funcName should be the name of f; it's used +// in failure reports. +func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCases []StringTest) { + for _, tc := range testCases { + actual := string(f([]byte(tc.in))) + if actual != tc.out { + t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out) + } + } +} + +func tenRunes(r rune) string { + runes := make([]rune, 10) + for i := range runes { + runes[i] = r + } + return string(runes) +} + +// User-defined self-inverse mapping function +func rot13(r rune) rune { + const step = 13 + if r >= 'a' && r <= 'z' { + return ((r - 'a' + step) % 26) + 'a' + } + if r >= 'A' && r <= 'Z' { + return ((r - 'A' + step) % 26) + 'A' + } + return r +} + +func TestMap(t *testing.T) { + // Run a couple of awful growth/shrinkage tests + a := tenRunes('a') + + // 1. Grow. This triggers two reallocations in Map. + maxRune := func(r rune) rune { return unicode.MaxRune } + m := Map(maxRune, []byte(a)) + expect := tenRunes(unicode.MaxRune) + if string(m) != expect { + t.Errorf("growing: expected %q got %q", expect, m) + } + + // 2. Shrink + minRune := func(r rune) rune { return 'a' } + m = Map(minRune, []byte(tenRunes(unicode.MaxRune))) + expect = a + if string(m) != expect { + t.Errorf("shrinking: expected %q got %q", expect, m) + } + + // 3. Rot13 + m = Map(rot13, []byte("a to zed")) + expect = "n gb mrq" + if string(m) != expect { + t.Errorf("rot13: expected %q got %q", expect, m) + } + + // 4. Rot13^2 + m = Map(rot13, Map(rot13, []byte("a to zed"))) + expect = "a to zed" + if string(m) != expect { + t.Errorf("rot13: expected %q got %q", expect, m) + } + + // 5. Drop + dropNotLatin := func(r rune) rune { + if unicode.Is(unicode.Latin, r) { + return r + } + return -1 + } + m = Map(dropNotLatin, []byte("Hello, 세계")) + expect = "Hello" + if string(m) != expect { + t.Errorf("drop: expected %q got %q", expect, m) + } + + // 6. Invalid rune + invalidRune := func(r rune) rune { + return utf8.MaxRune + 1 + } + m = Map(invalidRune, []byte("x")) + expect = "\uFFFD" + if string(m) != expect { + t.Errorf("invalidRune: expected %q got %q", expect, m) + } +} + +func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } + +func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) } + +func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) } + +type RepeatTest struct { + in, out string + count int +} + +var RepeatTests = []RepeatTest{ + {"", "", 0}, + {"", "", 1}, + {"", "", 2}, + {"-", "", 0}, + {"-", "-", 1}, + {"-", "----------", 10}, + {"abc ", "abc abc abc ", 3}, +} + +func TestRepeat(t *testing.T) { + for _, tt := range RepeatTests { + tin := []byte(tt.in) + tout := []byte(tt.out) + a := Repeat(tin, tt.count) + if !Equal(a, tout) { + t.Errorf("Repeat(%q, %d) = %q; want %q", tin, tt.count, a, tout) + continue + } + } +} + +func runesEqual(a, b []rune) bool { + if len(a) != len(b) { + return false + } + for i, r := range a { + if r != b[i] { + return false + } + } + return true +} + +type RunesTest struct { + in string + out []rune + lossy bool +} + +var RunesTests = []RunesTest{ + {"", []rune{}, false}, + {" ", []rune{32}, false}, + {"ABC", []rune{65, 66, 67}, false}, + {"abc", []rune{97, 98, 99}, false}, + {"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false}, + {"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true}, + {"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true}, +} + +func TestRunes(t *testing.T) { + for _, tt := range RunesTests { + tin := []byte(tt.in) + a := Runes(tin) + if !runesEqual(a, tt.out) { + t.Errorf("Runes(%q) = %v; want %v", tin, a, tt.out) + continue + } + if !tt.lossy { + // can only test reassembly if we didn't lose information + s := string(a) + if s != tt.in { + t.Errorf("string(Runes(%q)) = %x; want %x", tin, s, tin) + } + } + } +} + +type TrimTest struct { + f string + in, arg, out string +} + +var trimTests = []TrimTest{ + {"Trim", "abba", "a", "bb"}, + {"Trim", "abba", "ab", ""}, + {"TrimLeft", "abba", "ab", ""}, + {"TrimRight", "abba", "ab", ""}, + {"TrimLeft", "abba", "a", "bba"}, + {"TrimRight", "abba", "a", "abb"}, + {"Trim", "", "<>", "tag"}, + {"Trim", "* listitem", " *", "listitem"}, + {"Trim", `"quote"`, `"`, "quote"}, + {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"}, + //empty string tests + {"Trim", "abba", "", "abba"}, + {"Trim", "", "123", ""}, + {"Trim", "", "", ""}, + {"TrimLeft", "abba", "", "abba"}, + {"TrimLeft", "", "123", ""}, + {"TrimLeft", "", "", ""}, + {"TrimRight", "abba", "", "abba"}, + {"TrimRight", "", "123", ""}, + {"TrimRight", "", "", ""}, + {"TrimRight", "☺\xc0", "☺", "☺\xc0"}, + {"TrimPrefix", "aabb", "a", "abb"}, + {"TrimPrefix", "aabb", "b", "aabb"}, + {"TrimSuffix", "aabb", "a", "aabb"}, + {"TrimSuffix", "aabb", "b", "aab"}, +} + +func TestTrim(t *testing.T) { + for _, tc := range trimTests { + name := tc.f + var f func([]byte, string) []byte + var fb func([]byte, []byte) []byte + switch name { + case "Trim": + f = Trim + case "TrimLeft": + f = TrimLeft + case "TrimRight": + f = TrimRight + case "TrimPrefix": + fb = TrimPrefix + case "TrimSuffix": + fb = TrimSuffix + default: + t.Errorf("Undefined trim function %s", name) + } + var actual string + if f != nil { + actual = string(f([]byte(tc.in), tc.arg)) + } else { + actual = string(fb([]byte(tc.in), []byte(tc.arg))) + } + if actual != tc.out { + t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out) + } + } +} + +type predicate struct { + f func(r rune) bool + name string +} + +var isSpace = predicate{unicode.IsSpace, "IsSpace"} +var isDigit = predicate{unicode.IsDigit, "IsDigit"} +var isUpper = predicate{unicode.IsUpper, "IsUpper"} +var isValidRune = predicate{ + func(r rune) bool { + return r != utf8.RuneError + }, + "IsValidRune", +} + +type TrimFuncTest struct { + f predicate + in, out string +} + +func not(p predicate) predicate { + return predicate{ + func(r rune) bool { + return !p.f(r) + }, + "not " + p.name, + } +} + +var trimFuncTests = []TrimFuncTest{ + {isSpace, space + " hello " + space, "hello"}, + {isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"}, + {isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"}, + {not(isSpace), "hello" + space + "hello", space}, + {not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"}, + {isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"}, + {not(isValidRune), "\xc0a\xc0", "a"}, +} + +func TestTrimFunc(t *testing.T) { + for _, tc := range trimFuncTests { + actual := string(TrimFunc([]byte(tc.in), tc.f.f)) + if actual != tc.out { + t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out) + } + } +} + +type IndexFuncTest struct { + in string + f predicate + first, last int +} + +var indexFuncTests = []IndexFuncTest{ + {"", isValidRune, -1, -1}, + {"abc", isDigit, -1, -1}, + {"0123", isDigit, 0, 3}, + {"a1b", isDigit, 1, 1}, + {space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes + {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18}, + {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34}, + {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12}, + + // tests of invalid UTF-8 + {"\x801", isDigit, 1, 1}, + {"\x80abc", isDigit, -1, -1}, + {"\xc0a\xc0", isValidRune, 1, 1}, + {"\xc0a\xc0", not(isValidRune), 0, 2}, + {"\xc0☺\xc0", not(isValidRune), 0, 4}, + {"\xc0☺\xc0\xc0", not(isValidRune), 0, 5}, + {"ab\xc0a\xc0cd", not(isValidRune), 2, 4}, + {"a\xe0\x80cd", not(isValidRune), 1, 2}, +} + +func TestIndexFunc(t *testing.T) { + for _, tc := range indexFuncTests { + first := IndexFunc([]byte(tc.in), tc.f.f) + if first != tc.first { + t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first) + } + last := LastIndexFunc([]byte(tc.in), tc.f.f) + if last != tc.last { + t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last) + } + } +} + +type ReplaceTest struct { + in string + old, new string + n int + out string +} + +var ReplaceTests = []ReplaceTest{ + {"hello", "l", "L", 0, "hello"}, + {"hello", "l", "L", -1, "heLLo"}, + {"hello", "x", "X", -1, "hello"}, + {"", "x", "X", -1, ""}, + {"radar", "r", "", -1, "ada"}, + {"", "", "<>", -1, "<>"}, + {"banana", "a", "<>", -1, "b<>n<>n<>"}, + {"banana", "a", "<>", 1, "b<>nana"}, + {"banana", "a", "<>", 1000, "b<>n<>n<>"}, + {"banana", "an", "<>", -1, "b<><>a"}, + {"banana", "ana", "<>", -1, "b<>na"}, + {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"}, + {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"}, + {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"}, + {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"}, + {"banana", "", "<>", 1, "<>banana"}, + {"banana", "a", "a", -1, "banana"}, + {"banana", "a", "a", 1, "banana"}, + {"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"}, +} + +func TestReplace(t *testing.T) { + for _, tt := range ReplaceTests { + in := append([]byte(tt.in), ""...) + in = in[:len(tt.in)] + out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n) + if s := string(out); s != tt.out { + t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out) + } + if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] { + t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n) + } + } +} + +type TitleTest struct { + in, out string +} + +var TitleTests = []TitleTest{ + {"", ""}, + {"a", "A"}, + {" aaa aaa aaa ", " Aaa Aaa Aaa "}, + {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "}, + {"123a456", "123a456"}, + {"double-blind", "Double-Blind"}, + {"ÿøû", "Ÿøû"}, + {"with_underscore", "With_underscore"}, + {"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"}, +} + +func TestTitle(t *testing.T) { + for _, tt := range TitleTests { + if s := string(Title([]byte(tt.in))); s != tt.out { + t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out) + } + } +} + +var ToTitleTests = []TitleTest{ + {"", ""}, + {"a", "A"}, + {" aaa aaa aaa ", " AAA AAA AAA "}, + {" Aaa Aaa Aaa ", " AAA AAA AAA "}, + {"123a456", "123A456"}, + {"double-blind", "DOUBLE-BLIND"}, + {"ÿøû", "ŸØÛ"}, +} + +func TestToTitle(t *testing.T) { + for _, tt := range ToTitleTests { + if s := string(ToTitle([]byte(tt.in))); s != tt.out { + t.Errorf("ToTitle(%q) = %q, want %q", tt.in, s, tt.out) + } + } +} + +var EqualFoldTests = []struct { + s, t string + out bool +}{ + {"abc", "abc", true}, + {"ABcd", "ABcd", true}, + {"123abc", "123ABC", true}, + {"αβδ", "ΑΒΔ", true}, + {"abc", "xyz", false}, + {"abc", "XYZ", false}, + {"abcdefghijk", "abcdefghijX", false}, + {"abcdefghijk", "abcdefghij\u212A", true}, + {"abcdefghijK", "abcdefghij\u212A", true}, + {"abcdefghijkz", "abcdefghij\u212Ay", false}, + {"abcdefghijKz", "abcdefghij\u212Ay", false}, +} + +func TestEqualFold(t *testing.T) { + for _, tt := range EqualFoldTests { + if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out { + t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out) + } + if out := EqualFold([]byte(tt.t), []byte(tt.s)); out != tt.out { + t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out) + } + } +} + +func TestBufferGrowNegative(t *testing.T) { + defer func() { + if err := recover(); err == nil { + t.Fatal("Grow(-1) should have panicked") + } + }() + var b Buffer + b.Grow(-1) +} + +func TestBufferTruncateNegative(t *testing.T) { + defer func() { + if err := recover(); err == nil { + t.Fatal("Truncate(-1) should have panicked") + } + }() + var b Buffer + b.Truncate(-1) +} + +func TestBufferTruncateOutOfRange(t *testing.T) { + defer func() { + if err := recover(); err == nil { + t.Fatal("Truncate(20) should have panicked") + } + }() + var b Buffer + b.Write(make([]byte, 10)) + b.Truncate(20) +} + +var containsTests = []struct { + b, subslice []byte + want bool +}{ + {[]byte("hello"), []byte("hel"), true}, + {[]byte("日本語"), []byte("日本"), true}, + {[]byte("hello"), []byte("Hello, world"), false}, + {[]byte("東京"), []byte("京東"), false}, +} + +func TestContains(t *testing.T) { + for _, tt := range containsTests { + if got := Contains(tt.b, tt.subslice); got != tt.want { + t.Errorf("Contains(%q, %q) = %v, want %v", tt.b, tt.subslice, got, tt.want) + } + } +} + +var makeFieldsInput = func() []byte { + x := make([]byte, 1<<20) + // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space. + for i := range x { + switch rand.Intn(10) { + case 0: + x[i] = ' ' + case 1: + if i > 0 && x[i-1] == 'x' { + copy(x[i-1:], "χ") + break + } + fallthrough + default: + x[i] = 'x' + } + } + return x +} + +var fieldsInput = makeFieldsInput() + +func BenchmarkFields(b *testing.B) { + b.SetBytes(int64(len(fieldsInput))) + for i := 0; i < b.N; i++ { + Fields(fieldsInput) + } +} + +func BenchmarkFieldsFunc(b *testing.B) { + b.SetBytes(int64(len(fieldsInput))) + for i := 0; i < b.N; i++ { + FieldsFunc(fieldsInput, unicode.IsSpace) + } +} + +func BenchmarkTrimSpace(b *testing.B) { + s := []byte(" Some text. \n") + for i := 0; i < b.N; i++ { + TrimSpace(s) + } +} + +func BenchmarkRepeat(b *testing.B) { + for i := 0; i < b.N; i++ { + Repeat([]byte("-"), 80) + } +} diff --git a/src/bytes/compare_test.go b/src/bytes/compare_test.go new file mode 100644 index 000000000..63522374e --- /dev/null +++ b/src/bytes/compare_test.go @@ -0,0 +1,208 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes_test + +import ( + . "bytes" + "testing" +) + +var compareTests = []struct { + a, b []byte + i int +}{ + {[]byte(""), []byte(""), 0}, + {[]byte("a"), []byte(""), 1}, + {[]byte(""), []byte("a"), -1}, + {[]byte("abc"), []byte("abc"), 0}, + {[]byte("ab"), []byte("abc"), -1}, + {[]byte("abc"), []byte("ab"), 1}, + {[]byte("x"), []byte("ab"), 1}, + {[]byte("ab"), []byte("x"), -1}, + {[]byte("x"), []byte("a"), 1}, + {[]byte("b"), []byte("x"), -1}, + // test runtime·memeq's chunked implementation + {[]byte("abcdefgh"), []byte("abcdefgh"), 0}, + {[]byte("abcdefghi"), []byte("abcdefghi"), 0}, + {[]byte("abcdefghi"), []byte("abcdefghj"), -1}, + // nil tests + {nil, nil, 0}, + {[]byte(""), nil, 0}, + {nil, []byte(""), 0}, + {[]byte("a"), nil, 1}, + {nil, []byte("a"), -1}, +} + +func TestCompare(t *testing.T) { + for _, tt := range compareTests { + cmp := Compare(tt.a, tt.b) + if cmp != tt.i { + t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp) + } + } +} + +func TestCompareIdenticalSlice(t *testing.T) { + var b = []byte("Hello Gophers!") + if Compare(b, b) != 0 { + t.Error("b != b") + } + if Compare(b, b[:1]) != 1 { + t.Error("b > b[:1] failed") + } +} + +func TestCompareBytes(t *testing.T) { + n := 128 + a := make([]byte, n+1) + b := make([]byte, n+1) + for len := 0; len < 128; len++ { + // randomish but deterministic data. No 0 or 255. + for i := 0; i < len; i++ { + a[i] = byte(1 + 31*i%254) + b[i] = byte(1 + 31*i%254) + } + // data past the end is different + for i := len; i <= n; i++ { + a[i] = 8 + b[i] = 9 + } + cmp := Compare(a[:len], b[:len]) + if cmp != 0 { + t.Errorf(`CompareIdentical(%d) = %d`, len, cmp) + } + if len > 0 { + cmp = Compare(a[:len-1], b[:len]) + if cmp != -1 { + t.Errorf(`CompareAshorter(%d) = %d`, len, cmp) + } + cmp = Compare(a[:len], b[:len-1]) + if cmp != 1 { + t.Errorf(`CompareBshorter(%d) = %d`, len, cmp) + } + } + for k := 0; k < len; k++ { + b[k] = a[k] - 1 + cmp = Compare(a[:len], b[:len]) + if cmp != 1 { + t.Errorf(`CompareAbigger(%d,%d) = %d`, len, k, cmp) + } + b[k] = a[k] + 1 + cmp = Compare(a[:len], b[:len]) + if cmp != -1 { + t.Errorf(`CompareBbigger(%d,%d) = %d`, len, k, cmp) + } + b[k] = a[k] + } + } +} + +func BenchmarkCompareBytesEqual(b *testing.B) { + b1 := []byte("Hello Gophers!") + b2 := []byte("Hello Gophers!") + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != 0 { + b.Fatal("b1 != b2") + } + } +} + +func BenchmarkCompareBytesToNil(b *testing.B) { + b1 := []byte("Hello Gophers!") + var b2 []byte + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != 1 { + b.Fatal("b1 > b2 failed") + } + } +} + +func BenchmarkCompareBytesEmpty(b *testing.B) { + b1 := []byte("") + b2 := b1 + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != 0 { + b.Fatal("b1 != b2") + } + } +} + +func BenchmarkCompareBytesIdentical(b *testing.B) { + b1 := []byte("Hello Gophers!") + b2 := b1 + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != 0 { + b.Fatal("b1 != b2") + } + } +} + +func BenchmarkCompareBytesSameLength(b *testing.B) { + b1 := []byte("Hello Gophers!") + b2 := []byte("Hello, Gophers") + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != -1 { + b.Fatal("b1 < b2 failed") + } + } +} + +func BenchmarkCompareBytesDifferentLength(b *testing.B) { + b1 := []byte("Hello Gophers!") + b2 := []byte("Hello, Gophers!") + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != -1 { + b.Fatal("b1 < b2 failed") + } + } +} + +func BenchmarkCompareBytesBigUnaligned(b *testing.B) { + b.StopTimer() + b1 := make([]byte, 0, 1<<20) + for len(b1) < 1<<20 { + b1 = append(b1, "Hello Gophers!"...) + } + b2 := append([]byte("hello"), b1...) + b.StartTimer() + for i := 0; i < b.N; i++ { + if Compare(b1, b2[len("hello"):]) != 0 { + b.Fatal("b1 != b2") + } + } + b.SetBytes(int64(len(b1))) +} + +func BenchmarkCompareBytesBig(b *testing.B) { + b.StopTimer() + b1 := make([]byte, 0, 1<<20) + for len(b1) < 1<<20 { + b1 = append(b1, "Hello Gophers!"...) + } + b2 := append([]byte{}, b1...) + b.StartTimer() + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != 0 { + b.Fatal("b1 != b2") + } + } + b.SetBytes(int64(len(b1))) +} + +func BenchmarkCompareBytesBigIdentical(b *testing.B) { + b.StopTimer() + b1 := make([]byte, 0, 1<<20) + for len(b1) < 1<<20 { + b1 = append(b1, "Hello Gophers!"...) + } + b2 := b1 + b.StartTimer() + for i := 0; i < b.N; i++ { + if Compare(b1, b2) != 0 { + b.Fatal("b1 != b2") + } + } + b.SetBytes(int64(len(b1))) +} diff --git a/src/bytes/equal_test.go b/src/bytes/equal_test.go new file mode 100644 index 000000000..1bf19a74b --- /dev/null +++ b/src/bytes/equal_test.go @@ -0,0 +1,47 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// +build linux + +package bytes_test + +import ( + . "bytes" + "syscall" + "testing" + "unsafe" +) + +// This file tests the situation where memeq is checking +// data very near to a page boundary. We want to make sure +// equal does not read across the boundary and cause a page +// fault where it shouldn't. + +// This test runs only on linux. The code being tested is +// not OS-specific, so it does not need to be tested on all +// operating systems. + +func TestEqualNearPageBoundary(t *testing.T) { + pagesize := syscall.Getpagesize() + b := make([]byte, 4*pagesize) + i := pagesize + for ; uintptr(unsafe.Pointer(&b[i]))%uintptr(pagesize) != 0; i++ { + } + syscall.Mprotect(b[i-pagesize:i], 0) + syscall.Mprotect(b[i+pagesize:i+2*pagesize], 0) + defer syscall.Mprotect(b[i-pagesize:i], syscall.PROT_READ|syscall.PROT_WRITE) + defer syscall.Mprotect(b[i+pagesize:i+2*pagesize], syscall.PROT_READ|syscall.PROT_WRITE) + + // both of these should fault + //pagesize += int(b[i-1]) + //pagesize += int(b[i+pagesize]) + + for j := 0; j < pagesize; j++ { + b[i+j] = 'A' + } + for j := 0; j <= pagesize; j++ { + Equal(b[i:i+j], b[i+pagesize-j:i+pagesize]) + Equal(b[i+pagesize-j:i+pagesize], b[i:i+j]) + } +} diff --git a/src/bytes/example_test.go b/src/bytes/example_test.go new file mode 100644 index 000000000..ad2dbc69b --- /dev/null +++ b/src/bytes/example_test.go @@ -0,0 +1,85 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes_test + +import ( + "bytes" + "encoding/base64" + "fmt" + "io" + "os" + "sort" +) + +func ExampleBuffer() { + var b bytes.Buffer // A Buffer needs no initialization. + b.Write([]byte("Hello ")) + fmt.Fprintf(&b, "world!") + b.WriteTo(os.Stdout) + // Output: Hello world! +} + +func ExampleBuffer_reader() { + // A Buffer can turn a string or a []byte into an io.Reader. + buf := bytes.NewBufferString("R29waGVycyBydWxlIQ==") + dec := base64.NewDecoder(base64.StdEncoding, buf) + io.Copy(os.Stdout, dec) + // Output: Gophers rule! +} + +func ExampleCompare() { + // Interpret Compare's result by comparing it to zero. + var a, b []byte + if bytes.Compare(a, b) < 0 { + // a less b + } + if bytes.Compare(a, b) <= 0 { + // a less or equal b + } + if bytes.Compare(a, b) > 0 { + // a greater b + } + if bytes.Compare(a, b) >= 0 { + // a greater or equal b + } + + // Prefer Equal to Compare for equality comparisons. + if bytes.Equal(a, b) { + // a equal b + } + if !bytes.Equal(a, b) { + // a not equal b + } +} + +func ExampleCompare_search() { + // Binary search to find a matching byte slice. + var needle []byte + var haystack [][]byte // Assume sorted + i := sort.Search(len(haystack), func(i int) bool { + // Return haystack[i] >= needle. + return bytes.Compare(haystack[i], needle) >= 0 + }) + if i < len(haystack) && bytes.Equal(haystack[i], needle) { + // Found it! + } +} + +func ExampleTrimSuffix() { + var b = []byte("Hello, goodbye, etc!") + b = bytes.TrimSuffix(b, []byte("goodbye, etc!")) + b = bytes.TrimSuffix(b, []byte("gopher")) + b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...) + os.Stdout.Write(b) + // Output: Hello, world! +} + +func ExampleTrimPrefix() { + var b = []byte("Goodbye,, world!") + b = bytes.TrimPrefix(b, []byte("Goodbye,")) + b = bytes.TrimPrefix(b, []byte("See ya,")) + fmt.Printf("Hello%s", b) + // Output: Hello, world! +} diff --git a/src/bytes/export_test.go b/src/bytes/export_test.go new file mode 100644 index 000000000..3b915d5ea --- /dev/null +++ b/src/bytes/export_test.go @@ -0,0 +1,13 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes + +// Export func for testing +var IndexBytePortable = indexBytePortable +var EqualPortable = equalPortable + +func (b *Buffer) Cap() int { + return cap(b.buf) +} diff --git a/src/bytes/reader.go b/src/bytes/reader.go new file mode 100644 index 000000000..d2d40fa7c --- /dev/null +++ b/src/bytes/reader.go @@ -0,0 +1,144 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes + +import ( + "errors" + "io" + "unicode/utf8" +) + +// A Reader implements the io.Reader, io.ReaderAt, io.WriterTo, io.Seeker, +// io.ByteScanner, and io.RuneScanner interfaces by reading from +// a byte slice. +// Unlike a Buffer, a Reader is read-only and supports seeking. +type Reader struct { + s []byte + i int64 // current reading index + prevRune int // index of previous rune; or < 0 +} + +// Len returns the number of bytes of the unread portion of the +// slice. +func (r *Reader) Len() int { + if r.i >= int64(len(r.s)) { + return 0 + } + return int(int64(len(r.s)) - r.i) +} + +func (r *Reader) Read(b []byte) (n int, err error) { + if len(b) == 0 { + return 0, nil + } + if r.i >= int64(len(r.s)) { + return 0, io.EOF + } + r.prevRune = -1 + n = copy(b, r.s[r.i:]) + r.i += int64(n) + return +} + +func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { + // cannot modify state - see io.ReaderAt + if off < 0 { + return 0, errors.New("bytes.Reader.ReadAt: negative offset") + } + if off >= int64(len(r.s)) { + return 0, io.EOF + } + n = copy(b, r.s[off:]) + if n < len(b) { + err = io.EOF + } + return +} + +func (r *Reader) ReadByte() (b byte, err error) { + r.prevRune = -1 + if r.i >= int64(len(r.s)) { + return 0, io.EOF + } + b = r.s[r.i] + r.i++ + return +} + +func (r *Reader) UnreadByte() error { + r.prevRune = -1 + if r.i <= 0 { + return errors.New("bytes.Reader.UnreadByte: at beginning of slice") + } + r.i-- + return nil +} + +func (r *Reader) ReadRune() (ch rune, size int, err error) { + if r.i >= int64(len(r.s)) { + r.prevRune = -1 + return 0, 0, io.EOF + } + r.prevRune = int(r.i) + if c := r.s[r.i]; c < utf8.RuneSelf { + r.i++ + return rune(c), 1, nil + } + ch, size = utf8.DecodeRune(r.s[r.i:]) + r.i += int64(size) + return +} + +func (r *Reader) UnreadRune() error { + if r.prevRune < 0 { + return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune") + } + r.i = int64(r.prevRune) + r.prevRune = -1 + return nil +} + +// Seek implements the io.Seeker interface. +func (r *Reader) Seek(offset int64, whence int) (int64, error) { + r.prevRune = -1 + var abs int64 + switch whence { + case 0: + abs = offset + case 1: + abs = int64(r.i) + offset + case 2: + abs = int64(len(r.s)) + offset + default: + return 0, errors.New("bytes.Reader.Seek: invalid whence") + } + if abs < 0 { + return 0, errors.New("bytes.Reader.Seek: negative position") + } + r.i = abs + return abs, nil +} + +// WriteTo implements the io.WriterTo interface. +func (r *Reader) WriteTo(w io.Writer) (n int64, err error) { + r.prevRune = -1 + if r.i >= int64(len(r.s)) { + return 0, nil + } + b := r.s[r.i:] + m, err := w.Write(b) + if m > len(b) { + panic("bytes.Reader.WriteTo: invalid Write count") + } + r.i += int64(m) + n = int64(m) + if m != len(b) && err == nil { + err = io.ErrShortWrite + } + return +} + +// NewReader returns a new Reader reading from b. +func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} } diff --git a/src/bytes/reader_test.go b/src/bytes/reader_test.go new file mode 100644 index 000000000..d3dce5349 --- /dev/null +++ b/src/bytes/reader_test.go @@ -0,0 +1,246 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bytes_test + +import ( + . "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "sync" + "testing" +) + +func TestReader(t *testing.T) { + r := NewReader([]byte("0123456789")) + tests := []struct { + off int64 + seek int + n int + want string + wantpos int64 + seekerr string + }{ + {seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"}, + {seek: os.SEEK_SET, off: 1, n: 1, want: "1"}, + {seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"}, + {seek: os.SEEK_SET, off: -1, seekerr: "bytes.Reader.Seek: negative position"}, + {seek: os.SEEK_SET, off: 1 << 33, wantpos: 1 << 33}, + {seek: os.SEEK_CUR, off: 1, wantpos: 1<<33 + 1}, + {seek: os.SEEK_SET, n: 5, want: "01234"}, + {seek: os.SEEK_CUR, n: 5, want: "56789"}, + {seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"}, + } + + for i, tt := range tests { + pos, err := r.Seek(tt.off, tt.seek) + if err == nil && tt.seekerr != "" { + t.Errorf("%d. want seek error %q", i, tt.seekerr) + continue + } + if err != nil && err.Error() != tt.seekerr { + t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr) + continue + } + if tt.wantpos != 0 && tt.wantpos != pos { + t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos) + } + buf := make([]byte, tt.n) + n, err := r.Read(buf) + if err != nil { + t.Errorf("%d. read = %v", i, err) + continue + } + got := string(buf[:n]) + if got != tt.want { + t.Errorf("%d. got %q; want %q", i, got, tt.want) + } + } +} + +func TestReadAfterBigSeek(t *testing.T) { + r := NewReader([]byte("0123456789")) + if _, err := r.Seek(1<<31+5, os.SEEK_SET); err != nil { + t.Fatal(err) + } + if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF { + t.Errorf("Read = %d, %v; want 0, EOF", n, err) + } +} + +func TestReaderAt(t *testing.T) { + r := NewReader([]byte("0123456789")) + tests := []struct { + off int64 + n int + want string + wanterr interface{} + }{ + {0, 10, "0123456789", nil}, + {1, 10, "123456789", io.EOF}, + {1, 9, "123456789", nil}, + {11, 10, "", io.EOF}, + {0, 0, "", nil}, + {-1, 0, "", "bytes.Reader.ReadAt: negative offset"}, + } + for i, tt := range tests { + b := make([]byte, tt.n) + rn, err := r.ReadAt(b, tt.off) + got := string(b[:rn]) + if got != tt.want { + t.Errorf("%d. got %q; want %q", i, got, tt.want) + } + if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) { + t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr) + } + } +} + +func TestReaderAtConcurrent(t *testing.T) { + // Test for the race detector, to verify ReadAt doesn't mutate + // any state. + r := NewReader([]byte("0123456789")) + var wg sync.WaitGroup + for i := 0; i < 5; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + var buf [1]byte + r.ReadAt(buf[:], int64(i)) + }(i) + } + wg.Wait() +} + +func TestEmptyReaderConcurrent(t *testing.T) { + // Test for the race detector, to verify a Read that doesn't yield any bytes + // is okay to use from multiple goroutines. This was our historic behavior. + // See golang.org/issue/7856 + r := NewReader([]byte{}) + var wg sync.WaitGroup + for i := 0; i < 5; i++ { + wg.Add(2) + go func() { + defer wg.Done() + var buf [1]byte + r.Read(buf[:]) + }() + go func() { + defer wg.Done() + r.Read(nil) + }() + } + wg.Wait() +} + +func TestReaderWriteTo(t *testing.T) { + for i := 0; i < 30; i += 3 { + var l int + if i > 0 { + l = len(data) / i + } + s := data[:l] + r := NewReader(testBytes[:l]) + var b Buffer + n, err := r.WriteTo(&b) + if expect := int64(len(s)); n != expect { + t.Errorf("got %v; want %v", n, expect) + } + if err != nil { + t.Errorf("for length %d: got error = %v; want nil", l, err) + } + if b.String() != s { + t.Errorf("got string %q; want %q", b.String(), s) + } + if r.Len() != 0 { + t.Errorf("reader contains %v bytes; want 0", r.Len()) + } + } +} + +func TestReaderLen(t *testing.T) { + const data = "hello world" + r := NewReader([]byte(data)) + if got, want := r.Len(), 11; got != want { + t.Errorf("r.Len(): got %d, want %d", got, want) + } + if n, err := r.Read(make([]byte, 10)); err != nil || n != 10 { + t.Errorf("Read failed: read %d %v", n, err) + } + if got, want := r.Len(), 1; got != want { + t.Errorf("r.Len(): got %d, want %d", got, want) + } + if n, err := r.Read(make([]byte, 1)); err != nil || n != 1 { + t.Errorf("Read failed: read %d %v", n, err) + } + if got, want := r.Len(), 0; got != want { + t.Errorf("r.Len(): got %d, want %d", got, want) + } +} + +var UnreadRuneErrorTests = []struct { + name string + f func(*Reader) +}{ + {"Read", func(r *Reader) { r.Read([]byte{0}) }}, + {"ReadByte", func(r *Reader) { r.ReadByte() }}, + {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, + {"Seek", func(r *Reader) { r.Seek(0, 1) }}, + {"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }}, +} + +func TestUnreadRuneError(t *testing.T) { + for _, tt := range UnreadRuneErrorTests { + reader := NewReader([]byte("0123456789")) + if _, _, err := reader.ReadRune(); err != nil { + // should not happen + t.Fatal(err) + } + tt.f(reader) + err := reader.UnreadRune() + if err == nil { + t.Errorf("Unreading after %s: expected error", tt.name) + } + } +} + +func TestReaderDoubleUnreadRune(t *testing.T) { + buf := NewBuffer([]byte("groucho")) + if _, _, err := buf.ReadRune(); err != nil { + // should not happen + t.Fatal(err) + } + if err := buf.UnreadByte(); err != nil { + // should not happen + t.Fatal(err) + } + if err := buf.UnreadByte(); err == nil { + t.Fatal("UnreadByte: expected error, got nil") + } +} + +// verify that copying from an empty reader always has the same results, +// regardless of the presence of a WriteTo method. +func TestReaderCopyNothing(t *testing.T) { + type nErr struct { + n int64 + err error + } + type justReader struct { + io.Reader + } + type justWriter struct { + io.Writer + } + discard := justWriter{ioutil.Discard} // hide ReadFrom + + var with, withOut nErr + with.n, with.err = io.Copy(discard, NewReader(nil)) + withOut.n, withOut.err = io.Copy(discard, justReader{NewReader(nil)}) + if with != withOut { + t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut) + } +} diff --git a/src/cmd/5a/a.y b/src/cmd/5a/a.y index 56d0c563d..ad647606e 100644 --- a/src/cmd/5a/a.y +++ b/src/cmd/5a/a.y @@ -33,7 +33,7 @@ #include /* if we don't, bison will, and a.h re-#defines getc */ #include #include "a.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" %} %union { diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c index 571fdf7f2..9c6970947 100644 --- a/src/cmd/5a/lex.c +++ b/src/cmd/5a/lex.c @@ -85,6 +85,7 @@ main(int argc, char *argv[]) ctxt = linknew(&linkarm); ctxt->diag = yyerror; ctxt->bso = &bstdout; + ctxt->enforce_data_order = 1; Binit(&bstdout, 1, OWRITE); listinit5(); fmtinstall('L', Lconv); @@ -199,8 +200,8 @@ struct "R6", LREG, 6, "R7", LREG, 7, "R8", LREG, 8, - "m", LREG, 9, // avoid unintentionally clobber m/g using R9/R10 - "g", LREG, 10, + "R9", LREG, 9, + "g", LREG, 10, // avoid unintentionally clobber g using R10 "R11", LREG, 11, "R12", LREG, 12, "R13", LREG, 13, diff --git a/src/cmd/5a/y.tab.c b/src/cmd/5a/y.tab.c index 0bc8c34e1..a6251b835 100644 --- a/src/cmd/5a/y.tab.c +++ b/src/cmd/5a/y.tab.c @@ -69,7 +69,7 @@ #include /* if we don't, bison will, and a.h re-#defines getc */ #include #include "a.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" /* Line 371 of yacc.c */ #line 76 "y.tab.c" diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c index 08ed36055..5a049ae62 100644 --- a/src/cmd/5c/cgen.c +++ b/src/cmd/5c/cgen.c @@ -29,7 +29,7 @@ // THE SOFTWARE. #include "gc.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" void _cgen(Node *n, Node *nn, int inrel) @@ -46,7 +46,7 @@ _cgen(Node *n, Node *nn, int inrel) } if(n == Z || n->type == T) return; - if(typesuv[n->type->etype]) { + if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) { sugen(n, nn, n->type->width); return; } @@ -75,7 +75,7 @@ _cgen(Node *n, Node *nn, int inrel) if(r != Z && r->complex >= FNX) switch(o) { default: - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); @@ -107,7 +107,7 @@ _cgen(Node *n, Node *nn, int inrel) if(l->addable >= INDEXED && l->complex < FNX) { if(nn != Z || r->addable < INDEXED) { if(r->complex >= FNX && nn == Z) - regret(&nod, r); + regret(&nod, r, 0, 0); else regalloc(&nod, r, nn); cgen(r, &nod); @@ -348,7 +348,7 @@ _cgen(Node *n, Node *nn, int inrel) if(l->op != OIND) diag(n, "bad function call"); - regret(&nod, l->left); + regret(&nod, l->left, 0, 0); cgen(l->left, &nod); regsalloc(&nod1, l->left); gopcode(OAS, &nod, Z, &nod1); @@ -366,22 +366,20 @@ _cgen(Node *n, Node *nn, int inrel) if(REGARG >= 0) o = reg[REGARG]; gargs(r, &nod, &nod1); - gpcdata(PCDATA_ArgSize, curarg); if(l->addable < INDEXED) { reglcgen(&nod, l, Z); gopcode(OFUNC, Z, Z, &nod); regfree(&nod); } else gopcode(OFUNC, Z, Z, l); - gpcdata(PCDATA_ArgSize, -1); if(REGARG >= 0) if(o != reg[REGARG]) reg[REGARG]--; - if(nn != Z) { - regret(&nod, n); - gopcode(OAS, &nod, Z, nn); + regret(&nod, n, l->type, 1); + if(nn != Z) + gmove(&nod, nn); + if(nod.op == OREGISTER) regfree(&nod); - } break; case OIND: @@ -823,7 +821,7 @@ boolgen(Node *n, int true, Node *nn) if(true) o = comrel[relindex(o)]; if(l->complex >= FNX && r->complex >= FNX) { - regret(&nod, r); + regret(&nod, r, 0, 0); cgenrel(r, &nod); regsalloc(&nod1, r); gopcode(OAS, &nod, Z, &nod1); @@ -957,7 +955,7 @@ sugen(Node *n, Node *nn, int32 w) if(nn != Z && side(nn)) { nod1 = *n; nod1.type = typ(TIND, n->type); - regret(&nod2, &nod1); + regret(&nod2, &nod1, 0, 0); lcgen(nn, &nod2); regsalloc(&nod0, &nod1); gopcode(OAS, &nod2, Z, &nod0); @@ -1036,6 +1034,20 @@ sugen(Node *n, Node *nn, int32 w) break; case OFUNC: + if(!hasdotdotdot(n->left->type)) { + cgen(n, Z); + if(nn != Z) { + curarg -= n->type->width; + regret(&nod1, n, n->left->type, 1); + if(nn->complex >= FNX) { + regsalloc(&nod2, n); + cgen(&nod1, &nod2); + nod1 = nod2; + } + cgen(&nod1, nn); + } + break; + } if(nn == Z) { sugen(n, nodrat, w); break; diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h index 40d3a2b07..7417b7dbe 100644 --- a/src/cmd/5c/gc.h +++ b/src/cmd/5c/gc.h @@ -144,7 +144,6 @@ EXTERN Prog* lastp; EXTERN int32 maxargsafe; EXTERN int mnstring; EXTERN Multab multab[20]; -EXTERN int retok; extern int hintabsize; EXTERN Node* nodrat; EXTERN Node* nodret; @@ -211,7 +210,7 @@ void usedset(Node*, int); void xcom(Node*); int bcomplex(Node*, Node*); Prog* gtext(Sym*, int32); -vlong argsize(void); +vlong argsize(int); /* * cgen.c @@ -237,7 +236,7 @@ Node* nodconst(int32); Node* nod32const(vlong); Node* nodfconst(double); void nodreg(Node*, Node*, int); -void regret(Node*, Node*); +void regret(Node*, Node*, Type*, int); int tmpreg(void); void regalloc(Node*, Node*, Node*); void regfree(Node*); diff --git a/src/cmd/5c/peep.c b/src/cmd/5c/peep.c index 143400a63..1de56b594 100644 --- a/src/cmd/5c/peep.c +++ b/src/cmd/5c/peep.c @@ -853,11 +853,15 @@ xtramodes(Reg *r, Addr *a) switch (p1->from.type) { case D_REG: /* register offset */ + if(nacl) + return 0; a->type = D_SHIFT; a->offset = p1->from.reg; break; case D_SHIFT: /* scaled register offset */ + if(nacl) + return 0; a->type = D_SHIFT; case D_CONST: /* immediate offset */ diff --git a/src/cmd/5c/reg.c b/src/cmd/5c/reg.c index b9ac21abd..9024d5f49 100644 --- a/src/cmd/5c/reg.c +++ b/src/cmd/5c/reg.c @@ -204,6 +204,16 @@ regopt(Prog *p) break; } + /* the mod/div runtime routines smash R12 */ + switch(p->as) { + case AMOD: + case AMODU: + case ADIV: + case ADIVU: + regbits |= RtoB(12); + break; + } + if(p->as == AMOVM) { if(p->from.type == D_CONST) z = p->from.offset; @@ -396,7 +406,7 @@ loop2: rgp->cost = change; nregion++; if(nregion >= NRGN) { - warn(Z, "too many regions"); + fatal(Z, "too many regions"); goto brk; } rgp++; @@ -632,11 +642,8 @@ mkvar(Addr *a, int docon) if(s) if(s->name[0] == '.') goto none; - if(nvar >= NVAR) { - if(debug['w'] > 1 && s) - warn(Z, "variable not optimized: %s", s->name); - goto none; - } + if(nvar >= NVAR) + fatal(Z, "variable not optimized: %s", s->name); i = nvar; nvar++; v = &var[i]; diff --git a/src/cmd/5c/sgen.c b/src/cmd/5c/sgen.c index efcc0437b..a36612caa 100644 --- a/src/cmd/5c/sgen.c +++ b/src/cmd/5c/sgen.c @@ -36,7 +36,7 @@ gtext(Sym *s, int32 stkoff) { int32 a; - a = argsize(); + a = argsize(1); if((textflag & NOSPLIT) != 0 && stkoff >= 128) yyerror("stack frame too large for NOSPLIT function"); diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c index fd81a4e68..f39963b8f 100644 --- a/src/cmd/5c/swt.c +++ b/src/cmd/5c/swt.c @@ -60,7 +60,7 @@ swit2(C1 *q, int nc, int32 def, Node *n) if(nc >= 3) { i = (q+nc-1)->val - (q+0)->val; - if(i > 0 && i < nc*2) + if(!nacl && i > 0 && i < nc*2) goto direct; } if(nc < 5) { @@ -374,10 +374,11 @@ align(int32 i, Type *t, int op, int32 *maxalign) { int32 o; Type *v; - int w; + int w, packw; o = i; w = 1; + packw = 0; switch(op) { default: diag(Z, "unknown align opcode %d", op); @@ -388,7 +389,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1) w = 1; if(packflg) - w = packflg; + packw = packflg; break; case Ael1: /* initial align of struct element */ @@ -404,7 +405,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1 || w > SZ_LONG) fatal(Z, "align"); if(packflg) - w = packflg; + packw = packflg; break; case Ael2: /* width of a struct element */ @@ -440,6 +441,8 @@ align(int32 i, Type *t, int op, int32 *maxalign) w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ break; } + if(packw != 0 && xround(o, w) != xround(o, packw)) + diag(Z, "#pragma pack changes offset of %T", t); o = xround(o, w); if(maxalign != nil && *maxalign < w) *maxalign = w; diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c index a753510ca..af40220cc 100644 --- a/src/cmd/5c/txt.c +++ b/src/cmd/5c/txt.c @@ -274,15 +274,43 @@ nodreg(Node *n, Node *nn, int reg) } void -regret(Node *n, Node *nn) +regret(Node *n, Node *nn, Type *t, int mode) { int r; - r = REGRET; - if(typefd[nn->type->etype]) - r = FREGRET+NREG; - nodreg(n, nn, r); - reg[r]++; + if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) { + r = REGRET; + if(typefd[nn->type->etype]) + r = FREGRET+NREG; + nodreg(n, nn, r); + reg[r]++; + return; + } + + if(mode == 1) { + // fetch returned value after call. + // already called gargs, so curarg is set. + curarg = (curarg+3) & ~3; + regaalloc(n, nn); + return; + } + + if(mode == 2) { + // store value to be returned. + // must compute arg offset. + if(t->etype != TFUNC) + fatal(Z, "bad regret func %T", t); + *n = *nn; + n->op = ONAME; + n->class = CPARAM; + n->sym = slookup(".ret"); + n->complex = nodret->complex; + n->xoffset = argsize(0); + n->addable = 20; + return; + } + + fatal(Z, "bad regret"); } int diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 9011b2022..c535cfbef 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -254,7 +254,6 @@ cgen(Node *n, Node *res) case OOR: case OXOR: case OADD: - case OADDPTR: case OMUL: a = optoas(n->op, nl->type); goto sbop; @@ -1107,11 +1106,10 @@ bgen(Node *n, int true, int likely, Prog *to) { int et, a; Node *nl, *nr, *r; - Node n1, n2, n3, n4, tmp; + Node n1, n2, n3, tmp; NodeList *ll; Prog *p1, *p2; - USED(n4); // in unreachable code below if(debug['g']) { dump("\nbgen", n); } @@ -1497,7 +1495,7 @@ sgen(Node *n, Node *res, int64 w) if(osrc < odst && odst < osrc+w) dir = -dir; - if(op == AMOVW && dir > 0 && c >= 4 && c <= 128) { + if(op == AMOVW && !nacl && dir > 0 && c >= 4 && c <= 128) { r0.op = OREGISTER; r0.val.u.reg = REGALLOC_R0; r1.op = OREGISTER; @@ -1524,7 +1522,7 @@ sgen(Node *n, Node *res, int64 w) f = sysfunc("duffcopy"); p = gins(ADUFFCOPY, N, f); afunclit(&p->to, f); - // 8 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s + // 8 and 128 = magic constants: see ../../runtime/asm_arm.s p->to.offset = 8*(128-c); regfree(&tmp); @@ -1636,7 +1634,10 @@ int componentgen(Node *nr, Node *nl) { Node nodl, nodr, tmp; + Type *t; int freel, freer; + vlong fldcount; + vlong loffset, roffset; freel = 0; freer = 0; @@ -1646,8 +1647,33 @@ componentgen(Node *nr, Node *nl) goto no; case TARRAY: - if(!isslice(nl->type)) + t = nl->type; + + // Slices are ok. + if(isslice(t)) + break; + // Small arrays are ok. + if(t->bound > 0 && t->bound <= 3 && !isfat(t->type)) + break; + + goto no; + + case TSTRUCT: + // Small structs with non-fat types are ok. + // Zero-sized structs are treated separately elsewhere. + fldcount = 0; + for(t=nl->type->type; t; t=t->down) { + if(isfat(t->type)) + goto no; + if(t->etype != TFIELD) + fatal("componentgen: not a TFIELD: %lT", t); + fldcount++; + } + if(fldcount == 0 || fldcount > 4) goto no; + + break; + case TSTRING: case TINTER: break; @@ -1675,6 +1701,7 @@ componentgen(Node *nr, Node *nl) freer = 1; } + // nl and nr are 'cadable' which basically means they are names (variables) now. // If they are the same variable, don't generate any code, because the // VARDEF we generate will mark the old value as dead incorrectly. @@ -1684,8 +1711,25 @@ componentgen(Node *nr, Node *nl) switch(nl->type->etype) { case TARRAY: + // componentgen for arrays. if(nl->op == ONAME) gvardef(nl); + t = nl->type; + if(!isslice(t)) { + nodl.type = t->type; + nodr.type = nodl.type; + for(fldcount=0; fldcount < t->bound; fldcount++) { + if(nr == N) + clearslim(&nodl); + else + gmove(&nodr, &nodl); + nodl.xoffset += t->type->width; + nodr.xoffset += t->type->width; + } + goto yes; + } + + // componentgen for slices. nodl.xoffset += Array_array; nodl.type = ptrto(nl->type->type); @@ -1760,6 +1804,31 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); goto yes; + + case TSTRUCT: + if(nl->op == ONAME) + gvardef(nl); + loffset = nodl.xoffset; + roffset = nodr.xoffset; + // funarg structs may not begin at offset zero. + if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type) + loffset -= nl->type->type->width; + if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type) + roffset -= nr->type->type->width; + + for(t=nl->type->type; t; t=t->down) { + nodl.xoffset = loffset + t->width; + nodl.type = t->type; + + if(nr == N) + clearslim(&nodl); + else { + nodr.xoffset = roffset + t->width; + nodr.type = nodl.type; + gmove(&nodr, &nodl); + } + } + goto yes; } no: diff --git a/src/cmd/5g/galign.c b/src/cmd/5g/galign.c index a62102ef8..b4c45da69 100644 --- a/src/cmd/5g/galign.c +++ b/src/cmd/5g/galign.c @@ -23,10 +23,10 @@ vlong MAXWIDTH = (1LL<<32) - 1; */ Typedef typedefs[] = { - "int", TINT, TINT32, - "uint", TUINT, TUINT32, - "uintptr", TUINTPTR, TUINT32, - 0 + {"int", TINT, TINT32}, + {"uint", TUINT, TUINT32}, + {"uintptr", TUINTPTR, TUINT32}, + {0} }; void diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h index 413e93c24..00914bfa3 100644 --- a/src/cmd/5g/gg.h +++ b/src/cmd/5g/gg.h @@ -11,10 +11,13 @@ #define TEXTFLAG reg -#define REGALLOC_R0 0 -#define REGALLOC_RMAX REGEXT -#define REGALLOC_F0 NREG -#define REGALLOC_FMAX (REGALLOC_F0 + FREGEXT) +enum +{ + REGALLOC_R0 = 0, + REGALLOC_RMAX = REGEXT, + REGALLOC_F0 = NREG, + REGALLOC_FMAX = REGALLOC_F0 + FREGEXT, +}; EXTERN int32 dynloc; EXTERN uchar reg[REGALLOC_FMAX+1]; @@ -106,7 +109,6 @@ void split64(Node*, Node*, Node*); void splitclean(void); Node* ncon(uint32 i); void gtrack(Sym*); -void gargsize(int32); /* * obj.c diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c index fb32c2f36..53cddb760 100644 --- a/src/cmd/5g/ggen.c +++ b/src/cmd/5g/ggen.c @@ -76,7 +76,7 @@ zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0) if(cnt < 4*widthptr) { for(i = 0; i < cnt; i += widthptr) p = appendpp(p, AMOVW, D_REG, 0, 0, D_OREG, REGSP, 4+frame+lo+i); - } else if(cnt <= 128*widthptr) { + } else if(!nacl && (cnt <= 128*widthptr)) { p = appendpp(p, AADD, D_CONST, NREG, 4+frame+lo, D_REG, 1, 0); p->reg = REGSP; p = appendpp(p, ADUFFZERO, D_NONE, NREG, 0, D_OREG, NREG, 0); @@ -179,28 +179,12 @@ fixautoused(Prog* p) void ginscall(Node *f, int proc) { - int32 arg; Prog *p; Node n1, r, r1, con; if(f->type != T) setmaxarg(f->type); - arg = -1; - // Most functions have a fixed-size argument block, so traceback uses that during unwind. - // Not all, though: there are some variadic functions in package runtime, - // and for those we emit call-specific metadata recorded by caller. - // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub), - // so we do this for all indirect calls as well. - if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) { - arg = f->type->argwid; - if(proc == 1 || proc == 2) - arg += 3*widthptr; - } - - if(arg != -1) - gargsize(arg); - switch(proc) { default: fatal("ginscall: bad proc %d", proc); @@ -297,9 +281,6 @@ ginscall(Node *f, int proc) } break; } - - if(arg != -1) - gargsize(-1); } /* @@ -906,11 +887,11 @@ clearfat(Node *nl) patch(gbranch(ABNE, T, 0), pl); regfree(&end); - } else if(q >= 4) { + } else if(q >= 4 && !nacl) { f = sysfunc("duffzero"); p = gins(ADUFFZERO, N, f); afunclit(&p->to, f); - // 4 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s + // 4 and 128 = magic constants: see ../../runtime/asm_arm.s p->to.offset = 4*(128-q); } else while(q > 0) { diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c index f66c87b5a..06e274e14 100644 --- a/src/cmd/5g/gsubr.c +++ b/src/cmd/5g/gsubr.c @@ -31,11 +31,11 @@ #include #include #include "gg.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" // TODO(rsc): Can make this bigger if we move // the text segment up higher in 5l for all GOOS. -// At the same time, can raise StackBig in ../../pkg/runtime/stack.h. +// At the same time, can raise StackBig in ../../runtime/stack.h. long unmappedzero = 4096; void @@ -206,17 +206,7 @@ ggloblnod(Node *nam) } void -gargsize(int32 size) -{ - Node n1, n2; - - nodconst(&n1, types[TINT32], PCDATA_ArgSize); - nodconst(&n2, types[TINT32], size); - gins(APCDATA, &n1, &n2); -} - -void -ggloblsym(Sym *s, int32 width, int dupok, int rodata) +ggloblsym(Sym *s, int32 width, int8 flags) { Prog *p; @@ -227,10 +217,7 @@ ggloblsym(Sym *s, int32 width, int dupok, int rodata) p->to.type = D_CONST; p->to.name = D_NONE; p->to.offset = width; - if(dupok) - p->reg |= DUPOK; - if(rodata) - p->reg |= RODATA; + p->reg = flags; } void @@ -374,7 +361,7 @@ regalloc(Node *n, Type *t, Node *o) print("registers allocated at\n"); for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++) print("%d %p\n", i, regpc[i]); - yyerror("out of fixed registers"); + fatal("out of fixed registers"); goto err; case TFLOAT32: @@ -387,7 +374,7 @@ regalloc(Node *n, Type *t, Node *o) for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++) if(reg[i] == 0) goto out; - yyerror("out of floating point registers"); + fatal("out of floating point registers"); goto err; case TCOMPLEX64: @@ -636,6 +623,7 @@ splitclean(void) } #define CASE(a,b) (((a)<<16)|((b)<<0)) +/*c2go int CASE(int, int); */ void gmove(Node *f, Node *t) @@ -1601,7 +1589,6 @@ optoas(int op, Type *t) case CASE(OADD, TINT32): case CASE(OADD, TUINT32): case CASE(OADD, TPTR32): - case CASE(OADDPTR, TPTR32): a = AADD; break; diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h index e3e3f78ed..1946c1d33 100644 --- a/src/cmd/5g/opt.h +++ b/src/cmd/5g/opt.h @@ -49,6 +49,24 @@ typedef struct Reg Reg; typedef struct Rgn Rgn; +/*c2go +extern Node *Z; +enum +{ + D_HI = D_NONE, + D_LO = D_NONE, + CLOAD = 5, + CREF = 5, + CINF = 1000, + LOOP = 3, +}; + +uint32 BLOAD(Reg*); +uint32 BSTORE(Reg*); +uint32 LOAD(Reg*); +uint32 STORE(Reg*); +*/ + // A Reg is a wrapper around a single Prog (one instruction) that holds // register optimization information while the optimizer runs. // r->prog is the instruction. @@ -71,8 +89,10 @@ struct Reg int32 regu; // register used bitmap }; #define R ((Reg*)0) +/*c2go extern Reg *R; */ #define NRGN 600 +/*c2go enum { NRGN = 600 }; */ struct Rgn { Reg* enter; diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c index 4aa645206..639f4c5f6 100644 --- a/src/cmd/5g/peep.c +++ b/src/cmd/5g/peep.c @@ -564,6 +564,8 @@ gotit: * .. */ #define FAIL(msg) { if(debug['P']) print("\t%s; FAILURE\n", msg); return 0; } +/*c2go void FAIL(char*); */ + int shiftprop(Flow *r) { @@ -875,11 +877,15 @@ xtramodes(Graph *g, Flow *r, Adr *a) switch (p1->from.type) { case D_REG: /* register offset */ + if(nacl) + return 0; a->type = D_SHIFT; a->offset = p1->from.reg; break; case D_SHIFT: /* scaled register offset */ + if(nacl) + return 0; a->type = D_SHIFT; case D_CONST: /* immediate offset */ diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 4762df506..b78c268df 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -36,6 +36,11 @@ #define NREGVAR 32 #define REGBITS ((uint32)0xffffffff) +/*c2go enum { + NREGVAR = 32, + REGBITS = 0xffffffff, +}; +*/ void addsplits(void); static Reg* firstr; @@ -194,7 +199,7 @@ regopt(Prog *firstp) proginfo(&info, p); // Avoid making variables for direct-called functions. - if(p->as == ABL && p->to.type == D_EXTERN) + if(p->as == ABL && p->to.name == D_EXTERN) continue; bit = mkvar(r, &p->from); @@ -222,6 +227,10 @@ regopt(Prog *firstp) for(z=0; zset.b[z] |= bit.b[z]; } + + /* the mod/div runtime routines smash R12 */ + if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU) + r->set.b[0] |= RtoB(12); } if(firstr == R) return; @@ -1306,6 +1315,7 @@ void addreg(Adr *a, int rn) { a->sym = nil; + a->node = nil; a->name = D_NONE; a->type = D_REG; a->reg = rn; diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h index 9e8aceecb..7b16ac446 100644 --- a/src/cmd/5l/5.out.h +++ b/src/cmd/5l/5.out.h @@ -28,34 +28,94 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#define NSNAME 8 -#define NSYM 50 -#define NREG 16 +enum +{ + NSNAME = 8, + NSYM = 50, + NREG = 16, +}; #include "../ld/textflag.h" -#define REGRET 0 /* -1 disables use of REGARG */ #define REGARG -1 -/* compiler allocates R1 up as temps */ -/* compiler allocates register variables R3 up */ -#define REGEXT 10 -/* these two registers are declared in runtime.h */ -#define REGG (REGEXT-0) -#define REGM (REGEXT-1) -/* compiler allocates external registers R10 down */ -#define REGTMP 11 -#define REGSP 13 -#define REGLINK 14 -#define REGPC 15 - -#define NFREG 16 -#define FREGRET 0 -#define FREGEXT 7 -#define FREGTMP 15 +/*c2go enum { REGARG = -1 }; */ + +enum +{ + REGRET = 0, + /* compiler allocates R1 up as temps */ + /* compiler allocates register variables R3 up */ + /* compiler allocates external registers R10 down */ + REGEXT = 10, + /* these two registers are declared in runtime.h */ + REGG = REGEXT-0, + REGM = REGEXT-1, + + REGTMP = 11, + REGSP = 13, + REGLINK = 14, + REGPC = 15, + + NFREG = 16, + FREGRET = 0, + FREGEXT = 7, + FREGTMP = 15, +}; /* compiler allocates register variables F0 up */ /* compiler allocates external registers F7 down */ -enum as +enum +{ + C_NONE, + C_REG, + C_REGREG, + C_REGREG2, + C_SHIFT, + C_FREG, + C_PSR, + C_FCR, + + C_RCON, /* 0xff rotated */ + C_NCON, /* ~RCON */ + C_SCON, /* 0xffff */ + C_LCON, + C_LCONADDR, + C_ZFCON, + C_SFCON, + C_LFCON, + + C_RACON, + C_LACON, + + C_SBRA, + C_LBRA, + + C_HAUTO, /* halfword insn offset (-0xff to 0xff) */ + C_FAUTO, /* float insn offset (0 to 0x3fc, word aligned) */ + C_HFAUTO, /* both H and F */ + C_SAUTO, /* -0xfff to 0xfff */ + C_LAUTO, + + C_HOREG, + C_FOREG, + C_HFOREG, + C_SOREG, + C_ROREG, + C_SROREG, /* both nil and R */ + C_LOREG, + + C_PC, + C_SP, + C_HREG, + + C_ADDR, /* reference to relocatable address */ + + C_GOK, + + C_NCLASS, /* must be the last */ +}; + +enum { AXXX, @@ -202,6 +262,8 @@ enum as AVARKILL, ADUFFCOPY, ADUFFZERO, + ADATABUNDLE, + ADATABUNDLEEND, AMRC, // MRC/MCR @@ -209,35 +271,38 @@ enum as }; /* scond byte */ -#define C_SCOND ((1<<4)-1) -#define C_SBIT (1<<4) -#define C_PBIT (1<<5) -#define C_WBIT (1<<6) -#define C_FBIT (1<<7) /* psr flags-only */ -#define C_UBIT (1<<7) /* up bit, unsigned bit */ - -#define C_SCOND_EQ 0 -#define C_SCOND_NE 1 -#define C_SCOND_HS 2 -#define C_SCOND_LO 3 -#define C_SCOND_MI 4 -#define C_SCOND_PL 5 -#define C_SCOND_VS 6 -#define C_SCOND_VC 7 -#define C_SCOND_HI 8 -#define C_SCOND_LS 9 -#define C_SCOND_GE 10 -#define C_SCOND_LT 11 -#define C_SCOND_GT 12 -#define C_SCOND_LE 13 -#define C_SCOND_NONE 14 -#define C_SCOND_NV 15 - -/* D_SHIFT type */ -#define SHIFT_LL 0<<5 -#define SHIFT_LR 1<<5 -#define SHIFT_AR 2<<5 -#define SHIFT_RR 3<<5 +enum +{ + C_SCOND = (1<<4)-1, + C_SBIT = 1<<4, + C_PBIT = 1<<5, + C_WBIT = 1<<6, + C_FBIT = 1<<7, /* psr flags-only */ + C_UBIT = 1<<7, /* up bit, unsigned bit */ + + C_SCOND_EQ = 0, + C_SCOND_NE = 1, + C_SCOND_HS = 2, + C_SCOND_LO = 3, + C_SCOND_MI = 4, + C_SCOND_PL = 5, + C_SCOND_VS = 6, + C_SCOND_VC = 7, + C_SCOND_HI = 8, + C_SCOND_LS = 9, + C_SCOND_GE = 10, + C_SCOND_LT = 11, + C_SCOND_GT = 12, + C_SCOND_LE = 13, + C_SCOND_NONE = 14, + C_SCOND_NV = 15, + + /* D_SHIFT type */ + SHIFT_LL = 0<<5, + SHIFT_LR = 1<<5, + SHIFT_AR = 2<<5, + SHIFT_RR = 3<<5, +}; enum { @@ -279,3 +344,4 @@ enum * this is the ranlib header */ #define SYMDEF "__.GOSYMDEF" +/*c2go extern char SYMDEF[]; */ diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index e87921218..9c1c04e2d 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -648,19 +648,20 @@ asmb(void) switch(HEADTYPE) { default: case Hplan9: /* plan 9 */ - lput(0x647); /* magic */ - lput(segtext.filelen); /* sizes */ - lput(segdata.filelen); - lput(segdata.len - segdata.filelen); - lput(symsize); /* nsyms */ - lput(entryvalue()); /* va of entry */ - lput(0L); - lput(lcsize); + LPUT(0x647); /* magic */ + LPUT(segtext.filelen); /* sizes */ + LPUT(segdata.filelen); + LPUT(segdata.len - segdata.filelen); + LPUT(symsize); /* nsyms */ + LPUT(entryvalue()); /* va of entry */ + LPUT(0L); + LPUT(lcsize); break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: + case Hnacl: asmbelf(symo); break; } @@ -675,64 +676,6 @@ asmb(void) } } -/* -void -cput(int32 c) -{ - *cbp++ = c; - if(--cbc <= 0) - cflush(); -} -*/ - -void -wput(int32 l) -{ - - cbp[0] = l>>8; - cbp[1] = l; - cbp += 2; - cbc -= 2; - if(cbc <= 0) - cflush(); -} - - -void -hput(int32 l) -{ - - cbp[0] = l>>8; - cbp[1] = l; - cbp += 2; - cbc -= 2; - if(cbc <= 0) - cflush(); -} - -void -lput(int32 l) -{ - - cbp[0] = l>>24; - cbp[1] = l>>16; - cbp[2] = l>>8; - cbp[3] = l; - cbp += 4; - cbc -= 4; - if(cbc <= 0) - cflush(); -} - -void -nopstat(char *f, Count *c) -{ - if(c->outof) - Bprint(&bso, "%s delay %d/%d (%.2f)\n", f, - c->outof - c->count, c->outof, - (double)(c->outof - c->count)/c->outof); -} - int32 rnd(int32 v, int32 r) { diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index 761bc861a..c881a544a 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -48,23 +48,8 @@ enum #define EXTERN extern #endif -/* do not undefine this - code will be removed eventually */ -#define CALLEEBX - -#define dynptrsize 0 - #define P ((Prog*)0) #define S ((LSym*)0) -#define TNAME (ctxt->cursym?ctxt->cursym->name:noname) - -#define SIGNINTERN (1729*325*1729) - -typedef struct Count Count; -struct Count -{ - int32 count; - int32 outof; -}; enum { @@ -73,62 +58,9 @@ enum LABEL = 1<<1, LEAF = 1<<2, - STRINGSZ = 200, - MINSIZ = 64, - NENT = 100, - MAXIO = 8192, - MAXHIST = 40, /* limit of path elements for history symbols */ MINLC = 4, - - C_NONE = 0, - C_REG, - C_REGREG, - C_REGREG2, - C_SHIFT, - C_FREG, - C_PSR, - C_FCR, - - C_RCON, /* 0xff rotated */ - C_NCON, /* ~RCON */ - C_SCON, /* 0xffff */ - C_LCON, - C_LCONADDR, - C_ZFCON, - C_SFCON, - C_LFCON, - - C_RACON, - C_LACON, - - C_SBRA, - C_LBRA, - - C_HAUTO, /* halfword insn offset (-0xff to 0xff) */ - C_FAUTO, /* float insn offset (0 to 0x3fc, word aligned) */ - C_HFAUTO, /* both H and F */ - C_SAUTO, /* -0xfff to 0xfff */ - C_LAUTO, - - C_HOREG, - C_FOREG, - C_HFOREG, - C_SOREG, - C_ROREG, - C_SROREG, /* both nil and R */ - C_LOREG, - - C_PC, - C_SP, - C_HREG, - - C_ADDR, /* reference to relocatable address */ - - C_GOK, }; -#ifndef COFFCVT - EXTERN int32 autosize; EXTERN LSym* datap; EXTERN int debug[128]; @@ -152,26 +84,18 @@ void adddynrela(LSym *rel, LSym *s, Reloc *r); void adddynsym(Link *ctxt, LSym *s); int archreloc(Reloc *r, LSym *s, vlong *val); void asmb(void); -void cput(int32 c); int elfreloc1(Reloc *r, vlong sectoff); void elfsetupplt(void); -void hput(int32 l); void listinit(void); -void lput(int32 l); int machoreloc1(Reloc *r, vlong sectoff); void main(int argc, char *argv[]); -void noops(void); -void nopstat(char *f, Count *c); int32 rnd(int32 v, int32 r); -void wput(int32 l); /* Native is little-endian */ #define LPUT(a) lputl(a) #define WPUT(a) wputl(a) #define VPUT(a) abort() -#endif - /* Used by ../ld/dwarf.c */ enum { diff --git a/src/cmd/5l/mkenam b/src/cmd/5l/mkenam deleted file mode 100644 index 6cccb0263..000000000 --- a/src/cmd/5l/mkenam +++ /dev/null @@ -1,45 +0,0 @@ -# Inferno utils/5c/mkenam -# http://code.google.com/p/inferno-os/source/browse/utils/5c/mkenam -# -# Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -# Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -# Portions Copyright © 1997-1999 Vita Nuova Limited -# Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -# Portions Copyright © 2004,2006 Bruce Ellis -# Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -# Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -# Portions Copyright © 2009 The Go Authors. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -awk ' -BEGIN { - print "char* anames[] =" - print "{" -} - -/^ A/ { - name=$1 - sub(/,/, "", name) - sub(/^A/, "", name) - print "\t\"" name "\"," -} - -END { print "};" } -' ../5l/5.out.h >enam.c diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c deleted file mode 100644 index d42c86289..000000000 --- a/src/cmd/5l/noop.c +++ /dev/null @@ -1,43 +0,0 @@ -// Inferno utils/5l/noop.c -// http://code.google.com/p/inferno-os/source/browse/utils/5l/noop.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// Code transformations. - -#include "l.h" -#include "../ld/lib.h" - -void -noops(void) -{ - LSym *s; - - for(s = ctxt->textp; s != nil; s = s->next) - ctxt->arch->addstacksplit(ctxt, s); -} diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c index 86a0ece2e..c6f60ee7c 100644 --- a/src/cmd/5l/obj.c +++ b/src/cmd/5l/obj.c @@ -63,6 +63,7 @@ archinit(void) break; case Hlinux: case Hfreebsd: + case Hnacl: break; } @@ -82,7 +83,6 @@ archinit(void) case Hlinux: /* arm elf */ case Hfreebsd: case Hnetbsd: - case Hnacl: debug['d'] = 0; // with dynamic linking elfinit(); HEADR = ELFRESERVE; @@ -93,6 +93,17 @@ archinit(void) if(INITRND == -1) INITRND = 4096; break; + case Hnacl: + elfinit(); + HEADR = 0x10000; + funcalign = 16; + if(INITTEXT == -1) + INITTEXT = 0x20000; + if(INITDAT == -1) + INITDAT = 0; + if(INITRND == -1) + INITRND = 0x10000; + break; } if(INITDAT != 0 && INITRND != 0) print("warning: -D0x%ux is ignored because of -R0x%ux\n", diff --git a/src/cmd/6a/a.y b/src/cmd/6a/a.y index 6fd491067..1089d4061 100644 --- a/src/cmd/6a/a.y +++ b/src/cmd/6a/a.y @@ -33,7 +33,7 @@ #include /* if we don't, bison will, and a.h re-#defines getc */ #include #include "a.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" %} %union { Sym *sym; diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c index 167e6b6c1..8973d6974 100644 --- a/src/cmd/6a/lex.c +++ b/src/cmd/6a/lex.c @@ -101,6 +101,7 @@ main(int argc, char *argv[]) ctxt = linknew(thelinkarch); ctxt->diag = yyerror; ctxt->bso = &bstdout; + ctxt->enforce_data_order = 1; Binit(&bstdout, 1, OWRITE); listinit6(); fmtinstall('L', Lconv); @@ -435,49 +436,49 @@ struct "IRETQ", LTYPE0, AIRETQ, "IRETW", LTYPE0, AIRETW, - "JOS", LTYPER, AJOS, + "JOS", LTYPER, AJOS, /* overflow set (OF = 1) */ "JO", LTYPER, AJOS, /* alternate */ - "JOC", LTYPER, AJOC, + "JOC", LTYPER, AJOC, /* overflow clear (OF = 0) */ "JNO", LTYPER, AJOC, /* alternate */ - "JCS", LTYPER, AJCS, + "JCS", LTYPER, AJCS, /* carry set (CF = 1) */ "JB", LTYPER, AJCS, /* alternate */ "JC", LTYPER, AJCS, /* alternate */ "JNAE", LTYPER, AJCS, /* alternate */ "JLO", LTYPER, AJCS, /* alternate */ - "JCC", LTYPER, AJCC, + "JCC", LTYPER, AJCC, /* carry clear (CF = 0) */ "JAE", LTYPER, AJCC, /* alternate */ "JNB", LTYPER, AJCC, /* alternate */ "JNC", LTYPER, AJCC, /* alternate */ "JHS", LTYPER, AJCC, /* alternate */ - "JEQ", LTYPER, AJEQ, + "JEQ", LTYPER, AJEQ, /* equal (ZF = 1) */ "JE", LTYPER, AJEQ, /* alternate */ "JZ", LTYPER, AJEQ, /* alternate */ - "JNE", LTYPER, AJNE, + "JNE", LTYPER, AJNE, /* not equal (ZF = 0) */ "JNZ", LTYPER, AJNE, /* alternate */ - "JLS", LTYPER, AJLS, + "JLS", LTYPER, AJLS, /* lower or same (unsigned) (CF = 1 || ZF = 1) */ "JBE", LTYPER, AJLS, /* alternate */ "JNA", LTYPER, AJLS, /* alternate */ - "JHI", LTYPER, AJHI, + "JHI", LTYPER, AJHI, /* higher (unsigned) (CF = 0 && ZF = 0) */ "JA", LTYPER, AJHI, /* alternate */ "JNBE", LTYPER, AJHI, /* alternate */ - "JMI", LTYPER, AJMI, + "JMI", LTYPER, AJMI, /* negative (minus) (SF = 1) */ "JS", LTYPER, AJMI, /* alternate */ - "JPL", LTYPER, AJPL, + "JPL", LTYPER, AJPL, /* non-negative (plus) (SF = 0) */ "JNS", LTYPER, AJPL, /* alternate */ - "JPS", LTYPER, AJPS, + "JPS", LTYPER, AJPS, /* parity set (PF = 1) */ "JP", LTYPER, AJPS, /* alternate */ "JPE", LTYPER, AJPS, /* alternate */ - "JPC", LTYPER, AJPC, + "JPC", LTYPER, AJPC, /* parity clear (PF = 0) */ "JNP", LTYPER, AJPC, /* alternate */ "JPO", LTYPER, AJPC, /* alternate */ - "JLT", LTYPER, AJLT, + "JLT", LTYPER, AJLT, /* less than (signed) (SF != OF) */ "JL", LTYPER, AJLT, /* alternate */ "JNGE", LTYPER, AJLT, /* alternate */ - "JGE", LTYPER, AJGE, + "JGE", LTYPER, AJGE, /* greater than or equal (signed) (SF = OF) */ "JNL", LTYPER, AJGE, /* alternate */ - "JLE", LTYPER, AJLE, + "JLE", LTYPER, AJLE, /* less than or equal (signed) (ZF = 1 || SF != OF) */ "JNG", LTYPER, AJLE, /* alternate */ - "JGT", LTYPER, AJGT, + "JGT", LTYPER, AJGT, /* greater than (signed) (ZF = 0 && SF = OF) */ "JG", LTYPER, AJGT, /* alternate */ "JNLE", LTYPER, AJGT, /* alternate */ "JCXZL", LTYPER, AJCXZL, @@ -612,7 +613,7 @@ struct "SCASL", LTYPE0, ASCASL, "SCASQ", LTYPE0, ASCASQ, "SCASW", LTYPE0, ASCASW, - "SETCC", LTYPE1, ASETCC, + "SETCC", LTYPE1, ASETCC, /* see JCC etc above for condition codes */ "SETCS", LTYPE1, ASETCS, "SETEQ", LTYPE1, ASETEQ, "SETGE", LTYPE1, ASETGE, diff --git a/src/cmd/6a/y.tab.c b/src/cmd/6a/y.tab.c index a4f0f74cc..b69fd95b5 100644 --- a/src/cmd/6a/y.tab.c +++ b/src/cmd/6a/y.tab.c @@ -150,7 +150,7 @@ #include /* if we don't, bison will, and a.h re-#defines getc */ #include #include "a.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" /* Enabling traces. */ diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c index bdef76ff0..68dd7bb5f 100644 --- a/src/cmd/6c/cgen.c +++ b/src/cmd/6c/cgen.c @@ -29,7 +29,7 @@ // THE SOFTWARE. #include "gc.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" /* ,x/^(print|prtree)\(/i/\/\/ */ int castup(Type*, Type*); @@ -51,7 +51,7 @@ cgen(Node *n, Node *nn) } if(n == Z || n->type == T) return; - if(typesu[n->type->etype]) { + if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) { sugen(n, nn, n->type->width); return; } @@ -88,7 +88,7 @@ cgen(Node *n, Node *nn) if(cond(o) && typesu[l->type->etype]) break; - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); @@ -135,7 +135,7 @@ cgen(Node *n, Node *nn) if(!hardleft) { if(nn != Z || r->addable < INDEXED || hardconst(r)) { if(r->complex >= FNX && nn == Z) - regret(&nod, r); + regret(&nod, r, 0, 0); else regalloc(&nod, r, nn); cgen(r, &nod); @@ -929,7 +929,7 @@ cgen(Node *n, Node *nn) if(l->op != OIND) diag(n, "bad function call"); - regret(&nod, l->left); + regret(&nod, l->left, 0, 0); cgen(l->left, &nod); regsalloc(&nod1, l->left); gmove(&nod, &nod1); @@ -945,7 +945,6 @@ cgen(Node *n, Node *nn) return; } gargs(r, &nod, &nod1); - gpcdata(PCDATA_ArgSize, curarg); if(l->addable < INDEXED) { reglcgen(&nod, l, nn); nod.op = OREGISTER; @@ -953,14 +952,13 @@ cgen(Node *n, Node *nn) regfree(&nod); } else gopcode(OFUNC, n->type, Z, l); - gpcdata(PCDATA_ArgSize, -1); if(REGARG >= 0 && reg[REGARG]) reg[REGARG]--; - if(nn != Z) { - regret(&nod, n); + regret(&nod, n, l->type, 1); // update maxarg if nothing else + if(nn != Z) gmove(&nod, nn); + if(nod.op == OREGISTER) regfree(&nod); - } break; case OIND: @@ -1382,7 +1380,7 @@ boolgen(Node *n, int true, Node *nn) if(true) o = comrel[relindex(o)]; if(l->complex >= FNX && r->complex >= FNX) { - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); gmove(&nod, &nod1); @@ -1535,7 +1533,7 @@ sugen(Node *n, Node *nn, int32 w) if(nn != Z && side(nn)) { nod1 = *n; nod1.type = typ(TIND, n->type); - regret(&nod2, &nod1); + regret(&nod2, &nod1, 0, 0); lcgen(nn, &nod2); regsalloc(&nod0, &nod1); cgen(&nod2, &nod0); @@ -1617,6 +1615,20 @@ sugen(Node *n, Node *nn, int32 w) break; case OFUNC: + if(!hasdotdotdot(n->left->type)) { + cgen(n, Z); + if(nn != Z) { + curarg -= n->type->width; + regret(&nod1, n, n->left->type, 1); + if(nn->complex >= FNX) { + regsalloc(&nod2, n); + cgen(&nod1, &nod2); + nod1 = nod2; + } + cgen(&nod1, nn); + } + break; + } if(nn == Z) { sugen(n, nodrat, w); break; diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h index a196e55a8..aa9d95d21 100644 --- a/src/cmd/6c/gc.h +++ b/src/cmd/6c/gc.h @@ -143,7 +143,6 @@ EXTERN int32 cursafe; EXTERN Prog* lastp; EXTERN int32 maxargsafe; EXTERN int mnstring; -EXTERN int retok; EXTERN Node* nodrat; EXTERN Node* nodret; EXTERN Node* nodsafe; @@ -211,7 +210,7 @@ void xcom(Node*); void indx(Node*); int bcomplex(Node*, Node*); Prog* gtext(Sym*, int32); -vlong argsize(void); +vlong argsize(int); /* * cgen.c @@ -240,7 +239,7 @@ Node* nodfconst(double); Node* nodgconst(vlong, Type*); int nodreg(Node*, Node*, int); int isreg(Node*, int); -void regret(Node*, Node*); +void regret(Node*, Node*, Type*, int); void regalloc(Node*, Node*, Node*); void regfree(Node*); void regialloc(Node*, Node*, Node*); diff --git a/src/cmd/6c/reg.c b/src/cmd/6c/reg.c index 348d747b7..6f8d3ce14 100644 --- a/src/cmd/6c/reg.c +++ b/src/cmd/6c/reg.c @@ -585,14 +585,11 @@ loop2: } rgp->cost = change; nregion++; - if(nregion >= NRGN) { - warn(Z, "too many regions"); - goto brk; - } + if(nregion >= NRGN) + fatal(Z, "too many regions"); rgp++; } } -brk: qsort(region, nregion, sizeof(region[0]), rcmp); /* @@ -808,11 +805,8 @@ mkvar(Reg *r, Addr *a) goto out; v++; } - if(nvar >= NVAR) { - if(debug['w'] > 1 && s) - warn(Z, "variable not optimized: %s", s->name); - goto none; - } + if(nvar >= NVAR) + fatal(Z, "variable not optimized: %s", s->name); i = nvar; nvar++; v = &var[i]; diff --git a/src/cmd/6c/sgen.c b/src/cmd/6c/sgen.c index ba1c1f652..fceb332b2 100644 --- a/src/cmd/6c/sgen.c +++ b/src/cmd/6c/sgen.c @@ -29,14 +29,14 @@ // THE SOFTWARE. #include "gc.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" Prog* gtext(Sym *s, int32 stkoff) { vlong v; - v = ((uvlong)argsize() << 32) | (stkoff & 0xffffffff); + v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff); if((textflag & NOSPLIT) && stkoff >= 128) yyerror("stack frame too large for NOSPLIT function"); @@ -124,10 +124,7 @@ xcom(Node *n) break; case ONAME: - if(flag_largemodel) - n->addable = 9; - else - n->addable = 10; + n->addable = 9; if(n->class == CPARAM || n->class == CAUTO) n->addable = 11; break; diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c index d7713648d..6e918eb10 100644 --- a/src/cmd/6c/swt.c +++ b/src/cmd/6c/swt.c @@ -250,10 +250,11 @@ align(int32 i, Type *t, int op, int32 *maxalign) { int32 o; Type *v; - int w; + int w, packw; o = i; w = 1; + packw = 0; switch(op) { default: diag(Z, "unknown align opcode %d", op); @@ -264,7 +265,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1) w = 1; if(packflg) - w = packflg; + packw = packflg; break; case Ael1: /* initial align of struct element */ @@ -277,7 +278,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1 || w > SZ_VLONG) fatal(Z, "align"); if(packflg) - w = packflg; + packw = packflg; break; case Ael2: /* width of a struct element */ @@ -331,6 +332,8 @@ align(int32 i, Type *t, int op, int32 *maxalign) o = align(o, t, Ael2, nil); break; } + if(packw != 0 && xround(o, w) != xround(o, packw)) + diag(Z, "#pragma pack changes offset of %T", t); o = xround(o, w); if(maxalign && *maxalign < w) *maxalign = w; diff --git a/src/cmd/6c/txt.c b/src/cmd/6c/txt.c index 4d07436c3..3bdbf410e 100644 --- a/src/cmd/6c/txt.c +++ b/src/cmd/6c/txt.c @@ -351,15 +351,43 @@ nodreg(Node *n, Node *nn, int r) } void -regret(Node *n, Node *nn) +regret(Node *n, Node *nn, Type *t, int mode) { int r; + + if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) { + r = REGRET; + if(typefd[nn->type->etype]) + r = FREGRET; + nodreg(n, nn, r); + reg[r]++; + return; + } + + if(mode == 1) { + // fetch returned value after call. + // already called gargs, so curarg is set. + curarg = (curarg+7) & ~7; + regaalloc(n, nn); + return; + } - r = REGRET; - if(typefd[nn->type->etype]) - r = FREGRET; - nodreg(n, nn, r); - reg[r]++; + if(mode == 2) { + // store value to be returned. + // must compute arg offset. + if(t->etype != TFUNC) + fatal(Z, "bad regret func %T", t); + *n = *nn; + n->op = ONAME; + n->class = CPARAM; + n->sym = slookup(".ret"); + n->complex = nodret->complex; + n->addable = 20; + n->xoffset = argsize(0); + return; + } + + fatal(Z, "bad regret"); } void diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index 4dd505b08..d13c98dad 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -247,7 +247,6 @@ cgen(Node *n, Node *res) case OOR: case OXOR: case OADD: - case OADDPTR: case OMUL: a = optoas(n->op, nl->type); if(a == AIMULB) { @@ -752,12 +751,7 @@ agenr(Node *n, Node *a, Node *res) regalloc(&n3, types[tptr], res); p1 = gins(ALEAQ, N, &n3); datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from); - if(flag_largemodel) { - gins(AADDQ, &n2, &n3); - } else { - p1->from.scale = 1; - p1->from.index = n2.val.u.reg; - } + gins(AADDQ, &n2, &n3); goto indexdone; } @@ -1457,7 +1451,7 @@ sgen(Node *n, Node *ns, int64 w) p = gins(ADUFFCOPY, N, N); p->to.type = D_ADDR; p->to.sym = linksym(pkglookup("duffcopy", runtimepkg)); - // 14 and 128 = magic constants: see ../../pkg/runtime/asm_amd64.s + // 14 and 128 = magic constants: see ../../runtime/asm_amd64.s p->to.offset = 14*(128-q); } else while(q > 0) { diff --git a/src/cmd/6g/galign.c b/src/cmd/6g/galign.c index 1d32c5a61..5670e6fac 100644 --- a/src/cmd/6g/galign.c +++ b/src/cmd/6g/galign.c @@ -30,10 +30,10 @@ int cmpptr = ACMPQ; */ Typedef typedefs[] = { - "int", TINT, TINT64, - "uint", TUINT, TUINT64, - "uintptr", TUINTPTR, TUINT64, - 0 + {"int", TINT, TINT64}, + {"uint", TUINT, TUINT64}, + {"uintptr", TUINTPTR, TUINT64}, + {0} }; void diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index a5da17d61..fe69d5c96 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -51,7 +51,6 @@ void allocparams(void); void checklabels(void); void ginscall(Node*, int); int gen_as_init(Node*); -void clearslim(Node*); /* * cgen.c @@ -100,7 +99,6 @@ int sudoaddable(int, Node*, Addr*); void afunclit(Addr*, Node*); void nodfconst(Node*, Type*, Mpflt*); void gtrack(Sym*); -void gargsize(vlong); void fixlargeoffset(Node *n); /* diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index 9665d831b..363620769 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -175,7 +175,6 @@ fixautoused(Prog *p) void ginscall(Node *f, int proc) { - int32 arg; Prog *p; Node reg, con; Node r1; @@ -183,21 +182,6 @@ ginscall(Node *f, int proc) if(f->type != T) setmaxarg(f->type); - arg = -1; - // Most functions have a fixed-size argument block, so traceback uses that during unwind. - // Not all, though: there are some variadic functions in package runtime, - // and for those we emit call-specific metadata recorded by caller. - // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub), - // so we do this for all indirect calls as well. - if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) { - arg = f->type->argwid; - if(proc == 1 || proc == 2) - arg += 2*widthptr; - } - - if(arg != -1) - gargsize(arg); - switch(proc) { default: fatal("ginscall: bad proc %d", proc); @@ -275,9 +259,6 @@ ginscall(Node *f, int proc) } break; } - - if(arg != -1) - gargsize(-1); } /* @@ -1121,26 +1102,54 @@ clearfat(Node *nl) c = w % 8; // bytes q = w / 8; // quads + if(q < 4) { + // Write sequence of MOV 0, off(base) instead of using STOSQ. + // The hope is that although the code will be slightly longer, + // the MOVs will have no dependencies and pipeline better + // than the unrolled STOSQ loop. + // NOTE: Must use agen, not igen, so that optimizer sees address + // being taken. We are not writing on field boundaries. + agenr(nl, &n1, N); + n1.op = OINDREG; + nodconst(&z, types[TUINT64], 0); + while(q-- > 0) { + n1.type = z.type; + gins(AMOVQ, &z, &n1); + n1.xoffset += 8; + } + if(c >= 4) { + nodconst(&z, types[TUINT32], 0); + n1.type = z.type; + gins(AMOVL, &z, &n1); + n1.xoffset += 4; + c -= 4; + } + nodconst(&z, types[TUINT8], 0); + while(c-- > 0) { + n1.type = z.type; + gins(AMOVB, &z, &n1); + n1.xoffset++; + } + regfree(&n1); + return; + } + savex(D_DI, &n1, &oldn1, N, types[tptr]); agen(nl, &n1); savex(D_AX, &ax, &oldax, N, types[tptr]); gconreg(AMOVL, 0, D_AX); - if(q > 128 || (q >= 4 && nacl)) { + if(q > 128 || nacl) { gconreg(movptr, q, D_CX); gins(AREP, N, N); // repeat gins(ASTOSQ, N, N); // STOQ AL,*(DI)+ - } else if(q >= 4) { + } else { p = gins(ADUFFZERO, N, N); p->to.type = D_ADDR; p->to.sym = linksym(pkglookup("duffzero", runtimepkg)); - // 2 and 128 = magic constants: see ../../pkg/runtime/asm_amd64.s + // 2 and 128 = magic constants: see ../../runtime/asm_amd64.s p->to.offset = 2*(128-q); - } else - while(q > 0) { - gins(ASTOSQ, N, N); // STOQ AL,*(DI)+ - q--; } z = ax; diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index e4d00bf41..5bd924660 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -31,11 +31,11 @@ #include #include #include "gg.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" // TODO(rsc): Can make this bigger if we move // the text segment up higher in 6l for all GOOS. -// At the same time, can raise StackBig in ../../pkg/runtime/stack.h. +// At the same time, can raise StackBig in ../../runtime/stack.h. vlong unmappedzero = 4096; void @@ -215,17 +215,7 @@ gtrack(Sym *s) } void -gargsize(vlong size) -{ - Node n1, n2; - - nodconst(&n1, types[TINT32], PCDATA_ArgSize); - nodconst(&n2, types[TINT32], size); - gins(APCDATA, &n1, &n2); -} - -void -ggloblsym(Sym *s, int32 width, int dupok, int rodata) +ggloblsym(Sym *s, int32 width, int8 flags) { Prog *p; @@ -236,10 +226,7 @@ ggloblsym(Sym *s, int32 width, int dupok, int rodata) p->to.type = D_CONST; p->to.index = D_NONE; p->to.offset = width; - if(dupok) - p->from.scale |= DUPOK; - if(rodata) - p->from.scale |= RODATA; + p->from.scale = flags; } int @@ -584,6 +571,7 @@ ginscon(int as, vlong c, Node *n2) } #define CASE(a,b) (((a)<<16)|((b)<<0)) +/*c2go int CASE(int, int); */ /* * Is this node a memory operand? @@ -600,11 +588,8 @@ ismem(Node *n) case ONAME: case OPARAM: case OCLOSUREVAR: - return 1; case OADDR: - if(flag_largemodel) - return 1; - break; + return 1; } return 0; } @@ -1542,14 +1527,12 @@ optoas(int op, Type *t) case CASE(OADD, TINT32): case CASE(OADD, TUINT32): case CASE(OADD, TPTR32): - case CASE(OADDPTR, TPTR32): a = AADDL; break; case CASE(OADD, TINT64): case CASE(OADD, TUINT64): case CASE(OADD, TPTR64): - case CASE(OADDPTR, TPTR64): a = AADDQ; break; diff --git a/src/cmd/6g/opt.h b/src/cmd/6g/opt.h index bf356af0c..dbd039d89 100644 --- a/src/cmd/6g/opt.h +++ b/src/cmd/6g/opt.h @@ -49,6 +49,24 @@ typedef struct Reg Reg; typedef struct Rgn Rgn; +/*c2go +extern Node *Z; +enum +{ + D_HI = D_NONE, + D_LO = D_NONE, + CLOAD = 5, + CREF = 5, + CINF = 1000, + LOOP = 3, +}; + +uint32 BLOAD(Reg*); +uint32 BSTORE(Reg*); +uint32 LOAD(Reg*); +uint32 STORE(Reg*); +*/ + // A Reg is a wrapper around a single Prog (one instruction) that holds // register optimization information while the optimizer runs. // r->prog is the instruction. @@ -71,8 +89,10 @@ struct Reg int32 regu; // register used bitmap }; #define R ((Reg*)0) +/*c2go extern Reg *R; */ #define NRGN 600 +/*c2go enum { NRGN = 600 }; */ struct Rgn { Reg* enter; diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index f3b1e55de..1f757e197 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -35,6 +35,11 @@ #define NREGVAR 32 /* 16 general + 16 floating */ #define REGBITS ((uint32)0xffffffff) +/*c2go enum { + NREGVAR = 32, + REGBITS = 0xffffffff, +}; +*/ static Reg* firstr; static int first = 1; @@ -839,7 +844,7 @@ prop(Reg *r, Bits ref, Bits cal) if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) { for(; v1 != nil; v1 = v1->nextinnode) { j = v1 - var; - cal.b[j/32] |= 1<<(j&31); + cal.b[j/32] |= 1UL<<(j&31); } } } @@ -1186,6 +1191,7 @@ void addreg(Adr *a, int rn) { a->sym = nil; + a->node = nil; a->offset = 0; a->type = rn; diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h index 1e2a1488f..af72784e8 100644 --- a/src/cmd/6l/6.out.h +++ b/src/cmd/6l/6.out.h @@ -36,7 +36,7 @@ * amd64 */ -enum as +enum { AXXX, AAAA, diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index 7828e2892..18b5aa311 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -290,7 +290,6 @@ elfreloc1(Reloc *r, vlong sectoff) break; case R_CALL: - case R_PCREL: if(r->siz == 4) { if(r->xsym->type == SDYNIMPORT) VPUT(R_X86_64_GOTPCREL | (uint64)elfsym<<32); @@ -299,7 +298,14 @@ elfreloc1(Reloc *r, vlong sectoff) } else return -1; break; - + + case R_PCREL: + if(r->siz == 4) { + VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); + } else + return -1; + break; + case R_TLS: if(r->siz == 4) { if(flag_shared) @@ -323,7 +329,7 @@ machoreloc1(Reloc *r, vlong sectoff) rs = r->xsym; - if(rs->type == SHOSTOBJ) { + if(rs->type == SHOSTOBJ || r->type == R_PCREL) { if(rs->dynid < 0) { diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type); return -1; @@ -345,10 +351,13 @@ machoreloc1(Reloc *r, vlong sectoff) v |= MACHO_X86_64_RELOC_UNSIGNED<<28; break; case R_CALL: - case R_PCREL: v |= 1<<24; // pc-relative bit v |= MACHO_X86_64_RELOC_BRANCH<<28; break; + case R_PCREL: + // NOTE: Only works with 'external' relocation. Forced above. + v |= 1<<24; // pc-relative bit + v |= MACHO_X86_64_RELOC_SIGNED<<28; } switch(r->siz) { diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index 7303910a6..ff2e69452 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -68,14 +68,9 @@ EXTERN int RegSize; #define P ((Prog*)0) #define S ((LSym*)0) -#define TNAME (ctxt->cursym?ctxt->cursym->name:noname) enum { - MINSIZ = 8, - STRINGSZ = 200, MINLC = 1, - MAXIO = 8192, - MAXHIST = 40, /* limit of path elements for history symbols */ }; #pragma varargck type "I" uchar* @@ -89,9 +84,6 @@ EXTERN int32 spsize; EXTERN LSym* symlist; EXTERN int32 symsize; -EXTERN vlong textstksiz; -EXTERN vlong textarg; - int Iconv(Fmt *fp); void adddynlib(char *lib); void adddynrel(LSym *s, Reloc *r); @@ -103,8 +95,6 @@ int elfreloc1(Reloc *r, vlong sectoff); void elfsetupplt(void); void listinit(void); int machoreloc1(Reloc *r, vlong sectoff); -void main(int argc, char *argv[]); -void parsetextconst(vlong arg); vlong rnd(vlong v, vlong r); /* Native is little-endian */ diff --git a/src/cmd/6l/mkenam b/src/cmd/6l/mkenam deleted file mode 100644 index 3001dbe93..000000000 --- a/src/cmd/6l/mkenam +++ /dev/null @@ -1,45 +0,0 @@ -# Inferno utils/6c/mkenam -# http://code.google.com/p/inferno-os/source/browse/utils/6c/mkenam -# -# Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -# Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -# Portions Copyright © 1997-1999 Vita Nuova Limited -# Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -# Portions Copyright © 2004,2006 Bruce Ellis -# Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -# Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -# Portions Copyright © 2009 The Go Authors. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -awk ' -BEGIN { - print "char* anames[] =" - print "{" -} - -/^ A/ { - name=$1 - sub(/,/, "", name) - sub(/^A/, "", name) - print "\t\"" name "\"," -} - -END { print "};" } -' ../6l/6.out.h >enam.c diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y index d7ff623da..6bcf1313b 100644 --- a/src/cmd/8a/a.y +++ b/src/cmd/8a/a.y @@ -33,7 +33,7 @@ #include /* if we don't, bison will, and a.h re-#defines getc */ #include #include "a.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" %} %union { Sym *sym; diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c index 32c099b75..6ce6a18ab 100644 --- a/src/cmd/8a/lex.c +++ b/src/cmd/8a/lex.c @@ -90,6 +90,7 @@ main(int argc, char *argv[]) ctxt = linknew(&link386); ctxt->diag = yyerror; ctxt->bso = &bstdout; + ctxt->enforce_data_order = 1; Binit(&bstdout, 1, OWRITE); listinit8(); fmtinstall('L', Lconv); @@ -352,49 +353,49 @@ struct "IRETL", LTYPE0, AIRETL, "IRETW", LTYPE0, AIRETW, - "JOS", LTYPER, AJOS, + "JOS", LTYPER, AJOS, /* overflow set (OF = 1) */ "JO", LTYPER, AJOS, /* alternate */ - "JOC", LTYPER, AJOC, + "JOC", LTYPER, AJOC, /* overflow clear (OF = 0) */ "JNO", LTYPER, AJOC, /* alternate */ - "JCS", LTYPER, AJCS, + "JCS", LTYPER, AJCS, /* carry set (CF = 1) */ "JB", LTYPER, AJCS, /* alternate */ "JC", LTYPER, AJCS, /* alternate */ "JNAE", LTYPER, AJCS, /* alternate */ "JLO", LTYPER, AJCS, /* alternate */ - "JCC", LTYPER, AJCC, + "JCC", LTYPER, AJCC, /* carry clear (CF = 0) */ "JAE", LTYPER, AJCC, /* alternate */ "JNB", LTYPER, AJCC, /* alternate */ "JNC", LTYPER, AJCC, /* alternate */ "JHS", LTYPER, AJCC, /* alternate */ - "JEQ", LTYPER, AJEQ, + "JEQ", LTYPER, AJEQ, /* equal (ZF = 1) */ "JE", LTYPER, AJEQ, /* alternate */ "JZ", LTYPER, AJEQ, /* alternate */ - "JNE", LTYPER, AJNE, + "JNE", LTYPER, AJNE, /* not equal (ZF = 0) */ "JNZ", LTYPER, AJNE, /* alternate */ - "JLS", LTYPER, AJLS, + "JLS", LTYPER, AJLS, /* lower or same (unsigned) (CF = 1 || ZF = 1) */ "JBE", LTYPER, AJLS, /* alternate */ "JNA", LTYPER, AJLS, /* alternate */ - "JHI", LTYPER, AJHI, + "JHI", LTYPER, AJHI, /* higher (unsigned) (CF = 0 && ZF = 0) */ "JA", LTYPER, AJHI, /* alternate */ "JNBE", LTYPER, AJHI, /* alternate */ - "JMI", LTYPER, AJMI, + "JMI", LTYPER, AJMI, /* negative (minus) (SF = 1) */ "JS", LTYPER, AJMI, /* alternate */ - "JPL", LTYPER, AJPL, + "JPL", LTYPER, AJPL, /* non-negative (plus) (SF = 0) */ "JNS", LTYPER, AJPL, /* alternate */ - "JPS", LTYPER, AJPS, + "JPS", LTYPER, AJPS, /* parity set (PF = 1) */ "JP", LTYPER, AJPS, /* alternate */ "JPE", LTYPER, AJPS, /* alternate */ - "JPC", LTYPER, AJPC, + "JPC", LTYPER, AJPC, /* parity clear (PF = 0) */ "JNP", LTYPER, AJPC, /* alternate */ "JPO", LTYPER, AJPC, /* alternate */ - "JLT", LTYPER, AJLT, + "JLT", LTYPER, AJLT, /* less than (signed) (SF != OF) */ "JL", LTYPER, AJLT, /* alternate */ "JNGE", LTYPER, AJLT, /* alternate */ - "JGE", LTYPER, AJGE, + "JGE", LTYPER, AJGE, /* greater than or equal (signed) (SF = OF) */ "JNL", LTYPER, AJGE, /* alternate */ - "JLE", LTYPER, AJLE, + "JLE", LTYPER, AJLE, /* less than or equal (signed) (ZF = 1 || SF != OF) */ "JNG", LTYPER, AJLE, /* alternate */ - "JGT", LTYPER, AJGT, + "JGT", LTYPER, AJGT, /* greater than (signed) (ZF = 0 && SF = OF) */ "JG", LTYPER, AJGT, /* alternate */ "JNLE", LTYPER, AJGT, /* alternate */ @@ -493,7 +494,7 @@ struct "SCASB", LTYPE0, ASCASB, "SCASL", LTYPE0, ASCASL, "SCASW", LTYPE0, ASCASW, - "SETCC", LTYPE1, ASETCC, + "SETCC", LTYPE1, ASETCC, /* see JCC etc above for condition codes */ "SETCS", LTYPE1, ASETCS, "SETEQ", LTYPE1, ASETEQ, "SETGE", LTYPE1, ASETGE, diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c index f48c9fe1f..85279c21f 100644 --- a/src/cmd/8a/y.tab.c +++ b/src/cmd/8a/y.tab.c @@ -146,7 +146,7 @@ #include /* if we don't, bison will, and a.h re-#defines getc */ #include #include "a.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" /* Enabling traces. */ diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c index f54102245..87e8fdad8 100644 --- a/src/cmd/8c/cgen.c +++ b/src/cmd/8c/cgen.c @@ -29,7 +29,7 @@ // THE SOFTWARE. #include "gc.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" /* ,x/^(print|prtree)\(/i/\/\/ */ @@ -49,7 +49,7 @@ cgen(Node *n, Node *nn) } if(n == Z || n->type == T) return; - if(typesuv[n->type->etype]) { + if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) { sugen(n, nn, n->type->width); return; } @@ -86,7 +86,7 @@ cgen(Node *n, Node *nn) if(cond(o) && typesuv[l->type->etype]) break; - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); @@ -147,7 +147,7 @@ cgen(Node *n, Node *nn) if(!hardleft) { if(nn != Z || r->addable < INDEXED) { if(r->complex >= FNX && nn == Z) - regret(&nod, r); + regret(&nod, r, 0, 0); else regalloc(&nod, r, nn); cgen(r, &nod); @@ -922,7 +922,7 @@ cgen(Node *n, Node *nn) if(l->op != OIND) diag(n, "bad function call"); - regret(&nod, l->left); + regret(&nod, l->left, 0, 0); cgen(l->left, &nod); regsalloc(&nod1, l->left); gmove(&nod, &nod1); @@ -938,7 +938,6 @@ cgen(Node *n, Node *nn) return; } gargs(r, &nod, &nod1); - gpcdata(PCDATA_ArgSize, curarg); if(l->addable < INDEXED) { reglcgen(&nod, l, nn); nod.op = OREGISTER; @@ -946,15 +945,14 @@ cgen(Node *n, Node *nn) regfree(&nod); } else gopcode(OFUNC, n->type, Z, l); - gpcdata(PCDATA_ArgSize, -1); if(REGARG >= 0 && reg[REGARG]) reg[REGARG]--; - if(nn != Z) { - regret(&nod, n); + regret(&nod, n, l->type, 1); // update maxarg if nothing else + if(nn != Z) gmove(&nod, nn); + if(nod.op == OREGISTER) regfree(&nod); - } else - if(typefd[n->type->etype]) + if(nn == Z && hasdotdotdot(l->type) && typefd[n->type->etype]) gins(AFMOVDP, &fregnode0, &fregnode0); break; @@ -1374,7 +1372,7 @@ boolgen(Node *n, int true, Node *nn) if(true) o = comrel[relindex(o)]; if(l->complex >= FNX && r->complex >= FNX) { - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); gmove(&nod, &nod1); @@ -1567,7 +1565,7 @@ sugen(Node *n, Node *nn, int32 w) if(nn != Z && side(nn)) { nod1 = *n; nod1.type = typ(TIND, n->type); - regret(&nod2, &nod1); + regret(&nod2, &nod1, 0, 0); lcgen(nn, &nod2); regsalloc(&nod0, &nod1); cgen(&nod2, &nod0); @@ -1649,6 +1647,20 @@ sugen(Node *n, Node *nn, int32 w) break; case OFUNC: + if(!hasdotdotdot(n->left->type)) { + cgen(n, Z); + if(nn != Z) { + curarg -= n->type->width; + regret(&nod1, n, n->left->type, 1); + if(nn->complex >= FNX) { + regsalloc(&nod2, n); + cgen(&nod1, &nod2); + nod1 = nod2; + } + cgen(&nod1, nn); + } + break; + } if(nn == Z) { sugen(n, nodrat, w); break; diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h index 87b8e22bc..aa3888d73 100644 --- a/src/cmd/8c/gc.h +++ b/src/cmd/8c/gc.h @@ -143,7 +143,6 @@ EXTERN int32 cursafe; EXTERN Prog* lastp; EXTERN int32 maxargsafe; EXTERN int mnstring; -EXTERN int retok; EXTERN Node* nodrat; EXTERN Node* nodret; EXTERN Node* nodsafe; @@ -211,7 +210,7 @@ void xcom(Node*); void indx(Node*); int bcomplex(Node*, Node*); Prog* gtext(Sym*, int32); -vlong argsize(void); +vlong argsize(int); /* * cgen.c @@ -245,7 +244,7 @@ Node* nodconst(int32); Node* nodfconst(double); int nodreg(Node*, Node*, int); int isreg(Node*, int); -void regret(Node*, Node*); +void regret(Node*, Node*, Type*, int); void regalloc(Node*, Node*, Node*); void regfree(Node*); void regialloc(Node*, Node*, Node*); diff --git a/src/cmd/8c/reg.c b/src/cmd/8c/reg.c index e6ba8bcb3..ea862f388 100644 --- a/src/cmd/8c/reg.c +++ b/src/cmd/8c/reg.c @@ -518,7 +518,7 @@ loop2: rgp->cost = change; nregion++; if(nregion >= NRGN) { - warn(Z, "too many regions"); + fatal(Z, "too many regions"); goto brk; } rgp++; @@ -746,11 +746,8 @@ mkvar(Reg *r, Addr *a) goto out; v++; } - if(nvar >= NVAR) { - if(debug['w'] > 1 && s) - warn(Z, "variable not optimized: %s", s->name); - goto none; - } + if(nvar >= NVAR) + fatal(Z, "variable not optimized: %s", s->name); i = nvar; nvar++; v = &var[i]; diff --git a/src/cmd/8c/sgen.c b/src/cmd/8c/sgen.c index 069bbc1fc..d647010ef 100644 --- a/src/cmd/8c/sgen.c +++ b/src/cmd/8c/sgen.c @@ -35,7 +35,7 @@ gtext(Sym *s, int32 stkoff) { int32 a; - a = argsize(); + a = argsize(1); if((textflag & NOSPLIT) != 0 && stkoff >= 128) yyerror("stack frame too large for NOSPLIT function"); diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c index ae36f84ea..d960519e3 100644 --- a/src/cmd/8c/swt.c +++ b/src/cmd/8c/swt.c @@ -255,10 +255,11 @@ align(int32 i, Type *t, int op, int32 *maxalign) { int32 o; Type *v; - int w; + int w, packw; o = i; w = 1; + packw = 0; switch(op) { default: diag(Z, "unknown align opcode %d", op); @@ -269,7 +270,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1) w = 1; if(packflg) - w = packflg; + packw = packflg; break; case Ael1: /* initial align of struct element */ @@ -285,7 +286,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1 || w > SZ_LONG) fatal(Z, "align"); if(packflg) - w = packflg; + packw = packflg; break; case Ael2: /* width of a struct element */ @@ -320,6 +321,8 @@ align(int32 i, Type *t, int op, int32 *maxalign) o = align(o, t, Ael2, nil); break; } + if(packw != 0 && xround(o, w) != xround(o, packw)) + diag(Z, "#pragma pack changes offset of %T", t); o = xround(o, w); if(maxalign && *maxalign < w) *maxalign = w; diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c index 25082de05..7f87a0a0d 100644 --- a/src/cmd/8c/txt.c +++ b/src/cmd/8c/txt.c @@ -311,15 +311,43 @@ nodreg(Node *n, Node *nn, int r) } void -regret(Node *n, Node *nn) +regret(Node *n, Node *nn, Type *t, int mode) { int r; - r = REGRET; - if(typefd[nn->type->etype]) - r = FREGRET; - nodreg(n, nn, r); - reg[r]++; + if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) { + r = REGRET; + if(typefd[nn->type->etype]) + r = FREGRET; + nodreg(n, nn, r); + reg[r]++; + return; + } + + if(mode == 1) { + // fetch returned value after call. + // already called gargs, so curarg is set. + curarg = (curarg+3) & ~3; + regaalloc(n, nn); + return; + } + + if(mode == 2) { + // store value to be returned. + // must compute arg offset. + if(t->etype != TFUNC) + fatal(Z, "bad regret func %T", t); + *n = *nn; + n->op = ONAME; + n->class = CPARAM; + n->sym = slookup(".retx"); + n->complex = 0; + n->addable = 20; + n->xoffset = argsize(0); + return; + } + + fatal(Z, "bad regret"); } void diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index d626c2eb0..2735fb6a5 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -242,7 +242,6 @@ cgen(Node *n, Node *res) case OOR: case OXOR: case OADD: - case OADDPTR: case OMUL: a = optoas(n->op, nl->type); if(a == AIMULB) { @@ -347,8 +346,11 @@ cgen(Node *n, Node *res) if(istype(nl->type, TCHAN)) { // chan has cap in the second 32-bit word. // a zero pointer means zero length - regalloc(&n1, types[tptr], res); + tempname(&n1, types[tptr]); cgen(nl, &n1); + regalloc(&n2, types[tptr], N); + gmove(&n1, &n2); + n1 = n2; nodconst(&n2, types[tptr], 0); gins(optoas(OCMP, types[tptr]), &n1, &n2); @@ -1324,7 +1326,7 @@ sgen(Node *n, Node *res, int64 w) p = gins(ADUFFCOPY, N, N); p->to.type = D_ADDR; p->to.sym = linksym(pkglookup("duffcopy", runtimepkg)); - // 10 and 128 = magic constants: see ../../pkg/runtime/asm_386.s + // 10 and 128 = magic constants: see ../../runtime/asm_386.s p->to.offset = 10*(128-q); } else while(q > 0) { @@ -1364,7 +1366,10 @@ int componentgen(Node *nr, Node *nl) { Node nodl, nodr; + Type *t; int freel, freer; + vlong fldcount; + vlong loffset, roffset; freel = 0; freer = 0; @@ -1374,8 +1379,33 @@ componentgen(Node *nr, Node *nl) goto no; case TARRAY: - if(!isslice(nl->type)) + t = nl->type; + + // Slices are ok. + if(isslice(t)) + break; + // Small arrays are ok. + if(t->bound > 0 && t->bound <= 3 && !isfat(t->type)) + break; + + goto no; + + case TSTRUCT: + // Small structs with non-fat types are ok. + // Zero-sized structs are treated separately elsewhere. + fldcount = 0; + for(t=nl->type->type; t; t=t->down) { + if(isfat(t->type)) + goto no; + if(t->etype != TFIELD) + fatal("componentgen: not a TFIELD: %lT", t); + fldcount++; + } + if(fldcount == 0 || fldcount > 4) goto no; + + break; + case TSTRING: case TINTER: break; @@ -1396,7 +1426,7 @@ componentgen(Node *nr, Node *nl) freer = 1; } } - + // nl and nr are 'cadable' which basically means they are names (variables) now. // If they are the same variable, don't generate any code, because the // VARDEF we generate will mark the old value as dead incorrectly. @@ -1406,8 +1436,25 @@ componentgen(Node *nr, Node *nl) switch(nl->type->etype) { case TARRAY: + // componentgen for arrays. if(nl->op == ONAME) gvardef(nl); + t = nl->type; + if(!isslice(t)) { + nodl.type = t->type; + nodr.type = nodl.type; + for(fldcount=0; fldcount < t->bound; fldcount++) { + if(nr == N) + clearslim(&nodl); + else + gmove(&nodr, &nodl); + nodl.xoffset += t->type->width; + nodr.xoffset += t->type->width; + } + goto yes; + } + + // componentgen for slices. nodl.xoffset += Array_array; nodl.type = ptrto(nl->type->type); @@ -1419,7 +1466,7 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); nodl.xoffset += Array_nel-Array_array; - nodl.type = types[TUINT32]; + nodl.type = types[simtype[TUINT]]; if(nr != N) { nodr.xoffset += Array_nel-Array_array; @@ -1429,7 +1476,7 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); nodl.xoffset += Array_cap-Array_nel; - nodl.type = types[TUINT32]; + nodl.type = types[simtype[TUINT]]; if(nr != N) { nodr.xoffset += Array_cap-Array_nel; @@ -1454,7 +1501,7 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); nodl.xoffset += Array_nel-Array_array; - nodl.type = types[TUINT32]; + nodl.type = types[simtype[TUINT]]; if(nr != N) { nodr.xoffset += Array_nel-Array_array; @@ -1489,6 +1536,31 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); goto yes; + + case TSTRUCT: + if(nl->op == ONAME) + gvardef(nl); + loffset = nodl.xoffset; + roffset = nodr.xoffset; + // funarg structs may not begin at offset zero. + if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type) + loffset -= nl->type->type->width; + if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type) + roffset -= nr->type->type->width; + + for(t=nl->type->type; t; t=t->down) { + nodl.xoffset = loffset + t->width; + nodl.type = t->type; + + if(nr == N) + clearslim(&nodl); + else { + nodr.xoffset = roffset + t->width; + nodr.type = nodl.type; + gmove(&nodr, &nodl); + } + } + goto yes; } no: diff --git a/src/cmd/8g/galign.c b/src/cmd/8g/galign.c index fbd2e9ad3..a0eb34937 100644 --- a/src/cmd/8g/galign.c +++ b/src/cmd/8g/galign.c @@ -23,10 +23,10 @@ vlong MAXWIDTH = (1LL<<32) - 1; */ Typedef typedefs[] = { - "int", TINT, TINT32, - "uint", TUINT, TUINT32, - "uintptr", TUINTPTR, TUINT32, - 0 + {"int", TINT, TINT32}, + {"uint", TUINT, TUINT32}, + {"uintptr", TUINTPTR, TUINT32}, + {0} }; void diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h index bdefa93b5..238f92765 100644 --- a/src/cmd/8g/gg.h +++ b/src/cmd/8g/gg.h @@ -114,7 +114,6 @@ void split64(Node*, Node*, Node*); void splitclean(void); void nswap(Node*, Node*); void gtrack(Sym*); -void gargsize(int32); /* * cplx.c */ diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 5e3140480..6333a60bb 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -157,7 +157,7 @@ void clearfat(Node *nl) { uint32 w, c, q; - Node n1; + Node n1, z; Prog *p; /* clear a fat object */ @@ -172,6 +172,32 @@ clearfat(Node *nl) c = w % 4; // bytes q = w / 4; // quads + if(q < 4) { + // Write sequence of MOV 0, off(base) instead of using STOSL. + // The hope is that although the code will be slightly longer, + // the MOVs will have no dependencies and pipeline better + // than the unrolled STOSL loop. + // NOTE: Must use agen, not igen, so that optimizer sees address + // being taken. We are not writing on field boundaries. + regalloc(&n1, types[tptr], N); + agen(nl, &n1); + n1.op = OINDREG; + nodconst(&z, types[TUINT64], 0); + while(q-- > 0) { + n1.type = z.type; + gins(AMOVL, &z, &n1); + n1.xoffset += 4; + } + nodconst(&z, types[TUINT8], 0); + while(c-- > 0) { + n1.type = z.type; + gins(AMOVB, &z, &n1); + n1.xoffset++; + } + regfree(&n1); + return; + } + nodreg(&n1, types[tptr], D_DI); agen(nl, &n1); gconreg(AMOVL, 0, D_AX); @@ -184,7 +210,7 @@ clearfat(Node *nl) p = gins(ADUFFZERO, N, N); p->to.type = D_ADDR; p->to.sym = linksym(pkglookup("duffzero", runtimepkg)); - // 1 and 128 = magic constants: see ../../pkg/runtime/asm_386.s + // 1 and 128 = magic constants: see ../../runtime/asm_386.s p->to.offset = 1*(128-q); } else while(q > 0) { @@ -210,28 +236,12 @@ clearfat(Node *nl) void ginscall(Node *f, int proc) { - int32 arg; Prog *p; Node reg, r1, con; if(f->type != T) setmaxarg(f->type); - arg = -1; - // Most functions have a fixed-size argument block, so traceback uses that during unwind. - // Not all, though: there are some variadic functions in package runtime, - // and for those we emit call-specific metadata recorded by caller. - // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub), - // so we do this for all indirect calls as well. - if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) { - arg = f->type->argwid; - if(proc == 1 || proc == 2) - arg += 2*widthptr; - } - - if(arg != -1) - gargsize(arg); - switch(proc) { default: fatal("ginscall: bad proc %d", proc); @@ -293,9 +303,6 @@ ginscall(Node *f, int proc) } break; } - - if(arg != -1) - gargsize(-1); } /* diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c index 2f3cb28c8..3077e0ad9 100644 --- a/src/cmd/8g/gsubr.c +++ b/src/cmd/8g/gsubr.c @@ -31,14 +31,15 @@ #include #include #include "gg.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" // TODO(rsc): Can make this bigger if we move // the text segment up higher in 8l for all GOOS. -// At the same time, can raise StackBig in ../../pkg/runtime/stack.h. +// At the same time, can raise StackBig in ../../runtime/stack.h. uint32 unmappedzero = 4096; #define CASE(a,b) (((a)<<16)|((b)<<0)) +/*c2go int CASE(int, int);*/ void clearp(Prog *p) @@ -205,17 +206,7 @@ ggloblnod(Node *nam) } void -gargsize(int32 size) -{ - Node n1, n2; - - nodconst(&n1, types[TINT32], PCDATA_ArgSize); - nodconst(&n2, types[TINT32], size); - gins(APCDATA, &n1, &n2); -} - -void -ggloblsym(Sym *s, int32 width, int dupok, int rodata) +ggloblsym(Sym *s, int32 width, int8 flags) { Prog *p; @@ -226,10 +217,7 @@ ggloblsym(Sym *s, int32 width, int dupok, int rodata) p->to.type = D_CONST; p->to.index = D_NONE; p->to.offset = width; - if(dupok) - p->from.scale |= DUPOK; - if(rodata) - p->from.scale |= RODATA; + p->from.scale = flags; } void @@ -432,7 +420,6 @@ optoas(int op, Type *t) case CASE(OADD, TINT32): case CASE(OADD, TUINT32): case CASE(OADD, TPTR32): - case CASE(OADDPTR, TPTR32): a = AADDL; break; @@ -697,6 +684,7 @@ optoas(int op, Type *t) } #define FCASE(a, b, c) (((a)<<16)|((b)<<8)|(c)) +/*c2go int FCASE(int, int, int); */ int foptoas(int op, Type *t, int flg) { @@ -950,7 +938,7 @@ regalloc(Node *n, Type *t, Node *o) fprint(2, "registers allocated at\n"); for(i=D_AX; i<=D_DI; i++) fprint(2, "\t%R\t%#lux\n", i, regpc[i]); - yyerror("out of fixed registers"); + fatal("out of fixed registers"); goto err; case TFLOAT32: diff --git a/src/cmd/8g/opt.h b/src/cmd/8g/opt.h index 77a69e13a..09f58c40a 100644 --- a/src/cmd/8g/opt.h +++ b/src/cmd/8g/opt.h @@ -49,6 +49,24 @@ typedef struct Reg Reg; typedef struct Rgn Rgn; +/*c2go +extern Node *Z; +enum +{ + D_HI = D_NONE, + D_LO = D_NONE, + CLOAD = 5, + CREF = 5, + CINF = 1000, + LOOP = 3, +}; + +uint32 BLOAD(Reg*); +uint32 BSTORE(Reg*); +uint32 LOAD(Reg*); +uint32 STORE(Reg*); +*/ + // A Reg is a wrapper around a single Prog (one instruction) that holds // register optimization information while the optimizer runs. // r->prog is the instruction. @@ -84,8 +102,10 @@ struct Reg Prog* prog; // actual instruction }; #define R ((Reg*)0) +/*c2go extern Reg *R; */ #define NRGN 600 +/*c2go enum { NRGN = 600 }; */ struct Rgn { Reg* enter; diff --git a/src/cmd/8g/peep.c b/src/cmd/8g/peep.c index e2f3a003d..91a91d20d 100644 --- a/src/cmd/8g/peep.c +++ b/src/cmd/8g/peep.c @@ -33,7 +33,9 @@ #include "gg.h" #include "opt.h" -#define REGEXT 0 +enum { + REGEXT = 0, +}; static void conprop(Flow *r); static void elimshortmov(Graph*); diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index fd610f87a..302b273a1 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -35,6 +35,11 @@ #define NREGVAR 16 /* 8 integer + 8 floating */ #define REGBITS ((uint32)0xffff) +/*c2go enum { + NREGVAR = 16, + REGBITS = (1<sym = nil; + a->node = nil; a->offset = 0; a->type = rn; diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h index 8e642d390..ed54f6744 100644 --- a/src/cmd/8l/8.out.h +++ b/src/cmd/8l/8.out.h @@ -32,7 +32,7 @@ #define NSNAME 8 #include "../ld/textflag.h" -enum as +enum { AXXX, AAAA, diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index c135dce70..98c042403 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -117,13 +117,21 @@ adddynrel(LSym *s, Reloc *r) case 256 + R_386_GOT32: if(targ->type != SDYNIMPORT) { // have symbol - // turn MOVL of GOT entry into LEAL of symbol itself - if(r->off < 2 || s->p[r->off-2] != 0x8b) { - diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); + if(r->off >= 2 && s->p[r->off-2] == 0x8b) { + // turn MOVL of GOT entry into LEAL of symbol address, relative to GOT. + s->p[r->off-2] = 0x8d; + r->type = R_GOTOFF; return; } - s->p[r->off-2] = 0x8d; - r->type = R_GOTOFF; + if(r->off >= 2 && s->p[r->off-2] == 0xff && s->p[r->off-1] == 0xb3) { + // turn PUSHL of GOT entry into PUSHL of symbol itself. + // use unnecessary SS prefix to keep instruction same length. + s->p[r->off-2] = 0x36; + s->p[r->off-1] = 0x68; + r->type = R_ADDR; + return; + } + diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); return; } addgotsym(ctxt, targ); diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index c9695ade0..70d3a4bb4 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -50,15 +50,10 @@ enum #define P ((Prog*)0) #define S ((LSym*)0) -#define TNAME (ctxt->cursym?ctxt->cursym->name:noname) enum { - MINSIZ = 4, - STRINGSZ = 200, MINLC = 1, - MAXIO = 8192, - MAXHIST = 40, /* limit of path elements for history symbols */ }; #pragma varargck type "I" uchar* @@ -72,7 +67,6 @@ EXTERN char* rpath; EXTERN int32 spsize; EXTERN LSym* symlist; EXTERN int32 symsize; -EXTERN int32 textsize; int Iconv(Fmt *fp); void adddynlib(char *lib); @@ -85,7 +79,6 @@ int elfreloc1(Reloc *r, vlong sectoff); void elfsetupplt(void); void listinit(void); int machoreloc1(Reloc *r, vlong sectoff); -void main(int argc, char *argv[]); int32 rnd(int32 v, int32 r); void s8put(char *n); char* xsymname(LSym *s); diff --git a/src/cmd/8l/mkenam b/src/cmd/8l/mkenam deleted file mode 100644 index 992aa3160..000000000 --- a/src/cmd/8l/mkenam +++ /dev/null @@ -1,45 +0,0 @@ -# Inferno utils/8c/mkenam -# http://code.google.com/p/inferno-os/source/browse/utils/8c/mkenam -# -# Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -# Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -# Portions Copyright © 1997-1999 Vita Nuova Limited -# Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -# Portions Copyright © 2004,2006 Bruce Ellis -# Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -# Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -# Portions Copyright © 2009 The Go Authors. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -awk ' -BEGIN { - print "char* anames[] =" - print "{" -} - -/^ A/ { - name=$1 - sub(/,/, "", name) - sub(/^A/, "", name) - print "\t\"" name "\"," -} - -END { print "};" } -' ../8l/8.out.h >enam.c diff --git a/src/cmd/addr2line/addr2line_test.go b/src/cmd/addr2line/addr2line_test.go index b278d08ce..10d1dc922 100644 --- a/src/cmd/addr2line/addr2line_test.go +++ b/src/cmd/addr2line/addr2line_test.go @@ -92,8 +92,9 @@ func testAddr2Line(t *testing.T, exepath, addr string) { // This is line 93. The test depends on that. func TestAddr2Line(t *testing.T) { - if runtime.GOOS == "nacl" { - t.Skip("skipping on nacl") + switch runtime.GOOS { + case "nacl", "android": + t.Skipf("skipping on %s", runtime.GOOS) } syms := loadSyms(t) diff --git a/src/cmd/addr2line/main.go b/src/cmd/addr2line/main.go index b94ba12ef..267f4170a 100644 --- a/src/cmd/addr2line/main.go +++ b/src/cmd/addr2line/main.go @@ -19,17 +19,14 @@ package main import ( "bufio" - "debug/elf" - "debug/gosym" - "debug/macho" - "debug/pe" - "debug/plan9obj" "flag" "fmt" "log" "os" "strconv" "strings" + + "cmd/internal/objfile" ) func printUsage(w *os.File) { @@ -60,18 +57,12 @@ func main() { usage() } - f, err := os.Open(flag.Arg(0)) + f, err := objfile.Open(flag.Arg(0)) if err != nil { log.Fatal(err) } - textStart, symtab, pclntab, err := loadTables(f) - if err != nil { - log.Fatalf("reading %s: %v", flag.Arg(0), err) - } - - pcln := gosym.NewLineTable(pclntab, textStart) - tab, err := gosym.NewTable(symtab, pcln) + tab, err := f.PCLineTable() if err != nil { log.Fatalf("reading %s: %v", flag.Arg(0), err) } @@ -102,152 +93,3 @@ func main() { } stdout.Flush() } - -func loadTables(f *os.File) (textStart uint64, symtab, pclntab []byte, err error) { - if obj, err := elf.NewFile(f); err == nil { - if sect := obj.Section(".text"); sect != nil { - textStart = sect.Addr - } - if sect := obj.Section(".gosymtab"); sect != nil { - if symtab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - if sect := obj.Section(".gopclntab"); sect != nil { - if pclntab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - return textStart, symtab, pclntab, nil - } - - if obj, err := macho.NewFile(f); err == nil { - if sect := obj.Section("__text"); sect != nil { - textStart = sect.Addr - } - if sect := obj.Section("__gosymtab"); sect != nil { - if symtab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - if sect := obj.Section("__gopclntab"); sect != nil { - if pclntab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - return textStart, symtab, pclntab, nil - } - - if obj, err := pe.NewFile(f); err == nil { - var imageBase uint64 - switch oh := obj.OptionalHeader.(type) { - case *pe.OptionalHeader32: - imageBase = uint64(oh.ImageBase) - case *pe.OptionalHeader64: - imageBase = oh.ImageBase - default: - return 0, nil, nil, fmt.Errorf("pe file format not recognized") - } - if sect := obj.Section(".text"); sect != nil { - textStart = imageBase + uint64(sect.VirtualAddress) - } - if pclntab, err = loadPETable(obj, "pclntab", "epclntab"); err != nil { - return 0, nil, nil, err - } - if symtab, err = loadPETable(obj, "symtab", "esymtab"); err != nil { - return 0, nil, nil, err - } - return textStart, symtab, pclntab, nil - } - - if obj, err := plan9obj.NewFile(f); err == nil { - sym, err := findPlan9Symbol(obj, "text") - if err != nil { - return 0, nil, nil, err - } - textStart = sym.Value - if pclntab, err = loadPlan9Table(obj, "pclntab", "epclntab"); err != nil { - return 0, nil, nil, err - } - if symtab, err = loadPlan9Table(obj, "symtab", "esymtab"); err != nil { - return 0, nil, nil, err - } - return textStart, symtab, pclntab, nil - } - - return 0, nil, nil, fmt.Errorf("unrecognized binary format") -} - -func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) { - for _, s := range f.Symbols { - if s.Name != name { - continue - } - if s.SectionNumber <= 0 { - return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) - } - if len(f.Sections) < int(s.SectionNumber) { - return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) - } - return s, nil - } - return nil, fmt.Errorf("no %s symbol found", name) -} - -func loadPETable(f *pe.File, sname, ename string) ([]byte, error) { - ssym, err := findPESymbol(f, sname) - if err != nil { - return nil, err - } - esym, err := findPESymbol(f, ename) - if err != nil { - return nil, err - } - if ssym.SectionNumber != esym.SectionNumber { - return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) - } - sect := f.Sections[ssym.SectionNumber-1] - data, err := sect.Data() - if err != nil { - return nil, err - } - return data[ssym.Value:esym.Value], nil -} - -func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) { - syms, err := f.Symbols() - if err != nil { - return nil, err - } - for _, s := range syms { - if s.Name != name { - continue - } - return &s, nil - } - return nil, fmt.Errorf("no %s symbol found", name) -} - -func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) { - ssym, err := findPlan9Symbol(f, sname) - if err != nil { - return nil, err - } - esym, err := findPlan9Symbol(f, ename) - if err != nil { - return nil, err - } - text, err := findPlan9Symbol(f, "text") - if err != nil { - return nil, err - } - sect := f.Section("text") - if sect == nil { - return nil, err - } - data, err := sect.Data() - if err != nil { - return nil, err - } - return data[ssym.Value-text.Value : esym.Value-text.Value], nil -} diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 4bde794a1..4a63eac71 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -107,6 +107,8 @@ func setContexts() { } } +var internalPkg = regexp.MustCompile(`(^|/)internal($|/)`) + func main() { flag.Parse() @@ -132,12 +134,16 @@ func main() { if err != nil { log.Fatal(err) } - pkgNames = strings.Fields(string(stds)) + for _, pkg := range strings.Fields(string(stds)) { + if !internalPkg.MatchString(pkg) { + pkgNames = append(pkgNames, pkg) + } + } } var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true for _, context := range contexts { - w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src/pkg")) + w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src")) for _, name := range pkgNames { // - Package "unsafe" contains special signatures requiring @@ -277,7 +283,7 @@ func compareAPI(w io.Writer, features, required, optional, exception []string) ( delete(optionalSet, newFeature) } else { fmt.Fprintf(w, "+%s\n", newFeature) - if !*allowNew { + if !*allowNew || !strings.Contains(runtime.Version(), "devel") { ok = false // we're in lock-down mode for next release } } @@ -307,11 +313,15 @@ func fileFeatures(filename string) []string { if err != nil { log.Fatalf("Error reading file %s: %v", filename, err) } - text := strings.TrimSpace(string(bs)) - if text == "" { - return nil + lines := strings.Split(string(bs), "\n") + var nonblank []string + for _, line := range lines { + line = strings.TrimSpace(line) + if line != "" && !strings.HasPrefix(line, "#") { + nonblank = append(nonblank, line) + } } - return strings.Split(text, "\n") + return nonblank } var fset = token.NewFileSet() @@ -370,6 +380,106 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) { log.Fatalf("incorrect generated file: %s", err) } } + if w.context != nil && file == fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH) { + // Just enough to keep the api checker happy. Keep sorted. + src := "package runtime; type (" + + " _defer struct{};" + + " _func struct{};" + + " _panic struct{};" + + " _select struct{}; " + + " _type struct{};" + + " alg struct{};" + + " chantype struct{};" + + " context struct{};" + // windows + " eface struct{};" + + " epollevent struct{};" + + " funcval struct{};" + + " g struct{};" + + " gobuf struct{};" + + " hchan struct{};" + + " iface struct{};" + + " interfacetype struct{};" + + " itab struct{};" + + " keventt struct{};" + + " m struct{};" + + " maptype struct{};" + + " mcache struct{};" + + " mspan struct{};" + + " mutex struct{};" + + " note struct{};" + + " p struct{};" + + " parfor struct{};" + + " slicetype struct{};" + + " stkframe struct{};" + + " sudog struct{};" + + " timespec struct{};" + + " waitq struct{};" + + " wincallbackcontext struct{};" + + "); " + + "const (" + + " cb_max = 2000;" + + " _CacheLineSize = 64;" + + " _Gidle = 1;" + + " _Grunnable = 2;" + + " _Grunning = 3;" + + " _Gsyscall = 4;" + + " _Gwaiting = 5;" + + " _Gdead = 6;" + + " _Genqueue = 7;" + + " _Gcopystack = 8;" + + " _NSIG = 32;" + + " _FlagNoScan = iota;" + + " _FlagNoZero;" + + " _TinySize;" + + " _TinySizeClass;" + + " _MaxSmallSize;" + + " _PageShift;" + + " _PageSize;" + + " _PageMask;" + + " _BitsPerPointer;" + + " _BitsMask;" + + " _PointersPerByte;" + + " _MaxGCMask;" + + " _BitsDead;" + + " _BitsPointer;" + + " _MSpanInUse;" + + " _ConcurrentSweep;" + + " _KindBool;" + + " _KindInt;" + + " _KindInt8;" + + " _KindInt16;" + + " _KindInt32;" + + " _KindInt64;" + + " _KindUint;" + + " _KindUint8;" + + " _KindUint16;" + + " _KindUint32;" + + " _KindUint64;" + + " _KindUintptr;" + + " _KindFloat32;" + + " _KindFloat64;" + + " _KindComplex64;" + + " _KindComplex128;" + + " _KindArray;" + + " _KindChan;" + + " _KindFunc;" + + " _KindInterface;" + + " _KindMap;" + + " _KindPtr;" + + " _KindSlice;" + + " _KindString;" + + " _KindStruct;" + + " _KindUnsafePointer;" + + " _KindDirectIface;" + + " _KindGCProg;" + + " _KindNoPointers;" + + " _KindMask;" + + ")" + f, err = parser.ParseFile(fset, filename, src, 0) + if err != nil { + log.Fatalf("incorrect generated file: %s", err) + } + } if f == nil { f, err = parser.ParseFile(fset, filename, nil, 0) @@ -391,6 +501,11 @@ func contains(list []string, s string) bool { return false } +// The package cache doesn't operate correctly in rare (so far artificial) +// circumstances (issue 8425). Disable before debugging non-obvious errors +// from the type-checker. +const usePkgCache = true + var ( pkgCache = map[string]*types.Package{} // map tagKey to package pkgTags = map[string][]string{} // map import dir to list of relevant tags @@ -452,11 +567,13 @@ func (w *Walker) Import(name string) (pkg *types.Package) { // If we've already done an import with the same set // of relevant tags, reuse the result. var key string - if tags, ok := pkgTags[dir]; ok { - key = tagKey(dir, context, tags) - if pkg := pkgCache[key]; pkg != nil { - w.imported[name] = pkg - return pkg + if usePkgCache { + if tags, ok := pkgTags[dir]; ok { + key = tagKey(dir, context, tags) + if pkg := pkgCache[key]; pkg != nil { + w.imported[name] = pkg + return pkg + } } } @@ -469,9 +586,11 @@ func (w *Walker) Import(name string) (pkg *types.Package) { } // Save tags list first time we see a directory. - if _, ok := pkgTags[dir]; !ok { - pkgTags[dir] = info.AllTags - key = tagKey(dir, context, info.AllTags) + if usePkgCache { + if _, ok := pkgTags[dir]; !ok { + pkgTags[dir] = info.AllTags + key = tagKey(dir, context, info.AllTags) + } } filenames := append(append([]string{}, info.GoFiles...), info.CgoFiles...) @@ -488,6 +607,11 @@ func (w *Walker) Import(name string) (pkg *types.Package) { if !contains(filenames, n) { filenames = append(filenames, n) } + + n = fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH) + if !contains(filenames, n) { + filenames = append(filenames, n) + } } // Parse package files. @@ -519,7 +643,9 @@ func (w *Walker) Import(name string) (pkg *types.Package) { log.Fatalf("error typechecking package %s: %s (%s)", name, err, ctxt) } - pkgCache[key] = pkg + if usePkgCache { + pkgCache[key] = pkg + } w.imported[name] = pkg return diff --git a/src/cmd/api/goapi_test.go b/src/cmd/api/goapi_test.go index b909c32b3..f4fb7d319 100644 --- a/src/cmd/api/goapi_test.go +++ b/src/cmd/api/goapi_test.go @@ -38,7 +38,7 @@ func TestGolden(t *testing.T) { continue } - goldenFile := filepath.Join("testdata", "src", "pkg", fi.Name(), "golden.txt") + goldenFile := filepath.Join("testdata", "src", fi.Name(), "golden.txt") w := NewWalker(nil, "testdata/src/pkg") w.export(w.Import(fi.Name())) @@ -142,6 +142,26 @@ func TestCompareAPI(t *testing.T) { } } +func TestSkipInternal(t *testing.T) { + tests := []struct { + pkg string + want bool + }{ + {"net/http", true}, + {"net/http/internal-foo", true}, + {"net/http/internal", false}, + {"net/http/internal/bar", false}, + {"internal/foo", false}, + {"internal", false}, + } + for _, tt := range tests { + got := !internalPkg.MatchString(tt.pkg) + if got != tt.want { + t.Errorf("%s is internal = %v; want %v", tt.pkg, got, tt.want) + } + } +} + func BenchmarkAll(b *testing.B) { stds, err := exec.Command("go", "list", "std").Output() if err != nil { @@ -156,7 +176,7 @@ func BenchmarkAll(b *testing.B) { for i := 0; i < b.N; i++ { for _, context := range contexts { - w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src/pkg")) + w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src")) for _, name := range pkgNames { if name != "unsafe" && !strings.HasPrefix(name, "cmd/") { w.export(w.Import(name)) diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go index 896b2b4a1..ed5613edd 100644 --- a/src/cmd/api/run.go +++ b/src/cmd/api/run.go @@ -21,6 +21,7 @@ import ( "os/exec" "os/user" "path/filepath" + "runtime" "strings" ) @@ -53,7 +54,7 @@ func main() { } out, err = exec.Command("go", "tool", "api", - "-c", file("go1", "go1.1", "go1.2", "go1.3"), + "-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4"), "-next", file("next"), "-except", file("except")).CombinedOutput() if err != nil { @@ -98,16 +99,14 @@ func prepGoPath() string { if err == nil { username = u.Username } else { - // Only need to handle Unix here, as Windows's os/user uses - // native syscall and should work fine without cgo. username = os.Getenv("USER") if username == "" { - log.Fatalf("Error getting current user: %v", err) + username = "nobody" } } // The GOPATH we'll return - gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username), goToolsVersion) + gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username)+"-"+cleanUsername(strings.Fields(runtime.Version())[0]), goToolsVersion) // cloneDir is where we run "hg clone". cloneDir := filepath.Join(gopath, "src", "code.google.com", "p") diff --git a/src/cmd/cc/bv.c b/src/cmd/cc/bv.c deleted file mode 100644 index 51b7f4076..000000000 --- a/src/cmd/cc/bv.c +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include -#include "cc.h" - -enum { - WORDSIZE = sizeof(uint32), - WORDBITS = 32, -}; - -uintptr -bvsize(uintptr n) -{ - return ((n + WORDBITS - 1) / WORDBITS) * WORDSIZE; -} - -Bvec* -bvalloc(int32 n) -{ - Bvec *bv; - uintptr nbytes; - - if(n < 0) - fatal(Z, "bvalloc: initial size is negative\n"); - nbytes = sizeof(Bvec) + bvsize(n); - bv = malloc(nbytes); - if(bv == nil) - fatal(Z, "bvalloc: malloc failed\n"); - memset(bv, 0, nbytes); - bv->n = n; - return bv; -} - -void -bvset(Bvec *bv, int32 i) -{ - uint32 mask; - - if(i < 0 || i >= bv->n) - fatal(Z, "bvset: index %d is out of bounds with length %d\n", i, bv->n); - mask = 1 << (i % WORDBITS); - bv->b[i / WORDBITS] |= mask; -} diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h index c8aac1253..9530f5cf6 100644 --- a/src/cmd/cc/cc.h +++ b/src/cmd/cc/cc.h @@ -761,12 +761,6 @@ Bits blsh(uint); int beq(Bits, Bits); int bset(Bits, uint); -/* - * bv.c - */ -Bvec* bvalloc(int32 n); -void bvset(Bvec *bv, int32 i); - /* * dpchk.c */ @@ -794,7 +788,7 @@ void xcom(Node*); int32 exreg(Type*); int32 align(int32, Type*, int, int32*); int32 maxround(int32, int32); -int hasdotdotdot(void); +int hasdotdotdot(Type*); void linkarchinit(void); extern schar ewidth[]; diff --git a/src/cmd/cc/cc.y b/src/cmd/cc/cc.y index 11ee444b7..8d7cb1472 100644 --- a/src/cmd/cc/cc.y +++ b/src/cmd/cc/cc.y @@ -1043,6 +1043,7 @@ complex: } | LSTRUCT sbody { + diag(Z, "struct must have tag"); taggen++; sprint(symb, "_%d_", taggen); $$ = dotag(lookup(), TSTRUCT, autobn); diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c index a7a942686..117508fd6 100644 --- a/src/cmd/cc/dcl.c +++ b/src/cmd/cc/dcl.c @@ -30,6 +30,9 @@ #include #include "cc.h" +#include "../ld/textflag.h" + +static int haspointers(Type*); Node* dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n) @@ -123,7 +126,8 @@ loop: if(dataflag) { s->dataflag = dataflag; dataflag = 0; - } + } else if(s->type != T && !haspointers(s->type)) + s->dataflag = NOPTR; firstbit = 0; n->sym = s; n->type = s->type; @@ -568,9 +572,8 @@ haspointers(Type *t) return 0; case TARRAY: return haspointers(t->link); - case TFUNC: case TIND: - return 1; + return t->link->etype != TFUNC; default: return 0; } @@ -697,7 +700,8 @@ argmark(Node *n, int pass) { Type *t; - autoffset = align(0, thisfn->link, Aarg0, nil); + if(hasdotdotdot(thisfn->link)) + autoffset = align(0, thisfn->link, Aarg0, nil); stkoff = 0; for(; n->left != Z; n = n->left) { if(n->op != OFUNC || n->left->op != ONAME) @@ -1401,6 +1405,10 @@ xdecl(int c, Type *t, Sym *s) } tmerge(t, s); s->type = t; + if(c == CTYPEDEF && (typechlv[t->etype] || typefd[t->etype])) { + s->type = copytyp(t); + s->type->tag = s; + } s->class = c; s->block = 0; s->offset = o; @@ -1481,12 +1489,9 @@ edecl(int c, Type *t, Sym *s) { Type *t1; - if(s == S) { - if(!typesu[t->etype]) - diag(Z, "unnamed structure element must be struct/union"); - if(c != CXXX) - diag(Z, "unnamed structure element cannot have class"); - } else + if(s == S) + diag(Z, "unnamed structure elements not supported"); + else if(c != CXXX) diag(Z, "structure element cannot have class: %s", s->name); t1 = t; diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c index 7457bd000..d9f67f0ae 100644 --- a/src/cmd/cc/godefs.c +++ b/src/cmd/cc/godefs.c @@ -154,7 +154,6 @@ static void printtypename(Type *t) { Sym *s; - Type *t1; int w; char *n; @@ -188,40 +187,27 @@ printtypename(Type *t) switch(t->etype) { case TINT: - Bprint(&outbuf, "int32"); - break; case TUINT: - Bprint(&outbuf, "uint32"); - break; case TCHAR: - Bprint(&outbuf, "int8"); - break; case TUCHAR: - Bprint(&outbuf, "uint8"); - break; case TSHORT: - Bprint(&outbuf, "int16"); - break; case TUSHORT: - Bprint(&outbuf, "uint16"); - break; case TLONG: - Bprint(&outbuf, "int32"); - break; case TULONG: - Bprint(&outbuf, "uint32"); - break; case TVLONG: - Bprint(&outbuf, "int64"); - break; case TUVLONG: - Bprint(&outbuf, "uint64"); - break; case TFLOAT: - Bprint(&outbuf, "float32"); - break; case TDOUBLE: - Bprint(&outbuf, "float64"); + // All names used in the runtime code should be typedefs. + if(t->tag != nil) { + if(strcmp(t->tag->name, "intgo") == 0) + Bprint(&outbuf, "int"); + else if(strcmp(t->tag->name, "uintgo") == 0) + Bprint(&outbuf, "uint"); + else + Bprint(&outbuf, "%s", t->tag->name); + } else + Bprint(&outbuf, "C.%T", t); break; case TUNION: case TSTRUCT: @@ -231,27 +217,18 @@ printtypename(Type *t) n = s->name; else if(t->tag) n = t->tag->name; - if(strcmp(n, "String") == 0){ + if(strcmp(n, "String") == 0) Bprint(&outbuf, "string"); - } else if(strcmp(n, "Slice") == 0){ + else if(strcmp(n, "Slice") == 0) Bprint(&outbuf, "[]byte"); - } else + else if(strcmp(n, "Eface") == 0) + Bprint(&outbuf, "interface{}"); + else Bprint(&outbuf, "%U", n); break; case TFUNC: - Bprint(&outbuf, "func("); - for(t1 = t->down; t1 != T; t1 = t1->down) { - if(t1->etype == TVOID) - break; - if(t1 != t->down) - Bprint(&outbuf, ", "); - printtypename(t1); - } - Bprint(&outbuf, ")"); - if(t->link && t->link->etype != TVOID) { - Bprint(&outbuf, " "); - printtypename(t->link); - } + // There's no equivalent to a C function in the Go world. + Bprint(&outbuf, "unsafe.Pointer"); break; case TDOT: Bprint(&outbuf, "...interface{}"); @@ -340,9 +317,9 @@ godefvar(Sym *s) switch(t->etype) { case TENUM: if(!typefd[t->etype]) - Bprint(&outbuf, "const %U = %lld\n", s->name, s->vconst); + Bprint(&outbuf, "const %s = %lld\n", s->name, s->vconst); else - Bprint(&outbuf, "const %U = %f\n;", s->name, s->fconst); + Bprint(&outbuf, "const %s = %f\n;", s->name, s->fconst); break; case TFUNC: @@ -376,8 +353,10 @@ godefvar(Sym *s) case CSTATIC: case CEXTERN: case CGLOBL: - if(strchr(s->name, '$') != nil) // TODO(lvd) - break; + if(strchr(s->name, '$') != nil) + break; + if(strncmp(s->name, "go.weak.", 8) == 0) + break; Bprint(&outbuf, "var %U\t", s->name); printtypename(t); Bprint(&outbuf, "\n"); diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c index 424843764..7c9f718c0 100644 --- a/src/cmd/cc/lex.c +++ b/src/cmd/cc/lex.c @@ -31,6 +31,7 @@ #include #include "cc.h" #include "y.tab.h" +#include "../ld/textflag.h" #ifndef CPP #define CPP "cpp" @@ -203,6 +204,7 @@ main(int argc, char *argv[]) flagparse(&argc, &argv, usage); ctxt->debugasm = debug['S']; + ctxt->debugvlog = debug['v']; if(argc < 1 && outfile == 0) usage(); @@ -1316,6 +1318,7 @@ cinit(void) t->width = 0; symstring = slookup(".string"); symstring->class = CSTATIC; + symstring->dataflag = NOPTR; symstring->type = t; t = typ(TARRAY, types[TCHAR]); diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c index 10bebc196..db9aae916 100644 --- a/src/cmd/cc/pgen.c +++ b/src/cmd/cc/pgen.c @@ -29,51 +29,27 @@ // THE SOFTWARE. #include "gc.h" -#include "../../pkg/runtime/funcdata.h" - -enum { BitsPerPointer = 2 }; - -static void dumpgcargs(Type *fn, Sym *sym); - -static Sym* -makefuncdatasym(char *namefmt, int64 funcdatakind) -{ - Node nod; - Sym *sym; - static int32 nsym; - static char namebuf[40]; - - snprint(namebuf, sizeof(namebuf), namefmt, nsym++); - sym = slookup(namebuf); - sym->class = CSTATIC; - memset(&nod, 0, sizeof nod); - nod.op = ONAME; - nod.sym = sym; - nod.class = CSTATIC; - gins(AFUNCDATA, nodconst(funcdatakind), &nod); - linksym(sym)->type = SRODATA; - return sym; -} +#include "../../runtime/funcdata.h" int -hasdotdotdot(void) +hasdotdotdot(Type *t) { - Type *t; - - for(t=thisfn->down; t!=T; t=t->down) + for(t=t->down; t!=T; t=t->down) if(t->etype == TDOT) return 1; return 0; } vlong -argsize(void) +argsize(int doret) { Type *t; int32 s; //print("t=%T\n", thisfn); - s = align(0, thisfn->link, Aarg0, nil); + s = 0; + if(hasdotdotdot(thisfn)) + s = align(s, thisfn->link, Aarg0, nil); for(t=thisfn->down; t!=T; t=t->down) { switch(t->etype) { case TVOID: @@ -93,6 +69,14 @@ argsize(void) s = (s+7) & ~7; else s = (s+3) & ~3; + if(doret && thisfn->link->etype != TVOID) { + s = align(s, thisfn->link, Aarg1, nil); + s = align(s, thisfn->link, Aarg2, nil); + if(thechar == '6') + s = (s+7) & ~7; + else + s = (s+3) & ~3; + } return s; } @@ -101,9 +85,6 @@ codgen(Node *n, Node *nn) { Prog *sp; Node *n1, nod, nod1; - Sym *gcargs; - Sym *gclocals; - int isvarargs; cursafe = 0; curarg = 0; @@ -123,18 +104,9 @@ codgen(Node *n, Node *nn) nearln = nn->lineno; p = gtext(n1->sym, stkoff); + p->from.sym->cfunc = 1; sp = p; - /* - * generate funcdata symbol for this function. - * data is filled in at the end of codgen(). - */ - isvarargs = hasdotdotdot(); - gcargs = nil; - if(!isvarargs) - gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps); - gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps); - /* * isolate first argument */ @@ -155,8 +127,6 @@ codgen(Node *n, Node *nn) } } - retok = 0; - canreach = 1; warnreach = 1; gen(n); @@ -171,22 +141,6 @@ codgen(Node *n, Node *nn) if(thechar=='6' || thechar=='7') /* [sic] */ maxargsafe = xround(maxargsafe, 8); sp->to.offset += maxargsafe; - - if(!isvarargs) - dumpgcargs(thisfn, gcargs); - - // TODO(rsc): "stkoff" is not right. It does not account for - // the possibility of data stored in .safe variables. - // Unfortunately those move up and down just like - // the argument frame (and in fact dovetail with it) - // so the number we need is not available or even - // well-defined. Probably we need to make the safe - // area its own section. - // That said, we've been using stkoff for months - // and nothing too terrible has happened. - gextern(gclocals, nodconst(-stkoff), 0, 4); // locals - gclocals->type = typ(0, T); - gclocals->type->width = 4; } void @@ -214,7 +168,7 @@ supgen(Node *n) void gen(Node *n) { - Node *l, nod; + Node *l, nod, nod1; Prog *sp, *spc, *spb; Case *cn; long sbc, scc; @@ -275,14 +229,26 @@ loop: gbranch(ORETURN); break; } + if(typecmplx[n->type->etype] && !hasdotdotdot(thisfn)) { + regret(&nod, n, thisfn, 2); + sugen(l, &nod, n->type->width); + noretval(3); + gbranch(ORETURN); + break; + } if(typecmplx[n->type->etype]) { sugen(l, nodret, n->type->width); noretval(3); gbranch(ORETURN); break; } - regret(&nod, n); + regret(&nod1, n, thisfn, 2); + nod = nod1; + if(nod.op != OREGISTER) + regalloc(&nod, n, Z); cgen(l, &nod); + if(nod1.op != OREGISTER) + gmove(&nod, &nod1); regfree(&nod); if(typefd[n->type->etype]) noretval(1); @@ -654,111 +620,3 @@ bcomplex(Node *n, Node *c) boolgen(n, 1, Z); return 0; } - -// Updates the bitvector with a set bit for each pointer containing -// value in the type description starting at offset. -static void -walktype1(Type *t, int32 offset, Bvec *bv, int param) -{ - Type *t1; - int32 o; - int32 widthptr; - - widthptr = ewidth[TIND]; - switch(t->etype) { - case TCHAR: - case TUCHAR: - case TSHORT: - case TUSHORT: - case TINT: - case TUINT: - case TLONG: - case TULONG: - case TVLONG: - case TUVLONG: - case TFLOAT: - case TDOUBLE: - // non-pointer types - for(o = 0; o < t->width; o++) - bvset(bv, ((offset + t->offset + o) / widthptr) * BitsPerPointer); // 1 = live scalar - break; - - case TIND: - pointer: - // pointer types - if((offset + t->offset) % widthptr != 0) - yyerror("unaligned pointer"); - bvset(bv, ((offset + t->offset) / widthptr)*BitsPerPointer + 1); // 2 = live ptr - break; - - case TARRAY: - if(param) // unlike Go, C passes arrays by reference - goto pointer; - // array in struct or union is an actual array - for(o = 0; o < t->width; o += t->link->width) - walktype1(t->link, offset+o, bv, 0); - break; - - case TSTRUCT: - // build map recursively - for(t1 = t->link; t1 != T; t1 = t1->down) - walktype1(t1, offset, bv, 0); - break; - - case TUNION: - walktype1(t->link, offset, bv, 0); - break; - - default: - yyerror("can't handle arg type %s\n", tnames[t->etype]); - } -} - -// Compute a bit vector to describe the pointer containing locations -// in the argument list. Adds the data to gcsym and returns the offset -// of end of the bit vector. -static void -dumpgcargs(Type *fn, Sym *sym) -{ - Bvec *bv; - Type *t; - int32 i; - int32 argbytes; - int32 symoffset, argoffset; - - // Dump the length of the bitmap array. This value is always one for - // functions written in C. - symoffset = 0; - gextern(sym, nodconst(1), symoffset, 4); - symoffset += 4; - argbytes = (argsize() + ewidth[TIND] - 1); - bv = bvalloc((argbytes / ewidth[TIND]) * BitsPerPointer); - argoffset = align(0, fn->link, Aarg0, nil); - if(argoffset > 0) { - // The C calling convention returns structs by copying them to a - // location pointed to by a hidden first argument. This first - // argument is a pointer. - if(argoffset != ewidth[TIND]) - yyerror("passbyptr arg not the right size"); - bvset(bv, 1); // 2 = live ptr - } - for(t = fn->down; t != T; t = t->down) { - if(t->etype == TVOID) - continue; - argoffset = align(argoffset, t, Aarg1, nil); - walktype1(t, argoffset, bv, 1); - argoffset = align(argoffset, t, Aarg2, nil); - } - // Dump the length of the bitmap. - gextern(sym, nodconst(bv->n), symoffset, 4); - symoffset += 4; - // Dump the words of the bitmap. - for(i = 0; i < bv->n; i += 32) { - gextern(sym, nodconst(bv->b[i/32]), symoffset, 4); - symoffset += 4; - } - free(bv); - // Finalize the gc symbol. - sym->type = typ(0, T); - sym->type->width = symoffset; -} diff --git a/src/cmd/cc/y.tab.c b/src/cmd/cc/y.tab.c index 8588515ab..94932efe5 100644 --- a/src/cmd/cc/y.tab.c +++ b/src/cmd/cc/y.tab.c @@ -1,21 +1,24 @@ -/* A Bison parser, made by GNU Bison 2.7.12-4996. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - + the Free Software Foundation; either version 2, or (at your option) + any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -26,7 +29,7 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ @@ -44,7 +47,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.7.12-4996" +#define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -52,53 +55,10 @@ /* Pure parsers. */ #define YYPURE 0 -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* Copy the first part of user declarations. */ -/* Line 371 of yacc.c */ -#line 31 "cc.y" - -#include -#include /* if we don't, bison will, and cc.h re-#defines getc */ -#include "cc.h" +/* Using locations. */ +#define YYLSP_NEEDED 0 -/* Line 371 of yacc.c */ -#line 74 "y.tab.c" -# ifndef YY_NULL -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULL nullptr -# else -# define YY_NULL 0 -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* In a future release of Bison, this section will be replaced - by #include "y.tab.h". */ -#ifndef YY_YY_Y_TAB_H_INCLUDED -# define YY_YY_Y_TAB_H_INCLUDED -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif /* Tokens. */ #ifndef YYTOKENTYPE @@ -256,12 +216,37 @@ extern int yydebug; + +/* Copy the first part of user declarations. */ +#line 31 "cc.y" + +#include +#include /* if we don't, bison will, and cc.h re-#defines getc */ +#include "cc.h" + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -{ -/* Line 387 of yacc.c */ #line 36 "cc.y" - +{ Node* node; Sym* sym; Type* type; @@ -285,38 +270,22 @@ typedef union YYSTYPE int32 lval; double dval; vlong vval; - - -/* Line 387 of yacc.c */ -#line 292 "y.tab.c" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 +} +/* Line 193 of yacc.c. */ +#line 276 "y.tab.c" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif -extern YYSTYPE yylval; -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - -#endif /* !YY_YY_Y_TAB_H_INCLUDED */ /* Copy the second part of user declarations. */ -/* Line 390 of yacc.c */ -#line 320 "y.tab.c" + +/* Line 216 of yacc.c. */ +#line 289 "y.tab.c" #ifdef short # undef short @@ -369,45 +338,36 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if (! defined __GNUC__ || __GNUC__ < 2 \ - || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) -# define __attribute__(Spec) /* empty */ +# define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YYUSE(e) ((void) (e)) #else -# define YYUSE(E) /* empty */ +# define YYUSE(e) /* empty */ #endif - /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(N) (N) +# define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int -YYID (int yyi) +YYID (int i) #else static int -YYID (yyi) - int yyi; +YYID (i) + int i; #endif { - return yyi; + return i; } #endif @@ -428,12 +388,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # endif @@ -456,24 +415,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ +# if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -489,9 +448,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; + yytype_int16 yyss; + YYSTYPE yyvs; + }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) @@ -502,19 +461,35 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -# define YYCOPY_NEEDED 1 +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ +# define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ @@ -522,26 +497,6 @@ union yyalloc #endif -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ @@ -737,16 +692,16 @@ static const yytype_uint16 yyrline[] = 794, 798, 802, 803, 810, 817, 824, 831, 838, 845, 852, 859, 860, 863, 873, 891, 901, 919, 922, 925, 926, 933, 932, 955, 959, 962, 967, 972, 978, 986, - 992, 998, 1004, 1012, 1020, 1027, 1033, 1032, 1044, 1052, - 1058, 1057, 1069, 1077, 1086, 1090, 1085, 1107, 1106, 1115, - 1121, 1122, 1128, 1131, 1137, 1138, 1139, 1142, 1143, 1149, - 1150, 1153, 1157, 1161, 1162, 1165, 1166, 1167, 1168, 1169, - 1170, 1171, 1172, 1173, 1176, 1177, 1178, 1179, 1180, 1181, - 1182, 1185, 1186, 1187, 1190, 1205, 1217, 1218 + 992, 998, 1004, 1012, 1020, 1027, 1033, 1032, 1044, 1053, + 1059, 1058, 1070, 1078, 1087, 1091, 1086, 1108, 1107, 1116, + 1122, 1123, 1129, 1132, 1138, 1139, 1140, 1143, 1144, 1150, + 1151, 1154, 1158, 1162, 1163, 1166, 1167, 1168, 1169, 1170, + 1171, 1172, 1173, 1174, 1177, 1178, 1179, 1180, 1181, 1182, + 1183, 1186, 1187, 1188, 1191, 1206, 1218, 1219 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || 0 +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -764,16 +719,16 @@ static const char *const yytname[] = "LTYPEDEF", "LTYPESTR", "LUNION", "LUNSIGNED", "LWHILE", "LVOID", "LENUM", "LSIGNED", "LCONSTNT", "LVOLATILE", "LSET", "LSIGNOF", "LRESTRICT", "LINLINE", "')'", "']'", "'{'", "'}'", "'!'", "'~'", - "$accept", "prog", "xdecl", "$@1", "$@2", "xdlist", "$@3", "xdecor", - "xdecor2", "adecl", "adlist", "$@4", "pdecl", "pdlist", "edecl", "$@5", - "$@6", "zedlist", "edlist", "edecor", "abdecor", "abdecor1", "abdecor2", + "$accept", "prog", "xdecl", "@1", "@2", "xdlist", "@3", "xdecor", + "xdecor2", "adecl", "adlist", "@4", "pdecl", "pdlist", "edecl", "@5", + "@6", "zedlist", "edlist", "edecor", "abdecor", "abdecor1", "abdecor2", "abdecor3", "init", "qual", "qlist", "ilist", "zarglist", "arglist", - "block", "slist", "labels", "label", "stmnt", "forexpr", "ulstmnt", - "$@7", "$@8", "zcexpr", "zexpr", "lexpr", "cexpr", "expr", "xuexpr", - "uexpr", "pexpr", "string", "lstring", "zelist", "elist", "sbody", "@9", - "zctlist", "types", "tlist", "ctlist", "complex", "$@10", "$@11", "$@12", - "$@13", "$@14", "gctnlist", "zgnlist", "gctname", "gcnlist", "gcname", - "enum", "tname", "cname", "gname", "name", "tag", "ltag", YY_NULL + "block", "slist", "labels", "label", "stmnt", "forexpr", "ulstmnt", "@7", + "@8", "zcexpr", "zexpr", "lexpr", "cexpr", "expr", "xuexpr", "uexpr", + "pexpr", "string", "lstring", "zelist", "elist", "sbody", "@9", + "zctlist", "types", "tlist", "ctlist", "complex", "@10", "@11", "@12", + "@13", "@14", "gctnlist", "zgnlist", "gctname", "gcnlist", "gcname", + "enum", "tname", "cname", "gname", "name", "tag", "ltag", 0 }; #endif @@ -855,8 +810,8 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1 }; -/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -981,7 +936,8 @@ static const yytype_int16 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If YYTABLE_NINF, syntax error. */ + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -205 static const yytype_int16 yytable[] = { @@ -1106,12 +1062,6 @@ static const yytype_int16 yytable[] = 178, 179, 180, 181, 182, 183, 184, 185, 186 }; -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-331))) - -#define yytable_value_is_error(Yytable_value) \ - YYID (0) - static const yytype_int16 yycheck[] = { 1, 27, 14, 91, 131, 17, 30, 58, 20, 33, @@ -1295,50 +1245,78 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ + Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) -/* Error token number */ + #define YYTERROR 1 #define YYERRCODE 256 -/* This macro is provided for backward compatibility. */ +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + #ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ + #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else @@ -1388,8 +1366,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) YYSTYPE const * const yyvaluep; #endif { - FILE *yyo = yyoutput; - YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT @@ -1398,7 +1374,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) # else YYUSE (yyoutput); # endif - YYUSE (yytype); + switch (yytype) + { + default: + break; + } } @@ -1435,20 +1415,17 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } @@ -1482,11 +1459,11 @@ yy_reduce_print (yyvsp, yyrule) /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - YYFPRINTF (stderr, " $%d = ", yyi + 1); + fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); - YYFPRINTF (stderr, "\n"); + fprintf (stderr, "\n"); } } @@ -1523,6 +1500,7 @@ int yydebug; # define YYMAXDEPTH 10000 #endif + #if YYERROR_VERBOSE @@ -1625,145 +1603,115 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) { - YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULL; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - Assume YYFAIL is not used. It's too flawed to consider. See - - for details. YYERROR is fine as it does not invoke this - function. - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } + int yyn = yypact[yystate]; - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } + if (yysize_overflow) + return YYSIZE_MAXIMUM; - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } } #endif /* YYERROR_VERBOSE */ + /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1788,31 +1736,44 @@ yydestruct (yymsg, yytype, yyvaluep) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - YYUSE (yytype); -} + switch (yytype) + { + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ -/* The lookahead symbol. */ -int yychar; -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif +/* The look-ahead symbol. */ +int yychar; -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; + /*----------. | yyparse. | `----------*/ @@ -1839,37 +1800,14 @@ yyparse () #endif #endif { - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - + + int yystate; int yyn; int yyresult; - /* Lookahead token as an internal (translated) token number. */ + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; @@ -1877,22 +1815,54 @@ yyparse () YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + goto yysetstate; /*------------------------------------------------------------. @@ -1919,6 +1889,7 @@ yyparse () YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; + /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might @@ -1926,6 +1897,7 @@ yyparse () yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); yyss = yyss1; @@ -1948,8 +1920,9 @@ yyparse () (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1960,6 +1933,7 @@ yyparse () yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; + YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1969,9 +1943,6 @@ yyparse () YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) - YYACCEPT; - goto yybackup; /*-----------. @@ -1980,16 +1951,16 @@ yyparse () yybackup: /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ + look-ahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to lookahead token. */ + /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) + if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a lookahead token if don't already have one. */ + /* Not known => get a look-ahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); @@ -2015,27 +1986,29 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yytable_value_is_error (yyn)) - goto yyerrlab; + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; yyn = -yyn; goto yyreduce; } + if (yyn == YYFINAL) + YYACCEPT; + /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the lookahead token. */ + /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the shifted token. */ - yychar = YYEMPTY; + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -2072,7 +2045,6 @@ yyreduce: switch (yyn) { case 4: -/* Line 1787 of yacc.c */ #line 109 "cc.y" { dodecl(xdecl, lastclass, lasttype, Z); @@ -2080,7 +2052,6 @@ yyreduce: break; case 6: -/* Line 1787 of yacc.c */ #line 114 "cc.y" { lastdcl = T; @@ -2098,7 +2069,6 @@ yyreduce: break; case 7: -/* Line 1787 of yacc.c */ #line 128 "cc.y" { argmark((yyvsp[(2) - (4)].node), 1); @@ -2106,7 +2076,6 @@ yyreduce: break; case 8: -/* Line 1787 of yacc.c */ #line 132 "cc.y" { Node *n; @@ -2120,7 +2089,6 @@ yyreduce: break; case 9: -/* Line 1787 of yacc.c */ #line 144 "cc.y" { dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node)); @@ -2128,7 +2096,6 @@ yyreduce: break; case 10: -/* Line 1787 of yacc.c */ #line 148 "cc.y" { (yyvsp[(1) - (1)].node) = dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node)); @@ -2136,7 +2103,6 @@ yyreduce: break; case 11: -/* Line 1787 of yacc.c */ #line 152 "cc.y" { doinit((yyvsp[(1) - (4)].node)->sym, (yyvsp[(1) - (4)].node)->type, 0L, (yyvsp[(4) - (4)].node)); @@ -2144,7 +2110,6 @@ yyreduce: break; case 14: -/* Line 1787 of yacc.c */ #line 160 "cc.y" { (yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z); @@ -2153,7 +2118,6 @@ yyreduce: break; case 16: -/* Line 1787 of yacc.c */ #line 168 "cc.y" { (yyval.node) = (yyvsp[(2) - (3)].node); @@ -2161,7 +2125,6 @@ yyreduce: break; case 17: -/* Line 1787 of yacc.c */ #line 172 "cc.y" { (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)); @@ -2169,7 +2132,6 @@ yyreduce: break; case 18: -/* Line 1787 of yacc.c */ #line 176 "cc.y" { (yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)); @@ -2177,7 +2139,6 @@ yyreduce: break; case 19: -/* Line 1787 of yacc.c */ #line 185 "cc.y" { (yyval.node) = dodecl(adecl, lastclass, lasttype, Z); @@ -2185,7 +2146,6 @@ yyreduce: break; case 20: -/* Line 1787 of yacc.c */ #line 189 "cc.y" { (yyval.node) = (yyvsp[(2) - (3)].node); @@ -2193,7 +2153,6 @@ yyreduce: break; case 21: -/* Line 1787 of yacc.c */ #line 195 "cc.y" { dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node)); @@ -2202,7 +2161,6 @@ yyreduce: break; case 22: -/* Line 1787 of yacc.c */ #line 200 "cc.y" { (yyvsp[(1) - (1)].node) = dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node)); @@ -2210,7 +2168,6 @@ yyreduce: break; case 23: -/* Line 1787 of yacc.c */ #line 204 "cc.y" { int32 w; @@ -2222,7 +2179,6 @@ yyreduce: break; case 24: -/* Line 1787 of yacc.c */ #line 212 "cc.y" { (yyval.node) = (yyvsp[(1) - (3)].node); @@ -2235,7 +2191,6 @@ yyreduce: break; case 27: -/* Line 1787 of yacc.c */ #line 229 "cc.y" { dodecl(pdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node)); @@ -2243,7 +2198,6 @@ yyreduce: break; case 29: -/* Line 1787 of yacc.c */ #line 239 "cc.y" { lasttype = (yyvsp[(1) - (1)].type); @@ -2251,7 +2205,6 @@ yyreduce: break; case 31: -/* Line 1787 of yacc.c */ #line 244 "cc.y" { lasttype = (yyvsp[(2) - (2)].type); @@ -2259,7 +2212,6 @@ yyreduce: break; case 33: -/* Line 1787 of yacc.c */ #line 250 "cc.y" { lastfield = 0; @@ -2268,7 +2220,6 @@ yyreduce: break; case 35: -/* Line 1787 of yacc.c */ #line 258 "cc.y" { dodecl(edecl, CXXX, lasttype, (yyvsp[(1) - (1)].node)); @@ -2276,7 +2227,6 @@ yyreduce: break; case 37: -/* Line 1787 of yacc.c */ #line 265 "cc.y" { lastbit = 0; @@ -2285,7 +2235,6 @@ yyreduce: break; case 38: -/* Line 1787 of yacc.c */ #line 270 "cc.y" { (yyval.node) = new(OBIT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2293,7 +2242,6 @@ yyreduce: break; case 39: -/* Line 1787 of yacc.c */ #line 274 "cc.y" { (yyval.node) = new(OBIT, Z, (yyvsp[(2) - (2)].node)); @@ -2301,7 +2249,6 @@ yyreduce: break; case 40: -/* Line 1787 of yacc.c */ #line 282 "cc.y" { (yyval.node) = (Z); @@ -2309,7 +2256,6 @@ yyreduce: break; case 42: -/* Line 1787 of yacc.c */ #line 289 "cc.y" { (yyval.node) = new(OIND, (Z), Z); @@ -2318,7 +2264,6 @@ yyreduce: break; case 43: -/* Line 1787 of yacc.c */ #line 294 "cc.y" { (yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z); @@ -2327,7 +2272,6 @@ yyreduce: break; case 46: -/* Line 1787 of yacc.c */ #line 303 "cc.y" { (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)); @@ -2335,7 +2279,6 @@ yyreduce: break; case 47: -/* Line 1787 of yacc.c */ #line 307 "cc.y" { (yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)); @@ -2343,7 +2286,6 @@ yyreduce: break; case 48: -/* Line 1787 of yacc.c */ #line 313 "cc.y" { (yyval.node) = new(OFUNC, (Z), Z); @@ -2351,7 +2293,6 @@ yyreduce: break; case 49: -/* Line 1787 of yacc.c */ #line 317 "cc.y" { (yyval.node) = new(OARRAY, (Z), (yyvsp[(2) - (3)].node)); @@ -2359,7 +2300,6 @@ yyreduce: break; case 50: -/* Line 1787 of yacc.c */ #line 321 "cc.y" { (yyval.node) = (yyvsp[(2) - (3)].node); @@ -2367,7 +2307,6 @@ yyreduce: break; case 52: -/* Line 1787 of yacc.c */ #line 328 "cc.y" { (yyval.node) = new(OINIT, invert((yyvsp[(2) - (3)].node)), Z); @@ -2375,7 +2314,6 @@ yyreduce: break; case 53: -/* Line 1787 of yacc.c */ #line 334 "cc.y" { (yyval.node) = new(OARRAY, (yyvsp[(2) - (3)].node), Z); @@ -2383,7 +2321,6 @@ yyreduce: break; case 54: -/* Line 1787 of yacc.c */ #line 338 "cc.y" { (yyval.node) = new(OELEM, Z, Z); @@ -2392,7 +2329,6 @@ yyreduce: break; case 57: -/* Line 1787 of yacc.c */ #line 347 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node)); @@ -2400,7 +2336,6 @@ yyreduce: break; case 59: -/* Line 1787 of yacc.c */ #line 352 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); @@ -2408,7 +2343,6 @@ yyreduce: break; case 62: -/* Line 1787 of yacc.c */ #line 360 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); @@ -2416,7 +2350,6 @@ yyreduce: break; case 63: -/* Line 1787 of yacc.c */ #line 365 "cc.y" { (yyval.node) = Z; @@ -2424,7 +2357,6 @@ yyreduce: break; case 64: -/* Line 1787 of yacc.c */ #line 369 "cc.y" { (yyval.node) = invert((yyvsp[(1) - (1)].node)); @@ -2432,7 +2364,6 @@ yyreduce: break; case 66: -/* Line 1787 of yacc.c */ #line 377 "cc.y" { (yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z); @@ -2441,7 +2372,6 @@ yyreduce: break; case 67: -/* Line 1787 of yacc.c */ #line 382 "cc.y" { (yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z); @@ -2450,7 +2380,6 @@ yyreduce: break; case 68: -/* Line 1787 of yacc.c */ #line 387 "cc.y" { (yyval.node) = new(ODOTDOT, Z, Z); @@ -2458,7 +2387,6 @@ yyreduce: break; case 69: -/* Line 1787 of yacc.c */ #line 391 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2466,7 +2394,6 @@ yyreduce: break; case 70: -/* Line 1787 of yacc.c */ #line 397 "cc.y" { (yyval.node) = invert((yyvsp[(2) - (3)].node)); @@ -2478,7 +2405,6 @@ yyreduce: break; case 71: -/* Line 1787 of yacc.c */ #line 406 "cc.y" { (yyval.node) = Z; @@ -2486,7 +2412,6 @@ yyreduce: break; case 72: -/* Line 1787 of yacc.c */ #line 410 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); @@ -2494,7 +2419,6 @@ yyreduce: break; case 73: -/* Line 1787 of yacc.c */ #line 414 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); @@ -2502,7 +2426,6 @@ yyreduce: break; case 75: -/* Line 1787 of yacc.c */ #line 421 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); @@ -2510,7 +2433,6 @@ yyreduce: break; case 76: -/* Line 1787 of yacc.c */ #line 427 "cc.y" { (yyval.node) = new(OCASE, (yyvsp[(2) - (3)].node), Z); @@ -2518,7 +2440,6 @@ yyreduce: break; case 77: -/* Line 1787 of yacc.c */ #line 431 "cc.y" { (yyval.node) = new(OCASE, Z, Z); @@ -2526,7 +2447,6 @@ yyreduce: break; case 78: -/* Line 1787 of yacc.c */ #line 435 "cc.y" { (yyval.node) = new(OLABEL, dcllabel((yyvsp[(1) - (2)].sym), 1), Z); @@ -2534,7 +2454,6 @@ yyreduce: break; case 79: -/* Line 1787 of yacc.c */ #line 441 "cc.y" { (yyval.node) = Z; @@ -2542,7 +2461,6 @@ yyreduce: break; case 81: -/* Line 1787 of yacc.c */ #line 446 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); @@ -2550,7 +2468,6 @@ yyreduce: break; case 83: -/* Line 1787 of yacc.c */ #line 453 "cc.y" { (yyval.node) = (yyvsp[(2) - (2)].node); @@ -2558,7 +2475,6 @@ yyreduce: break; case 85: -/* Line 1787 of yacc.c */ #line 459 "cc.y" { markdcl(); @@ -2566,7 +2482,6 @@ yyreduce: break; case 86: -/* Line 1787 of yacc.c */ #line 463 "cc.y" { (yyval.node) = revertdcl(); @@ -2578,7 +2493,6 @@ yyreduce: break; case 87: -/* Line 1787 of yacc.c */ #line 471 "cc.y" { (yyval.node) = new(OIF, (yyvsp[(3) - (5)].node), new(OLIST, (yyvsp[(5) - (5)].node), Z)); @@ -2588,7 +2502,6 @@ yyreduce: break; case 88: -/* Line 1787 of yacc.c */ #line 477 "cc.y" { (yyval.node) = new(OIF, (yyvsp[(3) - (7)].node), new(OLIST, (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node))); @@ -2600,13 +2513,11 @@ yyreduce: break; case 89: -/* Line 1787 of yacc.c */ #line 484 "cc.y" { markdcl(); } break; case 90: -/* Line 1787 of yacc.c */ #line 485 "cc.y" { (yyval.node) = revertdcl(); @@ -2621,7 +2532,6 @@ yyreduce: break; case 91: -/* Line 1787 of yacc.c */ #line 496 "cc.y" { (yyval.node) = new(OWHILE, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)); @@ -2629,7 +2539,6 @@ yyreduce: break; case 92: -/* Line 1787 of yacc.c */ #line 500 "cc.y" { (yyval.node) = new(ODWHILE, (yyvsp[(5) - (7)].node), (yyvsp[(2) - (7)].node)); @@ -2637,7 +2546,6 @@ yyreduce: break; case 93: -/* Line 1787 of yacc.c */ #line 504 "cc.y" { (yyval.node) = new(ORETURN, (yyvsp[(2) - (3)].node), Z); @@ -2646,7 +2554,6 @@ yyreduce: break; case 94: -/* Line 1787 of yacc.c */ #line 509 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -2664,7 +2571,6 @@ yyreduce: break; case 95: -/* Line 1787 of yacc.c */ #line 523 "cc.y" { (yyval.node) = new(OBREAK, Z, Z); @@ -2672,7 +2578,6 @@ yyreduce: break; case 96: -/* Line 1787 of yacc.c */ #line 527 "cc.y" { (yyval.node) = new(OCONTINUE, Z, Z); @@ -2680,7 +2585,6 @@ yyreduce: break; case 97: -/* Line 1787 of yacc.c */ #line 531 "cc.y" { (yyval.node) = new(OGOTO, dcllabel((yyvsp[(2) - (3)].sym), 0), Z); @@ -2688,7 +2592,6 @@ yyreduce: break; case 98: -/* Line 1787 of yacc.c */ #line 535 "cc.y" { (yyval.node) = new(OUSED, (yyvsp[(3) - (5)].node), Z); @@ -2696,7 +2599,6 @@ yyreduce: break; case 99: -/* Line 1787 of yacc.c */ #line 539 "cc.y" { (yyval.node) = new(OPREFETCH, (yyvsp[(3) - (5)].node), Z); @@ -2704,7 +2606,6 @@ yyreduce: break; case 100: -/* Line 1787 of yacc.c */ #line 543 "cc.y" { (yyval.node) = new(OSET, (yyvsp[(3) - (5)].node), Z); @@ -2712,7 +2613,6 @@ yyreduce: break; case 101: -/* Line 1787 of yacc.c */ #line 548 "cc.y" { (yyval.node) = Z; @@ -2720,7 +2620,6 @@ yyreduce: break; case 103: -/* Line 1787 of yacc.c */ #line 554 "cc.y" { (yyval.node) = Z; @@ -2728,7 +2627,6 @@ yyreduce: break; case 105: -/* Line 1787 of yacc.c */ #line 561 "cc.y" { (yyval.node) = new(OCAST, (yyvsp[(1) - (1)].node), Z); @@ -2737,7 +2635,6 @@ yyreduce: break; case 107: -/* Line 1787 of yacc.c */ #line 569 "cc.y" { (yyval.node) = new(OCOMMA, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2745,7 +2642,6 @@ yyreduce: break; case 109: -/* Line 1787 of yacc.c */ #line 576 "cc.y" { (yyval.node) = new(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2753,7 +2649,6 @@ yyreduce: break; case 110: -/* Line 1787 of yacc.c */ #line 580 "cc.y" { (yyval.node) = new(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2761,7 +2656,6 @@ yyreduce: break; case 111: -/* Line 1787 of yacc.c */ #line 584 "cc.y" { (yyval.node) = new(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2769,7 +2663,6 @@ yyreduce: break; case 112: -/* Line 1787 of yacc.c */ #line 588 "cc.y" { (yyval.node) = new(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2777,7 +2670,6 @@ yyreduce: break; case 113: -/* Line 1787 of yacc.c */ #line 592 "cc.y" { (yyval.node) = new(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2785,7 +2677,6 @@ yyreduce: break; case 114: -/* Line 1787 of yacc.c */ #line 596 "cc.y" { (yyval.node) = new(OASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2793,7 +2684,6 @@ yyreduce: break; case 115: -/* Line 1787 of yacc.c */ #line 600 "cc.y" { (yyval.node) = new(OASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2801,7 +2691,6 @@ yyreduce: break; case 116: -/* Line 1787 of yacc.c */ #line 604 "cc.y" { (yyval.node) = new(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2809,7 +2698,6 @@ yyreduce: break; case 117: -/* Line 1787 of yacc.c */ #line 608 "cc.y" { (yyval.node) = new(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2817,7 +2705,6 @@ yyreduce: break; case 118: -/* Line 1787 of yacc.c */ #line 612 "cc.y" { (yyval.node) = new(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2825,7 +2712,6 @@ yyreduce: break; case 119: -/* Line 1787 of yacc.c */ #line 616 "cc.y" { (yyval.node) = new(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2833,7 +2719,6 @@ yyreduce: break; case 120: -/* Line 1787 of yacc.c */ #line 620 "cc.y" { (yyval.node) = new(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2841,7 +2726,6 @@ yyreduce: break; case 121: -/* Line 1787 of yacc.c */ #line 624 "cc.y" { (yyval.node) = new(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2849,7 +2733,6 @@ yyreduce: break; case 122: -/* Line 1787 of yacc.c */ #line 628 "cc.y" { (yyval.node) = new(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2857,7 +2740,6 @@ yyreduce: break; case 123: -/* Line 1787 of yacc.c */ #line 632 "cc.y" { (yyval.node) = new(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2865,7 +2747,6 @@ yyreduce: break; case 124: -/* Line 1787 of yacc.c */ #line 636 "cc.y" { (yyval.node) = new(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2873,7 +2754,6 @@ yyreduce: break; case 125: -/* Line 1787 of yacc.c */ #line 640 "cc.y" { (yyval.node) = new(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2881,7 +2761,6 @@ yyreduce: break; case 126: -/* Line 1787 of yacc.c */ #line 644 "cc.y" { (yyval.node) = new(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2889,7 +2768,6 @@ yyreduce: break; case 127: -/* Line 1787 of yacc.c */ #line 648 "cc.y" { (yyval.node) = new(OCOND, (yyvsp[(1) - (5)].node), new(OLIST, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node))); @@ -2897,7 +2775,6 @@ yyreduce: break; case 128: -/* Line 1787 of yacc.c */ #line 652 "cc.y" { (yyval.node) = new(OAS, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2905,7 +2782,6 @@ yyreduce: break; case 129: -/* Line 1787 of yacc.c */ #line 656 "cc.y" { (yyval.node) = new(OASADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2913,7 +2789,6 @@ yyreduce: break; case 130: -/* Line 1787 of yacc.c */ #line 660 "cc.y" { (yyval.node) = new(OASSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2921,7 +2796,6 @@ yyreduce: break; case 131: -/* Line 1787 of yacc.c */ #line 664 "cc.y" { (yyval.node) = new(OASMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2929,7 +2803,6 @@ yyreduce: break; case 132: -/* Line 1787 of yacc.c */ #line 668 "cc.y" { (yyval.node) = new(OASDIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2937,7 +2810,6 @@ yyreduce: break; case 133: -/* Line 1787 of yacc.c */ #line 672 "cc.y" { (yyval.node) = new(OASMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2945,7 +2817,6 @@ yyreduce: break; case 134: -/* Line 1787 of yacc.c */ #line 676 "cc.y" { (yyval.node) = new(OASASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2953,7 +2824,6 @@ yyreduce: break; case 135: -/* Line 1787 of yacc.c */ #line 680 "cc.y" { (yyval.node) = new(OASASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2961,7 +2831,6 @@ yyreduce: break; case 136: -/* Line 1787 of yacc.c */ #line 684 "cc.y" { (yyval.node) = new(OASAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2969,7 +2838,6 @@ yyreduce: break; case 137: -/* Line 1787 of yacc.c */ #line 688 "cc.y" { (yyval.node) = new(OASXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2977,7 +2845,6 @@ yyreduce: break; case 138: -/* Line 1787 of yacc.c */ #line 692 "cc.y" { (yyval.node) = new(OASOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -2985,7 +2852,6 @@ yyreduce: break; case 140: -/* Line 1787 of yacc.c */ #line 699 "cc.y" { (yyval.node) = new(OCAST, (yyvsp[(5) - (5)].node), Z); @@ -2996,7 +2862,6 @@ yyreduce: break; case 141: -/* Line 1787 of yacc.c */ #line 706 "cc.y" { (yyval.node) = new(OSTRUCT, (yyvsp[(6) - (7)].node), Z); @@ -3006,7 +2871,6 @@ yyreduce: break; case 143: -/* Line 1787 of yacc.c */ #line 715 "cc.y" { (yyval.node) = new(OIND, (yyvsp[(2) - (2)].node), Z); @@ -3014,7 +2878,6 @@ yyreduce: break; case 144: -/* Line 1787 of yacc.c */ #line 719 "cc.y" { (yyval.node) = new(OADDR, (yyvsp[(2) - (2)].node), Z); @@ -3022,7 +2885,6 @@ yyreduce: break; case 145: -/* Line 1787 of yacc.c */ #line 723 "cc.y" { (yyval.node) = new(OPOS, (yyvsp[(2) - (2)].node), Z); @@ -3030,7 +2892,6 @@ yyreduce: break; case 146: -/* Line 1787 of yacc.c */ #line 727 "cc.y" { (yyval.node) = new(ONEG, (yyvsp[(2) - (2)].node), Z); @@ -3038,7 +2899,6 @@ yyreduce: break; case 147: -/* Line 1787 of yacc.c */ #line 731 "cc.y" { (yyval.node) = new(ONOT, (yyvsp[(2) - (2)].node), Z); @@ -3046,7 +2906,6 @@ yyreduce: break; case 148: -/* Line 1787 of yacc.c */ #line 735 "cc.y" { (yyval.node) = new(OCOM, (yyvsp[(2) - (2)].node), Z); @@ -3054,7 +2913,6 @@ yyreduce: break; case 149: -/* Line 1787 of yacc.c */ #line 739 "cc.y" { (yyval.node) = new(OPREINC, (yyvsp[(2) - (2)].node), Z); @@ -3062,7 +2920,6 @@ yyreduce: break; case 150: -/* Line 1787 of yacc.c */ #line 743 "cc.y" { (yyval.node) = new(OPREDEC, (yyvsp[(2) - (2)].node), Z); @@ -3070,7 +2927,6 @@ yyreduce: break; case 151: -/* Line 1787 of yacc.c */ #line 747 "cc.y" { (yyval.node) = new(OSIZE, (yyvsp[(2) - (2)].node), Z); @@ -3078,7 +2934,6 @@ yyreduce: break; case 152: -/* Line 1787 of yacc.c */ #line 751 "cc.y" { (yyval.node) = new(OSIGN, (yyvsp[(2) - (2)].node), Z); @@ -3086,7 +2941,6 @@ yyreduce: break; case 153: -/* Line 1787 of yacc.c */ #line 757 "cc.y" { (yyval.node) = (yyvsp[(2) - (3)].node); @@ -3094,7 +2948,6 @@ yyreduce: break; case 154: -/* Line 1787 of yacc.c */ #line 761 "cc.y" { (yyval.node) = new(OSIZE, Z, Z); @@ -3104,7 +2957,6 @@ yyreduce: break; case 155: -/* Line 1787 of yacc.c */ #line 767 "cc.y" { (yyval.node) = new(OSIGN, Z, Z); @@ -3114,7 +2966,6 @@ yyreduce: break; case 156: -/* Line 1787 of yacc.c */ #line 773 "cc.y" { (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), Z); @@ -3126,7 +2977,6 @@ yyreduce: break; case 157: -/* Line 1787 of yacc.c */ #line 781 "cc.y" { (yyval.node) = new(OIND, new(OADD, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)), Z); @@ -3134,7 +2984,6 @@ yyreduce: break; case 158: -/* Line 1787 of yacc.c */ #line 785 "cc.y" { (yyval.node) = new(ODOT, new(OIND, (yyvsp[(1) - (3)].node), Z), Z); @@ -3143,7 +2992,6 @@ yyreduce: break; case 159: -/* Line 1787 of yacc.c */ #line 790 "cc.y" { (yyval.node) = new(ODOT, (yyvsp[(1) - (3)].node), Z); @@ -3152,7 +3000,6 @@ yyreduce: break; case 160: -/* Line 1787 of yacc.c */ #line 795 "cc.y" { (yyval.node) = new(OPOSTINC, (yyvsp[(1) - (2)].node), Z); @@ -3160,7 +3007,6 @@ yyreduce: break; case 161: -/* Line 1787 of yacc.c */ #line 799 "cc.y" { (yyval.node) = new(OPOSTDEC, (yyvsp[(1) - (2)].node), Z); @@ -3168,7 +3014,6 @@ yyreduce: break; case 163: -/* Line 1787 of yacc.c */ #line 804 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3179,7 +3024,6 @@ yyreduce: break; case 164: -/* Line 1787 of yacc.c */ #line 811 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3190,7 +3034,6 @@ yyreduce: break; case 165: -/* Line 1787 of yacc.c */ #line 818 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3201,7 +3044,6 @@ yyreduce: break; case 166: -/* Line 1787 of yacc.c */ #line 825 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3212,7 +3054,6 @@ yyreduce: break; case 167: -/* Line 1787 of yacc.c */ #line 832 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3223,7 +3064,6 @@ yyreduce: break; case 168: -/* Line 1787 of yacc.c */ #line 839 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3234,7 +3074,6 @@ yyreduce: break; case 169: -/* Line 1787 of yacc.c */ #line 846 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3245,7 +3084,6 @@ yyreduce: break; case 170: -/* Line 1787 of yacc.c */ #line 853 "cc.y" { (yyval.node) = new(OCONST, Z, Z); @@ -3256,7 +3094,6 @@ yyreduce: break; case 173: -/* Line 1787 of yacc.c */ #line 864 "cc.y" { (yyval.node) = new(OSTRING, Z, Z); @@ -3270,7 +3107,6 @@ yyreduce: break; case 174: -/* Line 1787 of yacc.c */ #line 874 "cc.y" { char *s; @@ -3290,7 +3126,6 @@ yyreduce: break; case 175: -/* Line 1787 of yacc.c */ #line 892 "cc.y" { (yyval.node) = new(OLSTRING, Z, Z); @@ -3304,7 +3139,6 @@ yyreduce: break; case 176: -/* Line 1787 of yacc.c */ #line 902 "cc.y" { char *s; @@ -3324,7 +3158,6 @@ yyreduce: break; case 177: -/* Line 1787 of yacc.c */ #line 919 "cc.y" { (yyval.node) = Z; @@ -3332,7 +3165,6 @@ yyreduce: break; case 180: -/* Line 1787 of yacc.c */ #line 927 "cc.y" { (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -3340,7 +3172,6 @@ yyreduce: break; case 181: -/* Line 1787 of yacc.c */ #line 933 "cc.y" { (yyval.tyty).t1 = strf; @@ -3357,7 +3188,6 @@ yyreduce: break; case 182: -/* Line 1787 of yacc.c */ #line 946 "cc.y" { (yyval.type) = strf; @@ -3369,7 +3199,6 @@ yyreduce: break; case 183: -/* Line 1787 of yacc.c */ #line 955 "cc.y" { lastclass = CXXX; @@ -3378,7 +3207,6 @@ yyreduce: break; case 185: -/* Line 1787 of yacc.c */ #line 963 "cc.y" { (yyval.tycl).t = (yyvsp[(1) - (1)].type); @@ -3387,7 +3215,6 @@ yyreduce: break; case 186: -/* Line 1787 of yacc.c */ #line 968 "cc.y" { (yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval)); @@ -3396,7 +3223,6 @@ yyreduce: break; case 187: -/* Line 1787 of yacc.c */ #line 973 "cc.y" { (yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval)); @@ -3406,7 +3232,6 @@ yyreduce: break; case 188: -/* Line 1787 of yacc.c */ #line 979 "cc.y" { (yyval.tycl).t = (yyvsp[(1) - (2)].type); @@ -3418,7 +3243,6 @@ yyreduce: break; case 189: -/* Line 1787 of yacc.c */ #line 987 "cc.y" { (yyval.tycl).t = simplet(typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval))); @@ -3428,7 +3252,6 @@ yyreduce: break; case 190: -/* Line 1787 of yacc.c */ #line 993 "cc.y" { (yyval.tycl).t = (yyvsp[(2) - (3)].type); @@ -3438,7 +3261,6 @@ yyreduce: break; case 191: -/* Line 1787 of yacc.c */ #line 999 "cc.y" { (yyval.tycl).t = simplet((yyvsp[(2) - (2)].lval)); @@ -3448,7 +3270,6 @@ yyreduce: break; case 192: -/* Line 1787 of yacc.c */ #line 1005 "cc.y" { (yyval.tycl).t = simplet(typebitor((yyvsp[(2) - (3)].lval), (yyvsp[(3) - (3)].lval))); @@ -3458,7 +3279,6 @@ yyreduce: break; case 193: -/* Line 1787 of yacc.c */ #line 1013 "cc.y" { (yyval.type) = (yyvsp[(1) - (1)].tycl).t; @@ -3468,7 +3288,6 @@ yyreduce: break; case 194: -/* Line 1787 of yacc.c */ #line 1021 "cc.y" { lasttype = (yyvsp[(1) - (1)].tycl).t; @@ -3477,7 +3296,6 @@ yyreduce: break; case 195: -/* Line 1787 of yacc.c */ #line 1028 "cc.y" { dotag((yyvsp[(2) - (2)].sym), TSTRUCT, 0); @@ -3486,7 +3304,6 @@ yyreduce: break; case 196: -/* Line 1787 of yacc.c */ #line 1033 "cc.y" { dotag((yyvsp[(2) - (2)].sym), TSTRUCT, autobn); @@ -3494,7 +3311,6 @@ yyreduce: break; case 197: -/* Line 1787 of yacc.c */ #line 1037 "cc.y" { (yyval.type) = (yyvsp[(2) - (4)].sym)->suetag; @@ -3506,9 +3322,9 @@ yyreduce: break; case 198: -/* Line 1787 of yacc.c */ #line 1045 "cc.y" { + diag(Z, "struct must have tag"); taggen++; sprint(symb, "_%d_", taggen); (yyval.type) = dotag(lookup(), TSTRUCT, autobn); @@ -3518,8 +3334,7 @@ yyreduce: break; case 199: -/* Line 1787 of yacc.c */ -#line 1053 "cc.y" +#line 1054 "cc.y" { dotag((yyvsp[(2) - (2)].sym), TUNION, 0); (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag; @@ -3527,16 +3342,14 @@ yyreduce: break; case 200: -/* Line 1787 of yacc.c */ -#line 1058 "cc.y" +#line 1059 "cc.y" { dotag((yyvsp[(2) - (2)].sym), TUNION, autobn); } break; case 201: -/* Line 1787 of yacc.c */ -#line 1062 "cc.y" +#line 1063 "cc.y" { (yyval.type) = (yyvsp[(2) - (4)].sym)->suetag; if((yyval.type)->link != T) @@ -3547,8 +3360,7 @@ yyreduce: break; case 202: -/* Line 1787 of yacc.c */ -#line 1070 "cc.y" +#line 1071 "cc.y" { taggen++; sprint(symb, "_%d_", taggen); @@ -3559,8 +3371,7 @@ yyreduce: break; case 203: -/* Line 1787 of yacc.c */ -#line 1078 "cc.y" +#line 1079 "cc.y" { dotag((yyvsp[(2) - (2)].sym), TENUM, 0); (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag; @@ -3571,16 +3382,14 @@ yyreduce: break; case 204: -/* Line 1787 of yacc.c */ -#line 1086 "cc.y" +#line 1087 "cc.y" { dotag((yyvsp[(2) - (2)].sym), TENUM, autobn); } break; case 205: -/* Line 1787 of yacc.c */ -#line 1090 "cc.y" +#line 1091 "cc.y" { en.tenum = T; en.cenum = T; @@ -3588,8 +3397,7 @@ yyreduce: break; case 206: -/* Line 1787 of yacc.c */ -#line 1095 "cc.y" +#line 1096 "cc.y" { (yyval.type) = (yyvsp[(2) - (7)].sym)->suetag; if((yyval.type)->link != T) @@ -3604,8 +3412,7 @@ yyreduce: break; case 207: -/* Line 1787 of yacc.c */ -#line 1107 "cc.y" +#line 1108 "cc.y" { en.tenum = T; en.cenum = T; @@ -3613,186 +3420,158 @@ yyreduce: break; case 208: -/* Line 1787 of yacc.c */ -#line 1112 "cc.y" +#line 1113 "cc.y" { (yyval.type) = en.tenum; } break; case 209: -/* Line 1787 of yacc.c */ -#line 1116 "cc.y" +#line 1117 "cc.y" { (yyval.type) = tcopy((yyvsp[(1) - (1)].sym)->type); } break; case 211: -/* Line 1787 of yacc.c */ -#line 1123 "cc.y" +#line 1124 "cc.y" { (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval)); } break; case 212: -/* Line 1787 of yacc.c */ -#line 1128 "cc.y" +#line 1129 "cc.y" { (yyval.lval) = 0; } break; case 213: -/* Line 1787 of yacc.c */ -#line 1132 "cc.y" +#line 1133 "cc.y" { (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval)); } break; case 218: -/* Line 1787 of yacc.c */ -#line 1144 "cc.y" +#line 1145 "cc.y" { (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval)); } break; case 221: -/* Line 1787 of yacc.c */ -#line 1154 "cc.y" +#line 1155 "cc.y" { doenum((yyvsp[(1) - (1)].sym), Z); } break; case 222: -/* Line 1787 of yacc.c */ -#line 1158 "cc.y" +#line 1159 "cc.y" { doenum((yyvsp[(1) - (3)].sym), (yyvsp[(3) - (3)].node)); } break; case 225: -/* Line 1787 of yacc.c */ -#line 1165 "cc.y" +#line 1166 "cc.y" { (yyval.lval) = BCHAR; } break; case 226: -/* Line 1787 of yacc.c */ -#line 1166 "cc.y" +#line 1167 "cc.y" { (yyval.lval) = BSHORT; } break; case 227: -/* Line 1787 of yacc.c */ -#line 1167 "cc.y" +#line 1168 "cc.y" { (yyval.lval) = BINT; } break; case 228: -/* Line 1787 of yacc.c */ -#line 1168 "cc.y" +#line 1169 "cc.y" { (yyval.lval) = BLONG; } break; case 229: -/* Line 1787 of yacc.c */ -#line 1169 "cc.y" +#line 1170 "cc.y" { (yyval.lval) = BSIGNED; } break; case 230: -/* Line 1787 of yacc.c */ -#line 1170 "cc.y" +#line 1171 "cc.y" { (yyval.lval) = BUNSIGNED; } break; case 231: -/* Line 1787 of yacc.c */ -#line 1171 "cc.y" +#line 1172 "cc.y" { (yyval.lval) = BFLOAT; } break; case 232: -/* Line 1787 of yacc.c */ -#line 1172 "cc.y" +#line 1173 "cc.y" { (yyval.lval) = BDOUBLE; } break; case 233: -/* Line 1787 of yacc.c */ -#line 1173 "cc.y" +#line 1174 "cc.y" { (yyval.lval) = BVOID; } break; case 234: -/* Line 1787 of yacc.c */ -#line 1176 "cc.y" +#line 1177 "cc.y" { (yyval.lval) = BAUTO; } break; case 235: -/* Line 1787 of yacc.c */ -#line 1177 "cc.y" +#line 1178 "cc.y" { (yyval.lval) = BSTATIC; } break; case 236: -/* Line 1787 of yacc.c */ -#line 1178 "cc.y" +#line 1179 "cc.y" { (yyval.lval) = BEXTERN; } break; case 237: -/* Line 1787 of yacc.c */ -#line 1179 "cc.y" +#line 1180 "cc.y" { (yyval.lval) = BTYPEDEF; } break; case 238: -/* Line 1787 of yacc.c */ -#line 1180 "cc.y" +#line 1181 "cc.y" { (yyval.lval) = BTYPESTR; } break; case 239: -/* Line 1787 of yacc.c */ -#line 1181 "cc.y" +#line 1182 "cc.y" { (yyval.lval) = BREGISTER; } break; case 240: -/* Line 1787 of yacc.c */ -#line 1182 "cc.y" +#line 1183 "cc.y" { (yyval.lval) = 0; } break; case 241: -/* Line 1787 of yacc.c */ -#line 1185 "cc.y" +#line 1186 "cc.y" { (yyval.lval) = BCONSTNT; } break; case 242: -/* Line 1787 of yacc.c */ -#line 1186 "cc.y" +#line 1187 "cc.y" { (yyval.lval) = BVOLATILE; } break; case 243: -/* Line 1787 of yacc.c */ -#line 1187 "cc.y" +#line 1188 "cc.y" { (yyval.lval) = 0; } break; case 244: -/* Line 1787 of yacc.c */ -#line 1191 "cc.y" +#line 1192 "cc.y" { (yyval.node) = new(ONAME, Z, Z); if((yyvsp[(1) - (1)].sym)->class == CLOCAL) @@ -3809,8 +3588,7 @@ yyreduce: break; case 245: -/* Line 1787 of yacc.c */ -#line 1206 "cc.y" +#line 1207 "cc.y" { (yyval.node) = new(ONAME, Z, Z); (yyval.node)->sym = (yyvsp[(1) - (1)].sym); @@ -3824,21 +3602,10 @@ yyreduce: break; -/* Line 1787 of yacc.c */ -#line 3829 "y.tab.c" +/* Line 1267 of yacc.c. */ +#line 3607 "y.tab.c" default: break; } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -3847,6 +3614,7 @@ yyreduce: *++yyvsp = yyval; + /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -3866,10 +3634,6 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -3877,36 +3641,37 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } } -# undef YYSYNTAX_ERROR #endif } @@ -3914,7 +3679,7 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an + /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) @@ -3931,7 +3696,7 @@ yyerrlab: } } - /* Else will try to reuse lookahead token after shifting the error + /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; @@ -3965,7 +3730,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) + if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -3988,9 +3753,10 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + if (yyn == YYFINAL) + YYACCEPT; + *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -4014,7 +3780,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined yyoverflow || YYERROR_VERBOSE +#ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -4025,14 +3791,9 @@ yyexhaustedlab: #endif yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -4056,6 +3817,6 @@ yyreturn: } -/* Line 2050 of yacc.c */ -#line 1219 "cc.y" +#line 1220 "cc.y" + diff --git a/src/cmd/cc/y.tab.h b/src/cmd/cc/y.tab.h index b26d659ef..32daca9b6 100644 --- a/src/cmd/cc/y.tab.h +++ b/src/cmd/cc/y.tab.h @@ -1,21 +1,24 @@ -/* A Bison parser, made by GNU Bison 2.7.12-4996. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - + the Free Software Foundation; either version 2, or (at your option) + any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -26,20 +29,10 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -#ifndef YY_YY_Y_TAB_H_INCLUDED -# define YY_YY_Y_TAB_H_INCLUDED -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE @@ -196,12 +189,11 @@ extern int yydebug; + #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -{ -/* Line 2053 of yacc.c */ #line 36 "cc.y" - +{ Node* node; Sym* sym; Type* type; @@ -225,30 +217,14 @@ typedef union YYSTYPE int32 lval; double dval; vlong vval; - - -/* Line 2053 of yacc.c */ -#line 232 "y.tab.h" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 +} +/* Line 1529 of yacc.c. */ +#line 223 "y.tab.h" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - -#endif /* !YY_YY_Y_TAB_H_INCLUDED */ diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index 7757efa1b..10e2278a1 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -272,7 +272,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{} case nil: - // These are ordered and grouped to match ../../pkg/go/ast/ast.go + // These are ordered and grouped to match ../../go/ast/ast.go case *ast.Field: if len(n.Names) == 0 && context == "field" { f.walk(&n.Type, "embed-type", visit) @@ -308,6 +308,9 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{} if n.High != nil { f.walk(&n.High, "expr", visit) } + if n.Max != nil { + f.walk(&n.Max, "expr", visit) + } case *ast.TypeAssertExpr: f.walk(&n.X, "expr", visit) f.walk(&n.Type, "type", visit) diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 69c7ce893..6179c7afd 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -152,7 +152,7 @@ In C, a function argument written as a fixed size array actually requires a pointer to the first element of the array. C compilers are aware of this calling convention and adjust the call accordingly, but Go cannot. In Go, you must pass -the pointer to the first element explicitly: C.f(&x[0]). +the pointer to the first element explicitly: C.f(&C.x[0]). A few special functions convert between Go and C types by making copies of the data. In pseudo-Go definitions: diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index f55cfbac4..abdd369d7 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -229,7 +229,8 @@ func (p *Package) guessKinds(f *File) []*Name { // Determine kinds for names we already know about, // like #defines or 'struct foo', before bothering with gcc. var names, needType []*Name - for _, n := range f.Name { + for _, key := range nameKeys(f.Name) { + n := f.Name[key] // If we've already found this name as a #define // and we can translate it as a constant value, do so. if n.Define != "" { @@ -331,6 +332,7 @@ func (p *Package) guessKinds(f *File) []*Name { const ( notType = 1 << iota notConst + notDeclared ) for _, line := range strings.Split(stderr, "\n") { if !strings.Contains(line, ": error:") { @@ -365,7 +367,7 @@ func (p *Package) guessKinds(f *File) []*Name { completed = true case "not-declared": - error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:])) + sniff[i] |= notDeclared case "not-type": sniff[i] |= notType case "not-const": @@ -374,12 +376,12 @@ func (p *Package) guessKinds(f *File) []*Name { } if !completed { - fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes()) + fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr) } for i, n := range names { switch sniff[i] { - case 0: + default: error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go)) case notType: n.Kind = "const" @@ -390,6 +392,14 @@ func (p *Package) guessKinds(f *File) []*Name { } } if nerrors > 0 { + // Check if compiling the preamble by itself causes any errors, + // because the messages we've printed out so far aren't helpful + // to users debugging preamble mistakes. See issue 8442. + preambleErrors := p.gccErrors([]byte(f.Preamble)) + if len(preambleErrors) > 0 { + error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors) + } + fatalf("unresolved names") } @@ -649,7 +659,13 @@ func (p *Package) rewriteRef(f *File) { f.Name[fpName] = name } r.Name = name - expr = ast.NewIdent(name.Mangle) + // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr + // function is defined in out.go and simply returns its argument. See + // issue 7757. + expr = &ast.CallExpr{ + Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"}, + Args: []ast.Expr{ast.NewIdent(name.Mangle)}, + } } else if r.Name.Kind == "type" { // Okay - might be new(T) expr = r.Name.Type.Go @@ -928,9 +944,8 @@ type typeConv struct { // Map from types to incomplete pointers to those types. ptrs map[dwarf.Type][]*Type - - // Fields to be processed by godefsField after completing pointers. - todoFlds [][]*ast.Field + // Keys of ptrs in insertion order (deterministic worklist) + ptrKeys []dwarf.Type // Predeclared types. bool ast.Expr @@ -940,9 +955,9 @@ type typeConv struct { float32, float64 ast.Expr complex64, complex128 ast.Expr void ast.Expr - unsafePointer ast.Expr string ast.Expr goVoid ast.Expr // _Ctype_void, denotes C's void + goVoidPtr ast.Expr // unsafe.Pointer or *byte ptrSize int64 intSize int64 @@ -972,10 +987,17 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.float64 = c.Ident("float64") c.complex64 = c.Ident("complex64") c.complex128 = c.Ident("complex128") - c.unsafePointer = c.Ident("unsafe.Pointer") c.void = c.Ident("void") c.string = c.Ident("string") 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 { + c.goVoidPtr = &ast.StarExpr{X: c.byte} + } else { + c.goVoidPtr = c.Ident("unsafe.Pointer") + } } // base strips away qualifiers and typedefs to get the underlying type @@ -1037,29 +1059,22 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) { } // FinishType completes any outstanding type mapping work. -// In particular, it resolves incomplete pointer types and also runs -// godefsFields on any new struct types. +// In particular, it resolves incomplete pointer types. func (c *typeConv) FinishType(pos token.Pos) { // Completing one pointer type might produce more to complete. // Keep looping until they're all done. - for len(c.ptrs) > 0 { - for dtype := range c.ptrs { - // Note Type might invalidate c.ptrs[dtype]. - t := c.Type(dtype, pos) - for _, ptr := range c.ptrs[dtype] { - ptr.Go.(*ast.StarExpr).X = t.Go - ptr.C.Set("%s*", t.C) - } - delete(c.ptrs, dtype) - } - } + for len(c.ptrKeys) > 0 { + dtype := c.ptrKeys[0] + c.ptrKeys = c.ptrKeys[1:] - // Now that pointer types are completed, we can invoke godefsFields - // to rewrite struct definitions. - for _, fld := range c.todoFlds { - godefsFields(fld) + // Note Type might invalidate c.ptrs[dtype]. + t := c.Type(dtype, pos) + for _, ptr := range c.ptrs[dtype] { + ptr.Go.(*ast.StarExpr).X = t.Go + ptr.C.Set("%s*", t.C) + } + c.ptrs[dtype] = nil // retain the map key } - c.todoFlds = nil } // Type returns a *Type with the same memory layout as @@ -1072,12 +1087,6 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { return t } - // clang won't generate DW_AT_byte_size for pointer types, - // so we have to fix it here. - if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 { - dt.ByteSize = c.ptrSize - } - t := new(Type) t.Size = dtype.Size() // note: wrong for array of pointers, corrected below t.Align = -1 @@ -1101,12 +1110,20 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { t.Go = c.Opaque(t.Size) break } + count := dt.Count + if count == -1 { + // Indicates flexible array member, which Go doesn't support. + // Translate to zero-length array instead. + count = 0 + } sub := c.Type(dt.Type, pos) t.Align = sub.Align t.Go = &ast.ArrayType{ - Len: c.intExpr(dt.Count), + Len: c.intExpr(count), Elt: sub.Go, } + // Recalculate t.Size now that we know sub.Size. + t.Size = count * sub.Size t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count) case *dwarf.BoolType: @@ -1207,11 +1224,15 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { } case *dwarf.PtrType: + // Clang doesn't emit DW_AT_byte_size for pointer types. + if t.Size != c.ptrSize && t.Size != -1 { + fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype) + } + t.Size = c.ptrSize t.Align = c.ptrSize - // Translate void* as unsafe.Pointer if _, ok := base(dt.Type).(*dwarf.VoidType); ok { - t.Go = c.unsafePointer + t.Go = c.goVoidPtr t.C.Set("void*") break } @@ -1219,6 +1240,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { // Placeholder initialization; completed in FinishType. t.Go = &ast.StarExpr{} t.C.Set("*") + if _, ok := c.ptrs[dt.Type]; !ok { + c.ptrKeys = append(c.ptrKeys, dt.Type) + } c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t) case *dwarf.QualType: @@ -1379,34 +1403,24 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { } } - if t.Size <= 0 { - // Clang does not record the size of a pointer in its DWARF entry, - // so if dtype is an array, the call to dtype.Size at the top of the function - // computed the size as the array length * 0 = 0. - // The type switch called Type (this function) recursively on the pointer - // entry, and the code near the top of the function updated the size to - // be correct, so calling dtype.Size again will produce the correct value. - t.Size = dtype.Size() - if t.Size < 0 { - // Unsized types are [0]byte, unless they're typedefs of other types - // or structs with tags. - // if so, use the name we've already defined. - t.Size = 0 - switch dt := dtype.(type) { - case *dwarf.TypedefType: - // ok - case *dwarf.StructType: - if dt.StructName != "" { - break - } - t.Go = c.Opaque(0) - default: - t.Go = c.Opaque(0) - } - if t.C.Empty() { - t.C.Set("void") + if t.Size < 0 { + // Unsized types are [0]byte, unless they're typedefs of other types + // or structs with tags. + // if so, use the name we've already defined. + t.Size = 0 + switch dt := dtype.(type) { + case *dwarf.TypedefType: + // ok + case *dwarf.StructType: + if dt.StructName != "" { + break } - return t + t.Go = c.Opaque(0) + default: + t.Go = c.Opaque(0) + } + if t.C.Empty() { + t.C.Set("void") } } @@ -1538,6 +1552,9 @@ func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field { // Struct conversion: return Go and (6g) 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 + var buf bytes.Buffer buf.WriteString("struct {") fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field @@ -1579,7 +1596,27 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct fld = c.pad(fld, f.ByteOffset-off) off = f.ByteOffset } - t := c.Type(f.Type, pos) + + name := f.Name + ft := f.Type + + // In godefs or cdefs 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 file; see + // issue 6677. + if *godefs || *cdefs { + 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 + ft = st.Field[0].Type + } + } + + // TODO: Handle fields that are anonymous structs by + // promoting the fields of the inner struct. + + t := c.Type(ft, pos) tgo := t.Go size := t.Size talign := t.Align @@ -1598,17 +1635,18 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct talign = size } - if talign > 0 && f.ByteOffset%talign != 0 { + if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs { // 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) fld = fld[0 : n+1] - name := f.Name if name == "" { name = fmt.Sprintf("anon%d", anon) anon++ @@ -1635,7 +1673,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct csyntax = buf.String() if *godefs || *cdefs { - c.todoFlds = append(c.todoFlds, fld) + godefsFields(fld) } expr = &ast.StructType{Fields: &ast.FieldList{List: fld}} return @@ -1673,19 +1711,6 @@ func godefsFields(fld []*ast.Field) { n.Name = upper(n.Name) } } - p := &f.Type - t := *p - if star, ok := t.(*ast.StarExpr); ok { - star = &ast.StarExpr{X: star.X} - *p = star - p = &star.X - t = *p - } - if id, ok := t.(*ast.Ident); ok { - if id.Name == "unsafe.Pointer" { - *p = ast.NewIdent("*byte") - } - } } } diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 76c7247af..d92bed9bf 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -44,6 +44,7 @@ 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, "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. @@ -58,16 +59,14 @@ func (p *Package) writeDefs() { fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n") fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") - if *importSyscall { - fmt.Fprintf(fgo2, "import \"syscall\"\n\n") - } if !*gccgo && *importRuntimeCgo { fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n") } - fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n") if *importSyscall { - fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int32) { *dst = syscall.Errno(x) }\n") + fmt.Fprintf(fgo2, "import \"syscall\"\n\n") + fmt.Fprintf(fgo2, "var _ syscall.Errno\n") } + fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") typedefNames := make([]string, 0, len(typedef)) for name := range typedef { @@ -87,9 +86,10 @@ func (p *Package) writeDefs() { } if *gccgo { - fmt.Fprintf(fc, p.cPrologGccgo()) + fmt.Fprint(fc, p.cPrologGccgo()) } else { - fmt.Fprintf(fc, cProlog) + fmt.Fprint(fc, cProlog) + fmt.Fprint(fgo2, goProlog) } gccgoSymbolPrefix := p.gccgoSymbolPrefix() @@ -130,6 +130,7 @@ func (p *Package) writeDefs() { 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(fc, "\n") @@ -296,10 +297,6 @@ func (p *Package) structType(n *Name) (string, int64) { fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) off += pad } - if n.AddError { - fmt.Fprint(&buf, "\t\tint e[2*sizeof(void *)/sizeof(int)]; /* error */\n") - off += 2 * p.PtrSize - } if off == 0 { fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct } @@ -334,19 +331,18 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { } // Builtins defined in the C prolog. - inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc" + inProlog := builtinDefs[name] != "" + cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) + paramnames := []string(nil) + for i, param := range d.Type.Params.List { + paramName := fmt.Sprintf("p%d", i) + param.Names = []*ast.Ident{ast.NewIdent(paramName)} + paramnames = append(paramnames, paramName) + } if *gccgo { // Gccgo style hooks. fmt.Fprint(fgo2, "\n") - cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) - paramnames := []string(nil) - for i, param := range d.Type.Params.List { - paramName := fmt.Sprintf("p%d", i) - param.Names = []*ast.Ident{ast.NewIdent(paramName)} - paramnames = append(paramnames, paramName) - } - conf.Fprint(fgo2, fset, d) fmt.Fprint(fgo2, " {\n") if !inProlog { @@ -383,7 +379,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { fmt.Fprint(fgo2, "}\n") // declare the C function. - fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle) + fmt.Fprintf(fgo2, "//extern %s\n", cname) d.Name = ast.NewIdent(cname) if n.AddError { l := d.Type.Results.List @@ -394,61 +390,50 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { return } - conf.Fprint(fgo2, fset, d) - fmt.Fprint(fgo2, "\n") if inProlog { + fmt.Fprint(fgo2, builtinDefs[name]) return } - var argSize int64 - _, argSize = p.structType(n) - // C wrapper calls into gcc, passing a pointer to the argument frame. - fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangle) - fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle) - fmt.Fprintf(fc, "\n") - fmt.Fprintf(fc, "void\n") - if argSize == 0 { - argSize++ + 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) + + nret := 0 + if !void { + d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")} + nret = 1 } - // TODO(rsc): The struct here should declare pointers only where - // there are pointers in the actual argument frame. - // This is a workaround for golang.org/issue/6397. - fmt.Fprintf(fc, "·%s(struct{", n.Mangle) - if n := argSize / p.PtrSize; n > 0 { - fmt.Fprintf(fc, "void *y[%d];", n) + if n.AddError { + d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")} } - if n := argSize % p.PtrSize; n > 0 { - fmt.Fprintf(fc, "uint8 x[%d];", n) + + fmt.Fprint(fgo2, "\n") + fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname) + conf.Fprint(fgo2, fset, d) + fmt.Fprint(fgo2, " {\n") + + // NOTE: Using uintptr to hide from escape analysis. + arg := "0" + if len(paramnames) > 0 { + arg = "uintptr(unsafe.Pointer(&p0))" + } else if !void { + arg = "uintptr(unsafe.Pointer(&r1))" } - fmt.Fprintf(fc, "}p)\n") - fmt.Fprintf(fc, "{\n") - fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle) + + prefix := "" if n.AddError { - // gcc leaves errno in first word of interface at end of p. - // check whether it is zero; if so, turn interface into nil. - // if not, turn interface into errno. - // Go init function initializes ·_Cerrno with an os.Errno - // for us to copy. - fmt.Fprintln(fc, ` { - int32 e; - void **v; - v = (void**)(&p+1) - 2; /* v = final two void* of p */ - e = *(int32*)v; - v[0] = (void*)0xdeadbeef; - v[1] = (void*)0xdeadbeef; - if(e == 0) { - /* nil interface */ - v[0] = 0; - v[1] = 0; - } else { - ·_Cerrno(v, e); /* fill in v as error for errno e */ - } - }`) + prefix = "errno := " } - fmt.Fprintf(fc, "}\n") - fmt.Fprintf(fc, "\n") + fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg) + if n.AddError { + fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n") + } + fmt.Fprintf(fgo2, "\treturn\n") + fmt.Fprintf(fgo2, "}\n") } // writeOutput creates stubs for a specific source file to be compiled by 6g @@ -521,7 +506,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { // Gcc wrapper unpacks the C argument struct // and calls the actual C function. - fmt.Fprintf(fgcc, "void\n") + if n.AddError { + fmt.Fprintf(fgcc, "int\n") + } else { + fmt.Fprintf(fgcc, "void\n") + } fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle) fmt.Fprintf(fgcc, "{\n") if n.AddError { @@ -531,9 +520,13 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { // 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()) + if n.FuncType.Result != nil { + // Save the stack top for use below. + fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n") + } fmt.Fprintf(fgcc, "\t") if t := n.FuncType.Result; t != nil { - fmt.Fprintf(fgcc, "a->r = ") + fmt.Fprintf(fgcc, "__typeof__(a->r) r = ") if c := t.C.String(); c[len(c)-1] == '*' { fmt.Fprint(fgcc, "(__typeof__(a->r)) ") } @@ -556,8 +549,15 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { fmt.Fprintf(fgcc, "a->p%d", i) } fmt.Fprintf(fgcc, ");\n") + if n.FuncType.Result != nil { + // The cgo call may have caused a stack copy (via a callback). + // Adjust the return value pointer appropriately. + fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n") + // Save the return value. + fmt.Fprintf(fgcc, "\ta->r = r;\n") + } if n.AddError { - fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n") + fmt.Fprintf(fgcc, "\treturn errno;\n") } fmt.Fprintf(fgcc, "}\n") fmt.Fprintf(fgcc, "\n") @@ -1016,7 +1016,7 @@ func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) { fn(i, r.Type) i++ } else { - for _ = range r.Names { + for range r.Names { fn(i, r.Type) i++ } @@ -1143,21 +1143,17 @@ __cgo_size_assert(__cgo_long_long, 8) __cgo_size_assert(float, 4) __cgo_size_assert(double, 8) +extern char* _cgo_topofstack(void); + #include #include ` const builtinProlog = ` -#include /* for size_t below */ +#include /* for ptrdiff_t and size_t below */ /* Define intgo when compiling with GCC. */ -#ifdef __PTRDIFF_TYPE__ -typedef __PTRDIFF_TYPE__ intgo; -#elif defined(_LP64) -typedef long long intgo; -#else -typedef int intgo; -#endif +typedef ptrdiff_t intgo; typedef struct { char *p; intgo n; } _GoString_; typedef struct { char *p; intgo n; intgo c; } _GoBytes_; @@ -1171,47 +1167,86 @@ 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); +` -void -·_Cfunc_GoString(int8 *p, String s) -{ - s = runtime·gostring((byte*)p); - FLUSH(&s); +const goProlog = ` +var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32 +var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer +` + +const goStringDef = ` +var _cgo_runtime_gostring func(*_Ctype_char) string +func _Cfunc_GoString(p *_Ctype_char) string { + return _cgo_runtime_gostring(p) } +` -void -·_Cfunc_GoStringN(int8 *p, int32 l, String s) -{ - s = runtime·gostringn((byte*)p, l); - FLUSH(&s); +const goStringNDef = ` +var _cgo_runtime_gostringn func(*_Ctype_char, int) string +func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string { + return _cgo_runtime_gostringn(p, int(l)) } +` -void -·_Cfunc_GoBytes(int8 *p, int32 l, Slice s) -{ - s = runtime·gobytes((byte*)p, l); - FLUSH(&s); +const goBytesDef = ` +var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte +func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte { + return _cgo_runtime_gobytes(p, int(l)) } +` -void -·_Cfunc_CString(String s, int8 *p) -{ - p = runtime·cmalloc(s.len+1); - runtime·memmove((byte*)p, s.str, s.len); - p[s.len] = 0; - FLUSH(&p); +const cStringDef = ` +func _Cfunc_CString(s string) *_Ctype_char { + p := _cgo_runtime_cmalloc(uintptr(len(s)+1)) + pp := (*[1<<30]byte)(p) + copy(pp[:], s) + pp[len(s)] = 0 + return (*_Ctype_char)(p) } +` -void -·_Cfunc__CMalloc(uintptr n, int8 *p) -{ - p = runtime·cmalloc(n); - FLUSH(&p); +const cMallocDef = ` +func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer { + return _cgo_runtime_cmalloc(uintptr(n)) } ` +var builtinDefs = map[string]string{ + "GoString": goStringDef, + "GoStringN": goStringNDef, + "GoBytes": goBytesDef, + "CString": cStringDef, + "_CMalloc": cMallocDef, +} + func (p *Package) cPrologGccgo() string { return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1) } diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h index 6222e5060..288063b94 100644 --- a/src/cmd/dist/a.h +++ b/src/cmd/dist/a.h @@ -108,9 +108,6 @@ void mkzexperiment(char*, char*); // buildgo.c void mkzdefaultcc(char*, char*); -// goc2c.c -void goc2c(char*, char*); - // main.c extern int vflag; extern int sflag; @@ -129,6 +126,7 @@ bool isfile(char *p); char* lastelem(char*); Time mtime(char*); void readfile(Buf*, char*); +void copyfile(char*, char*, int); void run(Buf *b, char *dir, int mode, char *cmd, ...); void runv(Buf *b, char *dir, int mode, Vec *argv); void bgrunv(char *dir, int mode, Vec *argv); diff --git a/src/cmd/dist/arm.c b/src/cmd/dist/arm.c index 52a621c5d..1ce7b7710 100644 --- a/src/cmd/dist/arm.c +++ b/src/cmd/dist/arm.c @@ -21,7 +21,8 @@ xgetgoarm(void) // FreeBSD has broken VFP support return "5"; #endif - if(xtryexecfunc(useVFPv3)) + // NaCl always has VFP support. + if(streq(goos, "nacl") || xtryexecfunc(useVFPv3)) return "7"; else if(xtryexecfunc(useVFPv1)) return "6"; diff --git a/src/cmd/dist/buf.c b/src/cmd/dist/buf.c index 45fb1954d..2ddc6be75 100644 --- a/src/cmd/dist/buf.c +++ b/src/cmd/dist/buf.c @@ -202,7 +202,7 @@ vadd(Vec *v, char *p) } // vaddn adds a string consisting of the n bytes at p to the vector. -void +static void vaddn(Vec *v, char *p, int n) { char *q; diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index 6884e0aae..d638ae4eb 100644 --- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -35,7 +35,6 @@ bool rebuildall; bool defaultclang; static bool shouldbuild(char*, char*); -static void copy(char*, char*, int); static void dopack(char*, char*, char**, int); static char *findgoversion(void); @@ -56,6 +55,7 @@ static char *okgoos[] = { "darwin", "dragonfly", "linux", + "android", "solaris", "freebsd", "nacl", @@ -366,8 +366,8 @@ static char *oldtool[] = { // not be in release branches. static char *unreleased[] = { "src/cmd/link", - "src/pkg/debug/goobj", - "src/pkg/old", + "src/debug/goobj", + "src/old", }; // setup sets up the tree for the initial build. @@ -590,7 +590,7 @@ static struct { "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libbio.a", "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/lib9.a", }}, - {"pkg/runtime", { + {"runtime", { "zaexperiment.h", // must sort above zasm "zasm_$GOOS_$GOARCH.h", "zsys_$GOOS_$GOARCH.s", @@ -607,7 +607,6 @@ char *depsuffix[] = { ".h", ".s", ".go", - ".goc", }; // gentab records how to generate some trivial files. @@ -639,7 +638,7 @@ install(char *dir) { char *name, *p, *elem, *prefix, *exe; bool islib, ispkg, isgo, stale, ispackcmd; - Buf b, b1, path; + Buf b, b1, path, final_path, final_name; Vec compile, files, link, go, missing, clean, lib, extra; Time ttarg, t; int i, j, k, n, doclean, targ; @@ -654,6 +653,8 @@ install(char *dir) binit(&b); binit(&b1); binit(&path); + binit(&final_path); + binit(&final_name); vinit(&compile); vinit(&files); vinit(&link); @@ -666,15 +667,9 @@ install(char *dir) // path = full path to dir. bpathf(&path, "%s/src/%s", goroot, dir); + bpathf(&final_path, "%s/src/%s", goroot_final, dir); name = lastelem(dir); - // For misc/prof, copy into the tool directory and we're done. - if(hasprefix(dir, "misc/")) { - copy(bpathf(&b, "%s/%s", tooldir, name), - bpathf(&b1, "%s/misc/%s", goroot, name), 1); - goto out; - } - // set up gcc command line on first run. if(gccargs.len == 0) { bprintf(&b, "%s %s", defaultcc, defaultcflags); @@ -704,7 +699,7 @@ install(char *dir) } islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc"); - ispkg = hasprefix(dir, "pkg"); + ispkg = !islib && !hasprefix(dir, "cmd/"); isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo"); exe = ""; @@ -730,11 +725,11 @@ install(char *dir) // Go library (package). ispackcmd = 1; vadd(&link, "pack"); // program name - unused here, but all the other cases record one - p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir+4); + p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir); *xstrrchr(p, '/') = '\0'; xmkdirall(p); targ = link.len; - vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir+4)); + vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir)); } else if(streq(dir, "cmd/go") || streq(dir, "cmd/cgo")) { // Go command. vadd(&link, bpathf(&b, "%s/%sl", tooldir, gochar)); @@ -881,18 +876,22 @@ install(char *dir) goto out; // For package runtime, copy some files into the work space. - if(streq(dir, "pkg/runtime")) { - copy(bpathf(&b, "%s/arch_GOARCH.h", workdir), + if(streq(dir, "runtime")) { + copyfile(bpathf(&b, "%s/arch_GOARCH.h", workdir), bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0); - copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir), + copyfile(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir), bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0); p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch); if(isfile(p)) - copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0); - copy(bpathf(&b, "%s/os_GOOS.h", workdir), + copyfile(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0); + copyfile(bpathf(&b, "%s/os_GOOS.h", workdir), bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0); - copy(bpathf(&b, "%s/signals_GOOS.h", workdir), + copyfile(bpathf(&b, "%s/signals_GOOS.h", workdir), bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0); + copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch), + bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0); + copyfile(bpathf(&b, "%s/pkg/%s_%s/funcdata.h", goroot, goos, goarch), + bpathf(&b1, "%s/src/runtime/funcdata.h", goroot), 0); } // Generate any missing files; regenerate existing ones. @@ -907,7 +906,7 @@ install(char *dir) errprintf("generate %s\n", p); gentab[j].gen(bstr(&path), p); // Do not add generated file to clean list. - // In pkg/runtime, we want to be able to + // In runtime, we want to be able to // build the package with the go tool, // and it assumes these generated files already // exist (it does not know how to build them). @@ -925,27 +924,11 @@ install(char *dir) // One more copy for package runtime. // The last batch was required for the generators. // This one is generated. - if(streq(dir, "pkg/runtime")) { - copy(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), + if(streq(dir, "runtime")) { + copyfile(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0); } - // Generate .c files from .goc files. - if(streq(dir, "pkg/runtime")) { - for(i=0; i 1) @@ -1086,7 +1069,7 @@ install(char *dir) else vadd(&compile, "main"); - if(streq(dir, "pkg/runtime")) + if(streq(dir, "runtime")) vadd(&compile, "-+"); vcopy(&compile, go.p, go.len); @@ -1115,11 +1098,11 @@ install(char *dir) nobuild: // In package runtime, we install runtime.h and cgocall.h too, // for use by cgo compilation. - if(streq(dir, "pkg/runtime")) { - copy(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch), - bpathf(&b1, "%s/src/pkg/runtime/cgocall.h", goroot), 0); - copy(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch), - bpathf(&b1, "%s/src/pkg/runtime/runtime.h", goroot), 0); + if(streq(dir, "runtime")) { + copyfile(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch), + bpathf(&b1, "%s/src/runtime/cgocall.h", goroot), 0); + copyfile(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch), + bpathf(&b1, "%s/src/runtime/runtime.h", goroot), 0); } @@ -1149,7 +1132,7 @@ matchfield(char *f) p = xstrrchr(f, ','); if(p == nil) - return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1"); + return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1") || (streq(goos, "android") && streq(f, "linux")); *p = 0; res = matchfield(f) && matchfield(p+1); *p = ','; @@ -1241,8 +1224,8 @@ out: } // copy copies the file src to dst, via memory (so only good for small files). -static void -copy(char *dst, char *src, int exec) +void +copyfile(char *dst, char *src, int exec) { Buf b; @@ -1303,8 +1286,6 @@ static char *buildorder[] = { "libbio", "liblink", - "misc/pprof", - "cmd/cc", // must be before c "cmd/gc", // must be before g "cmd/%sl", // must be before a, c, g @@ -1316,47 +1297,47 @@ static char *buildorder[] = { // back when there were build scripts. Will have to // be maintained by hand, but shouldn't change very // often. - "pkg/runtime", - "pkg/errors", - "pkg/sync/atomic", - "pkg/sync", - "pkg/io", - "pkg/unicode", - "pkg/unicode/utf8", - "pkg/unicode/utf16", - "pkg/bytes", - "pkg/math", - "pkg/strings", - "pkg/strconv", - "pkg/bufio", - "pkg/sort", - "pkg/container/heap", - "pkg/encoding/base64", - "pkg/syscall", - "pkg/time", - "pkg/os", - "pkg/reflect", - "pkg/fmt", - "pkg/encoding", - "pkg/encoding/json", - "pkg/flag", - "pkg/path/filepath", - "pkg/path", - "pkg/io/ioutil", - "pkg/log", - "pkg/regexp/syntax", - "pkg/regexp", - "pkg/go/token", - "pkg/go/scanner", - "pkg/go/ast", - "pkg/go/parser", - "pkg/os/exec", - "pkg/os/signal", - "pkg/net/url", - "pkg/text/template/parse", - "pkg/text/template", - "pkg/go/doc", - "pkg/go/build", + "runtime", + "errors", + "sync/atomic", + "sync", + "io", + "unicode", + "unicode/utf8", + "unicode/utf16", + "bytes", + "math", + "strings", + "strconv", + "bufio", + "sort", + "container/heap", + "encoding/base64", + "syscall", + "time", + "os", + "reflect", + "fmt", + "encoding", + "encoding/json", + "flag", + "path/filepath", + "path", + "io/ioutil", + "log", + "regexp/syntax", + "regexp", + "go/token", + "go/scanner", + "go/ast", + "go/parser", + "os/exec", + "os/signal", + "net/url", + "text/template/parse", + "text/template", + "go/doc", + "go/build", "cmd/go", }; @@ -1364,6 +1345,7 @@ static char *buildorder[] = { // It is bigger than the buildorder because we clean all the // compilers but build only the $GOARCH ones. static char *cleantab[] = { + // Commands and C libraries. "cmd/5a", "cmd/5c", "cmd/5g", @@ -1382,46 +1364,48 @@ static char *cleantab[] = { "lib9", "libbio", "liblink", - "pkg/bufio", - "pkg/bytes", - "pkg/container/heap", - "pkg/encoding", - "pkg/encoding/base64", - "pkg/encoding/json", - "pkg/errors", - "pkg/flag", - "pkg/fmt", - "pkg/go/ast", - "pkg/go/build", - "pkg/go/doc", - "pkg/go/parser", - "pkg/go/scanner", - "pkg/go/token", - "pkg/io", - "pkg/io/ioutil", - "pkg/log", - "pkg/math", - "pkg/net/url", - "pkg/os", - "pkg/os/exec", - "pkg/path", - "pkg/path/filepath", - "pkg/reflect", - "pkg/regexp", - "pkg/regexp/syntax", - "pkg/runtime", - "pkg/sort", - "pkg/strconv", - "pkg/strings", - "pkg/sync", - "pkg/sync/atomic", - "pkg/syscall", - "pkg/text/template", - "pkg/text/template/parse", - "pkg/time", - "pkg/unicode", - "pkg/unicode/utf16", - "pkg/unicode/utf8", + + // Go packages. + "bufio", + "bytes", + "container/heap", + "encoding", + "encoding/base64", + "encoding/json", + "errors", + "flag", + "fmt", + "go/ast", + "go/build", + "go/doc", + "go/parser", + "go/scanner", + "go/token", + "io", + "io/ioutil", + "log", + "math", + "net/url", + "os", + "os/exec", + "path", + "path/filepath", + "reflect", + "regexp", + "regexp/syntax", + "runtime", + "sort", + "strconv", + "strings", + "sync", + "sync/atomic", + "syscall", + "text/template", + "text/template/parse", + "time", + "unicode", + "unicode/utf16", + "unicode/utf8", }; static void @@ -1450,9 +1434,9 @@ clean(void) xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4)); } - // remove src/pkg/runtime/z* unconditionally + // remove src/runtime/z* unconditionally vreset(&dir); - bpathf(&path, "%s/src/pkg/runtime", goroot); + bpathf(&path, "%s/src/runtime", goroot); xreaddir(&dir, bstr(&path)); for(j=0; j 0) usage(); + if(isdir(bpathf(&b, "%s/src/pkg", goroot))) { + fatal("\n\n" + "The Go package sources have moved to $GOROOT/src.\n" + "*** %s still exists. ***\n" + "It probably contains stale files that may confuse the build.\n" + "Please (check what's there and) remove it and try again.\n" + "See http://golang.org/s/go14nopkg\n", bpathf(&b, "%s/src/pkg", goroot)); + } + if(rebuildall) clean(); goversion = findgoversion(); @@ -1619,9 +1612,9 @@ cmdbootstrap(int argc, char **argv) xsetenv("GOARCH", goarch); xsetenv("GOOS", goos); - // Build pkg/runtime for actual goos/goarch too. + // Build runtime for actual goos/goarch too. if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) - install("pkg/runtime"); + install("runtime"); bfree(&b); } diff --git a/src/cmd/dist/buildgc.c b/src/cmd/dist/buildgc.c index 1f0625daa..66adf6857 100644 --- a/src/cmd/dist/buildgc.c +++ b/src/cmd/dist/buildgc.c @@ -65,24 +65,35 @@ gcopnames(char *dir, char *file) // mkanames reads [568].out.h and writes anames[568].c // The format is much the same as the Go opcodes above. +// it also writes out cnames array for C_* constants. void mkanames(char *dir, char *file) { - int i, ch; - Buf in, b, out; + int i, j, ch; + Buf in, b, out, out2; Vec lines; char *p; binit(&b); binit(&in); binit(&out); + binit(&out2); vinit(&lines); ch = file[xstrlen(file)-3]; bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch); readfile(&in, bstr(&b)); splitlines(&lines, bstr(&in)); - bprintf(&out, "char* anames%c[] = {\n", ch); + + // Include link.h so that the extern declaration there is + // checked against the non-extern declaration we are generating. + bwritestr(&out, bprintf(&b, "#include \n")); + bwritestr(&out, bprintf(&b, "#include \n")); + bwritestr(&out, bprintf(&b, "#include \n")); + bwritestr(&out, bprintf(&b, "#include \n")); + bwritestr(&out, bprintf(&b, "\n")); + + bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch)); for(i=0; i0) + bwriteb(&out, &out2); + writefile(&out, file, 0); bfree(&b); bfree(&in); bfree(&out); + bfree(&out2); vfree(&lines); } diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c index ba5993b2f..bb774e05f 100644 --- a/src/cmd/dist/buildruntime.c +++ b/src/cmd/dist/buildruntime.c @@ -5,7 +5,7 @@ #include "a.h" /* - * Helpers for building pkg/runtime. + * Helpers for building runtime. */ // mkzversion writes zversion.go: @@ -30,7 +30,8 @@ mkzversion(char *dir, char *file) "package runtime\n" "\n" "const defaultGoroot = `%s`\n" - "const theVersion = `%s`\n", goroot_final, goversion)); + "const theVersion = `%s`\n" + "var buildVersion = theVersion\n", goroot_final, goversion)); writefile(&out, file, 0); @@ -108,10 +109,14 @@ mkzgoos(char *dir, char *file) binit(&b); binit(&out); + + bwritestr(&out, "// auto generated by go tool dist\n\n"); + + if(streq(goos, "linux")) { + bwritestr(&out, "// +build !android\n\n"); + } bwritestr(&out, bprintf(&b, - "// auto generated by go tool dist\n" - "\n" "package runtime\n" "\n" "const theGoos = `%s`\n", goos)); @@ -130,17 +135,14 @@ static struct { {"386", "", "#define get_tls(r) MOVL TLS, r\n" "#define g(r) 0(r)(TLS*1)\n" - "#define m(r) 4(r)(TLS*1)\n" }, {"amd64p32", "", "#define get_tls(r) MOVL TLS, r\n" "#define g(r) 0(r)(TLS*1)\n" - "#define m(r) 4(r)(TLS*1)\n" }, {"amd64", "", "#define get_tls(r) MOVQ TLS, r\n" "#define g(r) 0(r)(TLS*1)\n" - "#define m(r) 8(r)(TLS*1)\n" }, {"arm", "", @@ -160,11 +162,12 @@ mkzasm(char *dir, char *file) { int i, n; char *aggr, *p; - Buf in, b, out, exp; + Buf in, b, b1, out, exp; Vec argv, lines, fields; binit(&in); binit(&b); + binit(&b1); binit(&out); binit(&exp); vinit(&argv); @@ -172,6 +175,10 @@ mkzasm(char *dir, char *file) vinit(&fields); bwritestr(&out, "// auto generated by go tool dist\n\n"); + if(streq(goos, "linux")) { + bwritestr(&out, "// +build !android\n\n"); + } + for(i=0; inext; - xfree(p->name); - xfree(p->type); - xfree(p); - p = next; - } -} - -/* Read a character, tracking lineno. */ -static int -getchar_update_lineno(void) -{ - int c; - - c = xgetchar(); - if (c == '\n') - ++lineno; - return c; -} - -/* Read a character, giving an error on EOF, tracking lineno. */ -static int -getchar_no_eof(void) -{ - int c; - - c = getchar_update_lineno(); - if (c == EOF) - bad_eof(); - return c; -} - -/* Read a character, skipping comments. */ -static int -getchar_skipping_comments(void) -{ - int c; - - while (1) { - c = getchar_update_lineno(); - if (c != '/') - return c; - - c = xgetchar(); - if (c == '/') { - do { - c = getchar_update_lineno(); - } while (c != EOF && c != '\n'); - return c; - } else if (c == '*') { - while (1) { - c = getchar_update_lineno(); - if (c == EOF) - return EOF; - if (c == '*') { - do { - c = getchar_update_lineno(); - } while (c == '*'); - if (c == '/') - break; - } - } - } else { - xungetc(); - return '/'; - } - } -} - -/* - * Read and return a token. Tokens are string or character literals - * or else delimited by whitespace or by [(),{}]. - * The latter are all returned as single characters. - */ -static char * -read_token(void) -{ - int c, q; - char *buf; - unsigned int alc, off; - char* delims = "(),{}"; - - while (1) { - c = getchar_skipping_comments(); - if (c == EOF) - return nil; - if (!xisspace(c)) - break; - } - alc = 16; - buf = xmalloc(alc + 1); - off = 0; - if(c == '"' || c == '\'') { - q = c; - buf[off] = c; - ++off; - while (1) { - if (off+2 >= alc) { // room for c and maybe next char - alc *= 2; - buf = xrealloc(buf, alc + 1); - } - c = getchar_no_eof(); - buf[off] = c; - ++off; - if(c == q) - break; - if(c == '\\') { - buf[off] = getchar_no_eof(); - ++off; - } - } - } else if (xstrrchr(delims, c) != nil) { - buf[off] = c; - ++off; - } else { - while (1) { - if (off >= alc) { - alc *= 2; - buf = xrealloc(buf, alc + 1); - } - buf[off] = c; - ++off; - c = getchar_skipping_comments(); - if (c == EOF) - break; - if (xisspace(c) || xstrrchr(delims, c) != nil) { - if (c == '\n') - lineno--; - xungetc(); - break; - } - } - } - buf[off] = '\0'; - return buf; -} - -/* Read a token, giving an error on EOF. */ -static char * -read_token_no_eof(void) -{ - char *token = read_token(); - if (token == nil) - bad_eof(); - return token; -} - -/* Read the package clause, and return the package name. */ -static char * -read_package(void) -{ - char *token; - - token = read_token_no_eof(); - if (token == nil) - fatal("%s:%d: no token\n", file, lineno); - if (!streq(token, "package")) { - fatal("%s:%d: expected \"package\", got \"%s\"\n", - file, lineno, token); - } - return read_token_no_eof(); -} - -/* Read and copy preprocessor lines. */ -static void -read_preprocessor_lines(void) -{ - int first; - - first = 1; - while (1) { - int c; - - do { - c = getchar_skipping_comments(); - } while (xisspace(c)); - if (c != '#') { - xungetc(); - break; - } - if(first) { - first = 0; - xputchar('\n'); - } - xputchar(c); - do { - c = getchar_update_lineno(); - xputchar(c); - } while (c != '\n'); - } -} - -/* - * Read a type in Go syntax and return a type in C syntax. We only - * permit basic types and pointers. - */ -static char * -read_type(void) -{ - char *p, *op, *q; - int pointer_count; - unsigned int len; - - p = read_token_no_eof(); - if (*p != '*' && !streq(p, "int") && !streq(p, "uint")) - return p; - op = p; - pointer_count = 0; - while (*p == '*') { - ++pointer_count; - ++p; - } - len = xstrlen(p); - q = xmalloc(len + 2 + pointer_count + 1); - xmemmove(q, p, len); - - // Turn int/uint into intgo/uintgo. - if((len == 3 && xmemcmp(q, "int", 3) == 0) || (len == 4 && xmemcmp(q, "uint", 4) == 0)) { - q[len++] = 'g'; - q[len++] = 'o'; - } - - while (pointer_count-- > 0) - q[len++] = '*'; - - q[len] = '\0'; - xfree(op); - return q; -} - -/* Return the size of the given type. */ -static int -type_size(char *p, int *rnd) -{ - int i; - - if(p[xstrlen(p)-1] == '*') { - *rnd = type_table[Uintptr].rnd; - return type_table[Uintptr].size; - } - - if(streq(p, "Iface")) - p = "Eface"; - - for(i=0; type_table[i].name; i++) - if(streq(type_table[i].name, p)) { - *rnd = type_table[i].rnd; - return type_table[i].size; - } - fatal("%s:%d: unknown type %s\n", file, lineno, p); - return 0; -} - -/* - * Read a list of parameters. Each parameter is a name and a type. - * The list ends with a ')'. We have already read the '('. - */ -static struct params * -read_params(int *poffset) -{ - char *token; - struct params *ret, **pp, *p; - int offset, size, rnd; - - ret = nil; - pp = &ret; - token = read_token_no_eof(); - offset = 0; - if (!streq(token, ")")) { - while (1) { - p = xmalloc(sizeof(struct params)); - p->name = token; - p->next = nil; - *pp = p; - pp = &p->next; - - if(streq(token, "...")) { - p->type = xstrdup(""); - } else { - p->type = read_type(); - rnd = 0; - size = type_size(p->type, &rnd); - if(rnd > structround) - rnd = structround; - if(offset%rnd) - offset += rnd - offset%rnd; - offset += size; - } - - token = read_token_no_eof(); - if (!streq(token, ",")) - break; - token = read_token_no_eof(); - } - } - if (!streq(token, ")")) { - fatal("%s:%d: expected '('\n", - file, lineno); - } - if (poffset != nil) - *poffset = offset; - return ret; -} - -/* - * Read a function header. This reads up to and including the initial - * '{' character. Returns 1 if it read a header, 0 at EOF. - */ -static int -read_func_header(char **name, struct params **params, int *paramwid, struct params **rets) -{ - int lastline; - char *token; - - lastline = -1; - while (1) { - read_preprocessor_lines(); - token = read_token(); - if (token == nil) - return 0; - if (streq(token, "func")) { - if(lastline != -1) - bwritef(output, "\n"); - break; - } - if (lastline != lineno) { - if (lastline == lineno-1) - bwritef(output, "\n"); - else - bwritef(output, "\n#line %d \"%s\"\n", lineno, file); - lastline = lineno; - } - bwritef(output, "%s ", token); - } - - *name = read_token_no_eof(); - - token = read_token(); - if (token == nil || !streq(token, "(")) { - fatal("%s:%d: expected \"(\"\n", - file, lineno); - } - *params = read_params(paramwid); - - token = read_token(); - if (token == nil || !streq(token, "(")) - *rets = nil; - else { - *rets = read_params(nil); - token = read_token(); - } - if (token == nil || !streq(token, "{")) { - fatal("%s:%d: expected \"{\"\n", - file, lineno); - } - return 1; -} - -/* Write out parameters. */ -static void -write_params(struct params *params, int *first) -{ - struct params *p; - - for (p = params; p != nil; p = p->next) { - if (*first) - *first = 0; - else - bwritef(output, ", "); - bwritef(output, "%s %s", p->type, p->name); - } -} - -/* Write a 6g function header. */ -static void -write_6g_func_header(char *package, char *name, struct params *params, - int paramwid, struct params *rets) -{ - int first, n; - struct params *p; - - bwritef(output, "void\n"); - if(!contains(name, "·")) - bwritef(output, "%s·", package); - bwritef(output, "%s(", name); - - first = 1; - write_params(params, &first); - - /* insert padding to align output struct */ - if(rets != nil && paramwid%structround != 0) { - n = structround - paramwid%structround; - if(n & 1) - bwritef(output, ", uint8"); - if(n & 2) - bwritef(output, ", uint16"); - if(n & 4) - bwritef(output, ", uint32"); - } - - write_params(rets, &first); - bwritef(output, ")\n{\n"); - - for (p = rets; p != nil; p = p->next) { - if(streq(p->name, "...")) - continue; - if(streq(p->type, "Slice")) - bwritef(output, "\t%s.array = 0;\n\t%s.len = 0;\n\t%s.cap = 0;\n", p->name, p->name, p->name); - else if(streq(p->type, "String")) - bwritef(output, "\t%s.str = 0;\n\t%s.len = 0;\n", p->name, p->name); - else if(streq(p->type, "Eface")) - bwritef(output, "\t%s.type = 0;\n\t%s.data = 0;\n", p->name, p->name); - else if(streq(p->type, "Iface")) - bwritef(output, "\t%s.tab = 0;\n\t%s.data = 0;\n", p->name, p->name); - else if(streq(p->type, "Complex128")) - bwritef(output, "\t%s.real = 0;\n\t%s.imag = 0;\n", p->name, p->name); - else - bwritef(output, "\t%s = 0;\n", p->name); - bwritef(output, "\tFLUSH(&%s);\n", p->name); - } -} - -/* Write a 6g function trailer. */ -static void -write_6g_func_trailer(struct params *rets) -{ - struct params *p; - - for (p = rets; p != nil; p = p->next) - if(!streq(p->name, "...")) - bwritef(output, "\tFLUSH(&%s);\n", p->name); - bwritef(output, "}\n"); -} - -/* Define the gcc function return type if necessary. */ -static void -define_gcc_return_type(char *package, char *name, struct params *rets) -{ - struct params *p; - - if (rets == nil || rets->next == nil) - return; - bwritef(output, "struct %s_%s_ret {\n", package, name); - for (p = rets; p != nil; p = p->next) - bwritef(output, " %s %s;\n", p->type, p->name); - bwritef(output, "};\n"); -} - -/* Write out the gcc function return type. */ -static void -write_gcc_return_type(char *package, char *name, struct params *rets) -{ - if (rets == nil) - bwritef(output, "void"); - else if (rets->next == nil) - bwritef(output, "%s", rets->type); - else - bwritef(output, "struct %s_%s_ret", package, name); -} - -/* Write out a gcc function header. */ -static void -write_gcc_func_header(char *package, char *name, struct params *params, - struct params *rets) -{ - int first; - struct params *p; - - define_gcc_return_type(package, name, rets); - write_gcc_return_type(package, name, rets); - bwritef(output, " %s_%s(", package, name); - first = 1; - write_params(params, &first); - bwritef(output, ") asm (\"%s.%s\");\n", package, name); - write_gcc_return_type(package, name, rets); - bwritef(output, " %s_%s(", package, name); - first = 1; - write_params(params, &first); - bwritef(output, ")\n{\n"); - for (p = rets; p != nil; p = p->next) - bwritef(output, " %s %s;\n", p->type, p->name); -} - -/* Write out a gcc function trailer. */ -static void -write_gcc_func_trailer(char *package, char *name, struct params *rets) -{ - if (rets == nil) { - // nothing to do - } - else if (rets->next == nil) - bwritef(output, "return %s;\n", rets->name); - else { - struct params *p; - - bwritef(output, " {\n struct %s_%s_ret __ret;\n", package, name); - for (p = rets; p != nil; p = p->next) - bwritef(output, " __ret.%s = %s;\n", p->name, p->name); - bwritef(output, " return __ret;\n }\n"); - } - bwritef(output, "}\n"); -} - -/* Write out a function header. */ -static void -write_func_header(char *package, char *name, - struct params *params, int paramwid, - struct params *rets) -{ - if (gcc) - write_gcc_func_header(package, name, params, rets); - else - write_6g_func_header(package, name, params, paramwid, rets); - bwritef(output, "#line %d \"%s\"\n", lineno, file); -} - -/* Write out a function trailer. */ -static void -write_func_trailer(char *package, char *name, - struct params *rets) -{ - if (gcc) - write_gcc_func_trailer(package, name, rets); - else - write_6g_func_trailer(rets); -} - -/* - * Read and write the body of the function, ending in an unnested } - * (which is read but not written). - */ -static void -copy_body(void) -{ - int nesting = 0; - while (1) { - int c; - - c = getchar_no_eof(); - if (c == '}' && nesting == 0) - return; - xputchar(c); - switch (c) { - default: - break; - case '{': - ++nesting; - break; - case '}': - --nesting; - break; - case '/': - c = getchar_update_lineno(); - xputchar(c); - if (c == '/') { - do { - c = getchar_no_eof(); - xputchar(c); - } while (c != '\n'); - } else if (c == '*') { - while (1) { - c = getchar_no_eof(); - xputchar(c); - if (c == '*') { - do { - c = getchar_no_eof(); - xputchar(c); - } while (c == '*'); - if (c == '/') - break; - } - } - } - break; - case '"': - case '\'': - { - int delim = c; - do { - c = getchar_no_eof(); - xputchar(c); - if (c == '\\') { - c = getchar_no_eof(); - xputchar(c); - c = '\0'; - } - } while (c != delim); - } - break; - } - } -} - -/* Process the entire file. */ -static void -process_file(void) -{ - char *package, *name, *p, *n; - struct params *params, *rets; - int paramwid; - - package = read_package(); - read_preprocessor_lines(); - while (read_func_header(&name, ¶ms, ¶mwid, &rets)) { - // name may have a package override already - n = xstrstr(name, "·"); - if(n != nil) { - p = xmalloc(n - name + 1); - xmemmove(p, name, n - name); - p[n - name] = 0; - n += xstrlen("·"); - } else { - p = package; - n = name; - } - write_func_header(p, n, params, paramwid, rets); - copy_body(); - write_func_trailer(p, n, rets); - xfree(name); - if(p != package) xfree(p); - free_params(params); - free_params(rets); - } - xfree(package); -} - -void -goc2c(char *goc, char *c) -{ - int i; - Buf in, out; - - binit(&in); - binit(&out); - - file = goc; - readfile(&in, goc); - - // TODO: set gcc=1 when using gcc - - if(!gcc) { - if(streq(goarch, "amd64")) { - type_table[Uintptr].size = 8; - if(use64bitint) { - type_table[Int].size = 8; - } else { - type_table[Int].size = 4; - } - structround = 8; - } else if(streq(goarch, "amd64p32")) { - type_table[Uintptr].size = 4; - type_table[Int].size = 4; - structround = 8; - } else { - // NOTE: These are set in the initializer, - // but they might have been changed by a - // previous invocation of goc2c, so we have - // to restore them. - type_table[Uintptr].size = 4; - type_table[Int].size = 4; - structround = 4; - } - - type_table[Uint].size = type_table[Int].size; - type_table[Slice].size = type_table[Uintptr].size+2*type_table[Int].size; - type_table[Eface].size = 2*type_table[Uintptr].size; - type_table[String].size = 2*type_table[Uintptr].size; - - for(i=0; i= ns && strcmp(p+np-ns, suffix) == 0; + return np >= ns && streq(p+np-ns, suffix); } // hasprefix reports whether p begins with prefix. diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c index 8b943a2d9..4a78684b4 100644 --- a/src/cmd/dist/unix.c +++ b/src/cmd/dist/unix.c @@ -431,7 +431,7 @@ xremoveall(char *p) } bfree(&b); - vfree(&dir); + vfree(&dir); } // xreaddir replaces dst with a list of the names of the files in dir. @@ -441,13 +441,13 @@ xreaddir(Vec *dst, char *dir) { DIR *d; struct dirent *dp; - + vreset(dst); d = opendir(dir); if(d == nil) fatal("opendir %s: %s", dir, strerror(errno)); while((dp = readdir(d)) != nil) { - if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) + if(streq(dp->d_name, ".") || streq(dp->d_name, "..")) continue; vadd(dst, dp->d_name); } @@ -461,7 +461,7 @@ xworkdir(void) { Buf b; char *p; - + binit(&b); xgetenv(&b, "TMPDIR"); @@ -546,10 +546,10 @@ bool hassuffix(char *p, char *suffix) { int np, ns; - + np = strlen(p); ns = strlen(suffix); - return np >= ns && strcmp(p+np-ns, suffix) == 0; + return np >= ns && streq(p+np-ns, suffix); } // hasprefix reports whether p begins with prefix. @@ -712,7 +712,7 @@ main(int argc, char **argv) fatal("unknown architecture: %s", u.machine); } - if(strcmp(gohostarch, "arm") == 0) + if(streq(gohostarch, "arm")) maxnbg = 1; // The OS X 10.6 linker does not support external linking mode. @@ -724,7 +724,7 @@ main(int argc, char **argv) // // Roughly, OS X 10.N shows up as uname release (N+4), // so OS X 10.6 is uname version 10 and OS X 10.8 is uname version 12. - if(strcmp(gohostos, "darwin") == 0) { + if(streq(gohostos, "darwin")) { if(uname(&u) < 0) fatal("uname: %s", strerror(errno)); osx = atoi(u.release) - 4; diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c index 2839c4bc5..ff1a27351 100644 --- a/src/cmd/dist/windows.c +++ b/src/cmd/dist/windows.c @@ -770,10 +770,10 @@ bool hassuffix(char *p, char *suffix) { int np, ns; - + np = strlen(p); ns = strlen(suffix); - return np >= ns && strcmp(p+np-ns, suffix) == 0; + return np >= ns && streq(p+np-ns, suffix); } bool @@ -929,7 +929,7 @@ xsamefile(char *f1, char *f2) return 1; torune(&ru, f1); - // refer to ../../pkg/os/stat_windows.go:/sameFile + // refer to ../../os/stat_windows.go:/sameFile fd1 = CreateFileW(ru, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); xfree(ru); if(fd1 == INVALID_HANDLE_VALUE) diff --git a/src/cmd/fix/doc.go b/src/cmd/fix/doc.go index 5de3e08c5..057016957 100644 --- a/src/cmd/fix/doc.go +++ b/src/cmd/fix/doc.go @@ -27,7 +27,7 @@ rewrites are idempotent, so that it is safe to apply fix to updated or partially updated code even without using the -r flag. Fix prints the full list of fixes it can apply in its help output; -to see them, run go tool fix -?. +to see them, run go tool fix -help. Fix does not make backup copies of the files that it edits. Instead, use a version control system's ``diff'' functionality to inspect diff --git a/src/cmd/fix/fix.go b/src/cmd/fix/fix.go index a100be794..a07bbac79 100644 --- a/src/cmd/fix/fix.go +++ b/src/cmd/fix/fix.go @@ -101,7 +101,7 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) { case *[]ast.Stmt: walkBeforeAfter(*n, before, after) - // These are ordered and grouped to match ../../pkg/go/ast/ast.go + // These are ordered and grouped to match ../../go/ast/ast.go case *ast.Field: walkBeforeAfter(&n.Names, before, after) walkBeforeAfter(&n.Type, before, after) diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c index b809640e4..6e5d149c7 100644 --- a/src/cmd/gc/align.c +++ b/src/cmd/gc/align.c @@ -119,8 +119,10 @@ dowidth(Type *t) if(t->width == -2) { lno = lineno; lineno = t->lineno; - if(!t->broke) + if(!t->broke) { + t->broke = 1; yyerror("invalid recursive type %T", t); + } t->width = 0; lineno = lno; return; diff --git a/src/cmd/gc/bisonerrors b/src/cmd/gc/bisonerrors index 1f97fc8ce..fa74c67c3 100755 --- a/src/cmd/gc/bisonerrors +++ b/src/cmd/gc/bisonerrors @@ -22,6 +22,7 @@ BEGIN{ bison = 1 grammar = 0 states = 0 + open = 0 } # In Grammar section of y.output, @@ -130,11 +131,26 @@ $1 == "%" { continue # No shift or reduce applied - found the error. - printf("\t%s, %s,\n", state, tok); + printf("\t{%s, %s,\n", state, tok); + open = 1; break } next } # Print other lines verbatim. +open && /,$/ { + s = $0; + sub(",", "},", s) + print s + open = 0 + next +} + +open && /"$/ { + print $0 "}" + open = 0 + next +} + {print} diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c index 5ca5aeb77..fbca4ee5f 100644 --- a/src/cmd/gc/builtin.c +++ b/src/cmd/gc/builtin.c @@ -2,18 +2,19 @@ char *runtimeimport = "package runtime\n" "import runtime \"runtime\"\n" - "func @\"\".new (@\"\".typ·2 *byte) (? *any)\n" + "func @\"\".newobject (@\"\".typ·2 *byte) (? *any)\n" "func @\"\".panicindex ()\n" "func @\"\".panicslice ()\n" "func @\"\".panicdivide ()\n" "func @\"\".throwreturn ()\n" "func @\"\".throwinit ()\n" "func @\"\".panicwrap (? string, ? string, ? string)\n" - "func @\"\".panic (? interface {})\n" - "func @\"\".recover (? *int32) (? interface {})\n" + "func @\"\".gopanic (? interface {})\n" + "func @\"\".gorecover (? *int32) (? interface {})\n" "func @\"\".printbool (? bool)\n" "func @\"\".printfloat (? float64)\n" "func @\"\".printint (? int64)\n" + "func @\"\".printhex (? uint64)\n" "func @\"\".printuint (? uint64)\n" "func @\"\".printcomplex (? complex128)\n" "func @\"\".printstring (? string)\n" @@ -23,7 +24,6 @@ char *runtimeimport = "func @\"\".printslice (? any)\n" "func @\"\".printnl ()\n" "func @\"\".printsp ()\n" - "func @\"\".goprintf ()\n" "func @\"\".concatstring2 (? string, ? string) (? string)\n" "func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n" "func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n" @@ -39,7 +39,7 @@ char *runtimeimport = "func @\"\".stringtoslicerune (? string) (? []rune)\n" "func @\"\".stringiter (? string, ? int) (? int)\n" "func @\"\".stringiter2 (? string, ? int) (@\"\".retk·1 int, @\"\".retv·2 rune)\n" - "func @\"\".copy (@\"\".to·2 any, @\"\".fr·3 any, @\"\".wid·4 uintptr) (? int)\n" + "func @\"\".slicecopy (@\"\".to·2 any, @\"\".fr·3 any, @\"\".wid·4 uintptr) (? int)\n" "func @\"\".slicestringcopy (@\"\".to·2 any, @\"\".fr·3 any) (? int)\n" "func @\"\".typ2Itab (@\"\".typ·2 *byte, @\"\".typ2·3 *byte, @\"\".cache·4 **byte) (@\"\".ret·1 *byte)\n" "func @\"\".convI2E (@\"\".elem·2 any) (@\"\".ret·1 any)\n" @@ -64,7 +64,6 @@ char *runtimeimport = "func @\"\".efaceeq (@\"\".i1·2 any, @\"\".i2·3 any) (@\"\".ret·1 bool)\n" "func @\"\".ifacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n" "func @\"\".efacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n" - "func @\"\".equal (@\"\".typ·2 *byte, @\"\".x1·3 any, @\"\".x2·4 any) (@\"\".ret·1 bool)\n" "func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64) (@\"\".hmap·1 map[any]any)\n" "func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 *any) (@\"\".val·1 *any)\n" "func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n" @@ -83,10 +82,18 @@ char *runtimeimport = "func @\"\".chanrecv2 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (? bool)\n" "func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 *any)\n" "func @\"\".closechan (@\"\".hchan·1 any)\n" + "func @\"\".writebarrierptr (@\"\".dst·1 *any, @\"\".src·2 any)\n" + "func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n" + "func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n" + "func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n" + "func @\"\".writebarrierfat2 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat3 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat4 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n" "func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n" "func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n" "func @\"\".selectnbrecv2 (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".received·4 *bool, @\"\".hchan·5 <-chan any) (? bool)\n" - "func @\"\".newselect (@\"\".size·2 int32) (@\"\".sel·1 *byte)\n" + "func @\"\".newselect (@\"\".sel·1 *byte, @\"\".selsize·2 int64, @\"\".size·3 int32)\n" "func @\"\".selectsend (@\"\".sel·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (@\"\".selected·1 bool)\n" "func @\"\".selectrecv (@\"\".sel·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (@\"\".selected·1 bool)\n" "func @\"\".selectrecv2 (@\"\".sel·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any, @\"\".received·5 *bool) (@\"\".selected·1 bool)\n" @@ -96,12 +103,12 @@ char *runtimeimport = "func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n" "func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int64) (@\"\".ary·1 []any)\n" "func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr)\n" - "func @\"\".memequal (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n" - "func @\"\".memequal8 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n" - "func @\"\".memequal16 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n" - "func @\"\".memequal32 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n" - "func @\"\".memequal64 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n" - "func @\"\".memequal128 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n" + "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" + "func @\"\".memequal8 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" + "func @\"\".memequal16 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" + "func @\"\".memequal32 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" + "func @\"\".memequal64 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" + "func @\"\".memequal128 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" "func @\"\".int64div (? int64, ? int64) (? int64)\n" "func @\"\".uint64div (? uint64, ? uint64) (? uint64)\n" "func @\"\".int64mod (? int64, ? int64) (? int64)\n" diff --git a/src/cmd/gc/bv.c b/src/cmd/gc/bv.c index 0e8f8d473..cfd1cd281 100644 --- a/src/cmd/gc/bv.c +++ b/src/cmd/gc/bv.c @@ -108,6 +108,9 @@ bvnext(Bvec *bv, int32 i) { uint32 w; + if(i >= bv->n) + return -1; + // Jump i ahead to next word with bits. if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) { i &= ~WORDMASK; @@ -117,7 +120,7 @@ bvnext(Bvec *bv, int32 i) } if(i >= bv->n) return -1; - + // Find 1 bit. w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK); while((w&1) == 0) { diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c index 143c1730d..e418b9c56 100644 --- a/src/cmd/gc/const.c +++ b/src/cmd/gc/const.c @@ -6,6 +6,7 @@ #include #include "go.h" #define TUP(x,y) (((x)<<16)|(y)) +/*c2go int TUP(int, int); */ static Val tocplx(Val); static Val toflt(Val); @@ -1565,7 +1566,6 @@ isgoconst(Node *n) case ORSH: case OSUB: case OXOR: - case OCONV: case OIOTA: case OCOMPLEX: case OREAL: @@ -1573,7 +1573,12 @@ isgoconst(Node *n) if(isgoconst(n->left) && (n->right == N || isgoconst(n->right))) return 1; break; - + + case OCONV: + if(okforconst[n->type->etype] && isgoconst(n->left)) + return 1; + break; + case OLEN: case OCAP: l = n->left; diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index 73c2581be..dfcf47520 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -488,6 +488,10 @@ colasdefn(NodeList *left, Node *defn) NodeList *l; Node *n; + for(l=left; l; l=l->next) + if(l->n->sym != S) + l->n->sym->flags |= SymUniq; + nnew = 0; nerr = 0; for(l=left; l; l=l->next) { @@ -499,6 +503,13 @@ colasdefn(NodeList *left, Node *defn) nerr++; continue; } + if((n->sym->flags & SymUniq) == 0) { + yyerrorl(defn->lineno, "%S repeated on left side of :=", n->sym); + n->diag++; + nerr++; + continue; + } + n->sym->flags &= ~SymUniq; if(n->sym->block == block) continue; @@ -547,6 +558,9 @@ ifacedcl(Node *n) if(n->op != ODCLFIELD || n->right == N) fatal("ifacedcl"); + if(isblank(n->left)) + yyerror("methods must have a unique non-blank name"); + dclcontext = PPARAM; markdcl(); funcdepth++; diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c index 78624d7cb..324f24fcf 100644 --- a/src/cmd/gc/esc.c +++ b/src/cmd/gc/esc.c @@ -495,7 +495,7 @@ esc(EscState *e, Node *n, Node *up) case ORANGE: // Everything but fixed array is a dereference. - if(isfixedarray(n->type) && n->list->next) + if(isfixedarray(n->type) && n->list && n->list->next) escassign(e, n->list->next->n, n->right); break; @@ -1110,6 +1110,7 @@ escflood(EscState *e, Node *dst) // pass all the tests we have written so far, which we assume matches // the level of complexity we want the escape analysis code to handle. #define MinLevel (-2) +/*c2go enum { MinLevel = -2 };*/ static void escwalk(EscState *e, int level, Node *dst, Node *src) diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c index b5f8a834f..89d2a1404 100644 --- a/src/cmd/gc/fmt.c +++ b/src/cmd/gc/fmt.c @@ -649,7 +649,7 @@ typefmt(Fmt *fp, Type *t) if(t->funarg) { fmtstrcpy(fp, "("); - if(fmtmode == FTypeId || fmtmode == FErr) { // no argument names on function signature, and no "noescape" tags + if(fmtmode == FTypeId || fmtmode == FErr) { // no argument names on function signature, and no "noescape"/"nosplit" tags for(t1=t->type; t1!=T; t1=t1->down) if(t1->down) fmtprint(fp, "%hT, ", t1); @@ -810,6 +810,13 @@ stmtfmt(Fmt *f, Node *n) break; case OASOP: + if(n->implicit) { + if(n->etype == OADD) + fmtprint(f, "%N++", n->left); + else + fmtprint(f, "%N--", n->left); + break; + } fmtprint(f, "%N %#O= %N", n->left, n->etype, n->right); break; @@ -880,7 +887,11 @@ stmtfmt(Fmt *f, Node *n) fmtstrcpy(f, "for loop"); break; } - + + if(n->list == nil) { + fmtprint(f, "for range %N { %H }", n->right, n->nbody); + break; + } fmtprint(f, "for %,H = range %N { %H }", n->list, n->right, n->nbody); break; @@ -974,7 +985,6 @@ static int opprec[] = { [OTFUNC] = 8, [OTINTER] = 8, [OTMAP] = 8, - [OTPAREN] = 8, [OTSTRUCT] = 8, [OINDEXMAP] = 8, @@ -1105,16 +1115,11 @@ exprfmt(Fmt *f, Node *n, int prec) case ONAME: // Special case: name used as local variable in export. - switch(n->class&~PHEAP){ - case PAUTO: - case PPARAM: - case PPARAMOUT: - // _ becomes ~b%d internally; print as _ for export - if(fmtmode == FExp && n->sym && n->sym->name[0] == '~' && n->sym->name[1] == 'b') - return fmtprint(f, "_"); - if(fmtmode == FExp && n->sym && !isblank(n) && n->vargen > 0) - return fmtprint(f, "%S·%d", n->sym, n->vargen); - } + // _ becomes ~b%d internally; print as _ for export + if(fmtmode == FExp && n->sym && n->sym->name[0] == '~' && n->sym->name[1] == 'b') + return fmtprint(f, "_"); + if(fmtmode == FExp && n->sym && !isblank(n) && n->vargen > 0) + return fmtprint(f, "%S·%d", n->sym, n->vargen); // Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method, // but for export, this should be rendered as (*pkg.T).meth. @@ -1140,9 +1145,6 @@ exprfmt(Fmt *f, Node *n, int prec) return fmtprint(f, "[]%N", n->left); return fmtprint(f, "[]%N", n->right); // happens before typecheck - case OTPAREN: - return fmtprint(f, "(%N)", n->left); - case OTMAP: return fmtprint(f, "map[%N]%N", n->left, n->right); @@ -1153,7 +1155,7 @@ exprfmt(Fmt *f, Node *n, int prec) case Csend: return fmtprint(f, "chan<- %N", n->left); default: - if(n->left != N && n->left->op == TCHAN && n->left->sym == S && n->left->etype == Crecv) + if(n->left != N && n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv) return fmtprint(f, "chan (%N)", n->left); else return fmtprint(f, "chan %N", n->left); diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index cf630f348..c7c9fcdaf 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -54,9 +54,6 @@ addrescapes(Node *n) if(n->class == PAUTO && n->esc == EscNever) break; - if(debug['N'] && n->esc != EscUnknown) - fatal("without escape analysis, only PAUTO's should have esc: %N", n); - switch(n->class) { case PPARAMREF: addrescapes(n->defn); @@ -91,8 +88,7 @@ addrescapes(Node *n) snprint(buf, sizeof buf, "&%S", n->sym); n->heapaddr->sym = lookup(buf); n->heapaddr->orig->sym = n->heapaddr->sym; - if(!debug['N']) - n->esc = EscHeap; + n->esc = EscHeap; if(debug['m']) print("%L: moved to heap: %N\n", n->lineno, n); curfn = oldfn; @@ -584,6 +580,8 @@ cgen_dcl(Node *n) } if(!(n->class & PHEAP)) return; + if(compiling_runtime) + yyerror("%N escapes to heap, not allowed in runtime.", n); if(n->alloc == nil) n->alloc = callnew(n->type); cgen_as(n->heapaddr, n->alloc); @@ -733,14 +731,10 @@ cgen_as(Node *nl, Node *nr) return; } - if(nr == N || isnil(nr)) { - // externals and heaps should already be clear - if(nr == N) { - if(nl->class == PEXTERN) - return; - if(nl->class & PHEAP) - return; - } + if(nr == N || iszero(nr)) { + // heaps should already be clear + if(nr == N && (nl->class & PHEAP)) + return; tl = nl->type; if(tl == T) @@ -804,7 +798,8 @@ cgen_eface(Node *n, Node *res) void cgen_slice(Node *n, Node *res) { - Node src, dst, *cap, *len, *offs, *add, *base; + Node src, dst, *cap, *len, *offs, *add, *base, *tmpcap, *tmplen, *cmp, con; + Prog *p1, *p2; cap = n->list->n; len = n->list->next->n; @@ -821,6 +816,11 @@ cgen_slice(Node *n, Node *res) // garbage collector can see. base = temp(types[TUINTPTR]); + tmplen = temp(types[TINT]); + if(n->op != OSLICESTR) + tmpcap = temp(types[TINT]); + else + tmpcap = tmplen; if(isnil(n->left)) { tempname(&src, n->left->type); @@ -835,43 +835,62 @@ cgen_slice(Node *n, Node *res) fatal("slicearr is supposed to work on pointer: %+N\n", n); cgen(&src, base); cgen_checknil(base); - if(offs != N) { - add = nod(OADD, base, offs); - typecheck(&add, Erv); - cgen(add, base); - } - } else if(offs == N) { - src.type = types[tptr]; - cgen(&src, base); } else { src.type = types[tptr]; - add = nod(OADDPTR, &src, offs); - typecheck(&add, Erv); - cgen(add, base); + cgen(&src, base); } // committed to the update gvardef(res); + // compute len and cap. + // len = n-i, cap = m-i, and offs = i*width. + // computing offs last lets the multiply overwrite i. + cgen(len, tmplen); + if(n->op != OSLICESTR) + cgen(cap, tmpcap); + + // if new cap != 0 { base += add } + // This avoids advancing base past the end of the underlying array/string, + // so that it cannot point at the next object in memory. + // If cap == 0, the base doesn't matter except insofar as it is 0 or non-zero. + // In essence we are replacing x[i:j:k] where i == j == k + // or x[i:j] where i == j == cap(x) with x[0:0:0]. + if(offs != N) { + p1 = gjmp(P); + p2 = gjmp(P); + patch(p1, pc); + + nodconst(&con, tmpcap->type, 0); + cmp = nod(OEQ, tmpcap, &con); + typecheck(&cmp, Erv); + bgen(cmp, 1, -1, p2); + + add = nod(OADD, base, offs); + typecheck(&add, Erv); + cgen(add, base); + + patch(p2, pc); + } + // dst.array = src.array [ + lo *width ] dst = *res; dst.xoffset += Array_array; dst.type = types[tptr]; - cgen(base, &dst); // dst.len = hi [ - lo ] dst = *res; dst.xoffset += Array_nel; dst.type = types[simtype[TUINT]]; - cgen(len, &dst); + cgen(tmplen, &dst); if(n->op != OSLICESTR) { // dst.cap = cap [ - lo ] dst = *res; dst.xoffset += Array_cap; dst.type = types[simtype[TUINT]]; - cgen(cap, &dst); + cgen(tmpcap, &dst); } } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index ee879f67f..965a0550d 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -269,6 +269,7 @@ struct Node uchar colas; // OAS resulting from := uchar diag; // already printed error about this uchar noescape; // func arguments do not escape + uchar nosplit; // func should not execute on separate stack uchar builtin; // built-in name, like len or close uchar walkdef; uchar typecheck; @@ -282,6 +283,7 @@ struct Node uchar addrtaken; // address taken, even if not moved to heap uchar dupok; // duplicate definitions ok (for func) uchar wrapper; // is method wrapper (for func) + uchar reslice; // this is a reslice x = x[0:y] or x = append(x, ...) schar likely; // likeliness of if statement uchar hasbreak; // has break statement uchar needzero; // if it contains pointers, needs to be zeroed on function entry @@ -380,7 +382,6 @@ enum SymExported = 1<<2, // already written out by export SymUniq = 1<<3, SymSiggen = 1<<4, - SymGcgen = 1<<5, }; struct Sym @@ -447,7 +448,6 @@ enum OSUB, // x - y OOR, // x | y OXOR, // x ^ y - OADDPTR, // ptr + uintptr, inserted by compiler only, used to avoid unsafe type changes during codegen OADDSTR, // s + "foo" OADDR, // &x OANDAND, // b0 && b1 @@ -573,7 +573,6 @@ enum OTINTER, // interface{} OTFUNC, // func() OTARRAY, // []int, [8]int, [N]int or [...]int - OTPAREN, // (T) // misc ODDD, // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}. @@ -975,11 +974,13 @@ EXTERN int funcdepth; EXTERN int typecheckok; EXTERN int compiling_runtime; EXTERN int compiling_wrappers; +EXTERN int use_writebarrier; EXTERN int pure_go; EXTERN char* flag_installsuffix; EXTERN int flag_race; EXTERN int flag_largemodel; EXTERN int noescape; +EXTERN int nosplit; EXTERN int debuglive; EXTERN Link* ctxt; @@ -1169,6 +1170,7 @@ void cgen_callmeth(Node *n, int proc); void cgen_eface(Node* n, Node* res); void cgen_slice(Node* n, Node* res); void clearlabels(void); +void clearslim(Node*); void checklabels(void); int dotoffset(Node *n, int64 *oary, Node **nn); void gen(Node *n); @@ -1284,6 +1286,7 @@ LSym* linksym(Sym*); * order.c */ void order(Node *fn); +void orderstmtinplace(Node **stmt); /* * range.c @@ -1302,7 +1305,6 @@ Sym* typenamesym(Type *t); Sym* tracksym(Type *t); Sym* typesymprefix(char *prefix, Type *t); int haspointers(Type *t); -void usefield(Node*); Type* hiter(Type* t); /* @@ -1364,6 +1366,7 @@ int is64(Type *t); int isbadimport(Strlit *s); int isblank(Node *n); int isblanksym(Sym *s); +int isdirectiface(Type*); int isfixedarray(Type *t); int isideal(Type *t); int isinter(Type *t); @@ -1372,6 +1375,7 @@ int isnilinter(Type *t); int isptrto(Type *t, int et); int isslice(Type *t); int istype(Type *t, int et); +int iszero(Node *n); void linehist(char *file, int32 off, int relative); NodeList* list(NodeList *l, Node *n); NodeList* list1(Node *n); @@ -1464,7 +1468,9 @@ void walkstmt(Node **np); void walkstmtlist(NodeList *l); Node* conv(Node*, Type*); int candiscard(Node*); +int needwritebarrier(Node*, Node*); Node* outervalue(Node*); +void usefield(Node*); /* * arch-specific ggen.c/gsubr.c/gobj.c/pgen.c/plive.c @@ -1505,7 +1511,7 @@ void gdata(Node*, Node*, int); void gdatacomplex(Node*, Mpcplx*); void gdatastring(Node*, Strlit*); void ggloblnod(Node *nam); -void ggloblsym(Sym *s, int32 width, int dupok, int rodata); +void ggloblsym(Sym *s, int32 width, int8 flags); void gvardef(Node*); void gvarkill(Node*); Prog* gjmp(Prog*); @@ -1514,6 +1520,7 @@ void movelarge(NodeList*); int isfat(Type*); void linkarchinit(void); void liveness(Node*, Prog*, Sym*, Sym*); +void twobitwalktype1(Type*, vlong*, Bvec*); void markautoused(Prog*); Plist* newplist(void); Node* nodarg(Type*, int); diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 2f354f723..68fccc1ad 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -460,11 +460,13 @@ simple_stmt: | expr LINC { $$ = nod(OASOP, $1, nodintconst(1)); + $$->implicit = 1; $$->etype = OADD; } | expr LDEC { $$ = nod(OASOP, $1, nodintconst(1)); + $$->implicit = 1; $$->etype = OSUB; } @@ -613,6 +615,11 @@ range_stmt: $$->colas = 1; colasdefn($1, $$); } +| LRANGE expr + { + $$ = nod(ORANGE, N, $2); + $$->etype = 0; // := flag + } for_header: osimple_stmt ';' osimple_stmt ';' osimple_stmt @@ -1180,7 +1187,7 @@ ntype: | dotname | '(' ntype ')' { - $$ = nod(OTPAREN, $2, N); + $$ = $2; } non_expr_type: @@ -1199,7 +1206,7 @@ non_recvchantype: | dotname | '(' ntype ')' { - $$ = nod(OTPAREN, $2, N); + $$ = $2; } convtype: @@ -1311,6 +1318,7 @@ xfndcl: $$->nbody = $3; $$->endlineno = lineno; $$->noescape = noescape; + $$->nosplit = nosplit; funcbody($$); } @@ -1365,8 +1373,6 @@ fndcl: yyerror("bad receiver in method"); break; } - if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN)) - yyerror("cannot parenthesize receiver type"); t = nod(OTFUNC, rcvr, N); t->list = $6; @@ -1495,6 +1501,7 @@ xdcl_list: testdclstack(); nointerface = 0; noescape = 0; + nosplit = 0; } vardcl_list: diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index a50101c42..523ba37aa 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -45,7 +45,7 @@ static struct { }; // Debug arguments. -// These can be specified with the -d flag, as in "-d checknil" +// These can be specified with the -d flag, as in "-d nil" // to set the debug_checknil variable. In general the list passed // to -d can be comma-separated. static struct { @@ -139,6 +139,8 @@ yy_isalnum(int c) #define isalnum use_yy_isalnum_instead_of_isalnum #define DBG if(!debug['x']){}else print +/*c2go void DBG(char*, ...); */ + enum { EOF = -1, @@ -310,6 +312,8 @@ main(int argc, char *argv[]) flagcount("u", "reject unsafe code", &safemode); flagcount("v", "increase debug verbosity", &debug['v']); flagcount("w", "debug type checking", &debug['w']); + use_writebarrier = 1; + flagcount("wb", "enable write barrier", &use_writebarrier); flagcount("x", "debug lexer", &debug['x']); flagcount("y", "debug declarations in canned imports (with -d)", &debug['y']); if(thechar == '6') @@ -317,6 +321,7 @@ main(int argc, char *argv[]) flagparse(&argc, &argv, usage); ctxt->debugasm = debug['S']; + ctxt->debugvlog = debug['v']; if(argc < 1) usage(); @@ -339,8 +344,8 @@ main(int argc, char *argv[]) break; } } - if(j == nelem(debugtab)) - fatal("unknown debug information -d '%s'\n", f[i]); + if(debugtab[j].name == nil) + sysfatal("unknown debug information -d '%s'\n", f[i]); } } @@ -476,8 +481,12 @@ main(int argc, char *argv[]) } // Phase 5: Escape analysis. - if(!debug['N']) - escapes(xtop); + // Required for moving heap allocations onto stack, + // which in turn is required by the closure implementation, + // which stores the addresses of stack variables into the closure. + // If the closure does not escape, it needs to be on the stack + // or else the stack copier will not update it. + escapes(xtop); // Escape analysis moved escaped values off stack. // Move large values off stack too. @@ -516,24 +525,18 @@ saveerrors(void) nerrors = 0; } -/* - * macro to portably read/write archive header. - * 'cmd' is read/write/Bread/Bwrite, etc. - */ -#define HEADER_IO(cmd, f, h) cmd(f, h.name, sizeof(h.name)) != sizeof(h.name)\ - || cmd(f, h.date, sizeof(h.date)) != sizeof(h.date)\ - || cmd(f, h.uid, sizeof(h.uid)) != sizeof(h.uid)\ - || cmd(f, h.gid, sizeof(h.gid)) != sizeof(h.gid)\ - || cmd(f, h.mode, sizeof(h.mode)) != sizeof(h.mode)\ - || cmd(f, h.size, sizeof(h.size)) != sizeof(h.size)\ - || cmd(f, h.fmag, sizeof(h.fmag)) != sizeof(h.fmag) - static int arsize(Biobuf *b, char *name) { struct ar_hdr a; - if (HEADER_IO(Bread, b, a)) + if(Bread(b, a.name, sizeof(a.name)) != sizeof(a.name) || + Bread(b, a.date, sizeof(a.date)) != sizeof(a.date) || + Bread(b, a.uid, sizeof(a.uid)) != sizeof(a.uid) || + Bread(b, a.gid, sizeof(a.gid)) != sizeof(a.gid) || + Bread(b, a.mode, sizeof(a.mode)) != sizeof(a.mode) || + Bread(b, a.size, sizeof(a.size)) != sizeof(a.size) || + Bread(b, a.fmag, sizeof(a.fmag)) != sizeof(a.fmag)) return -1; if(strncmp(a.name, name, strlen(name)) != 0) @@ -1592,6 +1595,10 @@ go: noescape = 1; goto out; } + if(strcmp(lexbuf, "go:nosplit") == 0) { + nosplit = 1; + goto out; + } out: return c; @@ -1854,74 +1861,74 @@ static struct /* name lexical etype op */ /* basic types */ - "int8", LNAME, TINT8, OXXX, - "int16", LNAME, TINT16, OXXX, - "int32", LNAME, TINT32, OXXX, - "int64", LNAME, TINT64, OXXX, - - "uint8", LNAME, TUINT8, OXXX, - "uint16", LNAME, TUINT16, OXXX, - "uint32", LNAME, TUINT32, OXXX, - "uint64", LNAME, TUINT64, OXXX, - - "float32", LNAME, TFLOAT32, OXXX, - "float64", LNAME, TFLOAT64, OXXX, - - "complex64", LNAME, TCOMPLEX64, OXXX, - "complex128", LNAME, TCOMPLEX128, OXXX, - - "bool", LNAME, TBOOL, OXXX, - "string", LNAME, TSTRING, OXXX, - - "any", LNAME, TANY, OXXX, - - "break", LBREAK, Txxx, OXXX, - "case", LCASE, Txxx, OXXX, - "chan", LCHAN, Txxx, OXXX, - "const", LCONST, Txxx, OXXX, - "continue", LCONTINUE, Txxx, OXXX, - "default", LDEFAULT, Txxx, OXXX, - "else", LELSE, Txxx, OXXX, - "defer", LDEFER, Txxx, OXXX, - "fallthrough", LFALL, Txxx, OXXX, - "for", LFOR, Txxx, OXXX, - "func", LFUNC, Txxx, OXXX, - "go", LGO, Txxx, OXXX, - "goto", LGOTO, Txxx, OXXX, - "if", LIF, Txxx, OXXX, - "import", LIMPORT, Txxx, OXXX, - "interface", LINTERFACE, Txxx, OXXX, - "map", LMAP, Txxx, OXXX, - "package", LPACKAGE, Txxx, OXXX, - "range", LRANGE, Txxx, OXXX, - "return", LRETURN, Txxx, OXXX, - "select", LSELECT, Txxx, OXXX, - "struct", LSTRUCT, Txxx, OXXX, - "switch", LSWITCH, Txxx, OXXX, - "type", LTYPE, Txxx, OXXX, - "var", LVAR, Txxx, OXXX, - - "append", LNAME, Txxx, OAPPEND, - "cap", LNAME, Txxx, OCAP, - "close", LNAME, Txxx, OCLOSE, - "complex", LNAME, Txxx, OCOMPLEX, - "copy", LNAME, Txxx, OCOPY, - "delete", LNAME, Txxx, ODELETE, - "imag", LNAME, Txxx, OIMAG, - "len", LNAME, Txxx, OLEN, - "make", LNAME, Txxx, OMAKE, - "new", LNAME, Txxx, ONEW, - "panic", LNAME, Txxx, OPANIC, - "print", LNAME, Txxx, OPRINT, - "println", LNAME, Txxx, OPRINTN, - "real", LNAME, Txxx, OREAL, - "recover", LNAME, Txxx, ORECOVER, - - "notwithstanding", LIGNORE, Txxx, OXXX, - "thetruthofthematter", LIGNORE, Txxx, OXXX, - "despiteallobjections", LIGNORE, Txxx, OXXX, - "whereas", LIGNORE, Txxx, OXXX, - "insofaras", LIGNORE, Txxx, OXXX, + {"int8", LNAME, TINT8, OXXX}, + {"int16", LNAME, TINT16, OXXX}, + {"int32", LNAME, TINT32, OXXX}, + {"int64", LNAME, TINT64, OXXX}, + + {"uint8", LNAME, TUINT8, OXXX}, + {"uint16", LNAME, TUINT16, OXXX}, + {"uint32", LNAME, TUINT32, OXXX}, + {"uint64", LNAME, TUINT64, OXXX}, + + {"float32", LNAME, TFLOAT32, OXXX}, + {"float64", LNAME, TFLOAT64, OXXX}, + + {"complex64", LNAME, TCOMPLEX64, OXXX}, + {"complex128", LNAME, TCOMPLEX128, OXXX}, + + {"bool", LNAME, TBOOL, OXXX}, + {"string", LNAME, TSTRING, OXXX}, + + {"any", LNAME, TANY, OXXX}, + + {"break", LBREAK, Txxx, OXXX}, + {"case", LCASE, Txxx, OXXX}, + {"chan", LCHAN, Txxx, OXXX}, + {"const", LCONST, Txxx, OXXX}, + {"continue", LCONTINUE, Txxx, OXXX}, + {"default", LDEFAULT, Txxx, OXXX}, + {"else", LELSE, Txxx, OXXX}, + {"defer", LDEFER, Txxx, OXXX}, + {"fallthrough", LFALL, Txxx, OXXX}, + {"for", LFOR, Txxx, OXXX}, + {"func", LFUNC, Txxx, OXXX}, + {"go", LGO, Txxx, OXXX}, + {"goto", LGOTO, Txxx, OXXX}, + {"if", LIF, Txxx, OXXX}, + {"import", LIMPORT, Txxx, OXXX}, + {"interface", LINTERFACE, Txxx, OXXX}, + {"map", LMAP, Txxx, OXXX}, + {"package", LPACKAGE, Txxx, OXXX}, + {"range", LRANGE, Txxx, OXXX}, + {"return", LRETURN, Txxx, OXXX}, + {"select", LSELECT, Txxx, OXXX}, + {"struct", LSTRUCT, Txxx, OXXX}, + {"switch", LSWITCH, Txxx, OXXX}, + {"type", LTYPE, Txxx, OXXX}, + {"var", LVAR, Txxx, OXXX}, + + {"append", LNAME, Txxx, OAPPEND}, + {"cap", LNAME, Txxx, OCAP}, + {"close", LNAME, Txxx, OCLOSE}, + {"complex", LNAME, Txxx, OCOMPLEX}, + {"copy", LNAME, Txxx, OCOPY}, + {"delete", LNAME, Txxx, ODELETE}, + {"imag", LNAME, Txxx, OIMAG}, + {"len", LNAME, Txxx, OLEN}, + {"make", LNAME, Txxx, OMAKE}, + {"new", LNAME, Txxx, ONEW}, + {"panic", LNAME, Txxx, OPANIC}, + {"print", LNAME, Txxx, OPRINT}, + {"println", LNAME, Txxx, OPRINTN}, + {"real", LNAME, Txxx, OREAL}, + {"recover", LNAME, Txxx, ORECOVER}, + + {"notwithstanding", LIGNORE, Txxx, OXXX}, + {"thetruthofthematter", LIGNORE, Txxx, OXXX}, + {"despiteallobjections", LIGNORE, Txxx, OXXX}, + {"whereas", LIGNORE, Txxx, OXXX}, + {"insofaras", LIGNORE, Txxx, OXXX}, }; static void @@ -2171,50 +2178,50 @@ struct char* name; } lexn[] = { - LANDAND, "ANDAND", - LANDNOT, "ANDNOT", - LASOP, "ASOP", - LBREAK, "BREAK", - LCASE, "CASE", - LCHAN, "CHAN", - LCOLAS, "COLAS", - LCOMM, "<-", - LCONST, "CONST", - LCONTINUE, "CONTINUE", - LDDD, "...", - LDEC, "DEC", - LDEFAULT, "DEFAULT", - LDEFER, "DEFER", - LELSE, "ELSE", - LEQ, "EQ", - LFALL, "FALL", - LFOR, "FOR", - LFUNC, "FUNC", - LGE, "GE", - LGO, "GO", - LGOTO, "GOTO", - LGT, "GT", - LIF, "IF", - LIMPORT, "IMPORT", - LINC, "INC", - LINTERFACE, "INTERFACE", - LLE, "LE", - LLITERAL, "LITERAL", - LLSH, "LSH", - LLT, "LT", - LMAP, "MAP", - LNAME, "NAME", - LNE, "NE", - LOROR, "OROR", - LPACKAGE, "PACKAGE", - LRANGE, "RANGE", - LRETURN, "RETURN", - LRSH, "RSH", - LSELECT, "SELECT", - LSTRUCT, "STRUCT", - LSWITCH, "SWITCH", - LTYPE, "TYPE", - LVAR, "VAR", + {LANDAND, "ANDAND"}, + {LANDNOT, "ANDNOT"}, + {LASOP, "ASOP"}, + {LBREAK, "BREAK"}, + {LCASE, "CASE"}, + {LCHAN, "CHAN"}, + {LCOLAS, "COLAS"}, + {LCOMM, "<-"}, + {LCONST, "CONST"}, + {LCONTINUE, "CONTINUE"}, + {LDDD, "..."}, + {LDEC, "DEC"}, + {LDEFAULT, "DEFAULT"}, + {LDEFER, "DEFER"}, + {LELSE, "ELSE"}, + {LEQ, "EQ"}, + {LFALL, "FALL"}, + {LFOR, "FOR"}, + {LFUNC, "FUNC"}, + {LGE, "GE"}, + {LGO, "GO"}, + {LGOTO, "GOTO"}, + {LGT, "GT"}, + {LIF, "IF"}, + {LIMPORT, "IMPORT"}, + {LINC, "INC"}, + {LINTERFACE, "INTERFACE"}, + {LLE, "LE"}, + {LLITERAL, "LITERAL"}, + {LLSH, "LSH"}, + {LLT, "LT"}, + {LMAP, "MAP"}, + {LNAME, "NAME"}, + {LNE, "NE"}, + {LOROR, "OROR"}, + {LPACKAGE, "PACKAGE"}, + {LRANGE, "RANGE"}, + {LRETURN, "RETURN"}, + {LRSH, "RSH"}, + {LSELECT, "SELECT"}, + {LSTRUCT, "STRUCT"}, + {LSWITCH, "SWITCH"}, + {LTYPE, "TYPE"}, + {LVAR, "VAR"}, }; char* @@ -2236,56 +2243,56 @@ struct char *want; } yytfix[] = { - "$end", "EOF", - "LLITERAL", "literal", - "LASOP", "op=", - "LBREAK", "break", - "LCASE", "case", - "LCHAN", "chan", - "LCOLAS", ":=", - "LCONST", "const", - "LCONTINUE", "continue", - "LDDD", "...", - "LDEFAULT", "default", - "LDEFER", "defer", - "LELSE", "else", - "LFALL", "fallthrough", - "LFOR", "for", - "LFUNC", "func", - "LGO", "go", - "LGOTO", "goto", - "LIF", "if", - "LIMPORT", "import", - "LINTERFACE", "interface", - "LMAP", "map", - "LNAME", "name", - "LPACKAGE", "package", - "LRANGE", "range", - "LRETURN", "return", - "LSELECT", "select", - "LSTRUCT", "struct", - "LSWITCH", "switch", - "LTYPE", "type", - "LVAR", "var", - "LANDAND", "&&", - "LANDNOT", "&^", - "LBODY", "{", - "LCOMM", "<-", - "LDEC", "--", - "LINC", "++", - "LEQ", "==", - "LGE", ">=", - "LGT", ">", - "LLE", "<=", - "LLT", "<", - "LLSH", "<<", - "LRSH", ">>", - "LOROR", "||", - "LNE", "!=", + {"$end", "EOF"}, + {"LLITERAL", "literal"}, + {"LASOP", "op="}, + {"LBREAK", "break"}, + {"LCASE", "case"}, + {"LCHAN", "chan"}, + {"LCOLAS", ":="}, + {"LCONST", "const"}, + {"LCONTINUE", "continue"}, + {"LDDD", "..."}, + {"LDEFAULT", "default"}, + {"LDEFER", "defer"}, + {"LELSE", "else"}, + {"LFALL", "fallthrough"}, + {"LFOR", "for"}, + {"LFUNC", "func"}, + {"LGO", "go"}, + {"LGOTO", "goto"}, + {"LIF", "if"}, + {"LIMPORT", "import"}, + {"LINTERFACE", "interface"}, + {"LMAP", "map"}, + {"LNAME", "name"}, + {"LPACKAGE", "package"}, + {"LRANGE", "range"}, + {"LRETURN", "return"}, + {"LSELECT", "select"}, + {"LSTRUCT", "struct"}, + {"LSWITCH", "switch"}, + {"LTYPE", "type"}, + {"LVAR", "var"}, + {"LANDAND", "&&"}, + {"LANDNOT", "&^"}, + {"LBODY", "{"}, + {"LCOMM", "<-"}, + {"LDEC", "--"}, + {"LINC", "++"}, + {"LEQ", "=="}, + {"LGE", ">="}, + {"LGT", ">"}, + {"LLE", "<="}, + {"LLT", "<"}, + {"LLSH", "<<"}, + {"LRSH", ">>"}, + {"LOROR", "||"}, + {"LNE", "!="}, // spell out to avoid confusion with punctuation in error messages - "';'", "semicolon or newline", - "','", "comma", + {"';'", "semicolon or newline"}, + {"','", "comma"}, }; static void diff --git a/src/cmd/gc/md5.c b/src/cmd/gc/md5.c index 0051ac964..46cb6b712 100644 --- a/src/cmd/gc/md5.c +++ b/src/cmd/gc/md5.c @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // 64-bit MD5 (does full MD5 but returns 64 bits only). -// Translation of ../../pkg/crypto/md5/md5*.go. +// Translation of ../../crypto/md5/md5*.go. #include #include @@ -20,7 +20,15 @@ enum { #define _Init1 0xEFCDAB89 #define _Init2 0x98BADCFE #define _Init3 0x10325476 - +/*c2go +enum { + _Init0 = 0x67452301, + _Init1 = 0xEFCDAB89, + _Init2 = 0x98BADCFE, + _Init3 = 0x10325476 +}; +*/ + void md5reset(MD5 *d) { diff --git a/src/cmd/gc/mparith1.c b/src/cmd/gc/mparith1.c index 1519caec7..d33a81e09 100644 --- a/src/cmd/gc/mparith1.c +++ b/src/cmd/gc/mparith1.c @@ -591,7 +591,7 @@ Fconv(Fmt *fp) d = mpgetflt(fvp); if(d >= 0 && (fp->flags & FmtSign)) fmtprint(fp, "+"); - return fmtprint(fp, "%g", d, exp, fvp); + return fmtprint(fp, "%g", d); } // very out of range. compute decimal approximation by hand. diff --git a/src/cmd/gc/mparith2.c b/src/cmd/gc/mparith2.c index 5cf98c62c..fd9f591ce 100644 --- a/src/cmd/gc/mparith2.c +++ b/src/cmd/gc/mparith2.c @@ -656,7 +656,7 @@ mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d) } static int -iszero(Mpint *a) +mpiszero(Mpint *a) { long *a1; int i; @@ -687,7 +687,7 @@ mpdivfract(Mpint *a, Mpint *b) for(j=0; j prec+1) s = prec+1; - if((v & ((1<>= s; e = minexp; } diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index 4eeb03aa8..b752a13ce 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -5,6 +5,7 @@ #include #include #include "go.h" +#include "../ld/textflag.h" /* * architecture-independent object file output @@ -84,7 +85,7 @@ dumpobj(void) externdcl = tmp; zero = pkglookup("zerovalue", runtimepkg); - ggloblsym(zero, zerosize, 1, 1); + ggloblsym(zero, zerosize, DUPOK|RODATA); dumpdata(); writeobj(ctxt, bout); @@ -128,7 +129,7 @@ dumpglobls(void) for(l=funcsyms; l; l=l->next) { n = l->n; dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0); - ggloblsym(n->sym, widthptr, 1, 1); + ggloblsym(n->sym, widthptr, DUPOK|RODATA); } // Do not reprocess funcsyms on next dumpglobls call. @@ -249,7 +250,7 @@ stringsym(char *s, int len) } off = duint8(sym, off, 0); // terminating NUL for runtime off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment - ggloblsym(sym, off, 1, 1); + ggloblsym(sym, off, DUPOK|RODATA); return sym; } @@ -272,7 +273,7 @@ slicebytes(Node *nam, char *s, int len) m = len-n; off = dsname(sym, off, s+n, m); } - ggloblsym(sym, off, 0, 0); + ggloblsym(sym, off, NOPTR); if(nam->op != ONAME) fatal("slicebytes %N", nam); diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c index 30dbc7dac..76820fde7 100644 --- a/src/cmd/gc/order.c +++ b/src/cmd/gc/order.c @@ -317,7 +317,7 @@ orderexprinplace(Node **np, Order *outer) // Orderstmtinplace orders the side effects of the single statement *np // and replaces it with the resulting statement list. -static void +void orderstmtinplace(Node **np) { Node *n; @@ -438,6 +438,9 @@ ordercall(Node *n, Order *order) // cases they are also typically registerizable, so not much harm done. // And this only applies to the multiple-assignment form. // We could do a more precise analysis if needed, like in walk.c. +// +// Ordermapassign also inserts these temporaries if needed for +// calling writebarrierfat with a pointer to n->right. static void ordermapassign(Node *n, Order *order) { @@ -451,7 +454,8 @@ ordermapassign(Node *n, Order *order) case OAS: order->out = list(order->out, n); - if(n->left->op == OINDEXMAP && !isaddrokay(n->right)) { + // We call writebarrierfat only for values > 4 pointers long. See walk.c. + if((n->left->op == OINDEXMAP || (needwritebarrier(n->left, n->right) && n->left->type->width > 4*widthptr)) && !isaddrokay(n->right)) { m = n->left; n->left = ordertemp(m->type, order, 0); a = nod(OAS, m, n->left); @@ -593,7 +597,10 @@ orderstmt(Node *n, Order *order) orderexpr(&n->rlist->n->left, order); // arg to recv ch = n->rlist->n->left->type; tmp1 = ordertemp(ch->type, order, haspointers(ch->type)); - tmp2 = ordertemp(types[TBOOL], order, 0); + if(!isblank(n->list->next->n)) + tmp2 = ordertemp(n->list->next->n->type, order, 0); + else + tmp2 = ordertemp(types[TBOOL], order, 0); order->out = list(order->out, n); r = nod(OAS, n->list->n, tmp1); typecheck(&r, Etop); @@ -768,6 +775,12 @@ orderstmt(Node *n, Order *order) // Special: clean case temporaries in each block entry. // Select must enter one of its blocks, so there is no // need for a cleaning at the end. + // Doubly special: evaluation order for select is stricter + // than ordinary expressions. Even something like p.c + // has to be hoisted into a temporary, so that it cannot be + // reordered after the channel evaluation for a different + // case (if p were nil, then the timing of the fault would + // give this away). t = marktemp(order); for(l=n->list; l; l=l->next) { if(l->n->op != OXCASE) @@ -810,6 +823,8 @@ orderstmt(Node *n, Order *order) // r->left == N means 'case <-c'. // c is always evaluated; x and ok are only evaluated when assigned. orderexpr(&r->right->left, order); + if(r->right->left->op != ONAME) + r->right->left = ordercopyexpr(r->right->left, r->right->left->type, order, 0); // Introduce temporary for receive and move actual copy into case body. // avoids problems with target being addressed, as usual. @@ -1017,11 +1032,21 @@ orderexpr(Node **np, Order *order) orderexprinplace(&n->right, order); break; + case OAPPEND: case OCALLFUNC: - case OCALLMETH: case OCALLINTER: - case OAPPEND: + case OCALLMETH: + case OCAP: case OCOMPLEX: + case OCOPY: + case OIMAG: + case OLEN: + case OMAKECHAN: + case OMAKEMAP: + case OMAKESLICE: + case ONEW: + case OREAL: + case ORECOVER: ordercall(n, order); n = ordercopyexpr(n, n->type, order, 0); break; @@ -1055,6 +1080,19 @@ orderexpr(Node **np, Order *order) orderexpr(&n->left, order); n = ordercopyexpr(n, n->type, order, 1); break; + + case OEQ: + case ONE: + orderexpr(&n->left, order); + orderexpr(&n->right, order); + t = n->left->type; + if(t->etype == TSTRUCT || isfixedarray(t)) { + // for complex comparisons, we need both args to be + // addressable so we can pass them to the runtime. + orderaddrtemp(&n->left, order); + orderaddrtemp(&n->right, order); + } + break; } lineno = lno; diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index 40620c3da..39028e3f8 100644 --- a/src/cmd/gc/pgen.c +++ b/src/cmd/gc/pgen.c @@ -11,9 +11,10 @@ #include "md5.h" #include "gg.h" #include "opt.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" static void allocauto(Prog* p); +static void emitptrargsmap(void); static Sym* makefuncdatasym(char *namefmt, int64 funcdatakind) @@ -173,9 +174,17 @@ compile(Node *fn) lno = setlineno(fn); + curfn = fn; + dowidth(curfn->type); + if(fn->nbody == nil) { - if(pure_go || strncmp(fn->nname->sym->name, "init·", 6) == 0) + if(pure_go || strncmp(fn->nname->sym->name, "init·", 6) == 0) { yyerror("missing function body", fn); + goto ret; + } + if(debug['A']) + goto ret; + emitptrargsmap(); goto ret; } @@ -184,9 +193,6 @@ compile(Node *fn) // set up domain for labels clearlabels(); - curfn = fn; - dowidth(curfn->type); - if(curfn->type->outnamed) { // add clearing of the output parameters t = structfirst(&save, getoutarg(curfn->type)); @@ -229,9 +235,11 @@ compile(Node *fn) ptxt->TEXTFLAG |= WRAPPER; if(fn->needctxt) ptxt->TEXTFLAG |= NEEDCTXT; + if(fn->nosplit) + ptxt->TEXTFLAG |= NOSPLIT; // Clumsy but important. - // See test/recover.go for test cases and src/pkg/reflect/value.go + // See test/recover.go for test cases and src/reflect/value.go // for the actual functions being considered. if(myimportpath != nil && strcmp(myimportpath, "reflect") == 0) { if(strcmp(curfn->nname->sym->name, "callReflect") == 0 || strcmp(curfn->nname->sym->name, "callMethod") == 0) @@ -327,6 +335,43 @@ ret: lineno = lno; } +static void +emitptrargsmap(void) +{ + int nptr, nbitmap, j, off; + vlong xoffset; + Bvec *bv; + Sym *sym; + + sym = lookup(smprint("%s.args_stackmap", curfn->nname->sym->name)); + + nptr = curfn->type->argwid / widthptr; + bv = bvalloc(nptr*2); + nbitmap = 1; + if(curfn->type->outtuple > 0) + nbitmap = 2; + off = duint32(sym, 0, nbitmap); + off = duint32(sym, off, bv->n); + if(curfn->type->thistuple > 0) { + xoffset = 0; + twobitwalktype1(getthisx(curfn->type), &xoffset, bv); + } + if(curfn->type->intuple > 0) { + xoffset = 0; + twobitwalktype1(getinargx(curfn->type), &xoffset, bv); + } + for(j = 0; j < bv->n; j += 32) + off = duint32(sym, off, bv->b[j/32]); + if(curfn->type->outtuple > 0) { + xoffset = 0; + twobitwalktype1(getoutargx(curfn->type), &xoffset, bv); + for(j = 0; j < bv->n; j += 32) + off = duint32(sym, off, bv->b[j/32]); + } + ggloblsym(sym, off, RODATA); + free(bv); +} + // Sort the list of stack variables. Autos after anything else, // within autos, unused after used, within used, things with // pointers first, zeroed things first, and then decreasing size. diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c index 7a40ab559..0feb2c710 100644 --- a/src/cmd/gc/plive.c +++ b/src/cmd/gc/plive.c @@ -17,9 +17,9 @@ #include #include "gg.h" #include "opt.h" -#include "../../pkg/runtime/funcdata.h" - -enum { BitsPerPointer = 2 }; +#include "../ld/textflag.h" +#include "../../runtime/funcdata.h" +#include "../../runtime/mgc0.h" enum { UNVISITED = 0, @@ -674,8 +674,8 @@ static void progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) { ProgInfo info; - Adr *from; - Adr *to; + Addr *from; + Addr *to; Node *node; int32 i; int32 pos; @@ -1063,7 +1063,7 @@ checkptxt(Node *fn, Prog *firstp) // and then simply copied into bv at the correct offset on future calls with // the same type t. On https://rsc.googlecode.com/hg/testdata/slow.go, twobitwalktype1 // accounts for 40% of the 6g execution time. -static void +void twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) { vlong fieldoffset; @@ -1113,8 +1113,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) // struct { byte *str; intgo len; } if((*xoffset & (widthptr-1)) != 0) fatal("twobitwalktype1: invalid alignment, %T", t); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 0); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 3:0 = multiword:string + bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot *xoffset += t->width; break; @@ -1145,9 +1144,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) // struct { byte *array; uintgo len; uintgo cap; } if((*xoffset & (widthptr-1)) != 0) fatal("twobitwalktype1: invalid TARRAY alignment, %T", t); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 0); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 2); // 3:1 = multiword/slice + bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot *xoffset += t->width; } else for(i = 0; i < t->bound; i++) @@ -1683,6 +1680,13 @@ livenessepilogue(Liveness *lv) // FNV-1 hash function constants. #define H0 2166136261UL #define Hp 16777619UL +/*c2go +enum +{ + H0 = 2166136261, + Hp = 16777619, +}; +*/ static uint32 hashbitmap(uint32 h, Bvec *bv) @@ -1932,11 +1936,15 @@ twobitwritesymbol(Array *arr, Sym *sym) break; for(j = 0; j < bv->n; j += 32) { word = bv->b[j/32]; - off = duint32(sym, off, word); + // Runtime reads the bitmaps as byte arrays. Oblige. + off = duint8(sym, off, word); + off = duint8(sym, off, word>>8); + off = duint8(sym, off, word>>16); + off = duint8(sym, off, word>>24); } } duint32(sym, 0, i); // number of bitmaps - ggloblsym(sym, off, 0, 1); + ggloblsym(sym, off, RODATA); } static void diff --git a/src/cmd/gc/popt.c b/src/cmd/gc/popt.c index ea88b94db..993bb2482 100644 --- a/src/cmd/gc/popt.c +++ b/src/cmd/gc/popt.c @@ -49,7 +49,7 @@ noreturn(Prog *p) symlist[0] = pkglookup("panicindex", runtimepkg); symlist[1] = pkglookup("panicslice", runtimepkg); symlist[2] = pkglookup("throwinit", runtimepkg); - symlist[3] = pkglookup("panic", runtimepkg); + symlist[3] = pkglookup("gopanic", runtimepkg); symlist[4] = pkglookup("panicwrap", runtimepkg); symlist[5] = pkglookup("throwreturn", runtimepkg); symlist[6] = pkglookup("selectgo", runtimepkg); @@ -98,6 +98,10 @@ chasejmp(Prog *p, int *jmploop) */ #define alive ((void*)0) #define dead ((void*)1) +/*c2go +extern void *alive; +extern void *dead; +*/ /* mark all code reachable from firstp as alive */ static void diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c index 285bd78a2..c9e27fe56 100644 --- a/src/cmd/gc/racewalk.c +++ b/src/cmd/gc/racewalk.c @@ -208,6 +208,26 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) goto ret; case OCALLFUNC: + // Instrument dst argument of runtime.writebarrier* calls + // as we do not instrument runtime code. + if(n->left->sym != S && n->left->sym->pkg == runtimepkg && strncmp(n->left->sym->name, "writebarrier", 12) == 0) { + // Find the dst argument. + // The list can be reordered, so it's not necessary just the first or the second element. + for(l = n->list; l; l = l->next) { + if(strcmp(n->left->sym->name, "writebarrierfat") == 0) { + if(l->n->left->xoffset == widthptr) + break; + } else { + if(l->n->left->xoffset == 0) + break; + } + } + if(l == nil) + fatal("racewalk: writebarrier no arg"); + if(l->n->right->op != OADDR) + fatal("racewalk: writebarrier bad arg"); + callinstr(&l->n->right->left, init, 1, 0); + } racewalknode(&n->left, init, 0, 0); goto ret; @@ -419,8 +439,10 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) ret: if(n->op != OBLOCK) // OBLOCK is handled above in a special way. racewalklist(n->list, init); - racewalknode(&n->ntest, &n->ntest->ninit, 0, 0); - racewalknode(&n->nincr, &n->nincr->ninit, 0, 0); + if(n->ntest != N) + racewalknode(&n->ntest, &n->ntest->ninit, 0, 0); + if(n->nincr != N) + racewalknode(&n->nincr, &n->nincr->ninit, 0, 0); racewalklist(n->nbody, nil); racewalklist(n->nelse, nil); racewalklist(n->rlist, nil); diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c index 45aa521b3..4ed452832 100644 --- a/src/cmd/gc/range.c +++ b/src/cmd/gc/range.c @@ -67,9 +67,11 @@ typecheckrange(Node *n) yyerror("too many variables in range"); } - v1 = n->list->n; + v1 = N; + if(n->list) + v1 = n->list->n; v2 = N; - if(n->list->next) + if(n->list && n->list->next) v2 = n->list->next->n; // this is not only a optimization but also a requirement in the spec. @@ -77,14 +79,17 @@ typecheckrange(Node *n) // clause is equivalent to the same clause with only the first variable // present." if(isblank(v2)) { - n->list = list1(v1); + if(v1 != N) + n->list = list1(v1); v2 = N; } - if(v1->defn == n) - v1->type = t1; - else if(v1->type != T && assignop(t1, v1->type, &why) == 0) - yyerror("cannot assign type %T to %lN in range%s", t1, v1, why); + if(v1) { + if(v1->defn == n) + v1->type = t1; + else if(v1->type != T && assignop(t1, v1->type, &why) == 0) + yyerror("cannot assign type %T to %lN in range%s", t1, v1, why); + } if(v2) { if(v2->defn == n) v2->type = t2; @@ -123,9 +128,11 @@ walkrange(Node *n) a = n->right; lno = setlineno(a); - v1 = n->list->n; + v1 = N; + if(n->list) + v1 = n->list->n; v2 = N; - if(n->list->next && !isblank(n->list->next->n)) + if(n->list && n->list->next && !isblank(n->list->next->n)) v2 = n->list->next->n; // n->list has no meaning anymore, clear it // to avoid erroneous processing by racewalk. @@ -154,7 +161,9 @@ walkrange(Node *n) n->ntest = nod(OLT, hv1, hn); n->nincr = nod(OAS, hv1, nod(OADD, hv1, nodintconst(1))); - if(v2 == N) + if(v1 == N) + body = nil; + else if(v2 == N) body = list1(nod(OAS, v1, hv1)); else { a = nod(OAS2, N, N); @@ -205,16 +214,18 @@ walkrange(Node *n) key = nod(ODOT, hit, keyname); key = nod(OIND, key, N); - if(v2 == N) { - a = nod(OAS, v1, key); + if(v1 == N) + body = nil; + else if(v2 == N) { + body = list1(nod(OAS, v1, key)); } else { val = nod(ODOT, hit, valname); val = nod(OIND, val, N); a = nod(OAS2, N, N); a->list = list(list1(v1), v2); a->rlist = list(list1(key), val); + body = list1(a); } - body = list1(a); break; case TCHAN: @@ -223,6 +234,7 @@ walkrange(Node *n) n->ntest = N; hv1 = temp(t->type); + hv1->typecheck = 1; if(haspointers(t->type)) init = list(init, nod(OAS, hv1, N)); hb = temp(types[TBOOL]); @@ -233,7 +245,10 @@ walkrange(Node *n) a->list = list(list1(hv1), hb); a->rlist = list1(nod(ORECV, ha, N)); n->ntest->ninit = list1(a); - body = list1(nod(OAS, v1, hv1)); + if(v1 == N) + body = nil; + else + body = list1(nod(OAS, v1, hv1)); break; case TSTRING: @@ -257,7 +272,10 @@ walkrange(Node *n) n->ntest = nod(ONE, hv1, nodintconst(0)); n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a); - body = list1(nod(OAS, v1, ohv1)); + + body = nil; + if(v1 != N) + body = list1(nod(OAS, v1, ohv1)); if(v2 != N) body = list(body, nod(OAS, v2, hv2)); break; diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index dbb447e4e..b2ff2fbc5 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -5,7 +5,9 @@ #include #include #include "go.h" -#include "../../pkg/runtime/mgc0.h" +#include "../ld/textflag.h" +#include "../../runtime/mgc0.h" +#include "../../runtime/typekind.h" /* * runtime interface and reflection data structures @@ -15,7 +17,9 @@ static NodeList* signatlist; static Sym* dtypesym(Type*); static Sym* weaktypesym(Type*); static Sym* dalgsym(Type*); -static Sym* dgcsym(Type*); +static int usegcprog(Type*); +static void gengcprog(Type*, Sym**, Sym**); +static void gengcmask(Type*, uint8[16]); static int sigcmp(Sig *a, Sig *b) @@ -105,7 +109,7 @@ lsort(Sig *l, int(*f)(Sig*, Sig*)) // the given map type. This type is not visible to users - // we include only enough information to generate a correct GC // program for it. -// Make sure this stays in sync with ../../pkg/runtime/hashmap.c! +// Make sure this stays in sync with ../../runtime/hashmap.c! enum { BUCKETSIZE = 8, MAXKEYSIZE = 128, @@ -188,7 +192,7 @@ mapbucket(Type *t) // the given map type. This type is not visible to users - // we include only enough information to generate a correct GC // program for it. -// Make sure this stays in sync with ../../pkg/runtime/hashmap.c! +// Make sure this stays in sync with ../../runtime/hashmap.go! static Type* hmap(Type *t) { @@ -207,10 +211,6 @@ hmap(Type *t) offset += 4; // flags offset += 4; // hash0 offset += 1; // B - offset += 1; // keysize - offset += 1; // valuesize - offset = (offset + 1) / 2 * 2; - offset += 2; // bucketsize offset = (offset + widthptr - 1) / widthptr * widthptr; bucketsfield = typ(TFIELD); @@ -261,7 +261,7 @@ hiter(Type *t) // bptr *Bucket // other [4]uintptr // } - // must match ../../pkg/runtime/hashmap.c:hash_iter. + // must match ../../runtime/hashmap.c:hash_iter. field[0] = typ(TFIELD); field[0]->type = ptrto(t->down); field[0]->sym = mal(sizeof(Sym)); @@ -378,7 +378,7 @@ methods(Type *t) // type stored in interface word it = t; - if(it->width > widthptr) + if(!isdirectiface(it)) it = ptrto(t); // make list of methods for t, @@ -524,7 +524,7 @@ dimportpath(Pkg *p) p->pathsym = n->sym; gdatastring(n, p->path); - ggloblsym(n->sym, types[TSTRING]->width, 1, 1); + ggloblsym(n->sym, types[TSTRING]->width, DUPOK|RODATA); } static int @@ -550,7 +550,7 @@ dgopkgpath(Sym *s, int ot, Pkg *pkg) /* * uncommonType - * ../../pkg/runtime/type.go:/uncommonType + * ../../runtime/type.go:/uncommonType */ static int dextratype(Sym *sym, int off, Type *t, int ptroff) @@ -564,6 +564,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff) return off; // fill in *extraType pointer in header + off = rnd(off, widthptr); dsymptr(sym, ptroff, sym, off); n = 0; @@ -593,7 +594,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff) // methods for(a=m; a; a=a->link) { // method - // ../../pkg/runtime/type.go:/method + // ../../runtime/type.go:/method ot = dgostringptr(s, ot, a->name); ot = dgopkgpath(s, ot, a->pkg); ot = dsymptr(s, ot, dtypesym(a->mtype), 0); @@ -611,37 +612,6 @@ dextratype(Sym *sym, int off, Type *t, int ptroff) return ot; } -enum { - KindBool = 1, - KindInt, - KindInt8, - KindInt16, - KindInt32, - KindInt64, - KindUint, - KindUint8, - KindUint16, - KindUint32, - KindUint64, - KindUintptr, - KindFloat32, - KindFloat64, - KindComplex64, - KindComplex128, - KindArray, - KindChan, - KindFunc, - KindInterface, - KindMap, - KindPtr, - KindSlice, - KindString, - KindStruct, - KindUnsafePointer, - - KindNoPointers = 1<<7, -}; - static int kinds[] = { @@ -740,28 +710,30 @@ haspointers(Type *t) /* * commonType - * ../../pkg/runtime/type.go:/commonType + * ../../runtime/type.go:/commonType */ static int dcommontype(Sym *s, int ot, Type *t) { - int i, alg, sizeofAlg; - Sym *sptr, *algsym, *zero; + int i, alg, sizeofAlg, gcprog; + Sym *sptr, *algsym, *zero, *gcprog0, *gcprog1, *sbits; + uint8 gcmask[16]; static Sym *algarray; + uint64 x1, x2; char *p; if(ot != 0) fatal("dcommontype %d", ot); - sizeofAlg = 4*widthptr; + sizeofAlg = 2*widthptr; if(algarray == nil) algarray = pkglookup("algarray", runtimepkg); + dowidth(t); alg = algtype(t); algsym = S; if(alg < 0) algsym = dalgsym(t); - dowidth(t); if(t->sym != nil && !isptr[t->etype]) sptr = dtypesym(ptrto(t)); else @@ -808,17 +780,52 @@ dcommontype(Sym *s, int ot, Type *t) ot = duint8(s, ot, t->align); // align ot = duint8(s, ot, t->align); // fieldAlign + gcprog = usegcprog(t); i = kinds[t->etype]; if(t->etype == TARRAY && t->bound < 0) i = KindSlice; if(!haspointers(t)) i |= KindNoPointers; + if(isdirectiface(t)) + i |= KindDirectIface; + if(gcprog) + i |= KindGCProg; ot = duint8(s, ot, i); // kind if(alg >= 0) ot = dsymptr(s, ot, algarray, alg*sizeofAlg); else ot = dsymptr(s, ot, algsym, 0); - ot = dsymptr(s, ot, dgcsym(t), 0); // gc + // gc + if(gcprog) { + gengcprog(t, &gcprog0, &gcprog1); + if(gcprog0 != S) + ot = dsymptr(s, ot, gcprog0, 0); + else + ot = duintptr(s, ot, 0); + ot = dsymptr(s, ot, gcprog1, 0); + } else { + gengcmask(t, gcmask); + x1 = 0; + for(i=0; i<8; i++) + x1 = x1<<8 | gcmask[i]; + if(widthptr == 4) { + p = smprint("gcbits.%#016llux", x1); + } else { + x2 = 0; + for(i=0; i<8; i++) + x2 = x2<<8 | gcmask[i+8]; + p = smprint("gcbits.%#016llux%016llux", x1, x2); + } + sbits = pkglookup(p, runtimepkg); + if((sbits->flags & SymUniq) == 0) { + sbits->flags |= SymUniq; + for(i = 0; i < 2*widthptr; i++) + duint8(sbits, i, gcmask[i]); + ggloblsym(sbits, 2*widthptr, DUPOK|RODATA); + } + ot = dsymptr(s, ot, sbits, 0); + ot = duintptr(s, ot, 0); + } p = smprint("%-uT", t); //print("dcommontype: %s\n", p); ot = dgostringptr(s, ot, p); // string @@ -975,7 +982,9 @@ dtypesym(Type *t) tbase = t; if(isptr[t->etype] && t->sym == S && t->type->sym != S) tbase = t->type; - dupok = tbase->sym == S; + dupok = 0; + if(tbase->sym == S) + dupok = DUPOK; if(compiling_runtime && (tbase == types[tbase->etype] || @@ -1002,7 +1011,7 @@ ok: case TARRAY: if(t->bound >= 0) { - // ../../pkg/runtime/type.go:/ArrayType + // ../../runtime/type.go:/ArrayType s1 = dtypesym(t->type); t2 = typ(TARRAY); t2->type = t->type; @@ -1014,7 +1023,7 @@ ok: ot = dsymptr(s, ot, s2, 0); ot = duintptr(s, ot, t->bound); } else { - // ../../pkg/runtime/type.go:/SliceType + // ../../runtime/type.go:/SliceType s1 = dtypesym(t->type); ot = dcommontype(s, ot, t); xt = ot - 3*widthptr; @@ -1023,7 +1032,7 @@ ok: break; case TCHAN: - // ../../pkg/runtime/type.go:/ChanType + // ../../runtime/type.go:/ChanType s1 = dtypesym(t->type); ot = dcommontype(s, ot, t); xt = ot - 3*widthptr; @@ -1073,14 +1082,14 @@ ok: n++; } - // ../../pkg/runtime/type.go:/InterfaceType + // ../../runtime/type.go:/InterfaceType ot = dcommontype(s, ot, t); xt = ot - 3*widthptr; ot = dsymptr(s, ot, s, ot+widthptr+2*widthint); ot = duintxx(s, ot, n, widthint); ot = duintxx(s, ot, n, widthint); for(a=m; a; a=a->link) { - // ../../pkg/runtime/type.go:/imethod + // ../../runtime/type.go:/imethod ot = dgostringptr(s, ot, a->name); ot = dgopkgpath(s, ot, a->pkg); ot = dsymptr(s, ot, dtypesym(a->type), 0); @@ -1088,7 +1097,7 @@ ok: break; case TMAP: - // ../../pkg/runtime/type.go:/MapType + // ../../runtime/type.go:/MapType s1 = dtypesym(t->down); s2 = dtypesym(t->type); s3 = dtypesym(mapbucket(t)); @@ -1099,16 +1108,31 @@ ok: ot = dsymptr(s, ot, s2, 0); ot = dsymptr(s, ot, s3, 0); ot = dsymptr(s, ot, s4, 0); + if(t->down->width > MAXKEYSIZE) { + ot = duint8(s, ot, widthptr); + ot = duint8(s, ot, 1); // indirect + } else { + ot = duint8(s, ot, t->down->width); + ot = duint8(s, ot, 0); // not indirect + } + if(t->type->width > MAXVALSIZE) { + ot = duint8(s, ot, widthptr); + ot = duint8(s, ot, 1); // indirect + } else { + ot = duint8(s, ot, t->type->width); + ot = duint8(s, ot, 0); // not indirect + } + ot = duint16(s, ot, mapbucket(t)->width); break; case TPTR32: case TPTR64: if(t->type->etype == TANY) { - // ../../pkg/runtime/type.go:/UnsafePointerType + // ../../runtime/type.go:/UnsafePointerType ot = dcommontype(s, ot, t); break; } - // ../../pkg/runtime/type.go:/PtrType + // ../../runtime/type.go:/PtrType s1 = dtypesym(t->type); ot = dcommontype(s, ot, t); xt = ot - 3*widthptr; @@ -1116,7 +1140,7 @@ ok: break; case TSTRUCT: - // ../../pkg/runtime/type.go:/StructType + // ../../runtime/type.go:/StructType // for security, only the exported fields. n = 0; for(t1=t->type; t1!=T; t1=t1->down) { @@ -1129,7 +1153,7 @@ ok: ot = duintxx(s, ot, n, widthint); ot = duintxx(s, ot, n, widthint); for(t1=t->type; t1!=T; t1=t1->down) { - // ../../pkg/runtime/type.go:/structField + // ../../runtime/type.go:/structField if(t1->sym && !t1->embedded) { ot = dgostringptr(s, ot, t1->sym->name); if(exportname(t1->sym->name)) @@ -1150,7 +1174,7 @@ ok: break; } ot = dextratype(s, ot, t, xt); - ggloblsym(s, ot, dupok, 1); + ggloblsym(s, ot, dupok|RODATA); // generate typelink.foo pointing at s = type.foo. // The linker will leave a table of all the typelinks for @@ -1164,7 +1188,7 @@ ok: case TMAP: slink = typelinksym(t); dsymptr(slink, 0, s, 0); - ggloblsym(slink, widthptr, dupok, 1); + ggloblsym(slink, widthptr, dupok|RODATA); } } @@ -1236,8 +1260,7 @@ static Sym* dalgsym(Type *t) { int ot; - Sym *s, *hash, *eq; - char buf[100]; + Sym *s, *hash, *hashfunc, *eq, *eqfunc; // dalgsym is only called for a type that needs an algorithm table, // which implies that the type is comparable (or else it would use ANOEQ). @@ -1248,55 +1271,225 @@ dalgsym(Type *t) eq = typesymprefix(".eq", t); geneq(eq, t); - // ../../pkg/runtime/runtime.h:/Alg + // make Go funcs (closures) for calling hash and equal from Go + hashfunc = typesymprefix(".hashfunc", t); + dsymptr(hashfunc, 0, hash, 0); + ggloblsym(hashfunc, widthptr, DUPOK|RODATA); + eqfunc = typesymprefix(".eqfunc", t); + dsymptr(eqfunc, 0, eq, 0); + ggloblsym(eqfunc, widthptr, DUPOK|RODATA); + + // ../../runtime/alg.go:/typeAlg ot = 0; - ot = dsymptr(s, ot, hash, 0); - ot = dsymptr(s, ot, eq, 0); - ot = dsymptr(s, ot, pkglookup("memprint", runtimepkg), 0); - switch(t->width) { - default: - ot = dsymptr(s, ot, pkglookup("memcopy", runtimepkg), 0); - break; - case 1: - case 2: - case 4: - case 8: - case 16: - snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8); - ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0); - break; - } + ot = dsymptr(s, ot, hashfunc, 0); + ot = dsymptr(s, ot, eqfunc, 0); - ggloblsym(s, ot, 1, 1); + ggloblsym(s, ot, DUPOK|RODATA); return s; } static int -gcinline(Type *t) +usegcprog(Type *t) { - switch(t->etype) { - case TARRAY: - if(t->bound == 1) - return 1; - if(t->width <= 4*widthptr) - return 1; - break; + vlong size, nptr; + + if(!haspointers(t)) + return 0; + if(t->width == BADWIDTH) + dowidth(t); + // Calculate size of the unrolled GC mask. + nptr = (t->width+widthptr-1)/widthptr; + size = nptr; + if(size%2) + size *= 2; // repeated + size = size*gcBits/8; // 4 bits per word + // Decide whether to use unrolled GC mask or GC program. + // We could use a more elaborate condition, but this seems to work well in practice. + // For small objects GC program can't give significant reduction. + // While large objects usually contain arrays; and even if it don't + // the program uses 2-bits per word while mask uses 4-bits per word, + // so the program is still smaller. + return size > 2*widthptr; +} + +// Generates sparse GC bitmask (4 bits per word). +static void +gengcmask(Type *t, uint8 gcmask[16]) +{ + Bvec *vec; + vlong xoffset, nptr, i, j; + int half, mw; + uint8 bits, *pos; + + memset(gcmask, 0, 16); + if(!haspointers(t)) + return; + + // Generate compact mask as stacks use. + xoffset = 0; + vec = bvalloc(2*widthptr*8); + twobitwalktype1(t, &xoffset, vec); + + // Unfold the mask for the GC bitmap format: + // 4 bits per word, 2 high bits encode pointer info. + pos = (uint8*)gcmask; + nptr = (t->width+widthptr-1)/widthptr; + half = 0; + mw = 0; + // If number of words is odd, repeat the mask. + // This makes simpler handling of arrays in runtime. + for(j=0; j<=(nptr%2); j++) { + for(i=0; ialign > 0 && (*off % t->align) != 0) - fatal("dgcsym1: invalid initial alignment, %T", t); +static void +proggeninit(ProgGen *g, Sym *s) +{ + g->s = s; + g->datasize = 0; + g->ot = 0; + memset(g->data, 0, sizeof(g->data)); +} + +static void +proggenemit(ProgGen *g, uint8 v) +{ + g->ot = duint8(g->s, g->ot, v); +} + +// Emits insData block from g->data. +static void +proggendataflush(ProgGen *g) +{ + int32 i, s; + + if(g->datasize == 0) + return; + proggenemit(g, insData); + proggenemit(g, g->datasize); + s = (g->datasize + PointersPerByte - 1)/PointersPerByte; + for(i = 0; i < s; i++) + proggenemit(g, g->data[i]); + g->datasize = 0; + memset(g->data, 0, sizeof(g->data)); +} + +static void +proggendata(ProgGen *g, uint8 d) +{ + g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer); + g->datasize++; + if(g->datasize == 255) + proggendataflush(g); +} + +// Skip v bytes due to alignment, etc. +static void +proggenskip(ProgGen *g, vlong off, vlong v) +{ + vlong i; + + for(i = off; i < off+v; i++) { + if((i%widthptr) == 0) + proggendata(g, BitsScalar); + } +} + +// Emit insArray instruction. +static void +proggenarray(ProgGen *g, vlong len) +{ + int32 i; + + proggendataflush(g); + proggenemit(g, insArray); + for(i = 0; i < widthptr; i++, len >>= 8) + proggenemit(g, len); +} + +static void +proggenarrayend(ProgGen *g) +{ + proggendataflush(g); + proggenemit(g, insArrayEnd); +} + +static vlong +proggenfini(ProgGen *g) +{ + proggendataflush(g); + proggenemit(g, insEnd); + return g->ot; +} + +static void gengcprog1(ProgGen *g, Type *t, vlong *xoffset); + +// Generates GC program for large types. +static void +gengcprog(Type *t, Sym **pgc0, Sym **pgc1) +{ + Sym *gc0, *gc1; + vlong nptr, size, ot, xoffset; + ProgGen g; + + nptr = (t->width+widthptr-1)/widthptr; + size = nptr; + if(size%2) + size *= 2; // repeated twice + size = size*PointersPerByte/8; // 4 bits per word + size++; // unroll flag in the beginning, used by runtime (see runtime.markallocated) + // emity space in BSS for unrolled program + *pgc0 = S; + // Don't generate it if it's too large, runtime will unroll directly into GC bitmap. + if(size <= MaxGCMask) { + gc0 = typesymprefix(".gc", t); + ggloblsym(gc0, size, DUPOK|NOPTR); + *pgc0 = gc0; + } + + // program in RODATA + gc1 = typesymprefix(".gcprog", t); + proggeninit(&g, gc1); + xoffset = 0; + gengcprog1(&g, t, &xoffset); + ot = proggenfini(&g); + ggloblsym(gc1, ot, DUPOK|RODATA); + *pgc1 = gc1; +} + +// Recursively walks type t and writes GC program into g. +static void +gengcprog1(ProgGen *g, Type *t, vlong *xoffset) +{ + vlong fieldoffset, i, o, n; + Type *t1; - if(t->width == BADWIDTH) - dowidth(t); - switch(t->etype) { case TINT8: case TUINT8: @@ -1314,187 +1507,71 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) case TFLOAT64: case TCOMPLEX64: case TCOMPLEX128: - *off += t->width; + proggenskip(g, *xoffset, t->width); + *xoffset += t->width; break; - case TPTR32: case TPTR64: - // NOTE: Any changes here need to be made to reflect.PtrTo as well. - if(*off % widthptr != 0) - fatal("dgcsym1: invalid alignment, %T", t); - - // NOTE(rsc): Emitting GC_APTR here for *nonptrtype - // (pointer to non-pointer-containing type) means that - // we do not record 'nonptrtype' and instead tell the - // garbage collector to look up the type of the memory in - // type information stored in the heap. In effect we are telling - // the collector "we don't trust our information - use yours". - // It's not completely clear why we want to do this. - // It does have the effect that if you have a *SliceHeader and a *[]int - // pointing at the same actual slice header, *SliceHeader will not be - // used as an authoritative type for the memory, which is good: - // if the collector scanned the memory as type *SliceHeader, it would - // see no pointers inside but mark the block as scanned, preventing - // the seeing of pointers when we followed the *[]int pointer. - // Perhaps that kind of situation is the rationale. - if(!haspointers(t->type)) { - ot = duintptr(s, ot, GC_APTR); - ot = duintptr(s, ot, *off); - } else { - ot = duintptr(s, ot, GC_PTR); - ot = duintptr(s, ot, *off); - ot = dsymptr(s, ot, dgcsym(t->type), 0); - } - *off += t->width; - break; - case TUNSAFEPTR: case TFUNC: - if(*off % widthptr != 0) - fatal("dgcsym1: invalid alignment, %T", t); - ot = duintptr(s, ot, GC_APTR); - ot = duintptr(s, ot, *off); - *off += t->width; - break; - - // struct Hchan* case TCHAN: - // NOTE: Any changes here need to be made to reflect.ChanOf as well. - if(*off % widthptr != 0) - fatal("dgcsym1: invalid alignment, %T", t); - ot = duintptr(s, ot, GC_CHAN_PTR); - ot = duintptr(s, ot, *off); - ot = dsymptr(s, ot, dtypesym(t), 0); - *off += t->width; - break; - - // struct Hmap* case TMAP: - // NOTE: Any changes here need to be made to reflect.MapOf as well. - if(*off % widthptr != 0) - fatal("dgcsym1: invalid alignment, %T", t); - ot = duintptr(s, ot, GC_PTR); - ot = duintptr(s, ot, *off); - ot = dsymptr(s, ot, dgcsym(hmap(t)), 0); - *off += t->width; + proggendata(g, BitsPointer); + *xoffset += t->width; break; - - // struct { byte *str; int32 len; } case TSTRING: - if(*off % widthptr != 0) - fatal("dgcsym1: invalid alignment, %T", t); - ot = duintptr(s, ot, GC_STRING); - ot = duintptr(s, ot, *off); - *off += t->width; + proggendata(g, BitsPointer); + proggendata(g, BitsScalar); + *xoffset += t->width; break; - - // struct { Itab* tab; void* data; } - // struct { Type* type; void* data; } // When isnilinter(t)==true case TINTER: - if(*off % widthptr != 0) - fatal("dgcsym1: invalid alignment, %T", t); - if(isnilinter(t)) { - ot = duintptr(s, ot, GC_EFACE); - ot = duintptr(s, ot, *off); - } else { - ot = duintptr(s, ot, GC_IFACE); - ot = duintptr(s, ot, *off); - } - *off += t->width; + proggendata(g, BitsMultiWord); + if(isnilinter(t)) + proggendata(g, BitsEface); + else + proggendata(g, BitsIface); + *xoffset += t->width; break; - case TARRAY: - if(t->bound < -1) - fatal("dgcsym1: invalid bound, %T", t); - if(t->type->width == BADWIDTH) - dowidth(t->type); if(isslice(t)) { - // NOTE: Any changes here need to be made to reflect.SliceOf as well. - // struct { byte* array; uint32 len; uint32 cap; } - if(*off % widthptr != 0) - fatal("dgcsym1: invalid alignment, %T", t); - if(t->type->width != 0) { - ot = duintptr(s, ot, GC_SLICE); - ot = duintptr(s, ot, *off); - ot = dsymptr(s, ot, dgcsym(t->type), 0); - } else { - ot = duintptr(s, ot, GC_APTR); - ot = duintptr(s, ot, *off); - } - *off += t->width; + proggendata(g, BitsPointer); + proggendata(g, BitsScalar); + proggendata(g, BitsScalar); } else { - // NOTE: Any changes here need to be made to reflect.ArrayOf as well, - // at least once ArrayOf's gc info is implemented and ArrayOf is exported. - // struct { byte* array; uint32 len; uint32 cap; } - if(t->bound < 1 || !haspointers(t->type)) { - *off += t->width; - } else if(gcinline(t)) { - for(i=0; ibound; i++) - ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1 + t1 = t->type; + if(t1->width == 0) { + // ignore + } if(t->bound <= 1 || t->bound*t1->width < 32*widthptr) { + for(i = 0; i < t->bound; i++) + gengcprog1(g, t1, xoffset); + } else if(!haspointers(t1)) { + n = t->width; + n -= -*xoffset&(widthptr-1); // skip to next ptr boundary + proggenarray(g, (n+widthptr-1)/widthptr); + proggendata(g, BitsScalar); + proggenarrayend(g); + *xoffset -= (n+widthptr-1)/widthptr*widthptr - t->width; } else { - if(stack_size < GC_STACK_CAPACITY) { - ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC - ot = duintptr(s, ot, *off); - ot = duintptr(s, ot, t->bound); - ot = duintptr(s, ot, t->type->width); - off2 = 0; - ot = dgcsym1(s, ot, t->type, &off2, stack_size+1); // recursive call of dgcsym1 - ot = duintptr(s, ot, GC_ARRAY_NEXT); // a stack pop during GC - } else { - ot = duintptr(s, ot, GC_REGION); - ot = duintptr(s, ot, *off); - ot = duintptr(s, ot, t->width); - ot = dsymptr(s, ot, dgcsym(t), 0); - } - *off += t->width; + proggenarray(g, t->bound); + gengcprog1(g, t1, xoffset); + *xoffset += (t->bound-1)*t1->width; + proggenarrayend(g); } } break; - case TSTRUCT: o = 0; - for(t1=t->type; t1!=T; t1=t1->down) { + for(t1 = t->type; t1 != T; t1 = t1->down) { fieldoffset = t1->width; - *off += fieldoffset - o; - ot = dgcsym1(s, ot, t1->type, off, stack_size); // recursive call of dgcsym1 + proggenskip(g, *xoffset, fieldoffset - o); + *xoffset += fieldoffset - o; + gengcprog1(g, t1->type, xoffset); o = fieldoffset + t1->type->width; } - *off += t->width - o; + proggenskip(g, *xoffset, t->width - o); + *xoffset += t->width - o; break; - default: - fatal("dgcsym1: unexpected type %T", t); + fatal("gengcprog1: unexpected type, %T", t); } - - return ot; -} - -static Sym* -dgcsym(Type *t) -{ - int ot; - vlong off; - Sym *s; - - s = typesymprefix(".gc", t); - if(s->flags & SymGcgen) - return s; - s->flags |= SymGcgen; - - if(t->width == BADWIDTH) - dowidth(t); - - ot = 0; - off = 0; - ot = duintptr(s, ot, t->width); - ot = dgcsym1(s, ot, t, &off, 0); - ot = duintptr(s, ot, GC_END); - ggloblsym(s, ot, 1, 1); - - if(t->align > 0) - off = rnd(off, t->align); - if(off != t->width) - fatal("dgcsym: off=%lld, size=%lld, type %T", off, t->width, t); - - return s; } diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index fb5c2a150..0fb15c265 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -12,7 +12,7 @@ package PACKAGE // emitted by compiler, not referred to by go programs -func new(typ *byte) *any +func newobject(typ *byte) *any func panicindex() func panicslice() func panicdivide() @@ -20,12 +20,13 @@ func throwreturn() func throwinit() func panicwrap(string, string, string) -func panic(interface{}) -func recover(*int32) interface{} +func gopanic(interface{}) +func gorecover(*int32) interface{} func printbool(bool) func printfloat(float64) func printint(int64) +func printhex(uint64) func printuint(uint64) func printcomplex(complex128) func printstring(string) @@ -35,7 +36,6 @@ func printeface(any) func printslice(any) func printnl() func printsp() -func goprintf() func concatstring2(string, string) string func concatstring3(string, string, string) string @@ -53,7 +53,7 @@ func stringtoslicebyte(string) []byte func stringtoslicerune(string) []rune func stringiter(string, int) int func stringiter2(string, int) (retk int, retv rune) -func copy(to any, fr any, wid uintptr) int +func slicecopy(to any, fr any, wid uintptr) int func slicestringcopy(to any, fr any) int // interface conversions @@ -84,8 +84,6 @@ func efaceeq(i1 any, i2 any) (ret bool) func ifacethash(i1 any) (ret uint32) func efacethash(i1 any) (ret uint32) -func equal(typ *byte, x1, x2 any) (ret bool) - // *byte is really *runtime.Type func makemap(mapType *byte, hint int64) (hmap map[any]any) func mapaccess1(mapType *byte, hmap map[any]any, key *any) (val *any) @@ -108,11 +106,25 @@ func chanrecv2(chanType *byte, hchan <-chan any, elem *any) bool func chansend1(chanType *byte, hchan chan<- any, elem *any) func closechan(hchan any) +// *byte is really *runtime.Type +func writebarrierptr(dst *any, src any) +func writebarrierstring(dst *any, src any) +func writebarrierslice(dst *any, src any) +func writebarrieriface(dst *any, src any) + +// The unused *byte argument makes sure that src is 2-pointer-aligned, +// which is the maximum alignment on NaCl amd64p32 +// (and possibly on 32-bit systems if we start 64-bit aligning uint64s). +func writebarrierfat2(dst *any, _ *byte, src any) +func writebarrierfat3(dst *any, _ *byte, src any) +func writebarrierfat4(dst *any, _ *byte, src any) +func writebarrierfat(typ *byte, dst *any, src *any) + func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool -func newselect(size int32) (sel *byte) +func newselect(sel *byte, selsize int64, size int32) func selectsend(sel *byte, hchan chan<- any, elem *any) (selected bool) func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool) func selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) (selected bool) @@ -124,12 +136,12 @@ func makeslice(typ *byte, nel int64, cap int64) (ary []any) func growslice(typ *byte, old []any, n int64) (ary []any) func memmove(to *any, frm *any, length uintptr) -func memequal(eq *bool, size uintptr, x, y *any) -func memequal8(eq *bool, size uintptr, x, y *any) -func memequal16(eq *bool, size uintptr, x, y *any) -func memequal32(eq *bool, size uintptr, x, y *any) -func memequal64(eq *bool, size uintptr, x, y *any) -func memequal128(eq *bool, size uintptr, x, y *any) +func memequal(x, y *any, size uintptr) bool +func memequal8(x, y *any, size uintptr) bool +func memequal16(x, y *any, size uintptr) bool +func memequal32(x, y *any, size uintptr) bool +func memequal64(x, y *any, size uintptr) bool +func memequal128(x, y *any, size uintptr) bool // only used on 32-bit func int64div(int64, int64) int64 diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c index 58a120674..965ad277f 100644 --- a/src/cmd/gc/select.c +++ b/src/cmd/gc/select.c @@ -10,6 +10,8 @@ #include #include "go.h" +static Type* selecttype(int32 size); + void typecheckselect(Node *sel) { @@ -95,7 +97,7 @@ void walkselect(Node *sel) { int lno, i; - Node *n, *r, *a, *var, *cas, *dflt, *ch; + Node *n, *r, *a, *var, *selv, *cas, *dflt, *ch; NodeList *l, *init; if(sel->list == nil && sel->xoffset != 0) @@ -257,8 +259,12 @@ walkselect(Node *sel) // generate sel-struct setlineno(sel); - var = temp(ptrto(types[TUINT8])); - r = nod(OAS, var, mkcall("newselect", var->type, nil, nodintconst(sel->xoffset))); + selv = temp(selecttype(sel->xoffset)); + r = nod(OAS, selv, N); + typecheck(&r, Etop); + init = list(init, r); + var = conv(conv(nod(OADDR, selv, N), types[TUNSAFEPTR]), ptrto(types[TUINT8])); + r = mkcall("newselect", T, nil, var, nodintconst(selv->type->width), nodintconst(sel->xoffset)); typecheck(&r, Etop); init = list(init, r); @@ -301,6 +307,8 @@ walkselect(Node *sel) break; } } + // selv is no longer alive after use. + r->nbody = list(r->nbody, nod(OVARKILL, selv, N)); r->nbody = concat(r->nbody, cas->nbody); r->nbody = list(r->nbody, nod(OBREAK, N, N)); init = list(init, r); @@ -316,3 +324,54 @@ out: walkstmtlist(sel->nbody); lineno = lno; } + +// Keep in sync with src/runtime/chan.h. +static Type* +selecttype(int32 size) +{ + Node *sel, *sudog, *scase, *arr; + + // TODO(dvyukov): it's possible to generate SudoG and Scase only once + // and then cache; and also cache Select per size. + sudog = nod(OTSTRUCT, N, N); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("g")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("selectdone")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("link")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("prev")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64]))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("nrelease")), typenod(types[TINT32]))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("waitlink")), typenod(ptrto(types[TUINT8])))); + typecheck(&sudog, Etype); + sudog->type->noalg = 1; + sudog->type->local = 1; + + scase = nod(OTSTRUCT, N, N); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8])))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("chan")), typenod(ptrto(types[TUINT8])))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("pc")), typenod(types[TUINTPTR]))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("kind")), typenod(types[TUINT16]))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("so")), typenod(types[TUINT16]))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("receivedp")), typenod(ptrto(types[TUINT8])))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64]))); + typecheck(&scase, Etype); + scase->type->noalg = 1; + scase->type->local = 1; + + sel = nod(OTSTRUCT, N, N); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("tcase")), typenod(types[TUINT16]))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("ncase")), typenod(types[TUINT16]))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorder")), typenod(ptrto(types[TUINT8])))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorder")), typenod(ptrto(types[TUINT8])))); + arr = nod(OTARRAY, nodintconst(size), scase); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("scase")), arr)); + arr = nod(OTARRAY, nodintconst(size), typenod(ptrto(types[TUINT8]))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorderarr")), arr)); + arr = nod(OTARRAY, nodintconst(size), typenod(types[TUINT16])); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorderarr")), arr)); + typecheck(&sel, Etype); + sel->type->noalg = 1; + sel->type->local = 1; + + return sel->type; +} diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index 59804cd8d..8ad7ae7ab 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -17,7 +17,6 @@ enum InitPending = 2, }; -static int iszero(Node*); static void initplan(Node*); static NodeList *initlist; static void init2(Node*, NodeList**); @@ -207,7 +206,7 @@ init2(Node *n, NodeList **out) if(n->op == OCLOSURE) init2list(n->closure->nbody, out); - if(n->op == ODOTMETH) + if(n->op == ODOTMETH || n->op == OCALLPART) init2(n->type->nname, out); } @@ -633,11 +632,14 @@ structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init) a = nod(ODOT, var, newname(index->sym)); a = nod(OAS, a, value); typecheck(&a, Etop); - walkexpr(&a, init); if(pass == 1) { + walkexpr(&a, init); // add any assignments in r to top if(a->op != OAS) fatal("structlit: not as"); a->dodata = 2; + } else { + orderstmtinplace(&a); + walkstmt(&a); } *init = list(*init, a); } @@ -693,11 +695,14 @@ arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init) a = nod(OINDEX, var, index); a = nod(OAS, a, value); typecheck(&a, Etop); - walkexpr(&a, init); // add any assignments in r to top if(pass == 1) { + walkexpr(&a, init); if(a->op != OAS) - fatal("structlit: not as"); + fatal("arraylit: not as"); a->dodata = 2; + } else { + orderstmtinplace(&a); + walkstmt(&a); } *init = list(*init, a); } @@ -807,7 +812,8 @@ slicelit(int ctxt, Node *n, Node *var, NodeList **init) // make slice out of heap (5) a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N))); typecheck(&a, Etop); - walkexpr(&a, init); + orderstmtinplace(&a); + walkstmt(&a); *init = list(*init, a); // put dynamics into slice (6) @@ -839,7 +845,8 @@ slicelit(int ctxt, Node *n, Node *var, NodeList **init) // build list of var[c] = expr a = nod(OAS, a, value); typecheck(&a, Etop); - walkexpr(&a, init); + orderstmtinplace(&a); + walkstmt(&a); *init = list(*init, a); } } @@ -1060,7 +1067,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init) if(t->etype != TSTRUCT) fatal("anylit: not struct"); - if(simplename(var)) { + if(simplename(var) && count(n->list) > 4) { if(ctxt == 0) { // lay out static data @@ -1083,7 +1090,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init) } // initialize of not completely specified - if(count(n->list) < structcount(t)) { + if(simplename(var) || count(n->list) < structcount(t)) { a = nod(OAS, var, N); typecheck(&a, Etop); walkexpr(&a, init); @@ -1100,7 +1107,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init) break; } - if(simplename(var)) { + if(simplename(var) && count(n->list) > 4) { if(ctxt == 0) { // lay out static data @@ -1123,7 +1130,7 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init) } // initialize of not completely specified - if(count(n->list) < t->bound) { + if(simplename(var) || count(n->list) < t->bound) { a = nod(OAS, var, N); typecheck(&a, Etop); walkexpr(&a, init); @@ -1348,7 +1355,6 @@ no: return 0; } -static int iszero(Node*); static int isvaluelit(Node*); static InitEntry* entry(InitPlan*); static void addvalue(InitPlan*, vlong, Node*, Node*); @@ -1432,7 +1438,7 @@ addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n) e->expr = n; } -static int +int iszero(Node *n) { NodeList *l; diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 72a9ac20c..c3bc5af3b 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -529,7 +529,8 @@ algtype1(Type *t, Type **bad) if(bad) *bad = T; - + if(t->broke) + return AMEM; if(t->noalg) return ANOEQ; @@ -656,11 +657,15 @@ maptype(Type *key, Type *val) { Type *t; Type *bad; - int atype; + int atype, mtype; if(key != nil) { atype = algtype1(key, &bad); - switch(bad == T ? key->etype : bad->etype) { + if(bad == T) + mtype = key->etype; + else + mtype = bad->etype; + switch(mtype) { default: if(atype == ANOEQ) yyerror("invalid map key type %T", key); @@ -2625,9 +2630,10 @@ hashmem(Type *t) n = newname(sym); n->class = PFUNC; tfn = nod(OTFUNC, N, N); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR])))); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); typecheck(&tfn, Etype); n->type = tfn->type; return n; @@ -2673,9 +2679,10 @@ hashfor(Type *t) n = newname(sym); n->class = PFUNC; tfn = nod(OTFUNC, N, N); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR])))); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); typecheck(&tfn, Etype); n->type = tfn->type; return n; @@ -2687,7 +2694,7 @@ hashfor(Type *t) void genhash(Sym *sym, Type *t) { - Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn; + Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn, *r; Node *hashel; Type *first, *t1; int old_safemode; @@ -2700,21 +2707,23 @@ genhash(Sym *sym, Type *t) dclcontext = PEXTERN; markdcl(); - // func sym(h *uintptr, s uintptr, p *T) + // func sym(p *T, s uintptr, h uintptr) uintptr fn = nod(ODCLFUNC, N, N); fn->nname = newname(sym); fn->nname->class = PFUNC; tfn = nod(OTFUNC, N, N); fn->nname->ntype = tfn; - n = nod(ODCLFIELD, newname(lookup("h")), typenod(ptrto(types[TUINTPTR]))); + n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t))); tfn->list = list(tfn->list, n); - nh = n->left; + np = n->left; n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR])); tfn->list = list(tfn->list, n); - n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t))); + n = nod(ODCLFIELD, newname(lookup("h")), typenod(types[TUINTPTR])); tfn->list = list(tfn->list, n); - np = n->left; + nh = n->left; + n = nod(ODCLFIELD, N, typenod(types[TUINTPTR])); // return value + tfn->rlist = list(tfn->rlist, n); funchdr(fn); typecheck(&fn->nname->ntype, Etype); @@ -2740,15 +2749,17 @@ genhash(Sym *sym, Type *t) colasdefn(n->list, n); ni = n->list->n; - // *h = *h<<3 | *h>>61 + // TODO: with aeshash we don't need these shift/mul parts + + // h = h<<3 | h>>61 n->nbody = list(n->nbody, nod(OAS, - nod(OIND, nh, N), + nh, nod(OOR, - nod(OLSH, nod(OIND, nh, N), nodintconst(3)), - nod(ORSH, nod(OIND, nh, N), nodintconst(widthptr*8-3))))); + nod(OLSH, nh, nodintconst(3)), + nod(ORSH, nh, nodintconst(widthptr*8-3))))); - // *h *= mul + // h *= mul // Same multipliers as in runtime.memhash. if(widthptr == 4) mul = 3267000013LL; @@ -2756,19 +2767,19 @@ genhash(Sym *sym, Type *t) mul = 23344194077549503LL; n->nbody = list(n->nbody, nod(OAS, - nod(OIND, nh, N), - nod(OMUL, nod(OIND, nh, N), nodintconst(mul)))); + nh, + nod(OMUL, nh, nodintconst(mul)))); - // hashel(h, sizeof(p[i]), &p[i]) + // h = hashel(&p[i], sizeof(p[i]), h) call = nod(OCALL, hashel, N); - call->list = list(call->list, nh); - call->list = list(call->list, nodintconst(t->type->width)); nx = nod(OINDEX, np, ni); nx->bounded = 1; na = nod(OADDR, nx, N); na->etype = 1; // no escape to heap call->list = list(call->list, na); - n->nbody = list(n->nbody, call); + call->list = list(call->list, nodintconst(t->type->width)); + call->list = list(call->list, nh); + n->nbody = list(n->nbody, nod(OAS, nh, call)); fn->nbody = list(fn->nbody, n); break; @@ -2793,15 +2804,15 @@ genhash(Sym *sym, Type *t) if(first != T) { size = offend - first->width; // first->width is offset hashel = hashmem(first->type); - // hashel(h, size, &p.first) + // h = hashel(&p.first, size, h) call = nod(OCALL, hashel, N); - call->list = list(call->list, nh); - call->list = list(call->list, nodintconst(size)); nx = nod(OXDOT, np, newname(first->sym)); // TODO: fields from other packages? na = nod(OADDR, nx, N); na->etype = 1; // no escape to heap call->list = list(call->list, na); - fn->nbody = list(fn->nbody, call); + call->list = list(call->list, nodintconst(size)); + call->list = list(call->list, nh); + fn->nbody = list(fn->nbody, nod(OAS, nh, call)); first = T; } @@ -2812,20 +2823,21 @@ genhash(Sym *sym, Type *t) // Run hash for this field. hashel = hashfor(t1->type); - // hashel(h, size, &p.t1) + // h = hashel(&p.t1, size, h) call = nod(OCALL, hashel, N); - call->list = list(call->list, nh); - call->list = list(call->list, nodintconst(t1->type->width)); nx = nod(OXDOT, np, newname(t1->sym)); // TODO: fields from other packages? na = nod(OADDR, nx, N); na->etype = 1; // no escape to heap call->list = list(call->list, na); - fn->nbody = list(fn->nbody, call); + call->list = list(call->list, nodintconst(t1->type->width)); + call->list = list(call->list, nh); + fn->nbody = list(fn->nbody, nod(OAS, nh, call)); } - // make sure body is not empty. - fn->nbody = list(fn->nbody, nod(ORETURN, N, N)); break; } + r = nod(ORETURN, N, N); + r->list = list(r->list, nh); + fn->nbody = list(fn->nbody, r); if(debug['r']) dumplist("genhash body", fn->nbody); @@ -2849,18 +2861,19 @@ genhash(Sym *sym, Type *t) } // Return node for -// if p.field != q.field { *eq = false; return } +// if p.field != q.field { return false } static Node* -eqfield(Node *p, Node *q, Node *field, Node *eq) +eqfield(Node *p, Node *q, Node *field) { - Node *nif, *nx, *ny; + Node *nif, *nx, *ny, *r; nx = nod(OXDOT, p, field); ny = nod(OXDOT, q, field); nif = nod(OIF, N, N); nif->ntest = nod(ONE, nx, ny); - nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, eq, N), nodbool(0))); - nif->nbody = list(nif->nbody, nod(ORETURN, N, N)); + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(0)); + nif->nbody = list(nif->nbody, r); return nif; } @@ -2889,11 +2902,11 @@ eqmemfunc(vlong size, Type *type) } // Return node for -// if memequal(size, &p.field, &q.field, eq); !*eq { return } +// if !memequal(&p.field, &q.field, size) { return false } static Node* -eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq) +eqmem(Node *p, Node *q, Node *field, vlong size) { - Node *nif, *nx, *ny, *call; + Node *nif, *nx, *ny, *call, *r; nx = nod(OADDR, nod(OXDOT, p, field), N); nx->etype = 1; // does not escape @@ -2903,15 +2916,16 @@ eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq) typecheck(&ny, Erv); call = nod(OCALL, eqmemfunc(size, nx->type->type), N); - call->list = list(call->list, eq); - call->list = list(call->list, nodintconst(size)); call->list = list(call->list, nx); call->list = list(call->list, ny); + call->list = list(call->list, nodintconst(size)); nif = nod(OIF, N, N); nif->ninit = list(nif->ninit, call); - nif->ntest = nod(ONOT, nod(OIND, eq, N), N); - nif->nbody = list(nif->nbody, nod(ORETURN, N, N)); + nif->ntest = nod(ONOT, call, N); + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(0)); + nif->nbody = list(nif->nbody, r); return nif; } @@ -2921,7 +2935,7 @@ eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq) void geneq(Sym *sym, Type *t) { - Node *n, *fn, *np, *neq, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange; + Node *n, *fn, *np, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange, *r; Type *t1, *first; int old_safemode; int64 size; @@ -2934,24 +2948,23 @@ geneq(Sym *sym, Type *t) dclcontext = PEXTERN; markdcl(); - // func sym(eq *bool, s uintptr, p, q *T) + // func sym(p, q *T, s uintptr) bool fn = nod(ODCLFUNC, N, N); fn->nname = newname(sym); fn->nname->class = PFUNC; tfn = nod(OTFUNC, N, N); fn->nname->ntype = tfn; - n = nod(ODCLFIELD, newname(lookup("eq")), typenod(ptrto(types[TBOOL]))); - tfn->list = list(tfn->list, n); - neq = n->left; - n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR])); - tfn->list = list(tfn->list, n); n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t))); tfn->list = list(tfn->list, n); np = n->left; n = nod(ODCLFIELD, newname(lookup("q")), typenod(ptrto(t))); tfn->list = list(tfn->list, n); nq = n->left; + n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR])); + tfn->list = list(tfn->list, n); + n = nod(ODCLFIELD, N, typenod(types[TBOOL])); + tfn->rlist = list(tfn->rlist, n); funchdr(fn); @@ -2977,7 +2990,7 @@ geneq(Sym *sym, Type *t) colasdefn(nrange->list, nrange); ni = nrange->list->n; - // if p[i] != q[i] { *eq = false; return } + // if p[i] != q[i] { return false } nx = nod(OINDEX, np, ni); nx->bounded = 1; ny = nod(OINDEX, nq, ni); @@ -2985,13 +2998,11 @@ geneq(Sym *sym, Type *t) nif = nod(OIF, N, N); nif->ntest = nod(ONE, nx, ny); - nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, neq, N), nodbool(0))); - nif->nbody = list(nif->nbody, nod(ORETURN, N, N)); + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(0)); + nif->nbody = list(nif->nbody, r); nrange->nbody = list(nrange->nbody, nif); fn->nbody = list(fn->nbody, nrange); - - // *eq = true; - fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1))); break; case TSTRUCT: @@ -3016,16 +3027,16 @@ geneq(Sym *sym, Type *t) // cross-package unexported fields. if(first != T) { if(first->down == t1) { - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym))); } else if(first->down->down == t1) { - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym))); first = first->down; if(!isblanksym(first->sym)) - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym))); } else { // More than two fields: use memequal. size = offend - first->width; // first->width is offset - fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size, neq)); + fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size)); } first = T; } @@ -3035,14 +3046,17 @@ geneq(Sym *sym, Type *t) continue; // Check this field, which is not just memory. - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym))); } - // *eq = true; - fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1))); break; } + // return true + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(1)); + fn->nbody = list(fn->nbody, r); + if(debug['r']) dumplist("geneq body", fn->nbody); @@ -3445,7 +3459,7 @@ smagic(Magic *m) mask = 0xffffffffLL; break; case 64: - mask = 0xffffffffffffffffLL; + mask = 0xffffffffffffffffULL; break; } two31 = mask ^ (mask>>1); @@ -3453,7 +3467,7 @@ smagic(Magic *m) p = m->w-1; ad = m->sd; if(m->sd < 0) - ad = -m->sd; + ad = -(uvlong)m->sd; // bad denominators if(ad == 0 || ad == 1 || ad == two31) { @@ -3543,7 +3557,7 @@ umagic(Magic *m) mask = 0xffffffffLL; break; case 64: - mask = 0xffffffffffffffffLL; + mask = 0xffffffffffffffffULL; break; } two31 = mask ^ (mask>>1); @@ -3628,7 +3642,7 @@ ngotype(Node *n) * users if we escape that as little as possible. * * If you edit this, edit ../ld/lib.c:/^pathtoprefix too. - * If you edit this, edit ../../pkg/debug/goobj/read.go:/importPathToPrefix too. + * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too. */ static char* pathtoprefix(char *s) @@ -3785,3 +3799,42 @@ checknil(Node *x, NodeList **init) n->typecheck = 1; *init = list(*init, n); } + +/* + * Can this type be stored directly in an interface word? + */ +int +isdirectiface(Type *t) +{ + // Setting IfacePointerOnly = 1 changes the + // interface representation so that the data word + // in an interface value must always be a pointer. + // Setting it to 0 uses the original representation, + // where the data word can hold a pointer or any + // non-pointer value no bigger than a pointer. + enum { + IfacePointerOnly = 1, + }; + + if(IfacePointerOnly) { + switch(t->etype) { + case TPTR32: + case TPTR64: + case TCHAN: + case TMAP: + case TFUNC: + case TUNSAFEPTR: + return 1; + case TARRAY: + // Array of 1 direct iface type can be direct. + return t->bound == 1 && isdirectiface(t->type); + case TSTRUCT: + // Struct with 1 field of direct iface type can be direct. + return t->type != T && t->type->down == T && isdirectiface(t->type->type); + } + return 0; + } + + dowidth(t); + return t->width <= widthptr; +} diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c index ce0190507..e1d8af878 100644 --- a/src/cmd/gc/swt.c +++ b/src/cmd/gc/swt.c @@ -34,6 +34,7 @@ struct Case Case* link; // linked list to link }; #define C ((Case*)nil) +/*c2go Case *C; */ void dumpcase(Case *c0) diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index c50b2285b..714c66268 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -33,7 +33,7 @@ static void stringtoarraylit(Node**); static Node* resolve(Node*); static void checkdefergo(Node*); static int checkmake(Type*, char*, Node*); -static int checksliceindex(Node*, Type*); +static int checksliceindex(Node*, Node*, Type*); static int checksliceconst(Node*, Node*); static NodeList* typecheckdefstack; @@ -311,6 +311,7 @@ typecheck1(Node **np, int top) Type *t, *tp, *missing, *have, *badtype; Val v; char *why, *desc, descbuf[64]; + vlong x; n = *np; @@ -382,16 +383,6 @@ reswitch: if(n->type == T) goto error; break; - - case OTPAREN: - ok |= Etype; - l = typecheck(&n->left, Etype); - if(l->type == T) - goto error; - n->op = OTYPE; - n->type = l->type; - n->left = N; - break; case OTARRAY: ok |= Etype; @@ -418,7 +409,10 @@ reswitch: v = toint(l->val); break; default: - yyerror("invalid array bound %N", l); + if(l->type != T && isint[l->type->etype] && l->op != OLITERAL) + yyerror("non-constant array bound %N", l); + else + yyerror("invalid array bound %N", l); goto error; } t->bound = mpgetfix(v.u.xval); @@ -535,19 +529,6 @@ reswitch: op = n->etype; goto arith; - case OADDPTR: - ok |= Erv; - l = typecheck(&n->left, Erv); - r = typecheck(&n->right, Erv); - if(l->type == T || r->type == T) - goto error; - if(l->type->etype != tptr) - fatal("bad OADDPTR left type %E for %N", l->type->etype, n->left); - if(r->type->etype != TUINTPTR) - fatal("bad OADDPTR right type %E for %N", r->type->etype, n->right); - n->type = types[tptr]; - goto ret; - case OADD: case OAND: case OANDAND: @@ -620,6 +601,10 @@ reswitch: } if(t->etype != TIDEAL && !eqtype(l->type, r->type)) { defaultlit2(&l, &r, 1); + if(n->op == OASOP && n->implicit) { + yyerror("invalid operation: %N (non-numeric type %T)", n, l->type); + goto error; + } yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type); goto error; } @@ -756,10 +741,6 @@ reswitch: l = n->left; if((t = l->type) == T) goto error; - // top&Eindir means this is &x in *&x. (or the arg to built-in print) - // n->etype means code generator flagged it as non-escaping. - if(debug['N'] && !(top & Eindir) && !n->etype) - addrescapes(n->left); n->type = ptrto(t); goto ret; @@ -915,11 +896,12 @@ reswitch: break; } if(isconst(n->right, CTINT)) { - if(mpgetfix(n->right->val.u.xval) < 0) + x = mpgetfix(n->right->val.u.xval); + if(x < 0) yyerror("invalid %s index %N (index must be non-negative)", why, n->right); - else if(isfixedarray(t) && t->bound > 0 && mpgetfix(n->right->val.u.xval) >= t->bound) + else if(isfixedarray(t) && t->bound > 0 && x >= t->bound) yyerror("invalid array index %N (out of bounds for %d-element array)", n->right, t->bound); - else if(isconst(n->left, CTSTR) && mpgetfix(n->right->val.u.xval) >= n->left->val.u.sval->len) + else if(isconst(n->left, CTSTR) && x >= n->left->val.u.sval->len) yyerror("invalid string index %N (out of bounds for %d-byte string)", n->right, n->left->val.u.sval->len); else if(mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0) yyerror("invalid %s index %N (index too large)", why, n->right); @@ -1019,9 +1001,9 @@ reswitch: yyerror("cannot slice %N (type %T)", l, t); goto error; } - if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0) + if((lo = n->right->left) != N && checksliceindex(l, lo, tp) < 0) goto error; - if((hi = n->right->right) != N && checksliceindex(hi, tp) < 0) + if((hi = n->right->right) != N && checksliceindex(l, hi, tp) < 0) goto error; if(checksliceconst(lo, hi) < 0) goto error; @@ -1068,11 +1050,11 @@ reswitch: yyerror("cannot slice %N (type %T)", l, t); goto error; } - if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0) + if((lo = n->right->left) != N && checksliceindex(l, lo, tp) < 0) goto error; - if((mid = n->right->right->left) != N && checksliceindex(mid, tp) < 0) + if((mid = n->right->right->left) != N && checksliceindex(l, mid, tp) < 0) goto error; - if((hi = n->right->right->right) != N && checksliceindex(hi, tp) < 0) + if((hi = n->right->right->right) != N && checksliceindex(l, hi, tp) < 0) goto error; if(checksliceconst(lo, hi) < 0 || checksliceconst(lo, mid) < 0 || checksliceconst(mid, hi) < 0) goto error; @@ -1842,7 +1824,7 @@ out: } static int -checksliceindex(Node *r, Type *tp) +checksliceindex(Node *l, Node *r, Type *tp) { Type *t; @@ -1859,6 +1841,9 @@ checksliceindex(Node *r, Type *tp) } else if(tp != nil && tp->bound > 0 && mpgetfix(r->val.u.xval) > tp->bound) { yyerror("invalid slice index %N (out of bounds for %d-element array)", r, tp->bound); return -1; + } else if(isconst(l, CTSTR) && mpgetfix(r->val.u.xval) > l->val.u.sval->len) { + yyerror("invalid slice index %N (out of bounds for %d-byte string)", r, l->val.u.sval->len); + return -1; } else if(mpcmpfixfix(r->val.u.xval, maxintval[TINT]) > 0) { yyerror("invalid slice index %N (index too large)", r); return -1; @@ -2139,18 +2124,19 @@ lookdot(Node *n, Type *t, int dostrcmp) if(!eqtype(rcvr, tt)) { if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) { checklvalue(n->left, "call pointer method on"); - if(debug['N']) - addrescapes(n->left); n->left = nod(OADDR, n->left, N); n->left->implicit = 1; typecheck(&n->left, Etype|Erv); - } else if(tt->etype == tptr && eqtype(tt->type, rcvr)) { + } else if(tt->etype == tptr && rcvr->etype != tptr && eqtype(tt->type, rcvr)) { n->left = nod(OIND, n->left, N); n->left->implicit = 1; typecheck(&n->left, Etype|Erv); - } else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), rcvr)) { + } else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), derefall(rcvr))) { yyerror("calling method %N with receiver %lN requires explicit dereference", n->right, n->left); while(tt->etype == tptr) { + // Stop one level early for method with pointer receiver. + if(rcvr->etype == tptr && tt->type->etype != tptr) + break; n->left = nod(OIND, n->left, N); n->left->implicit = 1; typecheck(&n->left, Etype|Erv); @@ -2831,6 +2817,33 @@ checkassignlist(NodeList *l) checkassign(l->n); } +// Check whether l and r are the same side effect-free expression, +// so that it is safe to reuse one instead of computing both. +static int +samesafeexpr(Node *l, Node *r) +{ + if(l->op != r->op || !eqtype(l->type, r->type)) + return 0; + + switch(l->op) { + case ONAME: + case OCLOSUREVAR: + return l == r; + + case ODOT: + case ODOTPTR: + return l->right != nil && r->right != nil && l->right->sym == r->right->sym && samesafeexpr(l->left, r->left); + + case OIND: + return samesafeexpr(l->left, r->left); + + case OINDEX: + return samesafeexpr(l->left, r->left) && samesafeexpr(l->right, r->right); + } + + return 0; +} + /* * type check assignment. * if this assignment is the definition of a var on the left side, @@ -2868,6 +2881,29 @@ typecheckas(Node *n) n->typecheck = 1; if(n->left->typecheck == 0) typecheck(&n->left, Erv | Easgn); + + // Recognize slices being updated in place, for better code generation later. + // Don't rewrite if using race detector, to avoid needing to teach race detector + // about this optimization. + if(n->left && n->left->op != OINDEXMAP && n->right && !flag_race) { + switch(n->right->op) { + case OSLICE: + case OSLICE3: + case OSLICESTR: + // For x = x[0:y], x can be updated in place, without touching pointer. + if(samesafeexpr(n->left, n->right->left) && (n->right->right->left == N || iszero(n->right->right->left))) + n->right->reslice = 1; + break; + + case OAPPEND: + // For x = append(x, ...), x can be updated in place when there is capacity, + // without touching the pointer; otherwise the emitted code to growslice + // can take care of updating the pointer, and only in that case. + if(n->right->list != nil && samesafeexpr(n->left, n->right->list->n)) + n->right->reslice = 1; + break; + } + } } static void @@ -2975,7 +3011,7 @@ typecheckas2(Node *n) if(l->defn == n) l->type = r->type; l = n->list->next->n; - if(l->type != T) + if(l->type != T && l->type->etype != TBOOL) checkassignto(types[TBOOL], l); if(l->defn == n && l->ntype == N) l->type = types[TBOOL]; diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 1cb25512e..ff9b36208 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -5,8 +5,11 @@ #include #include #include "go.h" +#include "../ld/textflag.h" -static Node* walkprint(Node*, NodeList**, int); +static Node* walkprint(Node*, NodeList**); +static Node* writebarrierfn(char*, Type*, Type*); +static Node* applywritebarrier(Node*, NodeList**); static Node* mapfn(char*, Type*); static Node* mapfndel(char*, Type*); static Node* ascompatee1(int, Node*, Node*, NodeList**); @@ -29,6 +32,7 @@ static void walkmul(Node**, NodeList**); static void walkdiv(Node**, NodeList**); static int bounded(Node*, int64); static Mpint mpzero; +static void walkprintfunc(Node**, NodeList**); void walk(Node *fn) @@ -134,6 +138,8 @@ walkstmt(Node **np) n = *np; if(n == N) return; + if(n->dodata == 2) // don't walk, generated by anylit. + return; setlineno(n); @@ -221,8 +227,7 @@ walkstmt(Node **np) switch(n->left->op) { case OPRINT: case OPRINTN: - walkexprlist(n->left->list, &n->ninit); - n->left = walkprint(n->left, &n->ninit, 1); + walkprintfunc(&n->left, &n->ninit); break; case OCOPY: n->left = copyany(n->left, &n->ninit, 1); @@ -255,8 +260,7 @@ walkstmt(Node **np) switch(n->left->op) { case OPRINT: case OPRINTN: - walkexprlist(n->left->list, &n->ninit); - n->left = walkprint(n->left, &n->ninit, 1); + walkprintfunc(&n->left, &n->ninit); break; case OCOPY: n->left = copyany(n->left, &n->ninit, 1); @@ -538,15 +542,15 @@ walkexpr(Node **np, NodeList **init) case OPRINT: case OPRINTN: walkexprlist(n->list, init); - n = walkprint(n, init, 0); + n = walkprint(n, init); goto ret; case OPANIC: - n = mkcall("panic", T, init, n->left); + n = mkcall("gopanic", T, init, n->left); goto ret; case ORECOVER: - n = mkcall("recover", n->type, init, nod(OADDR, nodfp, N)); + n = mkcall("gorecover", n->type, init, nod(OADDR, nodfp, N)); goto ret; case OLITERAL: @@ -609,7 +613,7 @@ walkexpr(Node **np, NodeList **init) if(oaslit(n, init)) goto ret; - if(n->right == N) + if(n->right == N || iszero(n->right) && !flag_race) goto ret; switch(n->right->op) { @@ -632,6 +636,7 @@ walkexpr(Node **np, NodeList **init) r = convas(nod(OAS, n->left, n->right), init); r->dodata = n->dodata; n = r; + n = applywritebarrier(n, init); } goto ret; @@ -643,6 +648,8 @@ walkexpr(Node **np, NodeList **init) walkexprlistsafe(n->rlist, init); ll = ascompatee(OAS, n->list, n->rlist, init); ll = reorder3(ll); + for(lr = ll; lr != nil; lr = lr->next) + lr->n = applywritebarrier(lr->n, init); n = liststmt(ll); goto ret; @@ -655,6 +662,8 @@ walkexpr(Node **np, NodeList **init) walkexpr(&r, init); ll = ascompatet(n->op, n->list, &r->type, 0, init); + for(lr = ll; lr != nil; lr = lr->next) + lr->n = applywritebarrier(lr->n, init); n = liststmt(concat(list1(r), ll)); goto ret; @@ -672,7 +681,7 @@ walkexpr(Node **np, NodeList **init) n1 = nod(OADDR, n->list->n, N); n1->etype = 1; // addr does not escape fn = chanfn("chanrecv2", 2, r->left->type); - r = mkcall1(fn, types[TBOOL], init, typename(r->left->type), r->left, n1); + r = mkcall1(fn, n->list->next->n->type, init, typename(r->left->type), r->left, n1); n = nod(OAS, n->list->next->n, r); typecheck(&n, Etop); goto ret; @@ -687,7 +696,7 @@ walkexpr(Node **np, NodeList **init) walkexpr(&r->right, init); t = r->left->type; p = nil; - if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing. + if(t->type->width <= 128) { // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing. switch(simsimtype(t->down)) { case TINT32: case TUINT32: @@ -722,6 +731,12 @@ walkexpr(Node **np, NodeList **init) var->typecheck = 1; fn = mapfn(p, t); r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, key); + + // mapaccess2* returns a typed bool, but due to spec changes, + // the boolean result of i.(T) is now untyped so we make it the + // same type as the variable on the lhs. + if(!isblank(n->list->next->n)) + r->type->type->down->type = n->list->next->n->type; n->rlist = list1(r); n->op = OAS2FUNC; n->list->n = var; @@ -769,6 +784,12 @@ walkexpr(Node **np, NodeList **init) *p = '\0'; fn = syslook(buf, 1); + + // runtime.assert(E|I)2TOK returns a typed bool, but due + // to spec changes, the boolean result of i.(T) is now untyped + // so we make it the same type as the variable on the lhs. + if(!isblank(n->list->next->n)) + fn->type->type->down->type->type = n->list->next->n->type; ll = list1(typename(r->type)); ll = list(ll, r->left); argtype(fn, r->left->type); @@ -821,9 +842,7 @@ walkexpr(Node **np, NodeList **init) walkexpr(&n->left, init); // Optimize convT2E as a two-word copy when T is uintptr-shaped. - if(!isinter(n->left->type) && isnilinter(n->type) && - (n->left->type->width == widthptr) && - isint[simsimtype(n->left->type)]) { + if(isnilinter(n->type) && isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) { l = nod(OEFACE, typename(n->left->type), n->left); l->type = n->type; l->typecheck = n->typecheck; @@ -865,14 +884,13 @@ walkexpr(Node **np, NodeList **init) l->class = PEXTERN; l->xoffset = 0; sym->def = l; - ggloblsym(sym, widthptr, 1, 0); + ggloblsym(sym, widthptr, DUPOK|NOPTR); } l = nod(OADDR, sym->def, N); l->addable = 1; ll = list(ll, l); - if(n->left->type->width == widthptr && - isint[simsimtype(n->left->type)]) { + if(isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) { /* For pointer types, we can make a special form of optimization * * These statements are put onto the expression init list: @@ -1073,7 +1091,7 @@ walkexpr(Node **np, NodeList **init) t = n->left->type; p = nil; - if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing. + if(t->type->width <= 128) { // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing. switch(simsimtype(t->down)) { case TINT32: case TUINT32: @@ -1371,7 +1389,6 @@ walkexpr(Node **np, NodeList **init) case OMAPLIT: case OSTRUCTLIT: case OPTRLIT: - // XXX TODO do we need to clear var? var = temp(n->type); anylit(0, n, var, init); n = var; @@ -1471,8 +1488,13 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init) static int fncall(Node *l, Type *rt) { + Node r; + if(l->ullman >= UINF || l->op == OINDEXMAP) return 1; + memset(&r, 0, sizeof r); + if(needwritebarrier(l, &r)) + return 1; if(eqtype(l->type, rt)) return 0; return 1; @@ -1523,8 +1545,10 @@ ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init) a = nod(OAS, l, nodarg(r, fp)); a = convas(a, init); ullmancalc(a); - if(a->ullman >= UINF) + if(a->ullman >= UINF) { + dump("ascompatet ucount", a); ucount++; + } nn = list(nn, a); r = structnext(&saver); } @@ -1732,7 +1756,7 @@ ret: // generate code for print static Node* -walkprint(Node *nn, NodeList **init, int defer) +walkprint(Node *nn, NodeList **init) { Node *r; Node *n; @@ -1740,31 +1764,17 @@ walkprint(Node *nn, NodeList **init, int defer) Node *on; Type *t; int notfirst, et, op; - NodeList *calls, *intypes, *args; - Fmt fmt; + NodeList *calls; on = nil; op = nn->op; all = nn->list; calls = nil; notfirst = 0; - intypes = nil; - args = nil; - - memset(&fmt, 0, sizeof fmt); - if(defer) { - // defer print turns into defer printf with format string - fmtstrinit(&fmt); - intypes = list(intypes, nod(ODCLFIELD, N, typenod(types[TSTRING]))); - args = list1(nod(OXXX, N, N)); - } for(l=all; l; l=l->next) { if(notfirst) { - if(defer) - fmtprint(&fmt, " "); - else - calls = list(calls, mkcall("printsp", T, init)); + calls = list(calls, mkcall("printsp", T, init)); } notfirst = op == OPRINTN; @@ -1792,119 +1802,63 @@ walkprint(Node *nn, NodeList **init, int defer) t = n->type; et = n->type->etype; if(isinter(n->type)) { - if(defer) { - if(isnilinter(n->type)) - fmtprint(&fmt, "%%e"); - else - fmtprint(&fmt, "%%i"); - } else { - if(isnilinter(n->type)) - on = syslook("printeface", 1); - else - on = syslook("printiface", 1); - argtype(on, n->type); // any-1 - } + if(isnilinter(n->type)) + on = syslook("printeface", 1); + else + on = syslook("printiface", 1); + argtype(on, n->type); // any-1 } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) { - if(defer) { - fmtprint(&fmt, "%%p"); - } else { - on = syslook("printpointer", 1); - argtype(on, n->type); // any-1 - } + on = syslook("printpointer", 1); + argtype(on, n->type); // any-1 } else if(isslice(n->type)) { - if(defer) { - fmtprint(&fmt, "%%a"); - } else { - on = syslook("printslice", 1); - argtype(on, n->type); // any-1 - } + on = syslook("printslice", 1); + argtype(on, n->type); // any-1 } else if(isint[et]) { - if(defer) { - if(et == TUINT64) - fmtprint(&fmt, "%%U"); - else { - fmtprint(&fmt, "%%D"); - t = types[TINT64]; - } - } else { - if(et == TUINT64) - on = syslook("printuint", 0); + if(et == TUINT64) { + if((t->sym->pkg == runtimepkg || compiling_runtime) && strcmp(t->sym->name, "hex") == 0) + on = syslook("printhex", 0); else - on = syslook("printint", 0); - } - } else if(isfloat[et]) { - if(defer) { - fmtprint(&fmt, "%%f"); - t = types[TFLOAT64]; + on = syslook("printuint", 0); } else - on = syslook("printfloat", 0); + on = syslook("printint", 0); + } else if(isfloat[et]) { + on = syslook("printfloat", 0); } else if(iscomplex[et]) { - if(defer) { - fmtprint(&fmt, "%%C"); - t = types[TCOMPLEX128]; - } else - on = syslook("printcomplex", 0); + on = syslook("printcomplex", 0); } else if(et == TBOOL) { - if(defer) - fmtprint(&fmt, "%%t"); - else - on = syslook("printbool", 0); + on = syslook("printbool", 0); } else if(et == TSTRING) { - if(defer) - fmtprint(&fmt, "%%S"); - else - on = syslook("printstring", 0); + on = syslook("printstring", 0); } else { badtype(OPRINT, n->type, T); continue; } - if(!defer) { - t = *getinarg(on->type); - if(t != nil) - t = t->type; - if(t != nil) - t = t->type; - } + t = *getinarg(on->type); + if(t != nil) + t = t->type; + if(t != nil) + t = t->type; if(!eqtype(t, n->type)) { n = nod(OCONV, n, N); n->type = t; } - if(defer) { - intypes = list(intypes, nod(ODCLFIELD, N, typenod(t))); - args = list(args, n); - } else { - r = nod(OCALL, on, N); - r->list = list1(n); - calls = list(calls, r); - } + r = nod(OCALL, on, N); + r->list = list1(n); + calls = list(calls, r); } - if(defer) { - if(op == OPRINTN) - fmtprint(&fmt, "\n"); - on = syslook("goprintf", 1); - on->type = functype(nil, intypes, nil); - args->n = nod(OLITERAL, N, N); - args->n->val.ctype = CTSTR; - args->n->val.u.sval = strlit(fmtstrflush(&fmt)); - r = nod(OCALL, on, N); - r->list = args; - typecheck(&r, Etop); - walkexpr(&r, init); - } else { - if(op == OPRINTN) - calls = list(calls, mkcall("printnl", T, nil)); - typechecklist(calls, Etop); - walkexprlist(calls, init); + if(op == OPRINTN) + calls = list(calls, mkcall("printnl", T, nil)); + typechecklist(calls, Etop); + walkexprlist(calls, init); - r = nod(OEMPTY, N, N); - typecheck(&r, Etop); - walkexpr(&r, init); - r->ninit = calls; - } + r = nod(OEMPTY, N, N); + typecheck(&r, Etop); + walkexpr(&r, init); + r->ninit = calls; return r; } @@ -1914,11 +1868,166 @@ callnew(Type *t) Node *fn; dowidth(t); - fn = syslook("new", 1); + fn = syslook("newobject", 1); argtype(fn, t); return mkcall1(fn, ptrto(t), nil, typename(t)); } +static int +isstack(Node *n) +{ + while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type)) + n = n->left; + + switch(n->op) { + case OINDREG: + // OINDREG only ends up in walk if it's indirect of SP. + return 1; + + case ONAME: + switch(n->class) { + case PAUTO: + case PPARAM: + case PPARAMOUT: + return 1; + } + break; + } + + return 0; +} + +static int +isglobal(Node *n) +{ + while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type)) + n = n->left; + + switch(n->op) { + case ONAME: + switch(n->class) { + case PEXTERN: + return 1; + } + break; + } + + return 0; +} + +// Do we need a write barrier for the assignment l = r? +int +needwritebarrier(Node *l, Node *r) +{ + if(!use_writebarrier) + return 0; + + if(l == N || isblank(l)) + return 0; + + // No write barrier for write of non-pointers. + dowidth(l->type); + if(!haspointers(l->type)) + return 0; + + // No write barrier for write to stack. + if(isstack(l)) + return 0; + + // No write barrier for implicit or explicit zeroing. + if(r == N || iszero(r)) + return 0; + + // No write barrier for initialization to constant. + if(r->op == OLITERAL) + return 0; + + // No write barrier for storing static (read-only) data. + if(r->op == ONAME && strncmp(r->sym->name, "statictmp_", 10) == 0) + return 0; + + // No write barrier for storing address of stack values, + // which are guaranteed only to be written to the stack. + if(r->op == OADDR && isstack(r->left)) + return 0; + + // No write barrier for storing address of global, which + // is live no matter what. + if(r->op == OADDR && isglobal(r->left)) + return 0; + + // No write barrier for reslice: x = x[0:y] or x = append(x, ...). + // Both are compiled to modify x directly. + // In the case of append, a write barrier may still be needed + // if the underlying array grows, but the append code can + // generate the write barrier directly in that case. + // (It does not yet, but the cost of the write barrier will be + // small compared to the cost of the allocation.) + if(r->reslice) { + switch(r->op) { + case OSLICE: + case OSLICE3: + case OSLICESTR: + case OAPPEND: + break; + default: + dump("bad reslice-l", l); + dump("bad reslice-r", r); + break; + } + return 0; + } + + // Otherwise, be conservative and use write barrier. + return 1; +} + +// TODO(rsc): Perhaps componentgen should run before this. +static Node* +applywritebarrier(Node *n, NodeList **init) +{ + Node *l, *r; + Type *t; + + if(n->left && n->right && needwritebarrier(n->left, n->right)) { + t = n->left->type; + l = nod(OADDR, n->left, N); + l->etype = 1; // addr does not escape + if(t->width == widthptr) { + n = mkcall1(writebarrierfn("writebarrierptr", t, n->right->type), T, init, + l, n->right); + } else if(t->etype == TSTRING) { + n = mkcall1(writebarrierfn("writebarrierstring", t, n->right->type), T, init, + l, n->right); + } else if(isslice(t)) { + n = mkcall1(writebarrierfn("writebarrierslice", t, n->right->type), T, init, + l, n->right); + } else if(isinter(t)) { + n = mkcall1(writebarrierfn("writebarrieriface", t, n->right->type), T, init, + l, n->right); + } else if(t->width == 2*widthptr) { + n = mkcall1(writebarrierfn("writebarrierfat2", t, n->right->type), T, init, + l, nodnil(), n->right); + } else if(t->width == 3*widthptr) { + n = mkcall1(writebarrierfn("writebarrierfat3", t, n->right->type), T, init, + l, nodnil(), n->right); + } else if(t->width == 4*widthptr) { + n = mkcall1(writebarrierfn("writebarrierfat4", t, n->right->type), T, init, + l, nodnil(), n->right); + } else { + r = n->right; + while(r->op == OCONVNOP) + r = r->left; + r = nod(OADDR, r, N); + r->etype = 1; // addr does not escape + //warnl(n->lineno, "writebarrierfat %T %N", t, r); + n = mkcall1(writebarrierfn("writebarrierfat", t, r->left->type), T, init, + typename(t), l, r); + } + } + return n; +} + static Node* convas(Node *n, NodeList **init) { @@ -1958,11 +2067,10 @@ convas(Node *n, NodeList **init) goto out; } - if(eqtype(lt, rt)) - goto out; - - n->right = assignconv(n->right, lt, "assignment"); - walkexpr(&n->right, init); + if(!eqtype(lt, rt)) { + n->right = assignconv(n->right, lt, "assignment"); + walkexpr(&n->right, init); + } out: ullmancalc(n); @@ -2355,6 +2463,8 @@ paramstoheap(Type **argin, int out) continue; // generate allocation & copying code + if(compiling_runtime) + yyerror("%N escapes to heap, not allowed in runtime.", v); if(v->alloc == nil) v->alloc = callnew(v->type); nn = list(nn, nod(OAS, v->heapaddr, v->alloc)); @@ -2511,6 +2621,17 @@ mapfndel(char *name, Type *t) return fn; } +static Node* +writebarrierfn(char *name, Type *l, Type *r) +{ + Node *fn; + + fn = syslook(name, 1); + argtype(fn, l); + argtype(fn, r); + return fn; +} + static Node* addstr(Node *n, NodeList **init) { @@ -2620,7 +2741,7 @@ appendslice(Node *n, NodeList **init) if(l2->type->etype == TSTRING) fn = syslook("slicestringcopy", 1); else - fn = syslook("copy", 1); + fn = syslook("slicecopy", 1); argtype(fn, l1->type); argtype(fn, l2->type); nt = mkcall1(fn, types[TINT], &l, @@ -2758,7 +2879,7 @@ copyany(Node *n, NodeList **init, int runtimecall) if(n->right->type->etype == TSTRING) fn = syslook("slicestringcopy", 1); else - fn = syslook("copy", 1); + fn = syslook("slicecopy", 1); argtype(fn, n->left->type); argtype(fn, n->right->type); return mkcall1(fn, n->type, init, @@ -2863,14 +2984,14 @@ sliceany(Node* n, NodeList **init) lb = N; } - // dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison - // generate - // if hb > bound || lb > hb { panicslice() } + // Checking src[lb:hb:cb] or src[lb:hb]. + // if chk0 || chk1 || chk2 { panicslice() } chk = N; - chk0 = N; - chk1 = N; - chk2 = N; + chk0 = N; // cap(src) < cb + chk1 = N; // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb] + chk2 = N; // hb < lb + // All comparisons are unsigned to avoid testing < 0. bt = types[simtype[TUINT]]; if(cb != N && cb->type->width > 4) bt = types[TUINT64]; @@ -3010,10 +3131,10 @@ eqfor(Type *t) n = newname(sym); n->class = PFUNC; ntype = nod(OTFUNC, N, N); - ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(types[TBOOL])))); - ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); + ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, N, typenod(types[TBOOL]))); typecheck(&ntype, Etype); n->type = ntype->type; return n; @@ -3034,10 +3155,9 @@ countfield(Type *t) static void walkcompare(Node **np, NodeList **init) { - Node *n, *l, *r, *fn, *call, *a, *li, *ri, *expr; + Node *n, *l, *r, *call, *a, *li, *ri, *expr, *cmpl, *cmpr; int andor, i; Type *t, *t1; - static Node *tempbool; n = *np; @@ -3055,17 +3175,25 @@ walkcompare(Node **np, NodeList **init) break; } - if(!islvalue(n->left) || !islvalue(n->right)) - goto hard; + cmpl = n->left; + while(cmpl != N && cmpl->op == OCONVNOP) + cmpl = cmpl->left; + cmpr = n->right; + while(cmpr != N && cmpr->op == OCONVNOP) + cmpr = cmpr->left; + + if(!islvalue(cmpl) || !islvalue(cmpr)) { + fatal("arguments of comparison must be lvalues - %N %N", cmpl, cmpr); + } l = temp(ptrto(t)); - a = nod(OAS, l, nod(OADDR, n->left, N)); + a = nod(OAS, l, nod(OADDR, cmpl, N)); a->right->etype = 1; // addr does not escape typecheck(&a, Etop); *init = list(*init, a); r = temp(ptrto(t)); - a = nod(OAS, r, nod(OADDR, n->right, N)); + a = nod(OAS, r, nod(OADDR, cmpr, N)); a->right->etype = 1; // addr does not escape typecheck(&a, Etop); *init = list(*init, a); @@ -3115,57 +3243,16 @@ walkcompare(Node **np, NodeList **init) goto ret; } - // Chose not to inline, but still have addresses. - // Call equality function directly. - // The equality function requires a bool pointer for - // storing its address, because it has to be callable - // from C, and C can't access an ordinary Go return value. - // To avoid creating many temporaries, cache one per function. - if(tempbool == N || tempbool->curfn != curfn) - tempbool = temp(types[TBOOL]); - + // Chose not to inline. Call equality function directly. call = nod(OCALL, eqfor(t), N); - a = nod(OADDR, tempbool, N); - a->etype = 1; // does not escape - call->list = list(call->list, a); - call->list = list(call->list, nodintconst(t->width)); call->list = list(call->list, l); call->list = list(call->list, r); - typecheck(&call, Etop); - walkstmt(&call); - *init = list(*init, call); - - // tempbool cannot be used directly as multiple comparison - // expressions may exist in the same statement. Create another - // temporary to hold the value (its address is not taken so it can - // be optimized away). - r = temp(types[TBOOL]); - a = nod(OAS, r, tempbool); - typecheck(&a, Etop); - walkstmt(&a); - *init = list(*init, a); - + call->list = list(call->list, nodintconst(t->width)); + r = call; if(n->op != OEQ) r = nod(ONOT, r, N); goto ret; -hard: - // Cannot take address of one or both of the operands. - // Instead, pass directly to runtime helper function. - // Easier on the stack than passing the address - // of temporary variables, because we are better at reusing - // the argument space than temporary variable space. - fn = syslook("equal", 1); - l = n->left; - r = n->right; - argtype(fn, n->left->type); - argtype(fn, n->left->type); - r = mkcall1(fn, n->type, init, typename(n->left->type), l, r); - if(n->op == ONE) { - r = nod(ONOT, r, N); - } - goto ret; - ret: typecheck(&r, Erv); walkexpr(&r, init); @@ -3780,3 +3867,71 @@ candiscard(Node *n) return 1; } + +// rewrite +// print(x, y, z) +// into +// func(a1, a2, a3) { +// print(a1, a2, a3) +// }(x, y, z) +// and same for println. +static void +walkprintfunc(Node **np, NodeList **init) +{ + Node *n; + Node *a, *fn, *t, *oldfn; + NodeList *l, *printargs; + int num; + char buf[100]; + static int prgen; + + n = *np; + + if(n->ninit != nil) { + walkstmtlist(n->ninit); + *init = concat(*init, n->ninit); + n->ninit = nil; + } + + t = nod(OTFUNC, N, N); + num = 0; + printargs = nil; + for(l=n->list; l != nil; l=l->next) { + snprint(buf, sizeof buf, "a%d", num++); + a = nod(ODCLFIELD, newname(lookup(buf)), typenod(l->n->type)); + t->list = list(t->list, a); + printargs = list(printargs, a->left); + } + + fn = nod(ODCLFUNC, N, N); + snprint(buf, sizeof buf, "print·%d", ++prgen); + fn->nname = newname(lookup(buf)); + fn->nname->defn = fn; + fn->nname->ntype = t; + declare(fn->nname, PFUNC); + + oldfn = curfn; + curfn = nil; + funchdr(fn); + + a = nod(n->op, N, N); + a->list = printargs; + typecheck(&a, Etop); + walkstmt(&a); + + fn->nbody = list1(a); + + funcbody(fn); + + typecheck(&fn, Etop); + typechecklist(fn->nbody, Etop); + xtop = list(xtop, fn); + curfn = oldfn; + + a = nod(OCALL, N, N); + a->left = fn->nname; + a->list = n->list; + typecheck(&a, Etop); + walkexpr(&a, init); + *np = a; +} diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c index 08d8ecff2..f464126ac 100644 --- a/src/cmd/gc/y.tab.c +++ b/src/cmd/gc/y.tab.c @@ -440,16 +440,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 4 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 2270 +#define YYLAST 2201 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 76 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 142 /* YYNRULES -- Number of rules. */ -#define YYNRULES 351 +#define YYNRULES 352 /* YYNRULES -- Number of states. */ -#define YYNSTATES 667 +#define YYNSTATES 669 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -506,35 +506,35 @@ static const yytype_uint16 yyprhs[] = 129, 132, 137, 141, 146, 150, 152, 155, 157, 159, 162, 164, 168, 172, 176, 179, 182, 186, 192, 198, 201, 202, 207, 208, 212, 213, 216, 217, 222, 227, - 232, 238, 240, 242, 245, 246, 250, 252, 256, 257, - 258, 259, 268, 269, 275, 276, 279, 280, 283, 284, - 285, 293, 294, 300, 302, 306, 310, 314, 318, 322, - 326, 330, 334, 338, 342, 346, 350, 354, 358, 362, - 366, 370, 374, 378, 382, 384, 387, 390, 393, 396, - 399, 402, 405, 408, 412, 418, 425, 427, 429, 433, - 439, 445, 450, 457, 466, 468, 474, 480, 486, 494, - 496, 497, 501, 503, 508, 510, 515, 517, 521, 523, - 525, 527, 529, 531, 533, 535, 536, 538, 540, 542, - 544, 549, 554, 556, 558, 560, 563, 565, 567, 569, - 571, 573, 577, 579, 581, 583, 586, 588, 590, 592, - 594, 598, 600, 602, 604, 606, 608, 610, 612, 614, - 616, 620, 625, 630, 633, 637, 643, 645, 647, 650, - 654, 660, 664, 670, 674, 678, 684, 693, 699, 708, - 714, 715, 719, 720, 722, 726, 728, 733, 736, 737, - 741, 743, 747, 749, 753, 755, 759, 761, 765, 767, - 771, 775, 778, 783, 787, 793, 799, 801, 805, 807, - 810, 812, 816, 821, 823, 826, 829, 831, 833, 837, - 838, 841, 842, 844, 846, 848, 850, 852, 854, 856, - 858, 860, 861, 866, 868, 871, 874, 877, 880, 883, - 886, 888, 892, 894, 898, 900, 904, 906, 910, 912, - 916, 918, 920, 924, 928, 929, 932, 933, 935, 936, - 938, 939, 941, 942, 944, 945, 947, 948, 950, 951, - 953, 954, 956, 957, 959, 964, 969, 975, 982, 987, - 992, 994, 996, 998, 1000, 1002, 1004, 1006, 1008, 1010, - 1014, 1019, 1025, 1030, 1035, 1038, 1041, 1046, 1050, 1054, - 1060, 1064, 1069, 1073, 1079, 1081, 1082, 1084, 1088, 1090, - 1092, 1095, 1097, 1099, 1105, 1106, 1109, 1111, 1115, 1117, - 1121, 1123 + 232, 235, 241, 243, 245, 248, 249, 253, 255, 259, + 260, 261, 262, 271, 272, 278, 279, 282, 283, 286, + 287, 288, 296, 297, 303, 305, 309, 313, 317, 321, + 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, + 365, 369, 373, 377, 381, 385, 387, 390, 393, 396, + 399, 402, 405, 408, 411, 415, 421, 428, 430, 432, + 436, 442, 448, 453, 460, 469, 471, 477, 483, 489, + 497, 499, 500, 504, 506, 511, 513, 518, 520, 524, + 526, 528, 530, 532, 534, 536, 538, 539, 541, 543, + 545, 547, 552, 557, 559, 561, 563, 566, 568, 570, + 572, 574, 576, 580, 582, 584, 586, 589, 591, 593, + 595, 597, 601, 603, 605, 607, 609, 611, 613, 615, + 617, 619, 623, 628, 633, 636, 640, 646, 648, 650, + 653, 657, 663, 667, 673, 677, 681, 687, 696, 702, + 711, 717, 718, 722, 723, 725, 729, 731, 736, 739, + 740, 744, 746, 750, 752, 756, 758, 762, 764, 768, + 770, 774, 778, 781, 786, 790, 796, 802, 804, 808, + 810, 813, 815, 819, 824, 826, 829, 832, 834, 836, + 840, 841, 844, 845, 847, 849, 851, 853, 855, 857, + 859, 861, 863, 864, 869, 871, 874, 877, 880, 883, + 886, 889, 891, 895, 897, 901, 903, 907, 909, 913, + 915, 919, 921, 923, 927, 931, 932, 935, 936, 938, + 939, 941, 942, 944, 945, 947, 948, 950, 951, 953, + 954, 956, 957, 959, 960, 962, 967, 972, 978, 985, + 990, 995, 997, 999, 1001, 1003, 1005, 1007, 1009, 1011, + 1013, 1017, 1022, 1028, 1033, 1038, 1041, 1044, 1049, 1053, + 1057, 1063, 1067, 1072, 1076, 1082, 1084, 1085, 1087, 1091, + 1093, 1095, 1098, 1100, 1102, 1108, 1109, 1112, 1114, 1118, + 1120, 1124, 1126 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ @@ -563,96 +563,96 @@ static const yytype_int16 yyrhs[] = -1, -1, 67, 101, 183, 68, -1, -1, 99, 103, 183, -1, -1, 104, 102, -1, -1, 35, 106, 183, 68, -1, 186, 65, 26, 126, -1, 186, 5, 26, - 126, -1, 194, 62, 194, 62, 194, -1, 194, -1, - 107, -1, 108, 105, -1, -1, 16, 111, 109, -1, - 194, -1, 194, 62, 194, -1, -1, -1, -1, 20, - 114, 112, 115, 105, 116, 119, 120, -1, -1, 14, - 20, 118, 112, 105, -1, -1, 119, 117, -1, -1, - 14, 100, -1, -1, -1, 30, 122, 112, 123, 35, - 104, 68, -1, -1, 28, 125, 35, 104, 68, -1, - 127, -1, 126, 47, 126, -1, 126, 33, 126, -1, - 126, 38, 126, -1, 126, 46, 126, -1, 126, 45, - 126, -1, 126, 43, 126, -1, 126, 39, 126, -1, - 126, 40, 126, -1, 126, 49, 126, -1, 126, 50, - 126, -1, 126, 51, 126, -1, 126, 52, 126, -1, - 126, 53, 126, -1, 126, 54, 126, -1, 126, 55, - 126, -1, 126, 56, 126, -1, 126, 34, 126, -1, - 126, 44, 126, -1, 126, 48, 126, -1, 126, 36, - 126, -1, 134, -1, 53, 127, -1, 56, 127, -1, - 49, 127, -1, 50, 127, -1, 69, 127, -1, 70, - 127, -1, 52, 127, -1, 36, 127, -1, 134, 59, - 60, -1, 134, 59, 187, 191, 60, -1, 134, 59, - 187, 11, 191, 60, -1, 3, -1, 143, -1, 134, - 63, 141, -1, 134, 63, 59, 135, 60, -1, 134, - 63, 59, 31, 60, -1, 134, 71, 126, 72, -1, - 134, 71, 192, 66, 192, 72, -1, 134, 71, 192, - 66, 192, 66, 192, 72, -1, 128, -1, 149, 59, - 126, 191, 60, -1, 150, 137, 130, 189, 68, -1, - 129, 67, 130, 189, 68, -1, 59, 135, 60, 67, - 130, 189, 68, -1, 165, -1, -1, 126, 66, 133, - -1, 126, -1, 67, 130, 189, 68, -1, 126, -1, - 67, 130, 189, 68, -1, 129, -1, 59, 135, 60, - -1, 126, -1, 147, -1, 146, -1, 35, -1, 67, - -1, 141, -1, 141, -1, -1, 138, -1, 24, -1, - 142, -1, 73, -1, 74, 3, 63, 24, -1, 74, - 3, 63, 73, -1, 141, -1, 138, -1, 11, -1, - 11, 146, -1, 155, -1, 161, -1, 153, -1, 154, - -1, 152, -1, 59, 146, 60, -1, 155, -1, 161, - -1, 153, -1, 53, 147, -1, 161, -1, 153, -1, - 154, -1, 152, -1, 59, 146, 60, -1, 161, -1, - 153, -1, 153, -1, 155, -1, 161, -1, 153, -1, - 154, -1, 152, -1, 143, -1, 143, 63, 141, -1, - 71, 192, 72, 146, -1, 71, 11, 72, 146, -1, - 8, 148, -1, 8, 36, 146, -1, 23, 71, 146, - 72, 146, -1, 156, -1, 157, -1, 53, 146, -1, - 36, 8, 146, -1, 29, 137, 170, 190, 68, -1, - 29, 137, 68, -1, 22, 137, 171, 190, 68, -1, - 22, 137, 68, -1, 17, 159, 162, -1, 141, 59, - 179, 60, 163, -1, 59, 179, 60, 141, 59, 179, - 60, 163, -1, 200, 59, 195, 60, 210, -1, 59, - 215, 60, 141, 59, 195, 60, 210, -1, 17, 59, - 179, 60, 163, -1, -1, 67, 183, 68, -1, -1, - 151, -1, 59, 179, 60, -1, 161, -1, 164, 137, - 183, 68, -1, 164, 1, -1, -1, 166, 90, 62, - -1, 93, -1, 167, 62, 93, -1, 95, -1, 168, - 62, 95, -1, 97, -1, 169, 62, 97, -1, 172, - -1, 170, 62, 172, -1, 175, -1, 171, 62, 175, - -1, 184, 146, 198, -1, 174, 198, -1, 59, 174, - 60, 198, -1, 53, 174, 198, -1, 59, 53, 174, - 60, 198, -1, 53, 59, 174, 60, 198, -1, 24, - -1, 24, 63, 141, -1, 173, -1, 138, 176, -1, - 173, -1, 59, 173, 60, -1, 59, 179, 60, 163, - -1, 136, -1, 141, 136, -1, 141, 145, -1, 145, - -1, 177, -1, 178, 75, 177, -1, -1, 178, 191, - -1, -1, 100, -1, 91, -1, 181, -1, 1, -1, - 98, -1, 110, -1, 121, -1, 124, -1, 113, -1, - -1, 144, 66, 182, 180, -1, 15, -1, 6, 140, - -1, 10, 140, -1, 18, 128, -1, 13, 128, -1, - 19, 138, -1, 27, 193, -1, 180, -1, 183, 62, - 180, -1, 138, -1, 184, 75, 138, -1, 139, -1, - 185, 75, 139, -1, 126, -1, 186, 75, 126, -1, - 135, -1, 187, 75, 135, -1, 131, -1, 132, -1, - 188, 75, 131, -1, 188, 75, 132, -1, -1, 188, - 191, -1, -1, 62, -1, -1, 75, -1, -1, 126, - -1, -1, 186, -1, -1, 98, -1, -1, 215, -1, - -1, 216, -1, -1, 217, -1, -1, 3, -1, 21, - 24, 3, 62, -1, 32, 200, 202, 62, -1, 9, - 200, 65, 213, 62, -1, 9, 200, 202, 65, 213, - 62, -1, 31, 201, 202, 62, -1, 17, 160, 162, - 62, -1, 142, -1, 200, -1, 204, -1, 205, -1, - 206, -1, 204, -1, 206, -1, 142, -1, 24, -1, - 71, 72, 202, -1, 71, 3, 72, 202, -1, 23, - 71, 202, 72, 202, -1, 29, 67, 196, 68, -1, - 22, 67, 197, 68, -1, 53, 202, -1, 8, 203, - -1, 8, 59, 205, 60, -1, 8, 36, 202, -1, - 36, 8, 202, -1, 17, 59, 195, 60, 210, -1, - 141, 202, 198, -1, 141, 11, 202, 198, -1, 141, - 202, 198, -1, 141, 59, 195, 60, 210, -1, 202, - -1, -1, 211, -1, 59, 195, 60, -1, 202, -1, - 3, -1, 50, 3, -1, 141, -1, 212, -1, 59, - 212, 49, 212, 60, -1, -1, 214, 199, -1, 207, - -1, 215, 75, 207, -1, 208, -1, 216, 62, 208, - -1, 209, -1, 217, 62, 209, -1 + 126, -1, 26, 126, -1, 194, 62, 194, 62, 194, + -1, 194, -1, 107, -1, 108, 105, -1, -1, 16, + 111, 109, -1, 194, -1, 194, 62, 194, -1, -1, + -1, -1, 20, 114, 112, 115, 105, 116, 119, 120, + -1, -1, 14, 20, 118, 112, 105, -1, -1, 119, + 117, -1, -1, 14, 100, -1, -1, -1, 30, 122, + 112, 123, 35, 104, 68, -1, -1, 28, 125, 35, + 104, 68, -1, 127, -1, 126, 47, 126, -1, 126, + 33, 126, -1, 126, 38, 126, -1, 126, 46, 126, + -1, 126, 45, 126, -1, 126, 43, 126, -1, 126, + 39, 126, -1, 126, 40, 126, -1, 126, 49, 126, + -1, 126, 50, 126, -1, 126, 51, 126, -1, 126, + 52, 126, -1, 126, 53, 126, -1, 126, 54, 126, + -1, 126, 55, 126, -1, 126, 56, 126, -1, 126, + 34, 126, -1, 126, 44, 126, -1, 126, 48, 126, + -1, 126, 36, 126, -1, 134, -1, 53, 127, -1, + 56, 127, -1, 49, 127, -1, 50, 127, -1, 69, + 127, -1, 70, 127, -1, 52, 127, -1, 36, 127, + -1, 134, 59, 60, -1, 134, 59, 187, 191, 60, + -1, 134, 59, 187, 11, 191, 60, -1, 3, -1, + 143, -1, 134, 63, 141, -1, 134, 63, 59, 135, + 60, -1, 134, 63, 59, 31, 60, -1, 134, 71, + 126, 72, -1, 134, 71, 192, 66, 192, 72, -1, + 134, 71, 192, 66, 192, 66, 192, 72, -1, 128, + -1, 149, 59, 126, 191, 60, -1, 150, 137, 130, + 189, 68, -1, 129, 67, 130, 189, 68, -1, 59, + 135, 60, 67, 130, 189, 68, -1, 165, -1, -1, + 126, 66, 133, -1, 126, -1, 67, 130, 189, 68, + -1, 126, -1, 67, 130, 189, 68, -1, 129, -1, + 59, 135, 60, -1, 126, -1, 147, -1, 146, -1, + 35, -1, 67, -1, 141, -1, 141, -1, -1, 138, + -1, 24, -1, 142, -1, 73, -1, 74, 3, 63, + 24, -1, 74, 3, 63, 73, -1, 141, -1, 138, + -1, 11, -1, 11, 146, -1, 155, -1, 161, -1, + 153, -1, 154, -1, 152, -1, 59, 146, 60, -1, + 155, -1, 161, -1, 153, -1, 53, 147, -1, 161, + -1, 153, -1, 154, -1, 152, -1, 59, 146, 60, + -1, 161, -1, 153, -1, 153, -1, 155, -1, 161, + -1, 153, -1, 154, -1, 152, -1, 143, -1, 143, + 63, 141, -1, 71, 192, 72, 146, -1, 71, 11, + 72, 146, -1, 8, 148, -1, 8, 36, 146, -1, + 23, 71, 146, 72, 146, -1, 156, -1, 157, -1, + 53, 146, -1, 36, 8, 146, -1, 29, 137, 170, + 190, 68, -1, 29, 137, 68, -1, 22, 137, 171, + 190, 68, -1, 22, 137, 68, -1, 17, 159, 162, + -1, 141, 59, 179, 60, 163, -1, 59, 179, 60, + 141, 59, 179, 60, 163, -1, 200, 59, 195, 60, + 210, -1, 59, 215, 60, 141, 59, 195, 60, 210, + -1, 17, 59, 179, 60, 163, -1, -1, 67, 183, + 68, -1, -1, 151, -1, 59, 179, 60, -1, 161, + -1, 164, 137, 183, 68, -1, 164, 1, -1, -1, + 166, 90, 62, -1, 93, -1, 167, 62, 93, -1, + 95, -1, 168, 62, 95, -1, 97, -1, 169, 62, + 97, -1, 172, -1, 170, 62, 172, -1, 175, -1, + 171, 62, 175, -1, 184, 146, 198, -1, 174, 198, + -1, 59, 174, 60, 198, -1, 53, 174, 198, -1, + 59, 53, 174, 60, 198, -1, 53, 59, 174, 60, + 198, -1, 24, -1, 24, 63, 141, -1, 173, -1, + 138, 176, -1, 173, -1, 59, 173, 60, -1, 59, + 179, 60, 163, -1, 136, -1, 141, 136, -1, 141, + 145, -1, 145, -1, 177, -1, 178, 75, 177, -1, + -1, 178, 191, -1, -1, 100, -1, 91, -1, 181, + -1, 1, -1, 98, -1, 110, -1, 121, -1, 124, + -1, 113, -1, -1, 144, 66, 182, 180, -1, 15, + -1, 6, 140, -1, 10, 140, -1, 18, 128, -1, + 13, 128, -1, 19, 138, -1, 27, 193, -1, 180, + -1, 183, 62, 180, -1, 138, -1, 184, 75, 138, + -1, 139, -1, 185, 75, 139, -1, 126, -1, 186, + 75, 126, -1, 135, -1, 187, 75, 135, -1, 131, + -1, 132, -1, 188, 75, 131, -1, 188, 75, 132, + -1, -1, 188, 191, -1, -1, 62, -1, -1, 75, + -1, -1, 126, -1, -1, 186, -1, -1, 98, -1, + -1, 215, -1, -1, 216, -1, -1, 217, -1, -1, + 3, -1, 21, 24, 3, 62, -1, 32, 200, 202, + 62, -1, 9, 200, 65, 213, 62, -1, 9, 200, + 202, 65, 213, 62, -1, 31, 201, 202, 62, -1, + 17, 160, 162, 62, -1, 142, -1, 200, -1, 204, + -1, 205, -1, 206, -1, 204, -1, 206, -1, 142, + -1, 24, -1, 71, 72, 202, -1, 71, 3, 72, + 202, -1, 23, 71, 202, 72, 202, -1, 29, 67, + 196, 68, -1, 22, 67, 197, 68, -1, 53, 202, + -1, 8, 203, -1, 8, 59, 205, 60, -1, 8, + 36, 202, -1, 36, 8, 202, -1, 17, 59, 195, + 60, 210, -1, 141, 202, 198, -1, 141, 11, 202, + 198, -1, 141, 202, 198, -1, 141, 59, 195, 60, + 210, -1, 202, -1, -1, 211, -1, 59, 195, 60, + -1, 202, -1, 3, -1, 50, 3, -1, 141, -1, + 212, -1, 59, 212, 49, 212, 60, -1, -1, 214, + 199, -1, 207, -1, 215, 75, 207, -1, 208, -1, + 216, 62, 208, -1, 209, -1, 217, 62, 209, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ @@ -663,37 +663,37 @@ static const yytype_uint16 yyrline[] = 263, 264, 271, 271, 284, 288, 289, 293, 298, 304, 308, 312, 316, 322, 328, 334, 339, 343, 347, 353, 359, 363, 367, 373, 377, 383, 384, 388, 394, 403, - 409, 427, 432, 444, 460, 465, 472, 492, 510, 519, - 538, 537, 552, 551, 583, 586, 593, 592, 603, 609, - 618, 629, 635, 638, 646, 645, 656, 662, 674, 678, - 683, 673, 704, 703, 716, 719, 725, 728, 740, 744, - 739, 762, 761, 777, 778, 782, 786, 790, 794, 798, - 802, 806, 810, 814, 818, 822, 826, 830, 834, 838, - 842, 846, 850, 855, 861, 862, 866, 877, 881, 885, - 889, 894, 898, 908, 912, 917, 925, 929, 930, 941, - 945, 949, 953, 957, 965, 966, 972, 979, 985, 992, - 995, 1002, 1008, 1025, 1032, 1033, 1040, 1041, 1060, 1061, - 1064, 1067, 1071, 1082, 1091, 1097, 1100, 1103, 1110, 1111, - 1117, 1130, 1145, 1153, 1165, 1170, 1176, 1177, 1178, 1179, - 1180, 1181, 1187, 1188, 1189, 1190, 1196, 1197, 1198, 1199, - 1200, 1206, 1207, 1210, 1213, 1214, 1215, 1216, 1217, 1220, - 1221, 1234, 1238, 1243, 1248, 1253, 1257, 1258, 1261, 1267, - 1274, 1280, 1287, 1293, 1304, 1318, 1347, 1387, 1412, 1430, - 1439, 1442, 1450, 1454, 1458, 1465, 1471, 1476, 1488, 1491, - 1501, 1502, 1508, 1509, 1515, 1519, 1525, 1526, 1532, 1536, - 1542, 1565, 1570, 1576, 1582, 1589, 1598, 1607, 1622, 1628, - 1633, 1637, 1644, 1657, 1658, 1664, 1670, 1673, 1677, 1683, - 1686, 1695, 1698, 1699, 1703, 1704, 1710, 1711, 1712, 1713, - 1714, 1716, 1715, 1730, 1736, 1740, 1744, 1748, 1752, 1757, - 1776, 1782, 1790, 1794, 1800, 1804, 1810, 1814, 1820, 1824, - 1833, 1837, 1841, 1845, 1851, 1854, 1862, 1863, 1865, 1866, - 1869, 1872, 1875, 1878, 1881, 1884, 1887, 1890, 1893, 1896, - 1899, 1902, 1905, 1908, 1914, 1918, 1922, 1926, 1930, 1934, - 1954, 1961, 1972, 1973, 1974, 1977, 1978, 1981, 1985, 1995, - 1999, 2003, 2007, 2011, 2015, 2019, 2025, 2031, 2039, 2047, - 2053, 2060, 2076, 2098, 2102, 2108, 2111, 2114, 2118, 2128, - 2132, 2151, 2159, 2160, 2172, 2173, 2176, 2180, 2186, 2190, - 2196, 2200 + 409, 427, 432, 444, 460, 466, 474, 494, 512, 521, + 540, 539, 554, 553, 585, 588, 595, 594, 605, 611, + 618, 625, 636, 642, 645, 653, 652, 663, 669, 681, + 685, 690, 680, 711, 710, 723, 726, 732, 735, 747, + 751, 746, 769, 768, 784, 785, 789, 793, 797, 801, + 805, 809, 813, 817, 821, 825, 829, 833, 837, 841, + 845, 849, 853, 857, 862, 868, 869, 873, 884, 888, + 892, 896, 901, 905, 915, 919, 924, 932, 936, 937, + 948, 952, 956, 960, 964, 972, 973, 979, 986, 992, + 999, 1002, 1009, 1015, 1032, 1039, 1040, 1047, 1048, 1067, + 1068, 1071, 1074, 1078, 1089, 1098, 1104, 1107, 1110, 1117, + 1118, 1124, 1137, 1152, 1160, 1172, 1177, 1183, 1184, 1185, + 1186, 1187, 1188, 1194, 1195, 1196, 1197, 1203, 1204, 1205, + 1206, 1207, 1213, 1214, 1217, 1220, 1221, 1222, 1223, 1224, + 1227, 1228, 1241, 1245, 1250, 1255, 1260, 1264, 1265, 1268, + 1274, 1281, 1287, 1294, 1300, 1311, 1326, 1355, 1393, 1418, + 1436, 1445, 1448, 1456, 1460, 1464, 1471, 1477, 1482, 1494, + 1497, 1508, 1509, 1515, 1516, 1522, 1526, 1532, 1533, 1539, + 1543, 1549, 1572, 1577, 1583, 1589, 1596, 1605, 1614, 1629, + 1635, 1640, 1644, 1651, 1664, 1665, 1671, 1677, 1680, 1684, + 1690, 1693, 1702, 1705, 1706, 1710, 1711, 1717, 1718, 1719, + 1720, 1721, 1723, 1722, 1737, 1743, 1747, 1751, 1755, 1759, + 1764, 1783, 1789, 1797, 1801, 1807, 1811, 1817, 1821, 1827, + 1831, 1840, 1844, 1848, 1852, 1858, 1861, 1869, 1870, 1872, + 1873, 1876, 1879, 1882, 1885, 1888, 1891, 1894, 1897, 1900, + 1903, 1906, 1909, 1912, 1915, 1921, 1925, 1929, 1933, 1937, + 1941, 1961, 1968, 1979, 1980, 1981, 1984, 1985, 1988, 1992, + 2002, 2006, 2010, 2014, 2018, 2022, 2026, 2032, 2038, 2046, + 2054, 2060, 2067, 2083, 2105, 2109, 2115, 2118, 2121, 2125, + 2135, 2139, 2158, 2166, 2167, 2179, 2180, 2183, 2187, 2193, + 2197, 2203, 2207 }; #endif @@ -772,35 +772,35 @@ static const yytype_uint8 yyr1[] = 93, 93, 93, 94, 94, 95, 95, 95, 96, 97, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 101, 100, 103, 102, 104, 104, 106, 105, 107, 107, - 108, 108, 108, 109, 111, 110, 112, 112, 114, 115, - 116, 113, 118, 117, 119, 119, 120, 120, 122, 123, - 121, 125, 124, 126, 126, 126, 126, 126, 126, 126, + 107, 108, 108, 108, 109, 111, 110, 112, 112, 114, + 115, 116, 113, 118, 117, 119, 119, 120, 120, 122, + 123, 121, 125, 124, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 128, 128, 128, 129, 129, 129, 129, + 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 128, 128, 128, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, - 130, 131, 132, 132, 133, 133, 134, 134, 135, 135, - 136, 137, 137, 138, 139, 140, 140, 141, 141, 141, - 142, 142, 143, 144, 145, 145, 146, 146, 146, 146, - 146, 146, 147, 147, 147, 147, 148, 148, 148, 148, - 148, 149, 149, 150, 151, 151, 151, 151, 151, 152, - 152, 153, 153, 153, 153, 153, 153, 153, 154, 155, - 156, 156, 157, 157, 158, 159, 159, 160, 160, 161, - 162, 162, 163, 163, 163, 164, 165, 165, 166, 166, - 167, 167, 168, 168, 169, 169, 170, 170, 171, 171, - 172, 172, 172, 172, 172, 172, 173, 173, 174, 175, - 175, 175, 176, 177, 177, 177, 177, 178, 178, 179, - 179, 180, 180, 180, 180, 180, 181, 181, 181, 181, - 181, 182, 181, 181, 181, 181, 181, 181, 181, 181, - 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, - 188, 188, 188, 188, 189, 189, 190, 190, 191, 191, - 192, 192, 193, 193, 194, 194, 195, 195, 196, 196, - 197, 197, 198, 198, 199, 199, 199, 199, 199, 199, - 200, 201, 202, 202, 202, 203, 203, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, 205, 206, - 207, 207, 208, 209, 209, 210, 210, 211, 211, 212, - 212, 212, 213, 213, 214, 214, 215, 215, 216, 216, - 217, 217 + 129, 130, 131, 132, 132, 133, 133, 134, 134, 135, + 135, 136, 137, 137, 138, 139, 140, 140, 141, 141, + 141, 142, 142, 143, 144, 145, 145, 146, 146, 146, + 146, 146, 146, 147, 147, 147, 147, 148, 148, 148, + 148, 148, 149, 149, 150, 151, 151, 151, 151, 151, + 152, 152, 153, 153, 153, 153, 153, 153, 153, 154, + 155, 156, 156, 157, 157, 158, 159, 159, 160, 160, + 161, 162, 162, 163, 163, 163, 164, 165, 165, 166, + 166, 167, 167, 168, 168, 169, 169, 170, 170, 171, + 171, 172, 172, 172, 172, 172, 172, 173, 173, 174, + 175, 175, 175, 176, 177, 177, 177, 177, 178, 178, + 179, 179, 180, 180, 180, 180, 180, 181, 181, 181, + 181, 181, 182, 181, 181, 181, 181, 181, 181, 181, + 181, 183, 183, 184, 184, 185, 185, 186, 186, 187, + 187, 188, 188, 188, 188, 189, 189, 190, 190, 191, + 191, 192, 192, 193, 193, 194, 194, 195, 195, 196, + 196, 197, 197, 198, 198, 199, 199, 199, 199, 199, + 199, 200, 201, 202, 202, 202, 203, 203, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, + 206, 207, 207, 208, 209, 209, 210, 210, 211, 211, + 212, 212, 212, 213, 213, 214, 214, 215, 215, 216, + 216, 217, 217 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -813,35 +813,35 @@ static const yytype_uint8 yyr2[] = 2, 4, 3, 4, 3, 1, 2, 1, 1, 2, 1, 3, 3, 3, 2, 2, 3, 5, 5, 2, 0, 4, 0, 3, 0, 2, 0, 4, 4, 4, - 5, 1, 1, 2, 0, 3, 1, 3, 0, 0, - 0, 8, 0, 5, 0, 2, 0, 2, 0, 0, - 7, 0, 5, 1, 3, 3, 3, 3, 3, 3, + 2, 5, 1, 1, 2, 0, 3, 1, 3, 0, + 0, 0, 8, 0, 5, 0, 2, 0, 2, 0, + 0, 7, 0, 5, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 1, 2, 2, 2, 2, 2, - 2, 2, 2, 3, 5, 6, 1, 1, 3, 5, - 5, 4, 6, 8, 1, 5, 5, 5, 7, 1, - 0, 3, 1, 4, 1, 4, 1, 3, 1, 1, - 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, - 4, 4, 1, 1, 1, 2, 1, 1, 1, 1, - 1, 3, 1, 1, 1, 2, 1, 1, 1, 1, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 4, 4, 2, 3, 5, 1, 1, 2, 3, - 5, 3, 5, 3, 3, 5, 8, 5, 8, 5, - 0, 3, 0, 1, 3, 1, 4, 2, 0, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 3, 2, 4, 3, 5, 5, 1, 3, 1, 2, - 1, 3, 4, 1, 2, 2, 1, 1, 3, 0, - 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 4, 1, 2, 2, 2, 2, 2, 2, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 1, 3, 3, 0, 2, 0, 1, 0, 1, - 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, - 0, 1, 0, 1, 4, 4, 5, 6, 4, 4, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 4, 5, 4, 4, 2, 2, 4, 3, 3, 5, - 3, 4, 3, 5, 1, 0, 1, 3, 1, 1, - 2, 1, 1, 5, 0, 2, 1, 3, 1, 3, - 1, 3 + 3, 3, 3, 3, 3, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 3, 5, 6, 1, 1, 3, + 5, 5, 4, 6, 8, 1, 5, 5, 5, 7, + 1, 0, 3, 1, 4, 1, 4, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 4, 4, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 3, 1, 1, 1, 2, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 4, 4, 2, 3, 5, 1, 1, 2, + 3, 5, 3, 5, 3, 3, 5, 8, 5, 8, + 5, 0, 3, 0, 1, 3, 1, 4, 2, 0, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 3, 2, 4, 3, 5, 5, 1, 3, 1, + 2, 1, 3, 4, 1, 2, 2, 1, 1, 3, + 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 4, 1, 2, 2, 2, 2, 2, + 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 1, 3, 3, 0, 2, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 4, 4, 5, 6, 4, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 4, 5, 4, 4, 2, 2, 4, 3, 3, + 5, 3, 4, 3, 5, 1, 0, 1, 3, 1, + 1, 2, 1, 1, 5, 0, 2, 1, 3, 1, + 3, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -849,656 +849,642 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint16 yydefact[] = { - 5, 0, 3, 0, 1, 0, 7, 0, 22, 157, - 159, 0, 0, 158, 218, 20, 6, 344, 0, 4, + 5, 0, 3, 0, 1, 0, 7, 0, 22, 158, + 160, 0, 0, 159, 219, 20, 6, 345, 0, 4, 0, 0, 0, 21, 0, 0, 0, 16, 0, 0, - 9, 22, 0, 8, 28, 126, 155, 0, 39, 155, - 0, 263, 74, 0, 0, 0, 78, 0, 0, 292, - 91, 0, 88, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 290, 0, 25, 0, 256, 257, - 260, 258, 259, 50, 93, 134, 146, 114, 163, 162, - 127, 0, 0, 0, 183, 196, 197, 26, 215, 0, - 139, 27, 0, 19, 0, 0, 0, 0, 0, 0, - 345, 160, 161, 11, 14, 286, 18, 22, 13, 17, - 156, 264, 153, 0, 0, 0, 0, 162, 189, 193, - 179, 177, 178, 176, 265, 134, 0, 294, 249, 0, - 210, 134, 268, 294, 151, 152, 0, 0, 276, 293, - 269, 0, 0, 294, 0, 0, 36, 48, 0, 29, - 274, 154, 0, 122, 117, 118, 121, 115, 116, 0, - 0, 148, 0, 149, 174, 172, 173, 119, 120, 0, - 291, 0, 219, 0, 32, 0, 0, 0, 0, 0, + 9, 22, 0, 8, 28, 127, 156, 0, 39, 156, + 0, 264, 75, 0, 0, 0, 79, 0, 0, 293, + 92, 0, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 291, 0, 25, 0, 257, 258, + 261, 259, 260, 50, 94, 135, 147, 115, 164, 163, + 128, 0, 0, 0, 184, 197, 198, 26, 216, 0, + 140, 27, 0, 19, 0, 0, 0, 0, 0, 0, + 346, 161, 162, 11, 14, 287, 18, 22, 13, 17, + 157, 265, 154, 0, 0, 0, 0, 163, 190, 194, + 180, 178, 179, 177, 266, 135, 0, 295, 250, 0, + 211, 135, 269, 295, 152, 153, 0, 0, 277, 294, + 270, 0, 0, 295, 0, 0, 36, 48, 0, 29, + 275, 155, 0, 123, 118, 119, 122, 116, 117, 0, + 0, 149, 0, 150, 175, 173, 174, 120, 121, 0, + 292, 0, 220, 0, 32, 0, 0, 0, 0, 0, 55, 0, 0, 0, 54, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, - 0, 0, 290, 261, 0, 140, 217, 0, 0, 0, - 0, 310, 0, 0, 210, 0, 0, 311, 0, 0, - 23, 287, 0, 12, 249, 0, 0, 194, 170, 168, - 169, 166, 167, 198, 0, 0, 295, 72, 0, 75, - 0, 71, 164, 243, 162, 246, 150, 247, 288, 0, - 249, 0, 204, 79, 76, 157, 0, 203, 0, 286, - 240, 228, 0, 64, 0, 0, 201, 272, 286, 226, - 238, 302, 0, 89, 38, 224, 286, 49, 31, 220, - 286, 0, 0, 40, 0, 175, 147, 0, 0, 35, - 286, 0, 0, 51, 95, 110, 113, 96, 100, 101, - 99, 111, 98, 97, 94, 112, 102, 103, 104, 105, - 106, 107, 108, 109, 284, 123, 278, 288, 0, 128, - 291, 0, 0, 288, 284, 255, 60, 253, 252, 270, - 254, 0, 53, 52, 277, 0, 0, 0, 0, 318, - 0, 0, 0, 0, 0, 317, 0, 312, 313, 314, - 0, 346, 0, 0, 296, 0, 0, 0, 15, 10, - 0, 0, 0, 180, 190, 66, 73, 0, 0, 294, - 165, 244, 245, 289, 250, 212, 0, 0, 0, 294, - 0, 236, 0, 249, 239, 287, 0, 0, 0, 0, - 302, 0, 0, 287, 0, 303, 231, 0, 302, 0, - 287, 0, 287, 0, 42, 275, 0, 0, 0, 199, - 170, 168, 169, 167, 140, 192, 191, 287, 0, 44, - 0, 140, 142, 280, 281, 288, 0, 288, 289, 0, - 0, 0, 131, 290, 262, 289, 0, 0, 0, 0, - 216, 0, 0, 325, 315, 316, 296, 300, 0, 298, - 0, 324, 339, 0, 0, 341, 342, 0, 0, 0, - 0, 0, 302, 0, 0, 309, 0, 297, 304, 308, - 305, 212, 171, 0, 0, 0, 0, 248, 249, 162, - 213, 188, 186, 187, 184, 185, 209, 212, 211, 80, - 77, 237, 241, 0, 229, 202, 195, 0, 0, 92, - 62, 65, 0, 233, 0, 302, 227, 200, 273, 230, - 64, 225, 37, 221, 30, 41, 0, 284, 45, 222, - 286, 47, 33, 43, 284, 0, 289, 285, 137, 0, - 279, 124, 130, 129, 0, 135, 136, 0, 271, 327, - 0, 0, 318, 0, 317, 0, 334, 350, 301, 0, - 0, 0, 348, 299, 328, 340, 0, 306, 0, 319, - 0, 302, 330, 0, 347, 335, 0, 69, 68, 294, - 0, 249, 205, 84, 212, 0, 59, 0, 302, 302, - 232, 0, 171, 0, 287, 0, 46, 0, 140, 144, - 141, 282, 283, 125, 290, 132, 61, 326, 335, 296, - 323, 0, 0, 302, 322, 0, 0, 320, 307, 331, - 296, 296, 338, 207, 336, 67, 70, 214, 0, 86, - 242, 0, 0, 56, 0, 63, 235, 234, 90, 138, - 223, 34, 143, 284, 0, 329, 0, 351, 321, 332, - 349, 0, 0, 0, 212, 0, 85, 81, 0, 0, - 0, 133, 335, 343, 335, 337, 206, 82, 87, 58, - 57, 145, 333, 208, 294, 0, 83 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 0, 0, 291, 262, 0, 141, 218, 0, 0, 0, + 0, 311, 0, 0, 211, 0, 0, 312, 0, 0, + 23, 288, 0, 12, 250, 0, 0, 195, 171, 169, + 170, 167, 168, 199, 0, 0, 0, 296, 73, 0, + 76, 0, 72, 165, 244, 163, 247, 151, 248, 289, + 0, 250, 0, 205, 80, 77, 158, 0, 204, 0, + 287, 241, 229, 0, 64, 0, 0, 202, 273, 287, + 227, 239, 303, 0, 90, 38, 225, 287, 49, 31, + 221, 287, 0, 0, 40, 0, 176, 148, 0, 0, + 35, 287, 0, 0, 51, 96, 111, 114, 97, 101, + 102, 100, 112, 99, 98, 95, 113, 103, 104, 105, + 106, 107, 108, 109, 110, 285, 124, 279, 289, 0, + 129, 292, 0, 0, 289, 285, 256, 60, 254, 253, + 271, 255, 0, 53, 52, 278, 0, 0, 0, 0, + 319, 0, 0, 0, 0, 0, 318, 0, 313, 314, + 315, 0, 347, 0, 0, 297, 0, 0, 0, 15, + 10, 0, 0, 0, 181, 191, 70, 66, 74, 0, + 0, 295, 166, 245, 246, 290, 251, 213, 0, 0, + 0, 295, 0, 237, 0, 250, 240, 288, 0, 0, + 0, 0, 303, 0, 0, 288, 0, 304, 232, 0, + 303, 0, 288, 0, 288, 0, 42, 276, 0, 0, + 0, 200, 171, 169, 170, 168, 141, 193, 192, 288, + 0, 44, 0, 141, 143, 281, 282, 289, 0, 289, + 290, 0, 0, 0, 132, 291, 263, 290, 0, 0, + 0, 0, 217, 0, 0, 326, 316, 317, 297, 301, + 0, 299, 0, 325, 340, 0, 0, 342, 343, 0, + 0, 0, 0, 0, 303, 0, 0, 310, 0, 298, + 305, 309, 306, 213, 172, 0, 0, 0, 0, 249, + 250, 163, 214, 189, 187, 188, 185, 186, 210, 213, + 212, 81, 78, 238, 242, 0, 230, 203, 196, 0, + 0, 93, 62, 65, 0, 234, 0, 303, 228, 201, + 274, 231, 64, 226, 37, 222, 30, 41, 0, 285, + 45, 223, 287, 47, 33, 43, 285, 0, 290, 286, + 138, 0, 280, 125, 131, 130, 0, 136, 137, 0, + 272, 328, 0, 0, 319, 0, 318, 0, 335, 351, + 302, 0, 0, 0, 349, 300, 329, 341, 0, 307, + 0, 320, 0, 303, 331, 0, 348, 336, 0, 69, + 68, 295, 0, 250, 206, 85, 213, 0, 59, 0, + 303, 303, 233, 0, 172, 0, 288, 0, 46, 0, + 141, 145, 142, 283, 284, 126, 291, 133, 61, 327, + 336, 297, 324, 0, 0, 303, 323, 0, 0, 321, + 308, 332, 297, 297, 339, 208, 337, 67, 71, 215, + 0, 87, 243, 0, 0, 56, 0, 63, 236, 235, + 91, 139, 224, 34, 144, 285, 0, 330, 0, 352, + 322, 333, 350, 0, 0, 0, 213, 0, 86, 82, + 0, 0, 0, 134, 336, 344, 336, 338, 207, 83, + 88, 58, 57, 146, 334, 209, 295, 0, 84 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 1, 6, 2, 3, 14, 21, 30, 105, 31, - 8, 24, 16, 17, 65, 327, 67, 149, 518, 519, - 145, 146, 68, 500, 328, 438, 501, 577, 388, 366, - 473, 237, 238, 239, 69, 127, 253, 70, 133, 378, - 573, 646, 664, 619, 647, 71, 143, 399, 72, 141, - 73, 74, 75, 76, 314, 423, 424, 590, 77, 316, - 243, 136, 78, 150, 111, 117, 13, 80, 81, 245, - 246, 163, 119, 82, 83, 480, 228, 84, 230, 231, - 85, 86, 87, 130, 214, 88, 252, 486, 89, 90, - 22, 280, 520, 276, 268, 259, 269, 270, 271, 261, - 384, 247, 248, 249, 329, 330, 322, 331, 272, 152, - 92, 317, 425, 426, 222, 374, 171, 140, 254, 466, - 551, 545, 396, 100, 212, 218, 612, 443, 347, 348, - 349, 351, 552, 547, 613, 614, 456, 457, 25, 467, - 553, 548 + 8, 24, 16, 17, 65, 328, 67, 149, 520, 521, + 145, 146, 68, 502, 329, 440, 503, 579, 390, 368, + 475, 238, 239, 240, 69, 127, 254, 70, 133, 380, + 575, 648, 666, 621, 649, 71, 143, 401, 72, 141, + 73, 74, 75, 76, 315, 425, 426, 592, 77, 317, + 244, 136, 78, 150, 111, 117, 13, 80, 81, 246, + 247, 163, 119, 82, 83, 482, 228, 84, 230, 231, + 85, 86, 87, 130, 214, 88, 253, 488, 89, 90, + 22, 281, 522, 277, 269, 260, 270, 271, 272, 262, + 386, 248, 249, 250, 330, 331, 323, 332, 273, 152, + 92, 318, 427, 428, 222, 376, 171, 140, 255, 468, + 553, 547, 398, 100, 212, 218, 614, 445, 348, 349, + 350, 352, 554, 549, 615, 616, 458, 459, 25, 469, + 555, 550 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -474 +#define YYPACT_NINF -473 static const yytype_int16 yypact[] = { - -474, 48, 28, 35, -474, 258, -474, 37, -474, -474, - -474, 61, 12, -474, 85, 107, -474, -474, 70, -474, - 156, 82, 1059, -474, 122, 328, 22, -474, 56, 199, - -474, 35, 211, -474, -474, -474, 258, 767, -474, 258, - 459, -474, -474, 152, 459, 258, -474, 23, 145, 1650, - -474, 23, -474, 294, 359, 1650, 1650, 1650, 1650, 1650, - 1650, 1693, 1650, 1650, 1289, 159, -474, 412, -474, -474, - -474, -474, -474, 939, -474, -474, 157, 302, -474, 168, - -474, 175, 184, 23, 204, -474, -474, -474, 219, 54, - -474, -474, 47, -474, 227, -12, 269, 227, 227, 239, - -474, -474, -474, -474, -474, 240, -474, -474, -474, -474, - -474, -474, -474, 250, 1813, 1813, 1813, -474, 259, -474, - -474, -474, -474, -474, -474, 64, 302, 1650, 1805, 262, - 260, 174, -474, 1650, -474, -474, 221, 1813, 2166, 255, - -474, 290, 237, 1650, 304, 1813, -474, -474, 420, -474, - -474, -474, 580, -474, -474, -474, -474, -474, -474, 1736, - 1693, 2166, 280, -474, 253, -474, 50, -474, -474, 275, - 2166, 285, -474, 430, -474, 612, 1650, 1650, 1650, 1650, - -474, 1650, 1650, 1650, -474, 1650, 1650, 1650, 1650, 1650, - 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, -474, - 1332, 428, 1650, -474, 1650, -474, -474, 1234, 1650, 1650, - 1650, -474, 763, 258, 260, 293, 369, -474, 1992, 1992, - -474, 51, 326, -474, 1805, 392, 1813, -474, -474, -474, - -474, -474, -474, -474, 341, 258, -474, -474, 371, -474, - 89, 342, 1813, -474, 1805, -474, -474, -474, 335, 360, - 1805, 1234, -474, -474, 357, 99, 399, -474, 365, 380, - -474, -474, 377, -474, 173, 151, -474, -474, 381, -474, - -474, 456, 1779, -474, -474, -474, 401, -474, -474, -474, - 404, 1650, 258, 366, 1838, -474, 405, 1813, 1813, -474, - 407, 1650, 410, 2166, 650, -474, 2190, 877, 877, 877, - 877, -474, 877, 877, 2214, -474, 461, 461, 461, 461, - -474, -474, -474, -474, 1387, -474, -474, 52, 1442, -474, - 2064, 411, 1160, 2031, 1387, -474, -474, -474, -474, -474, - -474, 19, 255, 255, 2166, 1905, 447, 441, 439, -474, - 444, 505, 1992, 225, 27, -474, 454, -474, -474, -474, - 1931, -474, 125, 458, 258, 460, 465, 466, -474, -474, - 463, 1813, 480, -474, -474, -474, -474, 1497, 1552, 1650, - -474, -474, -474, 1805, -474, 1872, 484, 24, 371, 1650, - 258, 485, 487, 1805, -474, 472, 481, 1813, 81, 399, - 456, 399, 490, 289, 483, -474, -474, 258, 456, 519, - 258, 495, 258, 496, 255, -474, 1650, 1897, 1813, -474, - 321, 349, 350, 354, -474, -474, -474, 258, 497, 255, - 1650, -474, 2094, -474, -474, 488, 491, 489, 1693, 498, - 500, 502, -474, 1650, -474, -474, 506, 503, 1234, 1160, - -474, 1992, 534, -474, -474, -474, 258, 1958, 1992, 258, - 1992, -474, -474, 565, 149, -474, -474, 510, 504, 1992, - 225, 1992, 456, 258, 258, -474, 514, 507, -474, -474, - -474, 1872, -474, 1234, 1650, 1650, 515, -474, 1805, 520, - -474, -474, -474, -474, -474, -474, -474, 1872, -474, -474, - -474, -474, -474, 518, -474, -474, -474, 1693, 517, -474, - -474, -474, 524, -474, 525, 456, -474, -474, -474, -474, - -474, -474, -474, -474, -474, 255, 526, 1387, -474, -474, - 527, 612, -474, 255, 1387, 1595, 1387, -474, -474, 530, - -474, -474, -474, -474, 116, -474, -474, 141, -474, -474, - 539, 540, 521, 542, 546, 538, -474, -474, 548, 543, - 1992, 549, -474, 552, -474, -474, 562, -474, 1992, -474, - 556, 456, -474, 560, -474, 1984, 238, 2166, 2166, 1650, - 561, 1805, -474, -474, 1872, 32, -474, 1160, 456, 456, - -474, 186, 370, 554, 258, 563, 410, 557, -474, 2166, - -474, -474, -474, -474, 1650, -474, -474, -474, 1984, 258, - -474, 1958, 1992, 456, -474, 258, 149, -474, -474, -474, - 258, 258, -474, -474, -474, -474, -474, -474, 564, 613, - -474, 1650, 1650, -474, 1693, 566, -474, -474, -474, -474, - -474, -474, -474, 1387, 558, -474, 571, -474, -474, -474, - -474, 577, 582, 583, 1872, 36, -474, -474, 2118, 2142, - 572, -474, 1984, -474, 1984, -474, -474, -474, -474, -474, - -474, -474, -474, -474, 1650, 371, -474 + -473, 65, 22, 49, -473, 261, -473, 64, -473, -473, + -473, 95, 52, -473, 143, 145, -473, -473, 104, -473, + 68, 128, 1049, -473, 142, 305, 16, -473, 56, 204, + -473, 49, 220, -473, -473, -473, 261, 974, -473, 261, + 562, -473, -473, 288, 562, 261, -473, 14, 147, 1615, + -473, 14, -473, 395, 401, 1615, 1615, 1615, 1615, 1615, + 1615, 1658, 1615, 1615, 737, 168, -473, 414, -473, -473, + -473, -473, -473, 649, -473, -473, 165, 122, -473, 169, + -473, 177, 218, 14, 219, -473, -473, -473, 235, 89, + -473, -473, 34, -473, 206, 124, 286, 206, 206, 260, + -473, -473, -473, -473, -473, 265, -473, -473, -473, -473, + -473, -473, -473, 270, 1803, 1803, 1803, -473, 269, -473, + -473, -473, -473, -473, -473, 39, 122, 882, 1777, 283, + 277, 230, -473, 1615, -473, -473, 292, 1803, 2097, 280, + -473, 332, 315, 1615, 215, 1803, -473, -473, 244, -473, + -473, -473, 949, -473, -473, -473, -473, -473, -473, 1701, + 1658, 2097, 298, -473, 9, -473, 59, -473, -473, 303, + 2097, 319, -473, 330, -473, 1744, 1615, 1615, 1615, 1615, + -473, 1615, 1615, 1615, -473, 1615, 1615, 1615, 1615, 1615, + 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, -473, + 1297, 455, 1615, -473, 1615, -473, -473, 1225, 1615, 1615, + 1615, -473, 594, 261, 277, 328, 403, -473, 1308, 1308, + -473, 152, 352, -473, 1777, 405, 1803, -473, -473, -473, + -473, -473, -473, -473, 354, 261, 1615, -473, -473, 382, + -473, 47, 360, 1803, -473, 1777, -473, -473, -473, 351, + 367, 1777, 1225, -473, -473, 366, 84, 407, -473, 374, + 373, -473, -473, 372, -473, 138, 42, -473, -473, 377, + -473, -473, 442, 1769, -473, -473, -473, 384, -473, -473, + -473, 389, 1615, 261, 391, 1830, -473, 394, 1803, 1803, + -473, 409, 1615, 411, 2097, 1935, -473, 2121, 1080, 1080, + 1080, 1080, -473, 1080, 1080, 2145, -473, 503, 503, 503, + 503, -473, -473, -473, -473, 1352, -473, -473, 27, 1407, + -473, 1995, 412, 1147, 1962, 1352, -473, -473, -473, -473, + -473, -473, 7, 280, 280, 2097, 698, 418, 415, 413, + -473, 416, 477, 1308, 188, 31, -473, 425, -473, -473, + -473, 1897, -473, 221, 433, 261, 434, 436, 439, -473, + -473, 432, 1803, 452, -473, -473, 2097, -473, -473, 1462, + 1517, 1615, -473, -473, -473, 1777, -473, 1856, 453, 91, + 382, 1615, 261, 454, 456, 1777, -473, 475, 451, 1803, + 133, 407, 442, 407, 460, 326, 462, -473, -473, 261, + 442, 467, 261, 478, 261, 486, 280, -473, 1615, 1864, + 1803, -473, 26, 248, 264, 430, -473, -473, -473, 261, + 492, 280, 1615, -473, 2025, -473, -473, 485, 493, 487, + 1658, 504, 506, 508, -473, 1615, -473, -473, 512, 505, + 1225, 1147, -473, 1308, 517, -473, -473, -473, 261, 1889, + 1308, 261, 1308, -473, -473, 571, 155, -473, -473, 514, + 509, 1308, 188, 1308, 442, 261, 261, -473, 518, 507, + -473, -473, -473, 1856, -473, 1225, 1615, 1615, 521, -473, + 1777, 528, -473, -473, -473, -473, -473, -473, -473, 1856, + -473, -473, -473, -473, -473, 520, -473, -473, -473, 1658, + 522, -473, -473, -473, 530, -473, 532, 442, -473, -473, + -473, -473, -473, -473, -473, -473, -473, 280, 535, 1352, + -473, -473, 536, 1744, -473, 280, 1352, 1560, 1352, -473, + -473, 539, -473, -473, -473, -473, 247, -473, -473, 308, + -473, -473, 541, 543, 545, 546, 547, 544, -473, -473, + 551, 548, 1308, 554, -473, 557, -473, -473, 576, -473, + 1308, -473, 564, 442, -473, 568, -473, 1923, 318, 2097, + 2097, 1615, 569, 1777, -473, -473, 1856, 156, -473, 1147, + 442, 442, -473, 243, 483, 563, 261, 577, 411, 570, + -473, 2097, -473, -473, -473, -473, 1615, -473, -473, -473, + 1923, 261, -473, 1889, 1308, 442, -473, 261, 155, -473, + -473, -473, 261, 261, -473, -473, -473, -473, -473, -473, + 579, 627, -473, 1615, 1615, -473, 1658, 580, -473, -473, + -473, -473, -473, -473, -473, 1352, 572, -473, 583, -473, + -473, -473, -473, 585, 586, 590, 1856, 77, -473, -473, + 2049, 2073, 584, -473, 1923, -473, 1923, -473, -473, -473, + -473, -473, -473, -473, -473, -473, 1615, 382, -473 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -474, -474, -474, -474, -474, -474, -474, -15, -474, -474, - 616, -474, -3, -474, -474, 622, -474, -125, -27, 66, - -474, -124, -112, -474, 11, -474, -474, -474, 147, -368, - -474, -474, -474, -474, -474, -474, -140, -474, -474, -474, - -474, -474, -474, -474, -474, -474, -474, -474, -474, -474, - 532, 10, 247, -474, -194, 132, 135, -474, 279, -59, - 418, 67, 5, 384, 624, 425, 317, 20, -474, 424, - 636, 509, -474, -474, -474, -474, -36, -37, -31, -49, - -474, -474, -474, -474, -474, -32, 464, -473, -474, -474, - -474, -474, -474, -474, -474, -474, 277, -119, -231, 287, - -474, 300, -474, -205, -300, 652, -474, -242, -474, -63, - 106, 182, -474, -316, -241, -285, -195, -474, -111, -420, - -474, -474, -245, -474, 402, -474, -176, -474, 345, 249, - 346, 218, 87, 96, -415, -474, -429, 252, -474, 522, - -474, -474 + -473, -473, -473, -473, -473, -473, -473, -12, -473, -473, + 624, -473, -1, -473, -473, 635, -473, -137, -48, 74, + -473, -130, -112, -473, 11, -473, -473, -473, 149, -372, + -473, -473, -473, -473, -473, -473, -140, -473, -473, -473, + -473, -473, -473, -473, -473, -473, -473, -473, -473, -473, + 662, 448, 257, -473, -196, 135, 139, -473, 262, -59, + 424, -16, -3, 387, 632, 427, 313, 20, -473, 428, + -89, 524, -473, -473, -473, -473, -36, -37, -31, -49, + -473, -473, -473, -473, -473, -32, 458, -472, -473, -473, + -473, -473, -473, -473, -473, -473, 279, -108, -211, 290, + -473, 306, -473, -214, -291, 658, -473, -230, -473, -63, + -6, 191, -473, -302, -219, -254, -195, -473, -107, -435, + -473, -473, -347, -473, 323, -473, 72, -473, 371, 268, + 380, 242, 102, 110, -468, -473, -438, 255, -473, 515, + -473, -473 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -277 +#define YYTABLE_NINF -278 static const yytype_int16 yytable[] = { - 121, 120, 162, 273, 175, 123, 122, 321, 437, 377, - 489, 324, 165, 104, 572, 236, 241, 260, 386, 360, - 275, 236, 434, 279, 164, 556, 541, 394, 108, 166, - 458, 236, 429, 390, 392, 401, 346, 621, 436, 403, - 174, 110, 356, 357, 110, 376, 101, 213, 4, 418, - 132, -215, 208, 5, 27, 206, 657, 118, 134, 27, - 7, 15, 11, 427, 18, 153, 154, 155, 156, 157, - 158, -267, 167, 168, 19, 9, -267, 229, 229, 229, - 9, 439, 232, 232, 232, -215, 439, 440, 497, 134, - 135, 229, 488, 498, 367, 102, 232, 622, 623, 459, - 229, 620, -236, 326, 223, 232, 20, 624, 229, -181, - 175, 165, 209, 232, 29, 229, 103, -215, 142, 29, - 232, 135, 210, 164, 10, 11, -267, 428, 166, 10, - 11, 23, -267, 26, 118, 118, 118, 382, 229, 538, - 527, 258, 529, 232, 33, 503, 290, 267, 118, 499, - 205, 165, 452, 509, 368, 139, 207, 118, 502, 27, - 504, -236, 380, 164, 210, 118, 451, -236, 166, 153, - 157, 656, 118, 9, 462, 381, 9, 641, 493, 636, - 9, -266, 594, 635, 93, 463, -266, 229, 595, 229, - 642, 643, 232, 497, 232, 118, 537, 381, 498, 453, - 464, 583, 106, 439, 391, 229, 358, 229, 587, 596, - 232, 128, 232, 229, 109, 28, 137, 562, 232, 29, - 517, 172, 10, 11, 199, 10, 11, 524, 452, 10, - 11, 566, 389, 240, -153, 229, -266, 662, 534, 663, - 232, 203, -266, 204, 118, 255, 118, 411, 410, 9, - 229, 229, 413, 412, 628, 232, 232, 236, 476, 431, - 580, 255, 118, -182, 118, 539, 260, 236, 490, 165, - 118, 546, 549, 570, 554, 453, 511, 513, -181, 585, - 256, 164, 9, 559, 454, 561, 166, 125, -183, 257, - 264, 131, 118, 216, 10, 11, 265, 666, 10, 11, - 439, 11, 221, 220, 118, 266, 615, 118, 118, 224, - 10, 11, -182, 255, 332, 333, 609, 650, 9, 126, - -183, 250, 235, 126, 229, 263, 484, 251, 9, 232, - 210, 10, 11, 626, 627, 625, 229, 94, 482, 481, - 286, 232, 264, 485, 483, 95, 229, 287, 265, 96, - 229, 232, 354, 144, 521, 232, -179, 288, 639, 97, - 98, 200, 10, 11, 274, 201, 618, 10, 11, 530, - 229, 229, 355, 202, 603, 232, 232, 10, 11, 165, - -179, 118, 607, 9, -177, -178, 359, 404, -179, -176, - 258, 164, 99, 118, 633, 118, 166, 419, 267, 634, - 361, 363, 508, 118, 369, -180, 365, 118, -177, -178, - 373, 211, 211, -176, 211, 211, -177, -178, 148, 379, - 375, -176, 484, 381, 383, 546, 638, 118, 118, -180, - 12, 406, 10, 11, 482, 481, 9, -180, 484, 485, - 483, 229, 385, 393, 9, 32, 232, 79, 165, 387, - 482, 481, 9, 32, 9, 485, 483, 236, 616, 395, - 164, 112, 35, 400, 112, 166, 402, 37, 129, 417, - 112, 173, 414, 332, 333, 420, 113, 433, 147, 151, - 278, 47, 48, 9, 229, 10, 11, 318, 51, 232, - 289, 118, 151, 10, 11, 178, 255, 215, 118, 217, - 219, 10, 11, 10, 11, 186, 446, 118, 447, 190, - 448, 449, 515, 450, 195, 196, 197, 198, 61, 460, - 465, 521, 468, 471, 665, 484, 523, 469, 470, 345, - 64, 256, 10, 11, 229, 345, 345, 482, 481, 232, - 472, 118, 485, 483, 487, 10, 11, 492, 380, 495, - 505, 507, 236, 244, 510, 512, 514, 522, 531, 528, - 532, 112, 533, 526, 435, 530, 535, 112, 555, 147, - 341, 536, 557, 151, 565, 165, 558, 569, 574, 571, - -157, 138, 464, 576, 578, 579, 582, 164, 37, 584, - 593, 118, 166, 161, 118, 484, 170, 113, 151, 597, - 598, 599, 47, 48, 9, -158, 600, 482, 481, 51, - 601, 606, 485, 483, 605, 602, 225, 604, 608, 610, - 37, 617, 629, 631, 644, 632, 319, 645, 439, 113, - 651, 652, 79, 115, 47, 48, 9, 653, 350, 226, - 661, 51, 654, 655, 66, 281, 32, 107, 225, 244, - 630, 64, 345, 10, 11, 282, 658, 581, 591, 345, - 364, 592, 371, 124, 118, 115, 405, 345, 372, 285, - 506, 226, 494, 477, 91, 244, 79, 291, 353, 575, - 444, 445, 564, 64, 178, 10, 11, 282, 181, 182, - 183, 540, 640, 185, 186, 187, 188, 637, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 151, 293, 294, - 295, 296, 560, 297, 298, 299, 0, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 0, 161, 0, 320, 352, 323, 0, 0, 0, - 138, 138, 334, 0, 0, 0, 0, 79, 0, 0, - 227, 233, 234, 0, 0, 0, 0, 0, 345, 0, - 0, 0, 0, 0, 544, 345, 0, 345, 455, 0, - 0, 335, 0, 262, 0, 37, 345, 0, 345, 350, - 336, 277, 0, 0, 113, 337, 338, 339, 283, 47, - 48, 9, 340, 0, 0, 0, 51, 0, 244, 341, - 479, 0, 0, 114, 0, 491, 0, 0, 244, 0, - 112, 292, 0, 138, 0, 0, 342, 0, 112, 0, - 115, 0, 112, 138, 0, 147, 116, 151, 343, 0, - 0, 0, 0, 0, 344, 0, 0, 11, 64, 0, - 10, 11, 151, 0, 0, 0, 422, 0, 0, 0, - 161, 0, 0, 0, 0, 0, 422, 0, 0, 0, - 0, 0, 362, 79, 79, 0, 0, 345, 0, 0, - 0, 350, 543, 0, 550, 345, 0, 0, 370, 455, - 0, 0, 345, 0, 0, 455, 0, 0, 563, 350, - 0, 0, 0, 0, 0, 0, 0, 0, 79, 138, - 138, 0, 0, 244, 0, 0, 0, 0, 398, 0, - 0, 178, 0, 0, 0, 345, 0, 0, 544, 345, - 409, 186, 0, 415, 416, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 0, 0, 0, 0, 138, 0, - 0, 0, 0, 176, -276, 0, 0, 0, 0, 0, - 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, - 161, 0, 0, 0, 0, 170, 0, 0, 0, 345, - 0, 345, 177, 178, 0, 179, 180, 181, 182, 183, - 0, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 244, 409, 0, 0, - 0, 0, 79, 0, -276, 0, 567, 568, 0, 151, - 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, - 0, 0, 0, 496, 350, 0, 543, 0, 0, 161, - 550, 455, 0, 0, 0, 350, 350, 0, 0, 0, - 0, 0, 0, 227, 516, 0, 0, 0, 0, 422, - 0, 0, 0, 0, 0, 0, 422, 589, 422, -2, + 121, 120, 162, 274, 175, 123, 122, 322, 491, 325, + 361, 280, 165, 543, 276, 237, 104, 574, 558, 174, + 242, 237, 379, 439, 164, 227, 233, 234, 261, 166, + 108, 237, 436, 110, 460, 142, 110, 378, 429, 208, + 101, 388, 132, 139, -184, 505, -268, 5, 263, 134, + 396, -268, 369, 511, 392, 394, 278, 118, 403, 27, + -216, -180, 405, 284, 431, 4, 383, 205, -183, 441, + 438, 27, 420, 207, 7, 442, -184, 229, 229, 229, + 9, 135, 232, 232, 232, -180, 293, -237, 15, 102, + 206, 229, 9, -180, -216, 393, 232, 659, 18, 209, + 229, -268, 430, 461, 622, 232, 223, -268, 229, 210, + 175, 165, 370, 232, 19, 229, 103, 564, -182, 29, + 232, 241, 210, 164, 134, 291, -216, 28, 166, 10, + 11, 29, 637, 259, 118, 118, 118, 363, 229, 268, + 499, 10, 11, 232, 327, 500, -237, 382, 118, 384, + 540, 165, -237, 441, 372, 27, 135, 118, 454, 490, + 582, 623, 383, 164, 20, 118, 638, 26, 166, 23, + 643, 495, 118, 529, 658, 531, 9, 644, 645, 9, + 504, 200, 506, 213, 400, 201, 664, 229, 665, 229, + 33, 454, 232, 202, 232, 118, 411, 391, 11, 417, + 418, 501, 333, 334, 93, 455, 229, 106, 229, 359, + 539, 232, 9, 232, 229, 29, 611, 585, 137, 232, + 519, 624, 625, 109, 589, 10, 11, 526, 10, 11, + 172, 626, 199, 628, 629, -154, 229, -267, 455, 9, + 536, 232, -267, 203, 118, 568, 118, 456, 413, 412, + 499, 229, 229, 415, 414, 500, 232, 232, 641, 237, + 433, 10, 11, 118, 478, 118, 572, 515, 9, 237, + 165, 118, 513, 411, 492, 275, 406, 204, -183, 261, + 11, 465, 164, -178, 347, 9, 421, 166, 10, 11, + 357, 358, -267, 118, -182, 668, 466, 125, -267, -179, + 498, 131, 126, 587, 279, 118, 126, -178, 118, 118, + 216, 630, 9, 596, 94, -178, 256, 10, 11, 597, + 227, 518, 95, -179, 220, 229, 96, 221, 486, 224, + 232, -179, 235, 652, 10, 11, 97, 98, 229, 256, + 484, 483, 251, 232, 252, 487, 485, 128, 229, 627, + 256, 257, 229, 232, 9, 210, 523, 232, 287, 620, + 258, 10, 11, 333, 334, 10, 11, 264, 265, 99, + 441, 532, 229, 229, 266, 288, 598, 232, 232, 265, + 441, 165, 118, 267, 259, 266, 617, 355, 10, 11, + 290, 289, 268, 164, 635, 118, 510, 118, 166, 10, + 11, 636, 517, 10, 11, 118, 356, 211, 211, 118, + 211, 211, 360, 362, 364, 453, 525, 367, 215, 9, + 217, 219, 371, 464, 486, 9, 375, 377, 381, 118, + 118, 383, 12, 385, 588, 387, 484, 483, 9, 395, + 486, 487, 485, 229, 389, 397, 402, 32, 232, 79, + 165, 404, 484, 483, 144, 32, 408, 487, 485, 237, + 148, 416, 164, 112, 618, -177, 112, 166, 10, 11, + 129, 419, 112, 173, 10, 11, 422, 448, 435, 9, + 147, 151, 449, 451, 450, 452, 229, 10, 11, -177, + 462, 232, 473, 118, 151, 467, 470, -177, 471, 256, + 118, 472, 512, 153, 154, 155, 156, 157, 158, 118, + 167, 168, 474, 489, 319, 541, 494, 382, -181, 497, + 507, 548, 551, 523, 556, 346, 667, 486, 10, 11, + 509, 346, 346, 561, 257, 563, 229, 178, 514, 484, + 483, 232, -181, 118, 487, 485, 516, 186, 10, 11, + -181, 190, 524, 342, 237, 245, 195, 196, 197, 198, + 528, 530, 437, 112, 533, 35, 534, 532, 535, 112, + 37, 147, 537, 538, 557, 151, 559, 165, 567, 113, + 576, 560, 466, 571, 47, 48, 9, 573, 578, 164, + 580, 51, 581, 118, 166, 584, 118, 486, 586, 595, + 151, 599, 336, 600, -158, 601, -159, 153, 157, 484, + 483, 337, 602, 603, 487, 485, 338, 339, 340, 607, + 604, 61, 606, 341, 605, 608, 610, 612, 320, 619, + 342, 631, 609, 64, 79, 10, 11, 633, 634, 646, + 351, 647, 441, 654, 653, 655, 656, 343, 32, 346, + 657, 245, 663, 176, -277, 107, 346, 66, 660, 344, + 632, 583, 365, 593, 346, 345, 118, 594, 11, 373, + 407, 124, 354, 374, 508, 548, 640, 496, 245, 79, + 91, 479, 177, 178, 286, 179, 180, 181, 182, 183, + 577, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 336, 446, 566, 642, + 151, 138, 542, 639, -277, 337, 447, 562, 0, 0, + 338, 339, 340, 161, -277, 0, 170, 341, 353, 0, + 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 0, 37, 0, 0, 169, 0, + 79, 343, 0, 0, 113, 0, 346, 444, 0, 47, + 48, 9, 546, 346, 0, 346, 51, 0, 0, 345, + 0, 457, 11, 55, 346, 0, 346, 0, 0, 0, + 0, 0, 351, 0, 0, 0, 56, 57, 0, 58, + 59, 0, 0, 60, 0, 0, 61, 0, 0, 0, + 0, 0, 245, 0, 481, 0, 62, 63, 64, 493, + 10, 11, 245, 0, 112, 0, 0, 0, 0, 0, + 0, 0, 112, 0, 0, 0, 112, 0, 0, 147, + 0, 151, 0, 0, 0, 0, 0, 0, 294, 295, + 296, 297, 0, 298, 299, 300, 151, 301, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 0, 161, 0, 321, 346, 324, 79, 79, 0, + 138, 138, 335, 346, 0, 351, 545, 0, 552, 0, + 346, 0, 0, 457, 0, 35, 0, 0, 0, 457, + 37, 0, 565, 351, 0, 0, 0, 0, 366, 113, + 0, 0, 79, 0, 47, 48, 9, 245, 236, 0, + 0, 51, 0, 346, 0, 0, 546, 346, 55, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 56, 57, 0, 58, 59, 0, 0, 60, 0, + 0, 61, 0, 0, 138, 0, 0, 0, 0, 0, + 0, 62, 63, 64, 138, 10, 11, 37, 0, 0, + 0, 0, 0, 0, 0, 0, 113, 346, 0, 346, + 0, 47, 48, 9, 0, 0, 0, 424, 51, 0, + 0, 161, 37, 0, 0, 225, 0, 424, 0, 0, + 0, 113, 0, 0, 0, 0, 47, 48, 9, 0, + 245, 0, 115, 51, 0, 0, 79, 0, 226, 0, + 114, 0, 0, 151, 282, 0, 0, 0, 0, 0, + 64, 0, 10, 11, 283, 0, 0, 115, 351, 0, + 545, 138, 138, 116, 552, 457, 0, 0, 0, 351, + 351, 0, 0, 0, 0, 64, 0, 10, 11, -2, 34, 0, 35, 0, 0, 36, 0, 37, 38, 39, 0, 0, 40, 0, 41, 42, 43, 44, 45, 46, - 0, 47, 48, 9, 0, 0, 49, 50, 51, 52, - 53, 54, 0, 0, 0, 55, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 56, 57, + 138, 47, 48, 9, 0, 0, 49, 50, 51, 52, + 53, 54, 0, 0, 138, 55, 0, 0, 0, 0, + 0, 0, 161, 0, 0, 0, 0, 170, 56, 57, 0, 58, 59, 0, 0, 60, 0, 0, 61, 0, - 0, -24, 0, 0, 0, 0, 170, 0, 62, 63, - 64, 0, 10, 11, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 648, 649, 0, 161, 586, 0, 0, - 0, 325, 0, 35, 0, 422, 36, -251, 37, 38, - 39, 0, -251, 40, 0, 41, 42, 113, 44, 45, - 46, 0, 47, 48, 9, 0, 0, 49, 50, 51, - 52, 53, 54, 0, 0, 0, 55, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, - 57, 0, 58, 59, 0, 0, 60, 0, 0, 61, - 0, 0, -251, 0, 0, 0, 0, 326, -251, 62, - 63, 64, 0, 10, 11, 325, 0, 35, 0, 0, - 36, 0, 37, 38, 39, 0, 0, 40, 0, 41, - 42, 113, 44, 45, 46, 0, 47, 48, 9, 0, - 0, 49, 50, 51, 52, 53, 54, 0, 0, 0, - 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 56, 57, 0, 58, 59, 0, 0, - 60, 0, 35, 61, 0, 0, -251, 37, 0, 0, - 169, 326, -251, 62, 63, 64, 113, 10, 11, 0, - 0, 47, 48, 9, 0, 0, 0, 0, 51, 0, - 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 56, 57, - 37, 58, 59, 0, 0, 60, 0, 0, 61, 113, - 0, 0, 0, 0, 47, 48, 9, 0, 62, 63, - 64, 51, 10, 11, 0, 0, 0, 0, 159, 0, + 0, -24, 0, 0, 178, 0, 0, 0, 62, 63, + 64, 0, 10, 11, 186, 0, 0, 0, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 0, 569, 570, + 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, + 35, 0, 0, 36, -252, 37, 38, 39, 0, -252, + 40, 161, 41, 42, 113, 44, 45, 46, 0, 47, + 48, 9, 0, 0, 49, 50, 51, 52, 53, 54, + 0, 424, 0, 55, 0, 0, 0, 0, 424, 591, + 424, 0, 0, 0, 0, 0, 56, 57, 0, 58, + 59, 0, 0, 60, 0, 0, 61, 0, 0, -252, + 0, 0, 0, 0, 327, -252, 62, 63, 64, 0, + 10, 11, 0, 0, 0, 0, 326, 0, 35, 0, + 0, 36, 0, 37, 38, 39, 0, 0, 40, 0, + 41, 42, 113, 44, 45, 46, 0, 47, 48, 9, + 0, 0, 49, 50, 51, 52, 53, 54, 170, 0, + 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 57, 0, 58, 59, 0, + 0, 60, 0, 0, 61, 650, 651, -252, 161, 0, + 0, 0, 327, -252, 62, 63, 64, 424, 10, 11, + 35, 0, 0, 0, 0, 37, 0, 0, 0, 0, + 0, 0, 0, 0, 113, 0, 336, 0, 0, 47, + 48, 9, 0, 0, 0, 337, 51, 0, 0, 0, + 338, 339, 340, 159, 0, 0, 0, 341, 0, 0, + 0, 0, 0, 0, 342, 0, 56, 57, 0, 58, + 160, 0, 0, 60, 0, 35, 61, 316, 0, 0, + 37, 343, 0, 0, 0, 0, 62, 63, 64, 113, + 10, 11, 0, 0, 47, 48, 9, 0, 0, 345, + 0, 51, 11, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 56, 57, 0, 58, 160, 0, 0, 60, 0, - 35, 61, 315, 0, 0, 37, 0, 0, 0, 0, + 0, 56, 57, 0, 58, 59, 0, 0, 60, 0, + 35, 61, 0, 0, 0, 37, 0, 0, 0, 423, 0, 62, 63, 64, 113, 10, 11, 0, 0, 47, - 48, 9, 0, 0, 0, 0, 51, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, + 48, 9, 0, 0, 0, 0, 51, 0, 432, 0, + 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 57, 0, 58, - 59, 0, 0, 60, 0, 35, 61, 0, 0, 0, - 37, 0, 0, 0, 421, 0, 62, 63, 64, 113, - 10, 11, 0, 0, 47, 48, 9, 0, 0, 0, - 0, 51, 0, 430, 0, 0, 0, 0, 159, 0, + 160, 0, 0, 60, 0, 35, 61, 0, 0, 0, + 37, 0, 0, 0, 0, 0, 62, 63, 64, 113, + 10, 11, 0, 0, 47, 48, 9, 0, 476, 0, + 0, 51, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 56, 57, 0, 58, 160, 0, 0, 60, 0, + 0, 56, 57, 0, 58, 59, 0, 0, 60, 0, 35, 61, 0, 0, 0, 37, 0, 0, 0, 0, 0, 62, 63, 64, 113, 10, 11, 0, 0, 47, - 48, 9, 0, 474, 0, 0, 51, 0, 0, 0, + 48, 9, 0, 477, 0, 0, 51, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 56, 57, 0, 58, - 59, 0, 0, 60, 0, 35, 61, 0, 0, 0, - 37, 0, 0, 0, 0, 0, 62, 63, 64, 113, - 10, 11, 0, 0, 47, 48, 9, 0, 475, 0, - 0, 51, 0, 0, 0, 0, 0, 0, 55, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, - 0, 56, 57, 37, 58, 59, 0, 0, 60, 0, - 0, 61, 113, 0, 0, 0, 0, 47, 48, 9, - 0, 62, 63, 64, 51, 10, 11, 0, 0, 0, + 0, 0, 0, 35, 0, 0, 56, 57, 37, 58, + 59, 0, 0, 60, 0, 0, 61, 113, 0, 0, + 0, 0, 47, 48, 9, 0, 62, 63, 64, 51, + 10, 11, 0, 0, 0, 0, 55, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, + 57, 0, 58, 59, 0, 0, 60, 0, 35, 61, + 0, 0, 0, 37, 0, 0, 0, 590, 0, 62, + 63, 64, 113, 10, 11, 0, 0, 47, 48, 9, + 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 56, 57, 0, 58, 59, 0, - 0, 60, 0, 35, 61, 0, 0, 0, 37, 0, - 0, 0, 588, 0, 62, 63, 64, 113, 10, 11, - 0, 0, 47, 48, 9, 0, 0, 0, 0, 51, - 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 35, 0, 0, 56, - 57, 37, 58, 59, 0, 0, 60, 0, 0, 61, - 113, 0, 0, 0, 0, 47, 48, 9, 0, 62, - 63, 64, 51, 10, 11, 0, 0, 0, 0, 159, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, - 0, 0, 56, 57, 284, 58, 160, 0, 0, 60, - 0, 0, 61, 113, 0, 0, 0, 0, 47, 48, - 9, 0, 62, 63, 64, 51, 10, 11, 0, 0, - 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 56, 57, 37, 58, 59, - 0, 0, 60, 0, 0, 61, 113, 0, 0, 0, - 0, 47, 48, 9, 0, 62, 63, 64, 51, 10, - 11, 0, 0, 37, 0, 225, 242, 0, 0, 0, - 0, 37, 113, 0, 0, 0, 0, 47, 48, 9, - 113, 0, 115, 0, 51, 47, 48, 9, 226, 0, - 0, 225, 51, 0, 0, 0, 37, 0, 0, 225, - 64, 0, 10, 11, 397, 113, 0, 0, 115, 0, - 47, 48, 9, 0, 226, 0, 115, 51, 0, 0, - 0, 0, 226, 0, 407, 0, 64, 0, 10, 11, - 37, 0, 0, 0, 64, 0, 10, 11, 0, 113, - 0, 115, 0, 0, 47, 48, 9, 408, 0, 0, - 0, 51, 0, 0, 0, 284, 0, 0, 225, 64, - 0, 10, 11, 335, 113, 0, 0, 0, 0, 47, - 48, 9, 336, 0, 0, 115, 51, 337, 338, 339, - 0, 478, 0, 225, 340, 0, 0, 0, 0, 335, - 0, 441, 461, 64, 0, 10, 11, 0, 336, 0, - 115, 0, 0, 337, 338, 339, 226, 0, 342, 0, - 340, 0, 0, 0, 442, 0, 335, 341, 64, 0, - 10, 11, 0, 0, 0, 336, 344, 0, 0, 11, - 337, 338, 542, 0, 342, 0, 0, 340, 0, 0, - 0, 0, 335, 0, 341, 0, 0, 0, 0, 0, - 335, 336, 344, 0, 0, 11, 337, 338, 339, 336, - 0, 342, 0, 340, 337, 338, 339, 0, 0, 0, - 341, 340, 0, 0, 0, 0, 0, 0, 341, 344, - 0, 10, 11, 0, 0, 0, 0, 342, 0, 0, - 0, 0, 0, 611, 0, 342, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 344, 0, 0, 11, 0, - 0, 0, 0, 344, 177, 178, 11, 179, 0, 181, + 0, 35, 0, 0, 56, 57, 37, 58, 59, 0, + 0, 60, 0, 0, 61, 113, 0, 0, 0, 0, + 47, 48, 9, 0, 62, 63, 64, 51, 10, 11, + 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 35, 0, 0, 56, 57, 285, + 58, 160, 0, 0, 60, 0, 0, 61, 113, 0, + 0, 0, 0, 47, 48, 9, 0, 62, 63, 64, + 51, 10, 11, 0, 0, 0, 0, 55, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 57, 37, 58, 59, 0, 0, 60, 0, 0, + 61, 113, 0, 0, 0, 0, 47, 48, 9, 0, + 62, 63, 64, 51, 10, 11, 0, 37, 0, 0, + 225, 0, 0, 0, 0, 37, 113, 0, 243, 0, + 0, 47, 48, 9, 113, 0, 0, 115, 51, 47, + 48, 9, 0, 226, 0, 225, 51, 0, 0, 292, + 0, 37, 0, 225, 0, 64, 0, 10, 11, 283, + 113, 0, 115, 0, 0, 47, 48, 9, 226, 0, + 115, 0, 51, 0, 0, 0, 226, 0, 37, 225, + 64, 0, 10, 11, 399, 0, 0, 113, 64, 0, + 10, 11, 47, 48, 9, 0, 115, 0, 0, 51, + 0, 0, 226, 0, 37, 0, 409, 0, 0, 0, + 0, 0, 285, 113, 64, 0, 10, 11, 47, 48, + 9, 113, 0, 115, 0, 51, 47, 48, 9, 410, + 0, 0, 225, 51, 0, 0, 0, 336, 0, 0, + 225, 64, 0, 10, 11, 336, 337, 0, 463, 115, + 0, 338, 339, 544, 337, 480, 0, 115, 341, 338, + 339, 340, 0, 226, 0, 342, 341, 64, 0, 10, + 11, 336, 0, 342, 0, 64, 0, 10, 11, 0, + 337, 0, 343, 0, 0, 338, 339, 340, 0, 0, + 343, 0, 341, 0, 0, 0, 0, 0, 0, 342, + 345, 0, 10, 11, 0, 0, 0, 0, 345, 178, + 0, 11, 0, 181, 182, 183, 343, 0, 185, 186, + 187, 188, 613, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 0, 0, 345, 177, 178, 11, 179, 0, + 181, 182, 183, 0, 0, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 177, 178, + 0, 179, 0, 181, 182, 183, 0, 437, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 0, 0, 0, 0, 0, 0, 177, 178, + 0, 179, 0, 181, 182, 183, 0, 434, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 177, 178, 0, 179, 0, 181, 182, 183, + 0, 527, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 177, 178, 0, 179, + 0, 181, 182, 183, 0, 661, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, + 177, 178, 0, 179, 0, 181, 182, 183, 0, 662, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 177, 178, 0, 0, 0, 181, 182, 183, 0, 0, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 177, 178, 0, - 179, 0, 181, 182, 183, 0, 435, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 0, 0, 0, 0, 0, 0, 177, 178, 0, - 179, 0, 181, 182, 183, 0, 432, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 177, 178, 0, 179, 0, 181, 182, 183, 0, - 525, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 177, 178, 0, 179, 0, - 181, 182, 183, 0, 659, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 177, - 178, 0, 179, 0, 181, 182, 183, 0, 660, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 177, 178, 0, 0, 0, 181, 182, - 183, 0, 0, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 177, 178, 0, - 0, 0, 181, 182, 183, 0, 0, 185, 186, 187, - 188, 0, 190, 191, 192, 193, 194, 195, 196, 197, - 198 + 191, 192, 193, 194, 195, 196, 197, 198, 177, 178, + 0, 0, 0, 181, 182, 183, 0, 0, 185, 186, + 187, 188, 0, 190, 191, 192, 193, 194, 195, 196, + 197, 198 }; static const yytype_int16 yycheck[] = { - 37, 37, 61, 143, 67, 37, 37, 202, 324, 251, - 378, 205, 61, 28, 487, 127, 127, 136, 259, 224, - 144, 133, 322, 148, 61, 454, 446, 268, 31, 61, - 3, 143, 317, 264, 265, 276, 212, 5, 323, 280, - 67, 36, 218, 219, 39, 250, 24, 59, 0, 290, - 45, 1, 5, 25, 3, 1, 20, 37, 35, 3, - 25, 24, 74, 11, 3, 55, 56, 57, 58, 59, - 60, 7, 62, 63, 62, 24, 12, 114, 115, 116, - 24, 62, 114, 115, 116, 35, 62, 68, 7, 35, - 67, 128, 68, 12, 5, 73, 128, 65, 66, 72, - 137, 574, 3, 67, 107, 137, 21, 75, 145, 59, - 173, 160, 65, 145, 63, 152, 60, 67, 51, 63, - 152, 67, 75, 160, 73, 74, 62, 75, 160, 73, - 74, 24, 68, 63, 114, 115, 116, 256, 175, 439, - 425, 136, 427, 175, 62, 390, 173, 142, 128, 68, - 83, 200, 3, 398, 65, 49, 89, 137, 389, 3, - 391, 62, 63, 200, 75, 145, 342, 68, 200, 159, - 160, 644, 152, 24, 350, 24, 24, 606, 383, 599, - 24, 7, 66, 598, 62, 60, 12, 224, 72, 226, - 610, 611, 224, 7, 226, 175, 438, 24, 12, 50, - 75, 517, 3, 62, 53, 242, 221, 244, 524, 68, - 242, 59, 244, 250, 3, 59, 71, 462, 250, 63, - 414, 62, 73, 74, 67, 73, 74, 421, 3, 73, - 74, 473, 59, 127, 66, 272, 62, 652, 433, 654, - 272, 66, 68, 59, 224, 24, 226, 284, 284, 24, - 287, 288, 284, 284, 68, 287, 288, 369, 369, 318, - 505, 24, 242, 59, 244, 441, 385, 379, 379, 318, - 250, 447, 448, 478, 450, 50, 400, 402, 59, 520, - 59, 318, 24, 459, 59, 461, 318, 40, 35, 68, - 53, 44, 272, 24, 73, 74, 59, 665, 73, 74, - 62, 74, 62, 64, 284, 68, 68, 287, 288, 59, - 73, 74, 59, 24, 208, 209, 561, 633, 24, 40, - 67, 59, 63, 44, 361, 35, 375, 67, 24, 361, - 75, 73, 74, 578, 579, 577, 373, 9, 375, 375, - 60, 373, 53, 375, 375, 17, 383, 72, 59, 21, - 387, 383, 59, 59, 417, 387, 35, 72, 603, 31, - 32, 59, 73, 74, 60, 63, 571, 73, 74, 428, - 407, 408, 3, 71, 550, 407, 408, 73, 74, 428, - 59, 361, 558, 24, 35, 35, 60, 281, 67, 35, - 385, 428, 64, 373, 588, 375, 428, 291, 393, 594, - 8, 60, 397, 383, 62, 35, 35, 387, 59, 59, - 75, 94, 95, 59, 97, 98, 67, 67, 59, 62, - 60, 67, 471, 24, 59, 601, 602, 407, 408, 59, - 5, 65, 73, 74, 471, 471, 24, 67, 487, 471, - 471, 478, 62, 62, 24, 20, 478, 22, 497, 72, - 487, 487, 24, 28, 24, 487, 487, 569, 569, 3, - 497, 36, 3, 62, 39, 497, 62, 8, 43, 62, - 45, 59, 67, 367, 368, 65, 17, 66, 53, 54, - 60, 22, 23, 24, 521, 73, 74, 59, 29, 521, - 60, 471, 67, 73, 74, 34, 24, 95, 478, 97, - 98, 73, 74, 73, 74, 44, 59, 487, 67, 48, - 71, 67, 406, 8, 53, 54, 55, 56, 59, 65, - 62, 584, 62, 60, 664, 574, 420, 62, 62, 212, - 71, 59, 73, 74, 571, 218, 219, 574, 574, 571, - 60, 521, 574, 574, 60, 73, 74, 60, 63, 68, - 60, 68, 664, 128, 35, 60, 60, 60, 60, 68, - 60, 136, 60, 75, 75, 624, 60, 142, 3, 144, - 36, 68, 62, 148, 60, 624, 72, 62, 60, 59, - 59, 49, 75, 66, 60, 60, 60, 624, 8, 62, - 60, 571, 624, 61, 574, 644, 64, 17, 173, 60, - 60, 59, 22, 23, 24, 59, 68, 644, 644, 29, - 62, 49, 644, 644, 62, 72, 36, 68, 62, 59, - 8, 60, 68, 60, 60, 68, 201, 14, 62, 17, - 72, 60, 207, 53, 22, 23, 24, 60, 213, 59, - 68, 29, 60, 60, 22, 65, 221, 31, 36, 224, - 584, 71, 335, 73, 74, 75, 645, 510, 526, 342, - 235, 526, 244, 39, 644, 53, 282, 350, 244, 160, - 393, 59, 385, 373, 22, 250, 251, 65, 214, 497, - 335, 335, 464, 71, 34, 73, 74, 75, 38, 39, - 40, 442, 605, 43, 44, 45, 46, 601, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 282, 176, 177, - 178, 179, 460, 181, 182, 183, -1, 185, 186, 187, + 37, 37, 61, 143, 67, 37, 37, 202, 380, 205, + 224, 148, 61, 448, 144, 127, 28, 489, 456, 67, + 127, 133, 252, 325, 61, 114, 115, 116, 136, 61, + 31, 143, 323, 36, 3, 51, 39, 251, 11, 5, + 24, 260, 45, 49, 35, 392, 7, 25, 137, 35, + 269, 12, 5, 400, 265, 266, 145, 37, 277, 3, + 1, 35, 281, 152, 318, 0, 24, 83, 59, 62, + 324, 3, 291, 89, 25, 68, 67, 114, 115, 116, + 24, 67, 114, 115, 116, 59, 175, 3, 24, 73, + 1, 128, 24, 67, 35, 53, 128, 20, 3, 65, + 137, 62, 75, 72, 576, 137, 107, 68, 145, 75, + 173, 160, 65, 145, 62, 152, 60, 464, 59, 63, + 152, 127, 75, 160, 35, 173, 67, 59, 160, 73, + 74, 63, 600, 136, 114, 115, 116, 226, 175, 142, + 7, 73, 74, 175, 67, 12, 62, 63, 128, 257, + 441, 200, 68, 62, 243, 3, 67, 137, 3, 68, + 507, 5, 24, 200, 21, 145, 601, 63, 200, 24, + 608, 385, 152, 427, 646, 429, 24, 612, 613, 24, + 391, 59, 393, 59, 273, 63, 654, 224, 656, 226, + 62, 3, 224, 71, 226, 175, 285, 59, 74, 288, + 289, 68, 208, 209, 62, 50, 243, 3, 245, 221, + 440, 243, 24, 245, 251, 63, 563, 519, 71, 251, + 416, 65, 66, 3, 526, 73, 74, 423, 73, 74, + 62, 75, 67, 580, 581, 66, 273, 7, 50, 24, + 435, 273, 12, 66, 224, 475, 226, 59, 285, 285, + 7, 288, 289, 285, 285, 12, 288, 289, 605, 371, + 319, 73, 74, 243, 371, 245, 480, 404, 24, 381, + 319, 251, 402, 362, 381, 60, 282, 59, 59, 387, + 74, 60, 319, 35, 212, 24, 292, 319, 73, 74, + 218, 219, 62, 273, 59, 667, 75, 40, 68, 35, + 389, 44, 40, 522, 60, 285, 44, 59, 288, 289, + 24, 68, 24, 66, 9, 67, 24, 73, 74, 72, + 409, 410, 17, 59, 64, 362, 21, 62, 377, 59, + 362, 67, 63, 635, 73, 74, 31, 32, 375, 24, + 377, 377, 59, 375, 67, 377, 377, 59, 385, 579, + 24, 59, 389, 385, 24, 75, 419, 389, 60, 573, + 68, 73, 74, 369, 370, 73, 74, 35, 53, 64, + 62, 430, 409, 410, 59, 72, 68, 409, 410, 53, + 62, 430, 362, 68, 387, 59, 68, 59, 73, 74, + 60, 72, 395, 430, 590, 375, 399, 377, 430, 73, + 74, 596, 408, 73, 74, 385, 3, 94, 95, 389, + 97, 98, 60, 8, 60, 343, 422, 35, 95, 24, + 97, 98, 62, 351, 473, 24, 75, 60, 62, 409, + 410, 24, 5, 59, 523, 62, 473, 473, 24, 62, + 489, 473, 473, 480, 72, 3, 62, 20, 480, 22, + 499, 62, 489, 489, 59, 28, 65, 489, 489, 571, + 59, 67, 499, 36, 571, 35, 39, 499, 73, 74, + 43, 62, 45, 59, 73, 74, 65, 59, 66, 24, + 53, 54, 67, 67, 71, 8, 523, 73, 74, 59, + 65, 523, 60, 473, 67, 62, 62, 67, 62, 24, + 480, 62, 35, 55, 56, 57, 58, 59, 60, 489, + 62, 63, 60, 60, 59, 443, 60, 63, 35, 68, + 60, 449, 450, 586, 452, 212, 666, 576, 73, 74, + 68, 218, 219, 461, 59, 463, 573, 34, 60, 576, + 576, 573, 59, 523, 576, 576, 60, 44, 73, 74, + 67, 48, 60, 36, 666, 128, 53, 54, 55, 56, + 75, 68, 75, 136, 60, 3, 60, 626, 60, 142, + 8, 144, 60, 68, 3, 148, 62, 626, 60, 17, + 60, 72, 75, 62, 22, 23, 24, 59, 66, 626, + 60, 29, 60, 573, 626, 60, 576, 646, 62, 60, + 173, 60, 8, 60, 59, 59, 59, 159, 160, 646, + 646, 17, 68, 62, 646, 646, 22, 23, 24, 62, + 72, 59, 68, 29, 552, 49, 62, 59, 201, 60, + 36, 68, 560, 71, 207, 73, 74, 60, 68, 60, + 213, 14, 62, 60, 72, 60, 60, 53, 221, 336, + 60, 224, 68, 4, 5, 31, 343, 22, 647, 65, + 586, 512, 235, 528, 351, 71, 646, 528, 74, 245, + 283, 39, 214, 245, 395, 603, 604, 387, 251, 252, + 22, 375, 33, 34, 160, 36, 37, 38, 39, 40, + 499, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 8, 336, 466, 607, + 283, 49, 444, 603, 65, 17, 336, 462, -1, -1, + 22, 23, 24, 61, 75, -1, 64, 29, 213, -1, + -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, + 3, -1, -1, -1, -1, 8, -1, -1, 11, -1, + 323, 53, -1, -1, 17, -1, 443, 59, -1, 22, + 23, 24, 449, 450, -1, 452, 29, -1, -1, 71, + -1, 344, 74, 36, 461, -1, 463, -1, -1, -1, + -1, -1, 355, -1, -1, -1, 49, 50, -1, 52, + 53, -1, -1, 56, -1, -1, 59, -1, -1, -1, + -1, -1, 375, -1, 377, -1, 69, 70, 71, 382, + 73, 74, 385, -1, 387, -1, -1, -1, -1, -1, + -1, -1, 395, -1, -1, -1, 399, -1, -1, 402, + -1, 404, -1, -1, -1, -1, -1, -1, 176, 177, + 178, 179, -1, 181, 182, 183, 419, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, -1, 200, -1, 202, 213, 204, -1, -1, -1, - 208, 209, 210, -1, -1, -1, -1, 322, -1, -1, - 114, 115, 116, -1, -1, -1, -1, -1, 441, -1, - -1, -1, -1, -1, 447, 448, -1, 450, 343, -1, - -1, 8, -1, 137, -1, 8, 459, -1, 461, 354, - 17, 145, -1, -1, 17, 22, 23, 24, 152, 22, - 23, 24, 29, -1, -1, -1, 29, -1, 373, 36, - 375, -1, -1, 36, -1, 380, -1, -1, 383, -1, - 385, 175, -1, 281, -1, -1, 53, -1, 393, -1, - 53, -1, 397, 291, -1, 400, 59, 402, 65, -1, - -1, -1, -1, -1, 71, -1, -1, 74, 71, -1, - 73, 74, 417, -1, -1, -1, 314, -1, -1, -1, - 318, -1, -1, -1, -1, -1, 324, -1, -1, -1, - -1, -1, 226, 438, 439, -1, -1, 550, -1, -1, - -1, 446, 447, -1, 449, 558, -1, -1, 242, 454, - -1, -1, 565, -1, -1, 460, -1, -1, 463, 464, - -1, -1, -1, -1, -1, -1, -1, -1, 473, 367, - 368, -1, -1, 478, -1, -1, -1, -1, 272, -1, - -1, 34, -1, -1, -1, 598, -1, -1, 601, 602, - 284, 44, -1, 287, 288, 48, 49, 50, 51, 52, - 53, 54, 55, 56, -1, -1, -1, -1, 406, -1, - -1, -1, -1, 4, 5, -1, -1, -1, -1, -1, - -1, -1, 420, -1, -1, -1, -1, -1, -1, -1, - 428, -1, -1, -1, -1, 433, -1, -1, -1, 652, - -1, 654, 33, 34, -1, 36, 37, 38, 39, 40, - -1, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 571, 361, -1, -1, - -1, -1, 577, -1, 65, -1, 474, 475, -1, 584, - -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, - -1, -1, -1, 387, 599, -1, 601, -1, -1, 497, - 605, 606, -1, -1, -1, 610, 611, -1, -1, -1, - -1, -1, -1, 407, 408, -1, -1, -1, -1, 517, - -1, -1, -1, -1, -1, -1, 524, 525, 526, 0, + 198, -1, 200, -1, 202, 552, 204, 440, 441, -1, + 208, 209, 210, 560, -1, 448, 449, -1, 451, -1, + 567, -1, -1, 456, -1, 3, -1, -1, -1, 462, + 8, -1, 465, 466, -1, -1, -1, -1, 236, 17, + -1, -1, 475, -1, 22, 23, 24, 480, 26, -1, + -1, 29, -1, 600, -1, -1, 603, 604, 36, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 49, 50, -1, 52, 53, -1, -1, 56, -1, + -1, 59, -1, -1, 282, -1, -1, -1, -1, -1, + -1, 69, 70, 71, 292, 73, 74, 8, -1, -1, + -1, -1, -1, -1, -1, -1, 17, 654, -1, 656, + -1, 22, 23, 24, -1, -1, -1, 315, 29, -1, + -1, 319, 8, -1, -1, 36, -1, 325, -1, -1, + -1, 17, -1, -1, -1, -1, 22, 23, 24, -1, + 573, -1, 53, 29, -1, -1, 579, -1, 59, -1, + 36, -1, -1, 586, 65, -1, -1, -1, -1, -1, + 71, -1, 73, 74, 75, -1, -1, 53, 601, -1, + 603, 369, 370, 59, 607, 608, -1, -1, -1, 612, + 613, -1, -1, -1, -1, 71, -1, 73, 74, 0, 1, -1, 3, -1, -1, 6, -1, 8, 9, 10, -1, -1, 13, -1, 15, 16, 17, 18, 19, 20, - -1, 22, 23, 24, -1, -1, 27, 28, 29, 30, - 31, 32, -1, -1, -1, 36, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 49, 50, + 408, 22, 23, 24, -1, -1, 27, 28, 29, 30, + 31, 32, -1, -1, 422, 36, -1, -1, -1, -1, + -1, -1, 430, -1, -1, -1, -1, 435, 49, 50, -1, 52, 53, -1, -1, 56, -1, -1, 59, -1, - -1, 62, -1, -1, -1, -1, 594, -1, 69, 70, - 71, -1, 73, 74, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 621, 622, -1, 624, 521, -1, -1, - -1, 1, -1, 3, -1, 633, 6, 7, 8, 9, - 10, -1, 12, 13, -1, 15, 16, 17, 18, 19, - 20, -1, 22, 23, 24, -1, -1, 27, 28, 29, - 30, 31, 32, -1, -1, -1, 36, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, - 50, -1, 52, 53, -1, -1, 56, -1, -1, 59, - -1, -1, 62, -1, -1, -1, -1, 67, 68, 69, - 70, 71, -1, 73, 74, 1, -1, 3, -1, -1, - 6, -1, 8, 9, 10, -1, -1, 13, -1, 15, - 16, 17, 18, 19, 20, -1, 22, 23, 24, -1, - -1, 27, 28, 29, 30, 31, 32, -1, -1, -1, - 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 49, 50, -1, 52, 53, -1, -1, - 56, -1, 3, 59, -1, -1, 62, 8, -1, -1, - 11, 67, 68, 69, 70, 71, 17, 73, 74, -1, - -1, 22, 23, 24, -1, -1, -1, -1, 29, -1, - -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3, -1, -1, 49, 50, - 8, 52, 53, -1, -1, 56, -1, -1, 59, 17, - -1, -1, -1, -1, 22, 23, 24, -1, 69, 70, - 71, 29, 73, 74, -1, -1, -1, -1, 36, -1, + -1, 62, -1, -1, 34, -1, -1, -1, 69, 70, + 71, -1, 73, 74, 44, -1, -1, -1, 48, 49, + 50, 51, 52, 53, 54, 55, 56, -1, 476, 477, + -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, + 3, -1, -1, 6, 7, 8, 9, 10, -1, 12, + 13, 499, 15, 16, 17, 18, 19, 20, -1, 22, + 23, 24, -1, -1, 27, 28, 29, 30, 31, 32, + -1, 519, -1, 36, -1, -1, -1, -1, 526, 527, + 528, -1, -1, -1, -1, -1, 49, 50, -1, 52, + 53, -1, -1, 56, -1, -1, 59, -1, -1, 62, + -1, -1, -1, -1, 67, 68, 69, 70, 71, -1, + 73, 74, -1, -1, -1, -1, 1, -1, 3, -1, + -1, 6, -1, 8, 9, 10, -1, -1, 13, -1, + 15, 16, 17, 18, 19, 20, -1, 22, 23, 24, + -1, -1, 27, 28, 29, 30, 31, 32, 596, -1, + -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 49, 50, -1, 52, 53, -1, + -1, 56, -1, -1, 59, 623, 624, 62, 626, -1, + -1, -1, 67, 68, 69, 70, 71, 635, 73, 74, + 3, -1, -1, -1, -1, 8, -1, -1, -1, -1, + -1, -1, -1, -1, 17, -1, 8, -1, -1, 22, + 23, 24, -1, -1, -1, 17, 29, -1, -1, -1, + 22, 23, 24, 36, -1, -1, -1, 29, -1, -1, + -1, -1, -1, -1, 36, -1, 49, 50, -1, 52, + 53, -1, -1, 56, -1, 3, 59, 60, -1, -1, + 8, 53, -1, -1, -1, -1, 69, 70, 71, 17, + 73, 74, -1, -1, 22, 23, 24, -1, -1, 71, + -1, 29, 74, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, 50, -1, 52, 53, -1, -1, 56, -1, - 3, 59, 60, -1, -1, 8, -1, -1, -1, -1, + 3, 59, -1, -1, -1, 8, -1, -1, -1, 67, -1, 69, 70, 71, 17, 73, 74, -1, -1, 22, - 23, 24, -1, -1, -1, -1, 29, -1, -1, -1, + 23, 24, -1, -1, -1, -1, 29, -1, 31, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, 50, -1, 52, 53, -1, -1, 56, -1, 3, 59, -1, -1, -1, - 8, -1, -1, -1, 67, -1, 69, 70, 71, 17, - 73, 74, -1, -1, 22, 23, 24, -1, -1, -1, - -1, 29, -1, 31, -1, -1, -1, -1, 36, -1, + 8, -1, -1, -1, -1, -1, 69, 70, 71, 17, + 73, 74, -1, -1, 22, 23, 24, -1, 26, -1, + -1, 29, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, 50, -1, 52, 53, -1, -1, 56, -1, 3, 59, -1, -1, -1, 8, -1, -1, -1, -1, -1, 69, 70, 71, 17, 73, 74, -1, -1, 22, 23, 24, -1, 26, -1, -1, 29, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 49, 50, -1, 52, - 53, -1, -1, 56, -1, 3, 59, -1, -1, -1, - 8, -1, -1, -1, -1, -1, 69, 70, 71, 17, - 73, 74, -1, -1, 22, 23, 24, -1, 26, -1, - -1, 29, -1, -1, -1, -1, -1, -1, 36, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, - -1, 49, 50, 8, 52, 53, -1, -1, 56, -1, - -1, 59, 17, -1, -1, -1, -1, 22, 23, 24, - -1, 69, 70, 71, 29, 73, 74, -1, -1, -1, + -1, -1, -1, 3, -1, -1, 49, 50, 8, 52, + 53, -1, -1, 56, -1, -1, 59, 17, -1, -1, + -1, -1, 22, 23, 24, -1, 69, 70, 71, 29, + 73, 74, -1, -1, -1, -1, 36, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, + 50, -1, 52, 53, -1, -1, 56, -1, 3, 59, + -1, -1, -1, 8, -1, -1, -1, 67, -1, 69, + 70, 71, 17, 73, 74, -1, -1, 22, 23, 24, + -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 49, 50, -1, 52, 53, -1, - -1, 56, -1, 3, 59, -1, -1, -1, 8, -1, - -1, -1, 67, -1, 69, 70, 71, 17, 73, 74, - -1, -1, 22, 23, 24, -1, -1, -1, -1, 29, - -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, -1, -1, 49, - 50, 8, 52, 53, -1, -1, 56, -1, -1, 59, - 17, -1, -1, -1, -1, 22, 23, 24, -1, 69, - 70, 71, 29, 73, 74, -1, -1, -1, -1, 36, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, - -1, -1, 49, 50, 8, 52, 53, -1, -1, 56, - -1, -1, 59, 17, -1, -1, -1, -1, 22, 23, - 24, -1, 69, 70, 71, 29, 73, 74, -1, -1, - -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 49, 50, 8, 52, 53, - -1, -1, 56, -1, -1, 59, 17, -1, -1, -1, - -1, 22, 23, 24, -1, 69, 70, 71, 29, 73, - 74, -1, -1, 8, -1, 36, 11, -1, -1, -1, - -1, 8, 17, -1, -1, -1, -1, 22, 23, 24, - 17, -1, 53, -1, 29, 22, 23, 24, 59, -1, - -1, 36, 29, -1, -1, -1, 8, -1, -1, 36, - 71, -1, 73, 74, 75, 17, -1, -1, 53, -1, - 22, 23, 24, -1, 59, -1, 53, 29, -1, -1, - -1, -1, 59, -1, 36, -1, 71, -1, 73, 74, - 8, -1, -1, -1, 71, -1, 73, 74, -1, 17, - -1, 53, -1, -1, 22, 23, 24, 59, -1, -1, - -1, 29, -1, -1, -1, 8, -1, -1, 36, 71, - -1, 73, 74, 8, 17, -1, -1, -1, -1, 22, - 23, 24, 17, -1, -1, 53, 29, 22, 23, 24, - -1, 59, -1, 36, 29, -1, -1, -1, -1, 8, - -1, 36, 11, 71, -1, 73, 74, -1, 17, -1, - 53, -1, -1, 22, 23, 24, 59, -1, 53, -1, - 29, -1, -1, -1, 59, -1, 8, 36, 71, -1, - 73, 74, -1, -1, -1, 17, 71, -1, -1, 74, - 22, 23, 24, -1, 53, -1, -1, 29, -1, -1, - -1, -1, 8, -1, 36, -1, -1, -1, -1, -1, - 8, 17, 71, -1, -1, 74, 22, 23, 24, 17, - -1, 53, -1, 29, 22, 23, 24, -1, -1, -1, - 36, 29, -1, -1, -1, -1, -1, -1, 36, 71, - -1, 73, 74, -1, -1, -1, -1, 53, -1, -1, - -1, -1, -1, 59, -1, 53, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 71, -1, -1, 74, -1, - -1, -1, -1, 71, 33, 34, 74, 36, -1, 38, + -1, 3, -1, -1, 49, 50, 8, 52, 53, -1, + -1, 56, -1, -1, 59, 17, -1, -1, -1, -1, + 22, 23, 24, -1, 69, 70, 71, 29, 73, 74, + -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 3, -1, -1, 49, 50, 8, + 52, 53, -1, -1, 56, -1, -1, 59, 17, -1, + -1, -1, -1, 22, 23, 24, -1, 69, 70, 71, + 29, 73, 74, -1, -1, -1, -1, 36, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 8, 52, 53, -1, -1, 56, -1, -1, + 59, 17, -1, -1, -1, -1, 22, 23, 24, -1, + 69, 70, 71, 29, 73, 74, -1, 8, -1, -1, + 36, -1, -1, -1, -1, 8, 17, -1, 11, -1, + -1, 22, 23, 24, 17, -1, -1, 53, 29, 22, + 23, 24, -1, 59, -1, 36, 29, -1, -1, 65, + -1, 8, -1, 36, -1, 71, -1, 73, 74, 75, + 17, -1, 53, -1, -1, 22, 23, 24, 59, -1, + 53, -1, 29, -1, -1, -1, 59, -1, 8, 36, + 71, -1, 73, 74, 75, -1, -1, 17, 71, -1, + 73, 74, 22, 23, 24, -1, 53, -1, -1, 29, + -1, -1, 59, -1, 8, -1, 36, -1, -1, -1, + -1, -1, 8, 17, 71, -1, 73, 74, 22, 23, + 24, 17, -1, 53, -1, 29, 22, 23, 24, 59, + -1, -1, 36, 29, -1, -1, -1, 8, -1, -1, + 36, 71, -1, 73, 74, 8, 17, -1, 11, 53, + -1, 22, 23, 24, 17, 59, -1, 53, 29, 22, + 23, 24, -1, 59, -1, 36, 29, 71, -1, 73, + 74, 8, -1, 36, -1, 71, -1, 73, 74, -1, + 17, -1, 53, -1, -1, 22, 23, 24, -1, -1, + 53, -1, 29, -1, -1, -1, -1, -1, -1, 36, + 71, -1, 73, 74, -1, -1, -1, -1, 71, 34, + -1, 74, -1, 38, 39, 40, 53, -1, 43, 44, + 45, 46, 59, 48, 49, 50, 51, 52, 53, 54, + 55, 56, -1, -1, 71, 33, 34, 74, 36, -1, + 38, 39, 40, -1, -1, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, + -1, 36, -1, 38, 39, 40, -1, 75, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, -1, -1, -1, -1, -1, -1, 33, 34, + -1, 36, -1, 38, 39, 40, -1, 72, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 33, 34, -1, 36, -1, 38, 39, 40, + -1, 66, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 33, 34, -1, 36, + -1, 38, 39, 40, -1, 66, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 33, 34, -1, 36, -1, 38, 39, 40, -1, 66, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 33, 34, -1, -1, -1, 38, 39, 40, -1, -1, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 33, 34, -1, - 36, -1, 38, 39, 40, -1, 75, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, -1, -1, -1, -1, -1, -1, 33, 34, -1, - 36, -1, 38, 39, 40, -1, 72, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 33, 34, -1, 36, -1, 38, 39, 40, -1, - 66, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 33, 34, -1, 36, -1, - 38, 39, 40, -1, 66, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 33, - 34, -1, 36, -1, 38, 39, 40, -1, 66, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 33, 34, -1, -1, -1, 38, 39, - 40, -1, -1, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 33, 34, -1, - -1, -1, 38, 39, 40, -1, -1, 43, 44, 45, - 46, -1, 48, 49, 50, 51, 52, 53, 54, 55, - 56 + 49, 50, 51, 52, 53, 54, 55, 56, 33, 34, + -1, -1, -1, 38, 39, 40, -1, -1, 43, 44, + 45, 46, -1, 48, 49, 50, 51, 52, 53, 54, + 55, 56 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1528,50 +1514,50 @@ static const yytype_uint8 yystos[] = 59, 63, 71, 66, 59, 137, 1, 137, 5, 65, 75, 142, 200, 59, 160, 200, 24, 200, 201, 200, 64, 62, 190, 88, 59, 36, 59, 146, 152, 153, - 154, 155, 161, 146, 146, 63, 98, 107, 108, 109, - 186, 194, 11, 136, 141, 145, 146, 177, 178, 179, - 59, 67, 162, 112, 194, 24, 59, 68, 138, 171, - 173, 175, 146, 35, 53, 59, 68, 138, 170, 172, - 173, 174, 184, 112, 60, 97, 169, 146, 60, 93, - 167, 65, 75, 146, 8, 147, 60, 72, 72, 60, - 94, 65, 146, 126, 126, 126, 126, 126, 126, 126, + 154, 155, 161, 146, 146, 63, 26, 98, 107, 108, + 109, 186, 194, 11, 136, 141, 145, 146, 177, 178, + 179, 59, 67, 162, 112, 194, 24, 59, 68, 138, + 171, 173, 175, 146, 35, 53, 59, 68, 138, 170, + 172, 173, 174, 184, 112, 60, 97, 169, 146, 60, + 93, 167, 65, 75, 146, 8, 147, 60, 72, 72, + 60, 94, 65, 146, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 130, 60, 135, 187, 59, 141, - 126, 192, 182, 126, 130, 1, 67, 91, 100, 180, - 181, 183, 186, 186, 126, 8, 17, 22, 23, 24, - 29, 36, 53, 65, 71, 142, 202, 204, 205, 206, - 141, 207, 215, 162, 59, 3, 202, 202, 83, 60, - 179, 8, 146, 60, 141, 35, 105, 5, 65, 62, - 146, 136, 145, 75, 191, 60, 179, 183, 115, 62, - 63, 24, 173, 59, 176, 62, 190, 72, 104, 59, - 174, 53, 174, 62, 190, 3, 198, 75, 146, 123, - 62, 190, 62, 190, 186, 139, 65, 36, 59, 146, - 152, 153, 154, 161, 67, 146, 146, 62, 190, 186, - 65, 67, 126, 131, 132, 188, 189, 11, 75, 191, - 31, 135, 72, 66, 180, 75, 191, 189, 101, 62, - 68, 36, 59, 203, 204, 206, 59, 67, 71, 67, - 8, 202, 3, 50, 59, 141, 212, 213, 3, 72, - 65, 11, 202, 60, 75, 62, 195, 215, 62, 62, - 62, 60, 60, 106, 26, 26, 194, 177, 59, 141, - 151, 152, 153, 154, 155, 161, 163, 60, 68, 105, - 194, 141, 60, 179, 175, 68, 146, 7, 12, 68, - 99, 102, 174, 198, 174, 60, 172, 68, 138, 198, - 35, 97, 60, 93, 60, 186, 146, 130, 94, 95, - 168, 185, 60, 186, 130, 66, 75, 191, 68, 191, - 135, 60, 60, 60, 192, 60, 68, 183, 180, 202, - 205, 195, 24, 141, 142, 197, 202, 209, 217, 202, - 141, 196, 208, 216, 202, 3, 212, 62, 72, 202, - 213, 202, 198, 141, 207, 60, 183, 126, 126, 62, - 179, 59, 163, 116, 60, 187, 66, 103, 60, 60, - 198, 104, 60, 189, 62, 190, 146, 189, 67, 126, - 133, 131, 132, 60, 66, 72, 68, 60, 60, 59, - 68, 62, 72, 202, 68, 62, 49, 202, 62, 198, - 59, 59, 202, 210, 211, 68, 194, 60, 179, 119, - 163, 5, 65, 66, 75, 183, 198, 198, 68, 68, - 95, 60, 68, 130, 192, 210, 195, 209, 202, 198, - 208, 212, 195, 195, 60, 14, 117, 120, 126, 126, - 189, 72, 60, 60, 60, 60, 163, 20, 100, 66, - 66, 68, 210, 210, 118, 112, 105 + 126, 126, 126, 126, 126, 130, 60, 135, 187, 59, + 141, 126, 192, 182, 126, 130, 1, 67, 91, 100, + 180, 181, 183, 186, 186, 126, 8, 17, 22, 23, + 24, 29, 36, 53, 65, 71, 142, 202, 204, 205, + 206, 141, 207, 215, 162, 59, 3, 202, 202, 83, + 60, 179, 8, 146, 60, 141, 126, 35, 105, 5, + 65, 62, 146, 136, 145, 75, 191, 60, 179, 183, + 115, 62, 63, 24, 173, 59, 176, 62, 190, 72, + 104, 59, 174, 53, 174, 62, 190, 3, 198, 75, + 146, 123, 62, 190, 62, 190, 186, 139, 65, 36, + 59, 146, 152, 153, 154, 161, 67, 146, 146, 62, + 190, 186, 65, 67, 126, 131, 132, 188, 189, 11, + 75, 191, 31, 135, 72, 66, 180, 75, 191, 189, + 101, 62, 68, 36, 59, 203, 204, 206, 59, 67, + 71, 67, 8, 202, 3, 50, 59, 141, 212, 213, + 3, 72, 65, 11, 202, 60, 75, 62, 195, 215, + 62, 62, 62, 60, 60, 106, 26, 26, 194, 177, + 59, 141, 151, 152, 153, 154, 155, 161, 163, 60, + 68, 105, 194, 141, 60, 179, 175, 68, 146, 7, + 12, 68, 99, 102, 174, 198, 174, 60, 172, 68, + 138, 198, 35, 97, 60, 93, 60, 186, 146, 130, + 94, 95, 168, 185, 60, 186, 130, 66, 75, 191, + 68, 191, 135, 60, 60, 60, 192, 60, 68, 183, + 180, 202, 205, 195, 24, 141, 142, 197, 202, 209, + 217, 202, 141, 196, 208, 216, 202, 3, 212, 62, + 72, 202, 213, 202, 198, 141, 207, 60, 183, 126, + 126, 62, 179, 59, 163, 116, 60, 187, 66, 103, + 60, 60, 198, 104, 60, 189, 62, 190, 146, 189, + 67, 126, 133, 131, 132, 60, 66, 72, 68, 60, + 60, 59, 68, 62, 72, 202, 68, 62, 49, 202, + 62, 198, 59, 59, 202, 210, 211, 68, 194, 60, + 179, 119, 163, 5, 65, 66, 75, 183, 198, 198, + 68, 68, 95, 60, 68, 130, 192, 210, 195, 209, + 202, 198, 208, 212, 195, 195, 60, 14, 117, 120, + 126, 126, 189, 72, 60, 60, 60, 60, 163, 20, + 100, 66, 66, 68, 210, 210, 118, 112, 105 }; #define yyerrok (yyerrstatus = 0) @@ -2795,20 +2781,22 @@ yyreduce: #line 461 "go.y" { (yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1)); + (yyval.node)->implicit = 1; (yyval.node)->etype = OADD; } break; case 55: -#line 466 "go.y" +#line 467 "go.y" { (yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1)); + (yyval.node)->implicit = 1; (yyval.node)->etype = OSUB; } break; case 56: -#line 473 "go.y" +#line 475 "go.y" { Node *n, *nn; @@ -2831,7 +2819,7 @@ yyreduce: break; case 57: -#line 493 "go.y" +#line 495 "go.y" { Node *n; @@ -2852,7 +2840,7 @@ yyreduce: break; case 58: -#line 511 "go.y" +#line 513 "go.y" { // will be converted to OCASE // right will point to next case @@ -2864,7 +2852,7 @@ yyreduce: break; case 59: -#line 520 "go.y" +#line 522 "go.y" { Node *n, *nn; @@ -2883,14 +2871,14 @@ yyreduce: break; case 60: -#line 538 "go.y" +#line 540 "go.y" { markdcl(); } break; case 61: -#line 542 "go.y" +#line 544 "go.y" { if((yyvsp[(3) - (4)].list) == nil) (yyval.node) = nod(OEMPTY, N, N); @@ -2901,7 +2889,7 @@ yyreduce: break; case 62: -#line 552 "go.y" +#line 554 "go.y" { // If the last token read by the lexer was consumed // as part of the case, clear it (parser has cleared yychar). @@ -2915,7 +2903,7 @@ yyreduce: break; case 63: -#line 563 "go.y" +#line 565 "go.y" { int last; @@ -2937,28 +2925,28 @@ yyreduce: break; case 64: -#line 583 "go.y" +#line 585 "go.y" { (yyval.list) = nil; } break; case 65: -#line 587 "go.y" +#line 589 "go.y" { (yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); } break; case 66: -#line 593 "go.y" +#line 595 "go.y" { markdcl(); } break; case 67: -#line 597 "go.y" +#line 599 "go.y" { (yyval.list) = (yyvsp[(3) - (4)].list); popdcl(); @@ -2966,7 +2954,7 @@ yyreduce: break; case 68: -#line 604 "go.y" +#line 606 "go.y" { (yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node)); (yyval.node)->list = (yyvsp[(1) - (4)].list); @@ -2975,7 +2963,7 @@ yyreduce: break; case 69: -#line 610 "go.y" +#line 612 "go.y" { (yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node)); (yyval.node)->list = (yyvsp[(1) - (4)].list); @@ -2986,6 +2974,14 @@ yyreduce: case 70: #line 619 "go.y" + { + (yyval.node) = nod(ORANGE, N, (yyvsp[(2) - (2)].node)); + (yyval.node)->etype = 0; // := flag + } + break; + + case 71: +#line 626 "go.y" { // init ; test ; incr if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0) @@ -2998,8 +2994,8 @@ yyreduce: } break; - case 71: -#line 630 "go.y" + case 72: +#line 637 "go.y" { // normal test (yyval.node) = nod(OFOR, N, N); @@ -3007,31 +3003,31 @@ yyreduce: } break; - case 73: -#line 639 "go.y" + case 74: +#line 646 "go.y" { (yyval.node) = (yyvsp[(1) - (2)].node); (yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list)); } break; - case 74: -#line 646 "go.y" + case 75: +#line 653 "go.y" { markdcl(); } break; - case 75: -#line 650 "go.y" + case 76: +#line 657 "go.y" { (yyval.node) = (yyvsp[(3) - (3)].node); popdcl(); } break; - case 76: -#line 657 "go.y" + case 77: +#line 664 "go.y" { // test (yyval.node) = nod(OIF, N, N); @@ -3039,8 +3035,8 @@ yyreduce: } break; - case 77: -#line 663 "go.y" + case 78: +#line 670 "go.y" { // init ; test (yyval.node) = nod(OIF, N, N); @@ -3050,30 +3046,30 @@ yyreduce: } break; - case 78: -#line 674 "go.y" + case 79: +#line 681 "go.y" { markdcl(); } break; - case 79: -#line 678 "go.y" + case 80: +#line 685 "go.y" { if((yyvsp[(3) - (3)].node)->ntest == N) yyerror("missing condition in if statement"); } break; - case 80: -#line 683 "go.y" + case 81: +#line 690 "go.y" { (yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list); } break; - case 81: -#line 687 "go.y" + case 82: +#line 694 "go.y" { Node *n; NodeList *nn; @@ -3090,15 +3086,15 @@ yyreduce: } break; - case 82: -#line 704 "go.y" + case 83: +#line 711 "go.y" { markdcl(); } break; - case 83: -#line 708 "go.y" + case 84: +#line 715 "go.y" { if((yyvsp[(4) - (5)].node)->ntest == N) yyerror("missing condition in if statement"); @@ -3107,29 +3103,29 @@ yyreduce: } break; - case 84: -#line 716 "go.y" + case 85: +#line 723 "go.y" { (yyval.list) = nil; } break; - case 85: -#line 720 "go.y" + case 86: +#line 727 "go.y" { (yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list)); } break; - case 86: -#line 725 "go.y" + case 87: +#line 732 "go.y" { (yyval.list) = nil; } break; - case 87: -#line 729 "go.y" + case 88: +#line 736 "go.y" { NodeList *node; @@ -3140,15 +3136,15 @@ yyreduce: } break; - case 88: -#line 740 "go.y" + case 89: +#line 747 "go.y" { markdcl(); } break; - case 89: -#line 744 "go.y" + case 90: +#line 751 "go.y" { Node *n; n = (yyvsp[(3) - (3)].node)->ntest; @@ -3158,8 +3154,8 @@ yyreduce: } break; - case 90: -#line 752 "go.y" + case 91: +#line 759 "go.y" { (yyval.node) = (yyvsp[(3) - (7)].node); (yyval.node)->op = OSWITCH; @@ -3169,15 +3165,15 @@ yyreduce: } break; - case 91: -#line 762 "go.y" + case 92: +#line 769 "go.y" { typesw = nod(OXXX, typesw, N); } break; - case 92: -#line 766 "go.y" + case 93: +#line 773 "go.y" { (yyval.node) = nod(OSELECT, N, N); (yyval.node)->lineno = typesw->lineno; @@ -3186,155 +3182,155 @@ yyreduce: } break; - case 94: -#line 779 "go.y" + case 95: +#line 786 "go.y" { (yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 95: -#line 783 "go.y" + case 96: +#line 790 "go.y" { (yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 96: -#line 787 "go.y" + case 97: +#line 794 "go.y" { (yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 97: -#line 791 "go.y" + case 98: +#line 798 "go.y" { (yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 98: -#line 795 "go.y" + case 99: +#line 802 "go.y" { (yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 99: -#line 799 "go.y" + case 100: +#line 806 "go.y" { (yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 100: -#line 803 "go.y" + case 101: +#line 810 "go.y" { (yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 101: -#line 807 "go.y" + case 102: +#line 814 "go.y" { (yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 102: -#line 811 "go.y" + case 103: +#line 818 "go.y" { (yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 103: -#line 815 "go.y" + case 104: +#line 822 "go.y" { (yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 104: -#line 819 "go.y" + case 105: +#line 826 "go.y" { (yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 105: -#line 823 "go.y" + case 106: +#line 830 "go.y" { (yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 106: -#line 827 "go.y" + case 107: +#line 834 "go.y" { (yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 107: -#line 831 "go.y" + case 108: +#line 838 "go.y" { (yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 108: -#line 835 "go.y" + case 109: +#line 842 "go.y" { (yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 109: -#line 839 "go.y" + case 110: +#line 846 "go.y" { (yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 110: -#line 843 "go.y" + case 111: +#line 850 "go.y" { (yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 111: -#line 847 "go.y" + case 112: +#line 854 "go.y" { (yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 112: -#line 851 "go.y" + case 113: +#line 858 "go.y" { (yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 113: -#line 856 "go.y" + case 114: +#line 863 "go.y" { (yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 115: -#line 863 "go.y" + case 116: +#line 870 "go.y" { (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N); } break; - case 116: -#line 867 "go.y" + case 117: +#line 874 "go.y" { if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) { // Special case for &T{...}: turn into (*T){...}. @@ -3347,66 +3343,66 @@ yyreduce: } break; - case 117: -#line 878 "go.y" + case 118: +#line 885 "go.y" { (yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N); } break; - case 118: -#line 882 "go.y" + case 119: +#line 889 "go.y" { (yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N); } break; - case 119: -#line 886 "go.y" + case 120: +#line 893 "go.y" { (yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N); } break; - case 120: -#line 890 "go.y" + case 121: +#line 897 "go.y" { yyerror("the bitwise complement operator is ^"); (yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N); } break; - case 121: -#line 895 "go.y" + case 122: +#line 902 "go.y" { (yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N); } break; - case 122: -#line 899 "go.y" + case 123: +#line 906 "go.y" { (yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N); } break; - case 123: -#line 909 "go.y" + case 124: +#line 916 "go.y" { (yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N); } break; - case 124: -#line 913 "go.y" + case 125: +#line 920 "go.y" { (yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N); (yyval.node)->list = (yyvsp[(3) - (5)].list); } break; - case 125: -#line 918 "go.y" + case 126: +#line 925 "go.y" { (yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N); (yyval.node)->list = (yyvsp[(3) - (6)].list); @@ -3414,15 +3410,15 @@ yyreduce: } break; - case 126: -#line 926 "go.y" + case 127: +#line 933 "go.y" { (yyval.node) = nodlit((yyvsp[(1) - (1)].val)); } break; - case 128: -#line 931 "go.y" + case 129: +#line 938 "go.y" { if((yyvsp[(1) - (3)].node)->op == OPACK) { Sym *s; @@ -3435,36 +3431,36 @@ yyreduce: } break; - case 129: -#line 942 "go.y" + case 130: +#line 949 "go.y" { (yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node)); } break; - case 130: -#line 946 "go.y" + case 131: +#line 953 "go.y" { (yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node)); } break; - case 131: -#line 950 "go.y" + case 132: +#line 957 "go.y" { (yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)); } break; - case 132: -#line 954 "go.y" + case 133: +#line 961 "go.y" { (yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node))); } break; - case 133: -#line 958 "go.y" + case 134: +#line 965 "go.y" { if((yyvsp[(5) - (8)].node) == N) yyerror("middle index required in 3-index slice"); @@ -3474,8 +3470,8 @@ yyreduce: } break; - case 135: -#line 967 "go.y" + case 136: +#line 974 "go.y" { // conversion (yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N); @@ -3483,8 +3479,8 @@ yyreduce: } break; - case 136: -#line 973 "go.y" + case 137: +#line 980 "go.y" { (yyval.node) = (yyvsp[(3) - (5)].node); (yyval.node)->right = (yyvsp[(1) - (5)].node); @@ -3493,8 +3489,8 @@ yyreduce: } break; - case 137: -#line 980 "go.y" + case 138: +#line 987 "go.y" { (yyval.node) = (yyvsp[(3) - (5)].node); (yyval.node)->right = (yyvsp[(1) - (5)].node); @@ -3502,8 +3498,8 @@ yyreduce: } break; - case 138: -#line 986 "go.y" + case 139: +#line 993 "go.y" { yyerror("cannot parenthesize type in composite literal"); (yyval.node) = (yyvsp[(5) - (7)].node); @@ -3512,8 +3508,8 @@ yyreduce: } break; - case 140: -#line 995 "go.y" + case 141: +#line 1002 "go.y" { // composite expression. // make node early so we get the right line number. @@ -3521,15 +3517,15 @@ yyreduce: } break; - case 141: -#line 1003 "go.y" + case 142: +#line 1010 "go.y" { (yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; - case 142: -#line 1009 "go.y" + case 143: +#line 1016 "go.y" { // These nodes do not carry line numbers. // Since a composite literal commonly spans several lines, @@ -3548,24 +3544,24 @@ yyreduce: } break; - case 143: -#line 1026 "go.y" + case 144: +#line 1033 "go.y" { (yyval.node) = (yyvsp[(2) - (4)].node); (yyval.node)->list = (yyvsp[(3) - (4)].list); } break; - case 145: -#line 1034 "go.y" + case 146: +#line 1041 "go.y" { (yyval.node) = (yyvsp[(2) - (4)].node); (yyval.node)->list = (yyvsp[(3) - (4)].list); } break; - case 147: -#line 1042 "go.y" + case 148: +#line 1049 "go.y" { (yyval.node) = (yyvsp[(2) - (3)].node); @@ -3584,22 +3580,22 @@ yyreduce: } break; - case 151: -#line 1068 "go.y" + case 152: +#line 1075 "go.y" { (yyval.i) = LBODY; } break; - case 152: -#line 1072 "go.y" + case 153: +#line 1079 "go.y" { (yyval.i) = '{'; } break; - case 153: -#line 1083 "go.y" + case 154: +#line 1090 "go.y" { if((yyvsp[(1) - (1)].sym) == S) (yyval.node) = N; @@ -3608,22 +3604,22 @@ yyreduce: } break; - case 154: -#line 1092 "go.y" + case 155: +#line 1099 "go.y" { (yyval.node) = dclname((yyvsp[(1) - (1)].sym)); } break; - case 155: -#line 1097 "go.y" + case 156: +#line 1104 "go.y" { (yyval.node) = N; } break; - case 157: -#line 1104 "go.y" + case 158: +#line 1111 "go.y" { (yyval.sym) = (yyvsp[(1) - (1)].sym); // during imports, unqualified non-exported identifiers are from builtinpkg @@ -3632,15 +3628,15 @@ yyreduce: } break; - case 159: -#line 1112 "go.y" + case 160: +#line 1119 "go.y" { (yyval.sym) = S; } break; - case 160: -#line 1118 "go.y" + case 161: +#line 1125 "go.y" { Pkg *p; @@ -3655,8 +3651,8 @@ yyreduce: } break; - case 161: -#line 1131 "go.y" + case 162: +#line 1138 "go.y" { Pkg *p; @@ -3671,8 +3667,8 @@ yyreduce: } break; - case 162: -#line 1146 "go.y" + case 163: +#line 1153 "go.y" { (yyval.node) = oldname((yyvsp[(1) - (1)].sym)); if((yyval.node)->pack != N) @@ -3680,44 +3676,44 @@ yyreduce: } break; - case 164: -#line 1166 "go.y" + case 165: +#line 1173 "go.y" { yyerror("final argument in variadic function missing type"); (yyval.node) = nod(ODDD, typenod(typ(TINTER)), N); } break; - case 165: -#line 1171 "go.y" + case 166: +#line 1178 "go.y" { (yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N); } break; - case 171: -#line 1182 "go.y" + case 172: +#line 1189 "go.y" { - (yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N); + (yyval.node) = (yyvsp[(2) - (3)].node); } break; - case 175: -#line 1191 "go.y" + case 176: +#line 1198 "go.y" { (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N); } break; - case 180: -#line 1201 "go.y" + case 181: +#line 1208 "go.y" { - (yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N); + (yyval.node) = (yyvsp[(2) - (3)].node); } break; - case 190: -#line 1222 "go.y" + case 191: +#line 1229 "go.y" { if((yyvsp[(1) - (3)].node)->op == OPACK) { Sym *s; @@ -3730,61 +3726,61 @@ yyreduce: } break; - case 191: -#line 1235 "go.y" + case 192: +#line 1242 "go.y" { (yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node)); } break; - case 192: -#line 1239 "go.y" + case 193: +#line 1246 "go.y" { // array literal of nelem (yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node)); } break; - case 193: -#line 1244 "go.y" + case 194: +#line 1251 "go.y" { (yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N); (yyval.node)->etype = Cboth; } break; - case 194: -#line 1249 "go.y" + case 195: +#line 1256 "go.y" { (yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N); (yyval.node)->etype = Csend; } break; - case 195: -#line 1254 "go.y" + case 196: +#line 1261 "go.y" { (yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)); } break; - case 198: -#line 1262 "go.y" + case 199: +#line 1269 "go.y" { (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N); } break; - case 199: -#line 1268 "go.y" + case 200: +#line 1275 "go.y" { (yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N); (yyval.node)->etype = Crecv; } break; - case 200: -#line 1275 "go.y" + case 201: +#line 1282 "go.y" { (yyval.node) = nod(OTSTRUCT, N, N); (yyval.node)->list = (yyvsp[(3) - (5)].list); @@ -3792,16 +3788,16 @@ yyreduce: } break; - case 201: -#line 1281 "go.y" + case 202: +#line 1288 "go.y" { (yyval.node) = nod(OTSTRUCT, N, N); fixlbrace((yyvsp[(2) - (3)].i)); } break; - case 202: -#line 1288 "go.y" + case 203: +#line 1295 "go.y" { (yyval.node) = nod(OTINTER, N, N); (yyval.node)->list = (yyvsp[(3) - (5)].list); @@ -3809,16 +3805,16 @@ yyreduce: } break; - case 203: -#line 1294 "go.y" + case 204: +#line 1301 "go.y" { (yyval.node) = nod(OTINTER, N, N); fixlbrace((yyvsp[(2) - (3)].i)); } break; - case 204: -#line 1305 "go.y" + case 205: +#line 1312 "go.y" { (yyval.node) = (yyvsp[(2) - (3)].node); if((yyval.node) == N) @@ -3828,12 +3824,13 @@ yyreduce: (yyval.node)->nbody = (yyvsp[(3) - (3)].list); (yyval.node)->endlineno = lineno; (yyval.node)->noescape = noescape; + (yyval.node)->nosplit = nosplit; funcbody((yyval.node)); } break; - case 205: -#line 1319 "go.y" + case 206: +#line 1327 "go.y" { Node *t; @@ -3864,8 +3861,8 @@ yyreduce: } break; - case 206: -#line 1348 "go.y" + case 207: +#line 1356 "go.y" { Node *rcvr, *t; @@ -3886,8 +3883,6 @@ yyreduce: yyerror("bad receiver in method"); break; } - if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN)) - yyerror("cannot parenthesize receiver type"); t = nod(OTFUNC, rcvr, N); t->list = (yyvsp[(6) - (8)].list); @@ -3905,8 +3900,8 @@ yyreduce: } break; - case 207: -#line 1388 "go.y" + case 208: +#line 1394 "go.y" { Sym *s; Type *t; @@ -3933,8 +3928,8 @@ yyreduce: } break; - case 208: -#line 1413 "go.y" + case 209: +#line 1419 "go.y" { (yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right); (yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list)); @@ -3952,8 +3947,8 @@ yyreduce: } break; - case 209: -#line 1431 "go.y" + case 210: +#line 1437 "go.y" { (yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1); (yyval.node) = nod(OTFUNC, N, N); @@ -3962,15 +3957,15 @@ yyreduce: } break; - case 210: -#line 1439 "go.y" + case 211: +#line 1445 "go.y" { (yyval.list) = nil; } break; - case 211: -#line 1443 "go.y" + case 212: +#line 1449 "go.y" { (yyval.list) = (yyvsp[(2) - (3)].list); if((yyval.list) == nil) @@ -3978,119 +3973,120 @@ yyreduce: } break; - case 212: -#line 1451 "go.y" + case 213: +#line 1457 "go.y" { (yyval.list) = nil; } break; - case 213: -#line 1455 "go.y" + case 214: +#line 1461 "go.y" { (yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node))); } break; - case 214: -#line 1459 "go.y" + case 215: +#line 1465 "go.y" { (yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0); (yyval.list) = (yyvsp[(2) - (3)].list); } break; - case 215: -#line 1466 "go.y" + case 216: +#line 1472 "go.y" { closurehdr((yyvsp[(1) - (1)].node)); } break; - case 216: -#line 1472 "go.y" + case 217: +#line 1478 "go.y" { (yyval.node) = closurebody((yyvsp[(3) - (4)].list)); fixlbrace((yyvsp[(2) - (4)].i)); } break; - case 217: -#line 1477 "go.y" + case 218: +#line 1483 "go.y" { (yyval.node) = closurebody(nil); } break; - case 218: -#line 1488 "go.y" + case 219: +#line 1494 "go.y" { (yyval.list) = nil; } break; - case 219: -#line 1492 "go.y" + case 220: +#line 1498 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list)); if(nsyntaxerrors == 0) testdclstack(); nointerface = 0; noescape = 0; + nosplit = 0; } break; - case 221: -#line 1503 "go.y" + case 222: +#line 1510 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); } break; - case 223: -#line 1510 "go.y" + case 224: +#line 1517 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); } break; - case 224: -#line 1516 "go.y" + case 225: +#line 1523 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 225: -#line 1520 "go.y" + case 226: +#line 1527 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 227: -#line 1527 "go.y" + case 228: +#line 1534 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); } break; - case 228: -#line 1533 "go.y" + case 229: +#line 1540 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 229: -#line 1537 "go.y" + case 230: +#line 1544 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 230: -#line 1543 "go.y" + case 231: +#line 1550 "go.y" { NodeList *l; @@ -4115,16 +4111,16 @@ yyreduce: } break; - case 231: -#line 1566 "go.y" + case 232: +#line 1573 "go.y" { (yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val); (yyval.list) = list1((yyvsp[(1) - (2)].node)); } break; - case 232: -#line 1571 "go.y" + case 233: +#line 1578 "go.y" { (yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val); (yyval.list) = list1((yyvsp[(2) - (4)].node)); @@ -4132,8 +4128,8 @@ yyreduce: } break; - case 233: -#line 1577 "go.y" + case 234: +#line 1584 "go.y" { (yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N); (yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val); @@ -4141,8 +4137,8 @@ yyreduce: } break; - case 234: -#line 1583 "go.y" + case 235: +#line 1590 "go.y" { (yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N); (yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val); @@ -4151,8 +4147,8 @@ yyreduce: } break; - case 235: -#line 1590 "go.y" + case 236: +#line 1597 "go.y" { (yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N); (yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val); @@ -4161,8 +4157,8 @@ yyreduce: } break; - case 236: -#line 1599 "go.y" + case 237: +#line 1606 "go.y" { Node *n; @@ -4173,8 +4169,8 @@ yyreduce: } break; - case 237: -#line 1608 "go.y" + case 238: +#line 1615 "go.y" { Pkg *pkg; @@ -4189,38 +4185,38 @@ yyreduce: } break; - case 238: -#line 1623 "go.y" + case 239: +#line 1630 "go.y" { (yyval.node) = embedded((yyvsp[(1) - (1)].sym), localpkg); } break; - case 239: -#line 1629 "go.y" + case 240: +#line 1636 "go.y" { (yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); ifacedcl((yyval.node)); } break; - case 240: -#line 1634 "go.y" + case 241: +#line 1641 "go.y" { (yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym))); } break; - case 241: -#line 1638 "go.y" + case 242: +#line 1645 "go.y" { (yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym))); yyerror("cannot parenthesize embedded type"); } break; - case 242: -#line 1645 "go.y" + case 243: +#line 1652 "go.y" { // without func keyword (yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1); @@ -4230,8 +4226,8 @@ yyreduce: } break; - case 244: -#line 1659 "go.y" + case 245: +#line 1666 "go.y" { (yyval.node) = nod(ONONAME, N, N); (yyval.node)->sym = (yyvsp[(1) - (2)].sym); @@ -4239,8 +4235,8 @@ yyreduce: } break; - case 245: -#line 1665 "go.y" + case 246: +#line 1672 "go.y" { (yyval.node) = nod(ONONAME, N, N); (yyval.node)->sym = (yyvsp[(1) - (2)].sym); @@ -4248,65 +4244,65 @@ yyreduce: } break; - case 247: -#line 1674 "go.y" + case 248: +#line 1681 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 248: -#line 1678 "go.y" + case 249: +#line 1685 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 249: -#line 1683 "go.y" + case 250: +#line 1690 "go.y" { (yyval.list) = nil; } break; - case 250: -#line 1687 "go.y" + case 251: +#line 1694 "go.y" { (yyval.list) = (yyvsp[(1) - (2)].list); } break; - case 251: -#line 1695 "go.y" + case 252: +#line 1702 "go.y" { (yyval.node) = N; } break; - case 253: -#line 1700 "go.y" + case 254: +#line 1707 "go.y" { (yyval.node) = liststmt((yyvsp[(1) - (1)].list)); } break; - case 255: -#line 1705 "go.y" + case 256: +#line 1712 "go.y" { (yyval.node) = N; } break; - case 261: -#line 1716 "go.y" + case 262: +#line 1723 "go.y" { (yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N); (yyvsp[(1) - (2)].node)->sym = dclstack; // context, for goto restrictions } break; - case 262: -#line 1721 "go.y" + case 263: +#line 1728 "go.y" { NodeList *l; @@ -4318,8 +4314,8 @@ yyreduce: } break; - case 263: -#line 1731 "go.y" + case 264: +#line 1738 "go.y" { // will be converted to OFALL (yyval.node) = nod(OXFALL, N, N); @@ -4327,44 +4323,44 @@ yyreduce: } break; - case 264: -#line 1737 "go.y" + case 265: +#line 1744 "go.y" { (yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N); } break; - case 265: -#line 1741 "go.y" + case 266: +#line 1748 "go.y" { (yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N); } break; - case 266: -#line 1745 "go.y" + case 267: +#line 1752 "go.y" { (yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N); } break; - case 267: -#line 1749 "go.y" + case 268: +#line 1756 "go.y" { (yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N); } break; - case 268: -#line 1753 "go.y" + case 269: +#line 1760 "go.y" { (yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N); (yyval.node)->sym = dclstack; // context, for goto restrictions } break; - case 269: -#line 1758 "go.y" + case 270: +#line 1765 "go.y" { (yyval.node) = nod(ORETURN, N, N); (yyval.node)->list = (yyvsp[(2) - (2)].list); @@ -4383,8 +4379,8 @@ yyreduce: } break; - case 270: -#line 1777 "go.y" + case 271: +#line 1784 "go.y" { (yyval.list) = nil; if((yyvsp[(1) - (1)].node) != N) @@ -4392,8 +4388,8 @@ yyreduce: } break; - case 271: -#line 1783 "go.y" + case 272: +#line 1790 "go.y" { (yyval.list) = (yyvsp[(1) - (3)].list); if((yyvsp[(3) - (3)].node) != N) @@ -4401,190 +4397,190 @@ yyreduce: } break; - case 272: -#line 1791 "go.y" + case 273: +#line 1798 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 273: -#line 1795 "go.y" + case 274: +#line 1802 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 274: -#line 1801 "go.y" + case 275: +#line 1808 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 275: -#line 1805 "go.y" + case 276: +#line 1812 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 276: -#line 1811 "go.y" + case 277: +#line 1818 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 277: -#line 1815 "go.y" + case 278: +#line 1822 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 278: -#line 1821 "go.y" + case 279: +#line 1828 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 279: -#line 1825 "go.y" + case 280: +#line 1832 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 280: -#line 1834 "go.y" + case 281: +#line 1841 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 281: -#line 1838 "go.y" + case 282: +#line 1845 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 282: -#line 1842 "go.y" + case 283: +#line 1849 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 283: -#line 1846 "go.y" + case 284: +#line 1853 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 284: -#line 1851 "go.y" + case 285: +#line 1858 "go.y" { (yyval.list) = nil; } break; - case 285: -#line 1855 "go.y" + case 286: +#line 1862 "go.y" { (yyval.list) = (yyvsp[(1) - (2)].list); } break; - case 290: -#line 1869 "go.y" + case 291: +#line 1876 "go.y" { (yyval.node) = N; } break; - case 292: -#line 1875 "go.y" + case 293: +#line 1882 "go.y" { (yyval.list) = nil; } break; - case 294: -#line 1881 "go.y" + case 295: +#line 1888 "go.y" { (yyval.node) = N; } break; - case 296: -#line 1887 "go.y" + case 297: +#line 1894 "go.y" { (yyval.list) = nil; } break; - case 298: -#line 1893 "go.y" + case 299: +#line 1900 "go.y" { (yyval.list) = nil; } break; - case 300: -#line 1899 "go.y" + case 301: +#line 1906 "go.y" { (yyval.list) = nil; } break; - case 302: -#line 1905 "go.y" + case 303: +#line 1912 "go.y" { (yyval.val).ctype = CTxxx; } break; - case 304: -#line 1915 "go.y" + case 305: +#line 1922 "go.y" { importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval); } break; - case 305: -#line 1919 "go.y" + case 306: +#line 1926 "go.y" { importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type)); } break; - case 306: -#line 1923 "go.y" + case 307: +#line 1930 "go.y" { importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node)); } break; - case 307: -#line 1927 "go.y" + case 308: +#line 1934 "go.y" { importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node)); } break; - case 308: -#line 1931 "go.y" + case 309: +#line 1938 "go.y" { importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type)); } break; - case 309: -#line 1935 "go.y" + case 310: +#line 1942 "go.y" { if((yyvsp[(2) - (4)].node) == N) { dclcontext = PEXTERN; // since we skip the funcbody below @@ -4604,31 +4600,31 @@ yyreduce: } break; - case 310: -#line 1955 "go.y" + case 311: +#line 1962 "go.y" { (yyval.sym) = (yyvsp[(1) - (1)].sym); structpkg = (yyval.sym)->pkg; } break; - case 311: -#line 1962 "go.y" + case 312: +#line 1969 "go.y" { (yyval.type) = pkgtype((yyvsp[(1) - (1)].sym)); importsym((yyvsp[(1) - (1)].sym), OTYPE); } break; - case 317: -#line 1982 "go.y" + case 318: +#line 1989 "go.y" { (yyval.type) = pkgtype((yyvsp[(1) - (1)].sym)); } break; - case 318: -#line 1986 "go.y" + case 319: +#line 1993 "go.y" { // predefined name like uint8 (yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg); @@ -4640,50 +4636,50 @@ yyreduce: } break; - case 319: -#line 1996 "go.y" + case 320: +#line 2003 "go.y" { (yyval.type) = aindex(N, (yyvsp[(3) - (3)].type)); } break; - case 320: -#line 2000 "go.y" + case 321: +#line 2007 "go.y" { (yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type)); } break; - case 321: -#line 2004 "go.y" + case 322: +#line 2011 "go.y" { (yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type)); } break; - case 322: -#line 2008 "go.y" + case 323: +#line 2015 "go.y" { (yyval.type) = tostruct((yyvsp[(3) - (4)].list)); } break; - case 323: -#line 2012 "go.y" + case 324: +#line 2019 "go.y" { (yyval.type) = tointerface((yyvsp[(3) - (4)].list)); } break; - case 324: -#line 2016 "go.y" + case 325: +#line 2023 "go.y" { (yyval.type) = ptrto((yyvsp[(2) - (2)].type)); } break; - case 325: -#line 2020 "go.y" + case 326: +#line 2027 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(2) - (2)].type); @@ -4691,8 +4687,8 @@ yyreduce: } break; - case 326: -#line 2026 "go.y" + case 327: +#line 2033 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(3) - (4)].type); @@ -4700,8 +4696,8 @@ yyreduce: } break; - case 327: -#line 2032 "go.y" + case 328: +#line 2039 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(3) - (3)].type); @@ -4709,8 +4705,8 @@ yyreduce: } break; - case 328: -#line 2040 "go.y" + case 329: +#line 2047 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(3) - (3)].type); @@ -4718,15 +4714,15 @@ yyreduce: } break; - case 329: -#line 2048 "go.y" + case 330: +#line 2055 "go.y" { (yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list)); } break; - case 330: -#line 2054 "go.y" + case 331: +#line 2061 "go.y" { (yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type))); if((yyvsp[(1) - (3)].sym)) @@ -4735,8 +4731,8 @@ yyreduce: } break; - case 331: -#line 2061 "go.y" + case 332: +#line 2068 "go.y" { Type *t; @@ -4752,8 +4748,8 @@ yyreduce: } break; - case 332: -#line 2077 "go.y" + case 333: +#line 2084 "go.y" { Sym *s; Pkg *p; @@ -4775,50 +4771,50 @@ yyreduce: } break; - case 333: -#line 2099 "go.y" + case 334: +#line 2106 "go.y" { (yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list)))); } break; - case 334: -#line 2103 "go.y" + case 335: +#line 2110 "go.y" { (yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))); } break; - case 335: -#line 2108 "go.y" + case 336: +#line 2115 "go.y" { (yyval.list) = nil; } break; - case 337: -#line 2115 "go.y" + case 338: +#line 2122 "go.y" { (yyval.list) = (yyvsp[(2) - (3)].list); } break; - case 338: -#line 2119 "go.y" + case 339: +#line 2126 "go.y" { (yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)))); } break; - case 339: -#line 2129 "go.y" + case 340: +#line 2136 "go.y" { (yyval.node) = nodlit((yyvsp[(1) - (1)].val)); } break; - case 340: -#line 2133 "go.y" + case 341: +#line 2140 "go.y" { (yyval.node) = nodlit((yyvsp[(2) - (2)].val)); switch((yyval.node)->val.ctype){ @@ -4839,8 +4835,8 @@ yyreduce: } break; - case 341: -#line 2152 "go.y" + case 342: +#line 2159 "go.y" { (yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg)); if((yyval.node)->op != OLITERAL) @@ -4848,8 +4844,8 @@ yyreduce: } break; - case 343: -#line 2161 "go.y" + case 344: +#line 2168 "go.y" { if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) { (yyval.node) = (yyvsp[(2) - (5)].node); @@ -4862,43 +4858,43 @@ yyreduce: } break; - case 346: -#line 2177 "go.y" + case 347: +#line 2184 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 347: -#line 2181 "go.y" + case 348: +#line 2188 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 348: -#line 2187 "go.y" + case 349: +#line 2194 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 349: -#line 2191 "go.y" + case 350: +#line 2198 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; - case 350: -#line 2197 "go.y" + case 351: +#line 2204 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; - case 351: -#line 2201 "go.y" + case 352: +#line 2208 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } @@ -4906,7 +4902,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 4911 "y.tab.c" +#line 4907 "y.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -5120,7 +5116,7 @@ yyreturn: } -#line 2205 "go.y" +#line 2212 "go.y" static void diff --git a/src/cmd/gc/yerr.h b/src/cmd/gc/yerr.h index 1526d8231..d0dd639ff 100644 --- a/src/cmd/gc/yerr.h +++ b/src/cmd/gc/yerr.h @@ -14,66 +14,66 @@ static struct { // is converted by bisonerrors into the yystate and yychar caused // by that token list. - 222, ',', - "unexpected comma during import block", + {222, ',', + "unexpected comma during import block"}, - 32, ';', - "missing import path; require quoted string", + {32, ';', + "missing import path; require quoted string"}, - 378, ';', - "missing { after if clause", + {380, ';', + "missing { after if clause"}, - 399, ';', - "missing { after switch clause", + {401, ';', + "missing { after switch clause"}, - 238, ';', - "missing { after for clause", + {239, ';', + "missing { after for clause"}, - 476, LBODY, - "missing { after for clause", + {478, LBODY, + "missing { after for clause"}, - 22, '{', - "unexpected semicolon or newline before {", + {22, '{', + "unexpected semicolon or newline before {"}, - 145, ';', - "unexpected semicolon or newline in type declaration", + {145, ';', + "unexpected semicolon or newline in type declaration"}, - 37, '}', - "unexpected } in channel type", + {37, '}', + "unexpected } in channel type"}, - 37, ')', - "unexpected ) in channel type", + {37, ')', + "unexpected ) in channel type"}, - 37, ',', - "unexpected comma in channel type", + {37, ',', + "unexpected comma in channel type"}, - 439, LELSE, - "unexpected semicolon or newline before else", + {441, LELSE, + "unexpected semicolon or newline before else"}, - 258, ',', - "name list not allowed in interface type", + {259, ',', + "name list not allowed in interface type"}, - 238, LVAR, - "var declaration not allowed in for initializer", + {239, LVAR, + "var declaration not allowed in for initializer"}, - 65, '{', - "unexpected { at end of statement", + {65, '{', + "unexpected { at end of statement"}, - 377, '{', - "unexpected { at end of statement", + {379, '{', + "unexpected { at end of statement"}, - 126, ';', - "argument to go/defer must be function call", + {126, ';', + "argument to go/defer must be function call"}, - 426, ';', - "need trailing comma before newline in composite literal", + {428, ';', + "need trailing comma before newline in composite literal"}, - 437, ';', - "need trailing comma before newline in composite literal", + {439, ';', + "need trailing comma before newline in composite literal"}, - 113, LNAME, - "nested func not allowed", + {113, LNAME, + "nested func not allowed"}, - 645, ';', - "else must be followed by if or statement block" + {647, ';', + "else must be followed by if or statement block"} }; diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index 3645f1c2d..1dd4314da 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -57,6 +57,7 @@ and test commands: -a force rebuilding of packages that are already up-to-date. + In Go releases, does not apply to the standard library. -n print the commands but do not run them. -p n @@ -64,7 +65,7 @@ and test commands: The default is the number of CPUs available. -race enable data race detection. - Supported only on linux/amd64, darwin/amd64 and windows/amd64. + Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. -v print the names of packages as they are compiled. -work @@ -284,23 +285,26 @@ func runBuild(cmd *Command, args []string) { } } + depMode := modeBuild + if buildI { + depMode = modeInstall + } + if *buildO != "" { if len(pkgs) > 1 { fatalf("go build: cannot use -o with multiple packages") + } else if len(pkgs) == 0 { + fatalf("no packages to build") } p := pkgs[0] p.target = "" // must build - not up to date - a := b.action(modeInstall, modeBuild, p) + a := b.action(modeInstall, depMode, p) a.target = *buildO b.do(a) return } a := &action{} - depMode := modeBuild - if buildI { - depMode = modeInstall - } for _, p := range packages(args) { a.deps = append(a.deps, b.action(modeBuild, depMode, p)) } @@ -431,12 +435,11 @@ const ( ) var ( - goroot = filepath.Clean(runtime.GOROOT()) - gobin = os.Getenv("GOBIN") - gorootBin = filepath.Join(goroot, "bin") - gorootSrcPkg = filepath.Join(goroot, "src/pkg") - gorootPkg = filepath.Join(goroot, "pkg") - gorootSrc = filepath.Join(goroot, "src") + goroot = filepath.Clean(runtime.GOROOT()) + gobin = os.Getenv("GOBIN") + gorootBin = filepath.Join(goroot, "bin") + gorootPkg = filepath.Join(goroot, "pkg") + gorootSrc = filepath.Join(goroot, "src") ) func (b *builder) init() { @@ -503,8 +506,13 @@ func goFilesPackage(gofiles []string) *Package { } ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil } - if !filepath.IsAbs(dir) { - dir = filepath.Join(cwd, dir) + var err error + if dir == "" { + dir = cwd + } + dir, err = filepath.Abs(dir) + if err != nil { + fatalf("%s", err) } bp, err := ctxt.ImportDir(dir, 0) @@ -823,12 +831,17 @@ func (b *builder) build(a *action) (err error) { } } - var gofiles, cfiles, sfiles, objects, cgoObjects []string + var gofiles, cfiles, sfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string gofiles = append(gofiles, a.p.GoFiles...) cfiles = append(cfiles, a.p.CFiles...) sfiles = append(sfiles, a.p.SFiles...) + if a.p.usesCgo() || a.p.usesSwig() { + if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.p); err != nil { + return + } + } // Run cgo. if a.p.usesCgo() { // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc. @@ -859,7 +872,7 @@ func (b *builder) build(a *action) (err error) { if a.cgo != nil && a.cgo.target != "" { cgoExe = a.cgo.target } - outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles, a.p.CXXFiles, a.p.MFiles) + outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, gccfiles, a.p.CXXFiles, a.p.MFiles) if err != nil { return err } @@ -872,9 +885,18 @@ func (b *builder) build(a *action) (err error) { // In a package using SWIG, any .c or .s files are // compiled with gcc. gccfiles := append(cfiles, sfiles...) + cxxfiles, mfiles := a.p.CXXFiles, a.p.MFiles cfiles = nil sfiles = nil - outGo, outObj, err := b.swig(a.p, obj, gccfiles, a.p.CXXFiles, a.p.MFiles) + + // Don't build c/c++ files twice if cgo is enabled (mainly for pkg-config). + if a.p.usesCgo() { + cxxfiles = nil + gccfiles = nil + mfiles = nil + } + + outGo, outObj, err := b.swig(a.p, obj, pcCFLAGS, gccfiles, cxxfiles, mfiles) if err != nil { return err } @@ -883,7 +905,7 @@ func (b *builder) build(a *action) (err error) { } if len(gofiles) == 0 { - return &build.NoGoError{a.p.Dir} + return &build.NoGoError{Dir: a.p.Dir} } // If we're doing coverage, preprocess the .go files and put them in the work directory @@ -1018,6 +1040,34 @@ func (b *builder) build(a *action) (err error) { return nil } +// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package. +func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err error) { + if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { + var out []byte + out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs) + if err != nil { + b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out)) + b.print(err.Error() + "\n") + err = errPrintedOutput + return + } + if len(out) > 0 { + cflags = strings.Fields(string(out)) + } + out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs) + if err != nil { + b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out)) + b.print(err.Error() + "\n") + err = errPrintedOutput + return + } + if len(out) > 0 { + ldflags = strings.Fields(string(out)) + } + } + return +} + // install is the action for installing a single package or executable. func (b *builder) install(a *action) (err error) { defer func() { @@ -1253,7 +1303,7 @@ func (b *builder) showcmd(dir string, format string, args ...interface{}) { // the source directory for the package that has failed to build. // showOutput rewrites mentions of dir with a relative path to dir // when the relative path is shorter. This is usually more pleasant. -// For example, if fmt doesn't compile and we are in src/pkg/html, +// For example, if fmt doesn't compile and we are in src/html, // the output is // // $ go build @@ -1265,7 +1315,7 @@ func (b *builder) showcmd(dir string, format string, args ...interface{}) { // // $ go build // # fmt -// /usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf +// /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf // $ // // showOutput also replaces references to the work directory with $WORK. @@ -1425,6 +1475,14 @@ func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter continue } + // err can be something like 'exit status 1'. + // Add information about what program was running. + // Note that if buf.Bytes() is non-empty, the caller usually + // shows buf.Bytes() and does not print err at all, so the + // prefix here does not make most output any more verbose. + if err != nil { + err = errors.New(cmdline[0] + ": " + err.Error()) + } return buf.Bytes(), err } } @@ -1587,7 +1645,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs [] extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) if p.Standard { switch p.ImportPath { - case "os", "runtime/pprof", "sync", "time": + case "bytes", "net", "os", "runtime/pprof", "sync", "time": extFiles++ } } @@ -1611,8 +1669,10 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs [] } func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { + // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. + inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) sfile = mkAbs(p.Dir, sfile) - return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) + return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) } func (gcToolchain) pkgpath(basedir string, p *Package) string { @@ -1706,7 +1766,7 @@ func packInternal(b *builder, afile string, ofiles []string) error { func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { importArgs := b.includeArgs("-L", allactions) - cxx := false + cxx := len(p.CXXFiles) > 0 for _, a := range allactions { if a.p != nil && len(a.p.CXXFiles) > 0 { cxx = true @@ -1766,14 +1826,30 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) cfile = mkAbs(p.Dir, cfile) - args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile) + warn := []string{"-w"} + if p.usesSwig() { + // When using SWIG, this compiler is only used to + // compile the C files generated by SWIG. + // We don't want warnings. + // See issue 9065 for details. + warn = nil + } + args := stringList(tool(archChar+"c"), "-F", "-V", warn, "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile) return b.run(p.Dir, p.ImportPath, nil, args) } // The Gccgo toolchain. type gccgoToolchain struct{} -var gccgoBin, _ = exec.LookPath("gccgo") +var gccgoName, gccgoBin string + +func init() { + gccgoName = os.Getenv("GCCGO") + if gccgoName == "" { + gccgoName = "gccgo" + } + gccgoBin, _ = exec.LookPath(gccgoName) +} func (gccgoToolchain) compiler() string { return gccgoBin @@ -1784,7 +1860,7 @@ func (gccgoToolchain) linker() string { } func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { - out := p.Name + ".o" + out := "_go_.o" ofile = obj + out gcargs := []string{"-g"} gcargs = append(gcargs, b.gccArchArgs()...) @@ -1794,7 +1870,7 @@ func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs if p.localPrefix != "" { gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix) } - args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags) + args := stringList(gccgoName, importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags) for _, f := range gofiles { args = append(args, mkAbs(p.Dir, f)) } @@ -1810,7 +1886,7 @@ func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) } defs = append(defs, b.gccArchArgs()...) - return b.run(p.Dir, p.ImportPath, nil, "gccgo", "-I", obj, "-o", ofile, defs, sfile) + return b.run(p.Dir, p.ImportPath, nil, gccgoName, "-I", obj, "-o", ofile, defs, sfile) } func (gccgoToolchain) pkgpath(basedir string, p *Package) string { @@ -1836,8 +1912,8 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] ldflags := b.gccArchArgs() cgoldflags := []string{} usesCgo := false - cxx := false - objc := false + cxx := len(p.CXXFiles) > 0 + objc := len(p.MFiles) > 0 // Prefer the output of an install action to the output of a build action, // because the install action will delete the output of the build action. @@ -1877,6 +1953,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] } ldflags = append(ldflags, afiles...) ldflags = append(ldflags, cgoldflags...) + ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...) ldflags = append(ldflags, p.CgoLDFLAGS...) if usesCgo && goos == "linux" { ldflags = append(ldflags, "-Wl,-E") @@ -1887,7 +1964,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] if objc { ldflags = append(ldflags, "-lobjc") } - return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags) + return b.run(".", p.ImportPath, nil, gccgoName, "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags) } func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { @@ -1898,8 +1975,7 @@ func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) } - // TODO: Support using clang here (during gccgo build)? - return b.run(p.Dir, p.ImportPath, nil, "gcc", "-Wall", "-g", + return b.run(p.Dir, p.ImportPath, nil, envList("CC", defaultCC), "-Wall", "-g", "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) } @@ -1950,9 +2026,9 @@ func (b *builder) libgcc(p *Package) (string, error) { return "$LIBGCC", nil } - // clang might not be able to find libgcc, and in that case, + // The compiler might not be able to find libgcc, and in that case, // it will simply return "libgcc.a", which is of no use to us. - if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) { + if !filepath.IsAbs(string(f)) { return "", nil } @@ -2090,36 +2166,16 @@ var ( cgoLibGccFileOnce sync.Once ) -func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { +func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true) _, cgoexeCFLAGS, _, _ := b.cflags(p, false) - + cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) + cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...) // If we are compiling Objective-C code, then we need to link against libobjc if len(mfiles) > 0 { cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc") } - if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { - out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs) - if err != nil { - b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out)) - b.print(err.Error() + "\n") - return nil, nil, errPrintedOutput - } - if len(out) > 0 { - cgoCPPFLAGS = append(cgoCPPFLAGS, strings.Fields(string(out))...) - } - out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs) - if err != nil { - b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out)) - b.print(err.Error() + "\n") - return nil, nil, errPrintedOutput - } - if len(out) > 0 { - cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(out))...) - } - } - // Allows including _cgo_export.h from .[ch] files in the package. cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj) @@ -2196,6 +2252,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles strings.HasSuffix(f, ".so"), strings.HasSuffix(f, ".dll"): continue + // Remove any -fsanitize=foo flags. + // Otherwise the compiler driver thinks that we are doing final link + // and links sanitizer runtime into the object file. But we are not doing + // the final link, we will link the resulting object file again. And + // so the program ends up with two copies of sanitizer runtime. + // See issue 8788 for details. + case strings.HasPrefix(f, "-fsanitize="): + continue default: bareLDFLAGS = append(bareLDFLAGS, f) } @@ -2262,13 +2326,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles linkobj = append(linkobj, p.SysoFiles...) dynobj := obj + "_cgo_.o" - if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux/ARM to get accurate imported sym + pie := goarch == "arm" && (goos == "linux" || goos == "android") + if pie { // we need to use -pie for Linux/ARM to get accurate imported sym cgoLDFLAGS = append(cgoLDFLAGS, "-pie") } if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil { return nil, nil, err } - if goarch == "arm" && goos == "linux" { // but we don't need -pie for normal cgo programs + if pie { // but we don't need -pie for normal cgo programs cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1] } @@ -2302,7 +2367,23 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles nonGccObjs = append(nonGccObjs, f) } } - if err := b.gccld(p, ofile, stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs), gccObjs); err != nil { + ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs) + + // Some systems, such as Ubuntu, always add --build-id to + // every link, but we don't want a build ID since we are + // producing an object file. On some of those system a plain + // -r (not -Wl,-r) will turn off --build-id, but clang 3.0 + // doesn't support a plain -r. I don't know how to turn off + // --build-id when using clang other than passing a trailing + // --build-id=none. So that is what we do, but only on + // systems likely to support it, which is to say, systems that + // normally use gold or the GNU linker. + switch goos { + case "android", "dragonfly", "linux", "netbsd": + ldflags = append(ldflags, "-Wl,--build-id=none") + } + + if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil { return nil, nil, err } @@ -2317,7 +2398,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles // Run SWIG on all SWIG input files. // TODO: Don't build a shared library, once SWIG emits the necessary // pragmas for external linking. -func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { +func (b *builder) swig(p *Package, obj string, pcCFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) @@ -2358,7 +2439,7 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri } for _, f := range p.SwigFiles { - goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, false, intgosize) + goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, false, intgosize) if err != nil { return nil, nil, err } @@ -2373,7 +2454,7 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri } } for _, f := range p.SwigCXXFiles { - goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, true, intgosize) + goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, true, intgosize) if err != nil { return nil, nil, err } @@ -2452,13 +2533,13 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) { } // Run SWIG on one SWIG input file. -func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) { +func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) { cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) var cflags []string if cxx { - cflags = stringList(cgoCPPFLAGS, cgoCXXFLAGS) + cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS) } else { - cflags = stringList(cgoCPPFLAGS, cgoCFLAGS) + cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS) } n := 5 // length of ".swig" @@ -2484,6 +2565,13 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri "-o", obj + gccBase + gccExt, "-outdir", obj, } + + for _, f := range cflags { + if len(f) > 3 && f[:2] == "-I" { + args = append(args, f) + } + } + if gccgo { args = append(args, "-gccgo") if pkgpath := gccgoPkgpath(p); pkgpath != "" { @@ -2556,8 +2644,8 @@ func raceInit() { if !buildRace { return } - if goarch != "amd64" || goos != "linux" && goos != "darwin" && goos != "windows" { - fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) + if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" { + fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) os.Exit(2) } buildGcflags = append(buildGcflags, "-race") diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go index 9840804ce..d0d8a8a5b 100644 --- a/src/cmd/go/doc.go +++ b/src/cmd/go/doc.go @@ -19,6 +19,7 @@ The commands are: env print Go environment information fix run go tool fix on packages fmt run gofmt on package sources + generate generate Go files by processing source get download and install packages and dependencies install compile and install packages and dependencies list list packages @@ -75,6 +76,7 @@ and test commands: -a force rebuilding of packages that are already up-to-date. + In Go releases, does not apply to the standard library. -n print the commands but do not run them. -p n @@ -82,7 +84,7 @@ and test commands: The default is the number of CPUs available. -race enable data race detection. - Supported only on linux/amd64, darwin/amd64 and windows/amd64. + Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. -v print the names of packages as they are compiled. -work @@ -219,11 +221,110 @@ To run gofmt with specific options, run gofmt itself. See also: go fix, go vet. +Generate Go files by processing source + +Usage: + + go generate [-run regexp] [file.go... | packages] + +Generate runs commands described by directives within existing +files. Those commands can run any process but the intent is to +create or update Go source files, for instance by running yacc. + +Go generate is never run automatically by go build, go get, go test, +and so on. It must be run explicitly. + +Go generate scans the file for directives, which are lines of +the form, + + //go:generate command argument... + +(note: no leading spaces and no space in "//go") where command +is the generator to be run, corresponding to an executable file +that can be run locally. It must either be in the shell path +(gofmt), a fully qualified path (/usr/you/bin/mytool), or a +command alias, described below. + +Note that go generate does not parse the file, so lines that look +like directives in comments or multiline strings will be treated +as directives. + +The arguments to the directive are space-separated tokens or +double-quoted strings passed to the generator as individual +arguments when it is run. + +Quoted strings use Go syntax and are evaluated before execution; a +quoted string appears as a single argument to the generator. + +Go generate sets several variables when it runs the generator: + + $GOARCH + The execution architecture (arm, amd64, etc.) + $GOOS + The execution operating system (linux, windows, etc.) + $GOFILE + The base name of the file. + $GOPACKAGE + The name of the package of the file containing the directive. + +Other than variable substitution and quoted-string evaluation, no +special processing such as "globbing" is performed on the command +line. + +As a last step before running the command, any invocations of any +environment variables with alphanumeric names, such as $GOFILE or +$HOME, are expanded throughout the command line. The syntax for +variable expansion is $NAME on all operating systems. Due to the +order of evaluation, variables are expanded even inside quoted +strings. If the variable NAME is not set, $NAME expands to the +empty string. + +A directive of the form, + + //go:generate -command xxx args... + +specifies, for the remainder of this source file only, that the +string xxx represents the command identified by the arguments. This +can be used to create aliases or to handle multiword generators. +For example, + + //go:generate -command yacc go tool yacc + +specifies that the command "yacc" represents the generator +"go tool yacc". + +Generate processes packages in the order given on the command line, +one at a time. If the command line lists .go files, they are treated +as a single package. Within a package, generate processes the +source files in a package in file name order, one at a time. Within +a source file, generate runs generators in the order they appear +in the file, one at a time. + +If any generator returns an error exit status, "go generate" skips +all further processing for that package. + +The generator is run in the package's source directory. + +Go generate accepts one specific flag: + + -run="" + if non-empty, specifies a regular expression to + select directives whose command 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 +processed. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +For more about specifying packages, see 'go help packages'. + + Download and install packages and dependencies Usage: - go get [-d] [-fix] [-t] [-u] [build flags] [packages] + go get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages] Get downloads and installs the packages named by the import paths, along with their dependencies. @@ -231,6 +332,11 @@ along with their dependencies. The -d flag instructs get to stop after downloading the packages; that is, it instructs get not to install the packages. +The -f flag, valid only when -u is set, forces get -u not to verify that +each package has been checked out from the source control repository +implied by its import path. This can be useful if the source is a local fork +of the original. + The -fix flag instructs get to run the fix tool on the downloaded packages before resolving dependencies or building the code. @@ -291,28 +397,29 @@ syntax of package template. The default output is equivalent to -f '{{.ImportPath}}'. The struct being passed to the template is: type Package struct { - Dir string // directory containing package sources - ImportPath string // import path of package in dir - Name string // package name - Doc string // package documentation string - Target string // install path - 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? - Root string // Go root or Go path dir containing this package + Dir string // directory containing package sources + ImportPath string // import path of package in dir + ImportComment string // path in import comment on package statement + Name string // package name + Doc string // package documentation string + Target string // install path + 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? + Root string // Go root or Go path dir containing this package // Source files - GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) - CgoFiles []string // .go sources files that import "C" + GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string // .go sources files that import "C" IgnoredGoFiles []string // .go sources ignored due to build constraints - CFiles []string // .c source files - CXXFiles []string // .cc, .cxx and .cpp source files - MFiles []string // .m source files - HFiles []string // .h, .hh, .hpp and .hxx source files - SFiles []string // .s source files - SwigFiles []string // .swig files - SwigCXXFiles []string // .swigcxx files - SysoFiles []string // .syso object files to add to archive + CFiles []string // .c source files + CXXFiles []string // .cc, .cxx and .cpp source files + MFiles []string // .m source files + HFiles []string // .h, .hh, .hpp and .hxx source files + SFiles []string // .s source files + SwigFiles []string // .swig files + SwigCXXFiles []string // .swigcxx files + SysoFiles []string // .syso object files to add to archive // Cgo directives CgoCFLAGS []string // cgo: flags for C compiler @@ -431,16 +538,23 @@ non-test installation. In addition to the build flags, the flags handled by 'go test' itself are: - -c Compile the test binary to pkg.test but do not run it. - (Where pkg is the last element of the package's import path.) + -c + Compile the test binary to pkg.test but do not run it + (where pkg is the last element of the package's import path). + The file name can be changed with the -o flag. + + -exec xprog + Run the test binary using xprog. The behavior is the same as + in 'go run'. See 'go help run' for details. -i Install packages that are dependencies of the test. Do not run the test. - -exec xprog - Run the test binary using xprog. The behavior is the same as - in 'go run'. See 'go help run' for details. + -o file + 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. @@ -488,7 +602,7 @@ Usage: Vet runs the Go vet command on the packages named by the import paths. -For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'. +For more about vet, see 'godoc golang.org/x/tools/cmd/vet'. For more about specifying packages, see 'go help packages'. To run the vet tool with specific options, run 'go tool vet'. @@ -681,6 +795,11 @@ A few common code hosting sites have special syntax: import "launchpad.net/~user/project/branch" import "launchpad.net/~user/project/branch/sub/directory" + IBM DevOps Services (Git) + + import "hub.jazz.net/git/user/project" + import "hub.jazz.net/git/user/project/sub/directory" + For code hosted on other servers, import paths may either be qualified with the version control type, or the go tool can dynamically fetch the import path over https/http and discover where the code resides @@ -756,7 +875,26 @@ listed in the GOPATH environment variable (see 'go help gopath'). The go command attempts to download the version of the package appropriate for the Go release being used. -Run 'go help install' for more. +Run 'go help get' for more. + +Import path checking + +When the custom import path feature described above redirects to a +known code hosting site, each of the resulting packages has two possible +import paths, using the custom domain or the known hosting site. + +A package statement is said to have an "import comment" if it is immediately +followed (before the next newline) by a comment of one of these two forms: + + package math // import "path" + package math /* import "path" * / + +The go command will refuse to install a package with an import comment +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. + +See https://golang.org/s/go14customimport for details. Description of package lists @@ -812,7 +950,8 @@ single directory, the command is applied to a single synthesized package made up of exactly those files, ignoring any build constraints in those files and ignoring any other files in the directory. -File names that begin with "." or "_" are ignored by the go tool. +Directory and file names that begin with "." or "_" are ignored +by the go tool, as are directories named "testdata". Description of testing flags @@ -844,6 +983,7 @@ control the execution of any test: -blockprofile block.out Write a goroutine blocking profile to the specified file when all tests are complete. + Writes test binary as -c would. -blockprofilerate n Control the detail provided in goroutine blocking profiles by @@ -875,8 +1015,7 @@ control the execution of any test: Sets -cover. -coverprofile cover.out - Write a coverage profile to the specified file after all tests - have passed. + Write a coverage profile to the file after all tests have passed. Sets -cover. -cpu 1,2,4 @@ -886,10 +1025,11 @@ control the execution of any test: -cpuprofile cpu.out Write a CPU profile to the specified file before exiting. + Writes test binary as -c would. -memprofile mem.out - Write a memory profile to the specified file after all tests - have passed. + Write a memory profile to the file after all tests have passed. + Writes test binary as -c would. -memprofilerate n Enable more precise (and expensive) memory profiles by setting diff --git a/src/cmd/go/generate.go b/src/cmd/go/generate.go new file mode 100644 index 000000000..baf4d2b55 --- /dev/null +++ b/src/cmd/go/generate.go @@ -0,0 +1,398 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bufio" + "bytes" + "fmt" + "io" + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +var cmdGenerate = &Command{ + Run: runGenerate, + UsageLine: "generate [-run regexp] [file.go... | packages]", + Short: "generate Go files by processing source", + Long: ` +Generate runs commands described by directives within existing +files. Those commands can run any process but the intent is to +create or update Go source files, for instance by running yacc. + +Go generate is never run automatically by go build, go get, go test, +and so on. It must be run explicitly. + +Go generate scans the file for directives, which are lines of +the form, + + //go:generate command argument... + +(note: no leading spaces and no space in "//go") where command +is the generator to be run, corresponding to an executable file +that can be run locally. It must either be in the shell path +(gofmt), a fully qualified path (/usr/you/bin/mytool), or a +command alias, described below. + +Note that go generate does not parse the file, so lines that look +like directives in comments or multiline strings will be treated +as directives. + +The arguments to the directive are space-separated tokens or +double-quoted strings passed to the generator as individual +arguments when it is run. + +Quoted strings use Go syntax and are evaluated before execution; a +quoted string appears as a single argument to the generator. + +Go generate sets several variables when it runs the generator: + + $GOARCH + The execution architecture (arm, amd64, etc.) + $GOOS + The execution operating system (linux, windows, etc.) + $GOFILE + The base name of the file. + $GOPACKAGE + The name of the package of the file containing the directive. + +Other than variable substitution and quoted-string evaluation, no +special processing such as "globbing" is performed on the command +line. + +As a last step before running the command, any invocations of any +environment variables with alphanumeric names, such as $GOFILE or +$HOME, are expanded throughout the command line. The syntax for +variable expansion is $NAME on all operating systems. Due to the +order of evaluation, variables are expanded even inside quoted +strings. If the variable NAME is not set, $NAME expands to the +empty string. + +A directive of the form, + + //go:generate -command xxx args... + +specifies, for the remainder of this source file only, that the +string xxx represents the command identified by the arguments. This +can be used to create aliases or to handle multiword generators. +For example, + + //go:generate -command yacc go tool yacc + +specifies that the command "yacc" represents the generator +"go tool yacc". + +Generate processes packages in the order given on the command line, +one at a time. If the command line lists .go files, they are treated +as a single package. Within a package, generate processes the +source files in a package in file name order, one at a time. Within +a source file, generate runs generators in the order they appear +in the file, one at a time. + +If any generator returns an error exit status, "go generate" skips +all further processing for that package. + +The generator is run in the package's source directory. + +Go generate accepts one specific flag: + + -run="" + if non-empty, specifies a regular expression to + select directives whose command 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 +processed. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +For more about specifying packages, see 'go help packages'. + `, +} + +var generateRunFlag string // generate -run flag + +func init() { + addBuildFlags(cmdGenerate) + cmdGenerate.Flag.StringVar(&generateRunFlag, "run", "", "") +} + +func runGenerate(cmd *Command, args []string) { + // Even if the arguments are .go files, this loop suffices. + for _, pkg := range packages(args) { + for _, file := range pkg.gofiles { + if !generate(pkg.Name, file) { + break + } + } + } +} + +// generate runs the generation directives for a single file. +func generate(pkg, absFile string) bool { + fd, err := os.Open(absFile) + if err != nil { + log.Fatalf("generate: %s", err) + } + defer fd.Close() + g := &Generator{ + r: fd, + path: absFile, + pkg: pkg, + commands: make(map[string][]string), + } + return g.run() +} + +// A Generator represents the state of a single Go source file +// being scanned for generator commands. +type Generator struct { + r io.Reader + path string // full rooted path name. + dir string // full rooted directory of file. + file string // base name of file. + pkg string + commands map[string][]string + lineNum int +} + +// run runs the generators in the current file. +func (g *Generator) run() (ok bool) { + // Processing below here calls g.errorf on failure, which does panic(stop). + // If we encounter an error, we abort the package. + defer func() { + e := recover() + if e != nil { + ok = false + if e != stop { + panic(e) + } + setExitStatus(1) + } + }() + g.dir, g.file = filepath.Split(g.path) + g.dir = filepath.Clean(g.dir) // No final separator please. + if buildV { + fmt.Fprintf(os.Stderr, "%s\n", shortPath(g.path)) + } + + // Scan for lines that start "//go:generate". + // Can't use bufio.Scanner because it can't handle long lines, + // which are likely to appear when using generate. + input := bufio.NewReader(g.r) + var err error + // One line per loop. + for { + g.lineNum++ // 1-indexed. + var buf []byte + buf, err = input.ReadSlice('\n') + if err == bufio.ErrBufferFull { + // Line too long - consume and ignore. + if isGoGenerate(buf) { + g.errorf("directive too long") + } + for err == bufio.ErrBufferFull { + _, err = input.ReadSlice('\n') + } + if err != nil { + break + } + continue + } + + if err != nil { + // Check for marker at EOF without final \n. + if err == io.EOF && isGoGenerate(buf) { + err = io.ErrUnexpectedEOF + } + break + } + + if !isGoGenerate(buf) { + continue + } + + words := g.split(string(buf)) + if len(words) == 0 { + g.errorf("no arguments to directive") + } + if words[0] == "-command" { + g.setShorthand(words) + continue + } + // Run the command line. + if buildN || buildX { + fmt.Fprintf(os.Stderr, "%s\n", strings.Join(words, " ")) + } + if buildN { + continue + } + g.exec(words) + } + if err != nil && err != io.EOF { + g.errorf("error reading %s: %s", shortPath(g.path), err) + } + return true +} + +func isGoGenerate(buf []byte) bool { + return bytes.HasPrefix(buf, []byte("//go:generate ")) || bytes.HasPrefix(buf, []byte("//go:generate\t")) +} + +// split breaks the line into words, evaluating quoted +// strings and evaluating environment variables. +// The initial //go:generate element is present in line. +func (g *Generator) split(line string) []string { + // Parse line, obeying quoted strings. + var words []string + line = line[len("//go:generate ") : len(line)-1] // Drop preamble and final newline. + // One (possibly quoted) word per iteration. +Words: + for { + line = strings.TrimLeft(line, " \t") + if len(line) == 0 { + break + } + if line[0] == '"' { + for i := 1; i < len(line); i++ { + c := line[i] // Only looking for ASCII so this is OK. + switch c { + case '\\': + if i+1 == len(line) { + g.errorf("bad backslash") + } + i++ // Absorb next byte (If it's a multibyte we'll get an error in Unquote). + case '"': + word, err := strconv.Unquote(line[0 : i+1]) + if err != nil { + g.errorf("bad quoted string") + } + words = append(words, word) + line = line[i+1:] + // Check the next character is space or end of line. + if len(line) > 0 && line[0] != ' ' && line[0] != '\t' { + g.errorf("expect space after quoted argument") + } + continue Words + } + } + g.errorf("mismatched quoted string") + } + i := strings.IndexAny(line, " \t") + if i < 0 { + i = len(line) + } + words = append(words, line[0:i]) + line = line[i:] + } + // Substitute command if required. + if len(words) > 0 && g.commands[words[0]] != nil { + // Replace 0th word by command substitution. + words = append(g.commands[words[0]], words[1:]...) + } + // Substitute environment variables. + for i, word := range words { + words[i] = g.expandEnv(word) + } + return words +} + +var stop = fmt.Errorf("error in generation") + +// errorf logs an error message prefixed with the file and line number. +// It then exits the program (with exit status 1) because generation stops +// at the first error. +func (g *Generator) errorf(format string, args ...interface{}) { + fmt.Fprintf(os.Stderr, "%s:%d: %s\n", shortPath(g.path), g.lineNum, + fmt.Sprintf(format, args...)) + panic(stop) +} + +// expandEnv expands any $XXX invocations in word. +func (g *Generator) expandEnv(word string) string { + if !strings.ContainsRune(word, '$') { + return 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. +func (g *Generator) identLength(word string) int { + for i, r := range word { + if r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) { + continue + } + return i + } + return len(word) +} + +// setShorthand installs a new shorthand as defined by a -command directive. +func (g *Generator) setShorthand(words []string) { + // Create command shorthand. + if len(words) == 1 { + g.errorf("no command specified for -command") + } + command := words[1] + if g.commands[command] != nil { + g.errorf("command %q defined multiply defined", command) + } + g.commands[command] = words[2:len(words):len(words)] // force later append to make copy +} + +// exec runs the command specified by the argument. The first word is +// the command name itself. +func (g *Generator) exec(words []string) { + cmd := exec.Command(words[0], words[1:]...) + // Standard in and out of generator should be the usual. + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + // Run the command in the package directory. + cmd.Dir = g.dir + env := []string{ + "GOARCH=" + runtime.GOARCH, + "GOOS=" + runtime.GOOS, + "GOFILE=" + g.file, + "GOPACKAGE=" + g.pkg, + } + cmd.Env = mergeEnvLists(env, os.Environ()) + err := cmd.Run() + if err != nil { + g.errorf("running %q: %s", words[0], err) + } +} diff --git a/src/cmd/go/generate_test.go b/src/cmd/go/generate_test.go new file mode 100644 index 000000000..660ebabbe --- /dev/null +++ b/src/cmd/go/generate_test.go @@ -0,0 +1,48 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "reflect" + "runtime" + "testing" +) + +type splitTest struct { + in string + out []string +} + +var splitTests = []splitTest{ + {"", nil}, + {"x", []string{"x"}}, + {" a b\tc ", []string{"a", "b", "c"}}, + {` " a " `, []string{" a "}}, + {"$GOARCH", []string{runtime.GOARCH}}, + {"$GOOS", []string{runtime.GOOS}}, + {"$GOFILE", []string{"proc.go"}}, + {"$GOPACKAGE", []string{"sys"}}, + {"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}}, + {"/$XXNOTDEFINED/", []string{"//"}}, + {"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}}, +} + +func TestGenerateCommandParse(t *testing.T) { + g := &Generator{ + r: nil, // Unused here. + path: "/usr/ken/sys/proc.go", + dir: "/usr/ken/sys", + file: "proc.go", + pkg: "sys", + commands: make(map[string][]string), + } + g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"}) + for _, test := range splitTests { + got := g.split("//go:generate " + test.in + "\n") + if !reflect.DeepEqual(got, test.out) { + t.Errorf("split(%q): got %q expected %q", test.in, got, test.out) + } + } +} diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go index e708fcf77..86e169761 100644 --- a/src/cmd/go/get.go +++ b/src/cmd/go/get.go @@ -16,7 +16,7 @@ import ( ) var cmdGet = &Command{ - UsageLine: "get [-d] [-fix] [-t] [-u] [build flags] [packages]", + UsageLine: "get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages]", Short: "download and install packages and dependencies", Long: ` Get downloads and installs the packages named by the import paths, @@ -25,6 +25,11 @@ along with their dependencies. The -d flag instructs get to stop after downloading the packages; that is, it instructs get not to install the packages. +The -f flag, valid only when -u is set, forces get -u not to verify that +each package has been checked out from the source control repository +implied by its import path. This can be useful if the source is a local fork +of the original. + The -fix flag instructs get to run the fix tool on the downloaded packages before resolving dependencies or building the code. @@ -53,6 +58,7 @@ See also: go build, go install, go clean. } var getD = cmdGet.Flag.Bool("d", false, "") +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, "") @@ -63,6 +69,10 @@ func init() { } func runGet(cmd *Command, args []string) { + if *getF && !*getU { + fatalf("go get: cannot use -f flag without -u") + } + // Phase 1. Download/update. var stk importStack for _, arg := range downloadPaths(args) { @@ -151,7 +161,9 @@ func download(arg string, stk *importStack, getTestDeps bool) { } // Only process each package once. - if downloadCache[arg] { + // (Unless we're fetching test dependencies for this package, + // in which case we want to process it again.) + if downloadCache[arg] && !getTestDeps { return } downloadCache[arg] = true @@ -264,6 +276,25 @@ func downloadPackage(p *Package) error { return err } repo = "" // should be unused; make distinctive + + // Double-check where it came from. + if *getU && vcs.remoteRepo != nil && !*getF { + dir := filepath.Join(p.build.SrcRoot, rootPath) + if remote, err := vcs.remoteRepo(vcs, dir); err == nil { + if rr, err := repoRootForImportPath(p.ImportPath); err == nil { + repo := rr.repo + if rr.vcs.resolveRepo != nil { + resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo) + if err == nil { + repo = resolved + } + } + if remote != repo { + return fmt.Errorf("%s is from %s, should be from %s", dir, remote, repo) + } + } + } + } } else { // Analyze the import path to determine the version control system, // repository, and the import path for the root of the repository. diff --git a/src/cmd/go/go_windows_test.go b/src/cmd/go/go_windows_test.go new file mode 100644 index 000000000..53d695ccc --- /dev/null +++ b/src/cmd/go/go_windows_test.go @@ -0,0 +1,55 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +func TestAbsolutePath(t *testing.T) { + tmp, err := ioutil.TempDir("", "TestAbsolutePath") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + + file := filepath.Join(tmp, "a.go") + err = ioutil.WriteFile(file, []byte{}, 0644) + if err != nil { + t.Fatal(err) + } + dir := filepath.Join(tmp, "dir") + err = os.Mkdir(dir, 0777) + if err != nil { + t.Fatal(err) + } + + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + defer os.Chdir(wd) + + // Chdir so current directory and a.go reside on the same drive. + err = os.Chdir(dir) + if err != nil { + t.Fatal(err) + } + + noVolume := file[len(filepath.VolumeName(file)):] + wrongPath := filepath.Join(dir, noVolume) + output, err := exec.Command("go", "build", noVolume).CombinedOutput() + if err == nil { + t.Fatal("build should fail") + } + if strings.Contains(string(output), wrongPath) { + t.Fatalf("wrong output found: %v %v", err, string(output)) + } +} diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go index 40da7e1f5..c590fdb37 100644 --- a/src/cmd/go/help.go +++ b/src/cmd/go/help.go @@ -81,7 +81,8 @@ single directory, the command is applied to a single synthesized package made up of exactly those files, ignoring any build constraints in those files and ignoring any other files in the directory. -File names that begin with "." or "_" are ignored by the go tool. +Directory and file names that begin with "." or "_" are ignored +by the go tool, as are directories named "testdata". `, } @@ -154,6 +155,11 @@ A few common code hosting sites have special syntax: import "launchpad.net/~user/project/branch" import "launchpad.net/~user/project/branch/sub/directory" + IBM DevOps Services (Git) + + import "hub.jazz.net/git/user/project" + import "hub.jazz.net/git/user/project/sub/directory" + For code hosted on other servers, import paths may either be qualified with the version control type, or the go tool can dynamically fetch the import path over https/http and discover where the code resides @@ -229,7 +235,26 @@ listed in the GOPATH environment variable (see 'go help gopath'). The go command attempts to download the version of the package appropriate for the Go release being used. -Run 'go help install' for more. +Run 'go help get' for more. + +Import path checking + +When the custom import path feature described above redirects to a +known code hosting site, each of the resulting packages has two possible +import paths, using the custom domain or the known hosting site. + +A package statement is said to have an "import comment" if it is immediately +followed (before the next newline) by a comment of one of these two forms: + + package math // import "path" + package math /* import "path" */ + +The go command will refuse to install a package with an import comment +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. + +See https://golang.org/s/go14customimport for details. `, } diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go index 0ead43502..fbf96167f 100644 --- a/src/cmd/go/list.go +++ b/src/cmd/go/list.go @@ -30,28 +30,29 @@ syntax of package template. The default output is equivalent to -f '{{.ImportPath}}'. The struct being passed to the template is: type Package struct { - Dir string // directory containing package sources - ImportPath string // import path of package in dir - Name string // package name - Doc string // package documentation string - Target string // install path - 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? - Root string // Go root or Go path dir containing this package + Dir string // directory containing package sources + ImportPath string // import path of package in dir + ImportComment string // path in import comment on package statement + Name string // package name + Doc string // package documentation string + Target string // install path + 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? + Root string // Go root or Go path dir containing this package // Source files - GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) - CgoFiles []string // .go sources files that import "C" + GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string // .go sources files that import "C" IgnoredGoFiles []string // .go sources ignored due to build constraints - CFiles []string // .c source files - CXXFiles []string // .cc, .cxx and .cpp source files - MFiles []string // .m source files - HFiles []string // .h, .hh, .hpp and .hxx source files - SFiles []string // .s source files - SwigFiles []string // .swig files - SwigCXXFiles []string // .swigcxx files - SysoFiles []string // .syso object files to add to archive + CFiles []string // .c source files + CXXFiles []string // .cc, .cxx and .cpp source files + MFiles []string // .m source files + HFiles []string // .h, .hh, .hpp and .hxx source files + SFiles []string // .s source files + SwigFiles []string // .swig files + SwigCXXFiles []string // .swigcxx files + SysoFiles []string // .syso object files to add to archive // Cgo directives CgoCFLAGS []string // cgo: flags for C compiler diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 5b1194aaa..9691f39c7 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -79,6 +79,7 @@ var commands = []*Command{ cmdEnv, cmdFix, cmdFmt, + cmdGenerate, cmdGet, cmdInstall, cmdList, @@ -536,7 +537,7 @@ func matchPackages(pattern string) []string { }) for _, src := range buildContext.SrcDirs() { - if pattern == "std" && src != gorootSrcPkg { + if pattern == "std" && src != gorootSrc { continue } src = filepath.Clean(src) + string(filepath.Separator) @@ -618,7 +619,7 @@ func matchPackagesInFS(pattern string) []string { // The initial case is not Cleaned, though, so we do this explicitly. // // This converts a path like "./io/" to "io". Without this step, running - // "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io + // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io // package, because prepending the prefix "./" to the unclean path would // result in "././io", and match("././io") returns false. path = filepath.Clean(path) diff --git a/src/cmd/go/mkdoc.sh b/src/cmd/go/mkdoc.sh index 12fd7ba3e..e15e8809c 100755 --- a/src/cmd/go/mkdoc.sh +++ b/src/cmd/go/mkdoc.sh @@ -4,6 +4,6 @@ # license that can be found in the LICENSE file. go install # So the next line will produce updated documentation. -go help documentation > doc.go +go help documentation | sed 's; \*/; * /;' >doc.go gofmt -w doc.go diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go index d45df265b..b71feb7a6 100644 --- a/src/cmd/go/pkg.go +++ b/src/cmd/go/pkg.go @@ -14,6 +14,7 @@ import ( "os" pathpkg "path" "path/filepath" + "runtime" "sort" "strings" "time" @@ -25,16 +26,17 @@ type Package struct { // Note: These fields are part of the go command's public API. // See list.go. It is okay to add fields, but not to change or // remove existing ones. Keep in sync with list.go - Dir string `json:",omitempty"` // directory containing package sources - ImportPath string `json:",omitempty"` // import path of package in dir - Name string `json:",omitempty"` // package name - Doc string `json:",omitempty"` // package documentation string - Target string `json:",omitempty"` // install path - Goroot bool `json:",omitempty"` // is this package found in the Go root? - Standard bool `json:",omitempty"` // is this package part of the standard Go library? - Stale bool `json:",omitempty"` // would 'go install' do anything for this package? - Root string `json:",omitempty"` // Go root or Go path dir containing this package - ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory + Dir string `json:",omitempty"` // directory containing package sources + ImportPath string `json:",omitempty"` // import path of package in dir + ImportComment string `json:",omitempty"` // path in import comment on package statement + Name string `json:",omitempty"` // package name + Doc string `json:",omitempty"` // package documentation string + Target string `json:",omitempty"` // install path + Goroot bool `json:",omitempty"` // is this package found in the Go root? + Standard bool `json:",omitempty"` // is this package part of the standard Go library? + Stale bool `json:",omitempty"` // would 'go install' do anything for this package? + Root string `json:",omitempty"` // Go root or Go path dir containing this package + ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory // Source files GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) @@ -103,6 +105,7 @@ func (p *Package) copyBuild(pp *build.Package) { p.Dir = pp.Dir p.ImportPath = pp.ImportPath + p.ImportComment = pp.ImportComment p.Name = pp.Name p.Doc = pp.Doc p.Root = pp.Root @@ -218,7 +221,7 @@ func dirToImportPath(dir string) string { } func makeImportValid(r rune) rune { - // Should match Go spec, compilers, and ../../pkg/go/parser/parser.go:/isValidImport. + // Should match Go spec, compilers, and ../../go/parser/parser.go:/isValidImport. const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) { return '_' @@ -244,6 +247,9 @@ func loadImport(path string, srcDir string, stk *importStack, importPos []token. importPath = dirToImportPath(filepath.Join(srcDir, path)) } if p := packageCache[importPath]; p != nil { + if perr := disallowInternal(srcDir, p, stk); perr != p { + return perr + } return reusePackage(p, stk) } @@ -258,11 +264,14 @@ func loadImport(path string, srcDir string, stk *importStack, importPos []token. // // TODO: After Go 1, decide when to pass build.AllowBinary here. // See issue 3268 for mistakes to avoid. - bp, err := buildContext.Import(path, srcDir, 0) + bp, err := buildContext.Import(path, srcDir, build.ImportComment) bp.ImportPath = importPath if gobin != "" { bp.BinDir = gobin } + if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path { + err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment) + } p.load(stk, bp, err) if p.Error != nil && len(importPos) > 0 { pos := importPos[0] @@ -270,6 +279,10 @@ func loadImport(path string, srcDir string, stk *importStack, importPos []token. p.Error.Pos = pos.String() } + if perr := disallowInternal(srcDir, p, stk); perr != p { + return perr + } + return p } @@ -298,12 +311,82 @@ func reusePackage(p *Package, stk *importStack) *Package { return p } +// disallowInternal checks that srcDir is allowed to import p. +// If the import is allowed, disallowInternal returns the original package p. +// If not, it returns a new package containing just an appropriate error. +func disallowInternal(srcDir string, p *Package, stk *importStack) *Package { + // golang.org/s/go14internal: + // An import of a path containing the element “internal” + // is disallowed if the importing code is outside the tree + // rooted at the parent of the “internal” directory. + // + // ... For Go 1.4, we will implement the rule first for $GOROOT, but not $GOPATH. + + // Only applies to $GOROOT. + if !p.Standard { + return p + } + + // The stack includes p.ImportPath. + // If that's the only thing on the stack, we started + // with a name given on the command line, not an + // import. Anything listed on the command line is fine. + if len(*stk) == 1 { + return p + } + + // Check for "internal" element: four cases depending on begin of string and/or end of string. + i, ok := findInternal(p.ImportPath) + if !ok { + return p + } + + // Internal is present. + // Map import path back to directory corresponding to parent of internal. + if i > 0 { + i-- // rewind over slash in ".../internal" + } + parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)] + if hasPathPrefix(filepath.ToSlash(srcDir), filepath.ToSlash(parent)) { + return p + } + + // Internal is present, and srcDir is outside parent's tree. Not allowed. + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.copy(), + Err: "use of internal package not allowed", + } + perr.Incomplete = true + return &perr +} + +// findInternal looks for the final "internal" path element in the given import path. +// If there isn't one, findInternal returns ok=false. +// Otherwise, findInternal returns ok=true and the index of the "internal". +func findInternal(path string) (index int, ok bool) { + // Four cases, depending on internal at start/end of string or not. + // The order matters: we must return the index of the final element, + // because the final one produces the most restrictive requirement + // on the importer. + switch { + case strings.HasSuffix(path, "/internal"): + return len(path) - len("internal"), true + case strings.Contains(path, "/internal/"): + return strings.LastIndex(path, "/internal/") + 1, true + case path == "internal", strings.HasPrefix(path, "internal/"): + return 0, true + } + return 0, false +} + type targetDir int const ( - toRoot targetDir = iota // to bin dir inside package root (default) - toTool // GOROOT/pkg/tool - toBin // GOROOT/bin + toRoot targetDir = iota // to bin dir inside package root (default) + toTool // GOROOT/pkg/tool + toBin // GOROOT/bin + stalePath // the old import path; fail to build ) // goTools is a map of Go program import path to install target directory. @@ -316,10 +399,14 @@ var goTools = map[string]targetDir{ "cmd/nm": toTool, "cmd/objdump": toTool, "cmd/pack": toTool, + "cmd/pprof": toTool, "cmd/yacc": toTool, - "code.google.com/p/go.tools/cmd/cover": toTool, - "code.google.com/p/go.tools/cmd/godoc": toBin, - "code.google.com/p/go.tools/cmd/vet": toTool, + "golang.org/x/tools/cmd/cover": toTool, + "golang.org/x/tools/cmd/godoc": toBin, + "golang.org/x/tools/cmd/vet": toTool, + "code.google.com/p/go.tools/cmd/cover": stalePath, + "code.google.com/p/go.tools/cmd/godoc": stalePath, + "code.google.com/p/go.tools/cmd/vet": stalePath, } // expandScanner expands a scanner.List error into all the errors in the list. @@ -380,6 +467,13 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package } if p.Name == "main" { + // Report an error when the old code.google.com/p/go.tools paths are used. + if goTools[p.ImportPath] == stalePath { + newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1) + e := fmt.Sprintf("the %v command has moved; use %v instead.", p.ImportPath, newPath) + p.Error = &PackageError{Err: e} + return p + } _, elem := filepath.Split(p.Dir) full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH { @@ -482,7 +576,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package // Build list of imported packages and full dependency list. imports := make([]*Package, 0, len(p.Imports)) - deps := make(map[string]bool) + deps := make(map[string]*Package) for i, path := range importPaths { if path == "C" { continue @@ -502,10 +596,10 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package path = p1.ImportPath importPaths[i] = path } - deps[path] = true + deps[path] = p1 imports = append(imports, p1) - for _, dep := range p1.Deps { - deps[dep] = true + for _, dep := range p1.deps { + deps[dep.ImportPath] = dep } if p1.Incomplete { p.Incomplete = true @@ -519,7 +613,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package } sort.Strings(p.Deps) for _, dep := range p.Deps { - p1 := packageCache[dep] + p1 := deps[dep] if p1 == nil { panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath) } @@ -535,6 +629,16 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package } p.Target = p.target + // Check for C code compiled with Plan 9 C compiler. + // No longer allowed except in runtime and runtime/cgo, for now. + if len(p.CFiles) > 0 && !p.usesCgo() && (!p.Standard || p.ImportPath != "runtime") { + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: fmt.Sprintf("C source files not allowed when not using cgo: %s", strings.Join(p.CFiles, " ")), + } + return p + } + // In the absence of errors lower in the dependency tree, // check for case-insensitive collisions of import paths. if len(p.DepsErrors) == 0 { @@ -596,6 +700,12 @@ func computeStale(pkgs ...*Package) { } } +// The runtime version string takes one of two forms: +// "go1.X[.Y]" for Go releases, and "devel +hash" at tip. +// Determine whether we are in a released copy by +// inspecting the version. +var isGoRelease = strings.HasPrefix(runtime.Version(), "go1") + // isStale reports whether package p needs to be rebuilt. func isStale(p *Package, topRoot map[string]bool) bool { if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") { @@ -616,7 +726,16 @@ func isStale(p *Package, topRoot map[string]bool) bool { return false } - if buildA || p.target == "" || p.Stale { + // If we are running a release copy of Go, do not rebuild the standard packages. + // They may not be writable anyway, but they are certainly not changing. + // This makes 'go build -a' skip the standard packages when using an official release. + // See issue 4106 and issue 8290. + pkgBuildA := buildA + if p.Standard && isGoRelease { + pkgBuildA = false + } + + if pkgBuildA || p.target == "" || p.Stale { return true } @@ -704,24 +823,13 @@ func loadPackage(arg string, stk *importStack) *Package { arg = sub } } - if strings.HasPrefix(arg, "cmd/") { + if strings.HasPrefix(arg, "cmd/") && !strings.Contains(arg[4:], "/") { if p := cmdCache[arg]; p != nil { return p } stk.push(arg) defer stk.pop() - if strings.Contains(arg[4:], "/") { - p := &Package{ - Error: &PackageError{ - ImportStack: stk.copy(), - Err: fmt.Sprintf("invalid import path: cmd/... is reserved for Go commands"), - hard: true, - }, - } - return p - } - bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0) bp.ImportPath = arg bp.Goroot = true diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash index 0060ce218..e0f066f18 100755 --- a/src/cmd/go/test.bash +++ b/src/cmd/go/test.bash @@ -4,18 +4,22 @@ # license that can be found in the LICENSE file. set -e -go build -o testgo +go build -tags testgo -o testgo go() { echo TEST ERROR: ran go, not testgo: go "$@" >&2 exit 2 } started=false +testdesc="" +nl=" +" TEST() { if $started; then stop fi echo TEST: "$@" + testdesc="$@" started=true ok=true } @@ -29,6 +33,7 @@ stop() { echo PASS else echo FAIL + testfail="$testfail $testdesc$nl" allok=false fi } @@ -55,12 +60,63 @@ if ! grep -q "^$fn:" $d/err.out; then fi rm -r $d +TEST 'program name in crash messages' +linker=$(./testgo env GOCHAR)l +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +./testgo build -ldflags -crash_for_testing $(./testgo env GOROOT)/test/helloworld.go 2>$d/err.out || true +if ! grep -q "/tool/.*/$linker" $d/err.out; then + echo "missing linker name in error message" + cat $d/err.out + ok=false +fi +rm -r $d + +TEST broken tests without Test functions all fail +d=$(mktemp -d -t testgoXXX) +./testgo test ./testdata/src/badtest/... >$d/err 2>&1 || true +if grep -q '^ok' $d/err; then + echo test passed unexpectedly: + grep '^ok' $d/err + ok=false +elif ! grep -q 'FAIL.*badtest/badexec' $d/err || ! grep -q 'FAIL.*badtest/badsyntax' $d/err || ! grep -q 'FAIL.*badtest/badvar' $d/err; then + echo test did not run everything + cat $d/err + ok=false +fi +rm -rf $d + +TEST 'go build -a in dev branch' +./testgo install math || ok=false # should be up to date already but just in case +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +if ! TESTGO_IS_GO_RELEASE=0 ./testgo build -v -a math 2>$d/err.out; then + cat $d/err.out + ok=false +elif ! grep -q runtime $d/err.out; then + echo "testgo build -a math in dev branch DID NOT build runtime, but should have" + cat $d/err.out + ok=false +fi +rm -r $d + +TEST 'go build -a in release branch' +./testgo install math || ok=false # should be up to date already but just in case +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +if ! TESTGO_IS_GO_RELEASE=1 ./testgo build -v -a math 2>$d/err.out; then + cat $d/err.out + ok=false +elif grep -q runtime $d/err.out; then + echo "testgo build -a math in dev branch DID build runtime, but should NOT have" + cat $d/err.out + ok=false +fi +rm -r $d + # Test local (./) imports. testlocal() { local="$1" TEST local imports $2 '(easy)' - ./testgo build -o hello "testdata/$local/easy.go" - ./hello >hello.out + ./testgo build -o hello "testdata/$local/easy.go" || ok=false + ./hello >hello.out || ok=false if ! grep -q '^easysub\.Hello' hello.out; then echo "testdata/$local/easy.go did not generate expected output" cat hello.out @@ -68,8 +124,8 @@ testlocal() { fi TEST local imports $2 '(easysub)' - ./testgo build -o hello "testdata/$local/easysub/main.go" - ./hello >hello.out + ./testgo build -o hello "testdata/$local/easysub/main.go" || ok=false + ./hello >hello.out || ok=false if ! grep -q '^easysub\.Hello' hello.out; then echo "testdata/$local/easysub/main.go did not generate expected output" cat hello.out @@ -77,8 +133,8 @@ testlocal() { fi TEST local imports $2 '(hard)' - ./testgo build -o hello "testdata/$local/hard.go" - ./hello >hello.out + ./testgo build -o hello "testdata/$local/hard.go" || ok=false + ./hello >hello.out || ok=false if ! grep -q '^sub\.Hello' hello.out || ! grep -q '^subsub\.Hello' hello.out ; then echo "testdata/$local/hard.go did not generate expected output" cat hello.out @@ -105,6 +161,132 @@ cp -R testdata/local "testdata/$bad" testlocal "$bad" 'with bad characters in path' rm -rf "testdata/$bad" +TEST 'internal packages in $GOROOT are respected' +if ./testgo build -v ./testdata/testinternal >testdata/std.out 2>&1; then + echo "go build ./testdata/testinternal succeeded incorrectly" + ok=false +elif ! grep 'use of internal package not allowed' testdata/std.out >/dev/null; then + echo "wrong error message for testdata/testinternal" + cat std.out + ok=false +fi + +TEST 'internal packages outside $GOROOT are not respected' +if ! ./testgo build -v ./testdata/testinternal2; then + echo "go build ./testdata/testinternal2 failed" + ok=false +fi + +# Test that 'go get -u' reports moved packages. +testmove() { + vcs=$1 + url=$2 + base=$3 + config=$4 + + TEST go get -u notices $vcs package that moved + d=$(mktemp -d -t testgoXXX) + mkdir -p $d/src + if ! GOPATH=$d ./testgo get -d $url; then + echo 'go get -d $url failed' + ok=false + elif ! GOPATH=$d ./testgo get -d -u $url; then + echo 'go get -d -u $url failed' + ok=false + else + set +e + case "$vcs" in + svn) + # SVN doesn't believe in text files so we can't just edit the config. + # Check out a different repo into the wrong place. + rm -rf $d/src/code.google.com/p/rsc-svn + GOPATH=$d ./testgo get -d -u code.google.com/p/rsc-svn2/trunk + mv $d/src/code.google.com/p/rsc-svn2 $d/src/code.google.com/p/rsc-svn + ;; + *) + echo '1,$s;'"$base"';'"$base"'XXX; +w +q' | ed $d/src/$config >/dev/null 2>&1 + esac + set -e + + if GOPATH=$d ./testgo get -d -u $url 2>$d/err; then + echo "go get -d -u $url succeeded with wrong remote repo" + cat $d/err + ok=false + elif ! grep 'should be from' $d/err >/dev/null; then + echo "go get -d -u $url failed for wrong reason" + cat $d/err + ok=false + fi + + if GOPATH=$d ./testgo get -d -f -u $url 2>$d/err; then + echo "go get -d -u $url succeeded with wrong remote repo" + cat $d/err + ok=false + elif ! egrep -i 'validating server certificate|not found' $d/err >/dev/null; then + echo "go get -d -f -u $url failed for wrong reason" + cat $d/err + ok=false + fi + fi + rm -rf $d +} + +testmove hg rsc.io/x86/x86asm x86 rsc.io/x86/.hg/hgrc +testmove git rsc.io/pdf pdf rsc.io/pdf/.git/config +testmove svn code.google.com/p/rsc-svn/trunk - - + +export GOPATH=$(pwd)/testdata/importcom +TEST 'import comment - match' +if ! ./testgo build ./testdata/importcom/works.go; then + echo 'go build ./testdata/importcom/works.go failed' + ok=false +fi +TEST 'import comment - mismatch' +if ./testgo build ./testdata/importcom/wrongplace.go 2>testdata/err; then + echo 'go build ./testdata/importcom/wrongplace.go suceeded' + ok=false +elif ! grep 'wrongplace expects import "my/x"' testdata/err >/dev/null; then + echo 'go build did not mention incorrect import:' + cat testdata/err + ok=false +fi +TEST 'import comment - syntax error' +if ./testgo build ./testdata/importcom/bad.go 2>testdata/err; then + echo 'go build ./testdata/importcom/bad.go suceeded' + ok=false +elif ! grep 'cannot parse import comment' testdata/err >/dev/null; then + echo 'go build did not mention syntax error:' + cat testdata/err + ok=false +fi +TEST 'import comment - conflict' +if ./testgo build ./testdata/importcom/conflict.go 2>testdata/err; then + echo 'go build ./testdata/importcom/conflict.go suceeded' + ok=false +elif ! grep 'found import comments' testdata/err >/dev/null; then + echo 'go build did not mention comment conflict:' + cat testdata/err + ok=false +fi +rm -f ./testdata/err +unset GOPATH + +export GOPATH=$(pwd)/testdata/src +TEST disallowed C source files +export GOPATH=$(pwd)/testdata +if ./testgo build badc 2>testdata/err; then + echo 'go build badc succeeded' + ok=false +elif ! grep 'C source files not allowed' testdata/err >/dev/null; then + echo 'go test did not say C source files not allowed:' + cat testdata/err + ok=false +fi +rm -f ./testdata/err +unset GOPATH + TEST error message for syntax error in test go file says FAIL export GOPATH=$(pwd)/testdata if ./testgo test syntaxerror 2>testdata/err; then @@ -251,20 +433,20 @@ TEST godoc installs into GOBIN d=$(mktemp -d -t testgoXXX) export GOPATH=$d mkdir $d/gobin -GOBIN=$d/gobin ./testgo get code.google.com/p/go.tools/cmd/godoc +GOBIN=$d/gobin ./testgo get golang.org/x/tools/cmd/godoc || ok=false if [ ! -x $d/gobin/godoc ]; then echo did not install godoc to '$GOBIN' - GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc + GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' golang.org/x/tools/cmd/godoc || true ok=false fi TEST godoc installs into GOROOT GOROOT=$(./testgo env GOROOT) rm -f $GOROOT/bin/godoc -./testgo install code.google.com/p/go.tools/cmd/godoc +./testgo install golang.org/x/tools/cmd/godoc || ok=false if [ ! -x $GOROOT/bin/godoc ]; then echo did not install godoc to '$GOROOT/bin' - ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc + ./testgo list -f 'Target: {{.Target}}' golang.org/x/tools/cmd/godoc || true ok=false fi @@ -272,36 +454,36 @@ TEST cmd/fix installs into tool GOOS=$(./testgo env GOOS) GOARCH=$(./testgo env GOARCH) rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix -./testgo install cmd/fix +./testgo install cmd/fix || ok=false if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then echo 'did not install cmd/fix to $GOROOT/pkg/tool' - GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix + GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix || true ok=false fi rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix -GOBIN=$d/gobin ./testgo install cmd/fix +GOBIN=$d/gobin ./testgo install cmd/fix || ok=false if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then echo 'did not install cmd/fix to $GOROOT/pkg/tool with $GOBIN set' - GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix + GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix || true ok=false fi TEST gopath program installs into GOBIN mkdir $d/src/progname echo 'package main; func main() {}' >$d/src/progname/p.go -GOBIN=$d/gobin ./testgo install progname +GOBIN=$d/gobin ./testgo install progname || ok=false if [ ! -x $d/gobin/progname ]; then echo 'did not install progname to $GOBIN/progname' - ./testgo list -f 'Target: {{.Target}}' cmd/api + ./testgo list -f 'Target: {{.Target}}' cmd/api || true ok=false fi rm -f $d/gobin/progname $d/bin/progname TEST gopath program installs into GOPATH/bin -./testgo install progname +./testgo install progname || ok=false if [ ! -x $d/bin/progname ]; then echo 'did not install progname to $GOPATH/bin/progname' - ./testgo list -f 'Target: {{.Target}}' progname + ./testgo list -f 'Target: {{.Target}}' progname || true ok=false fi @@ -330,7 +512,7 @@ fi # ensure that output of 'go list' is consistent between runs TEST go list is consistent -./testgo list std > test_std.list +./testgo list std > test_std.list || ok=false if ! ./testgo list std | cmp -s test_std.list - ; then echo "go list std ordering is inconsistent" ok=false @@ -378,9 +560,9 @@ fi # Test that without GOPATH set, go get should fail TEST without GOPATH, go get fails d=$(mktemp -d -t testgoXXX) -mkdir -p $d/src/pkg -if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then - echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset' +mkdir -p $d/src +if GOPATH= GOROOT=$d ./testgo get -d golang.org/x/codereview/cmd/hgpatch ; then + echo 'go get golang.org/x/codereview/cmd/hgpatch should not succeed with $GOPATH unset' ok=false fi rm -rf $d @@ -388,9 +570,9 @@ rm -rf $d # Test that with GOPATH=$GOROOT, go get should fail TEST with GOPATH=GOROOT, go get fails d=$(mktemp -d -t testgoXXX) -mkdir -p $d/src/pkg -if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then - echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT' +mkdir -p $d/src +if GOPATH=$d GOROOT=$d ./testgo get -d golang.org/x/codereview/cmd/hgpatch ; then + echo 'go get golang.org/x/codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT' ok=false fi rm -rf $d @@ -404,7 +586,7 @@ func main() { println(extern) } EOF -./testgo run -ldflags '-X main.extern "hello world"' $d/main.go 2>hello.out +./testgo run -ldflags '-X main.extern "hello world"' $d/main.go 2>hello.out || ok=false if ! grep -q '^hello world' hello.out; then echo "ldflags -X main.extern 'hello world' failed. Output:" cat hello.out @@ -420,6 +602,30 @@ if [ ! -x strings.test ]; then fi rm -f strings.prof strings.test +TEST go test -cpuprofile -o controls binary location +./testgo test -cpuprofile strings.prof -o mystrings.test strings || ok=false +if [ ! -x mystrings.test ]; then + echo "go test -cpuprofile -o mystrings.test did not create mystrings.test" + ok=false +fi +rm -f strings.prof mystrings.test + +TEST go test -c -o controls binary location +./testgo test -c -o mystrings.test strings || ok=false +if [ ! -x mystrings.test ]; then + echo "go test -c -o mystrings.test did not create mystrings.test" + ok=false +fi +rm -f mystrings.test + +TEST go test -o writes binary +./testgo test -o mystrings.test strings || ok=false +if [ ! -x mystrings.test ]; then + echo "go test -o mystrings.test did not create mystrings.test" + ok=false +fi +rm -f mystrings.test + TEST symlinks do not confuse go list '(issue 4568)' old=$(pwd) tmp=$(cd /tmp && pwd -P) @@ -522,37 +728,56 @@ elif ! grep "case-insensitive file name collision" $d/out >/dev/null; then fi TEST go get cover -./testgo get code.google.com/p/go.tools/cmd/cover || ok=false +./testgo get golang.org/x/tools/cmd/cover || ok=false unset GOPATH rm -rf $d +TEST go get -t "code.google.com/p/go-get-issue-8181/{a,b}" +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +export GOPATH=$d +if ./testgo get -t code.google.com/p/go-get-issue-8181/{a,b}; then + ./testgo list ... | grep go.tools/godoc > /dev/null || ok=false +else + ok=false +fi +unset GOPATH +rm -rf $d + TEST shadowing logic export GOPATH=$(pwd)/testdata/shadow/root1:$(pwd)/testdata/shadow/root2 # The math in root1 is not "math" because the standard math is. +set +e cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/math) -if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/pkg/math)" ]; then +set -e +if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/math)" ]; then echo shadowed math is not shadowed: "$cdir" ok=false fi # The foo in root1 is "foo". +set +e cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/foo) +set -e if [ "$cdir" != "(foo) ()" ]; then echo unshadowed foo is shadowed: "$cdir" ok=false fi # The foo in root2 is not "foo" because the foo in root1 got there first. +set +e cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root2/src/foo) +set -e if [ "$cdir" != "(_$(pwd)/testdata/shadow/root2/src/foo) ($(pwd)/testdata/shadow/root1/src/foo)" ]; then echo shadowed foo is not shadowed: "$cdir" ok=false fi # The error for go install should mention the conflicting directory. -err=$(! ./testgo install ./testdata/shadow/root2/src/foo 2>&1) +set +e +err=$(./testgo install ./testdata/shadow/root2/src/foo 2>&1) +set -e if [ "$err" != "go install: no install location for $(pwd)/testdata/shadow/root2/src/foo: hidden by $(pwd)/testdata/shadow/root1/src/foo" ]; then echo wrong shadowed install error: "$err" ok=false @@ -741,30 +966,46 @@ echo ' package foo func F() {} ' >$d/src/x/y/foo/foo.go +checkbar() { + desc="$1" + sleep 1 + touch $d/src/x/y/foo/foo.go + if ! ./testgo build -v -i x/y/bar &> $d/err; then + echo build -i "$1" failed + cat $d/err + ok=false + elif ! grep x/y/foo $d/err >/dev/null; then + echo first build -i "$1" did not build x/y/foo + cat $d/err + ok=false + fi + if ! ./testgo build -v -i x/y/bar &> $d/err; then + echo second build -i "$1" failed + cat $d/err + ok=false + elif grep x/y/foo $d/err >/dev/null; then + echo second build -i "$1" built x/y/foo + cat $d/err + ok=false + fi +} + echo ' package bar import "x/y/foo" func F() { foo.F() } ' >$d/src/x/y/bar/bar.go -if ! ./testgo build -v -i x/y/bar &> $d/err; then - echo build -i failed - cat $d/err - ok=false -elif ! grep x/y/foo $d/err >/dev/null; then - echo first build -i did not build x/y/foo - cat $d/err - ok=false -fi -if ! ./testgo build -v -i x/y/bar &> $d/err; then - echo second build -i failed - cat $d/err - ok=false -elif grep x/y/foo $d/err >/dev/null; then - echo second build -i built x/y/foo - cat $d/err - ok=false -fi -rm -rf $d +checkbar pkg + +TEST build -i installs dependencies for command +echo ' +package main +import "x/y/foo" +func main() { foo.F() } +' >$d/src/x/y/bar/bar.go +checkbar cmd + +rm -rf $d bar unset GOPATH TEST 'go build in test-only directory fails with a good error' @@ -799,13 +1040,74 @@ fi TEST 'go test xtestonly works' export GOPATH=$(pwd)/testdata -./testgo clean -i xtestonly +./testgo clean -i xtestonly || ok=false if ! ./testgo test xtestonly >/dev/null; then echo "go test xtestonly failed" ok=false fi unset GOPATH +TEST 'go test builds an xtest containing only non-runnable examples' +if ! ./testgo test -v ./testdata/norunexample > testdata/std.out; then + echo "go test ./testdata/norunexample failed" + ok=false +elif ! grep 'File with non-runnable example was built.' testdata/std.out > /dev/null; then + echo "file with non-runnable example was not built" + ok=false +fi + +TEST 'go generate handles simple command' +if ! ./testgo generate ./testdata/generate/test1.go > testdata/std.out; then + echo "go test ./testdata/generate/test1.go failed to run" + ok=false +elif ! grep 'Success' testdata/std.out > /dev/null; then + echo "go test ./testdata/generate/test1.go generated wrong output" + ok=false +fi + +TEST 'go generate handles command alias' +if ! ./testgo generate ./testdata/generate/test2.go > testdata/std.out; then + echo "go test ./testdata/generate/test2.go failed to run" + ok=false +elif ! grep 'Now is the time for all good men' testdata/std.out > /dev/null; then + echo "go test ./testdata/generate/test2.go generated wrong output" + ok=false +fi + +TEST 'go generate variable substitution' +if ! ./testgo generate ./testdata/generate/test3.go > testdata/std.out; then + echo "go test ./testdata/generate/test3.go failed to run" + ok=false +elif ! grep "$GOARCH test3.go p xyzp/test3.go/123" testdata/std.out > /dev/null; then + echo "go test ./testdata/generate/test3.go generated wrong output" + ok=false +fi + +TEST go get works with vanity wildcards +d=$(mktemp -d -t testgoXXX) +export GOPATH=$d +if ! ./testgo get -u rsc.io/pdf/...; then + ok=false +elif [ ! -x $d/bin/pdfpasswd ]; then + echo did not build rsc.io/pdf/pdfpasswd + ok=false +fi +unset GOPATH +rm -rf $d + +TEST go vet with external tests +d=$(mktemp -d -t testgoXXX) +export GOPATH=$(pwd)/testdata +if ./testgo vet vetpkg >$d/err 2>&1; then + echo "go vet vetpkg passes incorrectly" + ok=false +elif ! grep -q 'missing argument for Printf' $d/err; then + echo "go vet vetpkg did not find missing argument for Printf" + cat $d/err + ok=false +fi +unset GOPATH +rm -rf $d # clean up if $started; then stop; fi @@ -815,6 +1117,7 @@ rm -f testgo if $allok; then echo PASS else - echo FAIL + echo FAIL: + echo "$testfail" exit 1 fi diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go index 5935c98db..c81e40639 100644 --- a/src/cmd/go/test.go +++ b/src/cmd/go/test.go @@ -6,6 +6,7 @@ package main import ( "bytes" + "errors" "fmt" "go/ast" "go/build" @@ -48,7 +49,7 @@ It prints a summary of the test results in the format: followed by detailed output for each failed package. 'Go test' recompiles each package along with any files with names matching -the file pattern "*_test.go". +the file pattern "*_test.go". Files whose names begin with "_" (including "_test.go") or "." are ignored. These additional files can contain test functions, benchmark functions, and example functions. See 'go help testfunc' for more. @@ -65,16 +66,23 @@ non-test installation. In addition to the build flags, the flags handled by 'go test' itself are: - -c Compile the test binary to pkg.test but do not run it. - (Where pkg is the last element of the package's import path.) + -c + Compile the test binary to pkg.test but do not run it + (where pkg is the last element of the package's import path). + The file name can be changed with the -o flag. + + -exec xprog + Run the test binary using xprog. The behavior is the same as + in 'go run'. See 'go help run' for details. -i Install packages that are dependencies of the test. Do not run the test. - -exec xprog - Run the test binary using xprog. The behavior is the same as - in 'go run'. See 'go help run' for details. + -o file + 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. @@ -122,6 +130,7 @@ control the execution of any test: -blockprofile block.out Write a goroutine blocking profile to the specified file when all tests are complete. + Writes test binary as -c would. -blockprofilerate n Control the detail provided in goroutine blocking profiles by @@ -153,8 +162,7 @@ control the execution of any test: Sets -cover. -coverprofile cover.out - Write a coverage profile to the specified file after all tests - have passed. + Write a coverage profile to the file after all tests have passed. Sets -cover. -cpu 1,2,4 @@ -164,10 +172,11 @@ control the execution of any test: -cpuprofile cpu.out Write a CPU profile to the specified file before exiting. + Writes test binary as -c would. -memprofile mem.out - Write a memory profile to the specified file after all tests - have passed. + Write a memory profile to the file after all tests have passed. + Writes test binary as -c would. -memprofilerate n Enable more precise (and expensive) memory profiles by setting @@ -274,10 +283,10 @@ var ( testCoverMode string // -covermode flag testCoverPaths []string // -coverpkg flag testCoverPkgs []*Package // -coverpkg flag + testO string // -o flag testProfile bool // some profiling flag testNeedBinary bool // profile needs to keep binary around testV bool // -v flag - testFiles []string // -file flag(s) TODO: not respected testTimeout string // -timeout flag testArgs []string testBench bool @@ -291,6 +300,7 @@ var testMainDeps = map[string]bool{ // Dependencies for testmain. "testing": true, "regexp": true, + "os": true, } func runTest(cmd *Command, args []string) { @@ -308,6 +318,9 @@ func runTest(cmd *Command, args []string) { if testC && len(pkgs) != 1 { fatalf("cannot use -c flag with multiple packages") } + if testO != "" && len(pkgs) != 1 { + fatalf("cannot use -o flag with multiple packages") + } if testProfile && len(pkgs) != 1 { fatalf("cannot use test profile flag with multiple packages") } @@ -522,6 +535,13 @@ func contains(x []string, s string) bool { return false } +var windowsBadWords = []string{ + "install", + "patch", + "setup", + "update", +} + func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) { if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { build := b.action(modeBuild, modeBuild, p) @@ -687,7 +707,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, omitDWARF: !testC && !testNeedBinary, } - // The generated main also imports testing and regexp. + // The generated main also imports testing, regexp, and os. stk.push("testmain") for dep := range testMainDeps { if dep == ptest.ImportPath { @@ -723,11 +743,13 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, if err != nil { return nil, nil, nil, err } - if t.NeedTest || ptest.coverMode != "" { + if len(ptest.GoFiles) > 0 { pmain.imports = append(pmain.imports, ptest) + t.ImportTest = true } - if t.NeedXtest { + if pxtest != nil { pmain.imports = append(pmain.imports, pxtest) + t.ImportXtest = true } if ptest != p && localCover { @@ -779,17 +801,54 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, a.objdir = testDir + string(filepath.Separator) a.objpkg = filepath.Join(testDir, "main.a") a.target = filepath.Join(testDir, testBinary) + exeSuffix - pmainAction := a + if goos == "windows" { + // There are many reserved words on Windows that, + // if used in the name of an executable, cause Windows + // to try to ask for extra permissions. + // The word list includes setup, install, update, and patch, + // but it does not appear to be defined anywhere. + // We have run into this trying to run the + // go.codereview/patch tests. + // For package names containing those words, use test.test.exe + // instead of pkgname.test.exe. + // Note that this file name is only used in the Go command's + // temporary directory. If the -c or other flags are + // given, the code below will still use pkgname.test.exe. + // There are two user-visible effects of this change. + // First, you can actually run 'go test' in directories that + // have names that Windows thinks are installer-like, + // without getting a dialog box asking for more permissions. + // Second, in the Windows process listing during go test, + // the test shows up as test.test.exe, not pkgname.test.exe. + // That second one is a drawback, but it seems a small + // price to pay for the test running at all. + // If maintaining the list of bad words is too onerous, + // we could just do this always on Windows. + for _, bad := range windowsBadWords { + if strings.Contains(testBinary, bad) { + a.target = filepath.Join(testDir, "test.test") + exeSuffix + break + } + } + } + buildAction = a if testC || testNeedBinary { // -c or profiling flag: create action to copy binary to ./test.out. - runAction = &action{ + target := filepath.Join(cwd, testBinary+exeSuffix) + if testO != "" { + target = testO + if !filepath.IsAbs(target) { + target = filepath.Join(cwd, target) + } + } + buildAction = &action{ f: (*builder).install, - deps: []*action{pmainAction}, + deps: []*action{buildAction}, p: pmain, - target: filepath.Join(cwd, testBinary+exeSuffix), + target: target, } - pmainAction = runAction // in case we are running the test + runAction = buildAction // make sure runAction != nil even if not running test } if testC { printAction = &action{p: p, deps: []*action{runAction}} // nop @@ -797,7 +856,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, // run test runAction = &action{ f: (*builder).runTest, - deps: []*action{pmainAction}, + deps: []*action{buildAction}, p: p, ignoreFail: true, } @@ -813,7 +872,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, } } - return pmainAction, runAction, printAction, nil + return buildAction, runAction, printAction, nil } func testImportStack(top string, p *Package, target string) []string { @@ -1057,6 +1116,31 @@ func (b *builder) notest(a *action) error { return nil } +// isTestMain tells whether fn is a TestMain(m *testing.M) function. +func isTestMain(fn *ast.FuncDecl) bool { + if fn.Name.String() != "TestMain" || + fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || + fn.Type.Params == nil || + len(fn.Type.Params.List) != 1 || + len(fn.Type.Params.List[0].Names) > 1 { + return false + } + ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr) + if !ok { + return false + } + // We can't easily check that the type is *testing.M + // because we don't know how testing has been imported, + // but at least check that it's *M or *something.M. + if name, ok := ptr.X.(*ast.Ident); ok && name.Name == "M" { + return true + } + if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == "M" { + return true + } + return false +} + // isTest tells whether name looks like a test (or benchmark, according to prefix). // It is a Test (say) if there is a character after Test that is not a lower-case letter. // We don't want TesticularCancer. @@ -1082,12 +1166,12 @@ func loadTestFuncs(ptest *Package) (*testFuncs, error) { Package: ptest, } for _, file := range ptest.TestGoFiles { - if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.NeedTest); err != nil { + if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil { return nil, err } } for _, file := range ptest.XTestGoFiles { - if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.NeedXtest); err != nil { + if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil { return nil, err } } @@ -1110,13 +1194,16 @@ func writeTestmain(out string, t *testFuncs) error { } type testFuncs struct { - Tests []testFunc - Benchmarks []testFunc - Examples []testFunc - Package *Package - NeedTest bool - NeedXtest bool - Cover []coverInfo + Tests []testFunc + Benchmarks []testFunc + Examples []testFunc + TestMain *testFunc + Package *Package + ImportTest bool + NeedTest bool + ImportXtest bool + NeedXtest bool + Cover []coverInfo } func (t *testFuncs) CoverMode() string { @@ -1151,7 +1238,7 @@ type testFunc struct { var testFileSet = token.NewFileSet() -func (t *testFuncs) load(filename, pkg string, seen *bool) error { +func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments) if err != nil { return expandScanner(err) @@ -1166,17 +1253,24 @@ func (t *testFuncs) load(filename, pkg string, seen *bool) error { } name := n.Name.String() switch { + case isTestMain(n): + if t.TestMain != nil { + return errors.New("multiple definitions of TestMain") + } + t.TestMain = &testFunc{pkg, name, ""} + *doImport, *seen = true, true case isTest(name, "Test"): t.Tests = append(t.Tests, testFunc{pkg, name, ""}) - *seen = true + *doImport, *seen = true, true case isTest(name, "Benchmark"): t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""}) - *seen = true + *doImport, *seen = true, true } } ex := doc.Examples(f) sort.Sort(byOrder(ex)) for _, e := range ex { + *doImport = true // import test file whether executed or not if e.Output == "" && !e.EmptyOutput { // Don't run examples with no output. continue @@ -1197,14 +1291,17 @@ var testmainTmpl = template.Must(template.New("main").Parse(` package main import ( +{{if not .TestMain}} + "os" +{{end}} "regexp" "testing" -{{if .NeedTest}} - _test {{.Package.ImportPath | printf "%q"}} +{{if .ImportTest}} + {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}} {{end}} -{{if .NeedXtest}} - _xtest {{.Package.ImportPath | printf "%s_test" | printf "%q"}} +{{if .ImportXtest}} + {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}} {{end}} {{range $i, $p := .Cover}} _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} @@ -1291,7 +1388,12 @@ func main() { CoveredPackages: {{printf "%q" .Covered}}, }) {{end}} - testing.Main(matchString, tests, benchmarks, examples) + m := testing.MainStart(matchString, tests, benchmarks, examples) +{{with .TestMain}} + {{.Package}}.{{.Name}}(m) +{{else}} + os.Exit(m.Run()) +{{end}} } `)) diff --git a/src/cmd/go/testdata/generate/test1.go b/src/cmd/go/testdata/generate/test1.go new file mode 100644 index 000000000..1f05734f0 --- /dev/null +++ b/src/cmd/go/testdata/generate/test1.go @@ -0,0 +1,13 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Simple test for go generate. + +// We include a build tag that go generate should ignore. + +// +build ignore + +//go:generate echo Success + +package p diff --git a/src/cmd/go/testdata/generate/test2.go b/src/cmd/go/testdata/generate/test2.go new file mode 100644 index 000000000..ef1a3d951 --- /dev/null +++ b/src/cmd/go/testdata/generate/test2.go @@ -0,0 +1,10 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that go generate handles command aliases. + +//go:generate -command run echo Now is the time +//go:generate run for all good men + +package p diff --git a/src/cmd/go/testdata/generate/test3.go b/src/cmd/go/testdata/generate/test3.go new file mode 100644 index 000000000..41ffb7ea8 --- /dev/null +++ b/src/cmd/go/testdata/generate/test3.go @@ -0,0 +1,9 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test go generate variable substitution. + +//go:generate echo $GOARCH $GOFILE $GOPACKAGE xyz$GOPACKAGE/$GOFILE/123 + +package p diff --git a/src/cmd/go/testdata/importcom/bad.go b/src/cmd/go/testdata/importcom/bad.go new file mode 100644 index 000000000..e104c2e99 --- /dev/null +++ b/src/cmd/go/testdata/importcom/bad.go @@ -0,0 +1,3 @@ +package p + +import "bad" diff --git a/src/cmd/go/testdata/importcom/conflict.go b/src/cmd/go/testdata/importcom/conflict.go new file mode 100644 index 000000000..995556c51 --- /dev/null +++ b/src/cmd/go/testdata/importcom/conflict.go @@ -0,0 +1,3 @@ +package p + +import "conflict" diff --git a/src/cmd/go/testdata/importcom/src/bad/bad.go b/src/cmd/go/testdata/importcom/src/bad/bad.go new file mode 100644 index 000000000..bc51fd3fd --- /dev/null +++ b/src/cmd/go/testdata/importcom/src/bad/bad.go @@ -0,0 +1 @@ +package bad // import diff --git a/src/cmd/go/testdata/importcom/src/conflict/a.go b/src/cmd/go/testdata/importcom/src/conflict/a.go new file mode 100644 index 000000000..2d6770351 --- /dev/null +++ b/src/cmd/go/testdata/importcom/src/conflict/a.go @@ -0,0 +1 @@ +package conflict // import "a" diff --git a/src/cmd/go/testdata/importcom/src/conflict/b.go b/src/cmd/go/testdata/importcom/src/conflict/b.go new file mode 100644 index 000000000..8fcfb3c8b --- /dev/null +++ b/src/cmd/go/testdata/importcom/src/conflict/b.go @@ -0,0 +1 @@ +package conflict /* import "b" */ diff --git a/src/cmd/go/testdata/importcom/src/works/x/x.go b/src/cmd/go/testdata/importcom/src/works/x/x.go new file mode 100644 index 000000000..044c6eca8 --- /dev/null +++ b/src/cmd/go/testdata/importcom/src/works/x/x.go @@ -0,0 +1 @@ +package x // import "works/x" diff --git a/src/cmd/go/testdata/importcom/src/works/x/x1.go b/src/cmd/go/testdata/importcom/src/works/x/x1.go new file mode 100644 index 000000000..2449b29df --- /dev/null +++ b/src/cmd/go/testdata/importcom/src/works/x/x1.go @@ -0,0 +1 @@ +package x // important! not an import comment diff --git a/src/cmd/go/testdata/importcom/src/wrongplace/x.go b/src/cmd/go/testdata/importcom/src/wrongplace/x.go new file mode 100644 index 000000000..b89849da7 --- /dev/null +++ b/src/cmd/go/testdata/importcom/src/wrongplace/x.go @@ -0,0 +1 @@ +package x // import "my/x" diff --git a/src/cmd/go/testdata/importcom/works.go b/src/cmd/go/testdata/importcom/works.go new file mode 100644 index 000000000..31b55d08a --- /dev/null +++ b/src/cmd/go/testdata/importcom/works.go @@ -0,0 +1,3 @@ +package p + +import _ "works/x" diff --git a/src/cmd/go/testdata/importcom/wrongplace.go b/src/cmd/go/testdata/importcom/wrongplace.go new file mode 100644 index 000000000..e2535e01a --- /dev/null +++ b/src/cmd/go/testdata/importcom/wrongplace.go @@ -0,0 +1,3 @@ +package p + +import "wrongplace" diff --git a/src/cmd/go/testdata/norunexample/example_test.go b/src/cmd/go/testdata/norunexample/example_test.go new file mode 100644 index 000000000..e158305a6 --- /dev/null +++ b/src/cmd/go/testdata/norunexample/example_test.go @@ -0,0 +1,11 @@ +package pkg_test + +import "os" + +func init() { + os.Stdout.Write([]byte("File with non-runnable example was built.\n")) +} + +func Example_test() { + // This test will not be run, it has no "Output:" comment. +} diff --git a/src/cmd/go/testdata/norunexample/test_test.go b/src/cmd/go/testdata/norunexample/test_test.go new file mode 100644 index 000000000..d2e919838 --- /dev/null +++ b/src/cmd/go/testdata/norunexample/test_test.go @@ -0,0 +1,10 @@ +package pkg + +import ( + "os" + "testing" +) + +func TestBuilt(t *testing.T) { + os.Stdout.Write([]byte("A normal test was executed.\n")) +} diff --git a/src/cmd/go/testdata/src/badc/x.c b/src/cmd/go/testdata/src/badc/x.c new file mode 100644 index 000000000..f6cbf6924 --- /dev/null +++ b/src/cmd/go/testdata/src/badc/x.c @@ -0,0 +1 @@ +// C code! diff --git a/src/cmd/go/testdata/src/badc/x.go b/src/cmd/go/testdata/src/badc/x.go new file mode 100644 index 000000000..bfa1de28b --- /dev/null +++ b/src/cmd/go/testdata/src/badc/x.go @@ -0,0 +1 @@ +package badc diff --git a/src/cmd/go/testdata/src/badtest/badexec/x_test.go b/src/cmd/go/testdata/src/badtest/badexec/x_test.go new file mode 100644 index 000000000..12f505171 --- /dev/null +++ b/src/cmd/go/testdata/src/badtest/badexec/x_test.go @@ -0,0 +1,5 @@ +package badexec + +func init() { + panic("badexec") +} diff --git a/src/cmd/go/testdata/src/badtest/badsyntax/x.go b/src/cmd/go/testdata/src/badtest/badsyntax/x.go new file mode 100644 index 000000000..c8a5407a5 --- /dev/null +++ b/src/cmd/go/testdata/src/badtest/badsyntax/x.go @@ -0,0 +1 @@ +package badsyntax diff --git a/src/cmd/go/testdata/src/badtest/badsyntax/x_test.go b/src/cmd/go/testdata/src/badtest/badsyntax/x_test.go new file mode 100644 index 000000000..5be10745d --- /dev/null +++ b/src/cmd/go/testdata/src/badtest/badsyntax/x_test.go @@ -0,0 +1,3 @@ +package badsyntax + +func func func func func! diff --git a/src/cmd/go/testdata/src/badtest/badvar/x.go b/src/cmd/go/testdata/src/badtest/badvar/x.go new file mode 100644 index 000000000..fdd46c4c7 --- /dev/null +++ b/src/cmd/go/testdata/src/badtest/badvar/x.go @@ -0,0 +1 @@ +package badvar diff --git a/src/cmd/go/testdata/src/badtest/badvar/x_test.go b/src/cmd/go/testdata/src/badtest/badvar/x_test.go new file mode 100644 index 000000000..c67df01c5 --- /dev/null +++ b/src/cmd/go/testdata/src/badtest/badvar/x_test.go @@ -0,0 +1,5 @@ +package badvar_test + +func f() { + _ = notdefined +} diff --git a/src/cmd/go/testdata/src/vetpkg/a_test.go b/src/cmd/go/testdata/src/vetpkg/a_test.go new file mode 100644 index 000000000..9b64e8e1a --- /dev/null +++ b/src/cmd/go/testdata/src/vetpkg/a_test.go @@ -0,0 +1 @@ +package p_test diff --git a/src/cmd/go/testdata/src/vetpkg/b.go b/src/cmd/go/testdata/src/vetpkg/b.go new file mode 100644 index 000000000..99e18f63d --- /dev/null +++ b/src/cmd/go/testdata/src/vetpkg/b.go @@ -0,0 +1,7 @@ +package p + +import "fmt" + +func f() { + fmt.Printf("%d") +} diff --git a/src/cmd/go/testdata/testinternal/p.go b/src/cmd/go/testdata/testinternal/p.go new file mode 100644 index 000000000..e3558a53b --- /dev/null +++ b/src/cmd/go/testdata/testinternal/p.go @@ -0,0 +1,3 @@ +package p + +import _ "net/http/internal" diff --git a/src/cmd/go/testdata/testinternal2/p.go b/src/cmd/go/testdata/testinternal2/p.go new file mode 100644 index 000000000..c594f5c5e --- /dev/null +++ b/src/cmd/go/testdata/testinternal2/p.go @@ -0,0 +1,3 @@ +package p + +import _ "./x/y/z/internal/w" diff --git a/src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go b/src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go new file mode 100644 index 000000000..a796c0b5f --- /dev/null +++ b/src/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go @@ -0,0 +1 @@ +package w diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go index 73f311e5f..6da74b996 100644 --- a/src/cmd/go/testflag.go +++ b/src/cmd/go/testflag.go @@ -65,9 +65,9 @@ type testFlagSpec struct { var testFlagDefn = []*testFlagSpec{ // local. {name: "c", boolVar: &testC}, - {name: "file", multiOK: true}, {name: "cover", boolVar: &testCover}, {name: "coverpkg"}, + {name: "o"}, // build flags. {name: "a", boolVar: &buildA}, @@ -153,6 +153,9 @@ func testFlags(args []string) (packageNames, passToTest []string) { // 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": @@ -184,8 +187,6 @@ func testFlags(args []string) (packageNames, passToTest []string) { buildContext.BuildTags = strings.Fields(value) case "compiler": buildCompiler{}.Set(value) - case "file": - testFiles = append(testFiles, value) case "bench": // record that we saw the flag; don't care about the value testBench = true diff --git a/src/cmd/go/testgo.go b/src/cmd/go/testgo.go new file mode 100644 index 000000000..01923f74b --- /dev/null +++ b/src/cmd/go/testgo.go @@ -0,0 +1,21 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains extra hooks for testing the go command. +// It is compiled into the Go binary only when building the +// test copy; it does not get compiled into the standard go +// command, so these testing hooks are not present in the +// go command that everyone uses. + +// +build testgo + +package main + +import "os" + +func init() { + if v := os.Getenv("TESTGO_IS_GO_RELEASE"); v != "" { + isGoRelease = v == "1" + } +} diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go index 6d26f7a4b..3f11c3e3d 100644 --- a/src/cmd/go/tool.go +++ b/src/cmd/go/tool.go @@ -47,13 +47,13 @@ const toolWindowsExtension = ".exe" func tool(toolName string) string { toolPath := filepath.Join(toolDir, toolName) - if toolIsWindows && toolName != "pprof" { + if toolIsWindows { toolPath += toolWindowsExtension } // Give a nice message if there is no tool with that name. if _, err := os.Stat(toolPath); err != nil { if isInGoToolsRepo(toolName) { - fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get code.google.com/p/go.tools/cmd/%s\n", toolName, toolName) + fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName) } else { fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName) } @@ -91,16 +91,6 @@ func runTool(cmd *Command, args []string) { if toolPath == "" { return } - if toolIsWindows && toolName == "pprof" { - args = append([]string{"perl", toolPath}, args[1:]...) - var err error - toolPath, err = exec.LookPath("perl") - if err != nil { - fmt.Fprintf(os.Stderr, "go tool: perl not found\n") - setExitStatus(3) - return - } - } if toolN { fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " ")) return diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go index 8f0bae0b7..1cac61338 100644 --- a/src/cmd/go/vcs.go +++ b/src/cmd/go/vcs.go @@ -33,6 +33,9 @@ type vcsCmd struct { scheme []string pingCmd string + + remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error) + resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) } // A tagCmd describes a command to list available tags @@ -81,8 +84,17 @@ var vcsHg = &vcsCmd{ tagSyncCmd: "update -r {tag}", tagSyncDefault: "update default", - scheme: []string{"https", "http", "ssh"}, - pingCmd: "identify {scheme}://{repo}", + scheme: []string{"https", "http", "ssh"}, + pingCmd: "identify {scheme}://{repo}", + remoteRepo: hgRemoteRepo, +} + +func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error) { + out, err := vcsHg.runOutput(rootDir, "paths default") + if err != nil { + return "", err + } + return strings.TrimSpace(string(out)), nil } // vcsGit describes how to use Git. @@ -104,8 +116,38 @@ var vcsGit = &vcsCmd{ tagSyncCmd: "checkout {tag}", tagSyncDefault: "checkout master", - scheme: []string{"git", "https", "http", "git+ssh"}, - pingCmd: "ls-remote {scheme}://{repo}", + scheme: []string{"git", "https", "http", "git+ssh"}, + pingCmd: "ls-remote {scheme}://{repo}", + remoteRepo: gitRemoteRepo, +} + +func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsGit.runOutput(rootDir, "remote -v") + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // origin https://github.com/rsc/pdf (fetch) + // origin https://github.com/rsc/pdf (push) + // use first line only. + + if !strings.HasPrefix(out, "origin\t") { + return "", fmt.Errorf("unable to parse output of git remote -v") + } + 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 } // vcsBzr describes how to use Bazaar. @@ -123,8 +165,51 @@ var vcsBzr = &vcsCmd{ tagSyncCmd: "update -r {tag}", tagSyncDefault: "update -r revno:-1", - scheme: []string{"https", "http", "bzr", "bzr+ssh"}, - pingCmd: "info {scheme}://{repo}", + scheme: []string{"https", "http", "bzr", "bzr+ssh"}, + pingCmd: "info {scheme}://{repo}", + remoteRepo: bzrRemoteRepo, + resolveRepo: bzrResolveRepo, +} + +func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsBzr.runOutput(rootDir, "config parent_location") + if err != nil { + return "", err + } + return strings.TrimSpace(string(outb)), nil +} + +func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) { + outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo) + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // ... + // (branch root|repository branch): + // ... + + found := false + for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} { + i := strings.Index(out, prefix) + if i >= 0 { + out = out[i+len(prefix):] + found = true + break + } + } + if !found { + return "", fmt.Errorf("unable to parse output of bzr info") + } + + i := strings.Index(out, "\n") + if i < 0 { + return "", fmt.Errorf("unable to parse output of bzr info") + } + out = out[:i] + return strings.TrimSpace(string(out)), nil } // vcsSvn describes how to use Subversion. @@ -138,8 +223,34 @@ var vcsSvn = &vcsCmd{ // There is no tag command in subversion. // The branch information is all in the path names. - scheme: []string{"https", "http", "svn", "svn+ssh"}, - pingCmd: "info {scheme}://{repo}", + scheme: []string{"https", "http", "svn", "svn+ssh"}, + pingCmd: "info {scheme}://{repo}", + remoteRepo: svnRemoteRepo, +} + +func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsSvn.runOutput(rootDir, "info") + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // ... + // Repository Root: + // ... + + i := strings.Index(out, "\nRepository Root: ") + if i < 0 { + return "", fmt.Errorf("unable to parse output of svn info") + } + out = out[i+len("\nRepository Root: "):] + i = strings.Index(out, "\n") + if i < 0 { + return "", fmt.Errorf("unable to parse output of svn info") + } + out = out[:i] + return strings.TrimSpace(string(out)), nil } func (v *vcsCmd) String() string { @@ -361,7 +472,14 @@ var httpPrefixRE = regexp.MustCompile(`^https?:`) func repoRootForImportPath(importPath string) (*repoRoot, error) { rr, err := repoRootForImportPathStatic(importPath, "") if err == errUnknownSite { - rr, err = repoRootForImportDynamic(importPath) + // If there are wildcards, look up the thing before the wildcard, + // hoping it applies to the wildcarded parts too. + // This makes 'go get rsc.io/pdf/...' work in a fresh GOPATH. + lookup := strings.TrimSuffix(importPath, "/...") + if i := strings.Index(lookup, "/.../"); i >= 0 { + lookup = lookup[:i] + } + rr, err = repoRootForImportDynamic(lookup) // repoRootForImportDynamic returns error detail // that is irrelevant if the user didn't intend to use a @@ -465,11 +583,11 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) { func repoRootForImportDynamic(importPath string) (*repoRoot, error) { slash := strings.Index(importPath, "/") if slash < 0 { - return nil, errors.New("import path doesn't contain a slash") + return nil, errors.New("import path does not contain a slash") } host := importPath[:slash] if !strings.Contains(host, ".") { - return nil, errors.New("import path doesn't contain a hostname") + return nil, errors.New("import path does not begin with hostname") } urlStr, body, err := httpsOrHTTP(importPath) if err != nil { @@ -613,6 +731,15 @@ var vcsPaths = []*vcsPath{ check: launchpadVCS, }, + // IBM DevOps Services (JazzHub) + { + prefix: "hub.jazz.net/git", + re: `^(?Phub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, + vcs: "git", + repo: "https://{root}", + check: noVCSSuffix, + }, + // General syntax for any server. { re: `^(?P(?P([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?Pbzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`, diff --git a/src/cmd/go/vcs_test.go b/src/cmd/go/vcs_test.go new file mode 100644 index 000000000..14d681ba6 --- /dev/null +++ b/src/cmd/go/vcs_test.go @@ -0,0 +1,124 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "runtime" + "testing" +) + +// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath. +// TODO(cmang): Add tests for SVN and BZR. +func TestRepoRootForImportPath(t *testing.T) { + if testing.Short() { + t.Skip("skipping test to avoid external network") + } + switch runtime.GOOS { + case "nacl", "android": + t.Skipf("no networking available on %s", runtime.GOOS) + } + tests := []struct { + path string + want *repoRoot + }{ + { + "code.google.com/p/go", + &repoRoot{ + vcs: vcsHg, + repo: "https://code.google.com/p/go", + }, + }, + /*{ + "code.google.com/r/go", + &repoRoot{ + vcs: vcsHg, + repo: "https://code.google.com/r/go", + }, + },*/ + { + "github.com/golang/groupcache", + &repoRoot{ + vcs: vcsGit, + repo: "https://github.com/golang/groupcache", + }, + }, + // IBM DevOps Services tests + { + "hub.jazz.net/git/user1/pkgname", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user1/pkgname", + }, + }, + { + "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user1/pkgname", + }, + }, + { + "hub.jazz.net", + nil, + }, + { + "hub2.jazz.net", + nil, + }, + { + "hub.jazz.net/someotherprefix", + nil, + }, + { + "hub.jazz.net/someotherprefix/user1/pkgname", + nil, + }, + // Spaces are not valid in user names or package names + { + "hub.jazz.net/git/User 1/pkgname", + nil, + }, + { + "hub.jazz.net/git/user1/pkg name", + nil, + }, + // Dots are not valid in user names + { + "hub.jazz.net/git/user.1/pkgname", + nil, + }, + { + "hub.jazz.net/git/user/pkg.name", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user/pkg.name", + }, + }, + // User names cannot have uppercase letters + { + "hub.jazz.net/git/USER/pkgname", + nil, + }, + } + + for _, test := range tests { + got, err := repoRootForImportPath(test.path) + want := test.want + + if want == nil { + if err == nil { + t.Errorf("RepoRootForImport(%q): Error expected but not received", test.path) + } + continue + } + if err != nil { + t.Errorf("RepoRootForImport(%q): %v", test.path, err) + continue + } + if got.vcs.name != want.vcs.name || got.repo != want.repo { + t.Errorf("RepoRootForImport(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo) + } + } +} diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go index ffb431837..02ff54b2a 100644 --- a/src/cmd/go/vet.go +++ b/src/cmd/go/vet.go @@ -4,6 +4,8 @@ package main +import "path/filepath" + func init() { addBuildFlagsNX(cmdVet) } @@ -15,7 +17,7 @@ var cmdVet = &Command{ Long: ` Vet runs the Go vet command on the packages named by the import paths. -For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'. +For more about vet, see 'godoc golang.org/x/tools/cmd/vet'. For more about specifying packages, see 'go help packages'. To run the vet tool with specific options, run 'go tool vet'. @@ -28,10 +30,21 @@ See also: go fmt, go fix. } func runVet(cmd *Command, args []string) { - 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(tool("vet"), relPaths(stringList(pkg.gofiles, pkg.sfiles))) + for _, p := range packages(args) { + // Vet expects to be given a set of files all from the same package. + // Run once for package p and once for package p_test. + if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles) > 0 { + runVetFiles(p, stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.SFiles)) + } + if len(p.XTestGoFiles) > 0 { + runVetFiles(p, stringList(p.XTestGoFiles)) + } + } +} + +func runVetFiles(p *Package, files []string) { + for i := range files { + files[i] = filepath.Join(p.Dir, files[i]) } + run(tool("vet"), relPaths(files)) } diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go index 8f73ef5b9..3fc043954 100644 --- a/src/cmd/gofmt/doc.go +++ b/src/cmd/gofmt/doc.go @@ -67,7 +67,7 @@ To remove the parentheses: To convert the package tree from explicit slice upper bounds to implicit ones: - gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src/pkg + gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src The simplify command diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 576cae522..81da21ff1 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -87,13 +87,13 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error return err } - file, adjust, err := parse(fileSet, filename, src, stdin) + file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin) if err != nil { return err } if rewrite != nil { - if adjust == nil { + if sourceAdj == nil { file = rewrite(file) } else { fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n") @@ -106,15 +106,10 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error simplify(file) } - var buf bytes.Buffer - err = (&printer.Config{Mode: printerMode, Tabwidth: tabWidth}).Fprint(&buf, fileSet, file) + res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth}) if err != nil { return err } - res := buf.Bytes() - if adjust != nil { - res = adjust(src, res) - } if !bytes.Equal(src, res) { // formatting has changed @@ -122,7 +117,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error fmt.Fprintln(out, filename) } if *write { - err = ioutil.WriteFile(filename, res, 0) + err = ioutil.WriteFile(filename, res, 0644) if err != nil { return err } @@ -186,6 +181,11 @@ func gofmtMain() { initRewrite() if flag.NArg() == 0 { + if *write { + fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input") + exitCode = 2 + return + } if err := processFile("", os.Stdin, os.Stdout, true); err != nil { report(err) } @@ -235,19 +235,29 @@ func diff(b1, b2 []byte) (data []byte, err error) { } -// parse parses src, which was read from filename, -// as a Go source file or statement list. -func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.File, func(orig, src []byte) []byte, error) { +// ---------------------------------------------------------------------------- +// Support functions +// +// The functions parse, format, and isSpace below are identical to the +// respective functions in src/go/format/format.go - keep them in sync! +// +// TODO(gri) Factor out this functionality, eventually. + +// parse parses src, which was read from the named file, +// as a Go source file, declaration, or statement list. +func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) ( + file *ast.File, + sourceAdj func(src []byte, indent int) []byte, + indentAdj int, + err error, +) { // Try as whole source file. - file, err := parser.ParseFile(fset, filename, src, parserMode) - if err == nil { - return file, nil, nil - } - // If the error is that the source file didn't begin with a - // package line and this is standard input, fall through to + file, err = parser.ParseFile(fset, filename, src, parserMode) + // If there's no error, return. If the error is that the source file didn't begin with a + // package line and source fragments are ok, fall through to // try as a source fragment. Stop and return on any other error. - if !stdin || !strings.Contains(err.Error(), "expected 'package'") { - return nil, nil, err + if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") { + return } // If this is a declaration list, make it a source file @@ -257,19 +267,19 @@ func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.F psrc := append([]byte("package p;"), src...) file, err = parser.ParseFile(fset, filename, psrc, parserMode) if err == nil { - adjust := func(orig, src []byte) []byte { + sourceAdj = func(src []byte, indent int) []byte { // Remove the package clause. // Gofmt has turned the ; into a \n. - src = src[len("package p\n"):] - return matchSpace(orig, src) + src = src[indent+len("package p\n"):] + return bytes.TrimSpace(src) } - return file, adjust, nil + return } // If the error is that the source file didn't begin with a // declaration, fall through to try as a statement list. // Stop and return on any other error. if !strings.Contains(err.Error(), "expected declaration") { - return nil, nil, err + return } // If this is a statement list, make it a source file @@ -277,68 +287,101 @@ func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.F // into a function body. This handles expressions too. // Insert using a ;, not a newline, so that the line numbers // in fsrc match the ones in src. - fsrc := append(append([]byte("package p; func _() {"), src...), '}') + fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '}') file, err = parser.ParseFile(fset, filename, fsrc, parserMode) if err == nil { - adjust := func(orig, src []byte) []byte { + sourceAdj = func(src []byte, indent int) []byte { + // Cap adjusted indent to zero. + if indent < 0 { + indent = 0 + } // Remove the wrapping. // Gofmt has turned the ; into a \n\n. - src = src[len("package p\n\nfunc _() {"):] - src = src[:len(src)-len("}\n")] - // Gofmt has also indented the function body one level. - // Remove that indent. - src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1) - return matchSpace(orig, src) + // There will be two non-blank lines with indent, hence 2*indent. + src = src[2*indent+len("package p\n\nfunc _() {"):] + src = src[:len(src)-(indent+len("\n}\n"))] + return bytes.TrimSpace(src) } - return file, adjust, nil + // Gofmt has also indented the function body one level. + // Adjust that with indentAdj. + indentAdj = -1 } - // Failed, and out of options. - return nil, nil, err + // Succeeded, or out of options. + return } -func cutSpace(b []byte) (before, middle, after []byte) { - i := 0 - for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') { - i++ - } - j := len(b) - for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') { - j-- - } - if i <= j { - return b[:i], b[i:j], b[j:] +// format formats the given package file originally obtained from src +// and adjusts the result based on the original source via sourceAdj +// and indentAdj. +func format( + fset *token.FileSet, + file *ast.File, + sourceAdj func(src []byte, indent int) []byte, + indentAdj int, + src []byte, + cfg printer.Config, +) ([]byte, error) { + if sourceAdj == nil { + // Complete source file. + var buf bytes.Buffer + err := cfg.Fprint(&buf, fset, file) + if err != nil { + return nil, err + } + return buf.Bytes(), nil } - return nil, nil, b[j:] -} -// matchSpace reformats src to use the same space context as orig. -// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src. -// 2) matchSpace copies the indentation of the first non-blank line in orig -// to every non-blank line in src. -// 3) matchSpace copies the trailing space from orig and uses it in place -// of src's trailing space. -func matchSpace(orig []byte, src []byte) []byte { - before, _, after := cutSpace(orig) - i := bytes.LastIndex(before, []byte{'\n'}) - before, indent := before[:i+1], before[i+1:] - - _, src, _ = cutSpace(src) - - var b bytes.Buffer - b.Write(before) - for len(src) > 0 { - line := src - if i := bytes.IndexByte(line, '\n'); i >= 0 { - line, src = line[:i+1], line[i+1:] - } else { - src = nil + // Partial source file. + // Determine and prepend leading space. + i, j := 0, 0 + for j < len(src) && isSpace(src[j]) { + if src[j] == '\n' { + i = j + 1 // byte offset of last line in leading space } - if len(line) > 0 && line[0] != '\n' { // not blank - b.Write(indent) + j++ + } + var res []byte + res = append(res, src[:i]...) + + // Determine and prepend indentation of first code line. + // Spaces are ignored unless there are no tabs, + // in which case spaces count as one tab. + indent := 0 + hasSpace := false + for _, b := range src[i:j] { + switch b { + case ' ': + hasSpace = true + case '\t': + indent++ } - b.Write(line) } - b.Write(after) - return b.Bytes() + if indent == 0 && hasSpace { + indent = 1 + } + for i := 0; i < indent; i++ { + res = append(res, '\t') + } + + // Format the source. + // Write it without any leading and trailing space. + cfg.Indent = indent + indentAdj + var buf bytes.Buffer + err := cfg.Fprint(&buf, fset, file) + if err != nil { + return nil, err + } + res = append(res, sourceAdj(buf.Bytes(), cfg.Indent)...) + + // Determine and append trailing space. + i = len(src) + for i > 0 && isSpace(src[i-1]) { + i-- + } + return append(res, src[i:]...), nil +} + +func isSpace(b byte) bool { + return b == ' ' || b == '\t' || b == '\n' || b == '\r' } diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go index b9335b8f3..d1edb7bcc 100644 --- a/src/cmd/gofmt/gofmt_test.go +++ b/src/cmd/gofmt/gofmt_test.go @@ -6,18 +6,60 @@ package main import ( "bytes" + "flag" "io/ioutil" + "os" "path/filepath" "strings" "testing" + "text/scanner" ) -func runTest(t *testing.T, in, out, flags string) { +var update = flag.Bool("update", false, "update .golden files") + +// gofmtFlags looks for a comment of the form +// +// //gofmt flags +// +// within the first maxLines lines of the given file, +// and returns the flags string, if any. Otherwise it +// returns the empty string. +func gofmtFlags(filename string, maxLines int) string { + f, err := os.Open(filename) + if err != nil { + return "" // ignore errors - they will be found later + } + defer f.Close() + + // initialize scanner + var s scanner.Scanner + s.Init(f) + s.Error = func(*scanner.Scanner, string) {} // ignore errors + s.Mode = scanner.GoTokens &^ scanner.SkipComments // want comments + + // look for //gofmt comment + for s.Line <= maxLines { + switch s.Scan() { + case scanner.Comment: + const prefix = "//gofmt " + if t := s.TokenText(); strings.HasPrefix(t, prefix) { + return strings.TrimSpace(t[len(prefix):]) + } + case scanner.EOF: + return "" + } + + } + + return "" +} + +func runTest(t *testing.T, in, out string) { // process flags *simplifyAST = false *rewriteRule = "" stdin := false - for _, flag := range strings.Split(flags, " ") { + for _, flag := range strings.Split(gofmtFlags(in, 20), " ") { elts := strings.SplitN(flag, "=", 2) name := elts[0] value := "" @@ -56,6 +98,17 @@ func runTest(t *testing.T, in, out, flags string) { } if got := buf.Bytes(); !bytes.Equal(got, expected) { + if *update { + if in != out { + if err := ioutil.WriteFile(out, got, 0666); err != nil { + t.Error(err) + } + return + } + // in == out: don't accidentally destroy input + t.Errorf("WARNING: -update did not rewrite input file %s", in) + } + t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in) d, err := diff(expected, got) if err == nil { @@ -67,51 +120,37 @@ func runTest(t *testing.T, in, out, flags string) { } } -var tests = []struct { - in, flags string -}{ - {"gofmt.go", ""}, - {"gofmt_test.go", ""}, - {"testdata/composites.input", "-s"}, - {"testdata/slices1.input", "-s"}, - {"testdata/slices2.input", "-s"}, - {"testdata/old.input", ""}, - {"testdata/rewrite1.input", "-r=Foo->Bar"}, - {"testdata/rewrite2.input", "-r=int->bool"}, - {"testdata/rewrite3.input", "-r=x->x"}, - {"testdata/rewrite4.input", "-r=(x)->x"}, - {"testdata/rewrite5.input", "-r=x+x->2*x"}, - {"testdata/rewrite6.input", "-r=fun(x)->Fun(x)"}, - {"testdata/rewrite7.input", "-r=fun(x...)->Fun(x)"}, - {"testdata/rewrite8.input", "-r=interface{}->int"}, - {"testdata/stdin*.input", "-stdin"}, - {"testdata/comments.input", ""}, - {"testdata/import.input", ""}, - {"testdata/crlf.input", ""}, // test case for issue 3961; see also TestCRLF - {"testdata/typeswitch.input", ""}, // test case for issue 4470 -} - +// TestRewrite processes testdata/*.input files and compares them to the +// corresponding testdata/*.golden files. The gofmt flags used to process +// a file must be provided via a comment of the form +// +// //gofmt flags +// +// in the processed file within the first 20 lines, if any. func TestRewrite(t *testing.T) { - for _, test := range tests { - match, err := filepath.Glob(test.in) - if err != nil { - t.Error(err) - continue + // determine input files + match, err := filepath.Glob("testdata/*.input") + if err != nil { + t.Fatal(err) + } + + // add larger examples + match = append(match, "gofmt.go", "gofmt_test.go") + + for _, in := range match { + out := in // for files where input and output are identical + if strings.HasSuffix(in, ".input") { + out = in[:len(in)-len(".input")] + ".golden" } - for _, in := range match { - out := in - if strings.HasSuffix(in, ".input") { - out = in[:len(in)-len(".input")] + ".golden" - } - runTest(t, in, out, test.flags) - if in != out { - // Check idempotence. - runTest(t, out, out, test.flags) - } + runTest(t, in, out) + if in != out { + // Check idempotence. + runTest(t, out, out) } } } +// Test case for issue 3961. func TestCRLF(t *testing.T) { const input = "testdata/crlf.input" // must contain CR/LF's const golden = "testdata/crlf.golden" // must not contain any CR's diff --git a/src/cmd/gofmt/long_test.go b/src/cmd/gofmt/long_test.go index 108278b33..237b86021 100644 --- a/src/cmd/gofmt/long_test.go +++ b/src/cmd/gofmt/long_test.go @@ -32,7 +32,7 @@ var ( ) func gofmt(fset *token.FileSet, filename string, src *bytes.Buffer) error { - f, _, err := parse(fset, filename, src.Bytes(), false) + f, _, _, err := parse(fset, filename, src.Bytes(), false) if err != nil { return err } @@ -60,7 +60,7 @@ func testFile(t *testing.T, b1, b2 *bytes.Buffer, filename string) { // exclude files w/ syntax errors (typically test cases) fset := token.NewFileSet() - if _, _, err = parse(fset, filename, b1.Bytes(), false); err != nil { + if _, _, _, err = parse(fset, filename, b1.Bytes(), false); err != nil { if *verbose { fmt.Fprintf(os.Stderr, "ignoring %s\n", err) } diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go index fb6c6fc81..d267cfcc1 100644 --- a/src/cmd/gofmt/rewrite.go +++ b/src/cmd/gofmt/rewrite.go @@ -226,9 +226,6 @@ func match(m map[string]reflect.Value, pattern, val reflect.Value) bool { return true case reflect.Struct: - if p.NumField() != v.NumField() { - return false - } for i := 0; i < p.NumField(); i++ { if !match(m, p.Field(i), v.Field(i)) { return false diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go index 45d000d67..69f7bf23c 100644 --- a/src/cmd/gofmt/simplify.go +++ b/src/cmd/gofmt/simplify.go @@ -68,9 +68,10 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor { // a slice expression of the form: s[a:len(s)] // can be simplified to: s[a:] // if s is "simple enough" (for now we only accept identifiers) - if s.hasDotImport { - // if dot imports are present, we cannot be certain that an - // unresolved "len" identifier refers to the predefined len() + if n.Max != nil || s.hasDotImport { + // - 3-index slices always require the 2nd and 3rd index + // - if dot imports are present, we cannot be certain that an + // unresolved "len" identifier refers to the predefined len() break } if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil { @@ -96,16 +97,26 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor { // x, y := b[:n], b[n:] case *ast.RangeStmt: - // a range of the form: for x, _ = range v {...} + // - a range of the form: for x, _ = range v {...} // can be simplified to: for x = range v {...} - if ident, _ := n.Value.(*ast.Ident); ident != nil && ident.Name == "_" { + // - a range of the form: for _ = range v {...} + // can be simplified to: for range v {...} + if isBlank(n.Value) { n.Value = nil } + if isBlank(n.Key) && n.Value == nil { + n.Key = nil + } } return s } +func isBlank(x ast.Expr) bool { + ident, ok := x.(*ast.Ident) + return ok && ident.Name == "_" +} + func simplify(f *ast.File) { var s simplifier @@ -117,5 +128,34 @@ func simplify(f *ast.File) { } } + // remove empty declarations such as "const ()", etc + removeEmptyDeclGroups(f) + ast.Walk(&s, f) } + +func removeEmptyDeclGroups(f *ast.File) { + i := 0 + for _, d := range f.Decls { + if g, ok := d.(*ast.GenDecl); !ok || !isEmpty(f, g) { + f.Decls[i] = d + i++ + } + } + f.Decls = f.Decls[:i] +} + +func isEmpty(f *ast.File, g *ast.GenDecl) bool { + if g.Doc != nil || g.Specs != nil { + return false + } + + for _, c := range f.Comments { + // if there is a comment in the declaration, it is not considered empty + if g.Pos() <= c.Pos() && c.End() <= g.End() { + return false + } + } + + return true +} diff --git a/src/cmd/gofmt/testdata/composites.golden b/src/cmd/gofmt/testdata/composites.golden index b2825e732..fc9c98e62 100644 --- a/src/cmd/gofmt/testdata/composites.golden +++ b/src/cmd/gofmt/testdata/composites.golden @@ -1,3 +1,5 @@ +//gofmt -s + package P type T struct { diff --git a/src/cmd/gofmt/testdata/composites.input b/src/cmd/gofmt/testdata/composites.input index 7210dafc9..fc7598af9 100644 --- a/src/cmd/gofmt/testdata/composites.input +++ b/src/cmd/gofmt/testdata/composites.input @@ -1,3 +1,5 @@ +//gofmt -s + package P type T struct { diff --git a/src/cmd/gofmt/testdata/crlf.golden b/src/cmd/gofmt/testdata/crlf.golden index 57679f770..193dbacc7 100644 --- a/src/cmd/gofmt/testdata/crlf.golden +++ b/src/cmd/gofmt/testdata/crlf.golden @@ -2,6 +2,7 @@ Source containing CR/LF line endings. The gofmt'ed output must only have LF line endings. + Test case for issue 3961. */ package main diff --git a/src/cmd/gofmt/testdata/crlf.input b/src/cmd/gofmt/testdata/crlf.input index 61a1aa0b4..ae7e14dbf 100644 --- a/src/cmd/gofmt/testdata/crlf.input +++ b/src/cmd/gofmt/testdata/crlf.input @@ -2,6 +2,7 @@ Source containing CR/LF line endings. The gofmt'ed output must only have LF line endings. + Test case for issue 3961. */ package main diff --git a/src/cmd/gofmt/testdata/emptydecl.golden b/src/cmd/gofmt/testdata/emptydecl.golden new file mode 100644 index 000000000..33d6435e0 --- /dev/null +++ b/src/cmd/gofmt/testdata/emptydecl.golden @@ -0,0 +1,14 @@ +//gofmt -s + +// Test case for issue 7631. + +package main + +// Keep this declaration +var () + +const ( +// Keep this declaration +) + +func main() {} diff --git a/src/cmd/gofmt/testdata/emptydecl.input b/src/cmd/gofmt/testdata/emptydecl.input new file mode 100644 index 000000000..4948a61f0 --- /dev/null +++ b/src/cmd/gofmt/testdata/emptydecl.input @@ -0,0 +1,16 @@ +//gofmt -s + +// Test case for issue 7631. + +package main + +// Keep this declaration +var () + +const ( +// Keep this declaration +) + +type () + +func main() {} \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/ranges.golden b/src/cmd/gofmt/testdata/ranges.golden new file mode 100644 index 000000000..506b3a035 --- /dev/null +++ b/src/cmd/gofmt/testdata/ranges.golden @@ -0,0 +1,30 @@ +//gofmt -s + +// Test cases for range simplification. +package p + +func _() { + for a, b = range x { + } + for a = range x { + } + for _, b = range x { + } + for range x { + } + + for a = range x { + } + for range x { + } + + for a, b := range x { + } + for a := range x { + } + for _, b := range x { + } + + for a := range x { + } +} diff --git a/src/cmd/gofmt/testdata/ranges.input b/src/cmd/gofmt/testdata/ranges.input new file mode 100644 index 000000000..df5f8333c --- /dev/null +++ b/src/cmd/gofmt/testdata/ranges.input @@ -0,0 +1,20 @@ +//gofmt -s + +// Test cases for range simplification. +package p + +func _() { + for a, b = range x {} + for a, _ = range x {} + for _, b = range x {} + for _, _ = range x {} + + for a = range x {} + for _ = range x {} + + for a, b := range x {} + for a, _ := range x {} + for _, b := range x {} + + for a := range x {} +} diff --git a/src/cmd/gofmt/testdata/rewrite1.golden b/src/cmd/gofmt/testdata/rewrite1.golden index d9beb3705..3ee5373a7 100644 --- a/src/cmd/gofmt/testdata/rewrite1.golden +++ b/src/cmd/gofmt/testdata/rewrite1.golden @@ -1,3 +1,5 @@ +//gofmt -r=Foo->Bar + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite1.input b/src/cmd/gofmt/testdata/rewrite1.input index bdb894320..a84c8f781 100644 --- a/src/cmd/gofmt/testdata/rewrite1.input +++ b/src/cmd/gofmt/testdata/rewrite1.input @@ -1,3 +1,5 @@ +//gofmt -r=Foo->Bar + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite2.golden b/src/cmd/gofmt/testdata/rewrite2.golden index 64c67ffa6..f980e0353 100644 --- a/src/cmd/gofmt/testdata/rewrite2.golden +++ b/src/cmd/gofmt/testdata/rewrite2.golden @@ -1,3 +1,5 @@ +//gofmt -r=int->bool + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite2.input b/src/cmd/gofmt/testdata/rewrite2.input index 21171447a..489be4e07 100644 --- a/src/cmd/gofmt/testdata/rewrite2.input +++ b/src/cmd/gofmt/testdata/rewrite2.input @@ -1,3 +1,5 @@ +//gofmt -r=int->bool + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite3.golden b/src/cmd/gofmt/testdata/rewrite3.golden index 0d16d1601..261a220c6 100644 --- a/src/cmd/gofmt/testdata/rewrite3.golden +++ b/src/cmd/gofmt/testdata/rewrite3.golden @@ -1,3 +1,5 @@ +//gofmt -r=x->x + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite3.input b/src/cmd/gofmt/testdata/rewrite3.input index 0d16d1601..261a220c6 100644 --- a/src/cmd/gofmt/testdata/rewrite3.input +++ b/src/cmd/gofmt/testdata/rewrite3.input @@ -1,3 +1,5 @@ +//gofmt -r=x->x + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite4.golden b/src/cmd/gofmt/testdata/rewrite4.golden index 8dfc81a07..b05547b4b 100644 --- a/src/cmd/gofmt/testdata/rewrite4.golden +++ b/src/cmd/gofmt/testdata/rewrite4.golden @@ -1,3 +1,5 @@ +//gofmt -r=(x)->x + // Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite4.input b/src/cmd/gofmt/testdata/rewrite4.input index 164cc0451..081709920 100644 --- a/src/cmd/gofmt/testdata/rewrite4.input +++ b/src/cmd/gofmt/testdata/rewrite4.input @@ -1,3 +1,5 @@ +//gofmt -r=(x)->x + // Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite5.golden b/src/cmd/gofmt/testdata/rewrite5.golden index 5a448a63d..9beb34aee 100644 --- a/src/cmd/gofmt/testdata/rewrite5.golden +++ b/src/cmd/gofmt/testdata/rewrite5.golden @@ -1,3 +1,5 @@ +//gofmt -r=x+x->2*x + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite5.input b/src/cmd/gofmt/testdata/rewrite5.input index 0d759e69b..d7a6122d0 100644 --- a/src/cmd/gofmt/testdata/rewrite5.input +++ b/src/cmd/gofmt/testdata/rewrite5.input @@ -1,3 +1,5 @@ +//gofmt -r=x+x->2*x + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite6.golden b/src/cmd/gofmt/testdata/rewrite6.golden index e565dbdd9..48ec9aa0d 100644 --- a/src/cmd/gofmt/testdata/rewrite6.golden +++ b/src/cmd/gofmt/testdata/rewrite6.golden @@ -1,3 +1,5 @@ +//gofmt -r=fun(x)->Fun(x) + // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite6.input b/src/cmd/gofmt/testdata/rewrite6.input index 8c088b3e8..b085a84fe 100644 --- a/src/cmd/gofmt/testdata/rewrite6.input +++ b/src/cmd/gofmt/testdata/rewrite6.input @@ -1,3 +1,5 @@ +//gofmt -r=fun(x)->Fun(x) + // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite7.golden b/src/cmd/gofmt/testdata/rewrite7.golden index 29babad9f..8386a0b2a 100644 --- a/src/cmd/gofmt/testdata/rewrite7.golden +++ b/src/cmd/gofmt/testdata/rewrite7.golden @@ -1,3 +1,5 @@ +//gofmt -r=fun(x...)->Fun(x) + // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite7.input b/src/cmd/gofmt/testdata/rewrite7.input index 073e2a3e6..c1984708e 100644 --- a/src/cmd/gofmt/testdata/rewrite7.input +++ b/src/cmd/gofmt/testdata/rewrite7.input @@ -1,3 +1,5 @@ +//gofmt -r=fun(x...)->Fun(x) + // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite8.golden b/src/cmd/gofmt/testdata/rewrite8.golden index cfc452b03..62f0419df 100644 --- a/src/cmd/gofmt/testdata/rewrite8.golden +++ b/src/cmd/gofmt/testdata/rewrite8.golden @@ -1,3 +1,5 @@ +//gofmt -r=interface{}->int + // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/rewrite8.input b/src/cmd/gofmt/testdata/rewrite8.input index 235efa91c..7964c5c75 100644 --- a/src/cmd/gofmt/testdata/rewrite8.input +++ b/src/cmd/gofmt/testdata/rewrite8.input @@ -1,3 +1,5 @@ +//gofmt -r=interface{}->int + // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/gofmt/testdata/slices1.golden b/src/cmd/gofmt/testdata/slices1.golden index 61e074f68..04bc16f21 100644 --- a/src/cmd/gofmt/testdata/slices1.golden +++ b/src/cmd/gofmt/testdata/slices1.golden @@ -1,3 +1,5 @@ +//gofmt -s + // Test cases for slice expression simplification. package p @@ -15,6 +17,7 @@ var ( _ = a[3:(len(a))] _ = a[len(a) : len(a)-1] _ = a[0:len(b)] + _ = a[2:len(a):len(a)] _ = a[:] _ = a[:10] @@ -22,6 +25,7 @@ var ( _ = a[:(len(a))] _ = a[:len(a)-1] _ = a[:len(b)] + _ = a[:len(a):len(a)] _ = s[0:] _ = s[1:10] @@ -29,6 +33,7 @@ var ( _ = s[3:(len(s))] _ = s[len(a) : len(s)-1] _ = s[0:len(b)] + _ = s[2:len(s):len(s)] _ = s[:] _ = s[:10] @@ -36,6 +41,7 @@ var ( _ = s[:(len(s))] _ = s[:len(s)-1] _ = s[:len(b)] + _ = s[:len(s):len(s)] _ = t.s[0:] _ = t.s[1:10] @@ -43,6 +49,7 @@ var ( _ = t.s[3:(len(t.s))] _ = t.s[len(a) : len(t.s)-1] _ = t.s[0:len(b)] + _ = t.s[2:len(t.s):len(t.s)] _ = t.s[:] _ = t.s[:10] @@ -50,6 +57,7 @@ var ( _ = t.s[:(len(t.s))] _ = t.s[:len(t.s)-1] _ = t.s[:len(b)] + _ = t.s[:len(t.s):len(t.s)] ) func _() { diff --git a/src/cmd/gofmt/testdata/slices1.input b/src/cmd/gofmt/testdata/slices1.input index 4d2cbfff4..1f25c43cc 100644 --- a/src/cmd/gofmt/testdata/slices1.input +++ b/src/cmd/gofmt/testdata/slices1.input @@ -1,3 +1,5 @@ +//gofmt -s + // Test cases for slice expression simplification. package p @@ -15,6 +17,7 @@ var ( _ = a[3:(len(a))] _ = a[len(a) : len(a)-1] _ = a[0:len(b)] + _ = a[2:len(a):len(a)] _ = a[:] _ = a[:10] @@ -22,6 +25,7 @@ var ( _ = a[:(len(a))] _ = a[:len(a)-1] _ = a[:len(b)] + _ = a[:len(a):len(a)] _ = s[0:] _ = s[1:10] @@ -29,6 +33,7 @@ var ( _ = s[3:(len(s))] _ = s[len(a) : len(s)-1] _ = s[0:len(b)] + _ = s[2:len(s):len(s)] _ = s[:] _ = s[:10] @@ -36,6 +41,7 @@ var ( _ = s[:(len(s))] _ = s[:len(s)-1] _ = s[:len(b)] + _ = s[:len(s):len(s)] _ = t.s[0:] _ = t.s[1:10] @@ -43,6 +49,7 @@ var ( _ = t.s[3:(len(t.s))] _ = t.s[len(a) : len(t.s)-1] _ = t.s[0:len(b)] + _ = t.s[2:len(t.s):len(t.s)] _ = t.s[:] _ = t.s[:10] @@ -50,6 +57,7 @@ var ( _ = t.s[:(len(t.s))] _ = t.s[:len(t.s)-1] _ = t.s[:len(b)] + _ = t.s[:len(t.s):len(t.s)] ) func _() { diff --git a/src/cmd/gofmt/testdata/slices2.golden b/src/cmd/gofmt/testdata/slices2.golden index 433788e1e..ab657004e 100644 --- a/src/cmd/gofmt/testdata/slices2.golden +++ b/src/cmd/gofmt/testdata/slices2.golden @@ -1,3 +1,5 @@ +//gofmt -s + // Test cases for slice expression simplification. // Because of a dot import, these slices must remain untouched. package p diff --git a/src/cmd/gofmt/testdata/slices2.input b/src/cmd/gofmt/testdata/slices2.input index 433788e1e..ab657004e 100644 --- a/src/cmd/gofmt/testdata/slices2.input +++ b/src/cmd/gofmt/testdata/slices2.input @@ -1,3 +1,5 @@ +//gofmt -s + // Test cases for slice expression simplification. // Because of a dot import, these slices must remain untouched. package p diff --git a/src/cmd/gofmt/testdata/stdin1.golden b/src/cmd/gofmt/testdata/stdin1.golden index ff8b0b7ab..9e4dcd20f 100644 --- a/src/cmd/gofmt/testdata/stdin1.golden +++ b/src/cmd/gofmt/testdata/stdin1.golden @@ -1,3 +1,5 @@ + //gofmt -stdin + if x { y } diff --git a/src/cmd/gofmt/testdata/stdin1.golden.gofmt b/src/cmd/gofmt/testdata/stdin1.golden.gofmt deleted file mode 100644 index 1f888877d..000000000 --- a/src/cmd/gofmt/testdata/stdin1.golden.gofmt +++ /dev/null @@ -1,3 +0,0 @@ - if x { - y -} diff --git a/src/cmd/gofmt/testdata/stdin1.input b/src/cmd/gofmt/testdata/stdin1.input index ff8b0b7ab..9e4dcd20f 100644 --- a/src/cmd/gofmt/testdata/stdin1.input +++ b/src/cmd/gofmt/testdata/stdin1.input @@ -1,3 +1,5 @@ + //gofmt -stdin + if x { y } diff --git a/src/cmd/gofmt/testdata/stdin1.input.gofmt b/src/cmd/gofmt/testdata/stdin1.input.gofmt deleted file mode 100644 index 1f888877d..000000000 --- a/src/cmd/gofmt/testdata/stdin1.input.gofmt +++ /dev/null @@ -1,3 +0,0 @@ - if x { - y -} diff --git a/src/cmd/gofmt/testdata/stdin2.golden b/src/cmd/gofmt/testdata/stdin2.golden index 7eb1b54fe..57df35540 100644 --- a/src/cmd/gofmt/testdata/stdin2.golden +++ b/src/cmd/gofmt/testdata/stdin2.golden @@ -1,4 +1,4 @@ - +//gofmt -stdin var x int diff --git a/src/cmd/gofmt/testdata/stdin2.golden.gofmt b/src/cmd/gofmt/testdata/stdin2.golden.gofmt deleted file mode 100644 index 85e800300..000000000 --- a/src/cmd/gofmt/testdata/stdin2.golden.gofmt +++ /dev/null @@ -1,10 +0,0 @@ - - - -var x int - -func f() { - y := z -} - - diff --git a/src/cmd/gofmt/testdata/stdin2.input b/src/cmd/gofmt/testdata/stdin2.input index 99defd2d1..69d6bdd68 100644 --- a/src/cmd/gofmt/testdata/stdin2.input +++ b/src/cmd/gofmt/testdata/stdin2.input @@ -1,4 +1,4 @@ - +//gofmt -stdin var x int diff --git a/src/cmd/gofmt/testdata/stdin2.input.gofmt b/src/cmd/gofmt/testdata/stdin2.input.gofmt deleted file mode 100644 index 7eb1b54fe..000000000 --- a/src/cmd/gofmt/testdata/stdin2.input.gofmt +++ /dev/null @@ -1,11 +0,0 @@ - - -var x int - -func f() { - y := z - /* this is a comment */ - // this is a comment too -} - - diff --git a/src/cmd/gofmt/testdata/stdin3.golden b/src/cmd/gofmt/testdata/stdin3.golden index 1bf2f5a48..d6da0e417 100644 --- a/src/cmd/gofmt/testdata/stdin3.golden +++ b/src/cmd/gofmt/testdata/stdin3.golden @@ -1,3 +1,4 @@ + //gofmt -stdin /* note: no newline at end of file */ for i := 0; i < 10; i++ { diff --git a/src/cmd/gofmt/testdata/stdin3.golden.gofmt b/src/cmd/gofmt/testdata/stdin3.golden.gofmt deleted file mode 100644 index b4d1d4663..000000000 --- a/src/cmd/gofmt/testdata/stdin3.golden.gofmt +++ /dev/null @@ -1,7 +0,0 @@ - - - /* note: no newline at end of file */ - for i := 0; i < 10; i++ { - s += i - } - \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin3.input b/src/cmd/gofmt/testdata/stdin3.input index d963bd0d2..ab46c1063 100644 --- a/src/cmd/gofmt/testdata/stdin3.input +++ b/src/cmd/gofmt/testdata/stdin3.input @@ -1,3 +1,4 @@ + //gofmt -stdin /* note: no newline at end of file */ for i := 0; i < 10; i++ { s += i } diff --git a/src/cmd/gofmt/testdata/stdin3.input.gofmt b/src/cmd/gofmt/testdata/stdin3.input.gofmt deleted file mode 100644 index b4d1d4663..000000000 --- a/src/cmd/gofmt/testdata/stdin3.input.gofmt +++ /dev/null @@ -1,7 +0,0 @@ - - - /* note: no newline at end of file */ - for i := 0; i < 10; i++ { - s += i - } - \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin4.golden b/src/cmd/gofmt/testdata/stdin4.golden index 5f7343551..0c7acace5 100644 --- a/src/cmd/gofmt/testdata/stdin4.golden +++ b/src/cmd/gofmt/testdata/stdin4.golden @@ -1,3 +1,5 @@ + //gofmt -stdin + // comment i := 0 diff --git a/src/cmd/gofmt/testdata/stdin4.golden.gofmt b/src/cmd/gofmt/testdata/stdin4.golden.gofmt deleted file mode 100644 index 5f7343551..000000000 --- a/src/cmd/gofmt/testdata/stdin4.golden.gofmt +++ /dev/null @@ -1,3 +0,0 @@ - // comment - - i := 0 diff --git a/src/cmd/gofmt/testdata/stdin4.input b/src/cmd/gofmt/testdata/stdin4.input index f02a54fb1..1fc73f31e 100644 --- a/src/cmd/gofmt/testdata/stdin4.input +++ b/src/cmd/gofmt/testdata/stdin4.input @@ -1,3 +1,5 @@ + //gofmt -stdin + // comment i := 0 diff --git a/src/cmd/gofmt/testdata/stdin4.input.gofmt b/src/cmd/gofmt/testdata/stdin4.input.gofmt deleted file mode 100644 index 5f7343551..000000000 --- a/src/cmd/gofmt/testdata/stdin4.input.gofmt +++ /dev/null @@ -1,3 +0,0 @@ - // comment - - i := 0 diff --git a/src/cmd/gofmt/testdata/stdin5.golden b/src/cmd/gofmt/testdata/stdin5.golden new file mode 100644 index 000000000..31ce6b248 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin5.golden @@ -0,0 +1,3 @@ +//gofmt -stdin + +i := 5 // Line comment without newline. \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin5.input b/src/cmd/gofmt/testdata/stdin5.input new file mode 100644 index 000000000..0a7c97d18 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin5.input @@ -0,0 +1,3 @@ +//gofmt -stdin + +i :=5// Line comment without newline. \ No newline at end of file diff --git a/src/cmd/gofmt/testdata/stdin6.golden b/src/cmd/gofmt/testdata/stdin6.golden new file mode 100644 index 000000000..ffcea8011 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin6.golden @@ -0,0 +1,19 @@ + //gofmt -stdin + + if err != nil { + source := strings.NewReader(`line 1. +line 2. +`) + return source + } + + f := func(hat, tail string) { + + fmt.Println(hat+` +foo + + +`+tail, + "more", + "and more") + } diff --git a/src/cmd/gofmt/testdata/stdin6.input b/src/cmd/gofmt/testdata/stdin6.input new file mode 100644 index 000000000..78330020c --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin6.input @@ -0,0 +1,21 @@ + //gofmt -stdin + + if err != nil { + source := strings.NewReader(`line 1. +line 2. +`) + return source + } + + f:=func( hat, tail string){ + + + + fmt. Println ( hat+ ` +foo + + +`+ tail , + "more" , + "and more" ) + } diff --git a/src/cmd/gofmt/testdata/stdin7.golden b/src/cmd/gofmt/testdata/stdin7.golden new file mode 100644 index 000000000..bbac7133c --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin7.golden @@ -0,0 +1,19 @@ + //gofmt -stdin + + if err != nil { + source := strings.NewReader(`line 1. +line 2. +`) + return source + } + + f := func(hat, tail string) { + + fmt.Println(hat+` + foo + + + `+tail, + "more", + "and more") + } diff --git a/src/cmd/gofmt/testdata/stdin7.input b/src/cmd/gofmt/testdata/stdin7.input new file mode 100644 index 000000000..fd772a3c4 --- /dev/null +++ b/src/cmd/gofmt/testdata/stdin7.input @@ -0,0 +1,21 @@ + //gofmt -stdin + + if err != nil { + source := strings.NewReader(`line 1. +line 2. +`) + return source + } + + f:=func( hat, tail string){ + + + + fmt. Println ( hat+ ` + foo + + + `+ tail , + "more" , + "and more" ) + } diff --git a/src/cmd/internal/goobj/read.go b/src/cmd/internal/goobj/read.go new file mode 100644 index 000000000..79a83e59a --- /dev/null +++ b/src/cmd/internal/goobj/read.go @@ -0,0 +1,666 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package goobj implements reading of Go object files and archives. +// +// TODO(rsc): Decide where this package should live. (golang.org/issue/6932) +// TODO(rsc): Decide the appropriate integer types for various fields. +// TODO(rsc): Write tests. (File format still up in the air a little.) +package goobj + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "strconv" + "strings" +) + +// A SymKind describes the kind of memory represented by a symbol. +type SymKind int + +// This list is taken from include/link.h. + +// Defined SymKind values. +// TODO(rsc): Give idiomatic Go names. +// TODO(rsc): Reduce the number of symbol types in the object files. +const ( + _ SymKind = iota + + // readonly, executable + STEXT + SELFRXSECT + + // readonly, non-executable + STYPE + SSTRING + SGOSTRING + SGOFUNC + SRODATA + SFUNCTAB + STYPELINK + SSYMTAB // TODO: move to unmapped section + SPCLNTAB + SELFROSECT + + // writable, non-executable + SMACHOPLT + SELFSECT + SMACHO // Mach-O __nl_symbol_ptr + SMACHOGOT + SNOPTRDATA + SINITARR + SDATA + SWINDOWS + SBSS + SNOPTRBSS + STLSBSS + + // not mapped + SXREF + SMACHOSYMSTR + SMACHOSYMTAB + SMACHOINDIRECTPLT + SMACHOINDIRECTGOT + SFILE + SFILEPATH + SCONST + SDYNIMPORT + SHOSTOBJ +) + +var symKindStrings = []string{ + SBSS: "SBSS", + SCONST: "SCONST", + SDATA: "SDATA", + SDYNIMPORT: "SDYNIMPORT", + SELFROSECT: "SELFROSECT", + SELFRXSECT: "SELFRXSECT", + SELFSECT: "SELFSECT", + SFILE: "SFILE", + SFILEPATH: "SFILEPATH", + SFUNCTAB: "SFUNCTAB", + SGOFUNC: "SGOFUNC", + SGOSTRING: "SGOSTRING", + SHOSTOBJ: "SHOSTOBJ", + SINITARR: "SINITARR", + SMACHO: "SMACHO", + SMACHOGOT: "SMACHOGOT", + SMACHOINDIRECTGOT: "SMACHOINDIRECTGOT", + SMACHOINDIRECTPLT: "SMACHOINDIRECTPLT", + SMACHOPLT: "SMACHOPLT", + SMACHOSYMSTR: "SMACHOSYMSTR", + SMACHOSYMTAB: "SMACHOSYMTAB", + SNOPTRBSS: "SNOPTRBSS", + SNOPTRDATA: "SNOPTRDATA", + SPCLNTAB: "SPCLNTAB", + SRODATA: "SRODATA", + SSTRING: "SSTRING", + SSYMTAB: "SSYMTAB", + STEXT: "STEXT", + STLSBSS: "STLSBSS", + STYPE: "STYPE", + STYPELINK: "STYPELINK", + SWINDOWS: "SWINDOWS", + SXREF: "SXREF", +} + +func (k SymKind) String() string { + if k < 0 || int(k) >= len(symKindStrings) { + return fmt.Sprintf("SymKind(%d)", k) + } + return symKindStrings[k] +} + +// A Sym is a named symbol in an object file. +type Sym struct { + SymID // symbol identifier (name and version) + Kind SymKind // kind of symbol + DupOK bool // are duplicate definitions okay? + Size int // size of corresponding data + Type SymID // symbol for Go type information + Data Data // memory image of symbol + Reloc []Reloc // relocations to apply to Data + Func *Func // additional data for functions +} + +// A SymID - the combination of Name and Version - uniquely identifies +// a symbol within a package. +type SymID struct { + // Name is the name of a symbol. + Name string + + // Version is zero for symbols with global visibility. + // Symbols with only file visibility (such as file-level static + // declarations in C) have a non-zero version distinguishing + // a symbol in one file from a symbol of the same name + // in another file + Version int +} + +func (s SymID) String() string { + if s.Version == 0 { + return s.Name + } + return fmt.Sprintf("%s<%d>", s.Name, s.Version) +} + +// A Data is a reference to data stored in an object file. +// It records the offset and size of the data, so that a client can +// read the data only if necessary. +type Data struct { + Offset int64 + Size int64 +} + +// A Reloc describes a relocation applied to a memory image to refer +// to an address within a particular symbol. +type Reloc struct { + // The bytes at [Offset, Offset+Size) within the memory image + // should be updated to refer to the address Add bytes after the start + // of the symbol Sym. + Offset int + Size int + Sym SymID + Add int + + // The Type records the form of address expected in the bytes + // described by the previous fields: absolute, PC-relative, and so on. + // TODO(rsc): The interpretation of Type is not exposed by this package. + Type int +} + +// A Var describes a variable in a function stack frame: a declared +// local variable, an input argument, or an output result. +type Var struct { + // The combination of Name, Kind, and Offset uniquely + // identifies a variable in a function stack frame. + // Using fewer of these - in particular, using only Name - does not. + Name string // Name of variable. + Kind int // TODO(rsc): Define meaning. + Offset int // Frame offset. TODO(rsc): Define meaning. + + Type SymID // Go type for variable. +} + +// Func contains additional per-symbol information specific to functions. +type Func struct { + Args int // size in bytes of argument frame: inputs and outputs + Frame int // size in bytes of local variable frame + Leaf bool // function omits save of link register (ARM) + NoSplit bool // function omits stack split prologue + Var []Var // detail about local variables + PCSP Data // PC → SP offset map + PCFile Data // PC → file number map (index into File) + PCLine Data // PC → line number map + PCData []Data // PC → runtime support data map + FuncData []FuncData // non-PC-specific runtime support data + File []string // paths indexed by PCFile +} + +// TODO: Add PCData []byte and PCDataIter (similar to liblink). + +// A FuncData is a single function-specific data value. +type FuncData struct { + Sym SymID // symbol holding data + Offset int64 // offset into symbol for funcdata pointer +} + +// A Package is a parsed Go object file or archive defining a Go package. +type Package struct { + ImportPath string // import path denoting this package + Imports []string // packages imported by this package + Syms []*Sym // symbols defined by this package + MaxVersion int // maximum Version in any SymID in Syms +} + +var ( + archiveHeader = []byte("!\n") + archiveMagic = []byte("`\n") + goobjHeader = []byte("go objec") // truncated to size of archiveHeader + + errCorruptArchive = errors.New("corrupt archive") + errTruncatedArchive = errors.New("truncated archive") + errNotArchive = errors.New("unrecognized archive format") + + errCorruptObject = errors.New("corrupt object file") + errTruncatedObject = errors.New("truncated object file") + errNotObject = errors.New("unrecognized object file format") +) + +// An objReader is an object file reader. +type objReader struct { + p *Package + b *bufio.Reader + f io.ReadSeeker + err error + offset int64 + limit int64 + tmp [256]byte + pkg string + pkgprefix string +} + +// importPathToPrefix returns the prefix that will be used in the +// final symbol table for the given import path. +// We escape '%', '"', all control characters and non-ASCII bytes, +// and any '.' after the final slash. +// +// See ../../../cmd/ld/lib.c:/^pathtoprefix and +// ../../../cmd/gc/subr.c:/^pathtoprefix. +func importPathToPrefix(s string) string { + // find index of last slash, if any, or else -1. + // used for determining whether an index is after the last slash. + slash := strings.LastIndex(s, "/") + + // check for chars that need escaping + n := 0 + for r := 0; r < len(s); r++ { + if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F { + n++ + } + } + + // quick exit + if n == 0 { + return s + } + + // escape + const hex = "0123456789abcdef" + p := make([]byte, 0, len(s)+2*n) + for r := 0; r < len(s); r++ { + if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F { + p = append(p, '%', hex[c>>4], hex[c&0xF]) + } else { + p = append(p, c) + } + } + + return string(p) +} + +// init initializes r to read package p from f. +func (r *objReader) init(f io.ReadSeeker, p *Package) { + r.f = f + r.p = p + r.offset, _ = f.Seek(0, 1) + r.limit, _ = f.Seek(0, 2) + f.Seek(r.offset, 0) + r.b = bufio.NewReader(f) + r.pkgprefix = importPathToPrefix(p.ImportPath) + "." +} + +// error records that an error occurred. +// It returns only the first error, so that an error +// caused by an earlier error does not discard information +// about the earlier error. +func (r *objReader) error(err error) error { + if r.err == nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + r.err = err + } + // panic("corrupt") // useful for debugging + return r.err +} + +// readByte reads and returns a byte from the input file. +// On I/O error or EOF, it records the error but returns byte 0. +// A sequence of 0 bytes will eventually terminate any +// parsing state in the object file. In particular, it ends the +// reading of a varint. +func (r *objReader) readByte() byte { + if r.err != nil { + return 0 + } + if r.offset >= r.limit { + r.error(io.ErrUnexpectedEOF) + return 0 + } + b, err := r.b.ReadByte() + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + r.error(err) + b = 0 + } else { + r.offset++ + } + return b +} + +// read reads exactly len(b) bytes from the input file. +// If an error occurs, read returns the error but also +// records it, so it is safe for callers to ignore the result +// as long as delaying the report is not a problem. +func (r *objReader) readFull(b []byte) error { + if r.err != nil { + return r.err + } + if r.offset+int64(len(b)) > r.limit { + return r.error(io.ErrUnexpectedEOF) + } + n, err := io.ReadFull(r.b, b) + r.offset += int64(n) + if err != nil { + return r.error(err) + } + return nil +} + +// readInt reads a zigzag varint from the input file. +func (r *objReader) readInt() int { + var u uint64 + + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + r.error(errCorruptObject) + return 0 + } + c := r.readByte() + u |= uint64(c&0x7F) << shift + if c&0x80 == 0 { + break + } + } + + v := int64(u>>1) ^ (int64(u) << 63 >> 63) + if int64(int(v)) != v { + r.error(errCorruptObject) // TODO + return 0 + } + return int(v) +} + +// readString reads a length-delimited string from the input file. +func (r *objReader) readString() string { + n := r.readInt() + buf := make([]byte, n) + r.readFull(buf) + return string(buf) +} + +// readSymID reads a SymID from the input file. +func (r *objReader) readSymID() SymID { + name, vers := r.readString(), r.readInt() + + // In a symbol name in an object file, "". denotes the + // prefix for the package in which the object file has been found. + // Expand it. + name = strings.Replace(name, `"".`, r.pkgprefix, -1) + + // An individual object file only records version 0 (extern) or 1 (static). + // To make static symbols unique across all files being read, we + // replace version 1 with the version corresponding to the current + // file number. The number is incremented on each call to parseObject. + if vers != 0 { + vers = r.p.MaxVersion + } + + return SymID{name, vers} +} + +// readData reads a data reference from the input file. +func (r *objReader) readData() Data { + n := r.readInt() + d := Data{Offset: r.offset, Size: int64(n)} + r.skip(int64(n)) + return d +} + +// skip skips n bytes in the input. +func (r *objReader) skip(n int64) { + if n < 0 { + r.error(fmt.Errorf("debug/goobj: internal error: misuse of skip")) + } + if n < int64(len(r.tmp)) { + // Since the data is so small, a just reading from the buffered + // reader is better than flushing the buffer and seeking. + r.readFull(r.tmp[:n]) + } else if n <= int64(r.b.Buffered()) { + // Even though the data is not small, it has already been read. + // Advance the buffer instead of seeking. + for n > int64(len(r.tmp)) { + r.readFull(r.tmp[:]) + n -= int64(len(r.tmp)) + } + r.readFull(r.tmp[:n]) + } else { + // Seek, giving up buffered data. + _, err := r.f.Seek(r.offset+n, 0) + if err != nil { + r.error(err) + } + r.offset += n + r.b.Reset(r.f) + } +} + +// Parse parses an object file or archive from r, +// assuming that its import path is pkgpath. +func Parse(r io.ReadSeeker, pkgpath string) (*Package, error) { + if pkgpath == "" { + pkgpath = `""` + } + p := new(Package) + p.ImportPath = pkgpath + + var rd objReader + rd.init(r, p) + err := rd.readFull(rd.tmp[:8]) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return nil, err + } + + switch { + default: + return nil, errNotObject + + case bytes.Equal(rd.tmp[:8], archiveHeader): + if err := rd.parseArchive(); err != nil { + return nil, err + } + case bytes.Equal(rd.tmp[:8], goobjHeader): + if err := rd.parseObject(goobjHeader); err != nil { + return nil, err + } + } + + return p, nil +} + +// trimSpace removes trailing spaces from b and returns the corresponding string. +// This effectively parses the form used in archive headers. +func trimSpace(b []byte) string { + return string(bytes.TrimRight(b, " ")) +} + +// parseArchive parses a Unix archive of Go object files. +// TODO(rsc): Need to skip non-Go object files. +// TODO(rsc): Maybe record table of contents in r.p so that +// linker can avoid having code to parse archives too. +func (r *objReader) parseArchive() error { + for r.offset < r.limit { + if err := r.readFull(r.tmp[:60]); err != nil { + return err + } + data := r.tmp[:60] + + // Each file is preceded by this text header (slice indices in first column): + // 0:16 name + // 16:28 date + // 28:34 uid + // 34:40 gid + // 40:48 mode + // 48:58 size + // 58:60 magic - `\n + // We only care about name, size, and magic. + // The fields are space-padded on the right. + // The size is in decimal. + // The file data - size bytes - follows the header. + // Headers are 2-byte aligned, so if size is odd, an extra padding + // byte sits between the file data and the next header. + // The file data that follows is padded to an even number of bytes: + // if size is odd, an extra padding byte is inserted betw the next header. + if len(data) < 60 { + return errTruncatedArchive + } + if !bytes.Equal(data[58:60], archiveMagic) { + return errCorruptArchive + } + name := trimSpace(data[0:16]) + size, err := strconv.ParseInt(trimSpace(data[48:58]), 10, 64) + if err != nil { + return errCorruptArchive + } + data = data[60:] + fsize := size + size&1 + if fsize < 0 || fsize < size { + return errCorruptArchive + } + switch name { + case "__.SYMDEF", "__.GOSYMDEF", "__.PKGDEF": + r.skip(size) + default: + oldLimit := r.limit + r.limit = r.offset + size + if err := r.parseObject(nil); err != nil { + return fmt.Errorf("parsing archive member %q: %v", name, err) + } + r.skip(r.limit - r.offset) + r.limit = oldLimit + } + if size&1 != 0 { + r.skip(1) + } + } + return nil +} + +// parseObject parses a single Go object file. +// The prefix is the bytes already read from the file, +// typically in order to detect that this is an object file. +// The object file consists of a textual header ending in "\n!\n" +// and then the part we want to parse begins. +// The format of that part is defined in a comment at the top +// of src/liblink/objfile.c. +func (r *objReader) parseObject(prefix []byte) error { + // TODO(rsc): Maybe use prefix and the initial input to + // record the header line from the file, which would + // give the architecture and other version information. + + r.p.MaxVersion++ + var c1, c2, c3 byte + for { + c1, c2, c3 = c2, c3, r.readByte() + if c3 == 0 { // NUL or EOF, either is bad + return errCorruptObject + } + if c1 == '\n' && c2 == '!' && c3 == '\n' { + break + } + } + + r.readFull(r.tmp[:8]) + if !bytes.Equal(r.tmp[:8], []byte("\x00\x00go13ld")) { + return r.error(errCorruptObject) + } + + b := r.readByte() + if b != 1 { + return r.error(errCorruptObject) + } + + // Direct package dependencies. + for { + s := r.readString() + if s == "" { + break + } + r.p.Imports = append(r.p.Imports, s) + } + + // Symbols. + for { + if b := r.readByte(); b != 0xfe { + if b != 0xff { + return r.error(errCorruptObject) + } + break + } + + typ := r.readInt() + s := &Sym{SymID: r.readSymID()} + r.p.Syms = append(r.p.Syms, s) + s.Kind = SymKind(typ) + flags := r.readInt() + s.DupOK = flags&1 != 0 + s.Size = r.readInt() + s.Type = r.readSymID() + s.Data = r.readData() + s.Reloc = make([]Reloc, r.readInt()) + for i := range s.Reloc { + rel := &s.Reloc[i] + rel.Offset = r.readInt() + rel.Size = r.readInt() + rel.Type = r.readInt() + rel.Add = r.readInt() + r.readInt() // Xadd - ignored + rel.Sym = r.readSymID() + r.readSymID() // Xsym - ignored + } + + if s.Kind == STEXT { + f := new(Func) + s.Func = f + f.Args = r.readInt() + f.Frame = r.readInt() + flags := r.readInt() + f.Leaf = flags&1 != 0 + f.NoSplit = r.readInt() != 0 + f.Var = make([]Var, r.readInt()) + for i := range f.Var { + v := &f.Var[i] + v.Name = r.readSymID().Name + v.Offset = r.readInt() + v.Kind = r.readInt() + v.Type = r.readSymID() + } + + f.PCSP = r.readData() + f.PCFile = r.readData() + f.PCLine = r.readData() + f.PCData = make([]Data, r.readInt()) + for i := range f.PCData { + f.PCData[i] = r.readData() + } + f.FuncData = make([]FuncData, r.readInt()) + for i := range f.FuncData { + f.FuncData[i].Sym = r.readSymID() + } + for i := range f.FuncData { + f.FuncData[i].Offset = int64(r.readInt()) // TODO + } + f.File = make([]string, r.readInt()) + for i := range f.File { + f.File[i] = r.readSymID().Name + } + } + } + + r.readFull(r.tmp[:7]) + if !bytes.Equal(r.tmp[:7], []byte("\xffgo13ld")) { + return r.error(errCorruptObject) + } + + return nil +} diff --git a/src/cmd/internal/goobj/read_test.go b/src/cmd/internal/goobj/read_test.go new file mode 100644 index 000000000..cc991e5d9 --- /dev/null +++ b/src/cmd/internal/goobj/read_test.go @@ -0,0 +1,28 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package goobj + +import "testing" + +var importPathToPrefixTests = []struct { + in string + out string +}{ + {"runtime", "runtime"}, + {"sync/atomic", "sync/atomic"}, + {"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"}, + {"foo.bar/baz.quux", "foo.bar/baz%2equux"}, + {"", ""}, + {"%foo%bar", "%25foo%25bar"}, + {"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"}, +} + +func TestImportPathToPrefix(t *testing.T) { + for _, tt := range importPathToPrefixTests { + if out := importPathToPrefix(tt.in); out != tt.out { + t.Errorf("importPathToPrefix(%q) = %q, want %q", tt.in, out, tt.out) + } + } +} diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go new file mode 100644 index 000000000..1a339c321 --- /dev/null +++ b/src/cmd/internal/objfile/disasm.go @@ -0,0 +1,248 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package objfile + +import ( + "bufio" + "debug/gosym" + "encoding/binary" + "fmt" + "io" + "regexp" + "sort" + "strings" + "text/tabwriter" + + "cmd/internal/rsc.io/arm/armasm" + "cmd/internal/rsc.io/x86/x86asm" +) + +// Disasm is a disassembler for a given File. +type Disasm struct { + syms []Sym //symbols in file, sorted by address + pcln *gosym.Table // pcln table + text []byte // bytes of text segment (actual instructions) + textStart uint64 // start PC of text + textEnd uint64 // end PC of text + goarch string // GOARCH string + disasm disasmFunc // disassembler function for goarch + byteOrder binary.ByteOrder // byte order for goarch +} + +// Disasm returns a disassembler for the file f. +func (f *File) Disasm() (*Disasm, error) { + syms, err := f.Symbols() + if err != nil { + return nil, err + } + + pcln, err := f.PCLineTable() + if err != nil { + return nil, err + } + + textStart, textBytes, err := f.Text() + if err != nil { + return nil, err + } + + goarch := f.GOARCH() + disasm := disasms[goarch] + byteOrder := byteOrders[goarch] + if disasm == nil || byteOrder == nil { + return nil, fmt.Errorf("unsupported architecture") + } + + // Filter out section symbols, overwriting syms in place. + keep := syms[:0] + for _, sym := range syms { + switch sym.Name { + case "runtime.text", "text", "_text", "runtime.etext", "etext", "_etext": + // drop + default: + keep = append(keep, sym) + } + } + syms = keep + d := &Disasm{ + syms: syms, + pcln: pcln, + text: textBytes, + textStart: textStart, + textEnd: textStart + uint64(len(textBytes)), + goarch: goarch, + disasm: disasm, + byteOrder: byteOrder, + } + + return d, nil +} + +// lookup finds the symbol name containing addr. +func (d *Disasm) lookup(addr uint64) (name string, base uint64) { + i := sort.Search(len(d.syms), func(i int) bool { return addr < d.syms[i].Addr }) + if i > 0 { + s := d.syms[i-1] + if s.Addr != 0 && s.Addr <= addr && addr < s.Addr+uint64(s.Size) { + return s.Name, s.Addr + } + } + return "", 0 +} + +// base returns the final element in the path. +// It works on both Windows and Unix paths, +// regardless of host operating system. +func base(path string) string { + path = path[strings.LastIndex(path, "/")+1:] + path = path[strings.LastIndex(path, `\`)+1:] + return path +} + +// Print prints a disassembly of the file to w. +// If filter is non-nil, the disassembly only includes functions with names matching filter. +// The disassembly only includes functions that overlap the range [start, end). +func (d *Disasm) Print(w io.Writer, filter *regexp.Regexp, start, end uint64) { + if start < d.textStart { + start = d.textStart + } + if end > d.textEnd { + end = d.textEnd + } + printed := false + bw := bufio.NewWriter(w) + for _, sym := range d.syms { + symStart := sym.Addr + symEnd := sym.Addr + uint64(sym.Size) + if sym.Code != 'T' && sym.Code != 't' || + symStart < d.textStart || + symEnd <= start || end <= symStart || + filter != nil && !filter.MatchString(sym.Name) { + continue + } + if printed { + fmt.Fprintf(bw, "\n") + } + printed = true + + file, _, _ := d.pcln.PCToLine(sym.Addr) + fmt.Fprintf(bw, "TEXT %s(SB) %s\n", sym.Name, file) + + tw := tabwriter.NewWriter(bw, 1, 8, 1, '\t', 0) + if symEnd > end { + symEnd = end + } + code := d.text[:end-d.textStart] + d.Decode(symStart, symEnd, func(pc, size uint64, file string, line int, text string) { + i := pc - d.textStart + fmt.Fprintf(tw, "\t%s:%d\t%#x\t", base(file), line, pc) + if size%4 != 0 || d.goarch == "386" || d.goarch == "amd64" { + // Print instruction as bytes. + fmt.Fprintf(tw, "%x", code[i:i+size]) + } else { + // Print instruction as 32-bit words. + for j := uint64(0); j < size; j += 4 { + if j > 0 { + fmt.Fprintf(tw, " ") + } + fmt.Fprintf(tw, "%08x", d.byteOrder.Uint32(code[i+j:])) + } + } + fmt.Fprintf(tw, "\t%s\n", text) + }) + tw.Flush() + } + bw.Flush() +} + +// Decode disassembles the text segment range [start, end), calling f for each instruction. +func (d *Disasm) Decode(start, end uint64, f func(pc, size uint64, file string, line int, text string)) { + if start < d.textStart { + start = d.textStart + } + if end > d.textEnd { + end = d.textEnd + } + code := d.text[:end-d.textStart] + lookup := d.lookup + for pc := start; pc < end; { + i := pc - d.textStart + text, size := d.disasm(code[i:], pc, lookup) + file, line, _ := d.pcln.PCToLine(pc) + f(pc, uint64(size), file, line, text) + pc += uint64(size) + } +} + +type lookupFunc func(addr uint64) (sym string, base uint64) +type disasmFunc func(code []byte, pc uint64, lookup lookupFunc) (text string, size int) + +func disasm_386(code []byte, pc uint64, lookup lookupFunc) (string, int) { + return disasm_x86(code, pc, lookup, 32) +} + +func disasm_amd64(code []byte, pc uint64, lookup lookupFunc) (string, int) { + return disasm_x86(code, pc, lookup, 64) +} + +func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, int) { + inst, err := x86asm.Decode(code, 64) + var text string + size := inst.Len + if err != nil || size == 0 || inst.Op == 0 { + size = 1 + text = "?" + } else { + text = x86asm.Plan9Syntax(inst, pc, lookup) + } + return text, size +} + +type textReader struct { + code []byte + pc uint64 +} + +func (r textReader) ReadAt(data []byte, off int64) (n int, err error) { + if off < 0 || uint64(off) < r.pc { + return 0, io.EOF + } + d := uint64(off) - r.pc + if d >= uint64(len(r.code)) { + return 0, io.EOF + } + n = copy(data, r.code[d:]) + if n < len(data) { + err = io.ErrUnexpectedEOF + } + return +} + +func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) { + inst, err := armasm.Decode(code, armasm.ModeARM) + var text string + size := inst.Len + if err != nil || size == 0 || inst.Op == 0 { + size = 4 + text = "?" + } else { + text = armasm.Plan9Syntax(inst, pc, lookup, textReader{code, pc}) + } + return text, size +} + +var disasms = map[string]disasmFunc{ + "386": disasm_386, + "amd64": disasm_amd64, + "arm": disasm_arm, +} + +var byteOrders = map[string]binary.ByteOrder{ + "386": binary.LittleEndian, + "amd64": binary.LittleEndian, + "arm": binary.LittleEndian, + "power64": binary.BigEndian, + "power64le": binary.LittleEndian, +} diff --git a/src/cmd/internal/objfile/elf.go b/src/cmd/internal/objfile/elf.go new file mode 100644 index 000000000..17755b84d --- /dev/null +++ b/src/cmd/internal/objfile/elf.go @@ -0,0 +1,104 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parsing of ELF executables (Linux, FreeBSD, and so on). + +package objfile + +import ( + "debug/elf" + "fmt" + "os" +) + +type elfFile struct { + elf *elf.File +} + +func openElf(r *os.File) (rawFile, error) { + f, err := elf.NewFile(r) + if err != nil { + return nil, err + } + return &elfFile{f}, nil +} + +func (f *elfFile) symbols() ([]Sym, error) { + elfSyms, err := f.elf.Symbols() + if err != nil { + return nil, err + } + + var syms []Sym + for _, s := range elfSyms { + sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'} + switch s.Section { + case elf.SHN_UNDEF: + sym.Code = 'U' + case elf.SHN_COMMON: + sym.Code = 'B' + default: + i := int(s.Section) + if i < 0 || i >= len(f.elf.Sections) { + break + } + sect := f.elf.Sections[i] + switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) { + case elf.SHF_ALLOC | elf.SHF_EXECINSTR: + sym.Code = 'T' + case elf.SHF_ALLOC: + sym.Code = 'R' + case elf.SHF_ALLOC | elf.SHF_WRITE: + sym.Code = 'D' + } + } + if elf.ST_BIND(s.Info) == elf.STB_LOCAL { + sym.Code += 'a' - 'A' + } + syms = append(syms, sym) + } + + return syms, nil +} + +func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { + if sect := f.elf.Section(".text"); sect != nil { + textStart = sect.Addr + } + if sect := f.elf.Section(".gosymtab"); sect != nil { + if symtab, err = sect.Data(); err != nil { + return 0, nil, nil, err + } + } + if sect := f.elf.Section(".gopclntab"); sect != nil { + if pclntab, err = sect.Data(); err != nil { + return 0, nil, nil, err + } + } + return textStart, symtab, pclntab, nil +} + +func (f *elfFile) text() (textStart uint64, text []byte, err error) { + sect := f.elf.Section(".text") + if sect == nil { + return 0, nil, fmt.Errorf("text section not found") + } + textStart = sect.Addr + text, err = sect.Data() + return +} + +func (f *elfFile) goarch() string { + switch f.elf.Machine { + case elf.EM_386: + return "386" + case elf.EM_X86_64: + return "amd64" + case elf.EM_ARM: + return "arm" + case elf.EM_PPC64: + return "power64" + } + return "" +} diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go new file mode 100644 index 000000000..6b1607a17 --- /dev/null +++ b/src/cmd/internal/objfile/goobj.go @@ -0,0 +1,93 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parsing of Go intermediate object files and archives. + +package objfile + +import ( + "cmd/internal/goobj" + "fmt" + "os" +) + +type goobjFile struct { + goobj *goobj.Package +} + +func openGoobj(r *os.File) (rawFile, error) { + f, err := goobj.Parse(r, `""`) + if err != nil { + return nil, err + } + return &goobjFile{f}, nil +} + +func goobjName(id goobj.SymID) string { + if id.Version == 0 { + return id.Name + } + return fmt.Sprintf("%s<%d>", id.Name, id.Version) +} + +func (f *goobjFile) symbols() ([]Sym, error) { + seen := make(map[goobj.SymID]bool) + + var syms []Sym + for _, s := range f.goobj.Syms { + seen[s.SymID] = true + sym := Sym{Addr: uint64(s.Data.Offset), Name: goobjName(s.SymID), Size: int64(s.Size), Type: s.Type.Name, Code: '?'} + switch s.Kind { + case goobj.STEXT, goobj.SELFRXSECT: + sym.Code = 'T' + case goobj.STYPE, goobj.SSTRING, goobj.SGOSTRING, goobj.SGOFUNC, goobj.SRODATA, goobj.SFUNCTAB, goobj.STYPELINK, goobj.SSYMTAB, goobj.SPCLNTAB, goobj.SELFROSECT: + sym.Code = 'R' + case goobj.SMACHOPLT, goobj.SELFSECT, goobj.SMACHO, goobj.SMACHOGOT, goobj.SNOPTRDATA, goobj.SINITARR, goobj.SDATA, goobj.SWINDOWS: + sym.Code = 'D' + case goobj.SBSS, goobj.SNOPTRBSS, goobj.STLSBSS: + sym.Code = 'B' + case goobj.SXREF, goobj.SMACHOSYMSTR, goobj.SMACHOSYMTAB, goobj.SMACHOINDIRECTPLT, goobj.SMACHOINDIRECTGOT, goobj.SFILE, goobj.SFILEPATH, goobj.SCONST, goobj.SDYNIMPORT, goobj.SHOSTOBJ: + sym.Code = 'X' // should not see + } + if s.Version != 0 { + sym.Code += 'a' - 'A' + } + syms = append(syms, sym) + } + + for _, s := range f.goobj.Syms { + for _, r := range s.Reloc { + if !seen[r.Sym] { + seen[r.Sym] = true + sym := Sym{Name: goobjName(r.Sym), Code: 'U'} + if s.Version != 0 { + // should not happen but handle anyway + sym.Code = 'u' + } + syms = append(syms, sym) + } + } + } + + return syms, nil +} + +// pcln does not make sense for Go object files, because each +// symbol has its own individual pcln table, so there is no global +// space of addresses to map. +func (f *goobjFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { + return 0, nil, nil, fmt.Errorf("pcln not available in go object file") +} + +// text does not make sense for Go object files, because +// each function has a separate section. +func (f *goobjFile) text() (textStart uint64, text []byte, err error) { + return 0, nil, fmt.Errorf("text not available in go object file") +} + +// goarch makes sense but is not exposed in debug/goobj's API, +// and we don't need it yet for any users of internal/objfile. +func (f *goobjFile) goarch() string { + return "GOARCH unimplemented for debug/goobj files" +} diff --git a/src/cmd/internal/objfile/macho.go b/src/cmd/internal/objfile/macho.go new file mode 100644 index 000000000..7dd84a339 --- /dev/null +++ b/src/cmd/internal/objfile/macho.go @@ -0,0 +1,116 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parsing of Mach-O executables (OS X). + +package objfile + +import ( + "debug/macho" + "fmt" + "os" + "sort" +) + +type machoFile struct { + macho *macho.File +} + +func openMacho(r *os.File) (rawFile, error) { + f, err := macho.NewFile(r) + if err != nil { + return nil, err + } + return &machoFile{f}, nil +} + +func (f *machoFile) symbols() ([]Sym, error) { + if f.macho.Symtab == nil { + return nil, fmt.Errorf("missing symbol table") + } + + // Build sorted list of addresses of all symbols. + // We infer the size of a symbol by looking at where the next symbol begins. + var addrs []uint64 + for _, s := range f.macho.Symtab.Syms { + addrs = append(addrs, s.Value) + } + sort.Sort(uint64s(addrs)) + + var syms []Sym + for _, s := range f.macho.Symtab.Syms { + sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'} + i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) + if i < len(addrs) { + sym.Size = int64(addrs[i] - s.Value) + } + if s.Sect == 0 { + sym.Code = 'U' + } else if int(s.Sect) <= len(f.macho.Sections) { + sect := f.macho.Sections[s.Sect-1] + switch sect.Seg { + case "__TEXT": + sym.Code = 'R' + case "__DATA": + sym.Code = 'D' + } + switch sect.Seg + " " + sect.Name { + case "__TEXT __text": + sym.Code = 'T' + case "__DATA __bss", "__DATA __noptrbss": + sym.Code = 'B' + } + } + syms = append(syms, sym) + } + + return syms, nil +} + +func (f *machoFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { + if sect := f.macho.Section("__text"); sect != nil { + textStart = sect.Addr + } + if sect := f.macho.Section("__gosymtab"); sect != nil { + if symtab, err = sect.Data(); err != nil { + return 0, nil, nil, err + } + } + if sect := f.macho.Section("__gopclntab"); sect != nil { + if pclntab, err = sect.Data(); err != nil { + return 0, nil, nil, err + } + } + return textStart, symtab, pclntab, nil +} + +func (f *machoFile) text() (textStart uint64, text []byte, err error) { + sect := f.macho.Section("__text") + if sect == nil { + return 0, nil, fmt.Errorf("text section not found") + } + textStart = sect.Addr + text, err = sect.Data() + return +} + +func (f *machoFile) goarch() string { + switch f.macho.Cpu { + case macho.Cpu386: + return "386" + case macho.CpuAmd64: + return "amd64" + case macho.CpuArm: + return "arm" + case macho.CpuPpc64: + return "power64" + } + return "" +} + +type uint64s []uint64 + +func (x uint64s) Len() int { return len(x) } +func (x uint64s) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x uint64s) Less(i, j int) bool { return x[i] < x[j] } diff --git a/src/cmd/internal/objfile/objfile.go b/src/cmd/internal/objfile/objfile.go new file mode 100644 index 000000000..9227ef387 --- /dev/null +++ b/src/cmd/internal/objfile/objfile.go @@ -0,0 +1,94 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package objfile implements portable access to OS-specific executable files. +package objfile + +import ( + "debug/gosym" + "fmt" + "os" + "sort" +) + +type rawFile interface { + symbols() (syms []Sym, err error) + pcln() (textStart uint64, symtab, pclntab []byte, err error) + text() (textStart uint64, text []byte, err error) + goarch() string +} + +// A File is an opened executable file. +type File struct { + r *os.File + raw rawFile +} + +// A Sym is a symbol defined in an executable file. +type Sym struct { + Name string // symbol name + Addr uint64 // virtual address of symbol + Size int64 // size in bytes + Code rune // nm code (T for text, D for data, and so on) + Type string // XXX? +} + +var openers = []func(*os.File) (rawFile, error){ + openElf, + openGoobj, + openMacho, + openPE, + openPlan9, +} + +// Open opens the named file. +// The caller must call f.Close when the file is no longer needed. +func Open(name string) (*File, error) { + r, err := os.Open(name) + if err != nil { + return nil, err + } + for _, try := range openers { + if raw, err := try(r); err == nil { + return &File{r, raw}, nil + } + } + r.Close() + return nil, fmt.Errorf("open %s: unrecognized object file", name) +} + +func (f *File) Close() error { + return f.r.Close() +} + +func (f *File) Symbols() ([]Sym, error) { + syms, err := f.raw.symbols() + if err != nil { + return nil, err + } + sort.Sort(byAddr(syms)) + return syms, nil +} + +type byAddr []Sym + +func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr } +func (x byAddr) Len() int { return len(x) } +func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func (f *File) PCLineTable() (*gosym.Table, error) { + textStart, symtab, pclntab, err := f.raw.pcln() + if err != nil { + return nil, err + } + return gosym.NewTable(symtab, gosym.NewLineTable(pclntab, textStart)) +} + +func (f *File) Text() (uint64, []byte, error) { + return f.raw.text() +} + +func (f *File) GOARCH() string { + return f.raw.goarch() +} diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go new file mode 100644 index 000000000..67e59c226 --- /dev/null +++ b/src/cmd/internal/objfile/pe.go @@ -0,0 +1,201 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parsing of PE executables (Microsoft Windows). + +package objfile + +import ( + "debug/pe" + "fmt" + "os" + "sort" +) + +type peFile struct { + pe *pe.File +} + +func openPE(r *os.File) (rawFile, error) { + f, err := pe.NewFile(r) + if err != nil { + return nil, err + } + switch f.OptionalHeader.(type) { + case *pe.OptionalHeader32, *pe.OptionalHeader64: + // ok + default: + return nil, fmt.Errorf("unrecognized PE format") + } + return &peFile{f}, nil +} + +func (f *peFile) symbols() ([]Sym, error) { + // Build sorted list of addresses of all symbols. + // We infer the size of a symbol by looking at where the next symbol begins. + var addrs []uint64 + + var imageBase uint64 + switch oh := f.pe.OptionalHeader.(type) { + case *pe.OptionalHeader32: + imageBase = uint64(oh.ImageBase) + case *pe.OptionalHeader64: + imageBase = oh.ImageBase + } + + var syms []Sym + for _, s := range f.pe.Symbols { + const ( + N_UNDEF = 0 // An undefined (extern) symbol + N_ABS = -1 // An absolute symbol (e_value is a constant, not an address) + N_DEBUG = -2 // A debugging symbol + ) + sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'} + switch s.SectionNumber { + case N_UNDEF: + sym.Code = 'U' + case N_ABS: + sym.Code = 'C' + case N_DEBUG: + sym.Code = '?' + default: + if s.SectionNumber < 0 || len(f.pe.Sections) < int(s.SectionNumber) { + return nil, fmt.Errorf("invalid section number in symbol table") + } + sect := f.pe.Sections[s.SectionNumber-1] + const ( + text = 0x20 + data = 0x40 + bss = 0x80 + permX = 0x20000000 + permR = 0x40000000 + permW = 0x80000000 + ) + ch := sect.Characteristics + switch { + case ch&text != 0: + sym.Code = 'T' + case ch&data != 0: + if ch&permW == 0 { + sym.Code = 'R' + } else { + sym.Code = 'D' + } + case ch&bss != 0: + sym.Code = 'B' + } + sym.Addr += imageBase + uint64(sect.VirtualAddress) + } + syms = append(syms, sym) + addrs = append(addrs, sym.Addr) + } + + sort.Sort(uint64s(addrs)) + for i := range syms { + j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr }) + if j < len(addrs) { + syms[i].Size = int64(addrs[j] - syms[i].Addr) + } + } + + return syms, nil +} + +func (f *peFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { + var imageBase uint64 + switch oh := f.pe.OptionalHeader.(type) { + case *pe.OptionalHeader32: + imageBase = uint64(oh.ImageBase) + case *pe.OptionalHeader64: + imageBase = oh.ImageBase + default: + return 0, nil, nil, fmt.Errorf("pe file format not recognized") + } + if sect := f.pe.Section(".text"); sect != nil { + textStart = imageBase + uint64(sect.VirtualAddress) + } + if pclntab, err = loadPETable(f.pe, "runtime.pclntab", "runtime.epclntab"); err != nil { + // We didn't find the symbols, so look for the names used in 1.3 and earlier. + // TODO: Remove code looking for the old symbols when we no longer care about 1.3. + var err2 error + if pclntab, err2 = loadPETable(f.pe, "pclntab", "epclntab"); err2 != nil { + return 0, nil, nil, err + } + } + if symtab, err = loadPETable(f.pe, "runtime.symtab", "runtime.esymtab"); err != nil { + // Same as above. + var err2 error + if symtab, err2 = loadPETable(f.pe, "symtab", "esymtab"); err2 != nil { + return 0, nil, nil, err + } + } + return textStart, symtab, pclntab, nil +} + +func (f *peFile) text() (textStart uint64, text []byte, err error) { + var imageBase uint64 + switch oh := f.pe.OptionalHeader.(type) { + case *pe.OptionalHeader32: + imageBase = uint64(oh.ImageBase) + case *pe.OptionalHeader64: + imageBase = oh.ImageBase + default: + return 0, nil, fmt.Errorf("pe file format not recognized") + } + sect := f.pe.Section(".text") + if sect == nil { + return 0, nil, fmt.Errorf("text section not found") + } + textStart = imageBase + uint64(sect.VirtualAddress) + text, err = sect.Data() + return +} + +func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) { + for _, s := range f.Symbols { + if s.Name != name { + continue + } + if s.SectionNumber <= 0 { + return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) + } + if len(f.Sections) < int(s.SectionNumber) { + return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) + } + return s, nil + } + return nil, fmt.Errorf("no %s symbol found", name) +} + +func loadPETable(f *pe.File, sname, ename string) ([]byte, error) { + ssym, err := findPESymbol(f, sname) + if err != nil { + return nil, err + } + esym, err := findPESymbol(f, ename) + if err != nil { + return nil, err + } + if ssym.SectionNumber != esym.SectionNumber { + return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) + } + sect := f.Sections[ssym.SectionNumber-1] + data, err := sect.Data() + if err != nil { + return nil, err + } + return data[ssym.Value:esym.Value], nil +} + +func (f *peFile) goarch() string { + // Not sure how to get the info we want from PE header. + // Look in symbol table for telltale rt0 symbol. + if _, err := findPESymbol(f.pe, "_rt0_386_windows"); err == nil { + return "386" + } + if _, err := findPESymbol(f.pe, "_rt0_amd64_windows"); err == nil { + return "amd64" + } + return "" +} diff --git a/src/cmd/internal/objfile/plan9obj.go b/src/cmd/internal/objfile/plan9obj.go new file mode 100644 index 000000000..eb6cba5eb --- /dev/null +++ b/src/cmd/internal/objfile/plan9obj.go @@ -0,0 +1,146 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parsing of Plan 9 a.out executables. + +package objfile + +import ( + "debug/plan9obj" + "fmt" + "os" + "sort" +) + +var validSymType = map[rune]bool{ + 'T': true, + 't': true, + 'D': true, + 'd': true, + 'B': true, + 'b': true, +} + +type plan9File struct { + plan9 *plan9obj.File +} + +func openPlan9(r *os.File) (rawFile, error) { + f, err := plan9obj.NewFile(r) + if err != nil { + return nil, err + } + return &plan9File{f}, nil +} + +func (f *plan9File) symbols() ([]Sym, error) { + plan9Syms, err := f.plan9.Symbols() + if err != nil { + return nil, err + } + + // Build sorted list of addresses of all symbols. + // We infer the size of a symbol by looking at where the next symbol begins. + var addrs []uint64 + for _, s := range plan9Syms { + if !validSymType[s.Type] { + continue + } + addrs = append(addrs, s.Value) + } + sort.Sort(uint64s(addrs)) + + var syms []Sym + + for _, s := range plan9Syms { + if !validSymType[s.Type] { + continue + } + sym := Sym{Addr: s.Value, Name: s.Name, Code: rune(s.Type)} + i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) + if i < len(addrs) { + sym.Size = int64(addrs[i] - s.Value) + } + syms = append(syms, sym) + } + + return syms, nil +} + +func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) { + textStart = f.plan9.LoadAddress + f.plan9.HdrSize + if pclntab, err = loadPlan9Table(f.plan9, "runtime.pclntab", "runtime.epclntab"); err != nil { + // We didn't find the symbols, so look for the names used in 1.3 and earlier. + // TODO: Remove code looking for the old symbols when we no longer care about 1.3. + var err2 error + if pclntab, err2 = loadPlan9Table(f.plan9, "pclntab", "epclntab"); err2 != nil { + return 0, nil, nil, err + } + } + if symtab, err = loadPlan9Table(f.plan9, "runtime.symtab", "runtime.esymtab"); err != nil { + // Same as above. + var err2 error + if symtab, err2 = loadPlan9Table(f.plan9, "symtab", "esymtab"); err2 != nil { + return 0, nil, nil, err + } + } + return textStart, symtab, pclntab, nil +} + +func (f *plan9File) text() (textStart uint64, text []byte, err error) { + sect := f.plan9.Section("text") + if sect == nil { + return 0, nil, fmt.Errorf("text section not found") + } + textStart = f.plan9.LoadAddress + f.plan9.HdrSize + text, err = sect.Data() + return +} + +func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) { + syms, err := f.Symbols() + if err != nil { + return nil, err + } + for _, s := range syms { + if s.Name != name { + continue + } + return &s, nil + } + return nil, fmt.Errorf("no %s symbol found", name) +} + +func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) { + ssym, err := findPlan9Symbol(f, sname) + if err != nil { + return nil, err + } + esym, err := findPlan9Symbol(f, ename) + if err != nil { + return nil, err + } + sect := f.Section("text") + if sect == nil { + return nil, err + } + data, err := sect.Data() + if err != nil { + return nil, err + } + textStart := f.LoadAddress + f.HdrSize + return data[ssym.Value-textStart : esym.Value-textStart], nil +} + +func (f *plan9File) goarch() string { + switch f.plan9.Magic { + case plan9obj.Magic386: + return "386" + case plan9obj.MagicAMD64: + return "amd64" + case plan9obj.MagicARM: + return "arm" + } + return "" +} diff --git a/src/cmd/internal/rsc.io/arm/armasm/Makefile b/src/cmd/internal/rsc.io/arm/armasm/Makefile new file mode 100644 index 000000000..a3f57001f --- /dev/null +++ b/src/cmd/internal/rsc.io/arm/armasm/Makefile @@ -0,0 +1,2 @@ +tables.go: ../armmap/map.go ../arm.csv + go run ../armmap/map.go -fmt=decoder ../arm.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode.go b/src/cmd/internal/rsc.io/arm/armasm/decode.go new file mode 100644 index 000000000..6b4d73841 --- /dev/null +++ b/src/cmd/internal/rsc.io/arm/armasm/decode.go @@ -0,0 +1,567 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package armasm + +import ( + "encoding/binary" + "fmt" +) + +// An instFormat describes the format of an instruction encoding. +// An instruction with 32-bit value x matches the format if x&mask == value +// and the condition matches. +// The condition matches if x>>28 == 0xF && value>>28==0xF +// or if x>>28 != 0xF and value>>28 == 0. +// If x matches the format, then the rest of the fields describe how to interpret x. +// The opBits describe bits that should be extracted from x and added to the opcode. +// For example opBits = 0x1234 means that the value +// (2 bits at offset 1) followed by (4 bits at offset 3) +// should be added to op. +// Finally the args describe how to decode the instruction arguments. +// args is stored as a fixed-size array; if there are fewer than len(args) arguments, +// args[i] == 0 marks the end of the argument list. +type instFormat struct { + mask uint32 + value uint32 + priority int8 + op Op + opBits uint64 + args instArgs +} + +type instArgs [4]instArg + +var ( + errMode = fmt.Errorf("unsupported execution mode") + errShort = fmt.Errorf("truncated instruction") + errUnknown = fmt.Errorf("unknown instruction") +) + +var decoderCover []bool + +// Decode decodes the leading bytes in src as a single instruction. +func Decode(src []byte, mode Mode) (inst Inst, err error) { + if mode != ModeARM { + return Inst{}, errMode + } + if len(src) < 4 { + return Inst{}, errShort + } + + if decoderCover == nil { + decoderCover = make([]bool, len(instFormats)) + } + + x := binary.LittleEndian.Uint32(src) + + // The instFormat table contains both conditional and unconditional instructions. + // Considering only the top 4 bits, the conditional instructions use mask=0, value=0, + // while the unconditional instructions use mask=f, value=f. + // Prepare a version of x with the condition cleared to 0 in conditional instructions + // and then assume mask=f during matching. + const condMask = 0xf0000000 + xNoCond := x + if x&condMask != condMask { + xNoCond &^= condMask + } + var priority int8 +Search: + for i := range instFormats { + f := &instFormats[i] + if xNoCond&(f.mask|condMask) != f.value || f.priority <= priority { + continue + } + delta := uint32(0) + deltaShift := uint(0) + for opBits := f.opBits; opBits != 0; opBits >>= 16 { + n := uint(opBits & 0xFF) + off := uint((opBits >> 8) & 0xFF) + delta |= (x >> off) & (1<> 8) & (1<<4 - 1)) + case arg_R_12: + return Reg((x >> 12) & (1<<4 - 1)) + case arg_R_16: + return Reg((x >> 16) & (1<<4 - 1)) + + case arg_R_12_nzcv: + r := Reg((x >> 12) & (1<<4 - 1)) + if r == R15 { + return APSR_nzcv + } + return r + + case arg_R_16_WB: + mode := AddrLDM + if (x>>21)&1 != 0 { + mode = AddrLDM_WB + } + return Mem{Base: Reg((x >> 16) & (1<<4 - 1)), Mode: mode} + + case arg_R_rotate: + Rm := Reg(x & (1<<4 - 1)) + typ, count := decodeShift(x) + // ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1. + if typ == RotateRightExt { + return Reg(Rm) + } + return RegShift{Rm, typ, uint8(count)} + + case arg_R_shift_R: + Rm := Reg(x & (1<<4 - 1)) + Rs := Reg((x >> 8) & (1<<4 - 1)) + typ := Shift((x >> 5) & (1<<2 - 1)) + return RegShiftReg{Rm, typ, Rs} + + case arg_R_shift_imm: + Rm := Reg(x & (1<<4 - 1)) + typ, count := decodeShift(x) + if typ == ShiftLeft && count == 0 { + return Reg(Rm) + } + return RegShift{Rm, typ, uint8(count)} + + case arg_R1_0: + return Reg((x & (1<<4 - 1))) + case arg_R1_12: + return Reg(((x >> 12) & (1<<4 - 1))) + case arg_R2_0: + return Reg((x & (1<<4 - 1)) | 1) + case arg_R2_12: + return Reg(((x >> 12) & (1<<4 - 1)) | 1) + + case arg_SP: + return SP + + case arg_Sd_Dd: + v := (x >> 12) & (1<<4 - 1) + vx := (x >> 22) & 1 + sz := (x >> 8) & 1 + if sz != 0 { + return D0 + Reg(vx<<4+v) + } else { + return S0 + Reg(v<<1+vx) + } + + case arg_Dd_Sd: + return decodeArg(arg_Sd_Dd, x^(1<<8)) + + case arg_Sd: + v := (x >> 12) & (1<<4 - 1) + vx := (x >> 22) & 1 + return S0 + Reg(v<<1+vx) + + case arg_Sm_Dm: + v := (x >> 0) & (1<<4 - 1) + vx := (x >> 5) & 1 + sz := (x >> 8) & 1 + if sz != 0 { + return D0 + Reg(vx<<4+v) + } else { + return S0 + Reg(v<<1+vx) + } + + case arg_Sm: + v := (x >> 0) & (1<<4 - 1) + vx := (x >> 5) & 1 + return S0 + Reg(v<<1+vx) + + case arg_Dn_half: + v := (x >> 16) & (1<<4 - 1) + vx := (x >> 7) & 1 + return RegX{D0 + Reg(vx<<4+v), int((x >> 21) & 1)} + + case arg_Sn_Dn: + v := (x >> 16) & (1<<4 - 1) + vx := (x >> 7) & 1 + sz := (x >> 8) & 1 + if sz != 0 { + return D0 + Reg(vx<<4+v) + } else { + return S0 + Reg(v<<1+vx) + } + + case arg_Sn: + v := (x >> 16) & (1<<4 - 1) + vx := (x >> 7) & 1 + return S0 + Reg(v<<1+vx) + + case arg_const: + v := x & (1<<8 - 1) + rot := (x >> 8) & (1<<4 - 1) * 2 + if rot > 0 && v&3 == 0 { + // could rotate less + return ImmAlt{uint8(v), uint8(rot)} + } + if rot >= 24 && ((v<<(32-rot))&0xFF)>>(32-rot) == v { + // could wrap around to rot==0. + return ImmAlt{uint8(v), uint8(rot)} + } + return Imm(v>>rot | v<<(32-rot)) + + case arg_endian: + return Endian((x >> 9) & 1) + + case arg_fbits: + return Imm((16 << ((x >> 7) & 1)) - ((x&(1<<4-1))<<1 | (x>>5)&1)) + + case arg_fp_0: + return Imm(0) + + case arg_imm24: + return Imm(x & (1<<24 - 1)) + + case arg_imm5: + return Imm((x >> 7) & (1<<5 - 1)) + + case arg_imm5_32: + x = (x >> 7) & (1<<5 - 1) + if x == 0 { + x = 32 + } + return Imm(x) + + case arg_imm5_nz: + x = (x >> 7) & (1<<5 - 1) + if x == 0 { + return nil + } + return Imm(x) + + case arg_imm_4at16_12at0: + return Imm((x>>16)&(1<<4-1)<<12 | x&(1<<12-1)) + + case arg_imm_12at8_4at0: + return Imm((x>>8)&(1<<12-1)<<4 | x&(1<<4-1)) + + case arg_imm_vfp: + x = (x>>16)&(1<<4-1)<<4 | x&(1<<4-1) + return Imm(x) + + case arg_label24: + imm := (x & (1<<24 - 1)) << 2 + return PCRel(int32(imm<<6) >> 6) + + case arg_label24H: + h := (x >> 24) & 1 + imm := (x&(1<<24-1))<<2 | h<<1 + return PCRel(int32(imm<<6) >> 6) + + case arg_label_m_12: + d := int32(x & (1<<12 - 1)) + return Mem{Base: PC, Mode: AddrOffset, Offset: int16(-d)} + + case arg_label_p_12: + d := int32(x & (1<<12 - 1)) + return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)} + + case arg_label_pm_12: + d := int32(x & (1<<12 - 1)) + u := (x >> 23) & 1 + if u == 0 { + d = -d + } + return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)} + + case arg_label_pm_4_4: + d := int32((x>>8)&(1<<4-1)<<4 | x&(1<<4-1)) + u := (x >> 23) & 1 + if u == 0 { + d = -d + } + return PCRel(d) + + case arg_lsb_width: + lsb := (x >> 7) & (1<<5 - 1) + msb := (x >> 16) & (1<<5 - 1) + if msb < lsb || msb >= 32 { + return nil + } + return Imm(msb + 1 - lsb) + + case arg_mem_R: + Rn := Reg((x >> 16) & (1<<4 - 1)) + return Mem{Base: Rn, Mode: AddrOffset} + + case arg_mem_R_pm_R_postindex: + // Treat [],+/- like [,+/-{,}]{!} + // by forcing shift bits to <<0 and P=0, W=0 (postindex=true). + return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5|1<<24|1<<21)) + + case arg_mem_R_pm_R_W: + // Treat [,+/-]{!} like [,+/-{,}]{!} + // by forcing shift bits to <<0. + return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5)) + + case arg_mem_R_pm_R_shift_imm_offset: + // Treat [],+/-{,} like [,+/-{,}]{!} + // by forcing P=1, W=0 (index=false, wback=false). + return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<21)|1<<24) + + case arg_mem_R_pm_R_shift_imm_postindex: + // Treat [],+/-{,} like [,+/-{,}]{!} + // by forcing P=0, W=0 (postindex=true). + return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<24|1<<21)) + + case arg_mem_R_pm_R_shift_imm_W: + Rn := Reg((x >> 16) & (1<<4 - 1)) + Rm := Reg(x & (1<<4 - 1)) + typ, count := decodeShift(x) + u := (x >> 23) & 1 + w := (x >> 21) & 1 + p := (x >> 24) & 1 + if p == 0 && w == 1 { + return nil + } + sign := int8(+1) + if u == 0 { + sign = -1 + } + mode := AddrMode(uint8(p<<1) | uint8(w^1)) + return Mem{Base: Rn, Mode: mode, Sign: sign, Index: Rm, Shift: typ, Count: count} + + case arg_mem_R_pm_imm12_offset: + // Treat [,#+/-] like [{,#+/-}]{!} + // by forcing P=1, W=0 (index=false, wback=false). + return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<21)|1<<24) + + case arg_mem_R_pm_imm12_postindex: + // Treat [],#+/- like [{,#+/-}]{!} + // by forcing P=0, W=0 (postindex=true). + return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<24|1<<21)) + + case arg_mem_R_pm_imm12_W: + Rn := Reg((x >> 16) & (1<<4 - 1)) + u := (x >> 23) & 1 + w := (x >> 21) & 1 + p := (x >> 24) & 1 + if p == 0 && w == 1 { + return nil + } + sign := int8(+1) + if u == 0 { + sign = -1 + } + imm := int16(x & (1<<12 - 1)) + mode := AddrMode(uint8(p<<1) | uint8(w^1)) + return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm} + + case arg_mem_R_pm_imm8_postindex: + // Treat [],#+/- like [{,#+/-}]{!} + // by forcing P=0, W=0 (postindex=true). + return decodeArg(arg_mem_R_pm_imm8_W, x&^(1<<24|1<<21)) + + case arg_mem_R_pm_imm8_W: + Rn := Reg((x >> 16) & (1<<4 - 1)) + u := (x >> 23) & 1 + w := (x >> 21) & 1 + p := (x >> 24) & 1 + if p == 0 && w == 1 { + return nil + } + sign := int8(+1) + if u == 0 { + sign = -1 + } + imm := int16((x>>8)&(1<<4-1)<<4 | x&(1<<4-1)) + mode := AddrMode(uint8(p<<1) | uint8(w^1)) + return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm} + + case arg_mem_R_pm_imm8at0_offset: + Rn := Reg((x >> 16) & (1<<4 - 1)) + u := (x >> 23) & 1 + sign := int8(+1) + if u == 0 { + sign = -1 + } + imm := int16(x&(1<<8-1)) << 2 + return Mem{Base: Rn, Mode: AddrOffset, Offset: int16(sign) * imm} + + case arg_option: + return Imm(x & (1<<4 - 1)) + + case arg_registers: + return RegList(x & (1<<16 - 1)) + + case arg_registers2: + x &= 1<<16 - 1 + n := 0 + for i := 0; i < 16; i++ { + if x>>uint(i)&1 != 0 { + n++ + } + } + if n < 2 { + return nil + } + return RegList(x) + + case arg_registers1: + Rt := (x >> 12) & (1<<4 - 1) + return RegList(1 << Rt) + + case arg_satimm4: + return Imm((x >> 16) & (1<<4 - 1)) + + case arg_satimm5: + return Imm((x >> 16) & (1<<5 - 1)) + + case arg_satimm4m1: + return Imm((x>>16)&(1<<4-1) + 1) + + case arg_satimm5m1: + return Imm((x>>16)&(1<<5-1) + 1) + + case arg_widthm1: + return Imm((x>>16)&(1<<5-1) + 1) + + } +} + +// decodeShift decodes the shift-by-immediate encoded in x. +func decodeShift(x uint32) (Shift, uint8) { + count := (x >> 7) & (1<<5 - 1) + typ := Shift((x >> 5) & (1<<2 - 1)) + switch typ { + case ShiftRight, ShiftRightSigned: + if count == 0 { + count = 32 + } + case RotateRight: + if count == 0 { + typ = RotateRightExt + count = 1 + } + } + return typ, uint8(count) +} diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode_test.go b/src/cmd/internal/rsc.io/arm/armasm/decode_test.go new file mode 100644 index 000000000..25a345a88 --- /dev/null +++ b/src/cmd/internal/rsc.io/arm/armasm/decode_test.go @@ -0,0 +1,69 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package armasm + +import ( + "encoding/hex" + "io/ioutil" + "strconv" + "strings" + "testing" +) + +func TestDecode(t *testing.T) { + data, err := ioutil.ReadFile("testdata/decode.txt") + if err != nil { + t.Fatal(err) + } + all := string(data) + for strings.Contains(all, "\t\t") { + all = strings.Replace(all, "\t\t", "\t", -1) + } + for _, line := range strings.Split(all, "\n") { + line = strings.TrimSpace(line) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + f := strings.SplitN(line, "\t", 4) + i := strings.Index(f[0], "|") + if i < 0 { + t.Errorf("parsing %q: missing | separator", f[0]) + continue + } + if i%2 != 0 { + t.Errorf("parsing %q: misaligned | separator", f[0]) + } + size := i / 2 + code, err := hex.DecodeString(f[0][:i] + f[0][i+1:]) + if err != nil { + t.Errorf("parsing %q: %v", f[0], err) + continue + } + mode, err := strconv.Atoi(f[1]) + if err != nil { + t.Errorf("invalid mode %q in: %s", f[1], line) + continue + } + syntax, asm := f[2], f[3] + inst, err := Decode(code, Mode(mode)) + var out string + if err != nil { + out = "error: " + err.Error() + } else { + switch syntax { + case "gnu": + out = GNUSyntax(inst) + case "plan9": + out = Plan9Syntax(inst, 0, nil, nil) + default: + t.Errorf("unknown syntax %q", syntax) + continue + } + } + if out != asm || inst.Len != size { + t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size) + } + } +} diff --git a/src/cmd/internal/rsc.io/arm/armasm/ext_test.go b/src/cmd/internal/rsc.io/arm/armasm/ext_test.go new file mode 100644 index 000000000..b0bd85597 --- /dev/null +++ b/src/cmd/internal/rsc.io/arm/armasm/ext_test.go @@ -0,0 +1,614 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Support for testing against external disassembler program. +// Copied and simplified from rsc.io/x86/x86asm/ext_test.go. + +package armasm + +import ( + "bufio" + "bytes" + "encoding/hex" + "flag" + "fmt" + "io/ioutil" + "log" + "math/rand" + "os" + "os/exec" + "regexp" + "runtime" + "strings" + "testing" + "time" +) + +var ( + printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths") + dumpTest = flag.Bool("dump", false, "dump all encodings") + mismatch = flag.Bool("mismatch", false, "log allowed mismatches") + longTest = flag.Bool("long", false, "long test") + keep = flag.Bool("keep", false, "keep object files around") + debug = false +) + +// A ExtInst represents a single decoded instruction parsed +// from an external disassembler's output. +type ExtInst struct { + addr uint32 + enc [4]byte + nenc int + text string +} + +func (r ExtInst) String() string { + return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text) +} + +// An ExtDis is a connection between an external disassembler and a test. +type ExtDis struct { + Arch Mode + Dec chan ExtInst + File *os.File + Size int + KeepFile bool + Cmd *exec.Cmd +} + +// Run runs the given command - the external disassembler - and returns +// a buffered reader of its standard output. +func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) { + if *keep { + log.Printf("%s\n", strings.Join(cmd, " ")) + } + ext.Cmd = exec.Command(cmd[0], cmd[1:]...) + out, err := ext.Cmd.StdoutPipe() + if err != nil { + return nil, fmt.Errorf("stdoutpipe: %v", err) + } + if err := ext.Cmd.Start(); err != nil { + return nil, fmt.Errorf("exec: %v", err) + } + + b := bufio.NewReaderSize(out, 1<<20) + return b, nil +} + +// Wait waits for the command started with Run to exit. +func (ext *ExtDis) Wait() error { + return ext.Cmd.Wait() +} + +// testExtDis tests a set of byte sequences against an external disassembler. +// The disassembler is expected to produce the given syntax and be run +// in the given architecture mode (16, 32, or 64-bit). +// The extdis function must start the external disassembler +// and then parse its output, sending the parsed instructions on ext.Dec. +// The generate function calls its argument f once for each byte sequence +// to be tested. The generate function itself will be called twice, and it must +// make the same sequence of calls to f each time. +// When a disassembly does not match the internal decoding, +// allowedMismatch determines whether this mismatch should be +// allowed, or else considered an error. +func testExtDis( + t *testing.T, + syntax string, + arch Mode, + extdis func(ext *ExtDis) error, + generate func(f func([]byte)), + allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool, +) { + start := time.Now() + ext := &ExtDis{ + Dec: make(chan ExtInst), + Arch: arch, + } + errc := make(chan error) + + // First pass: write instructions to input file for external disassembler. + file, f, size, err := writeInst(generate) + if err != nil { + t.Fatal(err) + } + ext.Size = size + ext.File = f + defer func() { + f.Close() + if !*keep { + os.Remove(file) + } + }() + + // Second pass: compare disassembly against our decodings. + var ( + totalTests = 0 + totalSkips = 0 + totalErrors = 0 + + errors = make([]string, 0, 100) // sampled errors, at most cap + ) + go func() { + errc <- extdis(ext) + }() + generate(func(enc []byte) { + dec, ok := <-ext.Dec + if !ok { + t.Errorf("decoding stream ended early") + return + } + inst, text := disasm(syntax, arch, pad(enc)) + totalTests++ + if *dumpTest { + fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc) + } + if text != dec.text || inst.Len != dec.nenc { + suffix := "" + if allowedMismatch(text, size, &inst, dec) { + totalSkips++ + if !*mismatch { + return + } + suffix += " (allowed mismatch)" + } + totalErrors++ + if len(errors) >= cap(errors) { + j := rand.Intn(totalErrors) + if j >= cap(errors) { + return + } + errors = append(errors[:j], errors[j+1:]...) + } + errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix)) + } + }) + + if *mismatch { + totalErrors -= totalSkips + } + + for _, b := range errors { + t.Log(b) + } + + if totalErrors > 0 { + t.Fail() + } + t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds()) + + if err := <-errc; err != nil { + t.Fatal("external disassembler: %v", err) + } + +} + +const start = 0x8000 // start address of text + +// writeInst writes the generated byte sequences to a new file +// starting at offset start. That file is intended to be the input to +// the external disassembler. +func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) { + f, err = ioutil.TempFile("", "armasm") + if err != nil { + return + } + + file = f.Name() + + f.Seek(start, 0) + w := bufio.NewWriter(f) + defer w.Flush() + size = 0 + generate(func(x []byte) { + if len(x) > 4 { + x = x[:4] + } + if debug { + fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):]) + } + w.Write(x) + w.Write(zeros[len(x):]) + size += len(zeros) + }) + return file, f, size, nil +} + +var zeros = []byte{0, 0, 0, 0} + +// pad pads the code sequenc with pops. +func pad(enc []byte) []byte { + if len(enc) < 4 { + enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...) + } + return enc +} + +// disasm returns the decoded instruction and text +// for the given source bytes, using the given syntax and mode. +func disasm(syntax string, mode Mode, src []byte) (inst Inst, text string) { + // If printTests is set, we record the coverage value + // before and after, and we write out the inputs for which + // coverage went up, in the format expected in testdata/decode.text. + // This produces a fairly small set of test cases that exercise nearly + // all the code. + var cover float64 + if *printTests { + cover -= coverage() + } + + inst, err := Decode(src, mode) + if err != nil { + text = "error: " + err.Error() + } else { + text = inst.String() + switch syntax { + //case "arm": + // text = ARMSyntax(inst) + case "gnu": + text = GNUSyntax(inst) + //case "plan9": + // text = Plan9Syntax(inst, 0, nil) + default: + text = "error: unknown syntax " + syntax + } + } + + if *printTests { + cover += coverage() + if cover > 0 { + max := len(src) + if max > 4 && inst.Len <= 4 { + max = 4 + } + fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text) + } + } + + return +} + +// coverage returns a floating point number denoting the +// test coverage until now. The number increases when new code paths are exercised, +// both in the Go program and in the decoder byte code. +func coverage() float64 { + /* + testing.Coverage is not in the main distribution. + The implementation, which must go in package testing, is: + + // Coverage reports the current code coverage as a fraction in the range [0, 1]. + func Coverage() float64 { + var n, d int64 + for _, counters := range cover.Counters { + for _, c := range counters { + if c > 0 { + n++ + } + d++ + } + } + if d == 0 { + return 0 + } + return float64(n) / float64(d) + } + */ + + var f float64 + f += testing.Coverage() + f += decodeCoverage() + return f +} + +func decodeCoverage() float64 { + n := 0 + for _, t := range decoderCover { + if t { + n++ + } + } + return float64(1+n) / float64(1+len(decoderCover)) +} + +// Helpers for writing disassembler output parsers. + +// hasPrefix reports whether any of the space-separated words in the text s +// begins with any of the given prefixes. +func hasPrefix(s string, prefixes ...string) bool { + for _, prefix := range prefixes { + for s := s; s != ""; { + if strings.HasPrefix(s, prefix) { + return true + } + i := strings.Index(s, " ") + if i < 0 { + break + } + s = s[i+1:] + } + } + return false +} + +// contains reports whether the text s contains any of the given substrings. +func contains(s string, substrings ...string) bool { + for _, sub := range substrings { + if strings.Contains(s, sub) { + return true + } + } + return false +} + +// isHex reports whether b is a hexadecimal character (0-9A-Fa-f). +func isHex(b byte) bool { return b == '0' || unhex[b] > 0 } + +// parseHex parses the hexadecimal byte dump in hex, +// appending the parsed bytes to raw and returning the updated slice. +// The returned bool signals whether any invalid hex was found. +// Spaces and tabs between bytes are okay but any other non-hex is not. +func parseHex(hex []byte, raw []byte) ([]byte, bool) { + hex = trimSpace(hex) + for j := 0; j < len(hex); { + for hex[j] == ' ' || hex[j] == '\t' { + j++ + } + if j >= len(hex) { + break + } + if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) { + return nil, false + } + raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]]) + j += 2 + } + return raw, true +} + +var unhex = [256]byte{ + '0': 0, + '1': 1, + '2': 2, + '3': 3, + '4': 4, + '5': 5, + '6': 6, + '7': 7, + '8': 8, + '9': 9, + 'A': 10, + 'B': 11, + 'C': 12, + 'D': 13, + 'E': 14, + 'F': 15, + 'a': 10, + 'b': 11, + 'c': 12, + 'd': 13, + 'e': 14, + 'f': 15, +} + +// index is like bytes.Index(s, []byte(t)) but avoids the allocation. +func index(s []byte, t string) int { + i := 0 + for { + j := bytes.IndexByte(s[i:], t[0]) + if j < 0 { + return -1 + } + i = i + j + if i+len(t) > len(s) { + return -1 + } + for k := 1; k < len(t); k++ { + if s[i+k] != t[k] { + goto nomatch + } + } + return i + nomatch: + i++ + } +} + +// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s. +// If s must be rewritten, it is rewritten in place. +func fixSpace(s []byte) []byte { + s = trimSpace(s) + for i := 0; i < len(s); i++ { + if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' { + goto Fix + } + } + return s + +Fix: + b := s + w := 0 + for i := 0; i < len(s); i++ { + c := s[i] + if c == '\t' || c == '\n' { + c = ' ' + } + if c == ' ' && w > 0 && b[w-1] == ' ' { + continue + } + b[w] = c + w++ + } + if w > 0 && b[w-1] == ' ' { + w-- + } + return b[:w] +} + +// trimSpace trims leading and trailing space from s, returning a subslice of s. +func trimSpace(s []byte) []byte { + j := len(s) + for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') { + j-- + } + i := 0 + for i < j && (s[i] == ' ' || s[i] == '\t') { + i++ + } + return s[i:j] +} + +// pcrel matches instructions using relative addressing mode. +var ( + pcrel = regexp.MustCompile(`^((?:.* )?(?:b|bl)x?(?:eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le)?) 0x([0-9a-f]+)$`) +) + +// Generators. +// +// The test cases are described as functions that invoke a callback repeatedly, +// with a new input sequence each time. These helpers make writing those +// a little easier. + +// condCases generates conditional instructions. +func condCases(t *testing.T) func(func([]byte)) { + return func(try func([]byte)) { + // All the strides are relatively prime to 2 and therefore to 2²⁸, + // so we will not repeat any instructions until we have tried all 2²⁸. + // Using a stride other than 1 is meant to visit the instructions in a + // pseudorandom order, which gives better variety in the set of + // test cases chosen by -printtests. + stride := uint32(10007) + n := 1 << 28 / 7 + if testing.Short() { + stride = 100003 + n = 1 << 28 / 1001 + } else if *longTest { + stride = 200000033 + n = 1 << 28 + } + x := uint32(0) + for i := 0; i < n; i++ { + enc := (x%15)<<28 | x&(1<<28-1) + try([]byte{byte(enc), byte(enc >> 8), byte(enc >> 16), byte(enc >> 24)}) + x += stride + } + } +} + +// uncondCases generates unconditional instructions. +func uncondCases(t *testing.T) func(func([]byte)) { + return func(try func([]byte)) { + condCases(t)(func(enc []byte) { + enc[3] |= 0xF0 + try(enc) + }) + } +} + +func countBits(x uint32) int { + n := 0 + for ; x != 0; x >>= 1 { + n += int(x & 1) + } + return n +} + +func expandBits(x, m uint32) uint32 { + var out uint32 + for i := uint(0); i < 32; i++ { + out >>= 1 + if m&1 != 0 { + out |= (x & 1) << 31 + x >>= 1 + } + m >>= 1 + } + return out +} + +func tryCondMask(mask, val uint32, try func([]byte)) { + n := countBits(^mask) + bits := uint32(0) + for i := 0; i < 1<> 8), byte(x >> 16), byte(x >> 24)}) + } +} + +// vfpCases generates VFP instructions. +func vfpCases(t *testing.T) func(func([]byte)) { + const ( + vfpmask uint32 = 0xFF00FE10 + vfp uint32 = 0x0E009A00 + ) + return func(try func([]byte)) { + tryCondMask(0xff00fe10, 0x0e009a00, try) // standard VFP instruction space + tryCondMask(0xffc00f7f, 0x0e000b10, try) // VFP MOV core reg to/from float64 half + tryCondMask(0xffe00f7f, 0x0e000a10, try) // VFP MOV core reg to/from float32 + tryCondMask(0xffef0fff, 0x0ee10a10, try) // VFP MOV core reg to/from cond codes + } +} + +// hexCases generates the cases written in hexadecimal in the encoded string. +// Spaces in 'encoded' separate entire test cases, not individual bytes. +func hexCases(t *testing.T, encoded string) func(func([]byte)) { + return func(try func([]byte)) { + for _, x := range strings.Fields(encoded) { + src, err := hex.DecodeString(x) + if err != nil { + t.Errorf("parsing %q: %v", x, err) + } + try(src) + } + } +} + +// testdataCases generates the test cases recorded in testdata/decode.txt. +// It only uses the inputs; it ignores the answers recorded in that file. +func testdataCases(t *testing.T) func(func([]byte)) { + var codes [][]byte + data, err := ioutil.ReadFile("testdata/decode.txt") + if err != nil { + t.Fatal(err) + } + for _, line := range strings.Split(string(data), "\n") { + line = strings.TrimSpace(line) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + f := strings.Fields(line)[0] + i := strings.Index(f, "|") + if i < 0 { + t.Errorf("parsing %q: missing | separator", f) + continue + } + if i%2 != 0 { + t.Errorf("parsing %q: misaligned | separator", f) + } + code, err := hex.DecodeString(f[:i] + f[i+1:]) + if err != nil { + t.Errorf("parsing %q: %v", f, err) + continue + } + codes = append(codes, code) + } + + return func(try func([]byte)) { + for _, code := range codes { + try(code) + } + } +} + +func caller(skip int) string { + pc, _, _, _ := runtime.Caller(skip) + f := runtime.FuncForPC(pc) + name := "?" + if f != nil { + name = f.Name() + if i := strings.LastIndex(name, "."); i >= 0 { + name = name[i+1:] + } + } + return name +} diff --git a/src/cmd/internal/rsc.io/arm/armasm/gnu.go b/src/cmd/internal/rsc.io/arm/armasm/gnu.go new file mode 100644 index 000000000..1a97a5a84 --- /dev/null +++ b/src/cmd/internal/rsc.io/arm/armasm/gnu.go @@ -0,0 +1,164 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package armasm + +import ( + "bytes" + "fmt" + "strings" +) + +var saveDot = strings.NewReplacer( + ".F16", "_dot_F16", + ".F32", "_dot_F32", + ".F64", "_dot_F64", + ".S32", "_dot_S32", + ".U32", "_dot_U32", + ".FXS", "_dot_S", + ".FXU", "_dot_U", + ".32", "_dot_32", +) + +// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils. +// This form typically matches the syntax defined in the ARM Reference Manual. +func GNUSyntax(inst Inst) string { + var buf bytes.Buffer + op := inst.Op.String() + op = saveDot.Replace(op) + op = strings.Replace(op, ".", "", -1) + op = strings.Replace(op, "_dot_", ".", -1) + op = strings.ToLower(op) + buf.WriteString(op) + sep := " " + for i, arg := range inst.Args { + if arg == nil { + break + } + text := gnuArg(&inst, i, arg) + if text == "" { + continue + } + buf.WriteString(sep) + sep = ", " + buf.WriteString(text) + } + return buf.String() +} + +func gnuArg(inst *Inst, argIndex int, arg Arg) string { + switch inst.Op &^ 15 { + case LDRD_EQ, LDREXD_EQ, STRD_EQ: + if argIndex == 1 { + // second argument in consecutive pair not printed + return "" + } + case STREXD_EQ: + if argIndex == 2 { + // second argument in consecutive pair not printed + return "" + } + } + + switch arg := arg.(type) { + case Imm: + switch inst.Op &^ 15 { + case BKPT_EQ: + return fmt.Sprintf("%#04x", uint32(arg)) + case SVC_EQ: + return fmt.Sprintf("%#08x", uint32(arg)) + } + return fmt.Sprintf("#%d", int32(arg)) + + case ImmAlt: + return fmt.Sprintf("#%d, %d", arg.Val, arg.Rot) + + case Mem: + R := gnuArg(inst, -1, arg.Base) + X := "" + if arg.Sign != 0 { + X = "" + if arg.Sign < 0 { + X = "-" + } + X += gnuArg(inst, -1, arg.Index) + if arg.Shift == ShiftLeft && arg.Count == 0 { + // nothing + } else if arg.Shift == RotateRightExt { + X += ", rrx" + } else { + X += fmt.Sprintf(", %s #%d", strings.ToLower(arg.Shift.String()), arg.Count) + } + } else { + X = fmt.Sprintf("#%d", arg.Offset) + } + + switch arg.Mode { + case AddrOffset: + if X == "#0" { + return fmt.Sprintf("[%s]", R) + } + return fmt.Sprintf("[%s, %s]", R, X) + case AddrPreIndex: + return fmt.Sprintf("[%s, %s]!", R, X) + case AddrPostIndex: + return fmt.Sprintf("[%s], %s", R, X) + case AddrLDM: + if X == "#0" { + return R + } + case AddrLDM_WB: + if X == "#0" { + return R + "!" + } + } + return fmt.Sprintf("[%s Mode(%d) %s]", R, int(arg.Mode), X) + + case PCRel: + return fmt.Sprintf(".%+#x", int32(arg)+4) + + case Reg: + switch inst.Op &^ 15 { + case LDREX_EQ: + if argIndex == 0 { + return fmt.Sprintf("r%d", int32(arg)) + } + } + switch arg { + case R10: + return "sl" + case R11: + return "fp" + case R12: + return "ip" + } + + case RegList: + var buf bytes.Buffer + fmt.Fprintf(&buf, "{") + sep := "" + for i := 0; i < 16; i++ { + if arg&(1<= Op(len(opstr)) || opstr[op] == "" { + return fmt.Sprintf("Op(%d)", int(op)) + } + return opstr[op] +} + +// An Inst is a single instruction. +type Inst struct { + Op Op // Opcode mnemonic + Enc uint32 // Raw encoding bits. + Len int // Length of encoding in bytes. + Args Args // Instruction arguments, in ARM manual order. +} + +func (i Inst) String() string { + var buf bytes.Buffer + buf.WriteString(i.Op.String()) + for j, arg := range i.Args { + if arg == nil { + break + } + if j == 0 { + buf.WriteString(" ") + } else { + buf.WriteString(", ") + } + buf.WriteString(arg.String()) + } + return buf.String() +} + +// An Args holds the instruction arguments. +// If an instruction has fewer than 4 arguments, +// the final elements in the array are nil. +type Args [4]Arg + +// An Arg is a single instruction argument, one of these types: +// Endian, Imm, Mem, PCRel, Reg, RegList, RegShift, RegShiftReg. +type Arg interface { + IsArg() + String() string +} + +type Float32Imm float32 + +func (Float32Imm) IsArg() {} + +func (f Float32Imm) String() string { + return fmt.Sprintf("#%v", float32(f)) +} + +type Float64Imm float32 + +func (Float64Imm) IsArg() {} + +func (f Float64Imm) String() string { + return fmt.Sprintf("#%v", float64(f)) +} + +// An Imm is an integer constant. +type Imm uint32 + +func (Imm) IsArg() {} + +func (i Imm) String() string { + return fmt.Sprintf("#%#x", uint32(i)) +} + +// A ImmAlt is an alternate encoding of an integer constant. +type ImmAlt struct { + Val uint8 + Rot uint8 +} + +func (ImmAlt) IsArg() {} + +func (i ImmAlt) Imm() Imm { + v := uint32(i.Val) + r := uint(i.Rot) + return Imm(v>>r | v<<(32-r)) +} + +func (i ImmAlt) String() string { + return fmt.Sprintf("#%#x, %d", i.Val, i.Rot) +} + +// A Label is a text (code) address. +type Label uint32 + +func (Label) IsArg() {} + +func (i Label) String() string { + return fmt.Sprintf("%#x", uint32(i)) +} + +// A Reg is a single register. +// The zero value denotes R0, not the absence of a register. +type Reg uint8 + +const ( + R0 Reg = iota + R1 + R2 + R3 + R4 + R5 + R6 + R7 + R8 + R9 + R10 + R11 + R12 + R13 + R14 + R15 + + S0 + S1 + S2 + S3 + S4 + S5 + S6 + S7 + S8 + S9 + S10 + S11 + S12 + S13 + S14 + S15 + S16 + S17 + S18 + S19 + S20 + S21 + S22 + S23 + S24 + S25 + S26 + S27 + S28 + S29 + S30 + S31 + + D0 + D1 + D2 + D3 + D4 + D5 + D6 + D7 + D8 + D9 + D10 + D11 + D12 + D13 + D14 + D15 + D16 + D17 + D18 + D19 + D20 + D21 + D22 + D23 + D24 + D25 + D26 + D27 + D28 + D29 + D30 + D31 + + APSR + APSR_nzcv + FPSCR + + SP = R13 + LR = R14 + PC = R15 +) + +func (Reg) IsArg() {} + +func (r Reg) String() string { + switch r { + case APSR: + return "APSR" + case APSR_nzcv: + return "APSR_nzcv" + case FPSCR: + return "FPSCR" + case SP: + return "SP" + case PC: + return "PC" + case LR: + return "LR" + } + if R0 <= r && r <= R15 { + return fmt.Sprintf("R%d", int(r-R0)) + } + if S0 <= r && r <= S31 { + return fmt.Sprintf("S%d", int(r-S0)) + } + if D0 <= r && r <= D31 { + return fmt.Sprintf("D%d", int(r-D0)) + } + return fmt.Sprintf("Reg(%d)", int(r)) +} + +// A RegX represents a fraction of a multi-value register. +// The Index field specifies the index number, +// but the size of the fraction is not specified. +// It must be inferred from the instruction and the register type. +// For example, in a VMOV instruction, RegX{D5, 1} represents +// the top 32 bits of the 64-bit D5 register. +type RegX struct { + Reg Reg + Index int +} + +func (RegX) IsArg() {} + +func (r RegX) String() string { + return fmt.Sprintf("%s[%d]", r.Reg, r.Index) +} + +// A RegList is a register list. +// Bits at indexes x = 0 through 15 indicate whether the corresponding Rx register is in the list. +type RegList uint16 + +func (RegList) IsArg() {} + +func (r RegList) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "{") + sep := "" + for i := 0; i < 16; i++ { + if r&(1<= 4 { + raw := binary.LittleEndian.Uint32(dec.enc[:4]) + + // word 21FFF0B5. + // the manual is clear that this is pre-indexed mode (with !) but libopcodes generates post-index (without !). + if raw&0x01200000 == 0x01200000 && strings.Replace(text, "!", "", -1) == dec.text { + return true + } + + // word C100543E: libopcodes says tst, but no evidence for that. + if strings.HasPrefix(dec.text, "tst") && raw&0x0ff00000 != 0x03100000 && raw&0x0ff00000 != 0x01100000 { + return true + } + + // word C3203CE8: libopcodes says teq, but no evidence for that. + if strings.HasPrefix(dec.text, "teq") && raw&0x0ff00000 != 0x03300000 && raw&0x0ff00000 != 0x01300000 { + return true + } + + // word D14C552E: libopcodes says cmp but no evidence for that. + if strings.HasPrefix(dec.text, "cmp") && raw&0x0ff00000 != 0x03500000 && raw&0x0ff00000 != 0x01500000 { + return true + } + + // word 2166AA4A: libopcodes says cmn but no evidence for that. + if strings.HasPrefix(dec.text, "cmn") && raw&0x0ff00000 != 0x03700000 && raw&0x0ff00000 != 0x01700000 { + return true + } + + // word E70AEEEF: libopcodes says str but no evidence for that. + if strings.HasPrefix(dec.text, "str") && len(dec.text) >= 5 && (dec.text[3] == ' ' || dec.text[5] == ' ') && raw&0x0e500018 != 0x06000000 && raw&0x0e500000 != 0x0400000 { + return true + } + + // word B0AF48F4: libopcodes says strd but P=0,W=1 which is unpredictable. + if hasPrefix(dec.text, "ldr", "str") && raw&0x01200000 == 0x00200000 { + return true + } + + // word B6CC1C76: libopcodes inexplicably says 'uxtab16lt r1, ip, r6, ROR #24' instead of 'uxtab16lt r1, ip, r6, ror #24' + if strings.ToLower(dec.text) == text { + return true + } + + // word F410FDA1: libopcodes says PLDW but the manual is clear that PLDW is F5/F7, not F4. + // word F7D0FB17: libopcodes says PLDW but the manual is clear that PLDW has 0x10 clear + if hasPrefix(dec.text, "pld") && raw&0xfd000010 != 0xf5000000 { + return true + } + + // word F650FE14: libopcodes says PLI but the manual is clear that PLI has 0x10 clear + if hasPrefix(dec.text, "pli") && raw&0xff000010 != 0xf6000000 { + return true + } + } + + return false +} + +// Instructions known to libopcodes (or xed) but not to us. +// Most of these are floating point coprocessor instructions. +var unsupported = strings.Fields(` + abs + acs + adf + aes + asn + atn + cdp + cf + cmf + cnf + cos + cps + crc32 + dvf + eret + exp + fadd + fcmp + fcpy + fcvt + fdiv + fdv + fix + fld + flt + fmac + fmd + fml + fmr + fms + fmul + fmx + fneg + fnm + frd + fsit + fsq + fst + fsu + fto + fui + hlt + hvc + lda + ldc + ldf + lfm + lgn + log + mar + mcr + mcrr + mia + mnf + mra + mrc + mrrc + mrs + msr + msr + muf + mvf + nrm + pol + pow + rdf + rfc + rfe + rfs + rmf + rnd + rpw + rsf + sdiv + sev + sfm + sha1 + sha256 + sin + smc + sqt + srs + stc + stf + stl + suf + tan + udf + udiv + urd + vfma + vfms + vfnma + vfnms + vrint + wfc + wfs +`) diff --git a/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go b/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go new file mode 100644 index 000000000..d88c67fc0 --- /dev/null +++ b/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go @@ -0,0 +1,260 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copied and simplified from rsc.io/x86/x86asm/objdumpext_test.go. + +package armasm + +import ( + "bytes" + "debug/elf" + "encoding/binary" + "fmt" + "io" + "log" + "os" + "strconv" + "strings" + "testing" +) + +const objdumpPath = "/usr/local/bin/arm-linux-elf-objdump" + +func testObjdumpARM(t *testing.T, generate func(func([]byte))) { + testObjdumpArch(t, generate, ModeARM) +} + +func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch Mode) { + if testing.Short() { + t.Skip("skipping objdump test in short mode") + } + + if _, err := os.Stat(objdumpPath); err != nil { + t.Fatal(err) + } + + testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump) +} + +func objdump(ext *ExtDis) error { + // File already written with instructions; add ELF header. + if ext.Arch == ModeARM { + if err := writeELF32(ext.File, ext.Size); err != nil { + return err + } + } else { + panic("unknown arch") + } + + b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name()) + if err != nil { + return err + } + + var ( + nmatch int + reading bool + next uint32 = start + addr uint32 + encbuf [4]byte + enc []byte + text string + ) + flush := func() { + if addr == next { + if m := pcrel.FindStringSubmatch(text); m != nil { + targ, _ := strconv.ParseUint(m[2], 16, 64) + text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc)))) + } + if strings.HasPrefix(text, "stmia") { + text = "stm" + text[5:] + } + if strings.HasPrefix(text, "stmfd") { + text = "stmdb" + text[5:] + } + if strings.HasPrefix(text, "ldmfd") { + text = "ldm" + text[5:] + } + text = strings.Replace(text, "#0.0", "#0", -1) + if text == "undefined" && len(enc) == 4 { + text = "error: unknown instruction" + enc = nil + } + if len(enc) == 4 { + // prints as word but we want to record bytes + enc[0], enc[3] = enc[3], enc[0] + enc[1], enc[2] = enc[2], enc[1] + } + ext.Dec <- ExtInst{addr, encbuf, len(enc), text} + encbuf = [4]byte{} + enc = nil + next += 4 + } + } + var textangle = []byte("<.text>:") + for { + line, err := b.ReadSlice('\n') + if err != nil { + if err == io.EOF { + break + } + return fmt.Errorf("reading objdump output: %v", err) + } + if bytes.Contains(line, textangle) { + reading = true + continue + } + if !reading { + continue + } + if debug { + os.Stdout.Write(line) + } + if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil { + enc = enc1 + continue + } + flush() + nmatch++ + addr, enc, text = parseLine(line, encbuf[:0]) + if addr > next { + return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line) + } + } + flush() + if next != start+uint32(ext.Size) { + return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size) + } + if err := ext.Wait(); err != nil { + return fmt.Errorf("exec: %v", err) + } + + return nil +} + +var ( + undefined = []byte("") + unpredictable = []byte("") + illegalShifter = []byte("") +) + +func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) { + oline := line + i := index(line, ":\t") + if i < 0 { + log.Fatalf("cannot parse disassembly: %q", oline) + } + x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32) + if err != nil { + log.Fatalf("cannot parse disassembly: %q", oline) + } + addr = uint32(x) + line = line[i+2:] + i = bytes.IndexByte(line, '\t') + if i < 0 { + log.Fatalf("cannot parse disassembly: %q", oline) + } + enc, ok := parseHex(line[:i], encstart) + if !ok { + log.Fatalf("cannot parse disassembly: %q", oline) + } + line = trimSpace(line[i:]) + if bytes.Contains(line, undefined) { + text = "undefined" + return + } + if bytes.Contains(line, illegalShifter) { + text = "undefined" + return + } + if false && bytes.Contains(line, unpredictable) { + text = "unpredictable" + return + } + if i := bytes.IndexByte(line, ';'); i >= 0 { + line = trimSpace(line[:i]) + } + text = string(fixSpace(line)) + return +} + +func parseContinuation(line []byte, enc []byte) []byte { + i := index(line, ":\t") + if i < 0 { + return nil + } + line = line[i+1:] + enc, _ = parseHex(line, enc) + return enc +} + +// writeELF32 writes an ELF32 header to the file, +// describing a text segment that starts at start +// and extends for size bytes. +func writeELF32(f *os.File, size int) error { + f.Seek(0, 0) + var hdr elf.Header32 + var prog elf.Prog32 + var sect elf.Section32 + var buf bytes.Buffer + binary.Write(&buf, binary.LittleEndian, &hdr) + off1 := buf.Len() + binary.Write(&buf, binary.LittleEndian, &prog) + off2 := buf.Len() + binary.Write(&buf, binary.LittleEndian, §) + off3 := buf.Len() + buf.Reset() + data := byte(elf.ELFDATA2LSB) + hdr = elf.Header32{ + Ident: [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1}, + Type: 2, + Machine: uint16(elf.EM_ARM), + Version: 1, + Entry: start, + Phoff: uint32(off1), + Shoff: uint32(off2), + Flags: 0x05000002, + Ehsize: uint16(off1), + Phentsize: uint16(off2 - off1), + Phnum: 1, + Shentsize: uint16(off3 - off2), + Shnum: 3, + Shstrndx: 2, + } + binary.Write(&buf, binary.LittleEndian, &hdr) + prog = elf.Prog32{ + Type: 1, + Off: start, + Vaddr: start, + Paddr: start, + Filesz: uint32(size), + Memsz: uint32(size), + Flags: 5, + Align: start, + } + binary.Write(&buf, binary.LittleEndian, &prog) + binary.Write(&buf, binary.LittleEndian, §) // NULL section + sect = elf.Section32{ + Name: 1, + Type: uint32(elf.SHT_PROGBITS), + Addr: start, + Off: start, + Size: uint32(size), + Flags: uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR), + Addralign: 4, + } + binary.Write(&buf, binary.LittleEndian, §) // .text + sect = elf.Section32{ + Name: uint32(len("\x00.text\x00")), + Type: uint32(elf.SHT_STRTAB), + Addr: 0, + Off: uint32(off2 + (off3-off2)*3), + Size: uint32(len("\x00.text\x00.shstrtab\x00")), + Addralign: 1, + } + binary.Write(&buf, binary.LittleEndian, §) + buf.WriteString("\x00.text\x00.shstrtab\x00") + f.Write(buf.Bytes()) + return nil +} diff --git a/src/cmd/internal/rsc.io/arm/armasm/plan9x.go b/src/cmd/internal/rsc.io/arm/armasm/plan9x.go new file mode 100644 index 000000000..952c5190b --- /dev/null +++ b/src/cmd/internal/rsc.io/arm/armasm/plan9x.go @@ -0,0 +1,211 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package armasm + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "strings" +) + +// Plan9Syntax returns the Go assembler syntax for the instruction. +// The syntax was originally defined by Plan 9. +// The pc is the program counter of the instruction, used for expanding +// PC-relative addresses into absolute ones. +// The symname function queries the symbol table for the program +// being disassembled. Given a target address it returns the name and base +// address of the symbol containing the target, if any; otherwise it returns "", 0. +// The reader r should read from the text segment using text addresses +// as offsets; it is used to display pc-relative loads as constant loads. +func Plan9Syntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string { + if symname == nil { + symname = func(uint64) (string, uint64) { return "", 0 } + } + + var args []string + for _, a := range inst.Args { + if a == nil { + break + } + args = append(args, plan9Arg(&inst, pc, symname, a)) + } + + op := inst.Op.String() + + switch inst.Op &^ 15 { + case LDR_EQ, LDRB_EQ, LDRH_EQ: + // Check for RET + reg, _ := inst.Args[0].(Reg) + mem, _ := inst.Args[1].(Mem) + if inst.Op&^15 == LDR_EQ && reg == R15 && mem.Base == SP && mem.Sign == 0 && mem.Mode == AddrPostIndex { + return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset) + } + + // Check for PC-relative load. + if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil { + addr := uint32(pc) + 8 + uint32(mem.Offset) + buf := make([]byte, 4) + switch inst.Op &^ 15 { + case LDRB_EQ: + if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil { + break + } + args[1] = fmt.Sprintf("$%#x", buf[0]) + + case LDRH_EQ: + if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil { + break + } + args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf)) + + case LDR_EQ: + if _, err := text.ReadAt(buf, int64(addr)); err != nil { + break + } + x := binary.LittleEndian.Uint32(buf) + if s, base := symname(uint64(x)); s != "" && uint64(x) == base { + args[1] = fmt.Sprintf("$%s(SB)", s) + } else { + args[1] = fmt.Sprintf("$%#x", x) + } + } + } + } + + // Move addressing mode into opcode suffix. + suffix := "" + switch inst.Op &^ 15 { + case LDR_EQ, LDRB_EQ, LDRH_EQ, STR_EQ, STRB_EQ, STRH_EQ: + mem, _ := inst.Args[1].(Mem) + switch mem.Mode { + case AddrOffset, AddrLDM: + // no suffix + case AddrPreIndex, AddrLDM_WB: + suffix = ".W" + case AddrPostIndex: + suffix = ".P" + } + off := "" + if mem.Offset != 0 { + off = fmt.Sprintf("%#x", mem.Offset) + } + base := fmt.Sprintf("(R%d)", int(mem.Base)) + index := "" + if mem.Sign != 0 { + sign := "" + if mem.Sign < 0 { + sign = "" + } + shift := "" + if mem.Count != 0 { + shift = fmt.Sprintf("%s%d", plan9Shift[mem.Shift], mem.Count) + } + index = fmt.Sprintf("(%sR%d%s)", sign, int(mem.Index), shift) + } + args[1] = off + base + index + } + + // Reverse args, placing dest last. + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + + switch inst.Op &^ 15 { + case MOV_EQ: + op = "MOVW" + op[3:] + + case LDR_EQ: + op = "MOVW" + op[3:] + suffix + case LDRB_EQ: + op = "MOVB" + op[4:] + suffix + case LDRH_EQ: + op = "MOVH" + op[4:] + suffix + + case STR_EQ: + op = "MOVW" + op[3:] + suffix + args[0], args[1] = args[1], args[0] + case STRB_EQ: + op = "MOVB" + op[4:] + suffix + args[0], args[1] = args[1], args[0] + case STRH_EQ: + op = "MOVH" + op[4:] + suffix + args[0], args[1] = args[1], args[0] + } + + if args != nil { + op += " " + strings.Join(args, ", ") + } + + return op +} + +// assembler syntax for the various shifts. +// @x> is a lie; the assembler uses @> 0 +// instead of @x> 1, but i wanted to be clear that it +// was a different operation (rotate right extended, not rotate right). +var plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"} + +func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string { + switch a := arg.(type) { + case Endian: + + case Imm: + return fmt.Sprintf("$%d", int(a)) + + case Mem: + + case PCRel: + addr := uint32(pc) + 8 + uint32(a) + if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base { + return fmt.Sprintf("%s(SB)", s) + } + return fmt.Sprintf("%#x", addr) + + case Reg: + if a < 16 { + return fmt.Sprintf("R%d", int(a)) + } + + case RegList: + var buf bytes.Buffer + start := -2 + end := -2 + fmt.Fprintf(&buf, "[") + flush := func() { + if start >= 0 { + if buf.Len() > 1 { + fmt.Fprintf(&buf, ",") + } + if start == end { + fmt.Fprintf(&buf, "R%d", start) + } else { + fmt.Fprintf(&buf, "R%d-R%d", start, end) + } + } + } + for i := 0; i < 16; i++ { + if a&(1< ,,# cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12 + {0x0fe00090, 0x00a00010, 4, ADC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // ADC{S} ,,, cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 + {0x0fe00010, 0x00a00000, 2, ADC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // ADC{S} ,,{,} cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 + {0x0fe00000, 0x02800000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // ADD{S} ,,# cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12 + {0x0fe00090, 0x00800010, 4, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // ADD{S} ,,, cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 + {0x0fe00010, 0x00800000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // ADD{S} ,,{,} cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 + {0x0fef0000, 0x028d0000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_const}}, // ADD{S} ,SP,# cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12 + {0x0fef0010, 0x008d0000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_R_shift_imm}}, // ADD{S} ,SP,{,} cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4 + {0x0fe00000, 0x02000000, 2, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // AND{S} ,,# cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12 + {0x0fe00090, 0x00000010, 4, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // AND{S} ,,, cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 + {0x0fe00010, 0x00000000, 2, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // AND{S} ,,{,} cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 + {0x0fef0070, 0x01a00040, 4, ASR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_imm5_32}}, // ASR{S} ,,# cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4 + {0x0fef00f0, 0x01a00050, 4, ASR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_R_8}}, // ASR{S} ,, cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4 + {0x0f000000, 0x0a000000, 4, B_EQ, 0x1c04, instArgs{arg_label24}}, // B cond:4|1|0|1|0|imm24:24 + {0x0fe0007f, 0x07c0001f, 4, BFC_EQ, 0x1c04, instArgs{arg_R_12, arg_imm5, arg_lsb_width}}, // BFC ,#,# cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1 + {0x0fe00070, 0x07c00010, 2, BFI_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_imm5, arg_lsb_width}}, // BFI ,,#,# cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4 + {0x0fe00000, 0x03c00000, 2, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // BIC{S} ,,# cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12 + {0x0fe00090, 0x01c00010, 4, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // BIC{S} ,,, cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 + {0x0fe00010, 0x01c00000, 2, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // BIC{S} ,,{,} cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 + {0x0ff000f0, 0x01200070, 4, BKPT_EQ, 0x1c04, instArgs{arg_imm_12at8_4at0}}, // BKPT # cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4 + {0x0f000000, 0x0b000000, 4, BL_EQ, 0x1c04, instArgs{arg_label24}}, // BL cond:4|1|0|1|1|imm24:24 + {0xfe000000, 0xfa000000, 4, BLX, 0x0, instArgs{arg_label24H}}, // BLX 1|1|1|1|1|0|1|H|imm24:24 + {0x0ffffff0, 0x012fff30, 4, BLX_EQ, 0x1c04, instArgs{arg_R_0}}, // BLX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4 + {0x0ff000f0, 0x012fff30, 3, BLX_EQ, 0x1c04, instArgs{arg_R_0}}, // BLX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4 + {0x0ffffff0, 0x012fff10, 4, BX_EQ, 0x1c04, instArgs{arg_R_0}}, // BX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 + {0x0ff000f0, 0x012fff10, 3, BX_EQ, 0x1c04, instArgs{arg_R_0}}, // BX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 + {0x0ffffff0, 0x012fff20, 4, BXJ_EQ, 0x1c04, instArgs{arg_R_0}}, // BXJ cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4 + {0x0ff000f0, 0x012fff20, 3, BXJ_EQ, 0x1c04, instArgs{arg_R_0}}, // BXJ cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4 + {0xffffffff, 0xf57ff01f, 4, CLREX, 0x0, instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1) + {0xfff000f0, 0xf57ff01f, 3, CLREX, 0x0, instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1) + {0x0fff0ff0, 0x016f0f10, 4, CLZ_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // CLZ , cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 + {0x0ff000f0, 0x016f0f10, 3, CLZ_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // CLZ , cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 + {0x0ff0f000, 0x03700000, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMN ,# cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 + {0x0ff00000, 0x03700000, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMN ,# cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 + {0x0ff0f090, 0x01700010, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMN ,, cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 + {0x0ff00090, 0x01700010, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMN ,, cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 + {0x0ff0f010, 0x01700000, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMN ,{,} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 + {0x0ff00010, 0x01700000, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMN ,{,} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 + {0x0ff0f000, 0x03500000, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMP ,# cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 + {0x0ff00000, 0x03500000, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMP ,# cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 + {0x0ff0f090, 0x01500010, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMP ,, cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 + {0x0ff00090, 0x01500010, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMP ,, cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 + {0x0ff0f010, 0x01500000, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMP ,{,} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 + {0x0ff00010, 0x01500000, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMP ,{,} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 + {0x0ffffff0, 0x0320f0f0, 4, DBG_EQ, 0x1c04, instArgs{arg_option}}, // DBG #