summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5c/swt.c4
-rw-r--r--src/cmd/5g/cgen.c18
-rw-r--r--src/cmd/5g/gg.h2
-rw-r--r--src/cmd/5g/peep.c4
-rw-r--r--src/cmd/5l/l.h1
-rw-r--r--src/cmd/5l/obj.c4
-rw-r--r--src/cmd/6g/cgen.c18
-rw-r--r--src/cmd/6g/reg.c2
-rw-r--r--src/cmd/6l/asm.c44
-rw-r--r--src/cmd/6l/l.h1
-rw-r--r--src/cmd/6l/obj.c14
-rw-r--r--src/cmd/8g/cgen.c6
-rw-r--r--src/cmd/8g/ggen.c4
-rw-r--r--src/cmd/8l/asm.c40
-rw-r--r--src/cmd/8l/l.h1
-rw-r--r--src/cmd/8l/obj.c5
-rw-r--r--src/cmd/8l/prof.c2
-rw-r--r--src/cmd/cc/dpchk.c30
-rw-r--r--src/cmd/cc/macbody2
-rw-r--r--src/cmd/cgo/main.go16
-rw-r--r--src/cmd/cgo/out.go78
-rw-r--r--src/cmd/gc/align.c4
-rw-r--r--src/cmd/gc/cplx.c20
-rw-r--r--src/cmd/gc/dcl.c41
-rw-r--r--src/cmd/gc/go.h5
-rw-r--r--src/cmd/gc/go.y4
-rw-r--r--src/cmd/gc/lex.c10
-rw-r--r--src/cmd/gc/print.c11
-rw-r--r--src/cmd/gc/reflect.c87
-rw-r--r--src/cmd/gc/subr.c28
-rw-r--r--src/cmd/gc/swt.c4
-rw-r--r--src/cmd/gc/typecheck.c57
-rw-r--r--src/cmd/gc/walk.c83
-rw-r--r--src/cmd/gofix/doc.go4
-rw-r--r--src/cmd/gofix/reflect.go18
-rw-r--r--src/cmd/gofix/testdata/reflect.asn1.go.out30
-rw-r--r--src/cmd/gofix/testdata/reflect.datafmt.go.out2
-rw-r--r--src/cmd/gofix/testdata/reflect.decode.go.out22
-rw-r--r--src/cmd/gofix/testdata/reflect.decoder.go.out4
-rw-r--r--src/cmd/gofix/testdata/reflect.dnsmsg.go.out6
-rw-r--r--src/cmd/gofix/testdata/reflect.encode.go.out4
-rw-r--r--src/cmd/gofix/testdata/reflect.encoder.go.out4
-rw-r--r--src/cmd/gofix/testdata/reflect.export.go.out8
-rw-r--r--src/cmd/gofix/testdata/reflect.print.go.out34
-rw-r--r--src/cmd/gofix/testdata/reflect.quick.go.out36
-rw-r--r--src/cmd/gofix/testdata/reflect.read.go.out14
-rw-r--r--src/cmd/gofix/testdata/reflect.scan.go.out4
-rw-r--r--src/cmd/gofix/testdata/reflect.script.go.out12
-rw-r--r--src/cmd/gofix/testdata/reflect.template.go.out6
-rw-r--r--src/cmd/gofix/testdata/reflect.type.go.out24
-rw-r--r--src/cmd/gofix/typecheck.go7
-rw-r--r--src/cmd/gofmt/doc.go26
-rw-r--r--src/cmd/gofmt/gofmt.go46
-rw-r--r--src/cmd/gofmt/gofmt_test.go1
-rw-r--r--src/cmd/gofmt/rewrite.go39
-rw-r--r--src/cmd/gofmt/simplify.go4
-rwxr-xr-xsrc/cmd/gofmt/test.sh2
-rw-r--r--src/cmd/gofmt/testdata/rewrite1.golden4
-rw-r--r--src/cmd/gofmt/testdata/rewrite1.input4
-rw-r--r--src/cmd/gofmt/testdata/rewrite2.golden10
-rw-r--r--src/cmd/gofmt/testdata/rewrite2.input10
-rw-r--r--src/cmd/goinstall/Makefile1
-rw-r--r--src/cmd/goinstall/download.go36
-rw-r--r--src/cmd/goinstall/main.go17
-rw-r--r--src/cmd/goinstall/make.go45
-rw-r--r--src/cmd/goinstall/parse.go3
-rw-r--r--src/cmd/goinstall/path.go117
-rw-r--r--src/cmd/gopack/ar.c45
-rw-r--r--src/cmd/gotest/gotest.go29
-rw-r--r--src/cmd/ld/data.c9
-rw-r--r--src/cmd/ld/dwarf.c22
-rw-r--r--src/cmd/ld/elf.c135
-rw-r--r--src/cmd/ld/elf.h9
-rw-r--r--src/cmd/ld/go.c14
-rw-r--r--src/cmd/ld/ldelf.c3
-rw-r--r--src/cmd/ld/lib.c5
-rw-r--r--src/cmd/ld/lib.h2
-rw-r--r--src/cmd/ld/macho.c23
-rw-r--r--src/cmd/ld/pe.c3
-rw-r--r--src/cmd/ld/symtab.c20
80 files changed, 1153 insertions, 420 deletions
diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c
index d45aabc5e..431f04817 100644
--- a/src/cmd/5c/swt.c
+++ b/src/cmd/5c/swt.c
@@ -665,7 +665,9 @@ align(int32 i, Type *t, int op, int32 *maxalign)
case Aarg2: /* width of a parameter */
o += t->width;
- w = SZ_LONG;
+ w = t->width;
+ if(w > SZ_LONG)
+ w = SZ_LONG;
break;
case Aaut3: /* total align of automatic */
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 032409bae..4e5f7ebcd 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -43,6 +43,8 @@ cgen(Node *n, Node *res)
}
if(isfat(n->type)) {
+ if(n->type->width < 0)
+ fatal("forgot to compute width for %T", n->type);
sgen(n, res, n->type->width);
goto ret;
}
@@ -960,7 +962,7 @@ bgen(Node *n, int true, Prog *to)
}
// make simplest on right
- if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
+ if(nl->op == OLITERAL || (nl->ullman < UINF && nl->ullman < nr->ullman)) {
a = brrev(a);
r = nl;
nl = nr;
@@ -1071,18 +1073,18 @@ bgen(Node *n, int true, Prog *to)
a = optoas(a, nr->type);
if(nr->ullman >= UINF) {
- regalloc(&n1, nr->type, N);
- cgen(nr, &n1);
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
- tempname(&tmp, nr->type);
+ tempname(&tmp, nl->type);
gmove(&n1, &tmp);
regfree(&n1);
- regalloc(&n1, nl->type, N);
- cgen(nl, &n1);
-
regalloc(&n2, nr->type, N);
- cgen(&tmp, &n2);
+ cgen(nr, &n2);
+
+ regalloc(&n1, nl->type, N);
+ cgen(&tmp, &n1);
gcmp(optoas(OCMP, nr->type), &n1, &n2);
patch(gbranch(a, nr->type), to);
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index ce4575be9..78e6833b2 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -52,7 +52,7 @@ struct Prog
EXTERN Biobuf* bout;
EXTERN int32 dynloc;
-EXTERN uchar reg[REGALLOC_FMAX];
+EXTERN uchar reg[REGALLOC_FMAX+1];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
extern char* anames[];
diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c
index ca12d70f2..6f36e12d4 100644
--- a/src/cmd/5g/peep.c
+++ b/src/cmd/5g/peep.c
@@ -1134,7 +1134,7 @@ copyu(Prog *p, Adr *v, Adr *s)
if(v->type == D_REG) {
if(v->reg <= REGEXT && v->reg > exregoffset)
return 2;
- if(v->reg == REGARG)
+ if(v->reg == (uchar)REGARG)
return 2;
}
if(v->type == D_FREG)
@@ -1152,7 +1152,7 @@ copyu(Prog *p, Adr *v, Adr *s)
case ATEXT: /* funny */
if(v->type == D_REG)
- if(v->reg == REGARG)
+ if(v->reg == (uchar)REGARG)
return 3;
return 0;
}
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index cf5a9990b..f3c9d839d 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -156,6 +156,7 @@ struct Sym
char* file;
char* dynimpname;
char* dynimplib;
+ char* dynimpvers;
// STEXT
Auto* autom;
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index f252f9fc5..c4a2bfc3f 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -317,7 +317,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
a->sym = h[c];
a->name = Bgetc(f);
- if(a->reg < 0 || a->reg > NREG) {
+ if((schar)a->reg < 0 || a->reg > NREG) {
print("register out of range %d\n", a->reg);
Bputc(f, ALAST+1);
return; /* force real diagnostic */
@@ -581,7 +581,7 @@ loop:
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
- savedata(s, p);
+ savedata(s, p, pn);
unmal(p, sizeof *p);
break;
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index 47f3374f5..75dc4fe13 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -47,6 +47,8 @@ cgen(Node *n, Node *res)
}
if(isfat(n->type)) {
+ if(n->type->width < 0)
+ fatal("forgot to compute width for %T", n->type);
sgen(n, res, n->type->width);
goto ret;
}
@@ -827,7 +829,7 @@ bgen(Node *n, int true, Prog *to)
}
// make simplest on right
- if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
+ if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
a = brrev(a);
r = nl;
nl = nr;
@@ -877,18 +879,18 @@ bgen(Node *n, int true, Prog *to)
}
if(nr->ullman >= UINF) {
- regalloc(&n1, nr->type, N);
- cgen(nr, &n1);
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
- tempname(&tmp, nr->type);
+ tempname(&tmp, nl->type);
gmove(&n1, &tmp);
regfree(&n1);
- regalloc(&n1, nl->type, N);
- cgen(nl, &n1);
+ regalloc(&n2, nr->type, N);
+ cgen(nr, &n2);
- regalloc(&n2, nr->type, &n2);
- cgen(&tmp, &n2);
+ regalloc(&n1, nl->type, N);
+ cgen(&tmp, &n1);
goto cmp;
}
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index 1e1d64c59..ed8bac3f0 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -1193,7 +1193,6 @@ void
paint1(Reg *r, int bn)
{
Reg *r1;
- Prog *p;
int z;
uint32 bb;
@@ -1219,7 +1218,6 @@ paint1(Reg *r, int bn)
}
for(;;) {
r->act.b[z] |= bb;
- p = r->prog;
if(r->use1.b[z] & bb) {
change += CREF * r->loop;
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index ba2074fde..dda19e48d 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -95,6 +95,8 @@ enum {
ElfStrStrtab,
ElfStrRelaPlt,
ElfStrPlt,
+ ElfStrGnuVersion,
+ ElfStrGnuVersionR,
NElfStr
};
@@ -436,6 +438,7 @@ adddynsym(Sym *s)
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
+
name = s->dynimpname;
if(name == nil)
name = s->name;
@@ -586,6 +589,8 @@ doelf(void)
elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt");
elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
+ elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
+ elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
/* dynamic symbol table - first entry all zeros */
s = lookup(".dynsym", 0);
@@ -629,6 +634,14 @@ doelf(void)
s = lookup(".rela.plt", 0);
s->reachable = 1;
s->type = SELFDATA;
+
+ s = lookup(".gnu.version", 0);
+ s->reachable = 1;
+ s->type = SELFDATA;
+
+ s = lookup(".gnu.version_r", 0);
+ s->reachable = 1;
+ s->type = SELFDATA;
/* define dynamic elf table */
s = lookup(".dynamic", 0);
@@ -653,7 +666,8 @@ doelf(void)
elfwritedynent(s, DT_PLTREL, DT_RELA);
elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
- elfwritedynent(s, DT_NULL, 0);
+
+ // Do not write DT_NULL. elfdynhash will finish it.
}
}
@@ -681,7 +695,7 @@ asmb(void)
{
int32 magic;
int a, dynsym;
- vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink;
+ vlong vl, startva, symo, elfsymo, elfstro, elfsymsize, machlink;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
@@ -735,8 +749,11 @@ asmb(void)
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
elftextsh = 1;
- if(!debug['d'])
+ if(!debug['d']) {
elftextsh += 10;
+ if(elfverneed)
+ elftextsh += 2;
+ }
break;
case Hwindows:
break;
@@ -846,10 +863,7 @@ asmb(void)
/* elf amd-64 */
eh = getElfEhdr();
- fo = HEADR;
startva = INITTEXT - HEADR;
- va = startva + fo;
- w = segtext.filelen;
/* This null SHdr must appear before all others */
sh = newElfShdr(elfstr[ElfStrEmpty]);
@@ -923,6 +937,24 @@ asmb(void)
sh->addralign = 1;
shsym(sh, lookup(".dynstr", 0));
+ if(elfverneed) {
+ sh = newElfShdr(elfstr[ElfStrGnuVersion]);
+ sh->type = SHT_GNU_VERSYM;
+ sh->flags = SHF_ALLOC;
+ sh->addralign = 2;
+ sh->link = dynsym;
+ sh->entsize = 2;
+ shsym(sh, lookup(".gnu.version", 0));
+
+ sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
+ sh->type = SHT_GNU_VERNEED;
+ sh->flags = SHF_ALLOC;
+ sh->addralign = 8;
+ sh->info = elfverneed;
+ sh->link = dynsym+1; // dynstr
+ shsym(sh, lookup(".gnu.version_r", 0));
+ }
+
sh = newElfShdr(elfstr[ElfStrRelaPlt]);
sh->type = SHT_RELA;
sh->flags = SHF_ALLOC;
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 4fc13b94a..33ca51b2c 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -148,6 +148,7 @@ struct Sym
char* file;
char* dynimpname;
char* dynimplib;
+ char* dynimpvers;
// STEXT
Auto* autom;
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 6b43d2df4..d53814a74 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -356,6 +356,15 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
return;
}
}
+
+ switch(t) {
+ case D_FILE:
+ case D_FILE1:
+ case D_AUTO:
+ case D_PARAM:
+ if(s == S)
+ mangle(pn);
+ }
u = mal(sizeof(*u));
u->link = curauto;
@@ -380,7 +389,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
vlong ipc;
Prog *p;
int v, o, r, skip, mode;
- Sym *h[NSYM], *s, *di;
+ Sym *h[NSYM], *s;
uint32 sig;
char *name, *x;
int ntext;
@@ -391,7 +400,6 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
lastp = nil;
ntext = 0;
eof = Boffset(f) + len;
- di = S;
src[0] = 0;
newloop:
@@ -559,7 +567,7 @@ loop:
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
- savedata(s, p);
+ savedata(s, p, pn);
unmal(p, sizeof *p);
goto loop;
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 9c326e8ef..596824a6c 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -78,6 +78,8 @@ cgen(Node *n, Node *res)
// structs etc get handled specially
if(isfat(n->type)) {
+ if(n->type->width < 0)
+ fatal("forgot to compute width for %T", n->type);
sgen(n, res, n->type->width);
return;
}
@@ -898,7 +900,7 @@ bgen(Node *n, int true, Prog *to)
}
// make simplest on right
- if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
+ if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
a = brrev(a);
r = nl;
nl = nr;
@@ -1023,8 +1025,8 @@ bgen(Node *n, int true, Prog *to)
if(nr->ullman >= UINF) {
tempname(&n1, nl->type);
tempname(&tmp, nr->type);
- cgen(nr, &tmp);
cgen(nl, &n1);
+ cgen(nr, &tmp);
regalloc(&n2, nr->type, N);
cgen(&tmp, &n2);
goto cmp;
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 8db552493..920725c3e 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -625,12 +625,8 @@ void
cgen_div(int op, Node *nl, Node *nr, Node *res)
{
Node ax, dx, oldax, olddx;
- int rax, rdx;
Type *t;
- rax = reg[D_AX];
- rdx = reg[D_DX];
-
if(is64(nl->type))
fatal("cgen_div %T", nl->type);
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index b9bd0dae9..f28b8d904 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -91,6 +91,8 @@ enum {
ElfStrStrtab,
ElfStrRelPlt,
ElfStrPlt,
+ ElfStrGnuVersion,
+ ElfStrGnuVersionR,
NElfStr
};
@@ -420,7 +422,7 @@ adddynsym(Sym *s)
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
-
+
/* name */
name = s->dynimpname;
if(name == nil)
@@ -545,6 +547,8 @@ doelf(void)
elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
+ elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
+ elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
/* interpreter string */
s = lookup(".interp", 0);
@@ -592,6 +596,14 @@ doelf(void)
s = lookup(".rel.plt", 0);
s->reachable = 1;
s->type = SELFDATA;
+
+ s = lookup(".gnu.version", 0);
+ s->reachable = 1;
+ s->type = SELFDATA;
+
+ s = lookup(".gnu.version_r", 0);
+ s->reachable = 1;
+ s->type = SELFDATA;
elfsetupplt();
@@ -617,7 +629,8 @@ doelf(void)
elfwritedynent(s, DT_PLTREL, DT_REL);
elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
- elfwritedynent(s, DT_NULL, 0);
+
+ // Do not write DT_NULL. elfdynhash will finish it.
}
}
@@ -681,8 +694,11 @@ asmb(void)
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
elftextsh = 1;
- if(!debug['d'])
+ if(!debug['d']) {
elftextsh += 10;
+ if(elfverneed)
+ elftextsh += 2;
+ }
}
symsize = 0;
@@ -966,6 +982,24 @@ asmb(void)
sh->addralign = 1;
shsym(sh, lookup(".dynstr", 0));
+ if(elfverneed) {
+ sh = newElfShdr(elfstr[ElfStrGnuVersion]);
+ sh->type = SHT_GNU_VERSYM;
+ sh->flags = SHF_ALLOC;
+ sh->addralign = 2;
+ sh->link = dynsym;
+ sh->entsize = 2;
+ shsym(sh, lookup(".gnu.version", 0));
+
+ sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
+ sh->type = SHT_GNU_VERNEED;
+ sh->flags = SHF_ALLOC;
+ sh->addralign = 4;
+ sh->info = elfverneed;
+ sh->link = dynsym+1; // dynstr
+ shsym(sh, lookup(".gnu.version_r", 0));
+ }
+
sh = newElfShdr(elfstr[ElfStrRelPlt]);
sh->type = SHT_REL;
sh->flags = SHF_ALLOC;
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index ac0f3953f..8f39ef519 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -147,6 +147,7 @@ struct Sym
char* file;
char* dynimpname;
char* dynimplib;
+ char* dynimpvers;
// STEXT
Auto* autom;
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index d505dc10e..2a38f7ef0 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -431,7 +431,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
int32 ipc;
Prog *p;
int v, o, r, skip;
- Sym *h[NSYM], *s, *di;
+ Sym *h[NSYM], *s;
uint32 sig;
int ntext;
int32 eof;
@@ -442,7 +442,6 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
lastp = nil;
ntext = 0;
eof = Boffset(f) + len;
- di = S;
src[0] = 0;
@@ -600,7 +599,7 @@ loop:
diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
errorexit();
}
- savedata(s, p);
+ savedata(s, p, pn);
unmal(p, sizeof *p);
goto loop;
diff --git a/src/cmd/8l/prof.c b/src/cmd/8l/prof.c
index 4e95fad79..d99c5e408 100644
--- a/src/cmd/8l/prof.c
+++ b/src/cmd/8l/prof.c
@@ -36,7 +36,7 @@
void
doprof1(void)
{
-#if 0 // TODO(rsc)
+#ifdef NOTDEF // TODO(rsc)
Sym *s;
int32 n;
Prog *p, *q;
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
index d78a72a2b..0e51101f1 100644
--- a/src/cmd/cc/dpchk.c
+++ b/src/cmd/cc/dpchk.c
@@ -534,6 +534,32 @@ out:
print("%s incomplete\n", s->name);
}
+Sym*
+getimpsym(void)
+{
+ int c;
+ char *cp;
+
+ c = getnsc();
+ if(isspace(c) || c == '"') {
+ unget(c);
+ return S;
+ }
+ for(cp = symb;;) {
+ if(cp <= symb+NSYMB-4)
+ *cp++ = c;
+ c = getc();
+ if(c > 0 && !isspace(c) && c != '"')
+ continue;
+ unget(c);
+ break;
+ }
+ *cp = 0;
+ if(cp > symb+NSYMB-4)
+ yyerror("symbol too large: %s", symb);
+ return lookup();
+}
+
void
pragdynimport(void)
{
@@ -541,11 +567,11 @@ pragdynimport(void)
char *path;
Dynimp *f;
- local = getsym();
+ local = getimpsym();
if(local == nil)
goto err;
- remote = getsym();
+ remote = getimpsym();
if(remote == nil)
goto err;
diff --git a/src/cmd/cc/macbody b/src/cmd/cc/macbody
index 35740e985..ca8a54c0b 100644
--- a/src/cmd/cc/macbody
+++ b/src/cmd/cc/macbody
@@ -63,7 +63,7 @@ getsym(void)
if(cp <= symb+NSYMB-4)
*cp++ = c;
c = getc();
- if(isalnum(c) || c == '_' || c >= 0x80 || c == '$')
+ if(isalnum(c) || c == '_' || c >= 0x80)
continue;
unget(c);
break;
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 00ffc4506..84aeccc21 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -20,7 +20,6 @@ import (
"os"
"reflect"
"strings"
- "runtime"
)
// A Package collects information about the package we're going to write.
@@ -135,20 +134,7 @@ func main() {
// instead of needing to make the linkers duplicate all the
// specialized knowledge gcc has about where to look for imported
// symbols and which ones to use.
- syms, imports := dynimport(*dynobj)
- if runtime.GOOS == "windows" {
- for _, sym := range syms {
- ss := strings.Split(sym, ":", -1)
- fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
- }
- return
- }
- for _, sym := range syms {
- fmt.Printf("#pragma dynimport %s %s %q\n", sym, sym, "")
- }
- for _, p := range imports {
- fmt.Printf("#pragma dynimport %s %s %q\n", "_", "_", p)
- }
+ dynimport(*dynobj)
return
}
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index abf8c8bc2..bc031cc58 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -95,42 +95,63 @@ func (p *Package) writeDefs() {
fc.Close()
}
-func dynimport(obj string) (syms, imports []string) {
- var f interface {
- ImportedLibraries() ([]string, os.Error)
- ImportedSymbols() ([]string, os.Error)
- }
- var isMacho bool
- var err1, err2, err3 os.Error
- if f, err1 = elf.Open(obj); err1 != nil {
- if f, err2 = pe.Open(obj); err2 != nil {
- if f, err3 = macho.Open(obj); err3 != nil {
- fatalf("cannot parse %s as ELF (%v) or PE (%v) or Mach-O (%v)", obj, err1, err2, err3)
+func dynimport(obj string) {
+ if f, err := elf.Open(obj); err == nil {
+ sym, err := f.ImportedSymbols()
+ if err != nil {
+ fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
+ }
+ for _, s := range sym {
+ targ := s.Name
+ if s.Version != "" {
+ targ += "@" + s.Version
}
- isMacho = true
+ fmt.Printf("#pragma dynimport %s %s %q\n", s.Name, targ, s.Library)
+ }
+ lib, err := f.ImportedLibraries()
+ if err != nil {
+ fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
+ }
+ for _, l := range lib {
+ fmt.Printf("#pragma dynimport _ _ %q\n", l)
}
+ return
}
- var err os.Error
- syms, err = f.ImportedSymbols()
- if err != nil {
- fatalf("cannot load dynamic symbols: %v", err)
- }
- if isMacho {
- // remove leading _ that OS X insists on
- for i, s := range syms {
- if len(s) >= 2 && s[0] == '_' {
- syms[i] = s[1:]
+ if f, err := macho.Open(obj); err == nil {
+ sym, err := f.ImportedSymbols()
+ if err != nil {
+ fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
+ }
+ for _, s := range sym {
+ if len(s) > 0 && s[0] == '_' {
+ s = s[1:]
}
+ fmt.Printf("#pragma dynimport %s %s %q\n", s, s, "")
+ }
+ lib, err := f.ImportedLibraries()
+ if err != nil {
+ fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
}
+ for _, l := range lib {
+ fmt.Printf("#pragma dynimport _ _ %q\n", l)
+ }
+ return
}
- imports, err = f.ImportedLibraries()
- if err != nil {
- fatalf("cannot load dynamic imports: %v", err)
+ if f, err := pe.Open(obj); err == nil {
+ sym, err := f.ImportedSymbols()
+ if err != nil {
+ fatalf("cannot load imported symbols from PE file %s: v", obj, err)
+ }
+ for _, s := range sym {
+ ss := strings.Split(s, ":", -1)
+ fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
+ }
+ return
}
- return
+ fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
}
// Construct a gcc struct matching the 6c argument frame.
@@ -312,8 +333,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
}
fmt.Fprintf(fgcc, "\t%s *a = v;\n", ctype)
fmt.Fprintf(fgcc, "\t")
- if n.FuncType.Result != nil {
+ if t := n.FuncType.Result; t != nil {
fmt.Fprintf(fgcc, "a->r = ")
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ fmt.Fprintf(fgcc, "(const %s) ", t.C)
+ }
}
fmt.Fprintf(fgcc, "%s(", n.C)
for i := range n.FuncType.Params {
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index a01e2ea46..a8454bf13 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -468,7 +468,7 @@ typeinit(void)
okforadd[i] = 1;
okforarith[i] = 1;
okforconst[i] = 1;
-// issimple[i] = 1;
+ issimple[i] = 1;
}
}
@@ -530,7 +530,7 @@ typeinit(void)
okfor[OCOM] = okforand;
okfor[OMINUS] = okforarith;
okfor[ONOT] = okforbool;
- okfor[OPLUS] = okforadd;
+ okfor[OPLUS] = okforarith;
// special
okfor[OCAP] = okforcap;
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
index 3ec9fe5a2..890cf7f10 100644
--- a/src/cmd/gc/cplx.c
+++ b/src/cmd/gc/cplx.c
@@ -12,6 +12,19 @@ static void minus(Node *nl, Node *res);
#define CASE(a,b) (((a)<<16)|((b)<<0))
+static int
+overlap(Node *f, Node *t)
+{
+ // check whether f and t could be overlapping stack references.
+ // not exact, because it's hard to check for the stack register
+ // in portable code. close enough: worst case we will allocate
+ // an extra temporary and the registerizer will clean it up.
+ return f->op == OINDREG &&
+ t->op == OINDREG &&
+ f->xoffset+f->type->width >= t->xoffset &&
+ t->xoffset+t->type->width >= f->xoffset;
+}
+
/*
* generate:
* res = n;
@@ -43,9 +56,10 @@ complexmove(Node *f, Node *t)
case CASE(TCOMPLEX64,TCOMPLEX128):
case CASE(TCOMPLEX128,TCOMPLEX64):
case CASE(TCOMPLEX128,TCOMPLEX128):
- // complex to complex move/convert
- // make from addable
- if(!f->addable) {
+ // complex to complex move/convert.
+ // make f addable.
+ // also use temporary if possible stack overlap.
+ if(!f->addable || overlap(f, t)) {
tempname(&n1, f->type);
complexmove(f, &n1);
f = &n1;
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 3089a23b0..99af18d9f 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -560,6 +560,7 @@ funcargs(Node *nt)
{
Node *n;
NodeList *l;
+ int gen;
if(nt->op != OTFUNC)
fatal("funcargs %O", nt->op);
@@ -589,6 +590,7 @@ funcargs(Node *nt)
}
// declare the out arguments.
+ gen = 0;
for(l=nt->rlist; l; l=l->next) {
n = l->n;
if(n->op != ODCLFIELD)
@@ -596,6 +598,11 @@ funcargs(Node *nt)
if(n->left != N) {
n->left->op = ONAME;
n->left->ntype = n->right;
+ if(isblank(n->left)) {
+ // Give it a name so we can assign to it during return.
+ snprint(namebuf, sizeof(namebuf), ".anon%d", gen++);
+ n->left->sym = lookup(namebuf);
+ }
declare(n->left, PPARAMOUT);
}
}
@@ -672,10 +679,10 @@ typedcl2(Type *pt, Type *t)
ok:
n = pt->nod;
- *pt = *t;
- pt->method = nil;
+ copytype(pt->nod, t);
+ // unzero nod
pt->nod = n;
- pt->sym = n->sym;
+
pt->sym->lastlineno = parserline();
declare(n, PEXTERN);
@@ -697,12 +704,10 @@ stotype(NodeList *l, int et, Type **t, int funarg)
Type *f, *t1, *t2, **t0;
Strlit *note;
int lno;
- NodeList *init;
Node *n, *left;
char *what;
t0 = t;
- init = nil;
lno = lineno;
what = "field";
if(et == TINTER)
@@ -1130,6 +1135,32 @@ addmethod(Sym *sf, Type *t, int local)
pa = pa->type;
f = methtype(pa);
if(f == T) {
+ t = pa;
+ if(t != T) {
+ if(isptr[t->etype]) {
+ if(t->sym != S) {
+ yyerror("invalid receiver type %T (%T is a pointer type)", pa, t);
+ return;
+ }
+ t = t->type;
+ }
+ }
+ if(t != T) {
+ if(t->sym == S) {
+ yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t);
+ return;
+ }
+ if(isptr[t->etype]) {
+ yyerror("invalid receiver type %T (%T is a pointer type)", pa, t);
+ return;
+ }
+ if(t->etype == TINTER) {
+ yyerror("invalid receiver type %T (%T is an interface type)", pa, t);
+ return;
+ }
+ }
+ // Should have picked off all the reasons above,
+ // but just in case, fall back to generic error.
yyerror("invalid receiver type %T", pa);
return;
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index bb258a193..f58b76789 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -315,6 +315,7 @@ struct Pkg
{
char* name;
Strlit* path;
+ Sym* pathsym;
char* prefix;
Pkg* link;
char exported; // import line written in export data
@@ -581,6 +582,7 @@ struct Io
Biobuf* bin;
int32 ilineno;
int nlsemi;
+ int eofnl;
int peekc;
int peekc1; // second peekc for ...
char* cp; // used for content when bin==nil
@@ -1170,9 +1172,12 @@ Node* unsafenmagic(Node *n);
*/
Node* callnew(Type *t);
Node* chanfn(char *name, int n, Type *t);
+void copytype(Node *n, Type *t);
+void defertypecopy(Node *n, Type *t);
Node* mkcall(char *name, Type *t, NodeList **init, ...);
Node* mkcall1(Node *fn, Type *t, NodeList **init, ...);
void queuemethod(Node *n);
+void resumetypecopy(void);
int vmatch1(Node *l, Node *r);
void walk(Node *fn);
Node* walkdef(Node *n);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 89899ae1e..7adfd002a 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1853,6 +1853,10 @@ hidden_interfacedcl:
{
$$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
}
+| hidden_importsym '(' ohidden_funarg_list ')' ohidden_funres
+ {
+ $$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
+ }
ohidden_funres:
{
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index bfd96274e..04dd0d5b9 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -249,6 +249,7 @@ main(int argc, char *argv[])
for(l=xtop; l; l=l->next)
if(l->n->op == ODCL || l->n->op == OAS)
typecheck(&l->n, Etop);
+ resumetypecopy();
resumecheckwidth();
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC)
@@ -1310,7 +1311,7 @@ getc(void)
lexlineno++;
return c;
}
-
+
if(curio.bin == nil) {
c = *curio.cp & 0xff;
if(c != 0)
@@ -1325,8 +1326,11 @@ getc(void)
break;
}
case EOF:
- return EOF;
-
+ // insert \n at EOF
+ if(curio.eofnl)
+ return EOF;
+ curio.eofnl = 1;
+ c = '\n';
case '\n':
if(pushedio.bin == nil)
lexlineno++;
diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c
index fee37f6d0..e03a14080 100644
--- a/src/cmd/gc/print.c
+++ b/src/cmd/gc/print.c
@@ -242,6 +242,17 @@ exprfmt(Fmt *f, Node *n, int prec)
exprfmt(f, n->right, 0);
break;
+ case OAS2:
+ case OAS2DOTTYPE:
+ case OAS2FUNC:
+ case OAS2MAPR:
+ case OAS2MAPW:
+ case OAS2RECV:
+ exprlistfmt(f, n->list);
+ fmtprint(f, " = ");
+ exprlistfmt(f, n->rlist);
+ break;
+
case OADD:
case OANDAND:
case OANDNOT:
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b98e820c6..810787d30 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -137,7 +137,6 @@ methodfunc(Type *f, Type *receiver)
static Sig*
methods(Type *t)
{
- int o;
Type *f, *mt, *it, *this;
Sig *a, *b;
Sym *method;
@@ -157,7 +156,6 @@ methods(Type *t)
// make list of methods for t,
// generating code if necessary.
a = nil;
- o = 0;
oldlist = nil;
for(f=mt->xmethod; f; f=f->down) {
if(f->type->etype != TFUNC)
@@ -184,6 +182,11 @@ methods(Type *t)
a = b;
a->name = method->name;
+ if(!exportname(method->name)) {
+ if(method->pkg == nil)
+ fatal("methods: missing package");
+ a->pkg = method->pkg;
+ }
a->isym = methodsym(method, it, 1);
a->tsym = methodsym(method, t, 0);
a->type = methodfunc(f->type, t);
@@ -240,14 +243,12 @@ static Sig*
imethods(Type *t)
{
Sig *a, *all, *last;
- int o;
Type *f;
Sym *method, *isym;
Prog *oldlist;
all = nil;
last = nil;
- o = 0;
oldlist = nil;
for(f=t->type; f; f=f->down) {
if(f->etype != TFIELD)
@@ -257,8 +258,11 @@ imethods(Type *t)
method = f->sym;
a = mal(sizeof(*a));
a->name = method->name;
- if(!exportname(method->name))
+ if(!exportname(method->name)) {
+ if(method->pkg == nil)
+ fatal("imethods: missing package");
a->pkg = method->pkg;
+ }
a->mtype = f->type;
a->offset = 0;
a->type = methodfunc(f->type, nil);
@@ -301,26 +305,6 @@ imethods(Type *t)
return all;
}
-static int
-dgopkgpath(Sym *s, int ot, Pkg *pkg)
-{
- if(pkg == nil)
- return dgostringptr(s, ot, nil);
-
- // Emit reference to go.importpath.""., which 6l will
- // rewrite using the correct import path. Every package
- // that imports this one directly defines the symbol.
- if(pkg == localpkg) {
- static Sym *ns;
-
- if(ns == nil)
- ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
- return dsymptr(s, ot, ns, 0);
- }
-
- return dgostringptr(s, ot, pkg->name);
-}
-
static void
dimportpath(Pkg *p)
{
@@ -328,6 +312,9 @@ dimportpath(Pkg *p)
char *nam;
Node *n;
+ if(p->pathsym != S)
+ return;
+
if(gopkg == nil) {
gopkg = mkpkg(strlit("go"));
gopkg->name = "go";
@@ -339,11 +326,33 @@ dimportpath(Pkg *p)
free(nam);
n->class = PEXTERN;
n->xoffset = 0;
+ p->pathsym = n->sym;
gdatastring(n, p->path);
ggloblsym(n->sym, types[TSTRING]->width, 1);
}
+static int
+dgopkgpath(Sym *s, int ot, Pkg *pkg)
+{
+ if(pkg == nil)
+ return dgostringptr(s, ot, nil);
+
+ // Emit reference to go.importpath.""., which 6l will
+ // rewrite using the correct import path. Every package
+ // that imports this one directly defines the symbol.
+ if(pkg == localpkg) {
+ static Sym *ns;
+
+ if(ns == nil)
+ ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
+ return dsymptr(s, ot, ns, 0);
+ }
+
+ dimportpath(pkg);
+ return dsymptr(s, ot, pkg->pathsym, 0);
+}
+
/*
* uncommonType
* ../../pkg/runtime/type.go:/uncommonType
@@ -694,7 +703,7 @@ dtypesym(Type *t)
int ot, xt, n, isddd, dupok;
Sym *s, *s1, *s2;
Sig *a, *m;
- Type *t1, *tbase;
+ Type *t1, *tbase, *t2;
if(isideal(t))
fatal("dtypesym %T", t);
@@ -731,15 +740,25 @@ ok:
break;
case TARRAY:
- // ../../pkg/runtime/type.go:/ArrayType
- s1 = dtypesym(t->type);
- ot = dcommontype(s, ot, t);
- xt = ot - 2*widthptr;
- ot = dsymptr(s, ot, s1, 0);
- if(t->bound < 0)
- ot = duintptr(s, ot, -1);
- else
+ if(t->bound >= 0) {
+ // ../../pkg/runtime/type.go:/ArrayType
+ s1 = dtypesym(t->type);
+ t2 = typ(TARRAY);
+ t2->type = t->type;
+ t2->bound = -1; // slice
+ s2 = dtypesym(t2);
+ ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
+ ot = dsymptr(s, ot, s1, 0);
+ ot = dsymptr(s, ot, s2, 0);
ot = duintptr(s, ot, t->bound);
+ } else {
+ // ../../pkg/runtime/type.go:/SliceType
+ s1 = dtypesym(t->type);
+ ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
+ ot = dsymptr(s, ot, s1, 0);
+ }
break;
case TCHAN:
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 2098794a7..bb2505694 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -488,7 +488,7 @@ algtype(Type *t)
{
int a;
- if(issimple[t->etype] || isptr[t->etype] || iscomplex[t->etype] ||
+ if(issimple[t->etype] || isptr[t->etype] ||
t->etype == TCHAN || t->etype == TFUNC || t->etype == TMAP) {
if(t->width == widthptr)
a = AMEMWORD;
@@ -660,12 +660,10 @@ nodbool(int b)
Type*
aindex(Node *b, Type *t)
{
- NodeList *init;
Type *r;
int bound;
bound = -1; // open bound
- init = nil;
typecheck(&b, Erv);
if(b != nil) {
switch(consttype(b)) {
@@ -1266,7 +1264,12 @@ Tpretty(Fmt *fp, Type *t)
case TINTER:
fmtprint(fp, "interface {");
for(t1=t->type; t1!=T; t1=t1->down) {
- fmtprint(fp, " %hS%hhT", t1->sym, t1->type);
+ fmtprint(fp, " ");
+ if(exportname(t1->sym->name))
+ fmtprint(fp, "%hS", t1->sym);
+ else
+ fmtprint(fp, "%S", t1->sym);
+ fmtprint(fp, "%hhT", t1->type);
if(t1->down)
fmtprint(fp, ";");
}
@@ -1728,17 +1731,13 @@ isideal(Type *t)
Type*
methtype(Type *t)
{
- int ptr;
-
if(t == T)
return T;
// strip away pointer if it's there
- ptr = 0;
if(isptr[t->etype]) {
if(t->sym != S)
return T;
- ptr = 1;
t = t->type;
if(t == T)
return T;
@@ -1929,13 +1928,14 @@ assignop(Type *src, Type *dst, char **why)
}
return 0;
}
+ if(isptrto(dst, TINTER)) {
+ if(why != nil)
+ *why = smprint(":\n\t%T is pointer to interface, not interface", dst);
+ return 0;
+ }
if(src->etype == TINTER && dst->etype != TBLANK) {
- if(why != nil) {
- if(isptrto(dst, TINTER))
- *why = smprint(":\n\t%T is interface, not pointer to interface", src);
- else
- *why = ": need type assertion";
- }
+ if(why != nil)
+ *why = ": need type assertion";
return 0;
}
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index fbc9c4903..6e8436c3c 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -250,7 +250,7 @@ newlabel(void)
static void
casebody(Node *sw, Node *typeswvar)
{
- Node *os, *oc, *n, *c, *last;
+ Node *n, *c, *last;
Node *def;
NodeList *cas, *stat, *l, *lc;
Node *go, *br;
@@ -263,8 +263,6 @@ casebody(Node *sw, Node *typeswvar)
cas = nil; // cases
stat = nil; // statements
def = N; // defaults
- os = N; // last statement
- oc = N; // last case
br = nod(OBREAK, N, N);
for(l=sw->list; l; l=l->next) {
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 1cc5abd5c..c48bf7a29 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -31,6 +31,7 @@ static void checkassign(Node*);
static void checkassignlist(NodeList*);
static void stringtoarraylit(Node**);
static Node* resolve(Node*);
+static Type* getforwtype(Node*);
/*
* resolve ONONAME to definition, if any.
@@ -56,7 +57,7 @@ typechecklist(NodeList *l, int top)
typecheck(&l->n, top);
}
-static char* typekind[] = {
+static char* _typekind[] = {
[TINT] = "int",
[TUINT] = "uint",
[TINT8] = "int8",
@@ -82,8 +83,22 @@ static char* typekind[] = {
[TMAP] = "map",
[TARRAY] = "array",
[TFUNC] = "func",
+ [TNIL] = "nil",
+ [TIDEAL] = "ideal number",
};
+static char*
+typekind(int et)
+{
+ static char buf[50];
+ char *s;
+
+ if(0 <= et && et < nelem(_typekind) && (s=_typekind[et]) != nil)
+ return s;
+ snprint(buf, sizeof buf, "etype=%d", et);
+ return buf;
+}
+
/*
* type check node *np.
* replaces *np with a new pointer in some cases.
@@ -96,7 +111,7 @@ typecheck(Node **np, int top)
Node *n, *l, *r;
NodeList *args;
int lno, ok, ntop;
- Type *t, *tp, *missing, *have;
+ Type *t, *tp, *ft, *missing, *have;
Sym *sym;
Val v;
char *why;
@@ -139,6 +154,11 @@ typecheck(Node **np, int top)
yyerror("use of builtin %S not in function call", n->sym);
goto error;
}
+
+ // a dance to handle forward-declared recursive pointer types.
+ if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T)
+ defertypecopy(n, ft);
+
walkdef(n);
n->realtype = n->type;
if(n->op == ONONAME)
@@ -406,7 +426,7 @@ reswitch:
}
if(!okfor[op][et]) {
notokfor:
- yyerror("invalid operation: %#N (operator %#O not defined on %s)", n, op, typekind[et]);
+ yyerror("invalid operation: %#N (operator %#O not defined on %s)", n, op, typekind(et));
goto error;
}
// okfor allows any array == array;
@@ -992,9 +1012,13 @@ reswitch:
defaultlit(&n->right, T);
// copy([]byte, string)
- if(isslice(n->left->type) && n->left->type->type == types[TUINT8] && n->right->type->etype == TSTRING)
- goto ret;
-
+ if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
+ if (n->left->type->type ==types[TUINT8])
+ goto ret;
+ yyerror("arguments to copy have different element types: %lT and string", n->left->type);
+ goto error;
+ }
+
if(!isslice(n->left->type) || !isslice(n->right->type)) {
if(!isslice(n->left->type) && !isslice(n->right->type))
yyerror("arguments to copy must be slices; have %lT, %lT", n->left->type, n->right->type);
@@ -2452,3 +2476,24 @@ stringtoarraylit(Node **np)
typecheck(&nn, Erv);
*np = nn;
}
+
+static Type*
+getforwtype(Node *n)
+{
+ Node *f1, *f2;
+
+ for(f1=f2=n; ; n=n->ntype) {
+ if((n = resolve(n)) == N || n->op != OTYPE)
+ return T;
+
+ if(n->type != T && n->type->etype == TFORW)
+ return n->type;
+
+ // Check for ntype cycle.
+ if((f2 = resolve(f2)) != N && (f1 = resolve(f2->ntype)) != N) {
+ f2 = resolve(f1->ntype);
+ if(f1 == n || f2 == n)
+ return T;
+ }
+ }
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index b8c6842e0..278eef414 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -119,6 +119,62 @@ domethod(Node *n)
checkwidth(n->type);
}
+typedef struct NodeTypeList NodeTypeList;
+struct NodeTypeList {
+ Node *n;
+ Type *t;
+ NodeTypeList *next;
+};
+
+static NodeTypeList *dntq;
+static NodeTypeList *dntend;
+
+void
+defertypecopy(Node *n, Type *t)
+{
+ NodeTypeList *ntl;
+
+ if(n == N || t == T)
+ return;
+
+ ntl = mal(sizeof *ntl);
+ ntl->n = n;
+ ntl->t = t;
+ ntl->next = nil;
+
+ if(dntq == nil)
+ dntq = ntl;
+ else
+ dntend->next = ntl;
+
+ dntend = ntl;
+}
+
+void
+resumetypecopy(void)
+{
+ NodeTypeList *l;
+
+ for(l=dntq; l; l=l->next)
+ copytype(l->n, l->t);
+}
+
+void
+copytype(Node *n, Type *t)
+{
+ *n->type = *t;
+
+ t = n->type;
+ t->sym = n->sym;
+ t->local = n->local;
+ t->vargen = n->vargen;
+ t->siggen = 0;
+ t->method = nil;
+ t->nod = N;
+ t->printed = 0;
+ t->deferwidth = 0;
+}
+
static void
walkdeftype(Node *n)
{
@@ -141,20 +197,14 @@ walkdeftype(Node *n)
goto ret;
}
- // copy new type and clear fields
- // that don't come along
maplineno = n->type->maplineno;
embedlineno = n->type->embedlineno;
- *n->type = *t;
- t = n->type;
- t->sym = n->sym;
- t->local = n->local;
- t->vargen = n->vargen;
- t->siggen = 0;
- t->method = nil;
- t->nod = N;
- t->printed = 0;
- t->deferwidth = 0;
+
+ // copy new type and clear fields
+ // that don't come along.
+ // anything zeroed here must be zeroed in
+ // typedcl2 too.
+ copytype(n, t);
// double-check use of type as map key.
if(maplineno) {
@@ -197,7 +247,6 @@ Node*
walkdef(Node *n)
{
int lno;
- NodeList *init;
Node *e;
Type *t;
NodeList *l;
@@ -236,7 +285,6 @@ walkdef(Node *n)
if(n->type != T || n->sym == S) // builtin or no name
goto ret;
- init = nil;
switch(n->op) {
default:
fatal("walkdef %O", n->op);
@@ -380,14 +428,13 @@ walkstmt(Node **np)
{
NodeList *init;
NodeList *ll, *rl;
- int cl, lno;
+ int cl;
Node *n, *f;
n = *np;
if(n == N)
return;
- lno = lineno;
setlineno(n);
switch(n->op) {
@@ -1359,7 +1406,7 @@ walkexpr(Node **np, NodeList **init)
case OSTRARRAYBYTE:
// stringtoslicebyte(string) []byte;
- n = mkcall("stringtoslicebyte", n->type, init, n->left);
+ n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING]));
goto ret;
case OSTRARRAYRUNE:
@@ -1788,7 +1835,7 @@ walkprint(Node *nn, NodeList **init, int defer)
on = syslook("printiface", 1);
argtype(on, n->type); // any-1
}
- } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
+ } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
if(defer) {
fmtprint(&fmt, "%%p");
} else {
diff --git a/src/cmd/gofix/doc.go b/src/cmd/gofix/doc.go
index 902fe76f2..a9790e685 100644
--- a/src/cmd/gofix/doc.go
+++ b/src/cmd/gofix/doc.go
@@ -18,6 +18,9 @@ If the named path is a directory, gofix rewrites all .go files in that
directory tree. When gofix rewrites a file, it prints a line to standard
error giving the name of the file and the rewrite applied.
+If the -diff flag is set, no files are rewritten. Instead gofix prints
+the differences a rewrite would introduce.
+
The -r flag restricts the set of rewrites considered to those in the
named list. By default gofix considers all known rewrites. Gofix's
rewrites are idempotent, so that it is safe to apply gofix to updated
@@ -29,6 +32,5 @@ to see them, run gofix -?.
Gofix does not make backup copies of the files that it edits.
Instead, use a version control system's ``diff'' functionality to inspect
the changes that gofix makes before committing them.
-
*/
package documentation
diff --git a/src/cmd/gofix/reflect.go b/src/cmd/gofix/reflect.go
index 74ddb398f..3c8becaef 100644
--- a/src/cmd/gofix/reflect.go
+++ b/src/cmd/gofix/reflect.go
@@ -21,6 +21,7 @@ var reflectFix = fix{
`Adapt code to new reflect API.
http://codereview.appspot.com/4281055
+http://codereview.appspot.com/4433066
`,
}
@@ -279,6 +280,23 @@ func reflectFn(f *ast.File) bool {
fixed = true
})
+ // Rewrite
+ // reflect.Typeof -> reflect.TypeOf,
+ walk(f, func(n interface{}) {
+ sel, ok := n.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+ if isTopName(sel.X, "reflect") && sel.Sel.Name == "Typeof" {
+ sel.Sel.Name = "TypeOf"
+ fixed = true
+ }
+ if isTopName(sel.X, "reflect") && sel.Sel.Name == "NewValue" {
+ sel.Sel.Name = "ValueOf"
+ fixed = true
+ }
+ })
+
return fixed
}
diff --git a/src/cmd/gofix/testdata/reflect.asn1.go.out b/src/cmd/gofix/testdata/reflect.asn1.go.out
index 902635939..f5716f273 100644
--- a/src/cmd/gofix/testdata/reflect.asn1.go.out
+++ b/src/cmd/gofix/testdata/reflect.asn1.go.out
@@ -418,13 +418,13 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type
}
var (
- bitStringType = reflect.Typeof(BitString{})
- objectIdentifierType = reflect.Typeof(ObjectIdentifier{})
- enumeratedType = reflect.Typeof(Enumerated(0))
- flagType = reflect.Typeof(Flag(false))
- timeType = reflect.Typeof(&time.Time{})
- rawValueType = reflect.Typeof(RawValue{})
- rawContentsType = reflect.Typeof(RawContent(nil))
+ bitStringType = reflect.TypeOf(BitString{})
+ objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
+ enumeratedType = reflect.TypeOf(Enumerated(0))
+ flagType = reflect.TypeOf(Flag(false))
+ timeType = reflect.TypeOf(&time.Time{})
+ rawValueType = reflect.TypeOf(RawValue{})
+ rawContentsType = reflect.TypeOf(RawContent(nil))
)
// invalidLength returns true iff offset + length > sliceLength, or if the
@@ -461,7 +461,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
}
result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
offset += t.length
- v.Set(reflect.NewValue(result))
+ v.Set(reflect.ValueOf(result))
return
}
@@ -506,7 +506,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
return
}
if result != nil {
- ifaceValue.Set(reflect.NewValue(result))
+ ifaceValue.Set(reflect.ValueOf(result))
}
return
}
@@ -609,7 +609,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
sliceValue := v
sliceValue.Set(reflect.MakeSlice(sliceValue.Type(), len(newSlice), len(newSlice)))
if err1 == nil {
- reflect.Copy(sliceValue, reflect.NewValue(newSlice))
+ reflect.Copy(sliceValue, reflect.ValueOf(newSlice))
}
err = err1
return
@@ -617,7 +617,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
structValue := v
bs, err1 := parseBitString(innerBytes)
if err1 == nil {
- structValue.Set(reflect.NewValue(bs))
+ structValue.Set(reflect.ValueOf(bs))
}
err = err1
return
@@ -631,7 +631,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
time, err1 = parseGeneralizedTime(innerBytes)
}
if err1 == nil {
- ptrValue.Set(reflect.NewValue(time))
+ ptrValue.Set(reflect.ValueOf(time))
}
err = err1
return
@@ -679,7 +679,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
if structType.NumField() > 0 &&
structType.Field(0).Type == rawContentsType {
bytes := bytes[initOffset:offset]
- val.Field(0).Set(reflect.NewValue(RawContent(bytes)))
+ val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
}
innerOffset := 0
@@ -701,7 +701,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
sliceType := fieldType
if sliceType.Elem().Kind() == reflect.Uint8 {
val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
- reflect.Copy(val, reflect.NewValue(innerBytes))
+ reflect.Copy(val, reflect.ValueOf(innerBytes))
return
}
newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
@@ -806,7 +806,7 @@ func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) {
// UnmarshalWithParams allows field parameters to be specified for the
// top-level element. The form of the params is the same as the field tags.
func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) {
- v := reflect.NewValue(val).Elem()
+ v := reflect.ValueOf(val).Elem()
offset, err := parseField(v, b, 0, parseFieldParameters(params))
if err != nil {
return nil, err
diff --git a/src/cmd/gofix/testdata/reflect.datafmt.go.out b/src/cmd/gofix/testdata/reflect.datafmt.go.out
index 6d816fc2d..bd7f5fd31 100644
--- a/src/cmd/gofix/testdata/reflect.datafmt.go.out
+++ b/src/cmd/gofix/testdata/reflect.datafmt.go.out
@@ -671,7 +671,7 @@ func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) {
go func() {
for _, v := range args {
- fld := reflect.NewValue(v)
+ fld := reflect.ValueOf(v)
if !fld.IsValid() {
errors <- os.NewError("nil argument")
return
diff --git a/src/cmd/gofix/testdata/reflect.decode.go.out b/src/cmd/gofix/testdata/reflect.decode.go.out
index a5fd33912..feeb7b867 100644
--- a/src/cmd/gofix/testdata/reflect.decode.go.out
+++ b/src/cmd/gofix/testdata/reflect.decode.go.out
@@ -122,11 +122,11 @@ func (d *decodeState) unmarshal(v interface{}) (err os.Error) {
}
}()
- rv := reflect.NewValue(v)
+ rv := reflect.ValueOf(v)
pv := rv
if pv.Kind() != reflect.Ptr ||
pv.IsNil() {
- return &InvalidUnmarshalError{reflect.Typeof(v)}
+ return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d.scan.reset()
@@ -314,7 +314,7 @@ func (d *decodeState) array(v reflect.Value) {
iv := v
ok := iv.Kind() == reflect.Interface
if ok {
- iv.Set(reflect.NewValue(d.arrayInterface()))
+ iv.Set(reflect.ValueOf(d.arrayInterface()))
return
}
@@ -410,7 +410,7 @@ func (d *decodeState) object(v reflect.Value) {
// Decoding into nil interface? Switch to non-reflect code.
iv := v
if iv.Kind() == reflect.Interface {
- iv.Set(reflect.NewValue(d.objectInterface()))
+ iv.Set(reflect.ValueOf(d.objectInterface()))
return
}
@@ -423,7 +423,7 @@ func (d *decodeState) object(v reflect.Value) {
case reflect.Map:
// map must have string type
t := v.Type()
- if t.Key() != reflect.Typeof("") {
+ if t.Key() != reflect.TypeOf("") {
d.saveError(&UnmarshalTypeError{"object", v.Type()})
break
}
@@ -514,7 +514,7 @@ func (d *decodeState) object(v reflect.Value) {
// Write value back to map;
// if using struct, subv points into struct already.
if mv.IsValid() {
- mv.SetMapIndex(reflect.NewValue(key), subv)
+ mv.SetMapIndex(reflect.ValueOf(key), subv)
}
// Next token must be , or }.
@@ -570,7 +570,7 @@ func (d *decodeState) literal(v reflect.Value) {
case reflect.Bool:
v.SetBool(value)
case reflect.Interface:
- v.Set(reflect.NewValue(value))
+ v.Set(reflect.ValueOf(value))
}
case '"': // string
@@ -592,11 +592,11 @@ func (d *decodeState) literal(v reflect.Value) {
d.saveError(err)
break
}
- v.Set(reflect.NewValue(b[0:n]))
+ v.Set(reflect.ValueOf(b[0:n]))
case reflect.String:
v.SetString(string(s))
case reflect.Interface:
- v.Set(reflect.NewValue(string(s)))
+ v.Set(reflect.ValueOf(string(s)))
}
default: // number
@@ -613,7 +613,7 @@ func (d *decodeState) literal(v reflect.Value) {
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
break
}
- v.Set(reflect.NewValue(n))
+ v.Set(reflect.ValueOf(n))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.Atoi64(s)
@@ -767,7 +767,7 @@ func (d *decodeState) literalInterface() interface{} {
}
n, err := strconv.Atof64(string(item))
if err != nil {
- d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.Typeof(0.0)})
+ d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
}
return n
}
diff --git a/src/cmd/gofix/testdata/reflect.decoder.go.out b/src/cmd/gofix/testdata/reflect.decoder.go.out
index a631c27a2..170eedb05 100644
--- a/src/cmd/gofix/testdata/reflect.decoder.go.out
+++ b/src/cmd/gofix/testdata/reflect.decoder.go.out
@@ -50,7 +50,7 @@ func (dec *Decoder) recvType(id typeId) {
// Type:
wire := new(wireType)
- dec.decodeValue(tWireType, reflect.NewValue(wire))
+ dec.decodeValue(tWireType, reflect.ValueOf(wire))
if dec.err != nil {
return
}
@@ -161,7 +161,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
if e == nil {
return dec.DecodeValue(reflect.Value{})
}
- value := reflect.NewValue(e)
+ value := reflect.ValueOf(e)
// 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 {
diff --git a/src/cmd/gofix/testdata/reflect.dnsmsg.go.out b/src/cmd/gofix/testdata/reflect.dnsmsg.go.out
index 546e713a0..12e4c34c3 100644
--- a/src/cmd/gofix/testdata/reflect.dnsmsg.go.out
+++ b/src/cmd/gofix/testdata/reflect.dnsmsg.go.out
@@ -430,7 +430,7 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
if off+n > len(msg) {
return len(msg), false
}
- reflect.Copy(reflect.NewValue(msg[off:off+n]), fv)
+ reflect.Copy(reflect.ValueOf(msg[off:off+n]), fv)
off += n
case reflect.String:
// There are multiple string encodings.
@@ -460,7 +460,7 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
}
func structValue(any interface{}) reflect.Value {
- return reflect.NewValue(any).Elem()
+ return reflect.ValueOf(any).Elem()
}
func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
@@ -508,7 +508,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
if off+n > len(msg) {
return len(msg), false
}
- reflect.Copy(fv, reflect.NewValue(msg[off:off+n]))
+ reflect.Copy(fv, reflect.ValueOf(msg[off:off+n]))
off += n
case reflect.String:
var s string
diff --git a/src/cmd/gofix/testdata/reflect.encode.go.out b/src/cmd/gofix/testdata/reflect.encode.go.out
index 8c79a27d4..9a13a75ab 100644
--- a/src/cmd/gofix/testdata/reflect.encode.go.out
+++ b/src/cmd/gofix/testdata/reflect.encode.go.out
@@ -172,7 +172,7 @@ func (e *encodeState) marshal(v interface{}) (err os.Error) {
err = r.(os.Error)
}
}()
- e.reflectValue(reflect.NewValue(v))
+ e.reflectValue(reflect.ValueOf(v))
return nil
}
@@ -180,7 +180,7 @@ func (e *encodeState) error(err os.Error) {
panic(err)
}
-var byteSliceType = reflect.Typeof([]byte(nil))
+var byteSliceType = reflect.TypeOf([]byte(nil))
func (e *encodeState) reflectValue(v reflect.Value) {
if !v.IsValid() {
diff --git a/src/cmd/gofix/testdata/reflect.encoder.go.out b/src/cmd/gofix/testdata/reflect.encoder.go.out
index 928f3b244..781ef6504 100644
--- a/src/cmd/gofix/testdata/reflect.encoder.go.out
+++ b/src/cmd/gofix/testdata/reflect.encoder.go.out
@@ -97,7 +97,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
// Id:
state.encodeInt(-int64(info.id))
// Type:
- enc.encode(state.b, reflect.NewValue(info.wire), wireTypeUserInfo)
+ enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo)
enc.writeMessage(w, state.b)
if enc.err != nil {
return
@@ -162,7 +162,7 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ
// Encode transmits the data item represented by the empty interface value,
// guaranteeing that all necessary type information has been transmitted first.
func (enc *Encoder) Encode(e interface{}) os.Error {
- return enc.EncodeValue(reflect.NewValue(e))
+ return enc.EncodeValue(reflect.ValueOf(e))
}
// sendTypeDescriptor makes sure the remote side knows about this type.
diff --git a/src/cmd/gofix/testdata/reflect.export.go.out b/src/cmd/gofix/testdata/reflect.export.go.out
index 2209f04e8..486a812e2 100644
--- a/src/cmd/gofix/testdata/reflect.export.go.out
+++ b/src/cmd/gofix/testdata/reflect.export.go.out
@@ -111,9 +111,9 @@ func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
// data arrives from the client.
func (client *expClient) run() {
hdr := new(header)
- hdrValue := reflect.NewValue(hdr)
+ hdrValue := reflect.ValueOf(hdr)
req := new(request)
- reqValue := reflect.NewValue(req)
+ reqValue := reflect.ValueOf(req)
error := new(error)
for {
*hdr = header{}
@@ -341,7 +341,7 @@ func (exp *Exporter) Sync(timeout int64) os.Error {
}
func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
- chanType := reflect.Typeof(chT)
+ chanType := reflect.TypeOf(chT)
if chanType.Kind() != reflect.Chan {
return reflect.Value{}, os.ErrorString("not a channel")
}
@@ -359,7 +359,7 @@ func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
return reflect.Value{}, os.ErrorString("to import/export with Recv, must provide chan<-")
}
}
- return reflect.NewValue(chT), nil
+ return reflect.ValueOf(chT), nil
}
// Export exports a channel of a given type and specified direction. The
diff --git a/src/cmd/gofix/testdata/reflect.print.go.out b/src/cmd/gofix/testdata/reflect.print.go.out
index e3dc775cf..079948cca 100644
--- a/src/cmd/gofix/testdata/reflect.print.go.out
+++ b/src/cmd/gofix/testdata/reflect.print.go.out
@@ -260,7 +260,7 @@ func getField(v reflect.Value, i int) reflect.Value {
val := v.Field(i)
if i := val; i.Kind() == reflect.Interface {
if inter := i.Interface(); inter != nil {
- return reflect.NewValue(inter)
+ return reflect.ValueOf(inter)
}
}
return val
@@ -284,7 +284,7 @@ func (p *pp) unknownType(v interface{}) {
return
}
p.buf.WriteByte('?')
- p.buf.WriteString(reflect.Typeof(v).String())
+ p.buf.WriteString(reflect.TypeOf(v).String())
p.buf.WriteByte('?')
}
@@ -296,7 +296,7 @@ func (p *pp) badVerb(verb int, val interface{}) {
if val == nil {
p.buf.Write(nilAngleBytes)
} else {
- p.buf.WriteString(reflect.Typeof(val).String())
+ p.buf.WriteString(reflect.TypeOf(val).String())
p.add('=')
p.printField(val, 'v', false, false, 0)
}
@@ -525,7 +525,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
}
if goSyntax {
p.add('(')
- p.buf.WriteString(reflect.Typeof(field).String())
+ p.buf.WriteString(reflect.TypeOf(field).String())
p.add(')')
p.add('(')
if u == 0 {
@@ -540,10 +540,10 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
}
var (
- intBits = reflect.Typeof(0).Bits()
- floatBits = reflect.Typeof(0.0).Bits()
- complexBits = reflect.Typeof(1i).Bits()
- uintptrBits = reflect.Typeof(uintptr(0)).Bits()
+ intBits = reflect.TypeOf(0).Bits()
+ floatBits = reflect.TypeOf(0.0).Bits()
+ complexBits = reflect.TypeOf(1i).Bits()
+ uintptrBits = reflect.TypeOf(uintptr(0)).Bits()
)
func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) {
@@ -560,10 +560,10 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printField(reflect.Typeof(field).String(), 's', false, false, 0)
+ p.printField(reflect.TypeOf(field).String(), 's', false, false, 0)
return false
case 'p':
- p.fmtPointer(field, reflect.NewValue(field), verb, goSyntax)
+ p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax)
return false
}
// Is it a Formatter?
@@ -651,7 +651,7 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
}
// Need to use reflection
- value := reflect.NewValue(field)
+ value := reflect.ValueOf(field)
BigSwitch:
switch f := value; f.Kind() {
@@ -702,7 +702,7 @@ BigSwitch:
}
case reflect.Struct:
if goSyntax {
- p.buf.WriteString(reflect.Typeof(field).String())
+ p.buf.WriteString(reflect.TypeOf(field).String())
}
p.add('{')
v := f
@@ -728,7 +728,7 @@ BigSwitch:
value := f.Elem()
if !value.IsValid() {
if goSyntax {
- p.buf.WriteString(reflect.Typeof(field).String())
+ p.buf.WriteString(reflect.TypeOf(field).String())
p.buf.Write(nilParenBytes)
} else {
p.buf.Write(nilAngleBytes)
@@ -754,7 +754,7 @@ BigSwitch:
return verb == 's'
}
if goSyntax {
- p.buf.WriteString(reflect.Typeof(field).String())
+ p.buf.WriteString(reflect.TypeOf(field).String())
p.buf.WriteByte('{')
} else {
p.buf.WriteByte('[')
@@ -792,7 +792,7 @@ BigSwitch:
}
if goSyntax {
p.buf.WriteByte('(')
- p.buf.WriteString(reflect.Typeof(field).String())
+ p.buf.WriteString(reflect.TypeOf(field).String())
p.buf.WriteByte(')')
p.buf.WriteByte('(')
if v == 0 {
@@ -913,7 +913,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
for ; fieldnum < len(a); fieldnum++ {
field := a[fieldnum]
if field != nil {
- p.buf.WriteString(reflect.Typeof(field).String())
+ p.buf.WriteString(reflect.TypeOf(field).String())
p.buf.WriteByte('=')
}
p.printField(field, 'v', false, false, 0)
@@ -932,7 +932,7 @@ func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
// always add spaces if we're doing println
field := a[fieldnum]
if fieldnum > 0 {
- isString := field != nil && reflect.Typeof(field).Kind() == reflect.String
+ isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String
if addspace || !isString && !prevString {
p.buf.WriteByte(' ')
}
diff --git a/src/cmd/gofix/testdata/reflect.quick.go.out b/src/cmd/gofix/testdata/reflect.quick.go.out
index 152dbad32..c62305b83 100644
--- a/src/cmd/gofix/testdata/reflect.quick.go.out
+++ b/src/cmd/gofix/testdata/reflect.quick.go.out
@@ -59,39 +59,39 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
switch concrete := t; concrete.Kind() {
case reflect.Bool:
- return reflect.NewValue(rand.Int()&1 == 0), true
+ return reflect.ValueOf(rand.Int()&1 == 0), true
case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Complex64, reflect.Complex128:
switch t.Kind() {
case reflect.Float32:
- return reflect.NewValue(randFloat32(rand)), true
+ return reflect.ValueOf(randFloat32(rand)), true
case reflect.Float64:
- return reflect.NewValue(randFloat64(rand)), true
+ return reflect.ValueOf(randFloat64(rand)), true
case reflect.Complex64:
- return reflect.NewValue(complex(randFloat32(rand), randFloat32(rand))), true
+ return reflect.ValueOf(complex(randFloat32(rand), randFloat32(rand))), true
case reflect.Complex128:
- return reflect.NewValue(complex(randFloat64(rand), randFloat64(rand))), true
+ return reflect.ValueOf(complex(randFloat64(rand), randFloat64(rand))), true
case reflect.Int16:
- return reflect.NewValue(int16(randInt64(rand))), true
+ return reflect.ValueOf(int16(randInt64(rand))), true
case reflect.Int32:
- return reflect.NewValue(int32(randInt64(rand))), true
+ return reflect.ValueOf(int32(randInt64(rand))), true
case reflect.Int64:
- return reflect.NewValue(randInt64(rand)), true
+ return reflect.ValueOf(randInt64(rand)), true
case reflect.Int8:
- return reflect.NewValue(int8(randInt64(rand))), true
+ return reflect.ValueOf(int8(randInt64(rand))), true
case reflect.Int:
- return reflect.NewValue(int(randInt64(rand))), true
+ return reflect.ValueOf(int(randInt64(rand))), true
case reflect.Uint16:
- return reflect.NewValue(uint16(randInt64(rand))), true
+ return reflect.ValueOf(uint16(randInt64(rand))), true
case reflect.Uint32:
- return reflect.NewValue(uint32(randInt64(rand))), true
+ return reflect.ValueOf(uint32(randInt64(rand))), true
case reflect.Uint64:
- return reflect.NewValue(uint64(randInt64(rand))), true
+ return reflect.ValueOf(uint64(randInt64(rand))), true
case reflect.Uint8:
- return reflect.NewValue(uint8(randInt64(rand))), true
+ return reflect.ValueOf(uint8(randInt64(rand))), true
case reflect.Uint:
- return reflect.NewValue(uint(randInt64(rand))), true
+ return reflect.ValueOf(uint(randInt64(rand))), true
case reflect.Uintptr:
- return reflect.NewValue(uintptr(randInt64(rand))), true
+ return reflect.ValueOf(uintptr(randInt64(rand))), true
}
case reflect.Map:
numElems := rand.Intn(complexSize)
@@ -130,7 +130,7 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
for i := 0; i < numChars; i++ {
codePoints[i] = rand.Intn(0x10ffff)
}
- return reflect.NewValue(string(codePoints)), true
+ return reflect.ValueOf(string(codePoints)), true
case reflect.Struct:
s := reflect.Zero(t)
for i := 0; i < s.NumField(); i++ {
@@ -339,7 +339,7 @@ func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand
}
func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) {
- v = reflect.NewValue(f)
+ v = reflect.ValueOf(f)
ok = v.Kind() == reflect.Func
if !ok {
return
diff --git a/src/cmd/gofix/testdata/reflect.read.go.out b/src/cmd/gofix/testdata/reflect.read.go.out
index a3ddb9d4c..554b2a61b 100644
--- a/src/cmd/gofix/testdata/reflect.read.go.out
+++ b/src/cmd/gofix/testdata/reflect.read.go.out
@@ -139,7 +139,7 @@ import (
// to a freshly allocated value and then mapping the element to that value.
//
func Unmarshal(r io.Reader, val interface{}) os.Error {
- v := reflect.NewValue(val)
+ v := reflect.ValueOf(val)
if v.Kind() != reflect.Ptr {
return os.NewError("non-pointer passed to Unmarshal")
}
@@ -176,7 +176,7 @@ func (e *TagPathError) String() string {
// Passing a nil start element indicates that Unmarshal should
// read the token stream to find the start element.
func (p *Parser) Unmarshal(val interface{}, start *StartElement) os.Error {
- v := reflect.NewValue(val)
+ v := reflect.ValueOf(val)
if v.Kind() != reflect.Ptr {
return os.NewError("non-pointer passed to Unmarshal")
}
@@ -280,7 +280,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
case reflect.Struct:
if _, ok := v.Interface().(Name); ok {
- v.Set(reflect.NewValue(start.Name))
+ v.Set(reflect.ValueOf(start.Name))
break
}
@@ -316,7 +316,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
if _, ok := v.Interface().(Name); !ok {
return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name")
}
- v.Set(reflect.NewValue(start.Name))
+ v.Set(reflect.ValueOf(start.Name))
}
// Assign attributes.
@@ -508,21 +508,21 @@ Loop:
case reflect.String:
t.SetString(string(data))
case reflect.Slice:
- t.Set(reflect.NewValue(data))
+ t.Set(reflect.ValueOf(data))
}
switch t := saveComment; t.Kind() {
case reflect.String:
t.SetString(string(comment))
case reflect.Slice:
- t.Set(reflect.NewValue(comment))
+ t.Set(reflect.ValueOf(comment))
}
switch t := saveXML; t.Kind() {
case reflect.String:
t.SetString(string(saveXMLData))
case reflect.Slice:
- t.Set(reflect.NewValue(saveXMLData))
+ t.Set(reflect.ValueOf(saveXMLData))
}
return nil
diff --git a/src/cmd/gofix/testdata/reflect.scan.go.out b/src/cmd/gofix/testdata/reflect.scan.go.out
index b1b3975e2..42bc52c92 100644
--- a/src/cmd/gofix/testdata/reflect.scan.go.out
+++ b/src/cmd/gofix/testdata/reflect.scan.go.out
@@ -423,7 +423,7 @@ func (s *ss) token(skipSpace bool, f func(int) bool) []byte {
// typeError indicates that the type of the operand did not match the format
func (s *ss) typeError(field interface{}, expected string) {
- s.errorString("expected field of type pointer to " + expected + "; found " + reflect.Typeof(field).String())
+ s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String())
}
var complexError = os.ErrorString("syntax error scanning complex number")
@@ -908,7 +908,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
// If we scanned to bytes, the slice would point at the buffer.
*v = []byte(s.convertString(verb))
default:
- val := reflect.NewValue(v)
+ val := reflect.ValueOf(v)
ptr := val
if ptr.Kind() != reflect.Ptr {
s.errorString("Scan: type not a pointer: " + val.Type().String())
diff --git a/src/cmd/gofix/testdata/reflect.script.go.out b/src/cmd/gofix/testdata/reflect.script.go.out
index b18018497..bc5a6a41d 100644
--- a/src/cmd/gofix/testdata/reflect.script.go.out
+++ b/src/cmd/gofix/testdata/reflect.script.go.out
@@ -134,19 +134,19 @@ type empty struct {
}
func newEmptyInterface(e empty) reflect.Value {
- return reflect.NewValue(e).Field(0)
+ return reflect.ValueOf(e).Field(0)
}
func (s Send) send() {
// With reflect.ChanValue.Send, we must match the types exactly. So, if
// s.Channel is a chan interface{} we convert s.Value to an interface{}
// first.
- c := reflect.NewValue(s.Channel)
+ c := reflect.ValueOf(s.Channel)
var v reflect.Value
if iface := c.Type().Elem(); iface.Kind() == reflect.Interface && iface.NumMethod() == 0 {
v = newEmptyInterface(empty{s.Value})
} else {
- v = reflect.NewValue(s.Value)
+ v = reflect.ValueOf(s.Value)
}
c.Send(v)
}
@@ -162,7 +162,7 @@ func (s Close) getSend() sendAction { return s }
func (s Close) getChannel() interface{} { return s.Channel }
-func (s Close) send() { reflect.NewValue(s.Channel).Close() }
+func (s Close) send() { reflect.ValueOf(s.Channel).Close() }
// A ReceivedUnexpected error results if no active Events match a value
// received from a channel.
@@ -278,7 +278,7 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
continue
}
c := event.action.getChannel()
- if reflect.NewValue(c).Kind() != reflect.Chan {
+ if reflect.ValueOf(c).Kind() != reflect.Chan {
return nil, SetupError("one of the channel values is not a channel")
}
@@ -303,7 +303,7 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
// channel repeatedly, wrapping them up as either a channelRecv or
// channelClosed structure, and forwards them to the multiplex channel.
func recvValues(multiplex chan<- interface{}, channel interface{}) {
- c := reflect.NewValue(channel)
+ c := reflect.ValueOf(channel)
for {
v, ok := c.Recv()
diff --git a/src/cmd/gofix/testdata/reflect.template.go.out b/src/cmd/gofix/testdata/reflect.template.go.out
index 28872dbee..c36288455 100644
--- a/src/cmd/gofix/testdata/reflect.template.go.out
+++ b/src/cmd/gofix/testdata/reflect.template.go.out
@@ -646,7 +646,7 @@ func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value
}
return av.FieldByName(name)
case reflect.Map:
- if v := av.MapIndex(reflect.NewValue(name)); v.IsValid() {
+ if v := av.MapIndex(reflect.ValueOf(name)); v.IsValid() {
return v
}
return reflect.Zero(typ.Elem())
@@ -797,7 +797,7 @@ func (t *Template) executeElement(i int, st *state) int {
return elem.end
}
e := t.elems.At(i)
- t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.NewValue(e).Interface(), e)
+ t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.ValueOf(e).Interface(), e)
return 0
}
@@ -980,7 +980,7 @@ func (t *Template) ParseFile(filename string) (err os.Error) {
// generating output to wr.
func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) {
// Extract the driver data.
- val := reflect.NewValue(data)
+ val := reflect.ValueOf(data)
defer checkError(&err)
t.p = 0
t.execute(0, t.elems.Len(), &state{parent: nil, data: val, wr: wr})
diff --git a/src/cmd/gofix/testdata/reflect.type.go.out b/src/cmd/gofix/testdata/reflect.type.go.out
index 8fd174841..a39b074fe 100644
--- a/src/cmd/gofix/testdata/reflect.type.go.out
+++ b/src/cmd/gofix/testdata/reflect.type.go.out
@@ -243,18 +243,18 @@ var (
)
// Predefined because it's needed by the Decoder
-var tWireType = mustGetTypeInfo(reflect.Typeof(wireType{})).id
+var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
func init() {
// Some magic numbers to make sure there are no surprises.
checkId(16, tWireType)
- checkId(17, mustGetTypeInfo(reflect.Typeof(arrayType{})).id)
- checkId(18, mustGetTypeInfo(reflect.Typeof(CommonType{})).id)
- checkId(19, mustGetTypeInfo(reflect.Typeof(sliceType{})).id)
- checkId(20, mustGetTypeInfo(reflect.Typeof(structType{})).id)
- checkId(21, mustGetTypeInfo(reflect.Typeof(fieldType{})).id)
- checkId(23, mustGetTypeInfo(reflect.Typeof(mapType{})).id)
+ checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
+ checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
+ checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
+ checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
+ checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
+ checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
builtinIdToType = make(map[typeId]gobType)
for k, v := range idToType {
@@ -268,7 +268,7 @@ func init() {
}
nextId = firstUserId
registerBasics()
- wireTypeUserInfo = userType(reflect.Typeof((*wireType)(nil)))
+ wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
}
// Array type
@@ -569,7 +569,7 @@ func checkId(want, got typeId) {
// used for building the basic types; called only from init(). the incoming
// interface always refers to a pointer.
func bootstrapType(name string, e interface{}, expect typeId) typeId {
- rt := reflect.Typeof(e).Elem()
+ rt := reflect.TypeOf(e).Elem()
_, present := types[rt]
if present {
panic("bootstrap type already present: " + name + ", " + rt.String())
@@ -723,7 +723,7 @@ func RegisterName(name string, value interface{}) {
// reserved for nil
panic("attempt to register empty name")
}
- base := userType(reflect.Typeof(value)).base
+ base := userType(reflect.TypeOf(value)).base
// Check for incompatible duplicates.
if t, ok := nameToConcreteType[name]; ok && t != base {
panic("gob: registering duplicate types for " + name)
@@ -732,7 +732,7 @@ func RegisterName(name string, value interface{}) {
panic("gob: registering duplicate names for " + base.String())
}
// Store the name and type provided by the user....
- nameToConcreteType[name] = reflect.Typeof(value)
+ nameToConcreteType[name] = reflect.TypeOf(value)
// but the flattened type in the type table, since that's what decode needs.
concreteTypeToName[base] = name
}
@@ -745,7 +745,7 @@ func RegisterName(name string, value interface{}) {
// between types and names is not a bijection.
func Register(value interface{}) {
// Default to printed representation for unnamed types
- rt := reflect.Typeof(value)
+ rt := reflect.TypeOf(value)
name := rt.String()
// But for named types (or pointers to them), qualify with import path.
diff --git a/src/cmd/gofix/typecheck.go b/src/cmd/gofix/typecheck.go
index d565e7b4b..2d81b9710 100644
--- a/src/cmd/gofix/typecheck.go
+++ b/src/cmd/gofix/typecheck.go
@@ -259,7 +259,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
if n == nil {
return
}
- if false && reflect.Typeof(n).Kind() == reflect.Ptr { // debugging trace
+ if false && reflect.TypeOf(n).Kind() == reflect.Ptr { // debugging trace
defer func() {
if t := typeof[n]; t != "" {
pos := fset.Position(n.(ast.Node).Pos())
@@ -375,6 +375,11 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
typeof[n] = gofmt(n.Args[0])
return
}
+ // new(T) has type *T
+ if isTopName(n.Fun, "new") && len(n.Args) == 1 {
+ typeof[n] = "*" + gofmt(n.Args[0])
+ return
+ }
// Otherwise, use type of function to determine arguments.
t := typeof[n.Fun]
in, out := splitFunc(t)
diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go
index e44030eee..1373b2657 100644
--- a/src/cmd/gofmt/doc.go
+++ b/src/cmd/gofmt/doc.go
@@ -8,29 +8,37 @@ Gofmt formats Go programs.
Without an explicit path, it processes the standard input. Given a file,
it operates on that file; given a directory, it operates on all .go files in
that directory, recursively. (Files starting with a period are ignored.)
+By default, gofmt prints the reformatted sources to standard output.
Usage:
gofmt [flags] [path ...]
The flags are:
+ -d
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different than gofmt's, print diffs
+ to standard output.
-l
- just list files whose formatting differs from gofmt's;
- generate no other output unless -w is also set.
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different from gofmt's, print its name
+ to standard output.
-r rule
- apply the rewrite rule to the source before reformatting.
+ Apply the rewrite rule to the source before reformatting.
-s
- try to simplify code (after applying the rewrite rule, if any).
+ Try to simplify code (after applying the rewrite rule, if any).
-w
- if set, overwrite each input file with its output.
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different from gofmt's, overwrite it
+ with gofmt's version.
-comments=true
- print comments; if false, all comments are elided from the output.
+ Print comments; if false, all comments are elided from the output.
-spaces
- align with spaces instead of tabs.
+ Align with spaces instead of tabs.
-tabindent
- indent with tabs independent of -spaces.
+ Indent with tabs independent of -spaces.
-tabwidth=8
- tab width in spaces.
+ Tab width in spaces.
The rewrite rule specified with the -r flag must be a string of the form:
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index ce274aa21..5dd801d90 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -6,6 +6,7 @@ package main
import (
"bytes"
+ "exec"
"flag"
"fmt"
"go/ast"
@@ -28,6 +29,7 @@ var (
write = flag.Bool("w", false, "write result to (source) file instead of stdout")
rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
simplifyAST = flag.Bool("s", false, "simplify code")
+ doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
// layout control
comments = flag.Bool("comments", true, "print comments")
@@ -134,9 +136,17 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error {
return err
}
}
+ if *doDiff {
+ data, err := diff(src, res)
+ if err != nil {
+ return fmt.Errorf("computing diff: %s", err)
+ }
+ fmt.Printf("diff %s gofmt/%s\n", filename, filename)
+ out.Write(data)
+ }
}
- if !*list && !*write {
+ if !*list && !*write && !*doDiff {
_, err = out.Write(res)
}
@@ -230,3 +240,37 @@ func gofmtMain() {
}
}
}
+
+
+func diff(b1, b2 []byte) (data []byte, err os.Error) {
+ f1, err := ioutil.TempFile("", "gofmt")
+ if err != nil {
+ return nil, err
+ }
+ defer os.Remove(f1.Name())
+ defer f1.Close()
+
+ f2, err := ioutil.TempFile("", "gofmt")
+ if err != nil {
+ return nil, err
+ }
+ defer os.Remove(f2.Name())
+ defer f2.Close()
+
+ f1.Write(b1)
+ f2.Write(b2)
+
+ diffcmd, err := exec.LookPath("diff")
+ if err != nil {
+ return nil, err
+ }
+
+ c, err := exec.Run(diffcmd, []string{"diff", "-u", f1.Name(), f2.Name()},
+ nil, "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
+ if err != nil {
+ return nil, err
+ }
+ defer c.Close()
+
+ return ioutil.ReadAll(c.Stdout)
+}
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 4ec94e293..a72530307 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -71,6 +71,7 @@ var tests = []struct {
{".", "gofmt_test.go", "gofmt_test.go", ""},
{"testdata", "composites.input", "composites.golden", "-s"},
{"testdata", "rewrite1.input", "rewrite1.golden", "-r=Foo->Bar"},
+ {"testdata", "rewrite2.input", "rewrite2.golden", "-r=int->bool"},
}
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index 93643dced..4c24282f3 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -19,6 +19,7 @@ import (
func initRewrite() {
if *rewriteRule == "" {
+ rewrite = nil // disable any previous rewrite
return
}
f := strings.Split(*rewriteRule, "->", -1)
@@ -59,26 +60,34 @@ func dump(msg string, val reflect.Value) {
// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
m := make(map[string]reflect.Value)
- pat := reflect.NewValue(pattern)
- repl := reflect.NewValue(replace)
+ pat := reflect.ValueOf(pattern)
+ repl := reflect.ValueOf(replace)
var f func(val reflect.Value) reflect.Value // f is recursive
f = func(val reflect.Value) reflect.Value {
+ // don't bother if val is invalid to start with
+ if !val.IsValid() {
+ return reflect.Value{}
+ }
for k := range m {
m[k] = reflect.Value{}, false
}
val = apply(f, val)
if match(m, pat, val) {
- val = subst(m, repl, reflect.NewValue(val.Interface().(ast.Node).Pos()))
+ val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
}
return val
}
- return apply(f, reflect.NewValue(p)).Interface().(*ast.File)
+ return apply(f, reflect.ValueOf(p)).Interface().(*ast.File)
}
// setValue is a wrapper for x.SetValue(y); it protects
// the caller from panics if x cannot be changed to y.
func setValue(x, y reflect.Value) {
+ // don't bother if y is invalid to start with
+ if !y.IsValid() {
+ return
+ }
defer func() {
if x := recover(); x != nil {
if s, ok := x.(string); ok && strings.HasPrefix(s, "type mismatch") {
@@ -94,11 +103,13 @@ func setValue(x, y reflect.Value) {
// Values/types for special cases.
var (
- objectPtrNil = reflect.NewValue((*ast.Object)(nil))
+ objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+ scopePtrNil = reflect.ValueOf((*ast.Scope)(nil))
- identType = reflect.Typeof((*ast.Ident)(nil))
- objectPtrType = reflect.Typeof((*ast.Object)(nil))
- positionType = reflect.Typeof(token.NoPos)
+ identType = reflect.TypeOf((*ast.Ident)(nil))
+ objectPtrType = reflect.TypeOf((*ast.Object)(nil))
+ positionType = reflect.TypeOf(token.NoPos)
+ scopePtrType = reflect.TypeOf((*ast.Scope)(nil))
)
@@ -115,6 +126,12 @@ func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value
return objectPtrNil
}
+ // similarly for scopes: they are likely incorrect after a rewrite;
+ // replace them with nil
+ if val.Type() == scopePtrType {
+ return scopePtrNil
+ }
+
switch v := reflect.Indirect(val); v.Kind() {
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
@@ -259,21 +276,21 @@ func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value)
return v
case reflect.Struct:
- v := reflect.Zero(p.Type())
+ v := reflect.New(p.Type()).Elem()
for i := 0; i < p.NumField(); i++ {
v.Field(i).Set(subst(m, p.Field(i), pos))
}
return v
case reflect.Ptr:
- v := reflect.Zero(p.Type())
+ v := reflect.New(p.Type()).Elem()
if elem := p.Elem(); elem.IsValid() {
v.Set(subst(m, elem, pos).Addr())
}
return v
case reflect.Interface:
- v := reflect.Zero(p.Type())
+ v := reflect.New(p.Type()).Elem()
if elem := p.Elem(); elem.IsValid() {
v.Set(subst(m, elem, pos))
}
diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go
index bcc67c4a6..40a9f8f17 100644
--- a/src/cmd/gofmt/simplify.go
+++ b/src/cmd/gofmt/simplify.go
@@ -26,7 +26,7 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
}
if eltType != nil {
- typ := reflect.NewValue(eltType)
+ typ := reflect.ValueOf(eltType)
for _, x := range outer.Elts {
// look at value of indexed/named elements
if t, ok := x.(*ast.KeyValueExpr); ok {
@@ -37,7 +37,7 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
// matches the outer literal's element type exactly, the inner
// literal type may be omitted
if inner, ok := x.(*ast.CompositeLit); ok {
- if match(nil, typ, reflect.NewValue(inner.Type)) {
+ if match(nil, typ, reflect.ValueOf(inner.Type)) {
inner.Type = nil
}
}
diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh
index 3340c48f0..99ec76932 100755
--- a/src/cmd/gofmt/test.sh
+++ b/src/cmd/gofmt/test.sh
@@ -36,7 +36,7 @@ apply1() {
# the following files are skipped because they are test cases
# for syntax errors and thus won't parse in the first place:
case `basename "$F"` in
- func3.go | const2.go | char_lit1.go | \
+ func3.go | const2.go | char_lit1.go | blank1.go | \
bug014.go | bug050.go | bug068.go | bug083.go | bug088.go | \
bug106.go | bug121.go | bug125.go | bug133.go | bug160.go | \
bug163.go | bug166.go | bug169.go | bug217.go | bug222.go | \
diff --git a/src/cmd/gofmt/testdata/rewrite1.golden b/src/cmd/gofmt/testdata/rewrite1.golden
index 3f909ff4a..d9beb3705 100644
--- a/src/cmd/gofmt/testdata/rewrite1.golden
+++ b/src/cmd/gofmt/testdata/rewrite1.golden
@@ -1,3 +1,7 @@
+// 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
type Bar int
diff --git a/src/cmd/gofmt/testdata/rewrite1.input b/src/cmd/gofmt/testdata/rewrite1.input
index 1f10e3601..bdb894320 100644
--- a/src/cmd/gofmt/testdata/rewrite1.input
+++ b/src/cmd/gofmt/testdata/rewrite1.input
@@ -1,3 +1,7 @@
+// 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
type Foo int
diff --git a/src/cmd/gofmt/testdata/rewrite2.golden b/src/cmd/gofmt/testdata/rewrite2.golden
new file mode 100644
index 000000000..64c67ffa6
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite2.golden
@@ -0,0 +1,10 @@
+// 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 p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []bool {}
diff --git a/src/cmd/gofmt/testdata/rewrite2.input b/src/cmd/gofmt/testdata/rewrite2.input
new file mode 100644
index 000000000..21171447a
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite2.input
@@ -0,0 +1,10 @@
+// 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 p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []int {}
diff --git a/src/cmd/goinstall/Makefile b/src/cmd/goinstall/Makefile
index aaf202ee7..202797cd5 100644
--- a/src/cmd/goinstall/Makefile
+++ b/src/cmd/goinstall/Makefile
@@ -10,6 +10,7 @@ GOFILES=\
main.go\
make.go\
parse.go\
+ path.go\
syslist.go\
CLEANFILES+=syslist.go
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go
index 88befc0dc..7dad596ab 100644
--- a/src/cmd/goinstall/download.go
+++ b/src/cmd/goinstall/download.go
@@ -37,15 +37,15 @@ var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z
var 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_.\-/]+)?$`)
// download checks out or updates pkg from the remote server.
-func download(pkg string) (string, os.Error) {
+func download(pkg, srcDir string) os.Error {
if strings.Contains(pkg, "..") {
- return "", os.ErrorString("invalid path (contains ..)")
+ return os.ErrorString("invalid path (contains ..)")
}
if m := bitbucket.FindStringSubmatch(pkg); m != nil {
- if err := vcsCheckout(&hg, m[1], "http://"+m[1], m[1]); err != nil {
- return "", err
+ if err := vcsCheckout(&hg, srcDir, m[1], "http://"+m[1], m[1]); err != nil {
+ return err
}
- return root + pkg, nil
+ return nil
}
if m := googlecode.FindStringSubmatch(pkg); m != nil {
var v *vcs
@@ -58,29 +58,29 @@ func download(pkg string) (string, os.Error) {
// regexp only allows hg, svn to get through
panic("missing case in download: " + pkg)
}
- if err := vcsCheckout(v, m[1], "https://"+m[1], m[1]); err != nil {
- return "", err
+ if err := vcsCheckout(v, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
+ return err
}
- return root + pkg, nil
+ return nil
}
if m := github.FindStringSubmatch(pkg); m != nil {
if strings.HasSuffix(m[1], ".git") {
- return "", os.ErrorString("repository " + pkg + " should not have .git suffix")
+ return os.ErrorString("repository " + pkg + " should not have .git suffix")
}
- if err := vcsCheckout(&git, m[1], "http://"+m[1]+".git", m[1]); err != nil {
- return "", err
+ if err := vcsCheckout(&git, srcDir, m[1], "http://"+m[1]+".git", m[1]); err != nil {
+ return err
}
- return root + pkg, nil
+ return nil
}
if m := launchpad.FindStringSubmatch(pkg); m != nil {
// Either lp.net/<project>[/<series>[/<path>]]
// or lp.net/~<user or team>/<project>/<branch>[/<path>]
- if err := vcsCheckout(&bzr, m[1], "https://"+m[1], m[1]); err != nil {
- return "", err
+ if err := vcsCheckout(&bzr, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
+ return err
}
- return root + pkg, nil
+ return nil
}
- return "", os.ErrorString("unknown repository: " + pkg)
+ return os.ErrorString("unknown repository: " + pkg)
}
// a vcs represents a version control system
@@ -172,8 +172,8 @@ func (v *vcs) updateRepo(dst string) os.Error {
// 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, pkgprefix, repo, dashpath string) os.Error {
- dst := filepath.Join(root, filepath.FromSlash(pkgprefix))
+func vcsCheckout(vcs *vcs, srcDir, pkgprefix, repo, dashpath string) 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)
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index 8fec8e312..6cd92907a 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -150,6 +150,7 @@ func install(pkg, parent string) {
// Check whether package is local or remote.
// If remote, download or update it.
var dir string
+ proot := gopath[0] // default to GOROOT
local := false
if strings.HasPrefix(pkg, "http://") {
fmt.Fprintf(os.Stderr, "%s: %s: 'http://' used in remote path, try '%s'\n", argv0, pkg, pkg[7:])
@@ -163,8 +164,9 @@ func install(pkg, parent string) {
dir = filepath.Join(root, filepath.FromSlash(pkg))
local = true
} else {
- var err os.Error
- dir, err = download(pkg)
+ proot = findPkgroot(pkg)
+ err := download(pkg, proot.srcDir())
+ dir = filepath.Join(proot.srcDir(), pkg)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
errors = true
@@ -192,18 +194,11 @@ func install(pkg, parent string) {
install(p, pkg)
}
}
- if dirInfo.pkgName == "main" {
- if !errors {
- fmt.Fprintf(os.Stderr, "%s: %s's dependencies are installed.\n", argv0, pkg)
- }
- errors = true
- visit[pkg] = done
- return
- }
// Install this package.
if !errors {
- if err := domake(dir, pkg, local); err != nil {
+ isCmd := dirInfo.pkgName == "main"
+ if err := domake(dir, pkg, proot, local, isCmd); err != nil {
fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
errors = true
} else if !local && *logPkgs {
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
index ceb119e5a..b2ca82b46 100644
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -9,6 +9,7 @@ package main
import (
"bytes"
"os"
+ "path/filepath"
"template"
)
@@ -17,7 +18,7 @@ import (
// For non-local packages or packages without Makefiles,
// domake generates a standard Makefile and passes it
// to make on standard input.
-func domake(dir, pkg string, local bool) (err os.Error) {
+func domake(dir, pkg string, root *pkgroot, local, isCmd bool) (err os.Error) {
needMakefile := true
if local {
_, err := os.Stat(dir + "/Makefile")
@@ -28,7 +29,7 @@ func domake(dir, pkg string, local bool) (err os.Error) {
cmd := []string{"gomake"}
var makefile []byte
if needMakefile {
- if makefile, err = makeMakefile(dir, pkg); err != nil {
+ if makefile, err = makeMakefile(dir, pkg, root, isCmd); err != nil {
return err
}
cmd = append(cmd, "-f-")
@@ -43,11 +44,26 @@ func domake(dir, pkg string, local 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) ([]byte, os.Error) {
+func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error) {
if !safeName(pkg) {
return nil, os.ErrorString("unsafe name: " + pkg)
}
- dirInfo, err := scanDir(dir, false)
+ targ := pkg
+ targDir := root.pkgDir()
+ if isCmd {
+ // use the last part of the package name only
+ _, targ = filepath.Split(pkg)
+ // if building the working dir use the directory name
+ if targ == "." {
+ d, err := filepath.Abs(dir)
+ if err != nil {
+ return nil, os.NewError("finding path: " + err.String())
+ }
+ _, targ = filepath.Split(d)
+ }
+ targDir = root.binDir()
+ }
+ dirInfo, err := scanDir(dir, isCmd)
if err != nil {
return nil, err
}
@@ -94,7 +110,10 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
}
var buf bytes.Buffer
- md := makedata{pkg, goFiles, oFiles, cgoFiles, cgoOFiles}
+ md := makedata{targ, targDir, "pkg", goFiles, oFiles, cgoFiles, cgoOFiles, imports}
+ if isCmd {
+ md.Type = "cmd"
+ }
if err := makefileTemplate.Execute(&buf, &md); err != nil {
return nil, err
}
@@ -104,6 +123,9 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
func safeName(s string) bool {
+ if s == "" {
+ return false
+ }
for i := 0; i < len(s); i++ {
if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
return false
@@ -114,17 +136,21 @@ func safeName(s string) bool {
// makedata is the data type for the makefileTemplate.
type makedata struct {
- Pkg string // package import path
+ Targ string // build target
+ TargDir string // build target directory
+ Type string // build type: "pkg" or "cmd"
GoFiles []string // list of non-cgo .go files
OFiles []string // list of .$O files
CgoFiles []string // list of cgo .go files
CgoOFiles []string // list of cgo .o files, without extension
+ Imports []string // gc/ld import paths
}
var makefileTemplate = template.MustParse(`
include $(GOROOT)/src/Make.inc
-TARG={Pkg}
+TARG={Targ}
+TARGDIR={TargDir}
{.section GoFiles}
GOFILES=\
@@ -154,6 +180,9 @@ CGO_OFILES=\
{.end}
{.end}
-include $(GOROOT)/src/Make.pkg
+GCIMPORTS={.repeated section Imports}-I "{@}" {.end}
+LDIMPORTS={.repeated section Imports}-L "{@}" {.end}
+
+include $(GOROOT)/src/Make.{Type}
`,
nil)
diff --git a/src/cmd/goinstall/parse.go b/src/cmd/goinstall/parse.go
index 0e617903c..a4bb761f2 100644
--- a/src/cmd/goinstall/parse.go
+++ b/src/cmd/goinstall/parse.go
@@ -88,6 +88,9 @@ func scanDir(dir string, allowMain bool) (info *dirInfo, err os.Error) {
if s == "main" && !allowMain {
continue
}
+ if s == "documentation" {
+ continue
+ }
if pkgName == "" {
pkgName = s
} else if pkgName != s {
diff --git a/src/cmd/goinstall/path.go b/src/cmd/goinstall/path.go
new file mode 100644
index 000000000..1153e0471
--- /dev/null
+++ b/src/cmd/goinstall/path.go
@@ -0,0 +1,117 @@
+// 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 (
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+)
+
+var (
+ gopath []*pkgroot
+ imports []string
+ defaultRoot *pkgroot // default root for remote packages
+)
+
+// set up gopath: parse and validate GOROOT and GOPATH variables
+func init() {
+ 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
+}
+
+// findPkgroot searches each of the gopath roots
+// for the source code for the given import path.
+func findPkgroot(importPath string) *pkgroot {
+ for _, r := range gopath {
+ if r.hasSrcDir(importPath) {
+ return r
+ }
+ }
+ return defaultRoot
+}
diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c
index dc3899f37..017978ced 100644
--- a/src/cmd/gopack/ar.c
+++ b/src/cmd/gopack/ar.c
@@ -144,6 +144,7 @@ char *file; /* current file or member being worked on */
Biobuf bout;
Biobuf bar;
char *prefix;
+int pkgdefsafe; /* was __.PKGDEF marked safe? */
void arcopy(Biobuf*, Arfile*, Armember*);
int arcreate(char*);
@@ -177,6 +178,7 @@ void scanpkg(Biobuf*, long);
void select(int*, long);
void setcom(void(*)(char*, int, char**));
void skip(Biobuf*, vlong);
+void checksafe(Biobuf*, vlong);
int symcomp(void*, void*);
void trim(char*, char*, int);
void usage(void);
@@ -322,9 +324,9 @@ rcmd(char *arname, int count, char **files)
skip(&bar, bp->size);
continue;
}
- /* pitch pkgdef file */
+ /* pitch pkgdef file but remember whether it was marked safe */
if (gflag && strcmp(file, pkgdef) == 0) {
- skip(&bar, bp->size);
+ checksafe(&bar, bp->size);
continue;
}
/*
@@ -773,7 +775,8 @@ scanpkg(Biobuf *b, long size)
goto foundstart;
}
// fprint(2, "gopack: warning: no package import section in %s\n", file);
- safe = 0; // non-Go file (C or assembly)
+ if(b != &bar || !pkgdefsafe)
+ safe = 0; // non-Go file (C or assembly)
return;
foundstart:
@@ -807,7 +810,7 @@ foundstart:
pkgname = armalloc(pkg - data + 1);
memmove(pkgname, data, pkg - data);
pkgname[pkg-data] = '\0';
- if(strcmp(pkg, " safe\n") != 0)
+ if(strcmp(pkg, " safe\n") != 0 && (b != &bar || !pkgdefsafe))
safe = 0;
start = Boffset(b); // after package statement
first = 0;
@@ -1094,6 +1097,36 @@ skip(Biobuf *bp, vlong len)
Bseek(bp, len, 1);
}
+void
+checksafe(Biobuf *bp, vlong len)
+{
+ char *p;
+ vlong end;
+
+ if (len & 01)
+ len++;
+ end = Boffset(bp) + len;
+
+ p = Brdline(bp, '\n');
+ if(p == nil || strncmp(p, "go object ", 10) != 0)
+ goto done;
+ for(;;) {
+ p = Brdline(bp, '\n');
+ if(p == nil || Boffset(bp) >= end)
+ goto done;
+ if(strncmp(p, "$$\n", 3) == 0)
+ break;
+ }
+ p = Brdline(bp, '\n');
+ if(p == nil || Boffset(bp) > end)
+ goto done;
+ if(Blinelen(bp) > 8+6 && strncmp(p, "package ", 8) == 0 && strncmp(p+Blinelen(bp)-6, " safe\n", 6) == 0)
+ pkgdefsafe = 1;
+
+done:
+ Bseek(bp, end, 0);
+}
+
/*
* Stream the three temp files to an archive
*/
@@ -1676,6 +1709,10 @@ arread_cutprefix(Biobuf *b, Armember *bp)
offset = o;
}
}
+ } else {
+ // didn't find the whole prefix.
+ // give up and let it emit the entire name.
+ inprefix = nil;
}
// copy instructions
diff --git a/src/cmd/gotest/gotest.go b/src/cmd/gotest/gotest.go
index 138216e68..a7ba8dd11 100644
--- a/src/cmd/gotest/gotest.go
+++ b/src/cmd/gotest/gotest.go
@@ -16,6 +16,7 @@ import (
"path/filepath"
"runtime"
"strings"
+ "time"
"unicode"
"utf8"
)
@@ -51,6 +52,13 @@ var (
xFlag bool
)
+// elapsed returns time elapsed since gotest started.
+func elapsed() float64 {
+ return float64(time.Nanoseconds()-start) / 1e9
+}
+
+var start = time.Nanoseconds()
+
// File represents a file that contains tests.
type File struct {
name string
@@ -80,6 +88,9 @@ func main() {
if !cFlag {
runTestWithArgs("./" + O + ".out")
}
+ if xFlag {
+ fmt.Printf("gotest %.2fs: done\n", elapsed())
+ }
}
// needMakefile tests that we have a Makefile in this directory.
@@ -119,7 +130,10 @@ func setEnvironment() {
// Basic environment.
GOROOT = runtime.GOROOT()
addEnv("GOROOT", GOROOT)
- GOARCH = runtime.GOARCH
+ GOARCH = os.Getenv("GOARCH")
+ if GOARCH == "" {
+ GOARCH = runtime.GOARCH
+ }
addEnv("GOARCH", GOARCH)
O = theChar[GOARCH]
if O == "" {
@@ -254,7 +268,12 @@ func runTestWithArgs(binary string) {
// retrieve standard output.
func doRun(argv []string, returnStdout bool) string {
if xFlag {
- fmt.Printf("gotest: %s\n", strings.Join(argv, " "))
+ fmt.Printf("gotest %.2fs: %s\n", elapsed(), strings.Join(argv, " "))
+ t := -time.Nanoseconds()
+ defer func() {
+ t += time.Nanoseconds()
+ fmt.Printf(" [+%.2fs]\n", float64(t)/1e9)
+ }()
}
command := argv[0]
if runtime.GOOS == "windows" && command == "gomake" {
@@ -266,7 +285,7 @@ func doRun(argv []string, returnStdout bool) string {
}
cmd += `"` + v + `"`
}
- argv = []string{"cmd", "/c", "sh", "-c", cmd}
+ argv = []string{"sh", "-c", cmd}
}
var err os.Error
argv[0], err = exec.LookPath(argv[0])
@@ -359,7 +378,7 @@ func writeTestmainGo() {
fmt.Fprintf(b, "import %q\n", "./_xtest_")
}
fmt.Fprintf(b, "import %q\n", "testing")
- fmt.Fprintf(b, "import __os__ %q\n", "os") // rename in case tested package is called os
+ fmt.Fprintf(b, "import __os__ %q\n", "os") // rename in case tested package is called os
fmt.Fprintf(b, "import __regexp__ %q\n", "regexp") // rename in case tested package is called regexp
fmt.Fprintln(b) // for gofmt
@@ -374,7 +393,7 @@ func writeTestmainGo() {
fmt.Fprintln(b)
// Benchmarks.
- fmt.Fprintln(b, "var benchmarks = []testing.InternalBenchmark{")
+ fmt.Fprintf(b, "var benchmarks = []testing.InternalBenchmark{")
for _, f := range files {
for _, bm := range f.benchmarks {
fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, bm, notMain(f.pkg), bm)
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index d27416dac..0cb2b2138 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -312,7 +312,7 @@ symgrow(Sym *s, int32 siz)
}
void
-savedata(Sym *s, Prog *p)
+savedata(Sym *s, Prog *p, char *pn)
{
int32 off, siz, i, fl;
uchar *cast;
@@ -321,8 +321,10 @@ savedata(Sym *s, Prog *p)
off = p->from.offset;
siz = p->datasize;
+ if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
+ mangle(pn);
symgrow(s, off+siz);
-
+
switch(p->to.type) {
default:
diag("bad data: %P", p);
@@ -876,7 +878,7 @@ textaddress(void)
void
address(void)
{
- Section *s, *text, *data, *rodata, *bss;
+ Section *s, *text, *data, *rodata;
Sym *sym, *sub;
uvlong va;
@@ -911,7 +913,6 @@ address(void)
text = segtext.sect;
rodata = segtext.sect->next;
data = segdata.sect;
- bss = segdata.sect->next;
for(sym = datap; sym != nil; sym = sym->next) {
cursym = sym;
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index fa55fcbb4..98b068008 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -1376,20 +1376,18 @@ synthesizemaptypes(DWDie *die)
static void
synthesizechantypes(DWDie *die)
{
- DWDie *sudog, *waitq, *link, *hchan,
+ DWDie *sudog, *waitq, *hchan,
*dws, *dww, *dwh, *elemtype;
DWAttr *a;
- int elemsize, linksize, sudogsize;
+ int elemsize, sudogsize;
sudog = defgotype(lookup_or_diag("type.runtime.sudog"));
waitq = defgotype(lookup_or_diag("type.runtime.waitq"));
- link = defgotype(lookup_or_diag("type.runtime.link"));
hchan = defgotype(lookup_or_diag("type.runtime.hchan"));
- if (sudog == nil || waitq == nil || link == nil || hchan == nil)
+ if (sudog == nil || waitq == nil || hchan == nil)
return;
sudogsize = getattr(sudog, DW_AT_byte_size)->value;
- linksize = getattr(link, DW_AT_byte_size)->value;
for (; die != nil; die = die->link) {
if (die->abbrev != DW_ABRV_CHANTYPE)
@@ -1422,7 +1420,7 @@ synthesizechantypes(DWDie *die)
copychildren(dwh, hchan);
substitutetype(dwh, "recvq", dww);
substitutetype(dwh, "sendq", dww);
- substitutetype(dwh, "free", dws);
+ substitutetype(dwh, "free", defptrto(dws));
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
getattr(hchan, DW_AT_byte_size)->value, NULL);
@@ -2569,12 +2567,8 @@ dwarfaddpeheaders(void)
newPEDWARFSection(".debug_line", linesize);
newPEDWARFSection(".debug_frame", framesize);
newPEDWARFSection(".debug_info", infosize);
- if (pubnamessize > 0)
- newPEDWARFSection(".debug_pubnames", pubnamessize);
- if (pubtypessize > 0)
- newPEDWARFSection(".debug_pubtypes", pubtypessize);
- if (arangessize > 0)
- newPEDWARFSection(".debug_aranges", arangessize);
- if (gdbscriptsize > 0)
- newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize);
+ newPEDWARFSection(".debug_pubnames", pubnamessize);
+ newPEDWARFSection(".debug_pubtypes", pubtypessize);
+ newPEDWARFSection(".debug_aranges", arangessize);
+ newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize);
}
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index b0cce4985..fc917b203 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -331,17 +331,62 @@ elfinterp(ElfShdr *sh, uint64 startva, char *p)
}
extern int nelfsym;
+int elfverneed;
+
+typedef struct Elfaux Elfaux;
+typedef struct Elflib Elflib;
+
+struct Elflib
+{
+ Elflib *next;
+ Elfaux *aux;
+ char *file;
+};
+
+struct Elfaux
+{
+ Elfaux *next;
+ int num;
+ char *vers;
+};
+
+Elfaux*
+addelflib(Elflib **list, char *file, char *vers)
+{
+ Elflib *lib;
+ Elfaux *aux;
+
+ for(lib=*list; lib; lib=lib->next)
+ if(strcmp(lib->file, file) == 0)
+ goto havelib;
+ lib = mal(sizeof *lib);
+ lib->next = *list;
+ lib->file = file;
+ *list = lib;
+havelib:
+ for(aux=lib->aux; aux; aux=aux->next)
+ if(strcmp(aux->vers, vers) == 0)
+ goto haveaux;
+ aux = mal(sizeof *aux);
+ aux->next = lib->aux;
+ aux->vers = vers;
+ lib->aux = aux;
+haveaux:
+ return aux;
+}
void
elfdynhash(void)
{
- Sym *s, *sy;
- int i, nbucket, b;
- uchar *pc;
- uint32 hc, g;
- uint32 *chain, *buckets;
+ Sym *s, *sy, *dynstr;
+ int i, j, nbucket, b, nfile;
+ uint32 hc, *chain, *buckets;
int nsym;
char *name;
+ Elfaux **need;
+ Elflib *needlib;
+ Elflib *l;
+ Elfaux *x;
if(!iself)
return;
@@ -358,29 +403,29 @@ elfdynhash(void)
i >>= 1;
}
- chain = malloc(nsym * sizeof(uint32));
- buckets = malloc(nbucket * sizeof(uint32));
- if(chain == nil || buckets == nil) {
+ needlib = nil;
+ need = malloc(nsym * sizeof need[0]);
+ chain = malloc(nsym * sizeof chain[0]);
+ buckets = malloc(nbucket * sizeof buckets[0]);
+ if(need == nil || chain == nil || buckets == nil) {
cursym = nil;
diag("out of memory");
errorexit();
}
- memset(chain, 0, nsym * sizeof(uint32));
- memset(buckets, 0, nbucket * sizeof(uint32));
+ memset(need, 0, nsym * sizeof need[0]);
+ memset(chain, 0, nsym * sizeof chain[0]);
+ memset(buckets, 0, nbucket * sizeof buckets[0]);
for(sy=allsym; sy!=S; sy=sy->allsym) {
if (sy->dynid <= 0)
continue;
- hc = 0;
+ if(sy->dynimpvers)
+ need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);
+
name = sy->dynimpname;
if(name == nil)
name = sy->name;
- for(pc = (uchar*)name; *pc; pc++) {
- hc = (hc<<4) + *pc;
- g = hc & 0xf0000000;
- hc ^= g >> 24;
- hc &= ~g;
- }
+ hc = elfhash((uchar*)name);
b = hc % nbucket;
chain[sy->dynid] = buckets[b];
@@ -396,8 +441,62 @@ elfdynhash(void)
free(chain);
free(buckets);
+
+ // version symbols
+ dynstr = lookup(".dynstr", 0);
+ s = lookup(".gnu.version_r", 0);
+ i = 2;
+ nfile = 0;
+ for(l=needlib; l; l=l->next) {
+ nfile++;
+ // header
+ adduint16(s, 1); // table version
+ j = 0;
+ for(x=l->aux; x; x=x->next)
+ j++;
+ adduint16(s, j); // aux count
+ adduint32(s, addstring(dynstr, l->file)); // file string offset
+ adduint32(s, 16); // offset from header to first aux
+ if(l->next)
+ adduint32(s, 16+j*16); // offset from this header to next
+ else
+ adduint32(s, 0);
+
+ for(x=l->aux; x; x=x->next) {
+ x->num = i++;
+ // aux struct
+ adduint32(s, elfhash((uchar*)x->vers)); // hash
+ adduint16(s, 0); // flags
+ adduint16(s, x->num); // other - index we refer to this by
+ adduint32(s, addstring(dynstr, x->vers)); // version string offset
+ if(x->next)
+ adduint32(s, 16); // offset from this aux to next
+ else
+ adduint32(s, 0);
+ }
+ }
+
+ // version references
+ s = lookup(".gnu.version", 0);
+ for(i=0; i<nsym; i++) {
+ if(i == 0)
+ adduint16(s, 0); // first entry - no symbol
+ else if(need[i] == nil)
+ adduint16(s, 1); // global
+ else
+ adduint16(s, need[i]->num);
+ }
- elfwritedynent(lookup(".dynamic", 0), DT_NULL, 0);
+ free(need);
+
+ s = lookup(".dynamic", 0);
+ elfverneed = nfile;
+ if(elfverneed) {
+ elfwritedynentsym(s, DT_VERNEED, lookup(".gnu.version_r", 0));
+ elfwritedynent(s, DT_VERNEEDNUM, nfile);
+ elfwritedynentsym(s, DT_VERSYM, lookup(".gnu.version", 0));
+ }
+ elfwritedynent(s, DT_NULL, 0);
}
ElfPhdr*
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index b27ae679b..08583cc8f 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -216,6 +216,9 @@ typedef struct {
#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
+#define SHT_GNU_VERDEF 0x6ffffffd
+#define SHT_GNU_VERNEED 0x6ffffffe
+#define SHT_GNU_VERSYM 0x6fffffff
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
#define SHT_HIPROC 0x7fffffff /* specific section header types */
#define SHT_LOUSER 0x80000000 /* reserved range for application */
@@ -311,6 +314,10 @@ typedef struct {
#define DT_LOPROC 0x70000000 /* First processor-specific type. */
#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
+#define DT_VERNEED 0x6ffffffe
+#define DT_VERNEEDNUM 0x6fffffff
+#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
@@ -962,12 +969,14 @@ uint64 endelf(void);
extern int numelfphdr;
extern int numelfshdr;
extern int iself;
+extern int elfverneed;
int elfwriteinterp(void);
void elfinterp(ElfShdr*, uint64, char*);
void elfdynhash(void);
ElfPhdr* elfphload(Segment*);
ElfShdr* elfshbits(Section*);
void elfsetstring(char*, int);
+void elfaddverneed(Sym*);
/*
* Total amount of space to reserve at the start of the file
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index 055163d08..e52c5cb34 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -412,7 +412,7 @@ parsemethod(char **pp, char *ep, char **methp)
static void
loaddynimport(char *file, char *pkg, char *p, int n)
{
- char *pend, *next, *name, *def, *p0, *lib;
+ char *pend, *next, *name, *def, *p0, *lib, *q;
Sym *s;
pend = p + n;
@@ -445,6 +445,12 @@ loaddynimport(char *file, char *pkg, char *p, int n)
*strchr(name, ' ') = 0;
*strchr(def, ' ') = 0;
+ if(debug['d']) {
+ fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
+ nerrors++;
+ return;
+ }
+
if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) {
// allow #pragma dynimport _ _ "foo.so"
// to force a link of foo.so.
@@ -453,17 +459,21 @@ loaddynimport(char *file, char *pkg, char *p, int n)
}
name = expandpkg(name, pkg);
+ q = strchr(def, '@');
+ if(q)
+ *q++ = '\0';
s = lookup(name, 0);
if(s->type == 0 || s->type == SXREF) {
s->dynimplib = lib;
s->dynimpname = def;
+ s->dynimpvers = q;
s->type = SDYNIMPORT;
}
}
return;
err:
- fprint(2, "%s: invalid dynimport line: %s\n", argv0, p0);
+ fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
nerrors++;
}
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index 44bbe68ee..d61020e49 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -319,7 +319,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
char *name;
int i, j, rela, is64, n;
uchar hdrbuf[64];
- uchar *p, *dp;
+ uchar *p;
ElfHdrBytes *hdr;
ElfObj *obj;
ElfSect *sect, *rsect;
@@ -561,7 +561,6 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
n = rsect->size/(4+4*is64)/(2+rela);
r = mal(n*sizeof r[0]);
p = rsect->base;
- dp = sect->base;
for(j=0; j<n; j++) {
add = 0;
rp = &r[j];
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 8cd570463..15219ba11 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -438,7 +438,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
return;
}
t = smprint("%s %s %s", getgoos(), thestring, getgoversion());
- if(strcmp(line+10, t) != 0) {
+ if(strcmp(line+10, t) != 0 && !debug['f']) {
diag("%s: object is [%s] expected [%s]", pn, line+10, t);
free(t);
return;
@@ -1033,7 +1033,7 @@ mkfwd(void)
Prog *p;
int i;
int32 dwn[LOG], cnt[LOG];
- Prog *lst[LOG], *last;
+ Prog *lst[LOG];
for(i=0; i<LOG; i++) {
if(i == 0)
@@ -1044,7 +1044,6 @@ mkfwd(void)
lst[i] = P;
}
i = 0;
- last = nil;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
if(p->link == P) {
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 646aeb535..8b603a04a 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -173,7 +173,7 @@ void datblk(int32, int32);
Sym* datsort(Sym*);
void reloc(void);
void relocsym(Sym*);
-void savedata(Sym*, Prog*);
+void savedata(Sym*, Prog*, char*);
void symgrow(Sym*, int32);
vlong addstring(Sym*, char*);
vlong adduint32(Sym*, uint32);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index c8d7c4a6d..01349bb10 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -12,10 +12,10 @@
static int macho64;
static MachoHdr hdr;
-static MachoLoad load[16];
+static MachoLoad *load;
static MachoSeg seg[16];
static MachoDebug xdebug[16];
-static int nload, nseg, ndebug, nsect;
+static int nload, mload, nseg, ndebug, nsect;
void
machoinit(void)
@@ -43,11 +43,18 @@ newMachoLoad(uint32 type, uint32 ndata)
{
MachoLoad *l;
- if(nload >= nelem(load)) {
- diag("too many loads");
- errorexit();
+ if(nload >= mload) {
+ if(mload == 0)
+ mload = 1;
+ else
+ mload *= 2;
+ load = realloc(load, mload*sizeof load[0]);
+ if(load == nil) {
+ diag("out of memory");
+ errorexit();
+ }
}
-
+
if(macho64 && (ndata & 1))
ndata++;
@@ -342,11 +349,13 @@ asmbmacho(void)
msect = newMachoSect(ms, "__data");
msect->addr = va+v;
- msect->size = symaddr(lookup(".got", 0)) - msect->addr;
msect->off = v;
+ msect->size = segdata.filelen;
s = lookup(".got", 0);
if(s->size > 0) {
+ msect->size = symaddr(s) - msect->addr;
+
msect = newMachoSect(ms, "__nl_symbol_ptr");
msect->addr = symaddr(s);
msect->size = s->size;
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index 0d4240e36..d523ca9c5 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -415,6 +415,9 @@ newPEDWARFSection(char *name, vlong size)
IMAGE_SECTION_HEADER *h;
char s[8];
+ if(size == 0)
+ return nil;
+
if(nextsymoff+strlen(name)+1 > sizeof(symnames)) {
diag("pe string table is full");
errorexit();
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index aefe0b1af..da698fcc0 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -140,29 +140,25 @@ void
putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
{
int i;
-
+
switch(t) {
case 'T':
- case 't':
case 'L':
- case 'l':
case 'D':
- case 'd':
case 'B':
- case 'b':
+ if(ver)
+ t += 'a' - 'A';
case 'a':
case 'p':
-
case 'f':
case 'z':
case 'Z':
-
case 'm':
lputb(addr);
cput(t+0x80); /* 0x80 is variable length */
-
+
if(t == 'z' || t == 'Z') {
- cput(0);
+ cput(s[0]);
for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
cput(s[i]);
cput(s[i+1]);
@@ -172,19 +168,17 @@ putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
i++;
} else {
/* skip the '<' in filenames */
- if(t=='f')
+ if(t == 'f')
s++;
-
for(i=0; s[i]; i++)
cput(s[i]);
cput(0);
}
-
symsize += 4 + 1 + i + 1;
break;
default:
return;
- };
+ };
}
void