summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5c/gc.h2
-rw-r--r--src/cmd/5c/txt.c28
-rw-r--r--src/cmd/5g/ggen.c32
-rw-r--r--src/cmd/5g/gobj.c4
-rw-r--r--src/cmd/5g/gsubr.c13
-rw-r--r--src/cmd/5g/reg.c43
-rw-r--r--src/cmd/5l/asm.c31
-rw-r--r--src/cmd/5l/mkenam30
-rw-r--r--src/cmd/5l/noop.c24
-rw-r--r--src/cmd/6c/cgen.c2
-rw-r--r--src/cmd/6c/gc.h1
-rw-r--r--src/cmd/6g/ggen.c32
-rw-r--r--src/cmd/6g/gobj.c4
-rw-r--r--src/cmd/6g/gsubr.c13
-rw-r--r--src/cmd/6g/reg.c1
-rw-r--r--src/cmd/6l/asm.c29
-rw-r--r--src/cmd/6l/mkenam30
-rw-r--r--src/cmd/8a/a.h4
-rw-r--r--src/cmd/8a/a.y2
-rw-r--r--src/cmd/8a/l.s734
-rw-r--r--src/cmd/8a/lex.c3
-rw-r--r--src/cmd/8c/cgen.c2
-rw-r--r--src/cmd/8c/gc.h2
-rw-r--r--src/cmd/8c/swt.c4
-rw-r--r--src/cmd/8g/ggen.c32
-rw-r--r--src/cmd/8g/gobj.c4
-rw-r--r--src/cmd/8g/gsubr.c13
-rw-r--r--src/cmd/8g/reg.c1
-rw-r--r--src/cmd/8l/asm.c35
-rw-r--r--src/cmd/8l/list.c2
-rw-r--r--src/cmd/8l/mkenam30
-rw-r--r--src/cmd/8l/obj.c17
-rw-r--r--src/cmd/8l/pass.c1
-rw-r--r--src/cmd/8l/span.c4
-rw-r--r--src/cmd/cc/acid.c1
-rw-r--r--src/cmd/cc/bits.c1
-rw-r--r--src/cmd/cc/cc.h4
-rw-r--r--src/cmd/cc/cc.y1
-rw-r--r--src/cmd/cc/com.c3
-rw-r--r--src/cmd/cc/com64.c1
-rw-r--r--src/cmd/cc/dcl.c2
-rw-r--r--src/cmd/cc/dpchk.c129
-rw-r--r--src/cmd/cc/funct.c1
-rw-r--r--src/cmd/cc/godefs.c3
-rw-r--r--src/cmd/cc/lex.c8
-rw-r--r--src/cmd/cc/lexbody6
-rw-r--r--src/cmd/cc/mac.c2
-rw-r--r--src/cmd/cc/macbody6
-rw-r--r--src/cmd/cc/omachcap.c2
-rw-r--r--src/cmd/cc/pgen.c2
-rw-r--r--src/cmd/cc/scon.c1
-rw-r--r--src/cmd/cc/sub.c1
-rw-r--r--src/cmd/cgo/gcc.go16
-rw-r--r--src/cmd/cgo/main.go3
-rw-r--r--src/cmd/cgo/out.go19
-rw-r--r--src/cmd/cgo/util.go2
-rw-r--r--src/cmd/cov/Makefile3
-rw-r--r--src/cmd/ebnflint/ebnflint.go29
-rw-r--r--src/cmd/gc/builtin.c.boot10
-rw-r--r--src/cmd/gc/closure.c78
-rw-r--r--src/cmd/gc/dcl.c26
-rw-r--r--src/cmd/gc/gen.c214
-rw-r--r--src/cmd/gc/go.h29
-rw-r--r--src/cmd/gc/go.y59
-rw-r--r--src/cmd/gc/lex.c18
-rw-r--r--src/cmd/gc/pgen.c32
-rw-r--r--src/cmd/gc/runtime.go1
-rw-r--r--src/cmd/gc/subr.c41
-rw-r--r--src/cmd/gc/typecheck.c7
-rw-r--r--src/cmd/gc/unsafe.c2
-rw-r--r--src/cmd/gc/unsafe.go8
-rw-r--r--src/cmd/gc/walk.c15
-rw-r--r--src/cmd/godefs/Makefile3
-rwxr-xr-xsrc/cmd/godefs/test.sh45
-rw-r--r--src/cmd/godefs/testdata.c41
-rw-r--r--src/cmd/godefs/testdata_darwin_386.golden31
-rw-r--r--src/cmd/godefs/testdata_darwin_amd64.golden31
-rw-r--r--src/cmd/godoc/Makefile2
-rw-r--r--src/cmd/godoc/codewalk.go40
-rw-r--r--src/cmd/godoc/dirtrees.go42
-rw-r--r--src/cmd/godoc/filesystem.go96
-rw-r--r--src/cmd/godoc/godoc.go62
-rw-r--r--src/cmd/godoc/index.go15
-rw-r--r--src/cmd/godoc/main.go10
-rw-r--r--src/cmd/godoc/mapping.go17
-rw-r--r--src/cmd/godoc/parser.go69
-rw-r--r--src/cmd/godoc/utils.go9
-rw-r--r--src/cmd/gofix/Makefile13
-rw-r--r--src/cmd/gofix/filepath.go53
-rw-r--r--src/cmd/gofix/filepath_test.go33
-rw-r--r--src/cmd/gofix/httpfinalurl.go2
-rw-r--r--src/cmd/gofix/httpfs.go63
-rw-r--r--src/cmd/gofix/httpfs_test.go47
-rw-r--r--src/cmd/gofix/httpheaders.go66
-rw-r--r--src/cmd/gofix/httpheaders_test.go73
-rw-r--r--src/cmd/gofix/main.go4
-rw-r--r--src/cmd/gofix/oserrorstring.go75
-rw-r--r--src/cmd/gofix/oserrorstring_test.go57
-rw-r--r--src/cmd/gofix/osopen.go2
-rw-r--r--src/cmd/gofix/sorthelpers.go47
-rw-r--r--src/cmd/gofix/sorthelpers_test.go45
-rw-r--r--src/cmd/gofix/sortslice.go50
-rw-r--r--src/cmd/gofix/sortslice_test.go35
-rw-r--r--src/cmd/gofix/stringssplit.go71
-rw-r--r--src/cmd/gofix/stringssplit_test.go51
-rw-r--r--src/cmd/gofix/testdata/reflect.decoder.go.out6
-rw-r--r--src/cmd/gofix/testdata/reflect.encoder.go.out2
-rw-r--r--src/cmd/gofix/testdata/reflect.export.go.out12
-rw-r--r--src/cmd/gofix/testdata/reflect.print.go.out2
-rw-r--r--src/cmd/gofix/testdata/reflect.read.go.out4
-rw-r--r--src/cmd/gofix/testdata/reflect.scan.go.out8
-rw-r--r--src/cmd/gofix/testdata/reflect.template.go.in4
-rw-r--r--src/cmd/gofix/testdata/reflect.template.go.out4
-rw-r--r--src/cmd/gofix/testdata/reflect.type.go.out4
-rw-r--r--src/cmd/gofmt/gofmt_test.go4
-rw-r--r--src/cmd/gofmt/rewrite.go2
-rw-r--r--src/cmd/goinstall/Makefile17
-rw-r--r--src/cmd/goinstall/doc.go74
-rw-r--r--src/cmd/goinstall/download.go248
-rw-r--r--src/cmd/goinstall/main.go92
-rw-r--r--src/cmd/goinstall/make.go60
-rw-r--r--src/cmd/goinstall/parse.go172
-rw-r--r--src/cmd/goinstall/path.go149
-rw-r--r--src/cmd/goinstall/syslist_test.go61
-rw-r--r--src/cmd/gopack/Makefile3
-rw-r--r--src/cmd/gotest/doc.go11
-rw-r--r--src/cmd/gotest/flag.go4
-rw-r--r--src/cmd/gotype/gotype.go2
-rw-r--r--src/cmd/govet/Makefile3
-rw-r--r--src/cmd/govet/govet.go62
-rw-r--r--src/cmd/goyacc/goyacc.go2
-rw-r--r--src/cmd/hgpatch/main.go18
-rw-r--r--src/cmd/ld/data.c67
-rw-r--r--src/cmd/ld/dwarf.c2
-rw-r--r--src/cmd/ld/elf.h74
-rw-r--r--src/cmd/ld/ldelf.c7
-rw-r--r--src/cmd/ld/ldmacho.c1
-rw-r--r--src/cmd/ld/ldpe.c12
-rw-r--r--src/cmd/ld/lib.c2
-rw-r--r--src/cmd/ld/lib.h4
-rw-r--r--src/cmd/ld/pe.c6
-rw-r--r--src/cmd/ld/symtab.c15
-rw-r--r--src/cmd/nm/Makefile3
-rw-r--r--src/cmd/prof/Makefile3
144 files changed, 2496 insertions, 2025 deletions
diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h
index 549e0c88a..ff6d51916 100644
--- a/src/cmd/5c/gc.h
+++ b/src/cmd/5c/gc.h
@@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-
+#include <u.h>
#include "../cc/cc.h"
#include "../5l/5.out.h"
diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c
index 4be1f6f62..a32387bc1 100644
--- a/src/cmd/5c/txt.c
+++ b/src/cmd/5c/txt.c
@@ -292,8 +292,7 @@ tmpreg(void)
void
regalloc(Node *n, Node *tn, Node *o)
{
- int i, j;
- static int lasti;
+ int i;
switch(tn->type->etype) {
case TCHAR:
@@ -310,16 +309,9 @@ regalloc(Node *n, Node *tn, Node *o)
if(i >= 0 && i < NREG)
goto out;
}
- j = lasti + REGRET+1;
- for(i=REGRET+1; i<NREG; i++) {
- if(j >= NREG)
- j = REGRET+1;
- if(reg[j] == 0) {
- i = j;
+ for(i=REGRET+1; i<=REGEXT-2; i++)
+ if(reg[i] == 0)
goto out;
- }
- j++;
- }
diag(tn, "out of fixed registers");
goto err;
@@ -331,16 +323,9 @@ regalloc(Node *n, Node *tn, Node *o)
if(i >= NREG && i < NREG+NFREG)
goto out;
}
- j = 0*2 + NREG;
- for(i=NREG; i<NREG+NFREG; i++) {
- if(j >= NREG+NFREG)
- j = NREG;
- if(reg[j] == 0) {
- i = j;
+ for(i=NREG; i<NREG+NFREG; i++)
+ if(reg[i] == 0)
goto out;
- }
- j++;
- }
diag(tn, "out of float registers");
goto err;
}
@@ -350,9 +335,6 @@ err:
return;
out:
reg[i]++;
-/* lasti++; *** StrongARM does register forwarding */
- if(lasti >= 5)
- lasti = 0;
nodreg(n, tn, i);
}
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 0bc1b38fc..d5b00b34d 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -22,6 +22,32 @@ defframe(Prog *ptxt)
maxstksize = 0;
}
+// Sweep the prog list to mark any used nodes.
+void
+markautoused(Prog* p)
+{
+ for (; p; p = p->link) {
+ if (p->from.name == D_AUTO && p->from.node)
+ p->from.node->used++;
+
+ if (p->to.name == D_AUTO && p->to.node)
+ p->to.node->used++;
+ }
+}
+
+// Fixup instructions after compactframe has moved all autos around.
+void
+fixautoused(Prog* p)
+{
+ for (; p; p = p->link) {
+ if (p->from.name == D_AUTO && p->from.node)
+ p->from.offset += p->from.node->stkdelta;
+
+ if (p->to.name == D_AUTO && p->to.node)
+ p->to.offset += p->to.node->stkdelta;
+ }
+}
+
/*
* generate:
* call f
@@ -147,13 +173,13 @@ cgen_callinter(Node *n, Node *res, int proc)
nodindreg(&nodsp, types[tptr], REGSP);
nodsp.xoffset = 4;
nodo.xoffset += widthptr;
- cgen(&nodo, &nodsp); // 4(SP) = 8(REG) -- i.s
+ cgen(&nodo, &nodsp); // 4(SP) = 4(REG) -- i.data
nodo.xoffset -= widthptr;
- cgen(&nodo, &nodr); // REG = 0(REG) -- i.m
+ cgen(&nodo, &nodr); // REG = 0(REG) -- i.tab
nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
- cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.m->fun[f]
+ cgen(&nodo, &nodr); // REG = 20+offset(REG) -- i.tab->fun[f]
// BOTCH nodr.type = fntype;
nodr.type = n->left->type;
diff --git a/src/cmd/5g/gobj.c b/src/cmd/5g/gobj.c
index acece6c0d..27c8be67d 100644
--- a/src/cmd/5g/gobj.c
+++ b/src/cmd/5g/gobj.c
@@ -182,6 +182,8 @@ dumpfuncs(void)
// fix up pc
pcloc = 0;
for(pl=plist; pl!=nil; pl=pl->link) {
+ if(isblank(pl->name))
+ continue;
for(p=pl->firstpc; p!=P; p=p->link) {
p->loc = pcloc;
if(p->as != ADATA && p->as != AGLOBL)
@@ -191,6 +193,8 @@ dumpfuncs(void)
// put out functions
for(pl=plist; pl!=nil; pl=pl->link) {
+ if(isblank(pl->name))
+ continue;
if(debug['S']) {
s = S;
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index caaa3e246..2d9218461 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -102,6 +102,19 @@ patch(Prog *p, Prog *to)
p->to.offset = to->loc;
}
+Prog*
+unpatch(Prog *p)
+{
+ Prog *q;
+
+ if(p->to.type != D_BRANCH)
+ fatal("unpatch: not a branch");
+ q = p->to.branch;
+ p->to.branch = P;
+ p->to.offset = 0;
+ return q;
+}
+
/*
* start a new Prog list.
*/
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 5fba02c9e..77d0a87eb 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -1525,6 +1525,7 @@ noreturn(Prog *p)
symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
symlist[3] = pkglookup("panic", runtimepkg);
+ symlist[4] = pkglookup("panicwrap", runtimepkg);
}
s = p->to.sym;
@@ -1555,27 +1556,27 @@ dumpone(Reg *r)
r->regdiff.b[z] |
r->act.b[z] |
0;
-// if(bany(&bit)) {
-// print("\t");
-// if(bany(&r->set))
-// print(" s:%Q", r->set);
-// if(bany(&r->use1))
-// print(" u1:%Q", r->use1);
-// if(bany(&r->use2))
-// print(" u2:%Q", r->use2);
-// if(bany(&r->refbehind))
-// print(" rb:%Q ", r->refbehind);
-// if(bany(&r->refahead))
-// print(" ra:%Q ", r->refahead);
-// if(bany(&r->calbehind))
-// print("cb:%Q ", r->calbehind);
-// if(bany(&r->calahead))
-// print(" ca:%Q ", r->calahead);
-// if(bany(&r->regdiff))
-// print(" d:%Q ", r->regdiff);
-// if(bany(&r->act))
-// print(" a:%Q ", r->act);
-// }
+ if(bany(&bit)) {
+ print("\t");
+ if(bany(&r->set))
+ print(" s:%Q", r->set);
+ if(bany(&r->use1))
+ print(" u1:%Q", r->use1);
+ if(bany(&r->use2))
+ print(" u2:%Q", r->use2);
+ if(bany(&r->refbehind))
+ print(" rb:%Q ", r->refbehind);
+ if(bany(&r->refahead))
+ print(" ra:%Q ", r->refahead);
+ if(bany(&r->calbehind))
+ print("cb:%Q ", r->calbehind);
+ if(bany(&r->calahead))
+ print(" ca:%Q ", r->calahead);
+ if(bany(&r->regdiff))
+ print(" d:%Q ", r->regdiff);
+ if(bany(&r->act))
+ print(" a:%Q ", r->act);
+ }
print("\n");
}
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 4afed2b80..2c9e50d00 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -68,9 +68,6 @@ enum {
ElfStrText,
ElfStrData,
ElfStrBss,
- ElfStrGosymcounts,
- ElfStrGosymtab,
- ElfStrGopclntab,
ElfStrSymtab,
ElfStrStrtab,
ElfStrShstrtab,
@@ -160,12 +157,11 @@ doelf(void)
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data");
- addstring(shstrtab, ".rodata");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
+ addstring(shstrtab, ".rodata");
+ addstring(shstrtab, ".gosymtab");
+ addstring(shstrtab, ".gopclntab");
if(!debug['s']) {
- elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
- elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
- elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
}
@@ -307,10 +303,11 @@ asmb(void)
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
codeblk(sect->vaddr, sect->len);
- /* output read-only data in text segment */
- sect = segtext.sect->next;
- seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
- datblk(sect->vaddr, sect->len);
+ /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+ for(sect = sect->next; sect != nil; sect = sect->next) {
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ datblk(sect->vaddr, sect->len);
+ }
if(debug['v'])
Bprint(&bso, "%5.2f datblk\n", cputime());
@@ -572,18 +569,6 @@ asmb(void)
elfshbits(sect);
if (!debug['s']) {
- sh = newElfShdr(elfstr[ElfStrGosymtab]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup("symtab", 0));
-
- sh = newElfShdr(elfstr[ElfStrGopclntab]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup("pclntab", 0));
-
sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB;
sh->off = symo;
diff --git a/src/cmd/5l/mkenam b/src/cmd/5l/mkenam
index 265cb9988..6cccb0263 100644
--- a/src/cmd/5l/mkenam
+++ b/src/cmd/5l/mkenam
@@ -28,18 +28,18 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-ed - ../5l/5.out.h <<'!'
-v/^ A/d
-,s/^ A/ "/
-g/ .*$/s///
-,s/,*$/",/
-1i
-char* anames[] =
-{
-.
-$a
-};
-.
-w enam.c
-Q
-!
+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
index e7c2db5f2..eb44344f4 100644
--- a/src/cmd/5l/noop.c
+++ b/src/cmd/5l/noop.c
@@ -45,8 +45,6 @@ static Sym* sym_divu;
static Sym* sym_mod;
static Sym* sym_modu;
-static void setdiv(int);
-
void
noops(void)
{
@@ -93,7 +91,6 @@ noops(void)
if(prog_div == P)
initdiv();
cursym->text->mark &= ~LEAF;
- setdiv(p->as);
continue;
case ANOP:
@@ -533,27 +530,6 @@ initdiv(void)
}
}
-static void
-setdiv(int as)
-{
- Prog *p = nil;
-
- switch(as){
- case ADIV:
- p = prog_div;
- break;
- case ADIVU:
- p = prog_divu;
- break;
- case AMOD:
- p = prog_mod;
- break;
- case AMODU:
- p = prog_modu;
- break;
- }
-}
-
void
nocache(Prog *p)
{
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
index 90394884f..7aa4aa976 100644
--- a/src/cmd/6c/cgen.c
+++ b/src/cmd/6c/cgen.c
@@ -1544,7 +1544,7 @@ sugen(Node *n, Node *nn, int32 w)
nod0.addable = 0;
nod0.right = l;
- /* prtree(&nod0, "hand craft"); /* */
+ // prtree(&nod0, "hand craft");
cgen(&nod0, Z);
}
break;
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
index 735cd8909..775d97281 100644
--- a/src/cmd/6c/gc.h
+++ b/src/cmd/6c/gc.h
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "../cc/cc.h"
#include "../6l/6.out.h"
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index 5260335df..9e7fbab0d 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -18,6 +18,32 @@ defframe(Prog *ptxt)
ptxt->to.offset |= rnd(stksize+maxarg, widthptr);
}
+// Sweep the prog list to mark any used nodes.
+void
+markautoused(Prog* p)
+{
+ for (; p; p = p->link) {
+ if (p->from.type == D_AUTO && p->from.node)
+ p->from.node->used++;
+
+ if (p->to.type == D_AUTO && p->to.node)
+ p->to.node->used++;
+ }
+}
+
+// Fixup instructions after compactframe has moved all autos around.
+void
+fixautoused(Prog* p)
+{
+ for (; p; p = p->link) {
+ if (p->from.type == D_AUTO && p->from.node)
+ p->from.offset += p->from.node->stkdelta;
+
+ if (p->to.type == D_AUTO && p->to.node)
+ p->to.offset += p->to.node->stkdelta;
+ }
+}
+
/*
* generate:
@@ -102,13 +128,13 @@ cgen_callinter(Node *n, Node *res, int proc)
nodindreg(&nodsp, types[tptr], D_SP);
nodo.xoffset += widthptr;
- cgen(&nodo, &nodsp); // 0(SP) = 8(REG) -- i.s
+ cgen(&nodo, &nodsp); // 0(SP) = 8(REG) -- i.data
nodo.xoffset -= widthptr;
- cgen(&nodo, &nodr); // REG = 0(REG) -- i.m
+ cgen(&nodo, &nodr); // REG = 0(REG) -- i.tab
nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
- cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.m->fun[f]
+ cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.tab->fun[f]
// BOTCH nodr.type = fntype;
nodr.type = n->left->type;
diff --git a/src/cmd/6g/gobj.c b/src/cmd/6g/gobj.c
index 507764a3b..ba8a4870e 100644
--- a/src/cmd/6g/gobj.c
+++ b/src/cmd/6g/gobj.c
@@ -228,6 +228,8 @@ dumpfuncs(void)
// fix up pc
pcloc = 0;
for(pl=plist; pl!=nil; pl=pl->link) {
+ if(isblank(pl->name))
+ continue;
for(p=pl->firstpc; p!=P; p=p->link) {
p->loc = pcloc;
if(p->as != ADATA && p->as != AGLOBL)
@@ -237,6 +239,8 @@ dumpfuncs(void)
// put out functions
for(pl=plist; pl!=nil; pl=pl->link) {
+ if(isblank(pl->name))
+ continue;
if(debug['S']) {
s = S;
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index 49d66e083..211915f54 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -98,6 +98,19 @@ patch(Prog *p, Prog *to)
p->to.offset = to->loc;
}
+Prog*
+unpatch(Prog *p)
+{
+ Prog *q;
+
+ if(p->to.type != D_BRANCH)
+ fatal("unpatch: not a branch");
+ q = p->to.branch;
+ p->to.branch = P;
+ p->to.offset = 0;
+ return q;
+}
+
/*
* start a new Prog list.
*/
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index af9b29cbc..4d4263047 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -1677,6 +1677,7 @@ noreturn(Prog *p)
symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
symlist[3] = pkglookup("panic", runtimepkg);
+ symlist[4] = pkglookup("panicwrap", runtimepkg);
}
s = p->to.sym;
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 4c04112b7..9136e0379 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -87,9 +87,6 @@ enum {
ElfStrText,
ElfStrData,
ElfStrBss,
- ElfStrGosymcounts,
- ElfStrGosymtab,
- ElfStrGopclntab,
ElfStrShstrtab,
ElfStrSymtab,
ElfStrStrtab,
@@ -571,10 +568,9 @@ doelf(void)
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata");
+ addstring(shstrtab, ".gosymtab");
+ addstring(shstrtab, ".gopclntab");
if(!debug['s']) {
- elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
- elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
- elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
dwarfaddshstrings(shstrtab);
@@ -718,10 +714,11 @@ asmb(void)
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
codeblk(sect->vaddr, sect->len);
- /* output read-only data in text segment */
- sect = segtext.sect->next;
- seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
- datblk(sect->vaddr, sect->len);
+ /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+ for(sect = sect->next; sect != nil; sect = sect->next) {
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ datblk(sect->vaddr, sect->len);
+ }
if(debug['v'])
Bprint(&bso, "%5.2f datblk\n", cputime());
@@ -1013,18 +1010,6 @@ asmb(void)
elfshbits(sect);
if (!debug['s']) {
- sh = newElfShdr(elfstr[ElfStrGosymtab]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup("symtab", 0));
-
- sh = newElfShdr(elfstr[ElfStrGopclntab]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup("pclntab", 0));
-
sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB;
sh->off = symo;
diff --git a/src/cmd/6l/mkenam b/src/cmd/6l/mkenam
index 5cabb2633..3001dbe93 100644
--- a/src/cmd/6l/mkenam
+++ b/src/cmd/6l/mkenam
@@ -28,18 +28,18 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-/bin/ed - ../6l/6.out.h <<'!'
-v/^ A/d
-,s/^ A/ "/
-g/ .*$/s///
-,s/,*$/",/
-1i
-char* anames[] =
-{
-.
-$a
-};
-.
-w enam.c
-Q
-!
+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.h b/src/cmd/8a/a.h
index 3cb30f4c2..c5c22d7ba 100644
--- a/src/cmd/8a/a.h
+++ b/src/cmd/8a/a.h
@@ -28,8 +28,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include <u.h>
-#include <libc.h>
#include <bio.h>
#include "../8l/8.out.h"
@@ -57,7 +55,9 @@ typedef struct Gen2 Gen2;
#define NSYMB 500
#define BUFSIZ 8192
#define HISTSZ 20
+#ifndef EOF
#define EOF (-1)
+#endif
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index 04662f83d..a8ac773da 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -29,7 +29,9 @@
// THE SOFTWARE.
%{
+#include <u.h>
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
+#include <libc.h>
#include "a.h"
%}
%union {
diff --git a/src/cmd/8a/l.s b/src/cmd/8a/l.s
deleted file mode 100644
index 4e193a31a..000000000
--- a/src/cmd/8a/l.s
+++ /dev/null
@@ -1,734 +0,0 @@
-// Inferno utils/8a/l.s
-// http://code.google.com/p/inferno-os/source/browse/utils/8a/l.s
-//
-// 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.
-
-/*
- * Memory and machine-specific definitions. Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define BI2BY 8 /* bits per byte */
-#define BI2WD 32 /* bits per word */
-#define BY2WD 4 /* bytes per word */
-#define BY2PG 4096 /* bytes per page */
-#define WD2PG (BY2PG/BY2WD) /* words per page */
-#define PGSHIFT 12 /* log(BY2PG) */
-#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define MAXMACH 1 /* max # cpus system can run */
-
-/*
- * Time
- */
-#define HZ (20) /* clock frequency */
-#define MS2HZ (1000/HZ) /* millisec per clock tick */
-#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
-#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
-#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
-
-/*
- * Fundamental addresses
- */
-
-/*
- * Address spaces
- *
- * User is at 0-2GB
- * Kernel is at 2GB-4GB
- *
- * To avoid an extra page map, both the user stack (USTKTOP) and
- * the temporary user stack (TSTKTOP) should be in the the same
- * 4 meg.
- */
-#define UZERO 0 /* base of user address space */
-#define UTZERO (UZERO+BY2PG) /* first address in user text */
-#define KZERO 0x80000000 /* base of kernel address space */
-#define KTZERO KZERO /* first address in kernel text */
-#define USERADDR 0xC0000000 /* struct User */
-#define UREGADDR (USERADDR+BY2PG-4*19)
-#define TSTKTOP USERADDR /* end of new stack in sysexec */
-#define TSTKSIZ 10
-#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
-#define USTKSIZE (16*1024*1024 - TSTKSIZ*BY2PG) /* size of user stack */
-#define ROMBIOS (KZERO|0xF0000)
-
-#define MACHSIZE 4096
-
-#define isphys(x) (((ulong)x)&KZERO)
-
-/*
- * known 80386 segments (in GDT) and their selectors
- */
-#define NULLSEG 0 /* null segment */
-#define KDSEG 1 /* kernel data/stack */
-#define KESEG 2 /* kernel executable */
-#define UDSEG 3 /* user data/stack */
-#define UESEG 4 /* user executable */
-#define TSSSEG 5 /* task segment */
-
-#define SELGDT (0<<3) /* selector is in gdt */
-#define SELLDT (1<<3) /* selector is in ldt */
-
-#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
-
-#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)
-#define KESEL SELECTOR(KESEG, SELGDT, 0)
-#define KDSEL SELECTOR(KDSEG, SELGDT, 0)
-#define UESEL SELECTOR(UESEG, SELGDT, 3)
-#define UDSEL SELECTOR(UDSEG, SELGDT, 3)
-#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
-
-/*
- * fields in segment descriptors
- */
-#define SEGDATA (0x10<<8) /* data/stack segment */
-#define SEGEXEC (0x18<<8) /* executable segment */
-#define SEGTSS (0x9<<8) /* TSS segment */
-#define SEGCG (0x0C<<8) /* call gate */
-#define SEGIG (0x0E<<8) /* interrupt gate */
-#define SEGTG (0x0F<<8) /* task gate */
-#define SEGTYPE (0x1F<<8)
-
-#define SEGP (1<<15) /* segment present */
-#define SEGPL(x) ((x)<<13) /* priority level */
-#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
-#define SEGG (1<<23) /* granularity 1==4k (for other) */
-#define SEGE (1<<10) /* expand down */
-#define SEGW (1<<9) /* writable (for data/stack) */
-#define SEGR (1<<9) /* readable (for code) */
-#define SEGD (1<<22) /* default 1==32bit (for code) */
-
-/*
- * virtual MMU
- */
-#define PTEMAPMEM (1024*1024) /* ??? */
-#define SEGMAPSIZE 16 /* ??? */
-#define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */
-#define PPN(x) ((x)&~(BY2PG-1))
-
-/*
- * physical MMU
- */
-#define PTEVALID (1<<0)
-#define PTEUNCACHED 0 /* everything is uncached */
-#define PTEWRITE (1<<1)
-#define PTERONLY (0<<1)
-#define PTEKERNEL (0<<2)
-#define PTEUSER (1<<2)
-
-/*
- * flag register bits that we care about
- */
-#define IFLAG 0x200
-
-#define OP16 BYTE $0x66
-
-/*
- * about to walk all over ms/dos - turn off interrupts
- */
-TEXT origin(SB),$0
-
- CLI
-
-#ifdef BOOT
-/*
- * This part of l.s is used only in the boot kernel.
- * It assumes that we are in real address mode, i.e.,
- * that we look like an 8086.
- */
-/*
- * relocate everything to a half meg and jump there
- * - looks wierd because it is being assembled by a 32 bit
- * assembler for a 16 bit world
- */
- MOVL $0,BX
- INCL BX
- SHLL $15,BX
- MOVL BX,CX
- MOVW BX,ES
- MOVL $0,SI
- MOVL SI,DI
- CLD; REP; MOVSL
-/* JMPFAR 0X8000:$lowcore(SB) /**/
- BYTE $0xEA
- WORD $lowcore(SB)
- WORD $0X8000
-
-TEXT lowcore(SB),$0
-
-/*
- * now that we're in low core, update the DS
- */
-
- MOVW BX,DS
-
-/*
- * goto protected mode
- */
-/* MOVL tgdtptr(SB),GDTR /**/
- BYTE $0x0f
- BYTE $0x01
- BYTE $0x16
- WORD $tgdtptr(SB)
- MOVL CR0,AX
- ORL $1,AX
- MOVL AX,CR0
-
-/*
- * clear prefetch queue (wierd code to avoid optimizations)
- */
- CLC
- JCC flush
- MOVL AX,AX
-flush:
-
-/*
- * set all segs
- */
-/* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
- BYTE $0xc7
- BYTE $0xc0
- WORD $SELECTOR(1, SELGDT, 0)
- MOVW AX,DS
- MOVW AX,SS
- MOVW AX,ES
- MOVW AX,FS
- MOVW AX,GS
-
-/* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
- BYTE $0x66
- BYTE $0xEA
- LONG $mode32bit-KZERO(SB)
- WORD $SELECTOR(2, SELGDT, 0)
-
-TEXT mode32bit(SB),$0
-
-#endif BOOT
-
- /*
- * Clear BSS
- */
- LEAL edata-KZERO(SB),SI
- MOVL SI,DI
- ADDL $4,DI
- MOVL $0,AX
- MOVL AX,(SI)
- LEAL end-KZERO(SB),CX
- SUBL DI,CX
- SHRL $2,CX
- CLD; REP; MOVSL
-
- /*
- * make a bottom level page table page that maps the first
- * 16 meg of physical memory
- */
- LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */
- ADDL $(BY2PG-1),AX /* must be page aligned */
- ANDL $(~(BY2PG-1)),AX /* ... */
- MOVL $(4*1024),CX /* pte's per page */
- MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
-setpte:
- MOVL BX,-4(AX)(CX*4)
- SUBL $(1<<PGSHIFT),BX
- LOOP setpte
-
- /*
- * make a top level page table page that maps the first
- * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
- */
- MOVL AX,BX
- ADDL $(4*BY2PG),AX
- ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
- MOVL BX,0(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
- ADDL $BY2PG,BX
- MOVL BX,4(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
- ADDL $BY2PG,BX
- MOVL BX,8(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
- ADDL $BY2PG,BX
- MOVL BX,12(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
-
- /*
- * point processor to top level page & turn on paging
- */
- MOVL AX,CR3
- MOVL CR0,AX
- ORL $0X80000000,AX
- ANDL $~(0x8|0x2),AX /* TS=0, MP=0 */
- MOVL AX,CR0
-
- /*
- * use a jump to an absolute location to get the PC into
- * KZERO.
- */
- LEAL tokzero(SB),AX
- JMP* AX
-
-TEXT tokzero(SB),$0
-
- /*
- * stack and mach
- */
- MOVL $mach0(SB),SP
- MOVL SP,m(SB)
- MOVL $0,0(SP)
- ADDL $(MACHSIZE-4),SP /* start stack under machine struct */
- MOVL $0, u(SB)
-
- /*
- * clear flags
- */
- MOVL $0,AX
- PUSHL AX
- POPFL
-
- CALL main(SB)
-
-loop:
- JMP loop
-
-GLOBL mach0+0(SB), $MACHSIZE
-GLOBL u(SB), $4
-GLOBL m(SB), $4
-GLOBL tpt(SB), $(BY2PG*6)
-
-/*
- * gdt to get us to 32-bit/segmented/unpaged mode
- */
-TEXT tgdt(SB),$0
-
- /* null descriptor */
- LONG $0
- LONG $0
-
- /* data segment descriptor for 4 gigabytes (PL 0) */
- LONG $(0xFFFF)
- LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
-
- /* exec segment descriptor for 4 gigabytes (PL 0) */
- LONG $(0xFFFF)
- LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
-
-/*
- * pointer to initial gdt
- */
-TEXT tgdtptr(SB),$0
-
- WORD $(3*8)
- LONG $tgdt-KZERO(SB)
-
-/*
- * input a byte
- */
-TEXT inb(SB),$0
-
- MOVL p+0(FP),DX
- XORL AX,AX
- INB
- RET
-
-/*
- * output a byte
- */
-TEXT outb(SB),$0
-
- MOVL p+0(FP),DX
- MOVL b+4(FP),AX
- OUTB
- RET
-
-/*
- * input a string of shorts from a port
- */
-TEXT inss(SB),$0
- MOVL p+0(FP),DX
- MOVL a+4(FP),DI
- MOVL c+8(FP),CX
- CLD; REP; OP16; INSL
- RET
-
-/*
- * output a string of shorts to a port
- */
-TEXT outss(SB),$0
- MOVL p+0(FP),DX
- MOVL a+4(FP),SI
- MOVL c+8(FP),CX
- CLD; REP; OP16; OUTSL
- RET
-
-/*
- * test and set
- */
-TEXT tas(SB),$0
- MOVL $0xdeadead,AX
- MOVL l+0(FP),BX
- XCHGL AX,(BX)
- RET
-
-/*
- * routines to load/read various system registers
- */
-GLOBL idtptr(SB),$6
-TEXT putidt(SB),$0 /* interrupt descriptor table */
- MOVL t+0(FP),AX
- MOVL AX,idtptr+2(SB)
- MOVL l+4(FP),AX
- MOVW AX,idtptr(SB)
- MOVL idtptr(SB),IDTR
- RET
-
-GLOBL gdtptr(SB),$6
-TEXT putgdt(SB),$0 /* global descriptor table */
- MOVL t+0(FP),AX
- MOVL AX,gdtptr+2(SB)
- MOVL l+4(FP),AX
- MOVW AX,gdtptr(SB)
- MOVL gdtptr(SB),GDTR
- RET
-
-TEXT putcr3(SB),$0 /* top level page table pointer */
- MOVL t+0(FP),AX
- MOVL AX,CR3
- RET
-
-TEXT puttr(SB),$0 /* task register */
- MOVL t+0(FP),AX
- MOVW AX,TASK
- RET
-
-TEXT getcr0(SB),$0 /* coprocessor bits */
- MOVL CR0,AX
- RET
-
-TEXT getcr2(SB),$0 /* fault address */
- MOVL CR2,AX
- RET
-
-#define FPOFF\
- WAIT;\
- MOVL CR0,AX;\
- ORL $0x4,AX /* EM=1 */;\
- MOVL AX,CR0
-
-#define FPON\
- MOVL CR0,AX;\
- ANDL $~0x4,AX /* EM=0 */;\
- MOVL AX,CR0
-
-TEXT fpoff(SB),$0 /* turn off floating point */
- FPOFF
- RET
-
-TEXT fpinit(SB),$0 /* turn on & init the floating point */
- FPON
- FINIT
- WAIT
- PUSHW $0x0330
- FLDCW 0(SP) /* ignore underflow/precision, signal others */
- POPW AX
- WAIT
- RET
-
-TEXT fpsave(SB),$0 /* save floating point state and turn off */
- MOVL p+0(FP),AX
- WAIT
- FSAVE 0(AX)
- FPOFF
- RET
-
-TEXT fprestore(SB),$0 /* turn on floating point and restore regs */
- FPON
- MOVL p+0(FP),AX
- FRSTOR 0(AX)
- WAIT
- RET
-
-TEXT fpstatus(SB),$0 /* get floating point status */
- FSTSW AX
- RET
-
-/*
- * special traps
- */
-TEXT intr0(SB),$0
- PUSHL $0
- PUSHL $0
- JMP intrcommon
-TEXT intr1(SB),$0
- PUSHL $0
- PUSHL $1
- JMP intrcommon
-TEXT intr2(SB),$0
- PUSHL $0
- PUSHL $2
- JMP intrcommon
-TEXT intr3(SB),$0
- PUSHL $0
- PUSHL $3
- JMP intrcommon
-TEXT intr4(SB),$0
- PUSHL $0
- PUSHL $4
- JMP intrcommon
-TEXT intr5(SB),$0
- PUSHL $0
- PUSHL $5
- JMP intrcommon
-TEXT intr6(SB),$0
- PUSHL $0
- PUSHL $6
- JMP intrcommon
-TEXT intr7(SB),$0
- PUSHL $0
- PUSHL $7
- JMP intrcommon
-TEXT intr8(SB),$0
- PUSHL $8
- JMP intrscommon
-TEXT intr9(SB),$0
- PUSHL $0
- PUSHL $9
- JMP intrcommon
-TEXT intr10(SB),$0
- PUSHL $10
- JMP intrscommon
-TEXT intr11(SB),$0
- PUSHL $11
- JMP intrscommon
-TEXT intr12(SB),$0
- PUSHL $12
- JMP intrscommon
-TEXT intr13(SB),$0
- PUSHL $13
- JMP intrscommon
-TEXT intr14(SB),$0
- PUSHL $14
- JMP intrscommon
-TEXT intr15(SB),$0
- PUSHL $0
- PUSHL $15
- JMP intrcommon
-TEXT intr16(SB),$0
- PUSHL $0
- PUSHL $16
- JMP intrcommon
-TEXT intr24(SB),$0
- PUSHL $0
- PUSHL $24
- JMP intrcommon
-TEXT intr25(SB),$0
- PUSHL $0
- PUSHL $25
- JMP intrcommon
-TEXT intr26(SB),$0
- PUSHL $0
- PUSHL $26
- JMP intrcommon
-TEXT intr27(SB),$0
- PUSHL $0
- PUSHL $27
- JMP intrcommon
-TEXT intr28(SB),$0
- PUSHL $0
- PUSHL $28
- JMP intrcommon
-TEXT intr29(SB),$0
- PUSHL $0
- PUSHL $29
- JMP intrcommon
-TEXT intr30(SB),$0
- PUSHL $0
- PUSHL $30
- JMP intrcommon
-TEXT intr31(SB),$0
- PUSHL $0
- PUSHL $31
- JMP intrcommon
-TEXT intr32(SB),$0
- PUSHL $0
- PUSHL $16
- JMP intrcommon
-TEXT intr33(SB),$0
- PUSHL $0
- PUSHL $33
- JMP intrcommon
-TEXT intr34(SB),$0
- PUSHL $0
- PUSHL $34
- JMP intrcommon
-TEXT intr35(SB),$0
- PUSHL $0
- PUSHL $35
- JMP intrcommon
-TEXT intr36(SB),$0
- PUSHL $0
- PUSHL $36
- JMP intrcommon
-TEXT intr37(SB),$0
- PUSHL $0
- PUSHL $37
- JMP intrcommon
-TEXT intr38(SB),$0
- PUSHL $0
- PUSHL $38
- JMP intrcommon
-TEXT intr39(SB),$0
- PUSHL $0
- PUSHL $39
- JMP intrcommon
-TEXT intr64(SB),$0
- PUSHL $0
- PUSHL $64
- JMP intrcommon
-TEXT intrbad(SB),$0
- PUSHL $0
- PUSHL $0x1ff
- JMP intrcommon
-
-intrcommon:
- PUSHL DS
- PUSHL ES
- PUSHL FS
- PUSHL GS
- PUSHAL
- MOVL $(KDSEL),AX
- MOVW AX,DS
- MOVW AX,ES
- LEAL 0(SP),AX
- PUSHL AX
- CALL trap(SB)
- POPL AX
- POPAL
- POPL GS
- POPL FS
- POPL ES
- POPL DS
- ADDL $8,SP /* error code and trap type */
- IRETL
-
-intrscommon:
- PUSHL DS
- PUSHL ES
- PUSHL FS
- PUSHL GS
- PUSHAL
- MOVL $(KDSEL),AX
- MOVW AX,DS
- MOVW AX,ES
- LEAL 0(SP),AX
- PUSHL AX
- CALL trap(SB)
- POPL AX
- POPAL
- POPL GS
- POPL FS
- POPL ES
- POPL DS
- ADDL $8,SP /* error code and trap type */
- IRETL
-
-/*
- * interrupt level is interrupts on or off
- */
-TEXT spllo(SB),$0
- PUSHFL
- POPL AX
- STI
- RET
-
-TEXT splhi(SB),$0
- PUSHFL
- POPL AX
- CLI
- RET
-
-TEXT splx(SB),$0
- MOVL s+0(FP),AX
- PUSHL AX
- POPFL
- RET
-
-/*
- * do nothing whatsoever till interrupt happens
- */
-TEXT idle(SB),$0
- HLT
- RET
-
-/*
- * label consists of a stack pointer and a PC
- */
-TEXT gotolabel(SB),$0
- MOVL l+0(FP),AX
- MOVL 0(AX),SP /* restore sp */
- MOVL 4(AX),AX /* put return pc on the stack */
- MOVL AX,0(SP)
- MOVL $1,AX /* return 1 */
- RET
-
-TEXT setlabel(SB),$0
- MOVL l+0(FP),AX
- MOVL SP,0(AX) /* store sp */
- MOVL 0(SP),BX /* store return pc */
- MOVL BX,4(AX)
- MOVL $0,AX /* return 0 */
- RET
-
-/*
- * Used to get to the first process.
- * Set up an interrupt return frame and IRET to user level.
- */
-TEXT touser(SB),$0
- PUSHL $(UDSEL) /* old ss */
- PUSHL $(USTKTOP) /* old sp */
- PUSHFL /* old flags */
- PUSHL $(UESEL) /* old cs */
- PUSHL $(UTZERO+32) /* old pc */
- MOVL $(UDSEL),AX
- MOVW AX,DS
- MOVW AX,ES
- MOVW AX,GS
- MOVW AX,FS
- IRETL
-
-/*
- * set configuration register
- */
-TEXT config(SB),$0
- MOVL l+0(FP),AX
- MOVL $0x3F3,DX
- OUTB
- OUTB
- RET
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index 078861877..ab4de417a 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -29,9 +29,10 @@
// THE SOFTWARE.
#define EXTERN
+#include <u.h>
+#include <libc.h>
#include "a.h"
#include "y.tab.h"
-#include <ctype.h>
enum
{
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c
index edb29ad8c..7f02bd96e 100644
--- a/src/cmd/8c/cgen.c
+++ b/src/cmd/8c/cgen.c
@@ -1581,7 +1581,7 @@ sugen(Node *n, Node *nn, int32 w)
nod0.addable = 0;
nod0.right = l;
- /* prtree(&nod0, "hand craft"); /* */
+ // prtree(&nod0, "hand craft");
cgen(&nod0, Z);
}
break;
diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h
index 9fead60e4..32b80e995 100644
--- a/src/cmd/8c/gc.h
+++ b/src/cmd/8c/gc.h
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "../cc/cc.h"
#include "../8l/8.out.h"
@@ -400,6 +401,7 @@ void shiftit(Type*, Node*, Node*);
#pragma varargck type "A" int
#pragma varargck type "B" Bits
#pragma varargck type "D" Adr*
+#pragma varargck type "lD" Adr*
#pragma varargck type "P" Prog*
#pragma varargck type "R" int
#pragma varargck type "S" char*
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
index d07a5439c..769ef2c66 100644
--- a/src/cmd/8c/swt.c
+++ b/src/cmd/8c/swt.c
@@ -237,10 +237,10 @@ outcode(void)
Bprint(&b, "\n");
Bprint(&b, "$$ // exports\n\n");
Bprint(&b, "$$ // local types\n\n");
- Bprint(&b, "$$ // dynimport\n", thestring);
+ Bprint(&b, "$$ // dynimport\n");
for(i=0; i<ndynimp; i++)
Bprint(&b, "dynimport %s %s %s\n", dynimp[i].local, dynimp[i].remote, dynimp[i].path);
- Bprint(&b, "\n$$ // dynexport\n", thestring);
+ Bprint(&b, "\n$$ // dynexport\n");
for(i=0; i<ndynexp; i++)
Bprint(&b, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
Bprint(&b, "\n$$\n\n");
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 25adb38c0..6db0474c9 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -20,6 +20,32 @@ defframe(Prog *ptxt)
maxstksize = 0;
}
+// Sweep the prog list to mark any used nodes.
+void
+markautoused(Prog* p)
+{
+ for (; p; p = p->link) {
+ if (p->from.type == D_AUTO && p->from.node)
+ p->from.node->used++;
+
+ if (p->to.type == D_AUTO && p->to.node)
+ p->to.node->used++;
+ }
+}
+
+// Fixup instructions after compactframe has moved all autos around.
+void
+fixautoused(Prog* p)
+{
+ for (; p; p = p->link) {
+ if (p->from.type == D_AUTO && p->from.node)
+ p->from.offset += p->from.node->stkdelta;
+
+ if (p->to.type == D_AUTO && p->to.node)
+ p->to.offset += p->to.node->stkdelta;
+ }
+}
+
void
clearfat(Node *nl)
{
@@ -141,15 +167,15 @@ cgen_callinter(Node *n, Node *res, int proc)
nodindreg(&nodsp, types[tptr], D_SP);
nodo.xoffset += widthptr;
- cgen(&nodo, &nodsp); // 0(SP) = 8(REG) -- i.s
+ cgen(&nodo, &nodsp); // 0(SP) = 4(REG) -- i.data
nodo.xoffset -= widthptr;
- cgen(&nodo, &nodr); // REG = 0(REG) -- i.m
+ cgen(&nodo, &nodr); // REG = 0(REG) -- i.tab
if(n->left->xoffset == BADWIDTH)
fatal("cgen_callinter: badwidth");
nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
- cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.m->fun[f]
+ cgen(&nodo, &nodr); // REG = 20+offset(REG) -- i.tab->fun[f]
// BOTCH nodr.type = fntype;
nodr.type = n->left->type;
diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c
index bc1dfe8bf..31c42a3f2 100644
--- a/src/cmd/8g/gobj.c
+++ b/src/cmd/8g/gobj.c
@@ -226,6 +226,8 @@ dumpfuncs(void)
// fix up pc
pcloc = 0;
for(pl=plist; pl!=nil; pl=pl->link) {
+ if(isblank(pl->name))
+ continue;
for(p=pl->firstpc; p!=P; p=p->link) {
p->loc = pcloc;
if(p->as != ADATA && p->as != AGLOBL)
@@ -235,6 +237,8 @@ dumpfuncs(void)
// put out functions
for(pl=plist; pl!=nil; pl=pl->link) {
+ if(isblank(pl->name))
+ continue;
if(debug['S']) {
s = S;
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index a8d65cf22..a35c81eb1 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -100,6 +100,19 @@ patch(Prog *p, Prog *to)
p->to.offset = to->loc;
}
+Prog*
+unpatch(Prog *p)
+{
+ Prog *q;
+
+ if(p->to.type != D_BRANCH)
+ fatal("unpatch: not a branch");
+ q = p->to.branch;
+ p->to.branch = P;
+ p->to.offset = 0;
+ return q;
+}
+
/*
* start a new Prog list.
*/
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
index a2f3def37..a4828c3a3 100644
--- a/src/cmd/8g/reg.c
+++ b/src/cmd/8g/reg.c
@@ -1533,6 +1533,7 @@ noreturn(Prog *p)
symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
symlist[3] = pkglookup("panic", runtimepkg);
+ symlist[4] = pkglookup("panicwrap", runtimepkg);
}
s = p->to.sym;
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index cb900d28d..e1ccfb8a3 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -83,9 +83,6 @@ enum {
ElfStrText,
ElfStrData,
ElfStrBss,
- ElfStrGosymcounts,
- ElfStrGosymtab,
- ElfStrGopclntab,
ElfStrShstrtab,
ElfStrSymtab,
ElfStrStrtab,
@@ -531,10 +528,9 @@ doelf(void)
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata");
+ addstring(shstrtab, ".gosymtab");
+ addstring(shstrtab, ".gopclntab");
if(!debug['s']) {
- elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
- elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
- elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
dwarfaddshstrings(shstrtab);
@@ -679,10 +675,11 @@ asmb(void)
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
codeblk(sect->vaddr, sect->len);
- /* output read-only data in text segment */
- sect = segtext.sect->next;
- seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
- datblk(sect->vaddr, sect->len);
+ /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+ for(sect = sect->next; sect != nil; sect = sect->next) {
+ seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
+ datblk(sect->vaddr, sect->len);
+ }
if(debug['v'])
Bprint(&bso, "%5.2f datblk\n", cputime());
@@ -920,10 +917,6 @@ asmb(void)
break;
Elfput:
- /* elf 386 */
- if(HEADTYPE == Htiny)
- debug['d'] = 1;
-
eh = getElfEhdr();
startva = INITTEXT - HEADR;
@@ -1087,18 +1080,6 @@ asmb(void)
elfshbits(sect);
if (!debug['s']) {
- sh = newElfShdr(elfstr[ElfStrGosymtab]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup("symtab", 0));
-
- sh = newElfShdr(elfstr[ElfStrGopclntab]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup("pclntab", 0));
-
sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB;
sh->off = symo;
@@ -1276,6 +1257,6 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
}
if(debug['v'] || debug['n'])
- Bprint(&bso, "symsize = %uld\n", symsize);
+ Bprint(&bso, "symsize = %d\n", symsize);
Bflush(&bso);
}
diff --git a/src/cmd/8l/list.c b/src/cmd/8l/list.c
index 4e199d767..31ae02346 100644
--- a/src/cmd/8l/list.c
+++ b/src/cmd/8l/list.c
@@ -176,7 +176,7 @@ Dconv(Fmt *fp)
}
brk:
if(a->index != D_NONE) {
- sprint(s, "(%R*%d)", a->index, a->scale);
+ sprint(s, "(%R*%d)", (int)a->index, a->scale);
strcat(str, s);
}
conv:
diff --git a/src/cmd/8l/mkenam b/src/cmd/8l/mkenam
index b33fec7cc..992aa3160 100644
--- a/src/cmd/8l/mkenam
+++ b/src/cmd/8l/mkenam
@@ -28,18 +28,18 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-ed - ../8l/8.out.h <<'!'
-v/^ A/d
-,s/^ A/ "/
-g/ .*$/s///
-,s/,*$/",/
-1i
-char* anames[] =
-{
-.
-$a
-};
-.
-w enam.c
-Q
-!
+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/8l/obj.c b/src/cmd/8l/obj.c
index 440dcb77f..ce7b59518 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -54,11 +54,9 @@ Header headers[] = {
"msdosexe", Hmsdosexe,
"darwin", Hdarwin,
"linux", Hlinux,
- "nacl", Hnacl,
"freebsd", Hfreebsd,
"windows", Hwindows,
"windowsgui", Hwindows,
- "tiny", Htiny,
0, 0
};
@@ -70,10 +68,8 @@ Header headers[] = {
* -Hmsdosexe -Tx -Rx is fake MS-DOS .EXE
* -Hdarwin -Tx -Rx is Apple Mach-O
* -Hlinux -Tx -Rx is Linux ELF32
- * -Hnacl -Tx -Rx was Google Native Client
* -Hfreebsd -Tx -Rx is FreeBSD ELF32
* -Hwindows -Tx -Rx is MS Windows PE32
- * -Htiny -Tx -Rx is tiny (os image)
*/
void
@@ -254,17 +250,6 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = PESECTALIGN;
break;
- case Htiny:
- tlsoffset = 0;
- elfinit();
- HEADR = ELFRESERVE;
- if(INITTEXT == -1)
- INITTEXT = 0x100000+HEADR;
- if(INITDAT == -1)
- INITDAT = 0;
- if(INITRND == -1)
- INITRND = 4096;
- break;
}
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%ux is ignored because of -R0x%ux\n",
@@ -488,7 +473,6 @@ loop:
s = lookup(x, r);
if(x != name)
free(x);
- name = nil;
if(debug['S'] && r == 0)
sig = 1729;
@@ -718,7 +702,6 @@ loop:
lastp = p;
goto loop;
}
- goto loop;
eof:
diag("truncated object file: %s", pn);
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 72ae043d6..2e0990c5a 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -414,7 +414,6 @@ dostkoff(void)
autoffset = 0;
q = P;
- q1 = P;
if(pmorestack != P)
if(!(p->from.scale & NOSPLIT)) {
p = appendp(p); // load g into CX
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index 66a843b23..a4cba1257 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -89,7 +89,7 @@ span1(Sym *s)
*bp++ = v;
*bp++ = v>>8;
*bp++ = v>>16;
- *bp++ = v>>24;
+ *bp = v>>24;
}
}
p->comefrom = P;
@@ -1319,7 +1319,7 @@ asmins(Prog *p)
andptr = and;
doasm(p);
if(andptr > and+sizeof and) {
- print("and[] is too short - %d byte instruction\n", andptr - and);
+ print("and[] is too short - %ld byte instruction\n", andptr - and);
errorexit();
}
}
diff --git a/src/cmd/cc/acid.c b/src/cmd/cc/acid.c
index c6a6722bd..23147e519 100644
--- a/src/cmd/cc/acid.c
+++ b/src/cmd/cc/acid.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
static char *kwd[] =
diff --git a/src/cmd/cc/bits.c b/src/cmd/cc/bits.c
index aef4449e8..4496d65e7 100644
--- a/src/cmd/cc/bits.c
+++ b/src/cmd/cc/bits.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
Bits
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
index 8e8f6af44..a38e658ce 100644
--- a/src/cmd/cc/cc.h
+++ b/src/cmd/cc/cc.h
@@ -28,10 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include <u.h>
#include <libc.h>
#include <bio.h>
-#include <ctype.h>
#pragma lib "../cc/cc.a$O"
@@ -816,7 +814,9 @@ int machcap(Node*);
#pragma varargck type "L" int32
#pragma varargck type "Q" int32
#pragma varargck type "O" int
+#pragma varargck type "O" uint
#pragma varargck type "T" Type*
+#pragma varargck type "U" char*
#pragma varargck type "|" int
enum
diff --git a/src/cmd/cc/cc.y b/src/cmd/cc/cc.y
index 470fdae26..515a80372 100644
--- a/src/cmd/cc/cc.y
+++ b/src/cmd/cc/cc.y
@@ -29,6 +29,7 @@
// THE SOFTWARE.
%{
+#include <u.h>
#include <stdio.h> /* if we don't, bison will, and cc.h re-#defines getc */
#include "cc.h"
%}
diff --git a/src/cmd/cc/com.c b/src/cmd/cc/com.c
index b1a8a4704..6e470ee64 100644
--- a/src/cmd/cc/com.c
+++ b/src/cmd/cc/com.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
int compar(Node*, int);
@@ -127,7 +128,7 @@ tcomo(Node *n, int f)
case ORETURN:
if(l == Z) {
if(n->type->etype != TVOID)
- warn(n, "null return of a typed function");
+ diag(n, "null return of a typed function");
break;
}
if(tcom(l))
diff --git a/src/cmd/cc/com64.c b/src/cmd/cc/com64.c
index 8d6e07d1b..fb7a3f750 100644
--- a/src/cmd/cc/com64.c
+++ b/src/cmd/cc/com64.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
/*
diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c
index d7604b649..d624bf247 100644
--- a/src/cmd/cc/dcl.c
+++ b/src/cmd/cc/dcl.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
Node*
@@ -1378,7 +1379,6 @@ tmerge(Type *t1, Sym *s)
Type *ta, *tb, *t2;
t2 = s->type;
-/*print("merge %T; %T\n", t1, t2);/**/
for(;;) {
if(t1 == T || t2 == T || t1 == t2)
break;
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
index 0e51101f1..42c245b56 100644
--- a/src/cmd/cc/dpchk.c
+++ b/src/cmd/cc/dpchk.c
@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
+#include <ctype.h>
#include "cc.h"
#include "y.tab.h"
@@ -56,7 +58,9 @@ struct Tname
{
char* name;
int param;
+ int count;
Tname* link;
+ Tprot* prot;
};
static Type* indchar;
@@ -131,8 +135,8 @@ getflag(char *s)
return flag;
}
-void
-newprot(Sym *m, Type *t, char *s)
+static void
+newprot(Sym *m, Type *t, char *s, Tprot **prot)
{
Bits flag;
Tprot *l;
@@ -142,32 +146,37 @@ newprot(Sym *m, Type *t, char *s)
return;
}
flag = getflag(s);
- for(l=tprot; l; l=l->link)
+ for(l=*prot; l; l=l->link)
if(beq(flag, l->flag) && sametype(t, l->type))
return;
l = alloc(sizeof(*l));
l->type = t;
l->flag = flag;
- l->link = tprot;
- tprot = l;
+ l->link = *prot;
+ *prot = l;
}
-void
-newname(char *s, int p)
+static Tname*
+newname(char *s, int p, int count)
{
Tname *l;
for(l=tname; l; l=l->link)
if(strcmp(l->name, s) == 0) {
- if(l->param != p)
+ if(p >= 0 && l->param != p)
yyerror("vargck %s already defined\n", s);
- return;
+ return l;
}
+ if(p < 0)
+ return nil;
+
l = alloc(sizeof(*l));
l->name = s;
l->param = p;
l->link = tname;
+ l->count = count;
tname = l;
+ return l;
}
void
@@ -234,6 +243,7 @@ pragvararg(void)
int n, c;
char *t;
Type *ty;
+ Tname *l;
if(!debug['F'])
goto out;
@@ -244,6 +254,8 @@ pragvararg(void)
goto cktype;
if(s && strcmp(s->name, "flag") == 0)
goto ckflag;
+ if(s && strcmp(s->name, "countpos") == 0)
+ goto ckcount;
yyerror("syntax in #pragma varargck");
goto out;
@@ -255,7 +267,18 @@ ckpos:
n = getnsn();
if(n < 0)
goto bad;
- newname(s->name, n);
+ newname(s->name, n, 0);
+ goto out;
+
+ckcount:
+/*#pragma varargck countpos name 2*/
+ s = getsym();
+ if(s == S)
+ goto bad;
+ n = getnsn();
+ if(n < 0)
+ goto bad;
+ newname(s->name, 0, n);
goto out;
ckflag:
@@ -276,6 +299,25 @@ ckflag:
goto out;
cktype:
+ c = getnsc();
+ unget(c);
+ if(c != '"') {
+/*#pragma varargck type name int*/
+ s = getsym();
+ if(s == S)
+ goto bad;
+ l = newname(s->name, -1, -1);
+ s = getsym();
+ if(s == S)
+ goto bad;
+ ty = s->type;
+ while((c = getnsc()) == '*')
+ ty = typ(TIND, ty);
+ unget(c);
+ newprot(s, ty, "a", &l->prot);
+ goto out;
+ }
+
/*#pragma varargck type O int*/
t = getquoted();
if(t == nil)
@@ -287,7 +329,7 @@ cktype:
while((c = getnsc()) == '*')
ty = typ(TIND, ty);
unget(c);
- newprot(s, ty, t);
+ newprot(s, ty, t, &tprot);
goto out;
bad:
@@ -384,7 +426,8 @@ dpcheck(Node *n)
char *s;
Node *a, *b;
Tname *l;
- int i;
+ Tprot *tl;
+ int i, j;
if(n == Z)
return;
@@ -398,20 +441,76 @@ dpcheck(Node *n)
if(l == 0)
return;
+ if(l->count > 0) {
+ // fetch count, then check remaining length
+ i = l->count;
+ a = nil;
+ b = n->right;
+ while(i > 0) {
+ b = nextarg(b, &a);
+ i--;
+ }
+ if(a == Z) {
+ diag(n, "can't find count arg");
+ return;
+ }
+ if(a->op != OCONST || !typechl[a->type->etype]) {
+ diag(n, "count is invalid constant");
+ return;
+ }
+ j = a->vconst;
+ i = 0;
+ while(b != Z) {
+ b = nextarg(b, &a);
+ i++;
+ }
+ if(i != j)
+ diag(n, "found %d argument%s after count %d", i, i == 1 ? "" : "s", j);
+ }
+
+ if(l->prot != nil) {
+ // check that all arguments after param or count
+ // are listed in type list.
+ i = l->count;
+ if(i == 0)
+ i = l->param;
+ if(i == 0)
+ return;
+ a = nil;
+ b = n->right;
+ while(i > 0) {
+ b = nextarg(b, &a);
+ i--;
+ }
+ if(a == Z) {
+ diag(n, "can't find count/param arg");
+ return;
+ }
+ while(b != Z) {
+ b = nextarg(b, &a);
+ for(tl=l->prot; tl; tl=tl->link)
+ if(sametype(a->type, tl->type))
+ break;
+ if(tl == nil)
+ diag(a, "invalid type %T in call to %s", a->type, s);
+ }
+ }
+
+ if(l->param <= 0)
+ return;
i = l->param;
a = nil;
b = n->right;
- a = Z;
while(i > 0) {
b = nextarg(b, &a);
i--;
}
if(a == Z) {
- warn(n, "cant find format arg");
+ diag(n, "can't find format arg");
return;
}
if(!sametype(indchar, a->type)) {
- warn(n, "format arg type %T", a->type);
+ diag(n, "format arg type %T", a->type);
return;
}
if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
diff --git a/src/cmd/cc/funct.c b/src/cmd/cc/funct.c
index 21d86258f..99477b2b2 100644
--- a/src/cmd/cc/funct.c
+++ b/src/cmd/cc/funct.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
typedef struct Ftab Ftab;
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c
index 9503cb2f2..3ba979c8a 100644
--- a/src/cmd/cc/godefs.c
+++ b/src/cmd/cc/godefs.c
@@ -29,6 +29,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
static int upper;
@@ -238,7 +239,7 @@ printtypename(Type *t)
Bprint(&outbuf, "%U", n);
break;
case TFUNC:
- Bprint(&outbuf, "func(", t);
+ Bprint(&outbuf, "func(");
for(t1 = t->down; t1 != T; t1 = t1->down) {
if(t1->etype == TVOID)
break;
diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c
index 71cc89bf0..15f2d374d 100644
--- a/src/cmd/cc/lex.c
+++ b/src/cmd/cc/lex.c
@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
+#include <ctype.h>
#include "cc.h"
#include "y.tab.h"
@@ -384,7 +386,7 @@ lookup(void)
}else
*w++ = *r;
}
- *w++ = '\0';
+ *w = '\0';
h = 0;
for(p=symb; *p;) {
@@ -1524,7 +1526,7 @@ alloc(int32 n)
p = malloc(n);
if(p == nil) {
print("alloc out of mem\n");
- exit(1);
+ exits("alloc: out of mem");
}
memset(p, 0, n);
return p;
@@ -1538,7 +1540,7 @@ allocn(void *p, int32 n, int32 d)
p = realloc(p, n+d);
if(p == nil) {
print("allocn out of mem\n");
- exit(1);
+ exits("allocn: out of mem");
}
if(d > 0)
memset((char*)p+n, 0, d);
diff --git a/src/cmd/cc/lexbody b/src/cmd/cc/lexbody
index 24f9bdc85..f4cc19c2e 100644
--- a/src/cmd/cc/lexbody
+++ b/src/cmd/cc/lexbody
@@ -96,7 +96,7 @@ alloc(int32 n)
p = malloc(n);
if(p == nil) {
print("alloc out of mem\n");
- exit(1);
+ exits("alloc: out of mem");
}
memset(p, 0, n);
return p;
@@ -110,7 +110,7 @@ allocn(void *p, int32 n, int32 d)
p = realloc(p, n+d);
if(p == nil) {
print("allocn out of mem\n");
- exit(1);
+ exits("allocn: out of mem");
}
if(d > 0)
memset((char*)p+n, 0, d);
@@ -245,7 +245,7 @@ lookup(void)
}else
*w++ = *r;
}
- *w++ = '\0';
+ *w = '\0';
h = 0;
for(p=symb; c = *p; p++)
diff --git a/src/cmd/cc/mac.c b/src/cmd/cc/mac.c
index c08cd9c97..43ae214d7 100644
--- a/src/cmd/cc/mac.c
+++ b/src/cmd/cc/mac.c
@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
+#include <ctype.h>
#include "cc.h"
#include "macbody"
diff --git a/src/cmd/cc/macbody b/src/cmd/cc/macbody
index ca8a54c0b..ed66361f1 100644
--- a/src/cmd/cc/macbody
+++ b/src/cmd/cc/macbody
@@ -830,11 +830,11 @@ linehist(char *f, int offset)
if(debug['f'])
if(f) {
if(offset)
- print("%4ld: %s (#line %d)\n", lineno, f, offset);
+ print("%4d: %s (#line %d)\n", lineno, f, offset);
else
- print("%4ld: %s\n", lineno, f);
+ print("%4d: %s\n", lineno, f);
} else
- print("%4ld: <pop>\n", lineno);
+ print("%4d: <pop>\n", lineno);
newflag = 0;
h = alloc(sizeof(Hist));
diff --git a/src/cmd/cc/omachcap.c b/src/cmd/cc/omachcap.c
index ec5aa86e9..f8fc1d88b 100644
--- a/src/cmd/cc/omachcap.c
+++ b/src/cmd/cc/omachcap.c
@@ -28,11 +28,13 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
/* default, like old cc */
int
machcap(Node *n)
{
+ USED(n);
return 0;
}
diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c
index 5d17cafc9..0e5e8c059 100644
--- a/src/cmd/cc/pgen.c
+++ b/src/cmd/cc/pgen.c
@@ -112,7 +112,7 @@ codgen(Node *n, Node *nn)
warnreach = 1;
gen(n);
if(canreach && thisfn->link->etype != TVOID)
- warn(Z, "no return at end of function: %s", n1->sym->name);
+ diag(Z, "no return at end of function: %s", n1->sym->name);
noretval(3);
gbranch(ORETURN);
diff --git a/src/cmd/cc/scon.c b/src/cmd/cc/scon.c
index 3047ca44f..193331f77 100644
--- a/src/cmd/cc/scon.c
+++ b/src/cmd/cc/scon.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
static Node*
diff --git a/src/cmd/cc/sub.c b/src/cmd/cc/sub.c
index e0d5df719..e5992e213 100644
--- a/src/cmd/cc/sub.c
+++ b/src/cmd/cc/sub.c
@@ -28,6 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include <u.h>
#include "cc.h"
Node*
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index e4e56d8dd..a4d83f1e7 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -66,7 +66,7 @@ func cname(s string) string {
// preamble. Multiple occurrences are concatenated with a separating space,
// even across files.
func (p *Package) ParseFlags(f *File, srcfile string) {
- linesIn := strings.Split(f.Preamble, "\n", -1)
+ linesIn := strings.Split(f.Preamble, "\n")
linesOut := make([]string, 0, len(linesIn))
NextLine:
@@ -78,7 +78,7 @@ NextLine:
}
l = strings.TrimSpace(l[4:])
- fields := strings.Split(l, ":", 2)
+ fields := strings.SplitN(l, ":", 2)
if len(fields) != 2 {
fatalf("%s: bad #cgo line: %s", srcfile, line)
}
@@ -230,9 +230,9 @@ func splitQuoted(s string) (r []string, err os.Error) {
args = append(args, string(arg[:i]))
}
if quote != 0 {
- err = os.ErrorString("unclosed quote")
+ err = os.NewError("unclosed quote")
} else if escaped {
- err = os.ErrorString("unfinished escaping")
+ err = os.NewError("unfinished escaping")
}
return args, err
}
@@ -275,7 +275,7 @@ func (p *Package) loadDefines(f *File) {
b.WriteString(f.Preamble)
stdout := p.gccDefines(b.Bytes())
- for _, line := range strings.Split(stdout, "\n", -1) {
+ for _, line := range strings.Split(stdout, "\n") {
if len(line) < 9 || line[0:7] != "#define" {
continue
}
@@ -397,7 +397,7 @@ func (p *Package) guessKinds(f *File) []*Name {
isConst[i] = true // until proven otherwise
}
- for _, line := range strings.Split(stderr, "\n", -1) {
+ for _, line := range strings.Split(stderr, "\n") {
if len(line) < 9 || line[0:9] != "cgo-test:" {
// the user will see any compiler errors when the code is compiled later.
continue
@@ -697,7 +697,7 @@ func (p *Package) gccMachine() []string {
return nil
}
-const gccTmp = "_obj/_cgo_.o"
+var gccTmp = objDir + "_cgo_.o"
// gccCmd returns the gcc command line to use for compiling
// the input.
@@ -1188,7 +1188,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
if ss, ok := dwarfToName[s]; ok {
s = ss
}
- s = strings.Join(strings.Split(s, " ", -1), "") // strip spaces
+ s = strings.Join(strings.Split(s, " "), "") // strip spaces
name := c.Ident("_Ctype_" + s)
typedef[name.Name] = t.Go
t.Go = name
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 84aeccc21..be9c2bc4f 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -18,6 +18,7 @@ import (
"go/token"
"io"
"os"
+ "path/filepath"
"reflect"
"strings"
)
@@ -228,7 +229,7 @@ func main() {
}
pkg := f.Package
if dir := os.Getenv("CGOPKGPATH"); dir != "" {
- pkg = dir + "/" + pkg
+ pkg = filepath.Join(dir, pkg)
}
p.PackagePath = pkg
p.writeOutput(f, input)
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index dbc7bcf69..6802dd1cf 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -14,17 +14,20 @@ import (
"go/printer"
"go/token"
"os"
+ "path/filepath"
"strings"
)
+var objDir = "_obj" + string(filepath.Separator)
+
// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Package) writeDefs() {
- fgo2 := creat("_obj/_cgo_gotypes.go")
- fc := creat("_obj/_cgo_defun.c")
- fm := creat("_obj/_cgo_main.c")
+ fgo2 := creat(objDir + "_cgo_gotypes.go")
+ fc := creat(objDir + "_cgo_defun.c")
+ fm := creat(objDir + "_cgo_main.c")
- fflg := creat("_obj/_cgo_flags")
+ fflg := creat(objDir + "_cgo_flags")
for k, v := range p.CgoFlags {
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
}
@@ -145,7 +148,7 @@ func dynimport(obj string) {
fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
}
for _, s := range sym {
- ss := strings.Split(s, ":", -1)
+ ss := strings.Split(s, ":")
fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
}
return
@@ -285,8 +288,8 @@ func (p *Package) writeOutput(f *File, srcfile string) {
base = base[0 : len(base)-3]
}
base = strings.Map(slashToUnderscore, base)
- fgo1 := creat("_obj/" + base + ".cgo1.go")
- fgcc := creat("_obj/" + base + ".cgo2.c")
+ fgo1 := creat(objDir + base + ".cgo1.go")
+ fgcc := creat(objDir + base + ".cgo2.c")
p.GoFiles = append(p.GoFiles, base+".cgo1.go")
p.GccFiles = append(p.GccFiles, base+".cgo2.c")
@@ -361,7 +364,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fc, fm *os.File) {
- fgcc := creat("_obj/_cgo_export.c")
+ fgcc := creat(objDir + "_cgo_export.c")
fgcch := creat("_cgo_export.h")
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go
index 1ca24103e..e79b0e1bf 100644
--- a/src/cmd/cgo/util.go
+++ b/src/cmd/cgo/util.go
@@ -103,7 +103,7 @@ func creat(name string) *os.File {
}
func slashToUnderscore(c int) int {
- if c == '/' {
+ if c == '/' || c == '\\' || c == ':' {
c = '_'
}
return c
diff --git a/src/cmd/cov/Makefile b/src/cmd/cov/Makefile
index fdeb14636..95dba9c60 100644
--- a/src/cmd/cov/Makefile
+++ b/src/cmd/cov/Makefile
@@ -17,9 +17,6 @@ OFILES=\
HFILES=\
tree.h\
-LIB=\
- ../../../lib/libmach.a\
-
NOINSTALL=1
include ../../Make.ccmd
diff --git a/src/cmd/ebnflint/ebnflint.go b/src/cmd/ebnflint/ebnflint.go
index cac39179f..0b0443156 100644
--- a/src/cmd/ebnflint/ebnflint.go
+++ b/src/cmd/ebnflint/ebnflint.go
@@ -35,6 +35,12 @@ var (
)
+func report(err os.Error) {
+ scanner.PrintError(os.Stderr, err)
+ os.Exit(1)
+}
+
+
func extractEBNF(src []byte) []byte {
var buf bytes.Buffer
@@ -75,34 +81,35 @@ func extractEBNF(src []byte) []byte {
func main() {
flag.Parse()
- var filename string
+ var (
+ filename string
+ src []byte
+ err os.Error
+ )
switch flag.NArg() {
case 0:
- filename = "/dev/stdin"
+ filename = "<stdin>"
+ src, err = ioutil.ReadAll(os.Stdin)
case 1:
filename = flag.Arg(0)
+ src, err = ioutil.ReadFile(filename)
default:
usage()
}
-
- src, err := ioutil.ReadFile(filename)
if err != nil {
- scanner.PrintError(os.Stderr, err)
- os.Exit(1)
+ report(err)
}
- if filepath.Ext(filename) == ".html" {
+ if filepath.Ext(filename) == ".html" || bytes.Index(src, open) >= 0 {
src = extractEBNF(src)
}
grammar, err := ebnf.Parse(fset, filename, src)
if err != nil {
- scanner.PrintError(os.Stderr, err)
- os.Exit(1)
+ report(err)
}
if err = ebnf.Verify(fset, grammar, *start); err != nil {
- scanner.PrintError(os.Stderr, err)
- os.Exit(1)
+ report(err)
}
}
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index c9bf501d1..95098c8af 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -6,6 +6,7 @@ char *runtimeimport =
"func \"\".panicslice ()\n"
"func \"\".throwreturn ()\n"
"func \"\".throwinit ()\n"
+ "func \"\".panicwrap (? string, ? string, ? string)\n"
"func \"\".panic (? interface { })\n"
"func \"\".recover (? *int32) interface { }\n"
"func \"\".printbool (? bool)\n"
@@ -22,6 +23,7 @@ char *runtimeimport =
"func \"\".printsp ()\n"
"func \"\".goprintf ()\n"
"func \"\".concatstring ()\n"
+ "func \"\".append ()\n"
"func \"\".appendslice (typ *uint8, x any, y []any) any\n"
"func \"\".cmpstring (? string, ? string) int\n"
"func \"\".slicestring (? string, ? int, ? int) string\n"
@@ -81,7 +83,7 @@ char *runtimeimport =
"func \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
"func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
- "func \"\".growslice (typ *uint8, old []any, cap int64) []any\n"
+ "func \"\".growslice (typ *uint8, old []any, n int64) []any\n"
"func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
"func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
"func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
@@ -101,9 +103,9 @@ char *unsafeimport =
"package unsafe\n"
"import runtime \"runtime\"\n"
"type \"\".Pointer uintptr\n"
- "func \"\".Offsetof (? any) int\n"
- "func \"\".Sizeof (? any) int\n"
- "func \"\".Alignof (? any) int\n"
+ "func \"\".Offsetof (? any) uintptr\n"
+ "func \"\".Sizeof (? any) uintptr\n"
+ "func \"\".Alignof (? any) uintptr\n"
"func \"\".Typeof (i interface { }) interface { }\n"
"func \"\".Reflect (i interface { }) (typ interface { }, addr \"\".Pointer)\n"
"func \"\".Unreflect (typ interface { }, addr \"\".Pointer) interface { }\n"
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index 906dadbc9..7e7b40526 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -116,12 +116,11 @@ typecheckclosure(Node *func, int top)
}
}
-Node*
-walkclosure(Node *func, NodeList **init)
+static Node*
+makeclosure(Node *func, NodeList **init, int nowrap)
{
- int narg;
- Node *xtype, *v, *addr, *xfunc, *call, *clos;
- NodeList *l, *in;
+ Node *xtype, *v, *addr, *xfunc;
+ NodeList *l;
static int closgen;
char *p;
@@ -133,7 +132,6 @@ walkclosure(Node *func, NodeList **init)
// each closure variable has a corresponding
// address parameter.
- narg = 0;
for(l=func->cvars; l; l=l->next) {
v = l->n;
if(v->op == 0)
@@ -146,7 +144,6 @@ walkclosure(Node *func, NodeList **init)
addr->class = PPARAM;
addr->addable = 1;
addr->ullman = 1;
- narg++;
v->heapaddr = addr;
@@ -154,7 +151,8 @@ walkclosure(Node *func, NodeList **init)
}
// then a dummy arg where the closure's caller pc sits
- xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ if (!nowrap)
+ xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
// then the function arguments
xtype->list = concat(xtype->list, func->list);
@@ -176,15 +174,36 @@ walkclosure(Node *func, NodeList **init)
typecheck(&xfunc, Etop);
closures = list(closures, xfunc);
+ return xfunc;
+}
+
+Node*
+walkclosure(Node *func, NodeList **init)
+{
+ int narg;
+ Node *xtype, *xfunc, *call, *clos;
+ NodeList *l, *in;
+
+ /*
+ * wrap body in external function
+ * with extra closure parameters.
+ */
+
+ // create the function
+ xfunc = makeclosure(func, init, 0);
+ xtype = xfunc->nname->ntype;
+
// prepare call of sys.closure that turns external func into func literal value.
clos = syslook("closure", 1);
clos->type = T;
clos->ntype = nod(OTFUNC, N, N);
in = list1(nod(ODCLFIELD, N, typenod(types[TINT]))); // siz
in = list(in, nod(ODCLFIELD, N, xtype));
+ narg = 0;
for(l=func->cvars; l; l=l->next) {
if(l->n->op == 0)
continue;
+ narg++;
in = list(in, nod(ODCLFIELD, N, l->n->heapaddr->ntype));
}
clos->ntype->list = in;
@@ -211,33 +230,18 @@ walkclosure(Node *func, NodeList **init)
void
walkcallclosure(Node *n, NodeList **init)
{
- Node *z;
- NodeList *ll, *cargs;
-
- walkexpr(&n->left, init);
- cargs = n->left // FUNC runtime.closure
- ->list // arguments
- ->next // skip first
- ->next; // skip second
-
- n->left = n->left // FUNC runtime.closure
- ->list // arguments
- ->next // skip first
- ->n // AS (to indreg)
- ->right; // argument == the generated function
-
- // New arg list for n. First the closure-args, stolen from
- // runtime.closure's 3rd and following,
- ll = nil;
- for (; cargs; cargs = cargs->next)
- ll = list(ll, cargs->n->right); // cargs->n is the OAS(INDREG, arg)
-
- // then an extra zero, to fill the dummy return pointer slot,
- z = nod(OXXX, N, N);
- nodconst(z, types[TUINTPTR], 0);
- z->typecheck = 1;
- ll = list(ll, z);
-
- // and finally the original parameter list.
- n->list = concat(ll, n->list);
+ if (n->op != OCALLFUNC || n->left->op != OCLOSURE) {
+ dump("walkcallclosure", n);
+ fatal("abuse of walkcallclosure");
+ }
+
+ // New arg list for n. First the closure-args
+ // and then the original parameter list.
+ n->list = concat(n->left->enter, n->list);
+ n->left = makeclosure(n->left, init, 1)->nname;
+ dowidth(n->left->type);
+ n->type = getoutargx(n->left->type);
+ // for a single valued function, pull the field type out of the struct
+ if (n->type && n->type->type && !n->type->type->down)
+ n->type = n->type->type->type;
}
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 335d056a0..7290f9d3b 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -39,6 +39,7 @@ push(void)
Sym *d;
d = mal(sizeof(*d));
+ d->lastlineno = lineno;
d->link = dclstack;
dclstack = d;
return d;
@@ -60,6 +61,7 @@ void
popdcl(void)
{
Sym *d, *s;
+ int lno;
// if(dflag())
// print("revert\n");
@@ -68,7 +70,9 @@ popdcl(void)
if(d->name == nil)
break;
s = pkglookup(d->name, d->pkg);
+ lno = s->lastlineno;
dcopy(s, d);
+ d->lastlineno = lno;
if(dflag())
print("\t%L pop %S %p\n", lineno, s, s->def);
}
@@ -81,19 +85,12 @@ popdcl(void)
void
poptodcl(void)
{
- Sym *d, *s;
-
- for(d=dclstack; d!=S; d=d->link) {
- if(d->name == nil)
- break;
- s = pkglookup(d->name, d->pkg);
- dcopy(s, d);
- if(dflag())
- print("\t%L pop %S\n", lineno, s);
- }
- if(d == S)
- fatal("poptodcl: no mark");
- dclstack = d;
+ // pop the old marker and push a new one
+ // (cannot reuse the existing one)
+ // because we use the markers to identify blocks
+ // for the goto restriction checks.
+ popdcl();
+ markdcl();
}
void
@@ -1241,10 +1238,7 @@ funccompile(Node *n, int isclosure)
stksize = 0;
dclcontext = PAUTO;
funcdepth = n->funcdepth + 1;
- hasgoto = 0;
compile(n);
- if(hasgoto)
- clearstk();
curfn = nil;
funcdepth = 0;
dclcontext = PEXTERN;
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index ad7b65b30..cb66921ba 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -11,6 +11,10 @@
static void cgen_dcl(Node *n);
static void cgen_proc(Node *n, int proc);
+static void checkgoto(Node*, Node*);
+
+static Label *labellist;
+static Label *lastlabel;
Node*
sysfunc(char *name)
@@ -80,71 +84,122 @@ clearlabels(void)
lastlabel = L;
}
-static void
-newlab(int op, Node *nlab, Node *stmt)
+static Label*
+newlab(Node *n)
{
- Label *lab;
Sym *s;
- int32 lno;
+ Label *lab;
+
+ s = n->left->sym;
+ if((lab = s->label) == L) {
+ lab = mal(sizeof(*lab));
+ if(lastlabel == nil)
+ labellist = lab;
+ else
+ lastlabel->link = lab;
+ lastlabel = lab;
+ lab->sym = s;
+ s->label = lab;
+ }
- s = nlab->left->sym;
- lno = nlab->left->lineno;
-
- lab = mal(sizeof(*lab));
- if(lastlabel == nil)
- labellist = lab;
- else
- lastlabel->link = lab;
- lastlabel = lab;
-
- lab->lineno = lno;
- lab->sym = s;
- lab->op = op;
- lab->label = pc;
- lab->stmt = stmt;
- if(op == OLABEL) {
- if(s->label != L) {
- lineno = lno;
- yyerror("label %S already defined at %L", s, s->label->lineno);
- } else
- s->label = lab;
- }
+ if(n->op == OLABEL) {
+ if(lab->def != N)
+ yyerror("label %S already defined at %L", s, lab->def->lineno);
+ else
+ lab->def = n;
+ } else
+ lab->use = list(lab->use, n);
+
+ return lab;
}
void
checklabels(void)
{
- Label *l;
- Sym *s;
- int lno;
+ Label *lab;
+ NodeList *l;
- lno = lineno;
-
- // resolve goto using syms
- for(l=labellist; l!=L; l=l->link) {
- switch(l->op) {
- case OGOTO:
- s = l->sym;
- if(s->label == L) {
- lineno = l->lineno;
- yyerror("label %S not defined", s);
- break;
- }
- s->label->used = 1;
- patch(l->label, s->label->label);
- break;
+ for(lab=labellist; lab!=L; lab=lab->link) {
+ if(lab->def == N) {
+ for(l=lab->use; l; l=l->next)
+ yyerrorl(l->n->lineno, "label %S not defined", lab->sym);
+ continue;
}
+ if(lab->use == nil && !lab->used) {
+ yyerrorl(lab->def->lineno, "label %S defined and not used", lab->sym);
+ continue;
+ }
+ if(lab->gotopc != P)
+ fatal("label %S never resolved", lab->sym);
+ for(l=lab->use; l; l=l->next)
+ checkgoto(l->n, lab->def);
}
-
- // diagnose unused labels
- for(l=labellist; l!=L; l=l->link) {
- if(l->op == OLABEL && !l->used) {
- lineno = l->lineno;
- yyerror("label %S defined and not used", l->sym);
+}
+
+static void
+checkgoto(Node *from, Node *to)
+{
+ int nf, nt;
+ Sym *block, *dcl, *fs, *ts;
+ int lno;
+
+ if(from->sym == to->sym)
+ return;
+
+ nf = 0;
+ for(fs=from->sym; fs; fs=fs->link)
+ nf++;
+ nt = 0;
+ for(fs=to->sym; fs; fs=fs->link)
+ nt++;
+ fs = from->sym;
+ for(; nf > nt; nf--)
+ fs = fs->link;
+ if(fs != to->sym) {
+ lno = lineno;
+ setlineno(from);
+
+ // decide what to complain about.
+ // prefer to complain about 'into block' over declarations,
+ // so scan backward to find most recent block or else dcl.
+ block = S;
+ dcl = S;
+ ts = to->sym;
+ for(; nt > nf; nt--) {
+ if(ts->pkg == nil)
+ block = ts;
+ else
+ dcl = ts;
+ ts = ts->link;
}
+ while(ts != fs) {
+ if(ts->pkg == nil)
+ block = ts;
+ else
+ dcl = ts;
+ ts = ts->link;
+ fs = fs->link;
+ }
+
+ if(block)
+ yyerror("goto %S jumps into block starting at %L", from->left->sym, block->lastlineno);
+ else
+ yyerror("goto %S jumps over declaration of %S at %L", from->left->sym, dcl, dcl->lastlineno);
+ lineno = lno;
}
-
- lineno = lno;
+}
+
+static Label*
+stmtlabel(Node *n)
+{
+ Label *lab;
+
+ if(n->sym != S)
+ if((lab = n->sym->label) != L)
+ if(lab->def != N)
+ if(lab->def->right == n)
+ return lab;
+ return L;
}
/*
@@ -193,11 +248,6 @@ gen(Node *n)
break;
case OEMPTY:
- // insert no-op so that
- // L:; for { }
- // does not treat L as a label for the loop.
- if(lastlabel != L && lastlabel->label == p3)
- gused(N);
break;
case OBLOCK:
@@ -205,13 +255,41 @@ gen(Node *n)
break;
case OLABEL:
- newlab(OLABEL, n, n->right);
+ lab = newlab(n);
+
+ // if there are pending gotos, resolve them all to the current pc.
+ for(p1=lab->gotopc; p1; p1=p2) {
+ p2 = unpatch(p1);
+ patch(p1, pc);
+ }
+ lab->gotopc = P;
+ if(lab->labelpc == P)
+ lab->labelpc = pc;
+
+ if(n->right) {
+ switch(n->right->op) {
+ case OFOR:
+ case OSWITCH:
+ case OSELECT:
+ // so stmtlabel can find the label
+ n->right->sym = lab->sym;
+ }
+ }
break;
case OGOTO:
- hasgoto = 1;
- newlab(OGOTO, n, N);
- gjmp(P);
+ // if label is defined, emit jump to it.
+ // otherwise save list of pending gotos in lab->gotopc.
+ // the list is linked through the normal jump target field
+ // to avoid a second list. (the jumps are actually still
+ // valid code, since they're just going to another goto
+ // to the same label. we'll unwind it when we learn the pc
+ // of the label in the OLABEL case above.)
+ lab = newlab(n);
+ if(lab->labelpc != P)
+ gjmp(lab->labelpc);
+ else
+ lab->gotopc = gjmp(lab->gotopc);
break;
case OBREAK:
@@ -266,12 +344,10 @@ gen(Node *n)
continpc = pc;
// define break and continue labels
- if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n) {
+ if((lab = stmtlabel(n)) != L) {
lab->breakpc = breakpc;
lab->continpc = continpc;
- } else
- lab = L;
-
+ }
gen(n->nincr); // contin: incr
patch(p1, pc); // test:
bgen(n->ntest, 0, breakpc); // if(!test) goto break
@@ -304,10 +380,8 @@ gen(Node *n)
breakpc = gjmp(P); // break: goto done
// define break label
- if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
+ if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- else
- lab = L;
patch(p1, pc); // test:
genlist(n->nbody); // switch(test) body
@@ -323,10 +397,8 @@ gen(Node *n)
breakpc = gjmp(P); // break: goto done
// define break label
- if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
+ if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- else
- lab = L;
patch(p1, pc); // test:
genlist(n->nbody); // select() body
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index c16903e77..8ca086ee0 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -278,6 +278,7 @@ struct Node
int32 iota;
};
#define N ((Node*)0)
+EXTERN int32 walkgen;
struct NodeList
{
@@ -301,6 +302,7 @@ struct Sym
uchar flags;
uchar sym; // huffman encoding in object file
Sym* link;
+ int32 npkg; // number of imported packages with this name
// saved and restored by dcopy
Pkg* pkg;
@@ -632,21 +634,20 @@ typedef struct Prog Prog;
struct Label
{
- uchar op; // OGOTO/OLABEL
uchar used;
Sym* sym;
- Node* stmt;
- Prog* label; // pointer to code
+ Node* def;
+ NodeList* use;
+ Label* link;
+
+ // for use during gen
+ Prog* gotopc; // pointer to unresolved gotos
+ Prog* labelpc; // pointer to code
Prog* breakpc; // pointer to code
Prog* continpc; // pointer to code
- Label* link;
- int32 lineno;
};
#define L ((Label*)0)
-EXTERN Label* labellist;
-EXTERN Label* lastlabel;
-
/*
* note this is the runtime representation
* of the compilers arrays.
@@ -691,6 +692,7 @@ EXTERN char* infile;
EXTERN char* outfile;
EXTERN Biobuf* bout;
EXTERN int nerrors;
+EXTERN int nsavederrors;
EXTERN int nsyntaxerrors;
EXTERN int safemode;
EXTERN char namebuf[NSYMB];
@@ -776,6 +778,7 @@ EXTERN int32 nhunk;
EXTERN int32 thunk;
EXTERN int exporting;
+EXTERN int erroring;
EXTERN int noargnames;
EXTERN int funcdepth;
@@ -913,8 +916,8 @@ Type* pkgtype(Sym *s);
void allocparams(void);
void cgen_as(Node *nl, Node *nr);
void cgen_callmeth(Node *n, int proc);
-void checklabels(void);
void clearlabels(void);
+void checklabels(void);
int dotoffset(Node *n, int *oary, Node **nn);
void gen(Node *n);
void genlist(NodeList *l);
@@ -1132,6 +1135,7 @@ Type* ptrto(Type *t);
void* remal(void *p, int32 on, int32 n);
Sym* restrictlookup(char *name, Pkg *pkg);
Node* safeexpr(Node *n, NodeList **init);
+void saveerrors(void);
Node* cheapexpr(Node *n, NodeList **init);
int32 setlineno(Node *n);
void setmaxarg(Type *t);
@@ -1195,7 +1199,7 @@ void walkstmt(Node **np);
void walkstmtlist(NodeList *l);
/*
- * arch-specific ggen.c/gsubr.c/gobj.c
+ * arch-specific ggen.c/gsubr.c/gobj.c/pgen.c
*/
#define P ((Prog*)0)
@@ -1237,6 +1241,7 @@ int dsymptr(Sym *s, int off, Sym *x, int xoff);
int duintxx(Sym *s, int off, uint64 v, int wid);
void dumpdata(void);
void dumpfuncs(void);
+void fixautoused(Prog*);
void gdata(Node*, Node*, int);
void gdatacomplex(Node*, Mpcplx*);
void gdatastring(Node*, Strlit*);
@@ -1246,15 +1251,15 @@ void ggloblsym(Sym *s, int32 width, int dupok);
Prog* gjmp(Prog*);
void gused(Node*);
int isfat(Type*);
+void markautoused(Prog*);
Plist* newplist(void);
Node* nodarg(Type*, int);
void nopout(Prog*);
void patch(Prog*, Prog*);
+Prog* unpatch(Prog*);
void zfile(Biobuf *b, char *p, int n);
void zhist(Biobuf *b, int line, vlong offset);
void zname(Biobuf *b, Sym *s, int t);
void data(void);
void text(void);
-EXTERN int hasgoto;
-void clearstk(void);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 1278c2586..01a4e822f 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -66,7 +66,7 @@ static void fixlbrace(int);
%type <node> switch_stmt uexpr
%type <node> xfndcl typedcl
-%type <list> xdcl fnbody fnres switch_body loop_body dcl_name_list
+%type <list> xdcl fnbody fnres loop_body dcl_name_list
%type <list> new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
%type <list> oexpr_list caseblock_list stmt_list oarg_type_list_ocomma arg_type_list
%type <list> interfacedcl_list vardcl vardcl_list structdcl structdcl_list
@@ -237,7 +237,11 @@ import_here:
import_package:
LPACKAGE sym import_safety ';'
{
- importpkg->name = $2->name;
+ if(importpkg->name == nil) {
+ importpkg->name = $2->name;
+ pkglookup($2->name, nil)->npkg++;
+ } else if(strcmp(importpkg->name, $2->name) != 0)
+ yyerror("conflicting names %s and %s for package %Z", importpkg->name, $2->name, importpkg->path);
importpkg->direct = 1;
if(safemode && !curio.importsafe)
@@ -449,7 +453,7 @@ case:
// will be converted to OCASE
// right will point to next case
// done in casebody()
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
$$->list = $2;
if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
@@ -468,7 +472,7 @@ case:
// will be converted to OCASE
// right will point to next case
// done in casebody()
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
if($2->next == nil)
n = nod(OAS, $2->n, $4);
@@ -484,7 +488,7 @@ case:
// will be converted to OCASE
// right will point to next case
// done in casebody()
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
$$->list = list1(colas($2, list1($4)));
}
@@ -492,7 +496,7 @@ case:
{
Node *n;
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
// type switch - declare variable
@@ -514,17 +518,6 @@ compound_stmt:
popdcl();
}
-switch_body:
- LBODY
- {
- markdcl();
- }
- caseblock_list '}'
- {
- $$ = $3;
- popdcl();
- }
-
caseblock:
case
{
@@ -553,6 +546,7 @@ caseblock:
yyerror("missing statement after label");
$$ = $1;
$$->nbody = $3;
+ popdcl();
}
caseblock_list:
@@ -674,11 +668,11 @@ switch_stmt:
n = N;
typesw = nod(OXXX, typesw, n);
}
- switch_body
+ LBODY caseblock_list '}'
{
$$ = $3;
$$->op = OSWITCH;
- $$->list = $5;
+ $$->list = $6;
typesw = typesw->left;
popdcl();
}
@@ -686,15 +680,13 @@ switch_stmt:
select_stmt:
LSELECT
{
- markdcl();
typesw = nod(OXXX, typesw, N);
}
- switch_body
+ LBODY caseblock_list '}'
{
$$ = nod(OSELECT, N, N);
- $$->list = $3;
+ $$->list = $4;
typesw = typesw->left;
- popdcl();
}
/*
@@ -1474,13 +1466,19 @@ non_dcl_stmt:
$$ = $1;
$$->nelse = list1($3);
}
-| labelname ':' stmt
+| labelname ':'
+ {
+ $1 = nod(OLABEL, $1, N);
+ $1->sym = dclstack; // context, for goto restrictions
+ }
+ stmt
{
NodeList *l;
- l = list1(nod(OLABEL, $1, $3));
- if($3)
- l = list(l, $3);
+ $1->right = $4;
+ l = list1($1);
+ if($4)
+ l = list(l, $4);
$$ = liststmt(l);
}
| LFALL
@@ -1507,6 +1505,7 @@ non_dcl_stmt:
| LGOTO new_name
{
$$ = nod(OGOTO, $2, N);
+ $$->sym = dclstack; // context, for goto restrictions
}
| LRETURN oexpr_list
{
@@ -1662,7 +1661,11 @@ hidden_import:
Pkg *p;
p = mkpkg($3.u.sval);
- p->name = $2->name;
+ if(p->name == nil) {
+ p->name = $2->name;
+ pkglookup($2->name, nil)->npkg++;
+ } else if(strcmp(p->name, $2->name) != 0)
+ yyerror("conflicting names %s and %s for package %Z", p->name, $2->name, p->path);
}
| LVAR hidden_pkg_importsym hidden_type ';'
{
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 88acb60af..5c642375a 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -97,7 +97,7 @@ fault(int s)
// in the program, don't bother complaining
// about the seg fault too; let the user clean up
// the code and try again.
- if(nerrors > 0)
+ if(nsavederrors + nerrors > 0)
errorexit();
fatal("fault");
}
@@ -256,7 +256,10 @@ main(int argc, char *argv[])
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC) {
curfn = l->n;
+ saveerrors();
typechecklist(l->n->nbody, Etop);
+ if(nerrors != 0)
+ l->n->nbody = nil; // type errors; do not compile
}
curfn = nil;
@@ -264,7 +267,7 @@ main(int argc, char *argv[])
if(l->n->op == ODCLFUNC)
funccompile(l->n, 0);
- if(nerrors == 0)
+ if(nsavederrors+nerrors == 0)
fninit(xtop);
while(closures) {
@@ -278,12 +281,12 @@ main(int argc, char *argv[])
if(l->n->op == ONAME)
typecheck(&l->n, Erv);
- if(nerrors)
+ if(nerrors+nsavederrors)
errorexit();
dumpobj();
- if(nerrors)
+ if(nerrors+nsavederrors)
errorexit();
flusherrors();
@@ -291,6 +294,13 @@ main(int argc, char *argv[])
return 0;
}
+void
+saveerrors(void)
+{
+ nsavederrors += nerrors;
+ nerrors = 0;
+}
+
static int
arsize(Biobuf *b, char *name)
{
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index ab6186697..552e405d8 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -30,6 +30,8 @@ compile(Node *fn)
if(fn->nbody == nil)
return;
+ saveerrors();
+
// set up domain for labels
clearlabels();
@@ -53,7 +55,7 @@ compile(Node *fn)
hasdefer = 0;
walk(curfn);
- if(nerrors != 0 || isblank(curfn->nname))
+ if(nerrors != 0)
goto ret;
allocparams();
@@ -67,7 +69,7 @@ compile(Node *fn)
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, curfn->nname, &nod1);
+ ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
afunclit(&ptxt->from);
ginit();
@@ -111,8 +113,7 @@ compile(Node *fn)
}
oldstksize = stksize;
- if(thechar != '5')
- compactframe(ptxt);
+ compactframe(ptxt);
if(0)
print("compactframe: %ld to %ld\n", oldstksize, stksize);
@@ -142,12 +143,12 @@ cmpstackvar(Node *a, Node *b)
}
+// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
static void
compactframe(Prog* ptxt)
{
NodeList *ll;
Node* n;
- Prog *p;
uint32 w;
if (stksize == 0)
@@ -155,17 +156,10 @@ compactframe(Prog* ptxt)
// Mark the PAUTO's unused.
for(ll=curfn->dcl; ll != nil; ll=ll->next)
- if (ll->n->class == PAUTO && ll->n->op == ONAME)
+ if (ll->n->class == PAUTO)
ll->n->used = 0;
- // Sweep the prog list to mark any used nodes.
- for (p = ptxt; p; p = p->link) {
- if (p->from.type == D_AUTO && p->from.node)
- p->from.node->used++;
-
- if (p->to.type == D_AUTO && p->to.node)
- p->to.node->used++;
- }
+ markautoused(ptxt);
listsort(&curfn->dcl, cmpstackvar);
@@ -191,7 +185,6 @@ compactframe(Prog* ptxt)
stksize = 0;
for(ll = curfn->dcl; ll != nil; ll=ll->next) {
n = ll->n;
- // TODO find out where the literal autos come from
if (n->class != PAUTO || n->op != ONAME)
continue;
@@ -205,14 +198,7 @@ compactframe(Prog* ptxt)
n->stkdelta = -stksize - n->xoffset;
}
- // Fixup instructions.
- for (p = ptxt; p; p = p->link) {
- if (p->from.type == D_AUTO && p->from.node)
- p->from.offset += p->from.node->stkdelta;
-
- if (p->to.type == D_AUTO && p->to.node)
- p->to.offset += p->to.node->stkdelta;
- }
+ fixautoused(ptxt);
// The debug information needs accurate offsets on the symbols.
for(ll = curfn->dcl ;ll != nil; ll=ll->next) {
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 00fc720b8..e13c95db9 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -15,6 +15,7 @@ func panicindex()
func panicslice()
func throwreturn()
func throwinit()
+func panicwrap(string, string, string)
func panic(interface{})
func recover(*int32) interface{}
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 49797f9df..40b0c4fd1 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -45,10 +45,12 @@ adderr(int line, char *fmt, va_list arg)
Fmt f;
Error *p;
+ erroring++;
fmtstrinit(&f);
fmtprint(&f, "%L: ", line);
fmtvprint(&f, fmt, arg);
fmtprint(&f, "\n");
+ erroring--;
if(nerr >= merr) {
if(merr == 0)
@@ -1122,7 +1124,14 @@ Sconv(Fmt *fp)
return 0;
}
- if(s->pkg != localpkg || longsymnames || (fp->flags & FmtLong)) {
+ if(s->pkg && s->pkg != localpkg || longsymnames || (fp->flags & FmtLong)) {
+ // This one is for the user. If the package name
+ // was used by multiple packages, give the full
+ // import path to disambiguate.
+ if(erroring && pkglookup(s->pkg->name, nil)->npkg > 1) {
+ fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name);
+ return 0;
+ }
fmtprint(fp, "%s.%s", s->pkg->name, s->name);
return 0;
}
@@ -3131,8 +3140,9 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
NodeList *l, *args, *in, *out;
Type *tpad;
int isddd;
+ Val v;
- if(0 && debug['r'])
+ if(debug['r'])
print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
rcvr, method, newnam);
@@ -3174,17 +3184,38 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
args = list(args, l->n->left);
isddd = l->n->left->isddd;
}
+
+ // generate nil pointer check for better error
+ if(isptr[rcvr->etype] && rcvr->type == getthisx(method->type)->type->type) {
+ // generating wrapper from *T to T.
+ n = nod(OIF, N, N);
+ n->ntest = nod(OEQ, this->left, nodnil());
+ // these strings are already in the reflect tables,
+ // so no space cost to use them here.
+ l = nil;
+ v.ctype = CTSTR;
+ v.u.sval = strlit(rcvr->type->sym->pkg->name); // package name
+ l = list(l, nodlit(v));
+ v.u.sval = strlit(rcvr->type->sym->name); // type name
+ l = list(l, nodlit(v));
+ v.u.sval = strlit(method->sym->name);
+ l = list(l, nodlit(v)); // method name
+ call = nod(OCALL, syslook("panicwrap", 0), N);
+ call->list = l;
+ n->nbody = list1(call);
+ fn->nbody = list(fn->nbody, n);
+ }
// generate call
call = nod(OCALL, adddot(nod(OXDOT, this->left, newname(method->sym))), N);
call->list = args;
call->isddd = isddd;
- fn->nbody = list1(call);
if(method->type->outtuple > 0) {
n = nod(ORETURN, N, N);
- n->list = fn->nbody;
- fn->nbody = list1(n);
+ n->list = list1(call);
+ call = n;
}
+ fn->nbody = list(fn->nbody, call);
if(0 && debug['r'])
dumplist("genwrapper body", fn->nbody);
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 04dc1a507..dfe0f30f7 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -2716,6 +2716,11 @@ typecheckdef(Node *n)
default:
fatal("typecheckdef %O", n->op);
+ case OGOTO:
+ case OLABEL:
+ // not really syms
+ break;
+
case OLITERAL:
if(n->ntype != N) {
typecheck(&n->ntype, Etype);
@@ -2772,7 +2777,7 @@ typecheckdef(Node *n)
if(n->defn == N) {
if(n->etype != 0) // like OPRINTN
break;
- if(nerrors > 0) {
+ if(nsavederrors+nerrors > 0) {
// Can have undefined variables in x := foo
// that make x have an n->ndefn == nil.
// If there are other errors anyway, don't
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
index 540994ddd..d304077c8 100644
--- a/src/cmd/gc/unsafe.c
+++ b/src/cmd/gc/unsafe.c
@@ -92,6 +92,6 @@ ret:
mpmovecfix(val.u.xval, v);
n = nod(OLITERAL, N, N);
n->val = val;
- n->type = types[TINT];
+ n->type = types[TUINTPTR];
return n;
}
diff --git a/src/cmd/gc/unsafe.go b/src/cmd/gc/unsafe.go
index b2a341d39..db27d7425 100644
--- a/src/cmd/gc/unsafe.go
+++ b/src/cmd/gc/unsafe.go
@@ -10,9 +10,11 @@ package PACKAGE
type Pointer uintptr // not really; filled in by compiler
-func Offsetof(any) int
-func Sizeof(any) int
-func Alignof(any) int
+// return types here are ignored; see unsafe.c
+func Offsetof(any) uintptr
+func Sizeof(any) uintptr
+func Alignof(any) uintptr
+
func Typeof(i interface{}) (typ interface{})
func Reflect(i interface{}) (typ interface{}, addr Pointer)
func Unreflect(typ interface{}, addr Pointer) (ret interface{})
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 65a504bff..c9ca9b3b3 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -243,7 +243,16 @@ walkstmt(Node **np)
break;
case OPROC:
- walkexpr(&n->left, &n->ninit);
+ switch(n->left->op) {
+ case OPRINT:
+ case OPRINTN:
+ walkexprlist(n->left->list, &n->ninit);
+ n->left = walkprint(n->left, &n->ninit, 1);
+ break;
+ default:
+ walkexpr(&n->left, &n->ninit);
+ break;
+ }
break;
case ORETURN:
@@ -485,9 +494,9 @@ walkexpr(Node **np, NodeList **init)
if(n->left->op == OCLOSURE) {
walkcallclosure(n, init);
t = n->left->type;
- } else
- walkexpr(&n->left, init);
+ }
+ walkexpr(&n->left, init);
walkexprlist(n->list, init);
ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
diff --git a/src/cmd/godefs/Makefile b/src/cmd/godefs/Makefile
index b5c76fb0f..77cd26c04 100644
--- a/src/cmd/godefs/Makefile
+++ b/src/cmd/godefs/Makefile
@@ -14,3 +14,6 @@ OFILES=\
HFILES=a.h
include ../../Make.ccmd
+
+test: $(TARG)
+ ./test.sh
diff --git a/src/cmd/godefs/test.sh b/src/cmd/godefs/test.sh
new file mode 100755
index 000000000..c035af8f4
--- /dev/null
+++ b/src/cmd/godefs/test.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+# 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.
+
+eval $(gomake --no-print-directory -f ../../Make.inc go-env)
+
+TMP="testdata_tmp.go"
+TEST="testdata.c"
+GOLDEN="testdata_${GOOS}_${GOARCH}.golden"
+
+case ${GOARCH} in
+"amd64") CCARG="-f-m64";;
+"386") CCARG="-f-m32";;
+*) CCARG="";;
+esac
+
+cleanup() {
+ rm ${TMP}
+}
+
+error() {
+ cleanup
+ echo $1
+ exit 1
+}
+
+if [ ! -e ${GOLDEN} ]; then
+ echo "skipping - no golden defined for this platform"
+ exit
+fi
+
+./godefs -g test ${CCARG} ${TEST} > ${TMP}
+if [ $? != 0 ]; then
+ error "Error: Could not run godefs for ${TEST}"
+fi
+
+diff ${TMP} ${GOLDEN}
+if [ $? != 0 ]; then
+ error "FAIL: godefs for ${TEST} did not match ${GOLDEN}"
+fi
+
+cleanup
+
+echo "PASS"
diff --git a/src/cmd/godefs/testdata.c b/src/cmd/godefs/testdata.c
new file mode 100644
index 000000000..3f459c41b
--- /dev/null
+++ b/src/cmd/godefs/testdata.c
@@ -0,0 +1,41 @@
+// 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.
+
+#include <stdint.h>
+
+// Issue 432 - enum fields in struct can cause misaligned struct fields
+typedef enum {
+ a
+} T1;
+
+struct T2 {
+ uint8_t a;
+ T1 b;
+ T1 c;
+ uint16_t d;
+};
+
+typedef struct T2 T2;
+typedef T2 $T2;
+
+// Issue 1162 - structs with fields named Pad[0-9]+ conflict with field
+// names used by godefs for padding
+struct T3 {
+ uint8_t a;
+ int Pad0;
+};
+
+typedef struct T3 $T3;
+
+// Issue 1466 - forward references to types in stabs debug info were
+// always treated as enums
+struct T4 {};
+
+struct T5 {
+ struct T4 *a;
+};
+
+typedef struct T5 T5;
+typedef struct T4 $T4;
+typedef T5 $T5; \ No newline at end of file
diff --git a/src/cmd/godefs/testdata_darwin_386.golden b/src/cmd/godefs/testdata_darwin_386.golden
new file mode 100644
index 000000000..d929238b0
--- /dev/null
+++ b/src/cmd/godefs/testdata_darwin_386.golden
@@ -0,0 +1,31 @@
+// ./godefs -g test -f-m32 testdata.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+package test
+
+// Constants
+
+// Types
+
+type T2 struct {
+ A uint8;
+ Pad_godefs_0 [3]byte;
+ B uint32;
+ C uint32;
+ D uint16;
+ Pad_godefs_1 [2]byte;
+}
+
+type T3 struct {
+ A uint8;
+ Pad_godefs_0 [3]byte;
+ Pad0 int32;
+}
+
+type T4 struct {
+}
+
+type T5 struct {
+ A *T4;
+}
diff --git a/src/cmd/godefs/testdata_darwin_amd64.golden b/src/cmd/godefs/testdata_darwin_amd64.golden
new file mode 100644
index 000000000..a694f4a73
--- /dev/null
+++ b/src/cmd/godefs/testdata_darwin_amd64.golden
@@ -0,0 +1,31 @@
+// ./godefs -g test -f-m64 testdata.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+package test
+
+// Constants
+
+// Types
+
+type T2 struct {
+ A uint8;
+ Pad_godefs_0 [3]byte;
+ B uint32;
+ C uint32;
+ D uint16;
+ Pad_godefs_1 [2]byte;
+}
+
+type T3 struct {
+ A uint8;
+ Pad_godefs_0 [3]byte;
+ Pad0 int32;
+}
+
+type T4 struct {
+}
+
+type T5 struct {
+ A *T4;
+}
diff --git a/src/cmd/godoc/Makefile b/src/cmd/godoc/Makefile
index c4e0fd9f9..06a18be70 100644
--- a/src/cmd/godoc/Makefile
+++ b/src/cmd/godoc/Makefile
@@ -8,11 +8,13 @@ TARG=godoc
GOFILES=\
codewalk.go\
dirtrees.go\
+ filesystem.go\
format.go\
godoc.go\
index.go\
main.go\
mapping.go\
+ parser.go\
snippet.go\
spec.go\
utils.go\
diff --git a/src/cmd/godoc/codewalk.go b/src/cmd/godoc/codewalk.go
index 24087eb88..50043e2ab 100644
--- a/src/cmd/godoc/codewalk.go
+++ b/src/cmd/godoc/codewalk.go
@@ -17,7 +17,6 @@ import (
"fmt"
"http"
"io"
- "io/ioutil"
"log"
"os"
"regexp"
@@ -42,7 +41,7 @@ func codewalk(w http.ResponseWriter, r *http.Request) {
}
// If directory exists, serve list of code walks.
- dir, err := os.Lstat(abspath)
+ dir, err := fs.Lstat(abspath)
if err == nil && dir.IsDirectory() {
codewalkDir(w, r, relpath, abspath)
return
@@ -75,7 +74,7 @@ func codewalk(w http.ResponseWriter, r *http.Request) {
// A Codewalk represents a single codewalk read from an XML file.
type Codewalk struct {
- Title string "attr"
+ Title string `xml:"attr"`
File []string
Step []*Codestep
}
@@ -84,9 +83,9 @@ type Codewalk struct {
// A Codestep is a single step in a codewalk.
type Codestep struct {
// Filled in from XML
- Src string "attr"
- Title string "attr"
- XML string "innerxml"
+ Src string `xml:"attr"`
+ Title string `xml:"attr"`
+ XML string `xml:"innerxml"`
// Derived from Src; not in XML.
Err os.Error
@@ -114,8 +113,8 @@ func (st *Codestep) String() string {
// loadCodewalk reads a codewalk from the named XML file.
-func loadCodewalk(file string) (*Codewalk, os.Error) {
- f, err := os.Open(file)
+func loadCodewalk(filename string) (*Codewalk, os.Error) {
+ f, err := fs.Open(filename)
if err != nil {
return nil, err
}
@@ -125,7 +124,7 @@ func loadCodewalk(file string) (*Codewalk, os.Error) {
p.Entity = xml.HTMLEntity
err = p.Unmarshal(cw, nil)
if err != nil {
- return nil, &os.PathError{"parsing", file, err}
+ return nil, &os.PathError{"parsing", filename, err}
}
// Compute file list, evaluate line numbers for addresses.
@@ -135,8 +134,8 @@ func loadCodewalk(file string) (*Codewalk, os.Error) {
if i < 0 {
i = len(st.Src)
}
- file := st.Src[0:i]
- data, err := ioutil.ReadFile(absolutePath(file, *goroot))
+ filename := st.Src[0:i]
+ data, err := fs.ReadFile(absolutePath(filename, *goroot))
if err != nil {
st.Err = err
continue
@@ -158,8 +157,8 @@ func loadCodewalk(file string) (*Codewalk, os.Error) {
st.Hi = byteToLine(data, hi-1)
}
st.Data = data
- st.File = file
- m[file] = true
+ st.File = filename
+ m[filename] = true
}
// Make list of files
@@ -169,7 +168,7 @@ func loadCodewalk(file string) (*Codewalk, os.Error) {
cw.File[i] = f
i++
}
- sort.SortStrings(cw.File)
+ sort.Strings(cw.File)
return cw, nil
}
@@ -184,7 +183,7 @@ func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string
Title string
}
- dir, err := ioutil.ReadDir(abspath)
+ dir, err := fs.ReadDir(abspath)
if err != nil {
log.Print(err)
serveError(w, r, relpath, err)
@@ -192,14 +191,15 @@ func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string
}
var v vector.Vector
for _, fi := range dir {
+ name := fi.Name()
if fi.IsDirectory() {
- v.Push(&elem{fi.Name + "/", ""})
- } else if strings.HasSuffix(fi.Name, ".xml") {
- cw, err := loadCodewalk(abspath + "/" + fi.Name)
+ v.Push(&elem{name + "/", ""})
+ } else if strings.HasSuffix(name, ".xml") {
+ cw, err := loadCodewalk(abspath + "/" + name)
if err != nil {
continue
}
- v.Push(&elem{fi.Name[0 : len(fi.Name)-len(".xml")], cw.Title})
+ v.Push(&elem{name[0 : len(name)-len(".xml")], cw.Title})
}
}
@@ -216,7 +216,7 @@ func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string
// the usual godoc HTML wrapper.
func codewalkFileprint(w http.ResponseWriter, r *http.Request, f string) {
abspath := absolutePath(f, *goroot)
- data, err := ioutil.ReadFile(abspath)
+ data, err := fs.ReadFile(abspath)
if err != nil {
log.Print(err)
serveError(w, r, f, err)
diff --git a/src/cmd/godoc/dirtrees.go b/src/cmd/godoc/dirtrees.go
index 97737ca5a..e98e93a46 100644
--- a/src/cmd/godoc/dirtrees.go
+++ b/src/cmd/godoc/dirtrees.go
@@ -11,9 +11,7 @@ import (
"go/doc"
"go/parser"
"go/token"
- "io/ioutil"
"log"
- "os"
"path/filepath"
"strings"
"unicode"
@@ -29,21 +27,24 @@ type Directory struct {
}
-func isGoFile(f *os.FileInfo) bool {
- return f.IsRegular() &&
- !strings.HasPrefix(f.Name, ".") && // ignore .files
- filepath.Ext(f.Name) == ".go"
+func isGoFile(fi FileInfo) bool {
+ name := fi.Name()
+ return fi.IsRegular() &&
+ len(name) > 0 && name[0] != '.' && // ignore .files
+ filepath.Ext(name) == ".go"
}
-func isPkgFile(f *os.FileInfo) bool {
- return isGoFile(f) &&
- !strings.HasSuffix(f.Name, "_test.go") // ignore test files
+func isPkgFile(fi FileInfo) bool {
+ return isGoFile(fi) &&
+ !strings.HasSuffix(fi.Name(), "_test.go") // ignore test files
}
-func isPkgDir(f *os.FileInfo) bool {
- return f.IsDirectory() && len(f.Name) > 0 && f.Name[0] != '_'
+func isPkgDir(fi FileInfo) bool {
+ name := fi.Name()
+ return fi.IsDirectory() && len(name) > 0 &&
+ name[0] != '_' && name[0] != '.' // ignore _files and .files
}
@@ -101,12 +102,12 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
return &Directory{depth, path, name, "", nil}
}
- list, err := ioutil.ReadDir(path)
+ list, err := fs.ReadDir(path)
if err != nil {
// newDirTree is called with a path that should be a package
// directory; errors here should not happen, but if they do,
// we want to know about them
- log.Printf("ioutil.ReadDir(%s): %s", path, err)
+ log.Printf("ReadDir(%s): %s", path, err)
}
// determine number of subdirectories and if there are package files
@@ -123,7 +124,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
// though the directory doesn't contain any real package files - was bug)
if synopses[0] == "" {
// no "optimal" package synopsis yet; continue to collect synopses
- file, err := parser.ParseFile(fset, filepath.Join(path, d.Name), nil,
+ file, err := parser.ParseFile(fset, filepath.Join(path, d.Name()), nil,
parser.ParseComments|parser.PackageClauseOnly)
if err == nil {
hasPkgFiles = true
@@ -156,7 +157,8 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
i := 0
for _, d := range list {
if isPkgDir(d) {
- dd := b.newDirTree(fset, filepath.Join(path, d.Name), d.Name, depth+1)
+ name := d.Name()
+ dd := b.newDirTree(fset, filepath.Join(path, name), name, depth+1)
if dd != nil {
dirs[i] = dd
i++
@@ -195,8 +197,8 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
// (i.e., in this case the tree may contain directories w/o any package files).
//
func newDirectory(root string, pathFilter func(string) bool, maxDepth int) *Directory {
- // The root could be a symbolic link so use os.Stat not os.Lstat.
- d, err := os.Stat(root)
+ // The root could be a symbolic link so use Stat not Lstat.
+ d, err := fs.Stat(root)
// If we fail here, report detailed error messages; otherwise
// is is hard to see why a directory tree was not built.
switch {
@@ -213,7 +215,7 @@ func newDirectory(root string, pathFilter func(string) bool, maxDepth int) *Dire
b := treeBuilder{pathFilter, maxDepth}
// the file set provided is only for local parsing, no position
// information escapes and thus we don't need to save the set
- return b.newDirTree(token.NewFileSet(), root, d.Name, 0)
+ return b.newDirTree(token.NewFileSet(), root, d.Name(), 0)
}
@@ -266,8 +268,8 @@ func (dir *Directory) lookupLocal(name string) *Directory {
// lookup looks for the *Directory for a given path, relative to dir.
func (dir *Directory) lookup(path string) *Directory {
- d := strings.Split(dir.Path, string(filepath.Separator), -1)
- p := strings.Split(path, string(filepath.Separator), -1)
+ d := strings.Split(dir.Path, string(filepath.Separator))
+ p := strings.Split(path, string(filepath.Separator))
i := 0
for i < len(d) {
if i >= len(p) || d[i] != p[i] {
diff --git a/src/cmd/godoc/filesystem.go b/src/cmd/godoc/filesystem.go
new file mode 100644
index 000000000..bf68378d4
--- /dev/null
+++ b/src/cmd/godoc/filesystem.go
@@ -0,0 +1,96 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file defines abstract file system access.
+
+package main
+
+import (
+ "io"
+ "io/ioutil"
+ "os"
+)
+
+
+// The FileInfo interface provides access to file information.
+type FileInfo interface {
+ Name() string
+ Size() int64
+ IsRegular() bool
+ IsDirectory() bool
+}
+
+
+// The FileSystem interface specifies the methods godoc is using
+// to access the file system for which it serves documentation.
+type FileSystem interface {
+ Open(path string) (io.ReadCloser, os.Error)
+ Lstat(path string) (FileInfo, os.Error)
+ Stat(path string) (FileInfo, os.Error)
+ ReadDir(path string) ([]FileInfo, os.Error)
+ ReadFile(path string) ([]byte, os.Error)
+}
+
+
+// ----------------------------------------------------------------------------
+// OS-specific FileSystem implementation
+
+var OS FileSystem = osFS{}
+
+
+// osFI is the OS-specific implementation of FileInfo.
+type osFI struct {
+ *os.FileInfo
+}
+
+
+func (fi osFI) Name() string {
+ return fi.FileInfo.Name
+}
+
+
+func (fi osFI) Size() int64 {
+ if fi.IsDirectory() {
+ return 0
+ }
+ return fi.FileInfo.Size
+}
+
+
+// osFS is the OS-specific implementation of FileSystem
+type osFS struct{}
+
+func (osFS) Open(path string) (io.ReadCloser, os.Error) {
+ return os.Open(path)
+}
+
+
+func (osFS) Lstat(path string) (FileInfo, os.Error) {
+ fi, err := os.Lstat(path)
+ return osFI{fi}, err
+}
+
+
+func (osFS) Stat(path string) (FileInfo, os.Error) {
+ fi, err := os.Stat(path)
+ return osFI{fi}, err
+}
+
+
+func (osFS) ReadDir(path string) ([]FileInfo, os.Error) {
+ l0, err := ioutil.ReadDir(path)
+ if err != nil {
+ return nil, err
+ }
+ l1 := make([]FileInfo, len(l0))
+ for i, e := range l0 {
+ l1[i] = osFI{e}
+ }
+ return l1, nil
+}
+
+
+func (osFS) ReadFile(path string) ([]byte, os.Error) {
+ return ioutil.ReadFile(path)
+}
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index f97c764f9..20ebd3183 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -9,13 +9,12 @@ import (
"flag"
"fmt"
"go/ast"
+ "go/build"
"go/doc"
- "go/parser"
"go/printer"
"go/token"
"http"
"io"
- "io/ioutil"
"log"
"os"
"path"
@@ -71,10 +70,11 @@ var (
maxResults = flag.Int("maxresults", 10000, "maximum number of full text search results shown")
// file system mapping
- fsMap Mapping // user-defined mapping
- fsTree RWValue // *Directory tree of packages, updated with each sync
- pathFilter RWValue // filter used when building fsMap directory trees
- fsModified RWValue // timestamp of last call to invalidateIndex
+ fs FileSystem // the underlying file system
+ fsMap Mapping // user-defined mapping
+ fsTree RWValue // *Directory tree of packages, updated with each sync
+ pathFilter RWValue // filter used when building fsMap directory trees
+ fsModified RWValue // timestamp of last call to invalidateIndex
// http handlers
fileServer http.Handler // default file server
@@ -84,8 +84,16 @@ var (
func initHandlers() {
- fsMap.Init(*pkgPath)
- fileServer = http.FileServer(*goroot, "")
+ paths := filepath.SplitList(*pkgPath)
+ for _, t := range build.Path {
+ if t.Goroot {
+ continue
+ }
+ paths = append(paths, t.SrcDir())
+ }
+ fsMap.Init(paths)
+
+ fileServer = http.FileServer(http.Dir(*goroot))
cmdHandler = httpHandler{"/cmd/", filepath.Join(*goroot, "src", "cmd"), false}
pkgHandler = httpHandler{"/pkg/", filepath.Join(*goroot, "src", "pkg"), true}
}
@@ -147,13 +155,13 @@ func getPathFilter() func(string) bool {
// readDirList reads a file containing a newline-separated list
// of directory paths and returns the list of paths.
func readDirList(filename string) ([]string, os.Error) {
- contents, err := ioutil.ReadFile(filename)
+ contents, err := fs.ReadFile(filename)
if err != nil {
return nil, err
}
// create a sorted list of valid directory names
filter := func(path string) bool {
- d, e := os.Lstat(path)
+ d, e := fs.Lstat(path)
if e != nil && err == nil {
// remember first error and return it from readDirList
// so we have at least some information if things go bad
@@ -161,7 +169,7 @@ func readDirList(filename string) ([]string, os.Error) {
}
return e == nil && isPkgDir(d)
}
- list := canonicalizePaths(strings.Split(string(contents), "\n", -1), filter)
+ list := canonicalizePaths(strings.Split(string(contents), "\n"), filter)
// for each parent path, remove all it's children q
// (requirement for binary search to work when filtering)
i := 0
@@ -598,7 +606,7 @@ func timeFmt(w io.Writer, format string, x ...interface{}) {
// Template formatter for "dir/" format.
func dirslashFmt(w io.Writer, format string, x ...interface{}) {
- if x[0].(*os.FileInfo).IsDirectory() {
+ if x[0].(FileInfo).IsDirectory() {
w.Write([]byte{'/'})
}
}
@@ -642,12 +650,12 @@ func readTemplate(name string) *template.Template {
if *templateDir != "" {
defaultpath := path
path = filepath.Join(*templateDir, name)
- if _, err := os.Stat(path); err != nil {
+ if _, err := fs.Stat(path); err != nil {
log.Print("readTemplate:", err)
path = defaultpath
}
}
- data, err := ioutil.ReadFile(path)
+ data, err := fs.ReadFile(path)
if err != nil {
log.Fatalf("ReadFile %s: %v", path, err)
}
@@ -742,9 +750,9 @@ func extractString(src []byte, rx *regexp.Regexp) (s string) {
func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
// get HTML body contents
- src, err := ioutil.ReadFile(abspath)
+ src, err := fs.ReadFile(abspath)
if err != nil {
- log.Printf("ioutil.ReadFile: %s", err)
+ log.Printf("ReadFile: %s", err)
serveError(w, r, relpath, err)
return
}
@@ -793,9 +801,9 @@ func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) {
}
func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, title string) {
- src, err := ioutil.ReadFile(abspath)
+ src, err := fs.ReadFile(abspath)
if err != nil {
- log.Printf("ioutil.ReadFile: %s", err)
+ log.Printf("ReadFile: %s", err)
serveError(w, r, relpath, err)
return
}
@@ -814,19 +822,13 @@ func serveDirectory(w http.ResponseWriter, r *http.Request, abspath, relpath str
return
}
- list, err := ioutil.ReadDir(abspath)
+ list, err := fs.ReadDir(abspath)
if err != nil {
- log.Printf("ioutil.ReadDir: %s", err)
+ log.Printf("ReadDir: %s", err)
serveError(w, r, relpath, err)
return
}
- for _, d := range list {
- if d.IsDirectory() {
- d.Size = 0
- }
- }
-
contents := applyTemplate(dirlistHTML, "dirlistHTML", list)
servePage(w, "Directory "+relpath, "", "", contents)
}
@@ -864,7 +866,7 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
return
}
- dir, err := os.Lstat(abspath)
+ dir, err := fs.Lstat(abspath)
if err != nil {
log.Print(err)
serveError(w, r, relpath, err)
@@ -942,15 +944,15 @@ type httpHandler struct {
//
func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInfoMode) PageInfo {
// filter function to select the desired .go files
- filter := func(d *os.FileInfo) bool {
+ filter := func(d FileInfo) bool {
// If we are looking at cmd documentation, only accept
// the special fakePkgFile containing the documentation.
- return isPkgFile(d) && (h.isPkg || d.Name == fakePkgFile)
+ return isPkgFile(d) && (h.isPkg || d.Name() == fakePkgFile)
}
// get package ASTs
fset := token.NewFileSet()
- pkgs, err := parser.ParseDir(fset, abspath, filter, parser.ParseComments)
+ pkgs, err := parseDir(fset, abspath, filter)
if err != nil && pkgs == nil {
// only report directory read errors, ignore parse errors
// (may be able to extract partial package information)
diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go
index 5938d0b74..e0c89e794 100644
--- a/src/cmd/godoc/index.go
+++ b/src/cmd/godoc/index.go
@@ -45,7 +45,6 @@ import (
"go/token"
"go/scanner"
"index/suffixarray"
- "io/ioutil"
"os"
"path/filepath"
"regexp"
@@ -624,7 +623,7 @@ func pkgName(filename string) string {
// failed (that is, if the file was not added), it returns file == nil.
func (x *Indexer) addFile(filename string, goFile bool) (file *token.File, ast *ast.File) {
// open file
- f, err := os.Open(filename)
+ f, err := fs.Open(filename)
if err != nil {
return
}
@@ -727,12 +726,12 @@ func isWhitelisted(filename string) bool {
}
-func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool) {
+func (x *Indexer) visitFile(dirname string, f FileInfo, fulltextIndex bool) {
if !f.IsRegular() {
return
}
- filename := filepath.Join(dirname, f.Name)
+ filename := filepath.Join(dirname, f.Name())
goFile := false
switch {
@@ -745,7 +744,7 @@ func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool)
}
goFile = true
- case !fulltextIndex || !isWhitelisted(f.Name):
+ case !fulltextIndex || !isWhitelisted(f.Name()):
return
}
@@ -804,7 +803,7 @@ func NewIndex(dirnames <-chan string, fulltextIndex bool) *Index {
// index all files in the directories given by dirnames
for dirname := range dirnames {
- list, err := ioutil.ReadDir(dirname)
+ list, err := fs.ReadDir(dirname)
if err != nil {
continue // ignore this directory
}
@@ -902,7 +901,7 @@ func isIdentifier(s string) bool {
// identifier, Lookup returns a LookupResult, and a list of alternative
// spellings, if any. If the query syntax is wrong, an error is reported.
func (x *Index) Lookup(query string) (match *LookupResult, alt *AltWords, err os.Error) {
- ss := strings.Split(query, ".", -1)
+ ss := strings.Split(query, ".")
// check query syntax
for _, s := range ss {
@@ -955,7 +954,7 @@ func (list positionList) Swap(i, j int) { list[i], list[j] = list[j], list[
// unique returns the list sorted and with duplicate entries removed
func unique(list []int) []int {
- sort.SortInts(list)
+ sort.Ints(list)
var last int
i := 0
for _, x := range list {
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index 967ea8727..51fcf8dd0 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -31,6 +31,7 @@ import (
"flag"
"fmt"
"go/ast"
+ "go/build"
"http"
_ "http/pprof" // to serve /debug/pprof/*
"io"
@@ -222,6 +223,10 @@ func main() {
flag.Usage = usage
flag.Parse()
+ // Determine file system to use.
+ // TODO(gri) Complete this - for now we only have one.
+ fs = OS
+
// Clean goroot: normalize path separator.
*goroot = filepath.Clean(*goroot)
@@ -328,7 +333,10 @@ func main() {
}
relpath := path
abspath := path
- if !filepath.IsAbs(path) {
+ if t, pkg, err := build.FindTree(path); err == nil {
+ relpath = pkg
+ abspath = filepath.Join(t.SrcDir(), pkg)
+ } else if !filepath.IsAbs(path) {
abspath = absolutePath(path, pkgHandler.fsRoot)
} else {
relpath = relativeURL(path)
diff --git a/src/cmd/godoc/mapping.go b/src/cmd/godoc/mapping.go
index 6ae9032e4..92614e83e 100644
--- a/src/cmd/godoc/mapping.go
+++ b/src/cmd/godoc/mapping.go
@@ -9,7 +9,6 @@ package main
import (
"fmt"
"io"
- "os"
"path"
"path/filepath"
"sort"
@@ -60,10 +59,10 @@ type mapping struct {
}
-// Init initializes the Mapping from a list of paths separated by
-// filepath.ListSeparator. Empty paths are ignored; relative paths
-// are assumed to be relative to the current working directory and
-// converted to absolute paths. For each path of the form:
+// Init initializes the Mapping from a list of paths.
+// Empty paths are ignored; relative paths are assumed to be relative to
+// the current working directory and converted to absolute paths.
+// For each path of the form:
//
// dirname/localname
//
@@ -81,8 +80,8 @@ type mapping struct {
// user -> /home/user
// public -> /home/build/public
//
-func (m *Mapping) Init(paths string) {
- pathlist := canonicalizePaths(filepath.SplitList(paths), nil)
+func (m *Mapping) Init(paths []string) {
+ pathlist := canonicalizePaths(paths, nil)
list := make([]mapping, len(pathlist))
// create mapping list
@@ -121,7 +120,7 @@ func (m *Mapping) PrefixList() []string {
}
// sort the list and remove duplicate entries
- sort.SortStrings(list)
+ sort.Strings(list)
i := 0
prev := ""
for _, path := range list {
@@ -174,7 +173,7 @@ func (m *Mapping) ToAbsolute(spath string) string {
continue // no match
}
abspath := filepath.Join(e.path, tail)
- if _, err := os.Stat(abspath); err == nil {
+ if _, err := fs.Stat(abspath); err == nil {
return abspath
}
}
diff --git a/src/cmd/godoc/parser.go b/src/cmd/godoc/parser.go
new file mode 100644
index 000000000..423db222d
--- /dev/null
+++ b/src/cmd/godoc/parser.go
@@ -0,0 +1,69 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains support functions for parsing .go files.
+// Similar functionality is found in package go/parser but the
+// functions here operate using godoc's file system fs instead
+// of calling the OS's file operations directly.
+
+package main
+
+import (
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "os"
+ "path/filepath"
+)
+
+func parseFiles(fset *token.FileSet, filenames []string) (pkgs map[string]*ast.Package, first os.Error) {
+ pkgs = make(map[string]*ast.Package)
+ for _, filename := range filenames {
+ src, err := fs.ReadFile(filename)
+ if err != nil {
+ if first == nil {
+ first = err
+ }
+ continue
+ }
+
+ file, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
+ if err != nil {
+ if first == nil {
+ first = err
+ }
+ continue
+ }
+
+ name := file.Name.Name
+ pkg, found := pkgs[name]
+ if !found {
+ // TODO(gri) Use NewPackage here; reconsider ParseFiles API.
+ pkg = &ast.Package{name, nil, nil, make(map[string]*ast.File)}
+ pkgs[name] = pkg
+ }
+ pkg.Files[filename] = file
+ }
+ return
+}
+
+
+func parseDir(fset *token.FileSet, path string, filter func(FileInfo) bool) (map[string]*ast.Package, os.Error) {
+ list, err := fs.ReadDir(path)
+ if err != nil {
+ return nil, err
+ }
+
+ filenames := make([]string, len(list))
+ i := 0
+ for _, d := range list {
+ if filter == nil || filter(d) {
+ filenames[i] = filepath.Join(path, d.Name())
+ i++
+ }
+ }
+ filenames = filenames[0:i]
+
+ return parseFiles(fset, filenames)
+}
diff --git a/src/cmd/godoc/utils.go b/src/cmd/godoc/utils.go
index 593b51ce0..e2637ab3d 100644
--- a/src/cmd/godoc/utils.go
+++ b/src/cmd/godoc/utils.go
@@ -44,6 +44,10 @@ func (v *RWValue) get() (interface{}, int64) {
}
+// TODO(gri) For now, using os.Getwd() is ok here since the functionality
+// based on this code is not invoked for the appengine version,
+// but this is fragile. Determine what the right thing to do is,
+// here (possibly have some Getwd-equivalent in FileSystem).
var cwd, _ = os.Getwd() // ignore errors
// canonicalizePaths takes a list of (directory/file) paths and returns
@@ -76,7 +80,7 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {
list = list[0:i]
// sort the list and remove duplicate entries
- sort.SortStrings(list)
+ sort.Strings(list)
i = 0
prev := ""
for _, path := range list {
@@ -95,6 +99,7 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {
// atomically renames that file to the file named by filename.
//
func writeFileAtomically(filename string, data []byte) os.Error {
+ // TODO(gri) this won't work on appengine
f, err := ioutil.TempFile(filepath.Split(filename))
if err != nil {
return err
@@ -155,7 +160,7 @@ func isTextFile(filename string) bool {
// the extension is not known; read an initial chunk
// of the file and check if it looks like text
- f, err := os.Open(filename)
+ f, err := fs.Open(filename)
if err != nil {
return false
}
diff --git a/src/cmd/gofix/Makefile b/src/cmd/gofix/Makefile
index c4127d93e..7ce21e8aa 100644
--- a/src/cmd/gofix/Makefile
+++ b/src/cmd/gofix/Makefile
@@ -6,15 +6,22 @@ include ../../Make.inc
TARG=gofix
GOFILES=\
+ filepath.go\
fix.go\
- netdial.go\
- main.go\
- osopen.go\
httpfinalurl.go\
+ httpfs.go\
+ httpheaders.go\
httpserver.go\
+ main.go\
+ netdial.go\
+ oserrorstring.go\
+ osopen.go\
procattr.go\
reflect.go\
signal.go\
+ sorthelpers.go\
+ sortslice.go\
+ stringssplit.go\
typecheck.go\
include ../../Make.cmd
diff --git a/src/cmd/gofix/filepath.go b/src/cmd/gofix/filepath.go
new file mode 100644
index 000000000..1d0ad6879
--- /dev/null
+++ b/src/cmd/gofix/filepath.go
@@ -0,0 +1,53 @@
+// 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 (
+ "go/ast"
+)
+
+func init() {
+ register(fix{
+ "filepath",
+ filepathFunc,
+ `Adapt code from filepath.[List]SeparatorString to string(filepath.[List]Separator).
+
+http://codereview.appspot.com/4527090
+`,
+ })
+}
+
+func filepathFunc(f *ast.File) (fixed bool) {
+ if !imports(f, "path/filepath") {
+ return
+ }
+
+ walk(f, func(n interface{}) {
+ e, ok := n.(*ast.Expr)
+ if !ok {
+ return
+ }
+
+ var ident string
+ switch {
+ case isPkgDot(*e, "filepath", "SeparatorString"):
+ ident = "filepath.Separator"
+ case isPkgDot(*e, "filepath", "ListSeparatorString"):
+ ident = "filepath.ListSeparator"
+ default:
+ return
+ }
+
+ // string(filepath.[List]Separator)
+ *e = &ast.CallExpr{
+ Fun: ast.NewIdent("string"),
+ Args: []ast.Expr{ast.NewIdent(ident)},
+ }
+
+ fixed = true
+ })
+
+ return
+}
diff --git a/src/cmd/gofix/filepath_test.go b/src/cmd/gofix/filepath_test.go
new file mode 100644
index 000000000..d170c3ae3
--- /dev/null
+++ b/src/cmd/gofix/filepath_test.go
@@ -0,0 +1,33 @@
+// 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
+
+func init() {
+ addTestCases(filepathTests)
+}
+
+var filepathTests = []testCase{
+ {
+ Name: "filepath.0",
+ In: `package main
+
+import (
+ "path/filepath"
+)
+
+var _ = filepath.SeparatorString
+var _ = filepath.ListSeparatorString
+`,
+ Out: `package main
+
+import (
+ "path/filepath"
+)
+
+var _ = string(filepath.Separator)
+var _ = string(filepath.ListSeparator)
+`,
+ },
+}
diff --git a/src/cmd/gofix/httpfinalurl.go b/src/cmd/gofix/httpfinalurl.go
index 53642b22f..9e6cbf6bc 100644
--- a/src/cmd/gofix/httpfinalurl.go
+++ b/src/cmd/gofix/httpfinalurl.go
@@ -13,7 +13,7 @@ var httpFinalURLFix = fix{
httpfinalurl,
`Adapt http Get calls to not have a finalURL result parameter.
- http://codereview.appspot.com/4535056/
+http://codereview.appspot.com/4535056/
`,
}
diff --git a/src/cmd/gofix/httpfs.go b/src/cmd/gofix/httpfs.go
new file mode 100644
index 000000000..7f2765680
--- /dev/null
+++ b/src/cmd/gofix/httpfs.go
@@ -0,0 +1,63 @@
+// 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 (
+ "go/ast"
+ "go/token"
+)
+
+var httpFileSystemFix = fix{
+ "httpfs",
+ httpfs,
+ `Adapt http FileServer to take a FileSystem.
+
+http://codereview.appspot.com/4629047 http FileSystem interface
+`,
+}
+
+func init() {
+ register(httpFileSystemFix)
+}
+
+func httpfs(f *ast.File) bool {
+ if !imports(f, "http") {
+ return false
+ }
+
+ fixed := false
+ walk(f, func(n interface{}) {
+ call, ok := n.(*ast.CallExpr)
+ if !ok || !isPkgDot(call.Fun, "http", "FileServer") {
+ return
+ }
+ if len(call.Args) != 2 {
+ return
+ }
+ dir, prefix := call.Args[0], call.Args[1]
+ call.Args = []ast.Expr{&ast.CallExpr{
+ Fun: &ast.SelectorExpr{ast.NewIdent("http"), ast.NewIdent("Dir")},
+ Args: []ast.Expr{dir},
+ }}
+ wrapInStripHandler := true
+ if prefixLit, ok := prefix.(*ast.BasicLit); ok {
+ if prefixLit.Kind == token.STRING && (prefixLit.Value == `"/"` || prefixLit.Value == `""`) {
+ wrapInStripHandler = false
+ }
+ }
+ if wrapInStripHandler {
+ call.Fun.(*ast.SelectorExpr).Sel = ast.NewIdent("StripPrefix")
+ call.Args = []ast.Expr{
+ prefix,
+ &ast.CallExpr{
+ Fun: &ast.SelectorExpr{ast.NewIdent("http"), ast.NewIdent("FileServer")},
+ Args: call.Args,
+ },
+ }
+ }
+ fixed = true
+ })
+ return fixed
+}
diff --git a/src/cmd/gofix/httpfs_test.go b/src/cmd/gofix/httpfs_test.go
new file mode 100644
index 000000000..d1804e93b
--- /dev/null
+++ b/src/cmd/gofix/httpfs_test.go
@@ -0,0 +1,47 @@
+// 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
+
+func init() {
+ addTestCases(httpFileSystemTests)
+}
+
+var httpFileSystemTests = []testCase{
+ {
+ Name: "httpfs.0",
+ In: `package httpfs
+
+import (
+ "http"
+)
+
+func f() {
+ _ = http.FileServer("/var/www/foo", "/")
+ _ = http.FileServer("/var/www/foo", "")
+ _ = http.FileServer("/var/www/foo/bar", "/bar")
+ s := "/foo"
+ _ = http.FileServer(s, "/")
+ prefix := "/p"
+ _ = http.FileServer(s, prefix)
+}
+`,
+ Out: `package httpfs
+
+import (
+ "http"
+)
+
+func f() {
+ _ = http.FileServer(http.Dir("/var/www/foo"))
+ _ = http.FileServer(http.Dir("/var/www/foo"))
+ _ = http.StripPrefix("/bar", http.FileServer(http.Dir("/var/www/foo/bar")))
+ s := "/foo"
+ _ = http.FileServer(http.Dir(s))
+ prefix := "/p"
+ _ = http.StripPrefix(prefix, http.FileServer(http.Dir(s)))
+}
+`,
+ },
+}
diff --git a/src/cmd/gofix/httpheaders.go b/src/cmd/gofix/httpheaders.go
new file mode 100644
index 000000000..8a9080e8e
--- /dev/null
+++ b/src/cmd/gofix/httpheaders.go
@@ -0,0 +1,66 @@
+// 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 (
+ "go/ast"
+)
+
+var httpHeadersFix = fix{
+ "httpheaders",
+ httpheaders,
+ `Rename http Referer, UserAgent, Cookie, SetCookie, which are now methods.
+
+http://codereview.appspot.com/4620049/
+`,
+}
+
+func init() {
+ register(httpHeadersFix)
+}
+
+func httpheaders(f *ast.File) bool {
+ if !imports(f, "http") {
+ return false
+ }
+
+ called := make(map[ast.Node]bool)
+ walk(f, func(ni interface{}) {
+ switch n := ni.(type) {
+ case *ast.CallExpr:
+ called[n.Fun] = true
+ }
+ })
+
+ fixed := false
+ typeof := typecheck(headerTypeConfig, f)
+ walk(f, func(ni interface{}) {
+ switch n := ni.(type) {
+ case *ast.SelectorExpr:
+ if called[n] {
+ break
+ }
+ if t := typeof[n.X]; t != "*http.Request" && t != "*http.Response" {
+ break
+ }
+ switch n.Sel.Name {
+ case "Referer", "UserAgent":
+ n.Sel.Name += "()"
+ fixed = true
+ case "Cookie":
+ n.Sel.Name = "Cookies()"
+ fixed = true
+ }
+ }
+ })
+ return fixed
+}
+
+var headerTypeConfig = &TypeConfig{
+ Type: map[string]*Type{
+ "*http.Request": &Type{},
+ "*http.Response": &Type{},
+ },
+}
diff --git a/src/cmd/gofix/httpheaders_test.go b/src/cmd/gofix/httpheaders_test.go
new file mode 100644
index 000000000..cc82b5893
--- /dev/null
+++ b/src/cmd/gofix/httpheaders_test.go
@@ -0,0 +1,73 @@
+// 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
+
+func init() {
+ addTestCases(httpHeadersTests)
+}
+
+var httpHeadersTests = []testCase{
+ {
+ Name: "httpheaders.0",
+ In: `package headertest
+
+import (
+ "http"
+)
+
+type Other struct {
+ Referer string
+ UserAgent string
+ Cookie []*http.Cookie
+}
+
+func f(req *http.Request, res *http.Response, other *Other) {
+ _ = req.Referer
+ _ = req.UserAgent
+ _ = req.Cookie
+
+ _ = res.Cookie
+
+ _ = other.Referer
+ _ = other.UserAgent
+ _ = other.Cookie
+
+ _ = req.Referer()
+ _ = req.UserAgent()
+ _ = req.Cookies()
+ _ = res.Cookies()
+}
+`,
+ Out: `package headertest
+
+import (
+ "http"
+)
+
+type Other struct {
+ Referer string
+ UserAgent string
+ Cookie []*http.Cookie
+}
+
+func f(req *http.Request, res *http.Response, other *Other) {
+ _ = req.Referer()
+ _ = req.UserAgent()
+ _ = req.Cookies()
+
+ _ = res.Cookies()
+
+ _ = other.Referer
+ _ = other.UserAgent
+ _ = other.Cookie
+
+ _ = req.Referer()
+ _ = req.UserAgent()
+ _ = req.Cookies()
+ _ = res.Cookies()
+}
+`,
+ },
+}
diff --git a/src/cmd/gofix/main.go b/src/cmd/gofix/main.go
index 1b091c18a..e7e7013c5 100644
--- a/src/cmd/gofix/main.go
+++ b/src/cmd/gofix/main.go
@@ -53,7 +53,7 @@ func main() {
if *allowedRewrites != "" {
allowed = make(map[string]bool)
- for _, f := range strings.Split(*allowedRewrites, ",", -1) {
+ for _, f := range strings.Split(*allowedRewrites, ",") {
allowed[f] = true
}
}
@@ -123,7 +123,7 @@ func processFile(filename string, useStdin bool) os.Error {
newFile := file
fixed := false
for _, fix := range fixes {
- if allowed != nil && !allowed[fix.desc] {
+ if allowed != nil && !allowed[fix.name] {
continue
}
if fix.f(newFile) {
diff --git a/src/cmd/gofix/oserrorstring.go b/src/cmd/gofix/oserrorstring.go
new file mode 100644
index 000000000..5e61ab952
--- /dev/null
+++ b/src/cmd/gofix/oserrorstring.go
@@ -0,0 +1,75 @@
+// 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 (
+ "go/ast"
+)
+
+var oserrorstringFix = fix{
+ "oserrorstring",
+ oserrorstring,
+ `Replace os.ErrorString() conversions with calls to os.NewError().
+
+http://codereview.appspot.com/4607052
+`,
+}
+
+func init() {
+ register(oserrorstringFix)
+}
+
+func oserrorstring(f *ast.File) bool {
+ if !imports(f, "os") {
+ return false
+ }
+
+ fixed := false
+ walk(f, func(n interface{}) {
+ // The conversion os.ErrorString(x) looks like a call
+ // of os.ErrorString with one argument.
+ if call := callExpr(n, "os", "ErrorString"); call != nil {
+ // os.ErrorString(args) -> os.NewError(args)
+ call.Fun.(*ast.SelectorExpr).Sel.Name = "NewError"
+ // os.ErrorString(args) -> os.NewError(args)
+ call.Fun.(*ast.SelectorExpr).Sel.Name = "NewError"
+ fixed = true
+ return
+ }
+
+ // Remove os.Error type from variable declarations initialized
+ // with an os.NewError.
+ // (An *ast.ValueSpec may also be used in a const declaration
+ // but those won't be initialized with a call to os.NewError.)
+ if spec, ok := n.(*ast.ValueSpec); ok &&
+ len(spec.Names) == 1 &&
+ isPkgDot(spec.Type, "os", "Error") &&
+ len(spec.Values) == 1 &&
+ callExpr(spec.Values[0], "os", "NewError") != nil {
+ // var name os.Error = os.NewError(x) ->
+ // var name = os.NewError(x)
+ spec.Type = nil
+ fixed = true
+ return
+ }
+
+ // Other occurrences of os.ErrorString are not fixed
+ // but they are rare.
+
+ })
+ return fixed
+}
+
+
+// callExpr returns the call expression if x is a call to pkg.name with one argument;
+// otherwise it returns nil.
+func callExpr(x interface{}, pkg, name string) *ast.CallExpr {
+ if call, ok := x.(*ast.CallExpr); ok &&
+ len(call.Args) == 1 &&
+ isPkgDot(call.Fun, pkg, name) {
+ return call
+ }
+ return nil
+}
diff --git a/src/cmd/gofix/oserrorstring_test.go b/src/cmd/gofix/oserrorstring_test.go
new file mode 100644
index 000000000..070d9222b
--- /dev/null
+++ b/src/cmd/gofix/oserrorstring_test.go
@@ -0,0 +1,57 @@
+// 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
+
+func init() {
+ addTestCases(oserrorstringTests)
+}
+
+var oserrorstringTests = []testCase{
+ {
+ Name: "oserrorstring.0",
+ In: `package main
+
+import "os"
+
+var _ = os.ErrorString("foo")
+var _ os.Error = os.ErrorString("bar1")
+var _ os.Error = os.NewError("bar2")
+var _ os.Error = MyError("bal") // don't rewrite this one
+
+var (
+ _ = os.ErrorString("foo")
+ _ os.Error = os.ErrorString("bar1")
+ _ os.Error = os.NewError("bar2")
+ _ os.Error = MyError("bal") // don't rewrite this one
+)
+
+func _() (err os.Error) {
+ err = os.ErrorString("foo")
+ return os.ErrorString("foo")
+}
+`,
+ Out: `package main
+
+import "os"
+
+var _ = os.NewError("foo")
+var _ = os.NewError("bar1")
+var _ = os.NewError("bar2")
+var _ os.Error = MyError("bal") // don't rewrite this one
+
+var (
+ _ = os.NewError("foo")
+ _ = os.NewError("bar1")
+ _ = os.NewError("bar2")
+ _ os.Error = MyError("bal") // don't rewrite this one
+)
+
+func _() (err os.Error) {
+ err = os.NewError("foo")
+ return os.NewError("foo")
+}
+`,
+ },
+}
diff --git a/src/cmd/gofix/osopen.go b/src/cmd/gofix/osopen.go
index 8eb5d0655..56147c390 100644
--- a/src/cmd/gofix/osopen.go
+++ b/src/cmd/gofix/osopen.go
@@ -13,7 +13,7 @@ var osopenFix = fix{
osopen,
`Adapt os.Open calls to new, easier API and rename O_CREAT O_CREATE.
- http://codereview.appspot.com/4357052
+http://codereview.appspot.com/4357052
`,
}
diff --git a/src/cmd/gofix/sorthelpers.go b/src/cmd/gofix/sorthelpers.go
new file mode 100644
index 000000000..4d0bee6e7
--- /dev/null
+++ b/src/cmd/gofix/sorthelpers.go
@@ -0,0 +1,47 @@
+// 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 (
+ "go/ast"
+)
+
+func init() {
+ register(fix{
+ "sorthelpers",
+ sorthelpers,
+ `Adapt code from sort.Sort[Ints|Float64s|Strings] to sort.[Ints|Float64s|Strings].
+`,
+ })
+}
+
+
+func sorthelpers(f *ast.File) (fixed bool) {
+ if !imports(f, "sort") {
+ return
+ }
+
+ walk(f, func(n interface{}) {
+ s, ok := n.(*ast.SelectorExpr)
+ if !ok || !isTopName(s.X, "sort") {
+ return
+ }
+
+ switch s.Sel.String() {
+ case "SortFloat64s":
+ s.Sel.Name = "Float64s"
+ case "SortInts":
+ s.Sel.Name = "Ints"
+ case "SortStrings":
+ s.Sel.Name = "Strings"
+ default:
+ return
+ }
+
+ fixed = true
+ })
+
+ return
+}
diff --git a/src/cmd/gofix/sorthelpers_test.go b/src/cmd/gofix/sorthelpers_test.go
new file mode 100644
index 000000000..6c37858fd
--- /dev/null
+++ b/src/cmd/gofix/sorthelpers_test.go
@@ -0,0 +1,45 @@
+// 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
+
+func init() {
+ addTestCases(sorthelpersTests)
+}
+
+var sorthelpersTests = []testCase{
+ {
+ Name: "sortslice.0",
+ In: `package main
+
+import (
+ "sort"
+)
+
+func main() {
+ var s []string
+ sort.SortStrings(s)
+ var i []ints
+ sort.SortInts(i)
+ var f []float64
+ sort.SortFloat64s(f)
+}
+`,
+ Out: `package main
+
+import (
+ "sort"
+)
+
+func main() {
+ var s []string
+ sort.Strings(s)
+ var i []ints
+ sort.Ints(i)
+ var f []float64
+ sort.Float64s(f)
+}
+`,
+ },
+}
diff --git a/src/cmd/gofix/sortslice.go b/src/cmd/gofix/sortslice.go
new file mode 100644
index 000000000..b9c108b5a
--- /dev/null
+++ b/src/cmd/gofix/sortslice.go
@@ -0,0 +1,50 @@
+// 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 (
+ "go/ast"
+)
+
+func init() {
+ register(fix{
+ "sortslice",
+ sortslice,
+ `Adapt code from sort.[Float64|Int|String]Array to sort.[Float64|Int|String]Slice.
+
+http://codereview.appspot.com/4602054
+http://codereview.appspot.com/4639041
+`,
+ })
+}
+
+
+func sortslice(f *ast.File) (fixed bool) {
+ if !imports(f, "sort") {
+ return
+ }
+
+ walk(f, func(n interface{}) {
+ s, ok := n.(*ast.SelectorExpr)
+ if !ok || !isTopName(s.X, "sort") {
+ return
+ }
+
+ switch s.Sel.String() {
+ case "Float64Array":
+ s.Sel.Name = "Float64Slice"
+ case "IntArray":
+ s.Sel.Name = "IntSlice"
+ case "StringArray":
+ s.Sel.Name = "StringSlice"
+ default:
+ return
+ }
+
+ fixed = true
+ })
+
+ return
+}
diff --git a/src/cmd/gofix/sortslice_test.go b/src/cmd/gofix/sortslice_test.go
new file mode 100644
index 000000000..404feb26f
--- /dev/null
+++ b/src/cmd/gofix/sortslice_test.go
@@ -0,0 +1,35 @@
+// 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
+
+func init() {
+ addTestCases(sortsliceTests)
+}
+
+var sortsliceTests = []testCase{
+ {
+ Name: "sortslice.0",
+ In: `package main
+
+import (
+ "sort"
+)
+
+var _ = sort.Float64Array
+var _ = sort.IntArray
+var _ = sort.StringArray
+`,
+ Out: `package main
+
+import (
+ "sort"
+)
+
+var _ = sort.Float64Slice
+var _ = sort.IntSlice
+var _ = sort.StringSlice
+`,
+ },
+}
diff --git a/src/cmd/gofix/stringssplit.go b/src/cmd/gofix/stringssplit.go
new file mode 100644
index 000000000..4a1fe93d3
--- /dev/null
+++ b/src/cmd/gofix/stringssplit.go
@@ -0,0 +1,71 @@
+// 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 (
+ "go/ast"
+ "go/token"
+)
+
+var stringssplitFix = fix{
+ "stringssplit",
+ stringssplit,
+ `Restore strings.Split to its original meaning and add strings.SplitN. Bytes too.
+
+http://codereview.appspot.com/4661051
+`,
+}
+
+func init() {
+ register(stringssplitFix)
+}
+
+func stringssplit(f *ast.File) bool {
+ if !imports(f, "bytes") && !imports(f, "strings") {
+ return false
+ }
+
+ fixed := false
+ walk(f, func(n interface{}) {
+ call, ok := n.(*ast.CallExpr)
+ // func Split(s, sep string, n int) []string
+ // func SplitAfter(s, sep string, n int) []string
+ if !ok || len(call.Args) != 3 {
+ return
+ }
+ // Is this our function?
+ switch {
+ case isPkgDot(call.Fun, "bytes", "Split"):
+ case isPkgDot(call.Fun, "bytes", "SplitAfter"):
+ case isPkgDot(call.Fun, "strings", "Split"):
+ case isPkgDot(call.Fun, "strings", "SplitAfter"):
+ default:
+ return
+ }
+
+ sel := call.Fun.(*ast.SelectorExpr)
+ args := call.Args
+ fixed = true // We're committed.
+
+ // Is the last argument -1? If so, drop the arg.
+ // (Actually we just look for a negative integer literal.)
+ // Otherwise, Split->SplitN and keep the arg.
+ final := args[2]
+ if unary, ok := final.(*ast.UnaryExpr); ok && unary.Op == token.SUB {
+ if lit, ok := unary.X.(*ast.BasicLit); ok {
+ // Is it an integer? If so, it's a negative integer and that's what we're after.
+ if lit.Kind == token.INT {
+ // drop the last arg.
+ call.Args = args[0:2]
+ return
+ }
+ }
+ }
+
+ // If not, rename and keep the argument list.
+ sel.Sel.Name += "N"
+ })
+ return fixed
+}
diff --git a/src/cmd/gofix/stringssplit_test.go b/src/cmd/gofix/stringssplit_test.go
new file mode 100644
index 000000000..b925722af
--- /dev/null
+++ b/src/cmd/gofix/stringssplit_test.go
@@ -0,0 +1,51 @@
+// 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
+
+func init() {
+ addTestCases(stringssplitTests)
+}
+
+var stringssplitTests = []testCase{
+ {
+ Name: "stringssplit.0",
+ In: `package main
+
+import (
+ "bytes"
+ "strings"
+)
+
+func f() {
+ bytes.Split(a, b, c)
+ bytes.Split(a, b, -1)
+ bytes.SplitAfter(a, b, c)
+ bytes.SplitAfter(a, b, -1)
+ strings.Split(a, b, c)
+ strings.Split(a, b, -1)
+ strings.SplitAfter(a, b, c)
+ strings.SplitAfter(a, b, -1)
+}
+`,
+ Out: `package main
+
+import (
+ "bytes"
+ "strings"
+)
+
+func f() {
+ bytes.SplitN(a, b, c)
+ bytes.Split(a, b)
+ bytes.SplitAfterN(a, b, c)
+ bytes.SplitAfter(a, b)
+ strings.SplitN(a, b, c)
+ strings.Split(a, b)
+ strings.SplitAfterN(a, b, c)
+ strings.SplitAfter(a, b)
+}
+`,
+ },
+}
diff --git a/src/cmd/gofix/testdata/reflect.decoder.go.out b/src/cmd/gofix/testdata/reflect.decoder.go.out
index 170eedb05..ece88ecbe 100644
--- a/src/cmd/gofix/testdata/reflect.decoder.go.out
+++ b/src/cmd/gofix/testdata/reflect.decoder.go.out
@@ -44,7 +44,7 @@ func NewDecoder(r io.Reader) *Decoder {
func (dec *Decoder) recvType(id typeId) {
// Have we already seen this type? That's an error
if id < firstUserId || dec.wireType[id] != nil {
- dec.err = os.ErrorString("gob: duplicate type received")
+ dec.err = os.NewError("gob: duplicate type received")
return
}
@@ -143,7 +143,7 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
// will be absorbed by recvMessage.)
if dec.buf.Len() > 0 {
if !isInterface {
- dec.err = os.ErrorString("extra data in buffer")
+ dec.err = os.NewError("extra data in buffer")
break
}
dec.nextUint()
@@ -165,7 +165,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
// If e represents a value as opposed to a pointer, the answer won't
// get back to the caller. Make sure it's a pointer.
if value.Type().Kind() != reflect.Ptr {
- dec.err = os.ErrorString("gob: attempt to decode into a non-pointer")
+ dec.err = os.NewError("gob: attempt to decode into a non-pointer")
return dec.err
}
return dec.DecodeValue(value)
diff --git a/src/cmd/gofix/testdata/reflect.encoder.go.out b/src/cmd/gofix/testdata/reflect.encoder.go.out
index 781ef6504..925d39301 100644
--- a/src/cmd/gofix/testdata/reflect.encoder.go.out
+++ b/src/cmd/gofix/testdata/reflect.encoder.go.out
@@ -50,7 +50,7 @@ func (enc *Encoder) popWriter() {
}
func (enc *Encoder) badType(rt reflect.Type) {
- enc.setError(os.ErrorString("gob: can't encode type " + rt.String()))
+ enc.setError(os.NewError("gob: can't encode type " + rt.String()))
}
func (enc *Encoder) setError(err os.Error) {
diff --git a/src/cmd/gofix/testdata/reflect.export.go.out b/src/cmd/gofix/testdata/reflect.export.go.out
index 486a812e2..460edb40b 100644
--- a/src/cmd/gofix/testdata/reflect.export.go.out
+++ b/src/cmd/gofix/testdata/reflect.export.go.out
@@ -343,20 +343,20 @@ func (exp *Exporter) Sync(timeout int64) os.Error {
func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
chanType := reflect.TypeOf(chT)
if chanType.Kind() != reflect.Chan {
- return reflect.Value{}, os.ErrorString("not a channel")
+ return reflect.Value{}, os.NewError("not a channel")
}
if dir != Send && dir != Recv {
- return reflect.Value{}, os.ErrorString("unknown channel direction")
+ return reflect.Value{}, os.NewError("unknown channel direction")
}
switch chanType.ChanDir() {
case reflect.BothDir:
case reflect.SendDir:
if dir != Recv {
- return reflect.Value{}, os.ErrorString("to import/export with Send, must provide <-chan")
+ return reflect.Value{}, os.NewError("to import/export with Send, must provide <-chan")
}
case reflect.RecvDir:
if dir != Send {
- return reflect.Value{}, os.ErrorString("to import/export with Recv, must provide chan<-")
+ return reflect.Value{}, os.NewError("to import/export with Recv, must provide chan<-")
}
}
return reflect.ValueOf(chT), nil
@@ -376,7 +376,7 @@ func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
defer exp.mu.Unlock()
_, present := exp.names[name]
if present {
- return os.ErrorString("channel name already being exported:" + name)
+ return os.NewError("channel name already being exported:" + name)
}
exp.names[name] = &chanDir{ch, dir}
return nil
@@ -393,7 +393,7 @@ func (exp *Exporter) Hangup(name string) os.Error {
// TODO drop all instances of channel from client sets
exp.mu.Unlock()
if !ok {
- return os.ErrorString("netchan export: hangup: no such channel: " + name)
+ return os.NewError("netchan export: hangup: no such channel: " + name)
}
chDir.ch.Close()
return nil
diff --git a/src/cmd/gofix/testdata/reflect.print.go.out b/src/cmd/gofix/testdata/reflect.print.go.out
index 079948cca..10379bd20 100644
--- a/src/cmd/gofix/testdata/reflect.print.go.out
+++ b/src/cmd/gofix/testdata/reflect.print.go.out
@@ -185,7 +185,7 @@ func Sprintf(format string, a ...interface{}) string {
// Errorf formats according to a format specifier and returns the string
// converted to an os.ErrorString, which satisfies the os.Error interface.
func Errorf(format string, a ...interface{}) os.Error {
- return os.ErrorString(Sprintf(format, a...))
+ return os.NewError(Sprintf(format, a...))
}
// These routines do not take a format string
diff --git a/src/cmd/gofix/testdata/reflect.read.go.out b/src/cmd/gofix/testdata/reflect.read.go.out
index 554b2a61b..a6b126744 100644
--- a/src/cmd/gofix/testdata/reflect.read.go.out
+++ b/src/cmd/gofix/testdata/reflect.read.go.out
@@ -244,7 +244,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
switch v := val; v.Kind() {
default:
- return os.ErrorString("unknown type " + v.Type().String())
+ return os.NewError("unknown type " + v.Type().String())
case reflect.Slice:
typ := v.Type()
@@ -483,7 +483,7 @@ Loop:
case reflect.Invalid:
// Probably a comment, handled below
default:
- return os.ErrorString("cannot happen: unknown type " + t.Type().String())
+ return os.NewError("cannot happen: unknown type " + t.Type().String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if !getInt64() {
return err
diff --git a/src/cmd/gofix/testdata/reflect.scan.go.out b/src/cmd/gofix/testdata/reflect.scan.go.out
index 42bc52c92..2b07115e9 100644
--- a/src/cmd/gofix/testdata/reflect.scan.go.out
+++ b/src/cmd/gofix/testdata/reflect.scan.go.out
@@ -167,7 +167,7 @@ type ssave struct {
// satisfies io.Reader. It will never be called when used as
// intended, so there is no need to make it actually work.
func (s *ss) Read(buf []byte) (n int, err os.Error) {
- return 0, os.ErrorString("ScanState's Read should not be called. Use ReadRune")
+ return 0, os.NewError("ScanState's Read should not be called. Use ReadRune")
}
func (s *ss) ReadRune() (rune int, size int, err os.Error) {
@@ -240,7 +240,7 @@ func (s *ss) error(err os.Error) {
}
func (s *ss) errorString(err string) {
- panic(scanError{os.ErrorString(err)})
+ panic(scanError{os.NewError(err)})
}
func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.Error) {
@@ -426,8 +426,8 @@ func (s *ss) typeError(field interface{}, expected string) {
s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String())
}
-var complexError = os.ErrorString("syntax error scanning complex number")
-var boolError = os.ErrorString("syntax error scanning boolean")
+var complexError = os.NewError("syntax error scanning complex number")
+var boolError = os.NewError("syntax error scanning boolean")
// consume reads the next rune in the input and reports whether it is in the ok string.
// If accept is true, it puts the character into the input token.
diff --git a/src/cmd/gofix/testdata/reflect.template.go.in b/src/cmd/gofix/testdata/reflect.template.go.in
index ba06de4e3..1f5a8128f 100644
--- a/src/cmd/gofix/testdata/reflect.template.go.in
+++ b/src/cmd/gofix/testdata/reflect.template.go.in
@@ -444,7 +444,7 @@ func (t *Template) newVariable(words []string) *variableElement {
bar := strings.IndexRune(lastWord, '|')
if bar >= 0 {
words[len(words)-1] = lastWord[0:bar]
- formatters = strings.Split(lastWord[bar+1:], "|", -1)
+ formatters = strings.Split(lastWord[bar+1:], "|")
}
// We could remember the function address here and avoid the lookup later,
@@ -705,7 +705,7 @@ func (t *Template) findVar(st *state, s string) reflect.Value {
if s == "@" {
return indirectPtr(data, numStars)
}
- for _, elem := range strings.Split(s, ".", -1) {
+ for _, elem := range strings.Split(s, ".") {
// Look up field; data must be a struct or map.
data = t.lookup(st, data, elem)
if data == nil {
diff --git a/src/cmd/gofix/testdata/reflect.template.go.out b/src/cmd/gofix/testdata/reflect.template.go.out
index c36288455..f2f56ef3c 100644
--- a/src/cmd/gofix/testdata/reflect.template.go.out
+++ b/src/cmd/gofix/testdata/reflect.template.go.out
@@ -444,7 +444,7 @@ func (t *Template) newVariable(words []string) *variableElement {
bar := strings.IndexRune(lastWord, '|')
if bar >= 0 {
words[len(words)-1] = lastWord[0:bar]
- formatters = strings.Split(lastWord[bar+1:], "|", -1)
+ formatters = strings.Split(lastWord[bar+1:], "|")
}
// We could remember the function address here and avoid the lookup later,
@@ -705,7 +705,7 @@ func (t *Template) findVar(st *state, s string) reflect.Value {
if s == "@" {
return indirectPtr(data, numStars)
}
- for _, elem := range strings.Split(s, ".", -1) {
+ for _, elem := range strings.Split(s, ".") {
// Look up field; data must be a struct or map.
data = t.lookup(st, data, elem)
if !data.IsValid() {
diff --git a/src/cmd/gofix/testdata/reflect.type.go.out b/src/cmd/gofix/testdata/reflect.type.go.out
index a39b074fe..9cd78296d 100644
--- a/src/cmd/gofix/testdata/reflect.type.go.out
+++ b/src/cmd/gofix/testdata/reflect.type.go.out
@@ -67,7 +67,7 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) {
ut.base = pt.Elem()
if ut.base == slowpoke { // ut.base lapped slowpoke
// recursive pointer type.
- return nil, os.ErrorString("can't represent recursive pointer type " + ut.base.String())
+ return nil, os.NewError("can't represent recursive pointer type " + ut.base.String())
}
if ut.indir%2 == 0 {
slowpoke = slowpoke.Elem()
@@ -524,7 +524,7 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.
return st, nil
default:
- return nil, os.ErrorString("gob NewTypeObject can't handle type: " + rt.String())
+ return nil, os.NewError("gob NewTypeObject can't handle type: " + rt.String())
}
return nil, nil
}
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index a72530307..70700554b 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -20,8 +20,8 @@ func runTest(t *testing.T, dirname, in, out, flags string) {
// process flags
*simplifyAST = false
*rewriteRule = ""
- for _, flag := range strings.Split(flags, " ", -1) {
- elts := strings.Split(flag, "=", 2)
+ for _, flag := range strings.Split(flags, " ") {
+ elts := strings.SplitN(flag, "=", 2)
name := elts[0]
value := ""
if len(elts) == 2 {
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index 4c24282f3..f7f1fe824 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -22,7 +22,7 @@ func initRewrite() {
rewrite = nil // disable any previous rewrite
return
}
- f := strings.Split(*rewriteRule, "->", -1)
+ f := strings.Split(*rewriteRule, "->")
if len(f) != 2 {
fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n")
os.Exit(2)
diff --git a/src/cmd/goinstall/Makefile b/src/cmd/goinstall/Makefile
index 202797cd5..f61354f39 100644
--- a/src/cmd/goinstall/Makefile
+++ b/src/cmd/goinstall/Makefile
@@ -9,22 +9,5 @@ GOFILES=\
download.go\
main.go\
make.go\
- parse.go\
- path.go\
- syslist.go\
-
-CLEANFILES+=syslist.go
include ../../Make.cmd
-
-syslist.go:
- echo '// Generated automatically by make.' >$@
- echo 'package main' >>$@
- echo 'const goosList = "$(GOOS_LIST)"' >>$@
- echo 'const goarchList = "$(GOARCH_LIST)"' >>$@
-
-test:
- gotest
-
-testshort:
- gotest -test.short
diff --git a/src/cmd/goinstall/doc.go b/src/cmd/goinstall/doc.go
index 13c37d0a2..a5df7b3bd 100644
--- a/src/cmd/goinstall/doc.go
+++ b/src/cmd/goinstall/doc.go
@@ -5,7 +5,8 @@
/*
Goinstall is an experiment in automatic package installation.
It installs packages, possibly downloading them from the internet.
-It maintains a list of public Go packages at http://godashboard.appspot.com/package.
+It maintains a list of public Go packages at
+http://godashboard.appspot.com/package.
Usage:
goinstall [flags] importpath...
@@ -15,7 +16,9 @@ Flags and default settings:
-a=false install all previously installed packages
-clean=false clean the package directory before installing
-dashboard=true tally public packages on godashboard.appspot.com
+ -install=true build and install the package and its dependencies
-log=true log installed packages to $GOROOT/goinstall.log for use by -a
+ -nuke=false remove the target object and clean before installing
-u=false update already-downloaded packages
-v=false verbose operation
@@ -39,9 +42,22 @@ Another common idiom is to use
to update, recompile, and reinstall all goinstalled packages.
The source code for a package with import path foo/bar is expected
-to be in the directory $GOROOT/src/pkg/foo/bar/. If the import
-path refers to a code hosting site, goinstall will download the code
-if necessary. The recognized code hosting sites are:
+to be in the directory $GOROOT/src/pkg/foo/bar/ or $GOPATH/src/foo/bar/.
+See "The GOPATH Environment Variable" for more about GOPATH.
+
+By default, goinstall prints output only when it encounters an error.
+The -v flag causes goinstall to print information about packages
+being considered and installed.
+
+Goinstall ignores Makefiles.
+
+
+Remote Repositories
+
+If a package import path refers to a remote repository, goinstall will
+download the code if necessary.
+
+Goinstall recognizes packages from a few common code hosting sites:
BitBucket (Mercurial)
@@ -61,7 +77,7 @@ if necessary. The recognized code hosting sites are:
import "project.googlecode.com/svn/trunk"
import "project.googlecode.com/svn/trunk/sub/directory"
- Launchpad
+ Launchpad (Bazaar)
import "launchpad.net/project"
import "launchpad.net/project/series"
@@ -70,7 +86,6 @@ if necessary. The recognized code hosting sites are:
import "launchpad.net/~user/project/branch"
import "launchpad.net/~user/project/branch/sub/directory"
-
If the destination directory (e.g., $GOROOT/src/pkg/bitbucket.org/user/project)
already exists and contains an appropriate checkout, goinstall will not
attempt to fetch updates. The -u flag changes this behavior,
@@ -82,23 +97,42 @@ named "release". If there is one, it uses that version of the code.
Otherwise it uses the default version selected by the version control
system, typically HEAD for git, tip for Mercurial.
-After a successful download and installation of a publicly accessible
-remote package, goinstall reports the installation to godashboard.appspot.com,
-which increments a count associated with the package and the time
-of its most recent installation. This mechanism powers the package list
-at http://godashboard.appspot.com/package, allowing Go programmers
-to learn about popular packages that might be worth looking at.
+After a successful download and installation of one of these import paths,
+goinstall reports the installation to godashboard.appspot.com, which
+increments a count associated with the package and the time of its most
+recent installation. This mechanism powers the package list at
+http://godashboard.appspot.com/package, allowing Go programmers to learn about
+popular packages that might be worth looking at.
The -dashboard=false flag disables this reporting.
-By default, goinstall prints output only when it encounters an error.
-The -v flag causes goinstall to print information about packages
-being considered and installed.
+For code hosted on other servers, goinstall recognizes the general form
+
+ repository.vcs/path
+
+as denoting the given repository, with or without the .vcs suffix, using
+the named version control system, and then the path inside that repository.
+The supported version control systems are:
+
+ Bazaar .bzr
+ Git .git
+ Mercurial .hg
+ Subversion .svn
+
+For example,
+
+ import "example.org/user/foo.hg"
+
+denotes the root directory of the Mercurial repository at example.org/user/foo
+or foo.hg, and
+
+ import "example.org/repo.git/foo/bar"
+
+denotes the foo/bar directory of the Git repository at example.com/repo or
+repo.git.
-Goinstall does not attempt to be a replacement for make.
-Instead, it invokes "make install" after locating the package sources.
-For local packages without a Makefile and all remote packages,
-goinstall creates and uses a temporary Makefile constructed from
-the import path and the list of Go files in the package.
+When a version control system supports multiple protocols, goinstall tries each
+in turn.
+For example, for Git it tries git://, then https://, then http://.
The GOPATH Environment Variable
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go
index 2edf85efd..da892a69d 100644
--- a/src/cmd/goinstall/download.go
+++ b/src/cmd/goinstall/download.go
@@ -7,6 +7,8 @@
package main
import (
+ "exec"
+ "fmt"
"http"
"os"
"path/filepath"
@@ -31,74 +33,10 @@ func maybeReportToDashboard(path string) {
}
}
-var vcsPatterns = map[string]*regexp.Regexp{
- "googlecode": regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`),
- "github": regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`),
- "bitbucket": regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`),
- "launchpad": regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`),
-}
-
-// isRemote returns true if the provided package path
-// matches one of the supported remote repositories.
-func isRemote(pkg string) bool {
- for _, r := range vcsPatterns {
- if r.MatchString(pkg) {
- return true
- }
- }
- return false
-}
-
-// download checks out or updates pkg from the remote server.
-func download(pkg, srcDir string) os.Error {
- if strings.Contains(pkg, "..") {
- return os.ErrorString("invalid path (contains ..)")
- }
- if m := vcsPatterns["bitbucket"].FindStringSubmatch(pkg); m != nil {
- if err := vcsCheckout(&hg, srcDir, m[1], "http://"+m[1], m[1]); err != nil {
- return err
- }
- return nil
- }
- if m := vcsPatterns["googlecode"].FindStringSubmatch(pkg); m != nil {
- var v *vcs
- switch m[2] {
- case "hg":
- v = &hg
- case "svn":
- v = &svn
- default:
- // regexp only allows hg, svn to get through
- panic("missing case in download: " + pkg)
- }
- if err := vcsCheckout(v, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
- return err
- }
- return nil
- }
- if m := vcsPatterns["github"].FindStringSubmatch(pkg); m != nil {
- if strings.HasSuffix(m[1], ".git") {
- return os.ErrorString("repository " + pkg + " should not have .git suffix")
- }
- if err := vcsCheckout(&git, srcDir, m[1], "http://"+m[1]+".git", m[1]); err != nil {
- return err
- }
- return nil
- }
- if m := vcsPatterns["launchpad"].FindStringSubmatch(pkg); m != nil {
- // Either lp.net/<project>[/<series>[/<path>]]
- // or lp.net/~<user or team>/<project>/<branch>[/<path>]
- if err := vcsCheckout(&bzr, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
- return err
- }
- return nil
- }
- return os.ErrorString("unknown repository: " + pkg)
-}
-
// a vcs represents a version control system
// like Mercurial, Git, or Subversion.
type vcs struct {
+ name string
cmd string
metadir string
checkout string
@@ -110,9 +48,20 @@ type vcs struct {
log string
logLimitFlag string
logReleaseFlag string
+ check string
+ protocols []string
+ suffix string
+ defaultHosts []host
+}
+
+type host struct {
+ pattern *regexp.Regexp
+ protocol string
+ suffix string
}
var hg = vcs{
+ name: "Mercurial",
cmd: "hg",
metadir: ".hg",
checkout: "checkout",
@@ -123,9 +72,17 @@ var hg = vcs{
log: "log",
logLimitFlag: "-l1",
logReleaseFlag: "-rrelease",
+ check: "identify",
+ protocols: []string{"https", "http"},
+ suffix: ".hg",
+ defaultHosts: []host{
+ {regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/hg)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
+ {regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ""},
+ },
}
var git = vcs{
+ name: "Git",
cmd: "git",
metadir: ".git",
checkout: "checkout",
@@ -136,9 +93,16 @@ var git = vcs{
log: "show-ref",
logLimitFlag: "",
logReleaseFlag: "release",
+ check: "ls-remote",
+ protocols: []string{"git", "https", "http"},
+ suffix: ".git",
+ defaultHosts: []host{
+ {regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ".git"},
+ },
}
var svn = vcs{
+ name: "Subversion",
cmd: "svn",
metadir: ".svn",
checkout: "checkout",
@@ -148,9 +112,16 @@ var svn = vcs{
log: "log",
logLimitFlag: "-l1",
logReleaseFlag: "release",
+ check: "info",
+ protocols: []string{"https", "http", "svn"},
+ suffix: ".svn",
+ defaultHosts: []host{
+ {regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/svn)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
+ },
}
var bzr = vcs{
+ name: "Bazaar",
cmd: "bzr",
metadir: ".bzr",
checkout: "update",
@@ -162,6 +133,116 @@ var bzr = vcs{
log: "log",
logLimitFlag: "-l1",
logReleaseFlag: "-rrelease",
+ check: "info",
+ protocols: []string{"https", "http", "bzr"},
+ suffix: ".bzr",
+ defaultHosts: []host{
+ {regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`), "https", ""},
+ },
+}
+
+var vcsList = []*vcs{&git, &hg, &bzr, &svn}
+
+type vcsMatch struct {
+ *vcs
+ prefix, repo string
+}
+
+// findHostedRepo checks whether pkg is located at one of
+// the supported code hosting sites and, if so, returns a match.
+func findHostedRepo(pkg string) (*vcsMatch, os.Error) {
+ for _, v := range vcsList {
+ for _, host := range v.defaultHosts {
+ if hm := host.pattern.FindStringSubmatch(pkg); hm != nil {
+ if host.suffix != "" && strings.HasSuffix(hm[1], host.suffix) {
+ return nil, os.NewError("repository " + pkg + " should not have " + v.suffix + " suffix")
+ }
+ repo := host.protocol + "://" + hm[1] + host.suffix
+ return &vcsMatch{v, hm[1], repo}, nil
+ }
+ }
+ }
+ return nil, nil
+}
+
+// findAnyRepo looks for a vcs suffix in pkg (.git, etc) and returns a match.
+func findAnyRepo(pkg string) (*vcsMatch, os.Error) {
+ for _, v := range vcsList {
+ i := strings.Index(pkg+"/", v.suffix+"/")
+ if i < 0 {
+ continue
+ }
+ if !strings.Contains(pkg[:i], "/") {
+ continue // don't match vcs suffix in the host name
+ }
+ if m := v.find(pkg[:i]); m != nil {
+ return m, nil
+ }
+ return nil, fmt.Errorf("couldn't find %s repository", v.name)
+ }
+ return nil, nil
+}
+
+func (v *vcs) find(pkg string) *vcsMatch {
+ for _, proto := range v.protocols {
+ for _, suffix := range []string{"", v.suffix} {
+ repo := proto + "://" + pkg + suffix
+ out, err := exec.Command(v.cmd, v.check, repo).CombinedOutput()
+ if err == nil {
+ printf("find %s: found %s\n", pkg, repo)
+ return &vcsMatch{v, pkg + v.suffix, repo}
+ }
+ printf("find %s: %s %s %s: %v\n%s\n", pkg, v.cmd, v.check, repo, err, out)
+ }
+ }
+ return nil
+}
+
+// isRemote returns true if the first part of the package name looks like a
+// hostname - i.e. contains at least one '.' and the last part is at least 2
+// characters.
+func isRemote(pkg string) bool {
+ parts := strings.SplitN(pkg, "/", 2)
+ if len(parts) != 2 {
+ return false
+ }
+ parts = strings.Split(parts[0], ".")
+ if len(parts) < 2 || len(parts[len(parts)-1]) < 2 {
+ return false
+ }
+ return true
+}
+
+// download checks out or updates pkg from the remote server.
+func download(pkg, srcDir string) (dashReport bool, err os.Error) {
+ if strings.Contains(pkg, "..") {
+ err = os.NewError("invalid path (contains ..)")
+ return
+ }
+ m, err := findHostedRepo(pkg)
+ if err != nil {
+ return
+ }
+ if m != nil {
+ dashReport = true // only report public code hosting sites
+ } else {
+ m, err = findAnyRepo(pkg)
+ if err != nil {
+ return
+ }
+ }
+ if m == nil {
+ err = os.NewError("cannot download: " + pkg)
+ return
+ }
+ installed, err := m.checkoutRepo(srcDir, m.prefix, m.repo)
+ if err != nil {
+ return
+ }
+ if !installed {
+ dashReport = false
+ }
+ return
}
// Try to detect if a "release" tag exists. If it does, update
@@ -180,47 +261,46 @@ func (v *vcs) updateRepo(dst string) os.Error {
return nil
}
-// vcsCheckout checks out repo into dst using vcs.
+// checkoutRepo checks out repo into dst using vcs.
// It tries to check out (or update, if the dst already
// exists and -u was specified on the command line)
// the repository at tag/branch "release". If there is no
// such tag or branch, it falls back to the repository tip.
-func vcsCheckout(vcs *vcs, srcDir, pkgprefix, repo, dashpath string) os.Error {
+func (vcs *vcs) checkoutRepo(srcDir, pkgprefix, repo string) (installed bool, err os.Error) {
dst := filepath.Join(srcDir, filepath.FromSlash(pkgprefix))
dir, err := os.Stat(filepath.Join(dst, vcs.metadir))
if err == nil && !dir.IsDirectory() {
- return os.ErrorString("not a directory: " + dst)
+ err = os.NewError("not a directory: " + dst)
+ return
}
if err != nil {
parent, _ := filepath.Split(dst)
- if err := os.MkdirAll(parent, 0777); err != nil {
- return err
+ if err = os.MkdirAll(parent, 0777); err != nil {
+ return
}
- if err := run(string(filepath.Separator), nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
- return err
+ if err = run(string(filepath.Separator), nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
+ return
}
- if err := vcs.updateRepo(dst); err != nil {
- return err
+ if err = vcs.updateRepo(dst); err != nil {
+ return
}
- // success on first installation - report
- maybeReportToDashboard(dashpath)
+ installed = true
} else if *update {
// Retrieve new revisions from the remote branch, if the VCS
// supports this operation independently (e.g. svn doesn't)
if vcs.pull != "" {
if vcs.pullForceFlag != "" {
- if err := run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
- return err
+ if err = run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
+ return
}
- } else if err := run(dst, nil, vcs.cmd, vcs.pull); err != nil {
- return err
+ } else if err = run(dst, nil, vcs.cmd, vcs.pull); err != nil {
+ return
}
}
-
// Update to release or latest revision
- if err := vcs.updateRepo(dst); err != nil {
- return err
+ if err = vcs.updateRepo(dst); err != nil {
+ return
}
}
- return nil
+ return
}
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index 721e719d2..5cdf0f18e 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Experimental Go package installer; see doc.go.
-
package main
import (
@@ -11,6 +9,7 @@ import (
"exec"
"flag"
"fmt"
+ "go/build"
"go/token"
"io/ioutil"
"os"
@@ -39,7 +38,10 @@ var (
reportToDashboard = flag.Bool("dashboard", true, "report public packages at "+dashboardURL)
logPkgs = flag.Bool("log", true, "log installed packages to $GOROOT/goinstall.log for use by -a")
update = flag.Bool("u", false, "update already-downloaded packages")
+ doInstall = flag.Bool("install", true, "build and install")
clean = flag.Bool("clean", false, "clean the package directory before installing")
+ nuke = flag.Bool("nuke", false, "clean the package directory and target before installing")
+ useMake = flag.Bool("make", true, "use make to build and install")
verbose = flag.Bool("v", false, "verbose")
)
@@ -56,7 +58,7 @@ func logf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, format, args...)
}
-func vlogf(format string, args ...interface{}) {
+func printf(format string, args ...interface{}) {
if *verbose {
logf(format, args...)
}
@@ -160,66 +162,96 @@ func install(pkg, parent string) {
fmt.Fprintf(os.Stderr, "\t%s\n", pkg)
os.Exit(2)
}
- visit[pkg] = visiting
parents[pkg] = parent
-
- vlogf("%s: visit\n", pkg)
+ visit[pkg] = visiting
+ defer func() {
+ visit[pkg] = done
+ }()
// Check whether package is local or remote.
// If remote, download or update it.
- proot, pkg, err := findPackageRoot(pkg)
+ tree, pkg, err := build.FindTree(pkg)
// Don't build the standard library.
- if err == nil && proot.goroot && isStandardPath(pkg) {
+ if err == nil && tree.Goroot && isStandardPath(pkg) {
if parent == "" {
errorf("%s: can not goinstall the standard library\n", pkg)
} else {
- vlogf("%s: skipping standard library\n", pkg)
+ printf("%s: skipping standard library\n", pkg)
}
- visit[pkg] = done
return
}
// Download remote packages if not found or forced with -u flag.
remote := isRemote(pkg)
- if remote && (err == ErrPackageNotFound || (err == nil && *update)) {
- vlogf("%s: download\n", pkg)
- err = download(pkg, proot.srcDir())
+ dashReport := false
+ if remote && (err == build.ErrNotFound || (err == nil && *update)) {
+ printf("%s: download\n", pkg)
+ dashReport, err = download(pkg, tree.SrcDir())
}
if err != nil {
errorf("%s: %v\n", pkg, err)
- visit[pkg] = done
return
}
- dir := filepath.Join(proot.srcDir(), pkg)
+ dir := filepath.Join(tree.SrcDir(), pkg)
// Install prerequisites.
- dirInfo, err := scanDir(dir, parent == "")
+ dirInfo, err := build.ScanDir(dir, parent == "")
if err != nil {
errorf("%s: %v\n", pkg, err)
- visit[pkg] = done
return
}
- if len(dirInfo.goFiles) == 0 {
+ if len(dirInfo.GoFiles)+len(dirInfo.CgoFiles) == 0 {
errorf("%s: package has no files\n", pkg)
- visit[pkg] = done
return
}
- for _, p := range dirInfo.imports {
+ for _, p := range dirInfo.Imports {
if p != "C" {
install(p, pkg)
}
}
+ if errors {
+ return
+ }
// Install this package.
- if !errors {
- isCmd := dirInfo.pkgName == "main"
- if err := domake(dir, pkg, proot, isCmd); err != nil {
- errorf("installing: %v\n", err)
- } else if remote && *logPkgs {
- // mark package as installed in $GOROOT/goinstall.log
- logPackage(pkg)
+ if *useMake {
+ err := domake(dir, pkg, tree, dirInfo.IsCommand())
+ if err != nil {
+ errorf("%s: install: %v\n", pkg, err)
+ return
+ }
+ } else {
+ script, err := build.Build(tree, pkg, dirInfo)
+ if err != nil {
+ errorf("%s: install: %v\n", pkg, err)
+ return
+ }
+ if *nuke {
+ printf("%s: nuke\n", pkg)
+ script.Nuke()
+ } else if *clean {
+ printf("%s: clean\n", pkg)
+ script.Clean()
}
+ if *doInstall {
+ if script.Stale() {
+ printf("%s: install\n", pkg)
+ if err := script.Run(); err != nil {
+ errorf("%s: install: %v\n", pkg, err)
+ return
+ }
+ } else {
+ printf("%s: up-to-date\n", pkg)
+ }
+ }
+ }
+ if dashReport {
+ maybeReportToDashboard(pkg)
+ }
+ if remote {
+ // mark package as installed in $GOROOT/goinstall.log
+ logPackage(pkg)
}
- visit[pkg] = done
+ return
}
@@ -249,7 +281,7 @@ func genRun(dir string, stdin []byte, arg []string, quiet bool) os.Error {
cmd := exec.Command(arg[0], arg[1:]...)
cmd.Stdin = bytes.NewBuffer(stdin)
cmd.Dir = dir
- vlogf("%s: %s %s\n", dir, cmd.Path, strings.Join(arg[1:], " "))
+ printf("%s: %s %s\n", dir, cmd.Path, strings.Join(arg[1:], " "))
out, err := cmd.CombinedOutput()
if err != nil {
if !quiet || *verbose {
@@ -260,7 +292,7 @@ func genRun(dir string, stdin []byte, arg []string, quiet bool) os.Error {
os.Stderr.Write(out)
fmt.Fprintf(os.Stderr, "--- %s\n", err)
}
- return os.ErrorString("running " + arg[0] + ": " + err.String())
+ return os.NewError("running " + arg[0] + ": " + err.String())
}
return nil
}
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
index 0c44481d7..0fd9b02a8 100644
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -8,21 +8,25 @@ package main
import (
"bytes"
+ "go/build"
"os"
"path/filepath"
+ "strings"
"template"
)
// domake builds the package in dir.
// domake generates a standard Makefile and passes it
// to make on standard input.
-func domake(dir, pkg string, root *pkgroot, isCmd bool) (err os.Error) {
- makefile, err := makeMakefile(dir, pkg, root, isCmd)
+func domake(dir, pkg string, tree *build.Tree, isCmd bool) (err os.Error) {
+ makefile, err := makeMakefile(dir, pkg, tree, isCmd)
if err != nil {
return err
}
cmd := []string{"bash", "gomake", "-f-"}
- if *clean {
+ if *nuke {
+ cmd = append(cmd, "nuke")
+ } else if *clean {
cmd = append(cmd, "clean")
}
cmd = append(cmd, "install")
@@ -32,46 +36,46 @@ func domake(dir, pkg string, root *pkgroot, isCmd bool) (err os.Error) {
// makeMakefile computes the standard Makefile for the directory dir
// installing as package pkg. It includes all *.go files in the directory
// except those in package main and those ending in _test.go.
-func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error) {
+func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Error) {
if !safeName(pkg) {
- return nil, os.ErrorString("unsafe name: " + pkg)
+ return nil, os.NewError("unsafe name: " + pkg)
}
targ := pkg
- targDir := root.pkgDir()
+ targDir := tree.PkgDir()
if isCmd {
// use the last part of the package name for targ
_, targ = filepath.Split(pkg)
- targDir = root.binDir()
+ targDir = tree.BinDir()
}
- dirInfo, err := scanDir(dir, isCmd)
+ dirInfo, err := build.ScanDir(dir, isCmd)
if err != nil {
return nil, err
}
- cgoFiles := dirInfo.cgoFiles
+ cgoFiles := dirInfo.CgoFiles
isCgo := make(map[string]bool, len(cgoFiles))
for _, file := range cgoFiles {
if !safeName(file) {
- return nil, os.ErrorString("bad name: " + file)
+ return nil, os.NewError("bad name: " + file)
}
isCgo[file] = true
}
- goFiles := make([]string, 0, len(dirInfo.goFiles))
- for _, file := range dirInfo.goFiles {
+ goFiles := make([]string, 0, len(dirInfo.GoFiles))
+ for _, file := range dirInfo.GoFiles {
if !safeName(file) {
- return nil, os.ErrorString("unsafe name: " + file)
+ return nil, os.NewError("unsafe name: " + file)
}
if !isCgo[file] {
goFiles = append(goFiles, file)
}
}
- oFiles := make([]string, 0, len(dirInfo.cFiles)+len(dirInfo.sFiles))
- cgoOFiles := make([]string, 0, len(dirInfo.cFiles))
- for _, file := range dirInfo.cFiles {
+ oFiles := make([]string, 0, len(dirInfo.CFiles)+len(dirInfo.SFiles))
+ cgoOFiles := make([]string, 0, len(dirInfo.CFiles))
+ for _, file := range dirInfo.CFiles {
if !safeName(file) {
- return nil, os.ErrorString("unsafe name: " + file)
+ return nil, os.NewError("unsafe name: " + file)
}
// When cgo is in use, C files are compiled with gcc,
// otherwise they're compiled with gc.
@@ -82,13 +86,18 @@ func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error)
}
}
- for _, file := range dirInfo.sFiles {
+ for _, file := range dirInfo.SFiles {
if !safeName(file) {
- return nil, os.ErrorString("unsafe name: " + file)
+ return nil, os.NewError("unsafe name: " + file)
}
oFiles = append(oFiles, file[:len(file)-2]+".$O")
}
+ var imports []string
+ for _, t := range build.Path {
+ imports = append(imports, t.PkgDir())
+ }
+
var buf bytes.Buffer
md := makedata{targ, targDir, "pkg", goFiles, oFiles, cgoFiles, cgoOFiles, imports}
if isCmd {
@@ -106,6 +115,9 @@ func safeName(s string) bool {
if s == "" {
return false
}
+ if strings.Contains(s, "..") {
+ return false
+ }
for i := 0; i < len(s); i++ {
if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
return false
@@ -134,28 +146,28 @@ TARGDIR={TargDir}
{.section GoFiles}
GOFILES=\
-{.repeated section GoFiles}
+{.repeated section @}
{@}\
{.end}
{.end}
{.section OFiles}
OFILES=\
-{.repeated section OFiles}
+{.repeated section @}
{@}\
{.end}
{.end}
{.section CgoFiles}
CGOFILES=\
-{.repeated section CgoFiles}
+{.repeated section @}
{@}\
{.end}
{.end}
{.section CgoOFiles}
CGO_OFILES=\
-{.repeated section CgoOFiles}
+{.repeated section @}
{@}\
{.end}
diff --git a/src/cmd/goinstall/parse.go b/src/cmd/goinstall/parse.go
deleted file mode 100644
index a4bb761f2..000000000
--- a/src/cmd/goinstall/parse.go
+++ /dev/null
@@ -1,172 +0,0 @@
-// 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.
-
-// Wrappers for Go parser.
-
-package main
-
-import (
- "go/ast"
- "go/parser"
- "log"
- "os"
- "path/filepath"
- "strconv"
- "strings"
- "runtime"
-)
-
-
-type dirInfo struct {
- goFiles []string // .go files within dir (including cgoFiles)
- cgoFiles []string // .go files that import "C"
- cFiles []string // .c files within dir
- sFiles []string // .s files within dir
- imports []string // All packages imported by goFiles
- pkgName string // Name of package within dir
-}
-
-// scanDir returns a structure with details about the Go content found
-// in the given directory. The list of files will NOT contain the
-// following entries:
-//
-// - Files in package main (unless allowMain is true)
-// - Files ending in _test.go
-// - Files starting with _ (temporary)
-// - Files containing .cgo in their names
-//
-// The imports map keys are package paths imported by listed Go files,
-// and the values are the Go files importing the respective package paths.
-func scanDir(dir string, allowMain bool) (info *dirInfo, err os.Error) {
- f, err := os.Open(dir)
- if err != nil {
- return nil, err
- }
- dirs, err := f.Readdir(-1)
- f.Close()
- if err != nil {
- return nil, err
- }
-
- goFiles := make([]string, 0, len(dirs))
- cgoFiles := make([]string, 0, len(dirs))
- cFiles := make([]string, 0, len(dirs))
- sFiles := make([]string, 0, len(dirs))
- importsm := make(map[string]bool)
- pkgName := ""
- for i := range dirs {
- d := &dirs[i]
- if strings.HasPrefix(d.Name, "_") || strings.Index(d.Name, ".cgo") != -1 {
- continue
- }
- if !goodOSArch(d.Name) {
- continue
- }
-
- switch filepath.Ext(d.Name) {
- case ".go":
- if strings.HasSuffix(d.Name, "_test.go") {
- continue
- }
- case ".c":
- cFiles = append(cFiles, d.Name)
- continue
- case ".s":
- sFiles = append(sFiles, d.Name)
- continue
- default:
- continue
- }
-
- filename := filepath.Join(dir, d.Name)
- pf, err := parser.ParseFile(fset, filename, nil, parser.ImportsOnly)
- if err != nil {
- return nil, err
- }
- s := string(pf.Name.Name)
- if s == "main" && !allowMain {
- continue
- }
- if s == "documentation" {
- continue
- }
- if pkgName == "" {
- pkgName = s
- } else if pkgName != s {
- // Only if all files in the directory are in package main
- // do we return pkgName=="main".
- // A mix of main and another package reverts
- // to the original (allowMain=false) behaviour.
- if s == "main" || pkgName == "main" {
- return scanDir(dir, false)
- }
- return nil, os.ErrorString("multiple package names in " + dir)
- }
- goFiles = append(goFiles, d.Name)
- for _, decl := range pf.Decls {
- for _, spec := range decl.(*ast.GenDecl).Specs {
- quoted := string(spec.(*ast.ImportSpec).Path.Value)
- unquoted, err := strconv.Unquote(quoted)
- if err != nil {
- log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
- }
- importsm[unquoted] = true
- if unquoted == "C" {
- cgoFiles = append(cgoFiles, d.Name)
- }
- }
- }
- }
- imports := make([]string, len(importsm))
- i := 0
- for p := range importsm {
- imports[i] = p
- i++
- }
- return &dirInfo{goFiles, cgoFiles, cFiles, sFiles, imports, pkgName}, nil
-}
-
-// goodOSArch returns false if the filename contains a $GOOS or $GOARCH
-// suffix which does not match the current system.
-// The recognized filename formats are:
-//
-// name_$(GOOS).*
-// name_$(GOARCH).*
-// name_$(GOOS)_$(GOARCH).*
-//
-func goodOSArch(filename string) bool {
- if dot := strings.Index(filename, "."); dot != -1 {
- filename = filename[:dot]
- }
- l := strings.Split(filename, "_", -1)
- n := len(l)
- if n == 0 {
- return true
- }
- if good, known := goodOS[l[n-1]]; known {
- return good
- }
- if good, known := goodArch[l[n-1]]; known {
- if !good || n < 2 {
- return false
- }
- good, known = goodOS[l[n-2]]
- return good || !known
- }
- return true
-}
-
-var goodOS = make(map[string]bool)
-var goodArch = make(map[string]bool)
-
-func init() {
- goodOS = make(map[string]bool)
- goodArch = make(map[string]bool)
- for _, v := range strings.Fields(goosList) {
- goodOS[v] = v == runtime.GOOS
- }
- for _, v := range strings.Fields(goarchList) {
- goodArch[v] = v == runtime.GOARCH
- }
-}
diff --git a/src/cmd/goinstall/path.go b/src/cmd/goinstall/path.go
deleted file mode 100644
index b8c392931..000000000
--- a/src/cmd/goinstall/path.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// 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 (
- "fmt"
- "log"
- "os"
- "path/filepath"
- "runtime"
- "strings"
-)
-
-var (
- gopath []*pkgroot
- imports []string
- defaultRoot *pkgroot // default root for remote packages
-)
-
-// set up gopath: parse and validate GOROOT and GOPATH variables
-func init() {
- root := runtime.GOROOT()
- p, err := newPkgroot(root)
- if err != nil {
- log.Fatalf("Invalid GOROOT %q: %v", root, err)
- }
- p.goroot = true
- gopath = []*pkgroot{p}
-
- for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
- if p == "" {
- continue
- }
- r, err := newPkgroot(p)
- if err != nil {
- log.Printf("Invalid GOPATH %q: %v", p, err)
- continue
- }
- gopath = append(gopath, r)
- imports = append(imports, r.pkgDir())
-
- // select first GOPATH entry as default
- if defaultRoot == nil {
- defaultRoot = r
- }
- }
-
- // use GOROOT if no valid GOPATH specified
- if defaultRoot == nil {
- defaultRoot = gopath[0]
- }
-}
-
-type pkgroot struct {
- path string
- goroot bool // TODO(adg): remove this once Go tree re-organized
-}
-
-func newPkgroot(p string) (*pkgroot, os.Error) {
- if !filepath.IsAbs(p) {
- return nil, os.NewError("must be absolute")
- }
- ep, err := filepath.EvalSymlinks(p)
- if err != nil {
- return nil, err
- }
- return &pkgroot{path: ep}, nil
-}
-
-func (r *pkgroot) srcDir() string {
- if r.goroot {
- return filepath.Join(r.path, "src", "pkg")
- }
- return filepath.Join(r.path, "src")
-}
-
-func (r *pkgroot) pkgDir() string {
- goos, goarch := runtime.GOOS, runtime.GOARCH
- if e := os.Getenv("GOOS"); e != "" {
- goos = e
- }
- if e := os.Getenv("GOARCH"); e != "" {
- goarch = e
- }
- return filepath.Join(r.path, "pkg", goos+"_"+goarch)
-}
-
-func (r *pkgroot) binDir() string {
- return filepath.Join(r.path, "bin")
-}
-
-func (r *pkgroot) hasSrcDir(name string) bool {
- fi, err := os.Stat(filepath.Join(r.srcDir(), name))
- if err != nil {
- return false
- }
- return fi.IsDirectory()
-}
-
-func (r *pkgroot) hasPkg(name string) bool {
- fi, err := os.Stat(filepath.Join(r.pkgDir(), name+".a"))
- if err != nil {
- return false
- }
- return fi.IsRegular()
- // TODO(adg): check object version is consistent
-}
-
-
-var ErrPackageNotFound = os.NewError("package could not be found locally")
-
-// findPackageRoot takes an import or filesystem path and returns the
-// root where the package source should be and the package import path.
-func findPackageRoot(path string) (root *pkgroot, pkg string, err os.Error) {
- if isLocalPath(path) {
- if path, err = filepath.Abs(path); err != nil {
- return
- }
- for _, r := range gopath {
- rpath := r.srcDir() + string(filepath.Separator)
- if !strings.HasPrefix(path, rpath) {
- continue
- }
- root = r
- pkg = path[len(rpath):]
- return
- }
- err = fmt.Errorf("path %q not inside a GOPATH", path)
- return
- }
- root = defaultRoot
- pkg = path
- for _, r := range gopath {
- if r.hasSrcDir(path) {
- root = r
- return
- }
- }
- err = ErrPackageNotFound
- return
-}
-
-// Is this a local path? /foo ./foo ../foo . ..
-func isLocalPath(s string) bool {
- const sep = string(filepath.Separator)
- return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".."
-}
diff --git a/src/cmd/goinstall/syslist_test.go b/src/cmd/goinstall/syslist_test.go
deleted file mode 100644
index 795cd293a..000000000
--- a/src/cmd/goinstall/syslist_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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 (
- "runtime"
- "testing"
-)
-
-var (
- thisOS = runtime.GOOS
- thisArch = runtime.GOARCH
- otherOS = anotherOS()
- otherArch = anotherArch()
-)
-
-func anotherOS() string {
- if thisOS != "darwin" {
- return "darwin"
- }
- return "linux"
-}
-
-func anotherArch() string {
- if thisArch != "amd64" {
- return "amd64"
- }
- return "386"
-}
-
-type GoodFileTest struct {
- name string
- result bool
-}
-
-var tests = []GoodFileTest{
- {"file.go", true},
- {"file.c", true},
- {"file_foo.go", true},
- {"file_" + thisArch + ".go", true},
- {"file_" + otherArch + ".go", false},
- {"file_" + thisOS + ".go", true},
- {"file_" + otherOS + ".go", false},
- {"file_" + thisOS + "_" + thisArch + ".go", true},
- {"file_" + otherOS + "_" + thisArch + ".go", false},
- {"file_" + thisOS + "_" + otherArch + ".go", false},
- {"file_" + otherOS + "_" + otherArch + ".go", false},
- {"file_foo_" + thisArch + ".go", true},
- {"file_foo_" + otherArch + ".go", false},
- {"file_" + thisOS + ".c", true},
- {"file_" + otherOS + ".c", false},
-}
-
-func TestGoodOSArch(t *testing.T) {
- for _, test := range tests {
- if goodOSArch(test.name) != test.result {
- t.Fatalf("goodOSArch(%q) != %v", test.name, test.result)
- }
- }
-}
diff --git a/src/cmd/gopack/Makefile b/src/cmd/gopack/Makefile
index 859809562..91a8ac2df 100644
--- a/src/cmd/gopack/Makefile
+++ b/src/cmd/gopack/Makefile
@@ -9,7 +9,4 @@ TARG=gopack
OFILES=\
ar.$O\
-LIB=\
- ../../../lib/libmach.a\
-
include ../../Make.ccmd
diff --git a/src/cmd/gotest/doc.go b/src/cmd/gotest/doc.go
index 9dba390c1..5be06f817 100644
--- a/src/cmd/gotest/doc.go
+++ b/src/cmd/gotest/doc.go
@@ -53,7 +53,9 @@ The resulting test binary, called (for amd64) 6.out, has several flags.
Usage:
6.out [-test.v] [-test.run pattern] [-test.bench pattern] \
[-test.cpuprofile=cpu.out] \
- [-test.memprofile=mem.out] [-test.memprofilerate=1]
+ [-test.memprofile=mem.out] [-test.memprofilerate=1] \
+ [-test.timeout=10] [-test.short] \
+ [-test.benchtime=3] [-test.cpu=1,2,3,4]
The -test.v flag causes the tests to be logged as they run. The
-test.run flag causes only those tests whose names match the regular
@@ -93,6 +95,13 @@ The -test.timeout flag sets a timeout for the test in seconds. If the
test runs for longer than that, it will panic, dumping a stack trace
of all existing goroutines.
+The -test.benchtime flag specifies the number of seconds to run each benchmark.
+The default is one second.
+
+The -test.cpu flag specifies a list of GOMAXPROCS values for which
+the tests or benchmarks are executed. The default is the current
+value of GOMAXPROCS.
+
For convenience, each of these -test.X flags of the test binary is
also available as the flag -X in gotest itself. Flags not listed here
are unaffected. For instance, the command
diff --git a/src/cmd/gotest/flag.go b/src/cmd/gotest/flag.go
index 780c78b9c..c3a28f9a3 100644
--- a/src/cmd/gotest/flag.go
+++ b/src/cmd/gotest/flag.go
@@ -23,6 +23,8 @@ var usageMessage = `Usage of %s:
// These flags can be passed with or without a "test." prefix: -v or -test.v.
-bench="": passes -test.bench to test
+ -benchtime=1: passes -test.benchtime to test
+ -cpu="": passes -test.cpu to test
-cpuprofile="": passes -test.cpuprofile to test
-memprofile="": passes -test.memprofile to test
-memprofilerate=0: passes -test.memprofilerate to test
@@ -56,6 +58,8 @@ var flagDefn = []*flagSpec{
// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
&flagSpec{name: "bench", passToTest: true},
+ &flagSpec{name: "benchtime", passToTest: true},
+ &flagSpec{name: "cpu", passToTest: true},
&flagSpec{name: "cpuprofile", passToTest: true},
&flagSpec{name: "memprofile", passToTest: true},
&flagSpec{name: "memprofilerate", passToTest: true},
diff --git a/src/cmd/gotype/gotype.go b/src/cmd/gotype/gotype.go
index b6a23ae5f..501ead443 100644
--- a/src/cmd/gotype/gotype.go
+++ b/src/cmd/gotype/gotype.go
@@ -114,7 +114,7 @@ func parseFiles(fset *token.FileSet, filenames []string) (files map[string]*ast.
}
if file := parse(fset, filename, src); file != nil {
if files[filename] != nil {
- report(os.ErrorString(fmt.Sprintf("%q: duplicate file", filename)))
+ report(os.NewError(fmt.Sprintf("%q: duplicate file", filename)))
continue
}
files[filename] = file
diff --git a/src/cmd/govet/Makefile b/src/cmd/govet/Makefile
index 291b27197..f565b78f5 100644
--- a/src/cmd/govet/Makefile
+++ b/src/cmd/govet/Makefile
@@ -9,3 +9,6 @@ GOFILES=\
govet.go\
include ../../Make.cmd
+
+test testshort: $(TARG)
+ ../../../test/errchk $(TARG) -printfuncs='Warn:1,Warnf:1' govet.go
diff --git a/src/cmd/govet/govet.go b/src/cmd/govet/govet.go
index b811c61a2..5b24d2ff0 100644
--- a/src/cmd/govet/govet.go
+++ b/src/cmd/govet/govet.go
@@ -15,6 +15,7 @@ import (
"go/token"
"os"
"path/filepath"
+ "reflect"
"strconv"
"strings"
"utf8"
@@ -50,7 +51,7 @@ func main() {
flag.Parse()
if *printfuncs != "" {
- for _, name := range strings.Split(*printfuncs, ",", -1) {
+ for _, name := range strings.Split(*printfuncs, ",") {
if len(name) == 0 {
flag.Usage()
}
@@ -59,7 +60,7 @@ func main() {
var err os.Error
skip, err = strconv.Atoi(name[colon+1:])
if err != nil {
- error(`illegal format for "Func:N" argument %q; %s`, name, err)
+ errorf(`illegal format for "Func:N" argument %q; %s`, name, err)
}
name = name[:colon]
}
@@ -93,7 +94,7 @@ func doFile(name string, reader io.Reader) {
fs := token.NewFileSet()
parsedFile, err := parser.ParseFile(fs, name, reader, 0)
if err != nil {
- error("%s: %s", name, err)
+ errorf("%s: %s", name, err)
return
}
file := &File{fs.File(parsedFile.Pos())}
@@ -121,7 +122,7 @@ func walkDir(root string) {
done := make(chan bool)
go func() {
for e := range errors {
- error("walk error: %s", e)
+ errorf("walk error: %s", e)
}
done <- true
}()
@@ -132,7 +133,7 @@ func walkDir(root string) {
// error formats the error to standard error, adding program
// identification and a newline
-func error(format string, args ...interface{}) {
+func errorf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, "govet: "+format+"\n", args...)
setExit(2)
}
@@ -185,15 +186,35 @@ func (f *File) checkFile(name string, file *ast.File) {
// Visit implements the ast.Visitor interface.
func (f *File) Visit(node ast.Node) ast.Visitor {
- // TODO: could return nil for nodes that cannot contain a CallExpr -
- // will shortcut traversal. Worthwhile?
switch n := node.(type) {
case *ast.CallExpr:
f.checkCallExpr(n)
+ case *ast.Field:
+ f.checkFieldTag(n)
}
return f
}
+// checkField checks a struct field tag.
+func (f *File) checkFieldTag(field *ast.Field) {
+ if field.Tag == nil {
+ return
+ }
+
+ tag, err := strconv.Unquote(field.Tag.Value)
+ if err != nil {
+ f.Warnf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
+ return
+ }
+
+ // Check tag for validity by appending
+ // new key:value to end and checking that
+ // the tag parsing code can find it.
+ if reflect.StructTag(tag+` _gofix:"_magic"`).Get("_gofix") != "_magic" {
+ f.Warnf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
+ return
+ }
+}
// checkCallExpr checks a call expression.
func (f *File) checkCallExpr(call *ast.CallExpr) {
@@ -358,19 +379,24 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
}
// This function never executes, but it serves as a simple test for the program.
-// Test with govet -printfuncs="Bad:1,Badf:1,Warn:1,Warnf:1" govet.go
+// Test with make test.
func BadFunctionUsedInTests() {
- fmt.Println() // niladic call
- fmt.Println("%s", "hi") // % in call to Println
- fmt.Printf("%s", "hi", 3) // wrong # percents
- fmt.Printf("%s%%%d", "hi", 3) // right # percents
- fmt.Printf("%.*d", 3, 3) // right # percents, with a *
- fmt.Printf("%.*d", 3, 3, 3) // wrong # percents, with a *
- printf("now is the time", "buddy") // no %s
- Printf("now is the time", "buddy") // no %s
+ fmt.Println() // not an error
+ fmt.Println("%s", "hi") // ERROR "possible formatting directive in Println call"
+ fmt.Printf("%s", "hi", 3) // ERROR "wrong number of args in Printf call"
+ fmt.Printf("%s%%%d", "hi", 3) // correct
+ fmt.Printf("%.*d", 3, 3) // correct
+ fmt.Printf("%.*d", 3, 3, 3) // ERROR "wrong number of args in Printf call"
+ printf("now is the time", "buddy") // ERROR "no formatting directive"
+ Printf("now is the time", "buddy") // ERROR "no formatting directive"
+ Printf("hi") // ok
f := new(File)
- f.Warn(0, "%s", "hello", 3) // % in call to added function
- f.Warnf(0, "%s", "hello", 3) // wrong # %s in call to added function
+ f.Warn(0, "%s", "hello", 3) // ERROR "possible formatting directive in Warn call"
+ f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
+}
+
+type BadTypeUsedInTests struct {
+ X int "hello" // ERROR "struct field tag"
}
// printf is used by the test.
diff --git a/src/cmd/goyacc/goyacc.go b/src/cmd/goyacc/goyacc.go
index 220c99492..543f8b1e8 100644
--- a/src/cmd/goyacc/goyacc.go
+++ b/src/cmd/goyacc/goyacc.go
@@ -2834,7 +2834,7 @@ func others() {
// copy yaccpar
fmt.Fprintf(ftable, "\n//line yaccpar:1\n")
- parts := strings.Split(yaccpar, prefix+"run()", 2)
+ parts := strings.SplitN(yaccpar, prefix+"run()", 2)
fmt.Fprintf(ftable, "%v", parts[0])
ftable.Write(fcode.Bytes())
fmt.Fprintf(ftable, "%v", parts[1])
diff --git a/src/cmd/hgpatch/main.go b/src/cmd/hgpatch/main.go
index 8ee3422e2..4f7aec22b 100644
--- a/src/cmd/hgpatch/main.go
+++ b/src/cmd/hgpatch/main.go
@@ -176,7 +176,7 @@ func main() {
list[i] = f
i++
}
- sort.SortStrings(list)
+ sort.Strings(list)
for _, f := range list {
fmt.Printf("%s\n", f)
}
@@ -282,7 +282,7 @@ func hgModified() ([]string, os.Error) {
if err != nil {
return nil, err
}
- return strings.Split(strings.TrimSpace(out), "\n", -1), nil
+ return strings.Split(strings.TrimSpace(out), "\n"), nil
}
// hgAdd adds name to the repository.
@@ -329,15 +329,14 @@ var lookPathCache = make(map[string]string)
// It provides input on standard input to the command.
func run(argv []string, input []byte) (out string, err os.Error) {
if len(argv) < 1 {
- err = os.EINVAL
- goto Error
+ return "", &runError{dup(argv), os.EINVAL}
}
prog, ok := lookPathCache[argv[0]]
if !ok {
prog, err = exec.LookPath(argv[0])
if err != nil {
- goto Error
+ return "", &runError{dup(argv), err}
}
lookPathCache[argv[0]] = prog
}
@@ -347,13 +346,10 @@ func run(argv []string, input []byte) (out string, err os.Error) {
cmd.Stdin = bytes.NewBuffer(input)
}
bs, err := cmd.CombinedOutput()
- if err == nil {
- return string(bs), nil
+ if err != nil {
+ return "", &runError{dup(argv), err}
}
-
-Error:
- err = &runError{dup(argv), err}
- return
+ return string(bs), nil
}
// A runError represents an error that occurred while running a command.
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 3f3faade0..f1132fc8b 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -249,7 +249,7 @@ dynrelocsym(Sym *s)
return;
for(r=s->r; r<s->r+s->nr; r++) {
targ = r->sym;
- if(r->sym->plt == -2) { // make dynimport JMP table for PE object files.
+ if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files.
targ->plt = rel->size;
r->sym = rel;
r->add = targ->plt;
@@ -278,6 +278,10 @@ dynreloc(void)
{
Sym *s;
+ // -d supresses dynamic loader format, so we may as well not
+ // compute these sections or mark their symbols as reachable.
+ if(debug['d'] && HEADTYPE != Hwindows)
+ return;
if(debug['v'])
Bprint(&bso, "%5.2f reloc\n", cputime());
Bflush(&bso);
@@ -482,13 +486,13 @@ codeblk(int32 addr, int32 size)
q = sym->p;
while(n >= 16) {
- Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q);
+ Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q);
addr += 16;
q += 16;
n -= 16;
}
if(n > 0)
- Bprint(&bso, "%.6ux\t%-20.*I\n", addr, n, q);
+ Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q);
addr += n;
continue;
}
@@ -502,7 +506,7 @@ codeblk(int32 addr, int32 size)
Bprint(&bso, "%.6ux\t", p->pc);
q = sym->p + p->pc - sym->value;
n = epc - p->pc;
- Bprint(&bso, "%-20.*I | %P\n", n, q, p);
+ Bprint(&bso, "%-20.*I | %P\n", (int)n, q, p);
addr += n;
}
}
@@ -543,7 +547,7 @@ datblk(int32 addr, int32 size)
Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(pre-pad)", addr);
addr = sym->value;
}
- Bprint(&bso, "%-20s %.8ux|", sym->name, addr);
+ Bprint(&bso, "%-20s %.8ux|", sym->name, (uint)addr);
p = sym->p;
ep = p + sym->np;
while(p < ep)
@@ -555,8 +559,8 @@ datblk(int32 addr, int32 size)
}
if(addr < eaddr)
- Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(post-pad)", addr);
- Bprint(&bso, "%-20s %.8ux|\n", "", eaddr);
+ Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(post-pad)", (uint)addr);
+ Bprint(&bso, "%-20s %.8ux|\n", "", (uint)eaddr);
}
void
@@ -781,18 +785,38 @@ dodata(void)
*/
/* read-only data */
- sect = addsection(&segtext, ".rodata", 06);
+ sect = addsection(&segtext, ".rodata", 04);
sect->vaddr = 0;
datsize = 0;
s = datap;
- for(; s != nil && s->type < SDATA; s = s->next) {
+ for(; s != nil && s->type < SSYMTAB; s = s->next) {
s->type = SRODATA;
t = rnd(s->size, PtrSize);
s->value = datsize;
datsize += t;
}
sect->len = datsize - sect->vaddr;
-
+
+ /* gosymtab */
+ sect = addsection(&segtext, ".gosymtab", 04);
+ sect->vaddr = datsize;
+ for(; s != nil && s->type < SPCLNTAB; s = s->next) {
+ s->type = SRODATA;
+ s->value = datsize;
+ datsize += s->size;
+ }
+ sect->len = datsize - sect->vaddr;
+
+ /* gopclntab */
+ sect = addsection(&segtext, ".gopclntab", 04);
+ sect->vaddr = datsize;
+ for(; s != nil && s->type < SDATA; s = s->next) {
+ s->type = SRODATA;
+ s->value = datsize;
+ datsize += s->size;
+ }
+ sect->len = datsize - sect->vaddr;
+
/* data */
datsize = 0;
sect = addsection(&segdata, ".data", 06);
@@ -808,9 +832,9 @@ dodata(void)
t = rnd(t, PtrSize);
else if(t > 2)
t = rnd(t, 4);
- if(t & 1)
+ if(t & 1) {
;
- else if(t & 2)
+ } else if(t & 2)
datsize = rnd(datsize, 2);
else if(t & 4)
datsize = rnd(datsize, 4);
@@ -834,9 +858,9 @@ dodata(void)
t = rnd(t, PtrSize);
else if(t > 2)
t = rnd(t, 4);
- if(t & 1)
+ if(t & 1) {
;
- else if(t & 2)
+ } else if(t & 2)
datsize = rnd(datsize, 2);
else if(t & 4)
datsize = rnd(datsize, 4);
@@ -886,7 +910,7 @@ textaddress(void)
void
address(void)
{
- Section *s, *text, *data, *rodata;
+ Section *s, *text, *data, *rodata, *symtab, *pclntab;
Sym *sym, *sub;
uvlong va;
@@ -917,7 +941,9 @@ address(void)
segdata.filelen = segdata.sect->len; // assume .data is first
text = segtext.sect;
- rodata = segtext.sect->next;
+ rodata = text->next;
+ symtab = rodata->next;
+ pclntab = symtab->next;
data = segdata.sect;
for(sym = datap; sym != nil; sym = sym->next) {
@@ -934,12 +960,11 @@ address(void)
xdefine("etext", STEXT, text->vaddr + text->len);
xdefine("rodata", SRODATA, rodata->vaddr);
xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
+ xdefine("symtab", SRODATA, symtab->vaddr);
+ xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
+ xdefine("pclntab", SRODATA, pclntab->vaddr);
+ xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len);
xdefine("data", SBSS, data->vaddr);
xdefine("edata", SBSS, data->vaddr + data->len);
xdefine("end", SBSS, segdata.vaddr + segdata.len);
-
- sym = lookup("pclntab", 0);
- xdefine("epclntab", SRODATA, sym->value + sym->size);
- sym = lookup("symtab", 0);
- xdefine("esymtab", SRODATA, sym->value + sym->size);
}
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index 50b42183e..1c10dc796 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -1822,7 +1822,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
seek(cout, unitstart, 0);
LPUT(here - unitstart - sizeof(int32)); // unit_length
WPUT(3); // dwarf version
- LPUT(header_length); // header lenght starting here
+ LPUT(header_length); // header length starting here
cflush();
seek(cout, here, 0);
}
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index d1370d28b..c63df2241 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -110,7 +110,6 @@ typedef struct {
#define ELFOSABI_OPENVMS 13 /* Open VMS */
#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
#define ELFOSABI_ARM 97 /* ARM */
-#define ELFOSABI_NACL 123 /* Native Client */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
@@ -262,8 +261,8 @@ typedef struct {
/* Values for d_tag. */
#define DT_NULL 0 /* Terminating entry. */
-#define DT_NEEDED 1 /* String table offset of a needed shared
- library. */
+/* String table offset of a needed shared library. */
+#define DT_NEEDED 1
#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
#define DT_PLTGOT 3 /* Processor-dependent address. */
#define DT_HASH 4 /* Address of symbol hash table. */
@@ -276,8 +275,8 @@ typedef struct {
#define DT_SYMENT 11 /* Size of each symbol table entry. */
#define DT_INIT 12 /* Address of initialization function. */
#define DT_FINI 13 /* Address of finalization function. */
-#define DT_SONAME 14 /* String table offset of shared object
- name. */
+/* String table offset of shared object name. */
+#define DT_SONAME 14
#define DT_RPATH 15 /* String table offset of library path. [sup] */
#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
@@ -285,30 +284,29 @@ typedef struct {
#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
#define DT_PLTREL 20 /* Type of relocation used for PLT. */
#define DT_DEBUG 21 /* Reserved (not used). */
-#define DT_TEXTREL 22 /* Indicates there may be relocations in
- non-writable segments. [sup] */
+/* Indicates there may be relocations in non-writable segments. [sup] */
+#define DT_TEXTREL 22
#define DT_JMPREL 23 /* Address of PLT relocations. */
#define DT_BIND_NOW 24 /* [sup] */
-#define DT_INIT_ARRAY 25 /* Address of the array of pointers to
- initialization functions */
-#define DT_FINI_ARRAY 26 /* Address of the array of pointers to
- termination functions */
-#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of
- initialization functions. */
-#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of
- terminationfunctions. */
-#define DT_RUNPATH 29 /* String table offset of a null-terminated
- library search path string. */
+/* Address of the array of pointers to initialization functions */
+#define DT_INIT_ARRAY 25
+/* Address of the array of pointers to termination functions */
+#define DT_FINI_ARRAY 26
+/* Size in bytes of the array of initialization functions. */
+#define DT_INIT_ARRAYSZ 27
+/* Size in bytes of the array of terminationfunctions. */
+#define DT_FINI_ARRAYSZ 28
+/* String table offset of a null-terminated library search path string. */
+#define DT_RUNPATH 29
#define DT_FLAGS 30 /* Object specific flag values. */
-#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING
- and less than DT_LOOS follow the rules for
- the interpretation of the d_un union
- as follows: even == 'd_ptr', even == 'd_val'
- or none */
-#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to
- pre-initialization functions. */
-#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of
- pre-initialization functions. */
+/* Values greater than or equal to DT_ENCODING and less than
+ DT_LOOS follow the rules for the interpretation of the d_un
+ union as follows: even == 'd_ptr', even == 'd_val' or none */
+#define DT_ENCODING 32
+/* Address of the array of pointers to pre-initialization functions. */
+#define DT_PREINIT_ARRAY 32
+/* Size in bytes of the array of pre-initialization functions. */
+#define DT_PREINIT_ARRAYSZ 33
#define DT_LOOS 0x6000000d /* First OS-specific */
#define DT_HIOS 0x6ffff000 /* Last OS-specific */
#define DT_LOPROC 0x70000000 /* First processor-specific type. */
@@ -319,19 +317,19 @@ typedef struct {
#define DT_VERSYM 0x6ffffff0
/* Values for DT_FLAGS */
-#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may
- make reference to the $ORIGIN substitution
- string */
+/* Indicates that the object being loaded may make reference to
+ the $ORIGIN substitution string */
+#define DF_ORIGIN 0x0001
#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
-#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in
- non-writable segments. */
-#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should
- process all relocations for the object
- containing this entry before transferring
- control to the program. */
-#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or
- executable contains code using a static
- thread-local storage scheme. */
+/* Indicates there may be relocations in non-writable segments. */
+#define DF_TEXTREL 0x0004
+/* Indicates that the dynamic linker should process all
+ relocations for the object containing this entry before
+ transferring control to the program. */
+#define DF_BIND_NOW 0x0008
+/* Indicates that the shared object or executable contains code
+ using a static thread-local storage scheme. */
+#define DF_STATIC_TLS 0x0010
/* Values for n_type. Used in core files. */
#define NT_PRSTATUS 1 /* Process status. */
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index d61020e49..8334e988e 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -328,15 +328,16 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
Reloc *r, *rp;
Sym *s;
+ USED(pkg);
if(debug['v'])
Bprint(&bso, "%5.2f ldelf %s\n", cputime(), pn);
version++;
base = Boffset(f);
- if(Bread(f, &hdrbuf, sizeof hdrbuf) != sizeof hdrbuf)
+ if(Bread(f, hdrbuf, sizeof hdrbuf) != sizeof hdrbuf)
goto bad;
- hdr = (ElfHdrBytes*)&hdrbuf;
+ hdr = (ElfHdrBytes*)hdrbuf;
if(memcmp(hdr->ident, ElfMagic, 4) != 0)
goto bad;
switch(hdr->ident[5]) {
@@ -518,7 +519,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
name = smprint("%s(%s)", pn, sect->name);
s = lookup(name, version);
free(name);
- switch(sect->flags&(ElfSectFlagAlloc|ElfSectFlagWrite|ElfSectFlagExec)) {
+ switch((int)sect->flags&(ElfSectFlagAlloc|ElfSectFlagWrite|ElfSectFlagExec)) {
default:
werrstr("unexpected flags for ELF section %s", sect->name);
goto bad;
diff --git a/src/cmd/ld/ldmacho.c b/src/cmd/ld/ldmacho.c
index bbb21d51a..abbc3b3cd 100644
--- a/src/cmd/ld/ldmacho.c
+++ b/src/cmd/ld/ldmacho.c
@@ -440,6 +440,7 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
Reloc *r, *rp;
char *name;
+ USED(pkg);
version++;
base = Boffset(f);
if(Bread(f, hdr, sizeof hdr) != sizeof hdr)
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index d6aa267c4..98c866fee 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -125,10 +125,13 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
Sym *s;
Reloc *r, *rp;
PeSym *sym;
-
+
+ USED(len);
+ USED(pkg);
if(debug['v'])
Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn);
+ sect = nil;
version++;
base = Boffset(f);
@@ -304,6 +307,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
diag("%s: %s sectnum <0!", pn, s->name, sym->sectnum);
}
+ if(sect == nil)
+ return;
s->sub = sect->sym->sub;
sect->sym->sub = s;
s->type = sect->sym->type | SSUB;
@@ -366,12 +371,11 @@ readsym(PeObj *obj, int i, PeSym **y)
sym = &obj->pesym[i];
*y = sym;
- s = nil;
name = sym->name;
if(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0) // section
name = obj->sect[sym->sectnum-1].sym->name;
- if(strncmp(sym->name, "__imp__", 6) == 0)
+ if(strncmp(sym->name, "__imp__", 7) == 0)
name = &sym->name[7]; // __imp__Name => Name
else if(sym->name[0] == '_')
name = &sym->name[1]; // _Name => Name
@@ -403,6 +407,8 @@ readsym(PeObj *obj, int i, PeSym **y)
if(s != nil && s->type == 0 && !(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0))
s->type = SXREF;
+ if(strncmp(sym->name, "__imp__", 7) == 0)
+ s->got = -2; // flag for __imp__
sym->sym = s;
return 0;
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 04ee790a4..77a62f5de 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -956,7 +956,7 @@ pclntab(void)
uchar *bp;
sym = lookup("pclntab", 0);
- sym->type = SRODATA;
+ sym->type = SPCLNTAB;
sym->reachable = 1;
if(debug['s'])
return;
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index dfd18fbff..347987195 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -40,6 +40,8 @@ enum
SSTRING,
SGOSTRING,
SRODATA,
+ SSYMTAB,
+ SPCLNTAB,
SDATA,
SMACHO, /* Mach-O __nl_symbol_ptr */
SMACHOGOT,
@@ -260,10 +262,8 @@ enum {
Hipaq, // ipaq
Hdarwin, // Apple Mach-O
Hlinux, // Linux ELF
- Hnacl, // Google Native Client
Hfreebsd, // FreeBSD ELF
Hwindows, // MS Windows PE
- Htiny // tiny (os image)
};
typedef struct Header Header;
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index 91e15d343..9ac0a50d8 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -5,8 +5,6 @@
// PE (Portable Executable) file writing
// http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
-#include <time.h>
-
#include "l.h"
#include "../ld/lib.h"
#include "../ld/pe.h"
@@ -150,7 +148,7 @@ pewrite(void)
ewrite(cout, &oh64, sizeof oh64);
else
ewrite(cout, &oh, sizeof oh);
- ewrite(cout, &sh, nsect * sizeof sh[0]);
+ ewrite(cout, sh, nsect * sizeof sh[0]);
}
static void
@@ -175,7 +173,7 @@ initdynimport(void)
Sym *s, *dynamic;
dr = nil;
-
+ m = nil;
for(s = allsym; s != S; s = s->allsym) {
if(!s->reachable || !s->dynimpname || s->dynexport)
continue;
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index e3093b2aa..60e146b35 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -90,6 +90,7 @@ putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
{
int bind, type, shndx, off;
+ USED(go);
switch(t) {
default:
return;
@@ -127,6 +128,10 @@ putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
{
int i;
+ USED(go);
+ USED(ver);
+ USED(size);
+ USED(x);
switch(t) {
case 'T':
case 'L':
@@ -252,6 +257,7 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
int i, f, l;
Reloc *rel;
+ USED(size);
if(t == 'f')
name++;
l = 4;
@@ -280,7 +286,6 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
}
scput(0);
scput(0);
- i++;
}
else {
for(i=0; name[i]; i++)
@@ -311,9 +316,9 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
return;
}
if(ver)
- Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s, ver, typ ? typ->name : "");
+ Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s->name, ver, typ ? typ->name : "");
else
- Bprint(&bso, "%c %.8llux %s %s\n", t, v, s, typ ? typ->name : "");
+ Bprint(&bso, "%c %.8llux %s %s\n", t, v, s->name, typ ? typ->name : "");
}
}
@@ -346,7 +351,7 @@ symtab(void)
s->reachable = 1;
symt = lookup("symtab", 0);
- symt->type = SRODATA;
+ symt->type = SSYMTAB;
symt->size = 0;
symt->reachable = 1;
@@ -367,5 +372,7 @@ symtab(void)
}
}
+ if(debug['s'])
+ return;
genasmsym(putsymb);
}
diff --git a/src/cmd/nm/Makefile b/src/cmd/nm/Makefile
index 383dbd973..81bc348de 100644
--- a/src/cmd/nm/Makefile
+++ b/src/cmd/nm/Makefile
@@ -12,7 +12,4 @@ TARG=6nm
OFILES=\
nm.$O\
-LIB=\
- ../../../lib/libmach.a\
-
include ../../Make.ccmd
diff --git a/src/cmd/prof/Makefile b/src/cmd/prof/Makefile
index e643f267c..8a1a2f308 100644
--- a/src/cmd/prof/Makefile
+++ b/src/cmd/prof/Makefile
@@ -13,9 +13,6 @@ TARG=6prof
OFILES=\
main.$O\
-LIB=\
- ../../../lib/libmach.a\
-
NOINSTALL=1
include ../../Make.ccmd