summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-04-20 15:44:41 +0200
committerOndřej Surý <ondrej@sury.org>2011-04-20 15:44:41 +0200
commit50104cc32a498f7517a51c8dc93106c51c7a54b4 (patch)
tree47af80be259cc7c45d0eaec7d42e61fa38c8e4fb /src/cmd
parentc072558b90f1bbedc2022b0f30c8b1ac4712538e (diff)
downloadgolang-upstream/2011.03.07.1.tar.gz
Imported Upstream version 2011.03.07.1upstream/2011.03.07.1
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5a/lex.c2
-rw-r--r--src/cmd/5c/txt.c4
-rw-r--r--src/cmd/5g/gg.h1
-rw-r--r--src/cmd/5g/gsubr.c1
-rw-r--r--src/cmd/5g/reg.c4
-rw-r--r--src/cmd/5l/5.out.h3
-rw-r--r--src/cmd/5l/asm.c49
-rw-r--r--src/cmd/5l/doc.go2
-rw-r--r--src/cmd/5l/l.h5
-rw-r--r--src/cmd/5l/list.c4
-rw-r--r--src/cmd/5l/noop.c24
-rw-r--r--src/cmd/5l/obj.c51
-rw-r--r--src/cmd/5l/optab.c3
-rw-r--r--src/cmd/5l/pass.c12
-rw-r--r--src/cmd/5l/span.c2
-rw-r--r--src/cmd/6l/asm.c58
-rw-r--r--src/cmd/6l/doc.go8
-rw-r--r--src/cmd/6l/l.h4
-rw-r--r--src/cmd/6l/obj.c68
-rw-r--r--src/cmd/6l/pass.c30
-rw-r--r--src/cmd/8a/lex.c4
-rw-r--r--src/cmd/8l/8.out.h5
-rw-r--r--src/cmd/8l/asm.c56
-rw-r--r--src/cmd/8l/doc.go10
-rw-r--r--src/cmd/8l/l.h3
-rw-r--r--src/cmd/8l/obj.c94
-rw-r--r--src/cmd/8l/optab.c5
-rw-r--r--src/cmd/8l/pass.c30
-rw-r--r--src/cmd/Makefile66
-rw-r--r--src/cmd/cgo/gcc.go65
-rw-r--r--src/cmd/cgo/main.go12
-rw-r--r--src/cmd/cgo/out.go96
-rw-r--r--src/cmd/clean.bash16
-rw-r--r--src/cmd/ebnflint/ebnflint.go4
-rw-r--r--src/cmd/gc/const.c6
-rw-r--r--src/cmd/gc/doc.go2
-rw-r--r--src/cmd/gc/export.c12
-rw-r--r--src/cmd/gc/go.y9
-rw-r--r--src/cmd/gc/init.c27
-rw-r--r--src/cmd/gc/reflect.c33
-rw-r--r--src/cmd/gc/subr.c11
-rw-r--r--src/cmd/gc/typecheck.c6
-rw-r--r--src/cmd/godoc/dirtrees.go29
-rw-r--r--src/cmd/godoc/godoc.go82
-rw-r--r--src/cmd/godoc/index.go8
-rw-r--r--src/cmd/godoc/main.go10
-rw-r--r--src/cmd/godoc/mapping.go47
-rw-r--r--src/cmd/godoc/utils.go12
-rw-r--r--src/cmd/gofmt/gofmt.go4
-rwxr-xr-xsrc/cmd/gofmt/test.sh2
-rw-r--r--src/cmd/goinstall/download.go19
-rw-r--r--src/cmd/goinstall/main.go11
-rw-r--r--src/cmd/goinstall/make.go23
-rw-r--r--src/cmd/goinstall/parse.go12
-rw-r--r--src/cmd/gopack/ar.c2
-rw-r--r--src/cmd/gopack/doc.go4
-rw-r--r--src/cmd/gotest/doc.go20
-rw-r--r--src/cmd/govet/govet.go6
-rw-r--r--src/cmd/goyacc/Makefile2
-rw-r--r--src/cmd/goyacc/doc.go12
-rw-r--r--src/cmd/goyacc/goyacc.go314
-rw-r--r--src/cmd/goyacc/units.y9
-rw-r--r--src/cmd/hgpatch/main.go4
-rw-r--r--src/cmd/ld/data.c6
-rw-r--r--src/cmd/ld/dwarf.c42
-rw-r--r--src/cmd/ld/go.c33
-rw-r--r--src/cmd/ld/lib.c207
-rw-r--r--src/cmd/ld/lib.h37
-rw-r--r--src/cmd/ld/macho.c7
-rw-r--r--src/cmd/ld/pe.c8
-rw-r--r--src/cmd/ld/pe.h3
-rwxr-xr-xsrc/cmd/make.bash30
72 files changed, 1207 insertions, 705 deletions
diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c
index e762f5646..dbee3657f 100644
--- a/src/cmd/5a/lex.c
+++ b/src/cmd/5a/lex.c
@@ -364,7 +364,9 @@ struct
"MOVWF", LTYPE3, AMOVWF,
"LDREX", LTYPE3, ALDREX,
+ "LDREXD", LTYPE3, ALDREXD,
"STREX", LTYPE9, ASTREX,
+ "STREXD", LTYPE9, ASTREXD,
/*
"ABSF", LTYPEI, AABSF,
diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c
index 0f17cea89..f5619f800 100644
--- a/src/cmd/5c/txt.c
+++ b/src/cmd/5c/txt.c
@@ -1194,8 +1194,10 @@ gpseudo(int a, Sym *s, Node *n)
p->from.type = D_OREG;
p->from.sym = s;
p->from.name = D_EXTERN;
- if(a == ATEXT)
+ if(a == ATEXT) {
p->reg = textflag;
+ textflag = 0;
+ }
if(s->class == CSTATIC)
p->from.name = D_STATIC;
naddr(n, &p->to);
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index 603c09fc8..ce4575be9 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -27,6 +27,7 @@ struct Addr
uchar type;
char name;
char reg;
+ char pun;
uchar etype;
};
#define A ((Addr*)0)
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index 133a21b3e..83a9949d6 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -1168,6 +1168,7 @@ naddr(Node *n, Addr *a, int canemitcode)
a->etype = simtype[n->type->etype];
a->width = n->type->width;
}
+ a->pun = n->pun;
a->offset = n->xoffset;
a->sym = n->sym;
if(a->sym == S)
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index f31f70535..1cbeb3e3d 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -697,8 +697,8 @@ mkvar(Reg *r, Adr *a)
n = D_NONE;
flag = 0;
-// if(a->pun)
-// flag = 1;
+ if(a->pun)
+ flag = 1;
switch(t) {
default:
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index a25c0f71d..002b46d45 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -179,6 +179,9 @@ enum as
ALDREX,
ASTREX,
+
+ ALDREXD,
+ ASTREXD,
ALAST,
};
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 7163997c0..af6d1dfda 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -331,21 +331,21 @@ asmb(void)
Bprint(&bso, "%5.2f sym\n", cputime());
Bflush(&bso);
switch(HEADTYPE) {
- case 0:
- case 1:
- case 4:
- case 5:
+ case Hnoheader:
+ case Hrisc:
+ case Hixp1200:
+ case Hipaq:
debug['s'] = 1;
break;
- case 2:
+ case Hplan9x32:
OFFSET = HEADR+textsize+segdata.filelen;
seek(cout, OFFSET, 0);
break;
- case 3:
+ case Hnetbsd:
OFFSET += rnd(segdata.filelen, 4096);
seek(cout, OFFSET, 0);
break;
- case 6:
+ case Hlinux:
OFFSET += segdata.filelen;
seek(cout, rnd(OFFSET, INITRND), 0);
break;
@@ -362,9 +362,9 @@ asmb(void)
OFFSET = 0;
seek(cout, OFFSET, 0);
switch(HEADTYPE) {
- case 0: /* no header */
+ case Hnoheader: /* no header */
break;
- case 1: /* aif for risc os */
+ case Hrisc: /* aif for risc os */
lputl(0xe1a00000); /* NOP - decompress code */
lputl(0xe1a00000); /* NOP - relocation code */
lputl(0xeb000000 + 12); /* BL - zero init code */
@@ -394,7 +394,7 @@ asmb(void)
lputl(0xe1a00000); /* NOP - zero init code */
lputl(0xe1a0f00e); /* B (R14) - zero init return */
break;
- case 2: /* plan 9 */
+ case Hplan9x32: /* plan 9 */
lput(0x647); /* magic */
lput(textsize); /* sizes */
lput(segdata.filelen);
@@ -404,7 +404,7 @@ asmb(void)
lput(0L);
lput(lcsize);
break;
- case 3: /* boot for NetBSD */
+ case Hnetbsd: /* boot for NetBSD */
lput((143<<16)|0413); /* magic */
lputl(rnd(HEADR+textsize, 4096));
lputl(rnd(segdata.filelen, 4096));
@@ -414,15 +414,15 @@ asmb(void)
lputl(0L);
lputl(0L);
break;
- case 4: /* boot for IXP1200 */
+ case Hixp1200: /* boot for IXP1200 */
break;
- case 5: /* boot for ipaq */
+ case Hipaq: /* boot for ipaq */
lputl(0xe3300000); /* nop */
lputl(0xe3300000); /* nop */
lputl(0xe3300000); /* nop */
lputl(0xe3300000); /* nop */
break;
- case 6:
+ case Hlinux:
/* elf arm */
eh = getElfEhdr();
fo = HEADR;
@@ -1463,7 +1463,7 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na
aclass(&p->from);
if(instoffset != 0)
diag("offset must be zero in STREX");
- o1 = (0x3<<23) | (0xf9<<4);
+ o1 = (0x18<<20) | (0xf90);
o1 |= p->from.reg << 16;
o1 |= p->reg << 0;
o1 |= p->to.reg << 12;
@@ -1553,6 +1553,25 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na
o1 = oprrr(ACMP+AEND, p->scond);
o1 |= p->from.reg<<16;
break;
+ case 91: /* ldrexd oreg,reg */
+ aclass(&p->from);
+ if(instoffset != 0)
+ diag("offset must be zero in LDREX");
+ o1 = (0x1b<<20) | (0xf9f);
+ o1 |= p->from.reg << 16;
+ o1 |= p->to.reg << 12;
+ o1 |= (p->scond & C_SCOND) << 28;
+ break;
+ case 92: /* strexd reg,oreg,reg */
+ aclass(&p->from);
+ if(instoffset != 0)
+ diag("offset must be zero in STREX");
+ o1 = (0x1a<<20) | (0xf90);
+ o1 |= p->from.reg << 16;
+ o1 |= p->reg << 0;
+ o1 |= p->to.reg << 12;
+ o1 |= (p->scond & C_SCOND) << 28;
+ break;
}
out[0] = o1;
diff --git a/src/cmd/5l/doc.go b/src/cmd/5l/doc.go
index d266b9233..aa7ccebfc 100644
--- a/src/cmd/5l/doc.go
+++ b/src/cmd/5l/doc.go
@@ -23,6 +23,8 @@ Options new in this version:
-F
Force use of software floating point.
Also implied by setting GOARM=5 in the environment.
+-Hlinux
+ Write Linux ELF binaries (default when $GOOS is linux)
-I interpreter
Set the ELF dynamic linker to use.
-L dir1 -L dir2
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index e42be4e98..2e887dad7 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -35,6 +35,7 @@
enum
{
+ thechar = '5',
PtrSize = 4
};
@@ -109,6 +110,7 @@ struct Prog
Prog* dlink;
int32 pc;
int32 line;
+ int32 spadj;
uchar mark;
uchar optab;
uchar as;
@@ -122,6 +124,8 @@ struct Prog
#define datasize reg
#define textflag reg
+#define iscall(p) ((p)->as == ABL)
+
struct Sym
{
char* name;
@@ -131,6 +135,7 @@ struct Sym
uchar reachable;
uchar dynexport;
uchar leaf;
+ uchar stkcheck;
int32 dynid;
int32 plt;
int32 got;
diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c
index b4df89587..2ae25d491 100644
--- a/src/cmd/5l/list.c
+++ b/src/cmd/5l/list.c
@@ -98,6 +98,10 @@ Pconv(Fmt *fp)
fmtprint(fp, "(%d) DWORD %D %D", p->line, &p->from, &p->to);
break;
}
+
+ if(p->spadj)
+ fmtprint(fp, " (spadj%+d)", p->spadj);
+
return 0;
}
diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c
index a9439c27a..a5e66f038 100644
--- a/src/cmd/5l/noop.c
+++ b/src/cmd/5l/noop.c
@@ -227,7 +227,7 @@ noops(void)
#ifdef CALLEEBX
if(p->from.sym->foreign){
if(thumb)
- // don't allow literal pool to seperate these
+ // don't allow literal pool to separate these
p = adword(0xe28f7001, 0xe12fff17, p); // arm add 1, pc, r7 and bx r7
// p = aword(0xe12fff17, aword(0xe28f7001, p)); // arm add 1, pc, r7 and bx r7
else
@@ -282,6 +282,7 @@ noops(void)
q1->to.type = D_OREG;
q1->to.offset = -autosize;
q1->to.reg = REGSP;
+ q1->spadj = autosize;
q1->link = p->link;
p->link = q1;
} else if (autosize < StackBig) {
@@ -376,6 +377,7 @@ noops(void)
p->to.type = D_OREG;
p->to.offset = -autosize;
p->to.reg = REGSP;
+ p->spadj = autosize;
} else { // > StackBig
// MOVW $autosize, R1
// MOVW $args, R2
@@ -424,6 +426,7 @@ noops(void)
p->to.type = D_OREG;
p->to.offset = -autosize;
p->to.reg = REGSP;
+ p->spadj = autosize;
}
break;
@@ -527,9 +530,20 @@ noops(void)
p->from.reg = REGSP;
p->to.type = D_REG;
p->to.reg = REGPC;
+ // no spadj because it doesn't fall through
}
break;
+ case AADD:
+ if(p->from.type == D_CONST && p->from.reg == NREG && p->to.type == D_REG && p->to.reg == REGSP)
+ p->spadj = -p->from.offset;
+ break;
+
+ case ASUB:
+ if(p->from.type == D_CONST && p->from.reg == NREG && p->to.type == D_REG && p->to.reg == REGSP)
+ p->spadj = p->from.offset;
+ break;
+
case ADIV:
case ADIVU:
case AMOD:
@@ -635,6 +649,7 @@ noops(void)
p->reg = NREG;
p->to.type = D_REG;
p->to.reg = REGSP;
+ p->spadj = -8;
/* SUB $8,SP */
q1->as = ASUB;
@@ -644,6 +659,7 @@ noops(void)
q1->reg = NREG;
q1->to.type = D_REG;
q1->to.reg = REGSP;
+ q1->spadj = 8;
break;
case AMOVW:
@@ -653,6 +669,12 @@ noops(void)
if(a->type == D_CONST && ((a->name == D_NONE && a->reg == REGSP) || a->name == D_AUTO || a->name == D_PARAM) && (a->offset & 3))
diag("SP offset not multiple of 4");
}
+ if((p->scond & C_WBIT) && p->to.type == D_OREG && p->to.reg == REGSP)
+ p->spadj = -p->to.offset;
+ if((p->scond & C_PBIT) && p->from.type == D_OREG && p->from.reg == REGSP && p->to.reg != REGPC)
+ p->spadj = -p->from.offset;
+ if(p->from.type == D_CONST && p->from.reg == REGSP && p->to.type == D_REG && p->to.reg == REGSP)
+ p->spadj = -p->from.offset;
break;
case AMOVB:
case AMOVBU:
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 5b778d777..f252f9fc5 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -41,15 +41,26 @@
#endif
char *noname = "<none>";
-char thechar = '5';
char *thestring = "arm";
+Header headers[] = {
+ "noheader", Hnoheader,
+ "risc", Hrisc,
+ "plan9", Hplan9x32,
+ "netbsd", Hnetbsd,
+ "ixp1200", Hixp1200,
+ "ipaq", Hipaq,
+ "linux", Hlinux,
+ 0, 0
+};
+
/*
- * -H1 -T0x10005000 -R4 is aif for risc os
- * -H2 -T4128 -R4096 is plan9 format
- * -H3 -T0xF0000020 -R4 is NetBSD format
- * -H4 is IXP1200 (raw)
- * -H5 -T0xC0008010 -R1024 is ipaq
+ * -Hrisc -T0x10005000 -R4 is aif for risc os
+ * -Hplan9 -T4128 -R4096 is plan9 format
+ * -Hnetbsd -T0xF0000020 -R4 is NetBSD format
+ * -Hixp1200 is IXP1200 (raw)
+ * -Hipaq -T0xC0008010 -R1024 is ipaq
+ * -Hlinux -Tx -Rx is linux elf
*/
static char*
@@ -119,7 +130,7 @@ main(int argc, char *argv[])
rpath = EARGF(usage());
break;
case 'H':
- HEADTYPE = atolwhex(EARGF(usage()));
+ HEADTYPE = headtype(EARGF(usage()));
/* do something about setting INITTEXT */
break;
case 'V':
@@ -133,25 +144,23 @@ main(int argc, char *argv[])
usage();
libinit();
- if(rpath == nil)
- rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
if(!debug['9'] && !debug['U'] && !debug['B'])
debug[DEFAULT] = 1;
if(HEADTYPE == -1) {
if(debug['U'])
- HEADTYPE = 0;
+ HEADTYPE = Hnoheader;
if(debug['B'])
- HEADTYPE = 1;
+ HEADTYPE = Hrisc;
if(debug['9'])
- HEADTYPE = 2;
- HEADTYPE = 6;
+ HEADTYPE = Hplan9x32;
+ HEADTYPE = Hlinux;
}
switch(HEADTYPE) {
default:
diag("unknown -H option");
errorexit();
- case 0: /* no header */
+ case Hnoheader: /* no header */
HEADR = 0L;
if(INITTEXT == -1)
INITTEXT = 0;
@@ -160,7 +169,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4;
break;
- case 1: /* aif for risc os */
+ case Hrisc: /* aif for risc os */
HEADR = 128L;
if(INITTEXT == -1)
INITTEXT = 0x10005000 + HEADR;
@@ -169,7 +178,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4;
break;
- case 2: /* plan 9 */
+ case Hplan9x32: /* plan 9 */
HEADR = 32L;
if(INITTEXT == -1)
INITTEXT = 4128;
@@ -178,7 +187,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 3: /* boot for NetBSD */
+ case Hnetbsd: /* boot for NetBSD */
HEADR = 32L;
if(INITTEXT == -1)
INITTEXT = 0xF0000020L;
@@ -187,7 +196,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 4: /* boot for IXP1200 */
+ case Hixp1200: /* boot for IXP1200 */
HEADR = 0L;
if(INITTEXT == -1)
INITTEXT = 0x0;
@@ -196,7 +205,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4;
break;
- case 5: /* boot for ipaq */
+ case Hipaq: /* boot for ipaq */
HEADR = 16L;
if(INITTEXT == -1)
INITTEXT = 0xC0008010;
@@ -205,7 +214,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 1024;
break;
- case 6: /* arm elf */
+ case Hlinux: /* arm elf */
debug['d'] = 1; // no dynamic linking
elfinit();
HEADR = ELFRESERVE;
@@ -265,11 +274,13 @@ main(int argc, char *argv[])
follow();
softfloat();
noops();
+ dostkcheck();
span();
pclntab();
symtab();
dodata();
address();
+ doweak();
reloc();
asmb();
undef();
diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c
index 8b3135e06..625b66812 100644
--- a/src/cmd/5l/optab.c
+++ b/src/cmd/5l/optab.c
@@ -253,5 +253,8 @@ Optab optab[] =
{ ATST, C_REG, C_NONE, C_NONE, 90, 4, 0 },
+ { ALDREXD, C_SOREG,C_NONE, C_REG, 91, 4, 0 },
+ { ASTREXD, C_SOREG,C_REG, C_REG, 92, 4, 0 },
+
{ AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0 },
};
diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c
index e16b34171..7e1ba6a09 100644
--- a/src/cmd/5l/pass.c
+++ b/src/cmd/5l/pass.c
@@ -35,18 +35,6 @@
static void xfol(Prog*, Prog**);
-void
-undef(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->hash)
- if(s->type == SXREF)
- diag("%s: not defined", s->name);
-}
-
Prog*
brchain(Prog *p)
{
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c
index 220140f43..482d3e90a 100644
--- a/src/cmd/5l/span.c
+++ b/src/cmd/5l/span.c
@@ -1054,6 +1054,8 @@ buildop(void)
case ALDREX:
case ASTREX:
+ case ALDREXD:
+ case ASTREXD:
case ATST:
break;
}
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index d179e77b1..fb041d83a 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -262,7 +262,7 @@ adddynrel(Sym *s, Reloc *r)
r->type = 256; // ignore during relocsym
return;
}
- if(HEADTYPE == 6 && s->size == PtrSize && r->off == 0) {
+ if(HEADTYPE == Hdarwin && s->size == PtrSize && r->off == 0) {
// Mach-O relocations are a royal pain to lay out.
// They use a compact stateful bytecode representation
// that is too much bother to deal with.
@@ -365,7 +365,7 @@ addpltsym(Sym *s)
adduint64(rela, 0);
s->plt = plt->size - 16;
- } else if(HEADTYPE == 6) { // Mach-O
+ } else if(HEADTYPE == Hdarwin) {
// To do lazy symbol lookup right, we're supposed
// to tell the dynamic loader which library each
// symbol comes from and format the link info
@@ -412,7 +412,7 @@ addgotsym(Sym *s)
addaddrplus(rela, got, s->got);
adduint64(rela, ELF64_R_INFO(s->dynid, R_X86_64_GLOB_DAT));
adduint64(rela, 0);
- } else if(HEADTYPE == 6) { // Mach-O
+ } else if(HEADTYPE == Hdarwin) {
adduint32(lookup(".linkedit.got", 0), s->dynid);
} else {
diag("addgotsym: unsupported binary format");
@@ -486,7 +486,7 @@ adddynsym(Sym *s)
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
addstring(lookup(".dynstr", 0), s->dynimplib));
}
- } else if(HEADTYPE == 6) {
+ } else if(HEADTYPE == Hdarwin) {
// Mach-o symbol nlist64
d = lookup(".dynsym", 0);
name = s->dynimpname;
@@ -539,7 +539,7 @@ adddynlib(char *lib)
if(s->size == 0)
addstring(s, "");
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib));
- } else if(HEADTYPE == 6) { // Mach-O
+ } else if(HEADTYPE == Hdarwin) {
machoadddynlib(lib);
} else {
diag("adddynlib: unsupported binary format");
@@ -551,7 +551,7 @@ doelf(void)
{
Sym *s, *shstrtab, *dynstr;
- if(HEADTYPE != 7 && HEADTYPE != 9)
+ if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd)
return;
/* predefine strings we need for section headers */
@@ -717,20 +717,20 @@ asmb(void)
datblk(segdata.vaddr, segdata.filelen);
machlink = 0;
- if(HEADTYPE == 6)
+ if(HEADTYPE == Hdarwin)
machlink = domacholink();
switch(HEADTYPE) {
default:
diag("unknown header type %d", HEADTYPE);
- case 2:
- case 5:
+ case Hplan9x32:
+ case Helf:
break;
- case 6:
+ case Hdarwin:
debug['8'] = 1; /* 64-bit addresses */
break;
- case 7:
- case 9:
+ case Hlinux:
+ case Hfreebsd:
debug['8'] = 1; /* 64-bit addresses */
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
@@ -738,7 +738,7 @@ asmb(void)
if(!debug['d'])
elftextsh += 10;
break;
- case 10:
+ case Hwindows:
break;
}
@@ -752,20 +752,20 @@ asmb(void)
Bflush(&bso);
switch(HEADTYPE) {
default:
- case 2:
- case 5:
+ case Hplan9x32:
+ case Helf:
debug['s'] = 1;
symo = HEADR+segtext.len+segdata.filelen;
break;
- case 6:
+ case Hdarwin:
symo = rnd(HEADR+segtext.len, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
break;
- case 7:
- case 9:
+ case Hlinux:
+ case Hfreebsd:
symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND);
break;
- case 10:
+ case Hwindows:
symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
symo = rnd(symo, PEFILEALIGN);
break;
@@ -791,7 +791,7 @@ asmb(void)
lputl(symsize);
lputl(lcsize);
cflush();
- if(HEADTYPE != 10 && !debug['s']) {
+ if(HEADTYPE != Hwindows && !debug['s']) {
elfsymo = symo+8+symsize+lcsize;
seek(cout, elfsymo, 0);
asmelfsym64();
@@ -813,7 +813,7 @@ asmb(void)
seek(cout, 0L, 0);
switch(HEADTYPE) {
default:
- case 2: /* plan9 */
+ case Hplan9x32: /* plan9 */
magic = 4*26*26+7;
magic |= 0x00008000; /* fat header */
lputb(magic); /* magic */
@@ -827,7 +827,7 @@ asmb(void)
lputb(lcsize); /* line offsets */
vputb(vl); /* va of entry */
break;
- case 3: /* plan9 */
+ case Hplan9x64: /* plan9 */
magic = 4*26*26+7;
lputb(magic); /* magic */
lputb(segtext.filelen); /* sizes */
@@ -838,11 +838,11 @@ asmb(void)
lputb(spsize); /* sp offsets */
lputb(lcsize); /* line offsets */
break;
- case 6:
+ case Hdarwin:
asmbmacho();
break;
- case 7:
- case 9:
+ case Hlinux:
+ case Hfreebsd:
/* elf amd-64 */
eh = getElfEhdr();
@@ -871,10 +871,10 @@ asmb(void)
sh->addralign = 1;
if(interpreter == nil) {
switch(HEADTYPE) {
- case 7:
+ case Hlinux:
interpreter = linuxdynld;
break;
- case 9:
+ case Hfreebsd:
interpreter = freebsddynld;
break;
}
@@ -1032,7 +1032,7 @@ asmb(void)
eh->ident[EI_MAG1] = 'E';
eh->ident[EI_MAG2] = 'L';
eh->ident[EI_MAG3] = 'F';
- if(HEADTYPE == 9)
+ if(HEADTYPE == Hfreebsd)
eh->ident[EI_OSABI] = 9;
eh->ident[EI_CLASS] = ELFCLASS64;
eh->ident[EI_DATA] = ELFDATA2LSB;
@@ -1055,7 +1055,7 @@ asmb(void)
if(a+elfwriteinterp() > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
- case 10:
+ case Hwindows:
asmbpe();
break;
}
diff --git a/src/cmd/6l/doc.go b/src/cmd/6l/doc.go
index 97fa2cc5a..cc7782cfe 100644
--- a/src/cmd/6l/doc.go
+++ b/src/cmd/6l/doc.go
@@ -28,10 +28,14 @@ Options new in this version:
-e
Emit an extra ELF-compatible symbol table useful with tools such as
nm, gdb, and oprofile. This option makes the binary file considerably larger.
--H6
+-Hdarwin
Write Apple Mach-O binaries (default when $GOOS is darwin)
--H7
+-Hlinux
Write Linux ELF binaries (default when $GOOS is linux)
+-Hfreebsd
+ Write FreeBSD ELF binaries (default when $GOOS is freebsd)
+-Hwindows
+ Write Windows PE32+ binaries (default when $GOOS is windows)
-I interpreter
Set the ELF dynamic linker to use.
-L dir1 -L dir2
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 70473ecd2..6933d8eb1 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -39,6 +39,7 @@
enum
{
+ thechar = '6',
PtrSize = 8
};
@@ -111,6 +112,7 @@ struct Prog
};
#define datasize from.scale
#define textflag from.scale
+#define iscall(p) ((p)->as == ACALL)
struct Auto
{
@@ -129,6 +131,7 @@ struct Sym
uchar reachable;
uchar dynexport;
uchar special;
+ uchar stkcheck;
int32 dynid;
int32 sig;
int32 plt;
@@ -367,7 +370,6 @@ EXTERN Sym* fromgotype; // type symbol on last p->from read
EXTERN vlong textstksiz;
EXTERN vlong textarg;
-extern char thechar;
EXTERN int elfstrsize;
EXTERN char* elfstrdat;
EXTERN int elftextsh;
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index f9e257842..f113e3ec1 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -40,17 +40,29 @@
#include <ar.h>
char *noname = "<none>";
-char thechar = '6';
char* thestring = "amd64";
char* paramspace = "FP";
+Header headers[] = {
+ "plan9x32", Hplan9x32,
+ "plan9", Hplan9x64,
+ "elf", Helf,
+ "darwin", Hdarwin,
+ "linux", Hlinux,
+ "freebsd", Hfreebsd,
+ "windows", Hwindows,
+ "windowsgui", Hwindows,
+ 0, 0
+};
+
/*
- * -H2 -T4136 -R4096 is plan9 64-bit format
- * -H3 -T4128 -R4096 is plan9 32-bit format
- * -H5 -T0x80110000 -R4096 is ELF32
- * -H6 -Tx -Rx is apple MH-exec
- * -H7 -Tx -Rx is linux elf-exec
- * -H9 -Tx -Rx is FreeBSD elf-exec
+ * -Hplan9x32 -T4136 -R4096 is plan9 64-bit format
+ * -Hplan9 -T4128 -R4096 is plan9 32-bit format
+ * -Helf -T0x80110000 -R4096 is ELF32
+ * -Hdarwin -Tx -Rx is apple MH-exec
+ * -Hlinux -Tx -Rx is linux elf-exec
+ * -Hfreebsd -Tx -Rx is FreeBSD elf-exec
+ * -Hwindows -Tx -Rx is MS Windows PE32+
*
* options used: 189BLQSWabcjlnpsvz
*/
@@ -94,7 +106,7 @@ main(int argc, char *argv[])
INITENTRY = EARGF(usage());
break;
case 'H':
- HEADTYPE = atolwhex(EARGF(usage()));
+ HEADTYPE = headtype(EARGF(usage()));
break;
case 'I':
interpreter = EARGF(usage());
@@ -123,31 +135,15 @@ main(int argc, char *argv[])
usage();
libinit();
- if(rpath == nil)
- rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
- if(HEADTYPE == -1) {
- HEADTYPE = 2;
- if(strcmp(goos, "linux") == 0)
- HEADTYPE = 7;
- else
- if(strcmp(goos, "darwin") == 0)
- HEADTYPE = 6;
- else
- if(strcmp(goos, "freebsd") == 0)
- HEADTYPE = 9;
- else
- if(strcmp(goos, "windows") == 0)
- HEADTYPE = 10;
- else
- print("goos is not known: %s\n", goos);
- }
+ if(HEADTYPE == -1)
+ HEADTYPE = headtype(goos);
switch(HEADTYPE) {
default:
diag("unknown -H option");
errorexit();
- case 2: /* plan 9 */
+ case Hplan9x32: /* plan 9 */
HEADR = 32L+8L;
if(INITTEXT == -1)
INITTEXT = 4096+HEADR;
@@ -156,7 +152,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 3: /* plan 9 */
+ case Hplan9x64: /* plan 9 */
HEADR = 32L;
if(INITTEXT == -1)
INITTEXT = 4096+32;
@@ -165,7 +161,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 5: /* elf32 executable */
+ case Helf: /* elf32 executable */
HEADR = rnd(52L+3*32L, 16);
if(INITTEXT == -1)
INITTEXT = 0x80110000L;
@@ -174,7 +170,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 6: /* apple MACH */
+ case Hdarwin: /* apple MACH */
/*
* OS X system constant - offset from 0(GS) to our TLS.
* Explained in ../../libcgo/darwin_amd64.c.
@@ -189,8 +185,8 @@ main(int argc, char *argv[])
if(INITDAT == -1)
INITDAT = 0;
break;
- case 7: /* elf64 executable */
- case 9: /* freebsd */
+ case Hlinux: /* elf64 executable */
+ case Hfreebsd: /* freebsd */
/*
* ELF uses TLS offset negative from FS.
* Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
@@ -207,7 +203,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 10: /* PE executable */
+ case Hwindows: /* PE executable */
peinit();
HEADR = PEFILEHEADR;
if(INITTEXT == -1)
@@ -252,9 +248,10 @@ main(int argc, char *argv[])
patch();
follow();
doelf();
- if(HEADTYPE == 6)
+ if(HEADTYPE == Hdarwin)
domacho();
dostkoff();
+ dostkcheck();
paramspace = "SP"; /* (FP) now (SP) on output */
if(debug['p'])
if(debug['1'])
@@ -262,7 +259,7 @@ main(int argc, char *argv[])
else
doprof2();
span();
- if(HEADTYPE == 10)
+ if(HEADTYPE == Hwindows)
dope();
addexport();
textaddress();
@@ -270,6 +267,7 @@ main(int argc, char *argv[])
symtab();
dodata();
address();
+ doweak();
reloc();
asmb();
undef();
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index 5eb221a35..8fda94392 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -32,16 +32,10 @@
#include "l.h"
#include "../ld/lib.h"
+#include "../../pkg/runtime/stack.h"
static void xfol(Prog*, Prog**);
-// see ../../runtime/proc.c:/StackGuard
-enum
-{
- StackSmall = 128,
- StackBig = 4096,
-};
-
Prog*
brchain(Prog *p)
{
@@ -277,7 +271,7 @@ patch(void)
vexit = s->value;
for(cursym = textp; cursym != nil; cursym = cursym->next)
for(p = cursym->text; p != P; p = p->link) {
- if(HEADTYPE == 10) {
+ if(HEADTYPE == Hwindows) {
// Windows
// Convert
// op n(GS), reg
@@ -289,7 +283,7 @@ patch(void)
// a different method is used to access them.
if(p->from.type == D_INDIR+D_GS
&& p->to.type >= D_AX && p->to.type <= D_DI
- && p->from.offset != 0x58) {
+ && p->from.offset <= 8) {
q = appendp(p);
q->from = p->from;
q->from.type = D_INDIR + p->to.type;
@@ -300,7 +294,7 @@ patch(void)
p->from.offset = 0x58;
}
}
- if(HEADTYPE == 7 || HEADTYPE == 9) {
+ if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd) {
// ELF uses FS instead of GS.
if(p->from.type == D_INDIR+D_GS)
p->from.type = D_INDIR+D_FS;
@@ -428,13 +422,13 @@ dostkoff(void)
if(!(p->from.scale & NOSPLIT)) {
p = appendp(p); // load g into CX
p->as = AMOVQ;
- if(HEADTYPE == 7 || HEADTYPE == 9) // ELF uses FS
+ if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd) // ELF uses FS
p->from.type = D_INDIR+D_FS;
else
p->from.type = D_INDIR+D_GS;
p->from.offset = tlsoffset+0;
p->to.type = D_CX;
- if(HEADTYPE == 10) { // Windows
+ if(HEADTYPE == Hwindows) {
// movq %gs:0x58, %rcx
// movq (%rcx), %rcx
p->as = AMOVQ;
@@ -724,15 +718,3 @@ atolwhex(char *s)
n = -n;
return n;
}
-
-void
-undef(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->hash)
- if(s->type == SXREF)
- diag("%s: not defined", s->name);
-}
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index d5fa959aa..ca18b69ce 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -332,6 +332,7 @@ struct
"CMPSB", LTYPE0, ACMPSB,
"CMPSL", LTYPE0, ACMPSL,
"CMPSW", LTYPE0, ACMPSW,
+ "CMPXCHG8B", LTYPE1, ACMPXCHG8B,
"CMPXCHGB", LTYPE3, ACMPXCHGB,
"CMPXCHGL", LTYPE3, ACMPXCHGL,
"CMPXCHGW", LTYPE3, ACMPXCHGW,
@@ -546,6 +547,9 @@ struct
"VERW", LTYPE2, AVERW,
"WAIT", LTYPE0, AWAIT,
"WORD", LTYPE2, AWORD,
+ "XADDB", LTYPE3, AXADDB,
+ "XADDL", LTYPE3, AXADDL,
+ "XADDW", LTYPE3, AXADDW,
"XCHGB", LTYPE3, AXCHGB,
"XCHGL", LTYPE3, AXCHGL,
"XCHGW", LTYPE3, AXCHGW,
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 0866f05f0..03db0016b 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -392,6 +392,11 @@ enum as
ACMPXCHGB,
ACMPXCHGL,
ACMPXCHGW,
+ ACMPXCHG8B,
+
+ AXADDB,
+ AXADDL,
+ AXADDW,
/* conditional move */
ACMOVLCC,
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index d90eab7e7..1e760d89e 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -246,7 +246,7 @@ adddynrel(Sym *s, Reloc *r)
r->sym = S;
return;
}
- if(HEADTYPE == 6 && s->size == PtrSize && r->off == 0) {
+ if(HEADTYPE == Hdarwin && s->size == PtrSize && r->off == 0) {
// Mach-O relocations are a royal pain to lay out.
// They use a compact stateful bytecode representation
// that is too much bother to deal with.
@@ -356,7 +356,7 @@ addpltsym(Sym *s)
adduint32(rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT));
s->plt = plt->size - 16;
- } else if(HEADTYPE == 6) { // Mach-O
+ } else if(HEADTYPE == Hdarwin) {
// Same laziness as in 6l.
Sym *plt;
@@ -395,7 +395,7 @@ addgotsym(Sym *s)
rel = lookup(".rel", 0);
addaddrplus(rel, got, s->got);
adduint32(rel, ELF32_R_INFO(s->dynid, R_386_GLOB_DAT));
- } else if(HEADTYPE == 6) { // Mach-O
+ } else if(HEADTYPE == Hdarwin) {
adduint32(lookup(".linkedit.got", 0), s->dynid);
} else {
diag("addgotsym: unsupported binary format");
@@ -465,7 +465,7 @@ adddynsym(Sym *s)
}
adduint16(d, t);
}
- } else if(HEADTYPE == 6) {
+ } else if(HEADTYPE == Hdarwin) {
// Mach-O symbol nlist32
d = lookup(".dynsym", 0);
name = s->dynimpname;
@@ -481,7 +481,7 @@ adddynsym(Sym *s)
adduint8(d, 0); // section
adduint16(d, 0); // desc
adduint32(d, 0); // value
- } else if(HEADTYPE != 10) {
+ } else if(HEADTYPE != Hwindows) {
diag("adddynsym: unsupported binary format");
}
}
@@ -499,9 +499,9 @@ adddynlib(char *lib)
if(s->size == 0)
addstring(s, "");
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib));
- } else if(HEADTYPE == 6) { // Mach-O
+ } else if(HEADTYPE == Hdarwin) {
machoadddynlib(lib);
- } else if(HEADTYPE != 10) {
+ } else if(HEADTYPE != Hwindows) {
diag("adddynlib: unsupported binary format");
}
}
@@ -673,7 +673,7 @@ asmb(void)
datblk(segdata.vaddr, segdata.filelen);
machlink = 0;
- if(HEADTYPE == 6)
+ if(HEADTYPE == Hdarwin)
machlink = domacholink();
if(iself) {
@@ -697,28 +697,28 @@ asmb(void)
default:
if(iself)
goto Elfsym;
- case 0:
+ case Hgarbunix:
seek(cout, rnd(HEADR+segtext.filelen, 8192)+segdata.filelen, 0);
break;
- case 1:
+ case Hunixcoff:
seek(cout, rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen, 0);
break;
- case 2:
+ case Hplan9x32:
symo = HEADR+segtext.filelen+segdata.filelen;
break;
- case 3:
- case 4:
+ case Hmsdoscom:
+ case Hmsdosexe:
debug['s'] = 1;
symo = HEADR+segtext.filelen+segdata.filelen;
break;
- case 6:
+ case Hdarwin:
symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
break;
Elfsym:
symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND);
break;
- case 10:
+ case Hwindows:
// TODO(brainman): not sure what symo meant to be, but it is not used for Windows PE for now anyway
symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
symo = rnd(symo, PEFILEALIGN);
@@ -727,7 +727,7 @@ asmb(void)
if(!debug['s']) {
seek(cout, symo, 0);
- if(HEADTYPE == 2) {
+ if(HEADTYPE == Hplan9x32) {
asmplan9sym();
cflush();
@@ -740,7 +740,7 @@ asmb(void)
cflush();
}
- } else if(HEADTYPE != 10) {
+ } else if(HEADTYPE != Hwindows) {
if(debug['v'])
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
@@ -755,7 +755,7 @@ asmb(void)
default:
if(iself)
goto Elfput;
- case 0: /* garbage */
+ case Hgarbunix: /* garbage */
lputb(0x160L<<16); /* magic and sections */
lputb(0L); /* time and date */
lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen);
@@ -777,7 +777,7 @@ asmb(void)
lputb(~0L); /* gp value ?? */
break;
lputl(0); /* x */
- case 1: /* unix coff */
+ case Hunixcoff: /* unix coff */
/*
* file header
*/
@@ -845,7 +845,7 @@ asmb(void)
lputl(0); /* relocation, line numbers */
lputl(0x200); /* flags comment only */
break;
- case 2: /* plan9 */
+ case Hplan9x32: /* plan9 */
magic = 4*11*11+7;
lputb(magic); /* magic */
lputb(segtext.filelen); /* sizes */
@@ -856,10 +856,10 @@ asmb(void)
lputb(spsize); /* sp offsets */
lputb(lcsize); /* line offsets */
break;
- case 3:
+ case Hmsdoscom:
/* MS-DOS .COM */
break;
- case 4:
+ case Hmsdosexe:
/* fake MS-DOS .EXE */
v = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
wputl(0x5A4D); /* 'MZ' */
@@ -882,13 +882,13 @@ asmb(void)
wputl(0x0000); /* overlay number */
break;
- case 6:
+ case Hdarwin:
asmbmacho();
break;
Elfput:
/* elf 386 */
- if(HEADTYPE == 11)
+ if(HEADTYPE == Htiny)
debug['d'] = 1;
eh = getElfEhdr();
@@ -917,10 +917,10 @@ asmb(void)
sh->addralign = 1;
if(interpreter == nil) {
switch(HEADTYPE) {
- case 7:
+ case Hlinux:
interpreter = linuxdynld;
break;
- case 9:
+ case Hfreebsd:
interpreter = freebsddynld;
break;
}
@@ -1068,7 +1068,7 @@ asmb(void)
eh->ident[EI_DATA] = ELFDATA2LSB;
eh->ident[EI_VERSION] = EV_CURRENT;
switch(HEADTYPE) {
- case 9:
+ case Hfreebsd:
eh->ident[EI_OSABI] = 9;
break;
}
@@ -1093,7 +1093,7 @@ asmb(void)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
- case 10:
+ case Hwindows:
asmbpe();
break;
}
diff --git a/src/cmd/8l/doc.go b/src/cmd/8l/doc.go
index ef5ebc31d..b70888907 100644
--- a/src/cmd/8l/doc.go
+++ b/src/cmd/8l/doc.go
@@ -25,10 +25,16 @@ Options new in this version:
Elide the dynamic linking header. With this option, the binary
is statically linked and does not refer to dynld. Without this option
(the default), the binary's contents are identical but it is loaded with dynld.
--H6
+-Hplan9
+ Write Plan 9 32-bit format binaries (default when $GOOS is plan9)
+-Hdarwin
Write Apple Mach-O binaries (default when $GOOS is darwin)
--H7
+-Hlinux
Write Linux ELF binaries (default when $GOOS is linux)
+-Hfreebsd
+ Write FreeBSD ELF binaries (default when $GOOS is freebsd)
+-Hwindows
+ Write Windows PE32 binaries (default when $GOOS is windows)
-I interpreter
Set the ELF dynamic linker to use.
-L dir1 -L dir2
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index f2546cf20..e4650ee58 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -39,6 +39,7 @@
enum
{
+ thechar = '8',
PtrSize = 4
};
@@ -110,6 +111,7 @@ struct Prog
};
#define datasize from.scale
#define textflag from.scale
+#define iscall(p) ((p)->as == ACALL)
struct Auto
{
@@ -128,6 +130,7 @@ struct Sym
uchar reachable;
uchar dynexport;
uchar special;
+ uchar stkcheck;
int32 value;
int32 size;
int32 sig;
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 9c687f2fc..d505dc10e 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -44,21 +44,36 @@
#endif
char *noname = "<none>";
-char thechar = '8';
char *thestring = "386";
+Header headers[] = {
+ "garbunix", Hgarbunix,
+ "unixcoff", Hunixcoff,
+ "plan9", Hplan9x32,
+ "msdoscom", Hmsdoscom,
+ "msdosexe", Hmsdosexe,
+ "darwin", Hdarwin,
+ "linux", Hlinux,
+ "nacl", Hnacl,
+ "freebsd", Hfreebsd,
+ "windows", Hwindows,
+ "windowsgui", Hwindows,
+ "tiny", Htiny,
+ 0, 0
+};
+
/*
- * -H0 -T0x40004C -D0x10000000 is garbage unix
- * -H1 -T0xd0 -R4 is unix coff
- * -H2 -T4128 -R4096 is plan9 format
- * -H3 -Tx -Rx is MS-DOS .COM
- * -H4 -Tx -Rx is fake MS-DOS .EXE
- * -H6 -Tx -Rx is Apple Mach-O
- * -H7 -Tx -Rx is Linux ELF32
- * -H8 -Tx -Rx was Google Native Client
- * -H9 -Tx -Rx is FreeBSD ELF32
- * -H10 -Tx -Rx is MS Windows PE
- * -H11 -Tx -Rx is tiny (os image)
+ * -Hgarbunix -T0x40004C -D0x10000000 is garbage unix
+ * -Hunixcoff -T0xd0 -R4 is unix coff
+ * -Hplan9 -T4128 -R4096 is plan9 format
+ * -Hmsdoscom -Tx -Rx is MS-DOS .COM
+ * -Hmsdosexe -Tx -Rx is fake MS-DOS .EXE
+ * -Hdarwin -Tx -Rx is Apple Mach-O
+ * -Hlinux -Tx -Rx is Linux ELF32
+ * -Hnacl -Tx -Rx was Google Native Client
+ * -Hfreebsd -Tx -Rx is FreeBSD ELF32
+ * -Hwindows -Tx -Rx is MS Windows PE32
+ * -Htiny -Tx -Rx is tiny (os image)
*/
void
@@ -100,7 +115,7 @@ main(int argc, char *argv[])
INITENTRY = EARGF(usage());
break;
case 'H':
- HEADTYPE = atolwhex(EARGF(usage()));
+ HEADTYPE = headtype(EARGF(usage()));
break;
case 'I':
interpreter = EARGF(usage());
@@ -130,46 +145,24 @@ main(int argc, char *argv[])
mywhatsys(); // get goos
- if(HEADTYPE == -1) {
- HEADTYPE = 2;
- if(strcmp(goos, "linux") == 0)
- HEADTYPE = 7;
- else
- if(strcmp(goos, "darwin") == 0)
- HEADTYPE = 6;
- else
- if(strcmp(goos, "freebsd") == 0)
- HEADTYPE = 9;
- else
- if(strcmp(goos, "windows") == 0)
- HEADTYPE = 10;
- else
- if(strcmp(goos, "tiny") == 0)
- HEADTYPE = 11;
- else
- if(strcmp(goos, "plan9") == 0)
- HEADTYPE = 2;
- else
- print("goos is not known: %s\n", goos);
- }
+ if(HEADTYPE == -1)
+ HEADTYPE = headtype(goos);
if(outfile == nil) {
- if(HEADTYPE == 10)
+ if(HEADTYPE == Hwindows)
outfile = "8.out.exe";
else
outfile = "8.out";
}
libinit();
- if(rpath == nil)
- rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
switch(HEADTYPE) {
default:
diag("unknown -H option");
errorexit();
- case 0: /* this is garbage */
+ case Hgarbunix: /* this is garbage */
HEADR = 20L+56L;
if(INITTEXT == -1)
INITTEXT = 0x40004CL;
@@ -178,7 +171,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 0;
break;
- case 1: /* is unix coff */
+ case Hunixcoff: /* is unix coff */
HEADR = 0xd0L;
if(INITTEXT == -1)
INITTEXT = 0xd0;
@@ -187,7 +180,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 0;
break;
- case 2: /* plan 9 */
+ case Hplan9x32: /* plan 9 */
tlsoffset = -8;
HEADR = 32L;
if(INITTEXT == -1)
@@ -197,7 +190,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 1;
break;
- case 3: /* MS-DOS .COM */
+ case Hmsdoscom: /* MS-DOS .COM */
HEADR = 0;
if(INITTEXT == -1)
INITTEXT = 0x0100;
@@ -206,7 +199,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4;
break;
- case 4: /* fake MS-DOS .EXE */
+ case Hmsdosexe: /* fake MS-DOS .EXE */
HEADR = 0x200;
if(INITTEXT == -1)
INITTEXT = 0x0100;
@@ -218,7 +211,7 @@ main(int argc, char *argv[])
if(debug['v'])
Bprint(&bso, "HEADR = 0x%d\n", HEADR);
break;
- case 6: /* apple MACH */
+ case Hdarwin: /* apple MACH */
/*
* OS X system constant - offset from %gs to our TLS.
* Explained in ../../libcgo/darwin_386.c.
@@ -233,8 +226,8 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 7: /* elf32 executable */
- case 9:
+ case Hlinux: /* elf32 executable */
+ case Hfreebsd:
/*
* ELF uses TLS offsets negative from %gs.
* Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).
@@ -251,7 +244,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case 10: /* PE executable */
+ case Hwindows: /* PE executable */
peinit();
HEADR = PEFILEHEADR;
if(INITTEXT == -1)
@@ -261,7 +254,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = PESECTALIGN;
break;
- case 11:
+ case Htiny:
tlsoffset = 0;
elfinit();
HEADR = ELFRESERVE;
@@ -306,9 +299,9 @@ main(int argc, char *argv[])
patch();
follow();
doelf();
- if(HEADTYPE == 6)
+ if(HEADTYPE == Hdarwin)
domacho();
- if(HEADTYPE == 10)
+ if(HEADTYPE == Hwindows)
dope();
dostkoff();
if(debug['p'])
@@ -323,6 +316,7 @@ main(int argc, char *argv[])
symtab();
dodata();
address();
+ doweak();
reloc();
asmb();
undef();
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
index fceab785d..1e89a2105 100644
--- a/src/cmd/8l/optab.c
+++ b/src/cmd/8l/optab.c
@@ -702,6 +702,11 @@ Optab optab[] =
{ ACMPXCHGB, yrb_mb, Pm, 0xb0 },
{ ACMPXCHGL, yrl_ml, Pm, 0xb1 },
{ ACMPXCHGW, yrl_ml, Pm, 0xb1 },
+ { ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
+
+ { AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
+ { AXADDL, yrl_ml, Pm, 0xc1 },
+ { AXADDW, yrl_ml, Pe, 0x0f,0xc1 },
{ ACMOVLCC, yml_rl, Pm, 0x43 },
{ ACMOVLCS, yml_rl, Pm, 0x42 },
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 67acfa167..294926f29 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -262,12 +262,13 @@ patch(void)
s = lookup("exit", 0);
vexit = s->value;
- if(HEADTYPE == 2)
+ plan9_tos = S;
+ if(HEADTYPE == Hplan9x32)
plan9_tos = lookup("_tos", 0);
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
- if(HEADTYPE == 10) { // Windows
+ if(HEADTYPE == Hwindows) {
// Convert
// op n(GS), reg
// to
@@ -288,7 +289,7 @@ patch(void)
p->from.offset = 0x2C;
}
}
- if(HEADTYPE == 7) { // Linux
+ if(HEADTYPE == Hlinux) {
// Running binaries under Xen requires using
// MOVL 0(GS), reg
// and then off(reg) instead of saying off(GS) directly
@@ -305,7 +306,7 @@ patch(void)
p->from.offset = 0;
}
}
- if(HEADTYPE == 2) { // Plan 9
+ if(HEADTYPE == Hplan9x32) {
if(p->from.type == D_INDIR+D_GS
&& p->to.type >= D_AX && p->to.type <= D_DI) {
q = appendp(p);
@@ -412,7 +413,8 @@ dostkoff(void)
symmorestack->text->from.scale |= NOSPLIT;
}
- if(HEADTYPE == 2)
+ plan9_tos = S;
+ if(HEADTYPE == Hplan9x32)
plan9_tos = lookup("_tos", 0);
for(cursym = textp; cursym != nil; cursym = cursym->next) {
@@ -430,7 +432,7 @@ dostkoff(void)
if(!(p->from.scale & NOSPLIT)) {
p = appendp(p); // load g into CX
switch(HEADTYPE) {
- case 10: // Windows
+ case Hwindows:
p->as = AMOVL;
p->from.type = D_INDIR+D_FS;
p->from.offset = 0x2c;
@@ -443,7 +445,7 @@ dostkoff(void)
p->to.type = D_CX;
break;
- case 7: // Linux
+ case Hlinux:
p->as = AMOVL;
p->from.type = D_INDIR+D_GS;
p->from.offset = 0;
@@ -456,7 +458,7 @@ dostkoff(void)
p->to.type = D_CX;
break;
- case 2: // Plan 9
+ case Hplan9x32:
p->as = AMOVL;
p->from.type = D_EXTERN;
p->from.sym = plan9_tos;
@@ -664,15 +666,3 @@ atolwhex(char *s)
n = -n;
return n;
}
-
-void
-undef(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->hash)
- if(s->type == SXREF)
- diag("%s(%d): not defined", s->name, s->version);
-}
diff --git a/src/cmd/Makefile b/src/cmd/Makefile
new file mode 100644
index 000000000..104e9f5df
--- /dev/null
+++ b/src/cmd/Makefile
@@ -0,0 +1,66 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../Make.inc
+
+all: install
+
+# Only build tools for current architecture, and only tools written in C.
+# The tools written in Go are managed by ../pkg/Makefile.
+DIRS=\
+ $(O)a\
+ $(O)c\
+ $(O)g\
+ $(O)l\
+ cc\
+ cov\
+ gc\
+ godefs\
+ gopack\
+ gotest\
+ nm\
+ prof\
+
+# Clean applies to all directories, even for other architectures or
+# written in Go.
+CLEANDIRS=\
+ $(DIRS)\
+ 5a\
+ 5c\
+ 5g\
+ 5l\
+ 6a\
+ 6c\
+ 6g\
+ 6l\
+ 8a\
+ 8c\
+ 8g\
+ 8l\
+ cgo\
+ ebnflint\
+ godoc\
+ gofmt\
+ goinstall\
+ goyacc\
+ hgpatch\
+
+install: $(patsubst %,%.install,$(DIRS))
+clean: $(patsubst %,%.clean,$(CLEANDIRS))
+
+%.install:
+ @echo
+ @echo %%%% making $* %%%%
+ @echo
+ $(MAKE) -C $* install
+
+gc.install $(O)c.install: cc.install
+$(O)g.install: gc.install
+$(O)a.install $(O)c.install $(O)g.install: $(O)l.install
+
+%.clean:
+ $(MAKE) -C $* clean
+
+echo-dirs:
+ @echo $(DIRS)
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index e6ce21ed3..f7ecc9e14 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -599,7 +599,7 @@ func (p *Package) gccMachine() string {
return "-m32"
}
-const gccTmp = "_cgo_.o"
+const gccTmp = "_obj/_cgo_.o"
// gccCmd returns the gcc command line to use for compiling
// the input.
@@ -776,6 +776,32 @@ var dwarfToName = map[string]string{
const signedDelta = 64
+// String returns the current type representation. Format arguments
+// are assembled within this method so that any changes in mutable
+// values are taken into account.
+func (tr *TypeRepr) String() string {
+ if len(tr.Repr) == 0 {
+ return ""
+ }
+ if len(tr.FormatArgs) == 0 {
+ return tr.Repr
+ }
+ return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
+}
+
+// Empty returns true if the result of String would be "".
+func (tr *TypeRepr) Empty() bool {
+ return len(tr.Repr) == 0
+}
+
+// Set modifies the type representation.
+// If fargs are provided, repr is used as a format for fmt.Sprintf.
+// Otherwise, repr is used unprocessed as the type representation.
+func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
+ tr.Repr = repr
+ tr.FormatArgs = fargs
+}
+
// Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field.
func (c *typeConv) Type(dtype dwarf.Type) *Type {
@@ -789,16 +815,15 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t := new(Type)
t.Size = dtype.Size()
t.Align = -1
- t.C = dtype.Common().Name
- t.EnumValues = nil
+ t.C = &TypeRepr{Repr: dtype.Common().Name}
c.m[dtype] = t
if t.Size < 0 {
// Unsized types are [0]byte
t.Size = 0
t.Go = c.Opaque(0)
- if t.C == "" {
- t.C = "void"
+ if t.C.Empty() {
+ t.C.Set("void")
}
return t
}
@@ -827,7 +852,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
sub := c.Type(dt.Type)
t.Align = sub.Align
gt.Elt = sub.Go
- t.C = fmt.Sprintf("typeof(%s[%d])", sub.C, dt.Count)
+ t.C.Set("typeof(%s[%d])", sub.C, dt.Count)
case *dwarf.BoolType:
t.Go = c.bool
@@ -844,7 +869,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
if t.Align = t.Size; t.Align >= c.ptrSize {
t.Align = c.ptrSize
}
- t.C = "enum " + dt.EnumName
+ t.C.Set("enum " + dt.EnumName)
signed := 0
t.EnumValues = make(map[string]int64)
for _, ev := range dt.Val {
@@ -932,7 +957,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
// Translate void* as unsafe.Pointer
if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
t.Go = c.unsafePointer
- t.C = "void*"
+ t.C.Set("void*")
break
}
@@ -940,7 +965,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t.Go = gt // publish before recursive call
sub := c.Type(dt.Type)
gt.X = sub.Go
- t.C = sub.C + "*"
+ t.C.Set("%s*", sub.C)
case *dwarf.QualType:
// Ignore qualifier.
@@ -955,21 +980,21 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
if tag == "" {
tag = "__" + strconv.Itoa(tagGen)
tagGen++
- } else if t.C == "" {
- t.C = dt.Kind + " " + tag
+ } else if t.C.Empty() {
+ t.C.Set(dt.Kind + " " + tag)
}
name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
t.Go = name // publish before recursive calls
switch dt.Kind {
case "union", "class":
typedef[name.Name] = c.Opaque(t.Size)
- if t.C == "" {
- t.C = fmt.Sprintf("typeof(unsigned char[%d])", t.Size)
+ if t.C.Empty() {
+ t.C.Set("typeof(unsigned char[%d])", t.Size)
}
case "struct":
g, csyntax, align := c.Struct(dt)
- if t.C == "" {
- t.C = csyntax
+ if t.C.Empty() {
+ t.C.Set(csyntax)
}
t.Align = align
typedef[name.Name] = g
@@ -1024,7 +1049,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.VoidType:
t.Go = c.void
- t.C = "void"
+ t.C.Set("void")
}
switch dtype.(type) {
@@ -1041,7 +1066,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
}
}
- if t.C == "" {
+ if t.C.Empty() {
fatal("internal error: did not create C name for %s", dtype)
}
@@ -1056,11 +1081,13 @@ func (c *typeConv) FuncArg(dtype dwarf.Type) *Type {
case *dwarf.ArrayType:
// Arrays are passed implicitly as pointers in C.
// In Go, we must be explicit.
+ tr := &TypeRepr{}
+ tr.Set("%s*", t.C)
return &Type{
Size: c.ptrSize,
Align: c.ptrSize,
Go: &ast.StarExpr{X: t.Go},
- C: t.C + "*",
+ C: tr,
}
case *dwarf.TypedefType:
// C has much more relaxed rules than Go for
@@ -1189,7 +1216,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[f.Name])}, Type: t.Go}
off += t.Size
- buf.WriteString(t.C)
+ buf.WriteString(t.C.String())
buf.WriteString(" ")
buf.WriteString(f.Name)
buf.WriteString("; ")
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index b15d34527..2dc662de5 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -82,11 +82,17 @@ type ExpFunc struct {
ExpName string // name to use from C
}
+// A TypeRepr contains the string representation of a type.
+type TypeRepr struct {
+ Repr string
+ FormatArgs []interface{}
+}
+
// A Type collects information about a type in both the C and Go worlds.
type Type struct {
Size int64
Align int64
- C string
+ C *TypeRepr
Go ast.Expr
EnumValues map[string]int64
}
@@ -215,6 +221,10 @@ func main() {
fs[i] = f
}
+ // make sure that _obj directory exists, so that we can write
+ // all the output files there.
+ os.Mkdir("_obj", 0777)
+
for i, input := range goFiles {
f := fs[i]
p.Translate(f)
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index ede8f57d8..4a5fa6a73 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -20,20 +20,11 @@ import (
// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Package) writeDefs() {
- // The path for the shared object is slash-free so that ELF loaders
- // will treat it as a relative path. We rewrite slashes to underscores.
- sopath := "cgo_" + strings.Map(slashToUnderscore, p.PackagePath)
- soprefix := ""
- if os.Getenv("GOOS") == "darwin" {
- // OS X requires its own prefix for a relative path
- soprefix = "@rpath/"
- }
-
- fgo2 := creat("_cgo_gotypes.go")
- fc := creat("_cgo_defun.c")
- fm := creat("_cgo_main.c")
+ fgo2 := creat("_obj/_cgo_gotypes.go")
+ fc := creat("_obj/_cgo_defun.c")
+ fm := creat("_obj/_cgo_main.c")
- fflg := creat("_cgo_flags")
+ fflg := creat("_obj/_cgo_flags")
for k, v := range p.CgoFlags {
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
}
@@ -94,7 +85,7 @@ func (p *Package) writeDefs() {
for _, n := range p.Name {
if n.FuncType != nil {
- p.writeDefsFunc(fc, fgo2, n, soprefix, sopath)
+ p.writeDefsFunc(fc, fgo2, n)
}
}
@@ -172,7 +163,7 @@ func (p *Package) structType(n *Name) (string, int64) {
off += pad
}
qual := ""
- if t.C[len(t.C)-1] == '*' {
+ if c := t.C.String(); c[len(c)-1] == '*' {
qual = "const "
}
fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
@@ -189,13 +180,12 @@ func (p *Package) structType(n *Name) (string, int64) {
}
if off == 0 {
fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
- off++
}
fmt.Fprintf(&buf, "\t}")
return buf.String(), off
}
-func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name, soprefix, sopath string) {
+func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
name := n.Go
gtype := n.FuncType.Go
if n.AddError {
@@ -234,6 +224,9 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name, soprefix, sopath str
fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
fmt.Fprintf(fc, "\n")
fmt.Fprintf(fc, "void\n")
+ if argSize == 0 {
+ argSize++
+ }
fmt.Fprintf(fc, "·%s(struct{uint8 x[%d];}p)\n", n.Mangle, argSize)
fmt.Fprintf(fc, "{\n")
fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
@@ -271,8 +264,8 @@ func (p *Package) writeOutput(f *File, srcfile string) {
base = base[0 : len(base)-3]
}
base = strings.Map(slashToUnderscore, base)
- fgo1 := creat(base + ".cgo1.go")
- fgcc := creat(base + ".cgo2.c")
+ fgo1 := creat("_obj/" + base + ".cgo1.go")
+ fgcc := creat("_obj/" + base + ".cgo2.c")
p.GoFiles = append(p.GoFiles, base+".cgo1.go")
p.GccFiles = append(p.GccFiles, base+".cgo2.c")
@@ -340,7 +333,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fc, fm *os.File) {
- fgcc := creat("_cgo_export.c")
+ fgcc := creat("_obj/_cgo_export.c")
fgcch := creat("_cgo_export.h")
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
@@ -401,7 +394,6 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
}
if ctype == "struct {\n" {
ctype += "\t\tchar unused;\n" // avoid empty struct
- off++
}
ctype += "\t}"
@@ -411,7 +403,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
if fntype.Results == nil || len(fntype.Results.List) == 0 {
gccResult = "void"
} else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
- gccResult = p.cgoType(fntype.Results.List[0].Type).C
+ gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
} else {
fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
@@ -426,7 +418,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
// Build the wrapper function compiled by gcc.
s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
if fn.Recv != nil {
- s += p.cgoType(fn.Recv.List[0].Type).C
+ s += p.cgoType(fn.Recv.List[0].Type).C.String()
s += " recv"
}
forFieldList(fntype.Params,
@@ -453,7 +445,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
func(i int, atype ast.Expr) {
fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
})
- fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, (int) sizeof a);\n", cPrefix, exp.ExpName)
+ fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
if gccResult != "void" {
if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
fmt.Fprintf(fgcc, "\treturn a.r0;\n")
@@ -542,24 +534,28 @@ func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
}
}
+func c(repr string, args ...interface{}) *TypeRepr {
+ return &TypeRepr{repr, args}
+}
+
// Map predeclared Go types to Type.
var goTypes = map[string]*Type{
- "int": &Type{Size: 4, Align: 4, C: "int"},
- "uint": &Type{Size: 4, Align: 4, C: "uint"},
- "int8": &Type{Size: 1, Align: 1, C: "schar"},
- "uint8": &Type{Size: 1, Align: 1, C: "uchar"},
- "int16": &Type{Size: 2, Align: 2, C: "short"},
- "uint16": &Type{Size: 2, Align: 2, C: "ushort"},
- "int32": &Type{Size: 4, Align: 4, C: "int"},
- "uint32": &Type{Size: 4, Align: 4, C: "uint"},
- "int64": &Type{Size: 8, Align: 8, C: "int64"},
- "uint64": &Type{Size: 8, Align: 8, C: "uint64"},
- "float": &Type{Size: 4, Align: 4, C: "float"},
- "float32": &Type{Size: 4, Align: 4, C: "float"},
- "float64": &Type{Size: 8, Align: 8, C: "double"},
- "complex": &Type{Size: 8, Align: 8, C: "__complex float"},
- "complex64": &Type{Size: 8, Align: 8, C: "__complex float"},
- "complex128": &Type{Size: 16, Align: 16, C: "__complex double"},
+ "int": &Type{Size: 4, Align: 4, C: c("int")},
+ "uint": &Type{Size: 4, Align: 4, C: c("uint")},
+ "int8": &Type{Size: 1, Align: 1, C: c("schar")},
+ "uint8": &Type{Size: 1, Align: 1, C: c("uchar")},
+ "int16": &Type{Size: 2, Align: 2, C: c("short")},
+ "uint16": &Type{Size: 2, Align: 2, C: c("ushort")},
+ "int32": &Type{Size: 4, Align: 4, C: c("int")},
+ "uint32": &Type{Size: 4, Align: 4, C: c("uint")},
+ "int64": &Type{Size: 8, Align: 8, C: c("int64")},
+ "uint64": &Type{Size: 8, Align: 8, C: c("uint64")},
+ "float": &Type{Size: 4, Align: 4, C: c("float")},
+ "float32": &Type{Size: 4, Align: 4, C: c("float")},
+ "float64": &Type{Size: 8, Align: 8, C: c("double")},
+ "complex": &Type{Size: 8, Align: 8, C: c("__complex float")},
+ "complex64": &Type{Size: 8, Align: 8, C: c("__complex float")},
+ "complex128": &Type{Size: 16, Align: 16, C: c("__complex double")},
}
// Map an ast type to a Type.
@@ -567,21 +563,21 @@ func (p *Package) cgoType(e ast.Expr) *Type {
switch t := e.(type) {
case *ast.StarExpr:
x := p.cgoType(t.X)
- return &Type{Size: p.PtrSize, Align: p.PtrSize, C: x.C + "*"}
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
case *ast.ArrayType:
if t.Len == nil {
- return &Type{Size: p.PtrSize + 8, Align: p.PtrSize, C: "GoSlice"}
+ return &Type{Size: p.PtrSize + 8, Align: p.PtrSize, C: c("GoSlice")}
}
case *ast.StructType:
// TODO
case *ast.FuncType:
- return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "void*"}
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
case *ast.InterfaceType:
- return &Type{Size: 3 * p.PtrSize, Align: p.PtrSize, C: "GoInterface"}
+ return &Type{Size: 3 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
case *ast.MapType:
- return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "GoMap"}
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
case *ast.ChanType:
- return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "GoChan"}
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
case *ast.Ident:
// Look up the type in the top level declarations.
// TODO: Handle types defined within a function.
@@ -606,10 +602,10 @@ func (p *Package) cgoType(e ast.Expr) *Type {
}
}
if t.Name == "uintptr" {
- return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "uintptr"}
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")}
}
if t.Name == "string" {
- return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: "GoString"}
+ return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")}
}
if r, ok := goTypes[t.Name]; ok {
if r.Align > p.PtrSize {
@@ -620,11 +616,11 @@ func (p *Package) cgoType(e ast.Expr) *Type {
case *ast.SelectorExpr:
id, ok := t.X.(*ast.Ident)
if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
- return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "void*"}
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
}
}
error(e.Pos(), "unrecognized Go type %T", e)
- return &Type{Size: 4, Align: 4, C: "int"}
+ return &Type{Size: 4, Align: 4, C: c("int")}
}
const gccProlog = `
diff --git a/src/cmd/clean.bash b/src/cmd/clean.bash
deleted file mode 100644
index 92d8cc5c9..000000000
--- a/src/cmd/clean.bash
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-gomake=gomake
-if [ "$1" == "--gomake" -a "$2" != "" ]; then
- gomake=$2
-fi
-
-for i in cc 6l 6a 6c 8l 8a 8c 8g 5l 5a 5c 5g gc 6g gopack nm cgo cov ebnflint godefs godoc gofmt goinstall gotest goyacc hgpatch prof
-do
- cd $i
- $gomake clean
- cd ..
-done
diff --git a/src/cmd/ebnflint/ebnflint.go b/src/cmd/ebnflint/ebnflint.go
index 5eb398735..cac39179f 100644
--- a/src/cmd/ebnflint/ebnflint.go
+++ b/src/cmd/ebnflint/ebnflint.go
@@ -13,7 +13,7 @@ import (
"go/token"
"io/ioutil"
"os"
- "path"
+ "path/filepath"
)
@@ -91,7 +91,7 @@ func main() {
os.Exit(1)
}
- if path.Ext(filename) == ".html" {
+ if filepath.Ext(filename) == ".html" {
src = extractEBNF(src)
}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 0ee693c02..a54c40f6c 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -1051,12 +1051,12 @@ int
cmpslit(Node *l, Node *r)
{
int32 l1, l2, i, m;
- char *s1, *s2;
+ uchar *s1, *s2;
l1 = l->val.u.sval->len;
l2 = r->val.u.sval->len;
- s1 = l->val.u.sval->s;
- s2 = r->val.u.sval->s;
+ s1 = (uchar*)l->val.u.sval->s;
+ s2 = (uchar*)r->val.u.sval->s;
m = l1;
if(l2 < m)
diff --git a/src/cmd/gc/doc.go b/src/cmd/gc/doc.go
index 21e1b103b..3fe7fafdd 100644
--- a/src/cmd/gc/doc.go
+++ b/src/cmd/gc/doc.go
@@ -43,6 +43,8 @@ Flags:
disable optimization
-S
write assembly language text to standard output
+ -u
+ disallow importing packages not marked as safe
-V
print the compiler version
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index 594509915..09b963f27 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -51,6 +51,12 @@ exportname(char *s)
return isupperrune(r);
}
+static int
+initname(char *s)
+{
+ return strcmp(s, "init") == 0;
+}
+
void
autoexport(Node *n, int ctxt)
{
@@ -60,7 +66,7 @@ autoexport(Node *n, int ctxt)
return;
if(n->ntype && n->ntype->op == OTFUNC && n->ntype->left) // method
return;
- if(exportname(n->sym->name) || strcmp(n->sym->name, "init") == 0)
+ if(exportname(n->sym->name) || initname(n->sym->name))
exportsym(n);
else
packagesym(n);
@@ -304,7 +310,7 @@ importsym(Sym *s, int op)
// mark the symbol so it is not reexported
if(s->def == N) {
- if(exportname(s->name))
+ if(exportname(s->name) || initname(s->name))
s->flags |= SymExport;
else
s->flags |= SymPackage; // package scope
@@ -374,7 +380,7 @@ importvar(Sym *s, Type *t, int ctxt)
{
Node *n;
- if(!exportname(s->name) && !mypackage(s))
+ if(!exportname(s->name) && !initname(s->name) && !mypackage(s))
return;
importsym(s, ONAME);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 86e3cae33..4b838a491 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -640,10 +640,15 @@ if_stmt:
{
markdcl();
}
- if_header loop_body
+ if_header
+ {
+ if($3->ntest == N)
+ yyerror("missing condition in if statement");
+ }
+ loop_body
{
$$ = $3;
- $$->nbody = $4;
+ $$->nbody = $5;
// no popdcl; maybe there's an LELSE
}
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index dc073443e..af4eb0336 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -30,19 +30,19 @@ renameinit(Node *n)
/*
* hand-craft the following initialization code
- * var initdone·<file> uint8 (1)
- * func Init·<file>() (2)
- * if initdone·<file> != 0 { (3)
- * if initdone·<file> == 2 (4)
+ * var initdone· uint8 (1)
+ * func init() (2)
+ * if initdone· != 0 { (3)
+ * if initdone· == 2 (4)
* return
* throw(); (5)
* }
- * initdone.<file> = 1; (6)
+ * initdone· = 1; (6)
* // over all matching imported symbols
- * <pkg>.init·<file>() (7)
+ * <pkg>.init() (7)
* { <init stmts> } (8)
- * init·<file>() // if any (9)
- * initdone.<file> = 2; (10)
+ * init·<n>() // if any (9)
+ * initdone· = 2; (10)
* return (11)
* }
*/
@@ -79,7 +79,7 @@ anyinit(NodeList *n)
// are there any imported init functions
for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link) {
- if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
+ if(s->name[0] != 'i' || strcmp(s->name, "init") != 0)
continue;
if(s->def == N)
continue;
@@ -118,12 +118,7 @@ fninit(NodeList *n)
// (2)
maxarg = 0;
- snprint(namebuf, sizeof(namebuf), "Init·");
-
- // this is a botch since we need a known name to
- // call the top level init function out of rt0
- if(strcmp(localpkg->name, "main") == 0)
- snprint(namebuf, sizeof(namebuf), "init");
+ snprint(namebuf, sizeof(namebuf), "init");
fn = nod(ODCLFUNC, N, N);
initsym = lookup(namebuf);
@@ -154,7 +149,7 @@ fninit(NodeList *n)
// (7)
for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link) {
- if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
+ if(s->name[0] != 'i' || strcmp(s->name, "init") != 0)
continue;
if(s->def == N)
continue;
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 36c245d47..8129bf1ce 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -10,6 +10,7 @@
static NodeList* signatlist;
static Sym* dtypesym(Type*);
+static Sym* weaktypesym(Type*);
static int
sigcmp(Sig *a, Sig *b)
@@ -570,9 +571,17 @@ dcommontype(Sym *s, int ot, Type *t)
{
int i;
Sym *s1;
+ Sym *sptr;
char *p;
dowidth(t);
+
+ sptr = nil;
+ if(t->sym != nil && !isptr[t->etype])
+ sptr = dtypesym(ptrto(t));
+ else
+ sptr = weaktypesym(ptrto(t));
+
s1 = dextratype(t);
// empty interface pointing at this type.
@@ -592,7 +601,8 @@ dcommontype(Sym *s, int ot, Type *t)
// fieldAlign uint8;
// kind uint8;
// string *string;
- // *nameInfo;
+ // *extraType;
+ // ptrToThis *Type
// }
ot = duintptr(s, ot, t->width);
ot = duint32(s, ot, typehash(t));
@@ -616,7 +626,7 @@ dcommontype(Sym *s, int ot, Type *t)
ot = dsymptr(s, ot, s1, 0); // extraType
else
ot = duintptr(s, ot, 0);
-
+ ot = dsymptr(s, ot, sptr, 0); // ptr to type
return ot;
}
@@ -662,6 +672,25 @@ typename(Type *t)
}
static Sym*
+weaktypesym(Type *t)
+{
+ char *p;
+ Sym *s;
+ static Pkg *weak;
+
+ if(weak == nil) {
+ weak = mkpkg(strlit("weak.type"));
+ weak->name = "weak.type";
+ weak->prefix = "weak.type"; // not weak%2etype
+ }
+
+ p = smprint("%#-T", t);
+ s = pkglookup(p, weak);
+ free(p);
+ return s;
+}
+
+static Sym*
dtypesym(Type *t)
{
int ot, n, isddd, dupok;
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 0755ca3cd..142e5ba41 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -203,7 +203,6 @@ fatal(char *fmt, ...)
flusherrors();
-*(int*)0=0;
print("%L: internal compiler error: ", lineno);
va_start(arg, fmt);
vfprint(1, fmt, arg);
@@ -1909,8 +1908,12 @@ assignop(Type *src, Type *dst, char **why)
return 0;
}
if(src->etype == TINTER && dst->etype != TBLANK) {
- if(why != nil)
- *why = ": need type assertion";
+ if(why != nil) {
+ if(isptrto(dst, TINTER))
+ *why = smprint(":\n\t%T is interface, not pointer to interface", src);
+ else
+ *why = ": need type assertion";
+ }
return 0;
}
@@ -2265,7 +2268,7 @@ syslook(char *name, int copy)
s = pkglookup(name, runtimepkg);
if(s == S || s->def == N)
- fatal("looksys: cant find runtime.%s", name);
+ fatal("syslook: can't find runtime.%s", name);
if(!copy)
return s->def;
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 5edca964a..3e8f35877 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -318,7 +318,7 @@ reswitch:
n->left = N;
goto ret;
}
- if(!isptr[t->etype]) {
+ if(!isptr[t->etype] || (t->type != T && t->type->etype == TANY) /* unsafe.Pointer */) {
yyerror("invalid indirect of %+N", n->left);
goto error;
}
@@ -1613,7 +1613,7 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
exportassignok(tn->type, desc);
if(assignop(tn->type, tl->type->type, &why) == 0) {
if(call != N)
- yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type->type, desc, call, why);
+ yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type->type, call, why);
else
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type->type, desc, why);
}
@@ -1625,7 +1625,7 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
exportassignok(tn->type, desc);
if(assignop(tn->type, tl->type, &why) == 0) {
if(call != N)
- yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type, desc, call, why);
+ yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type, call, why);
else
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
}
diff --git a/src/cmd/godoc/dirtrees.go b/src/cmd/godoc/dirtrees.go
index edb4a169d..3ad7c8cfc 100644
--- a/src/cmd/godoc/dirtrees.go
+++ b/src/cmd/godoc/dirtrees.go
@@ -12,8 +12,9 @@ import (
"go/parser"
"go/token"
"io/ioutil"
+ "log"
"os"
- pathutil "path"
+ "path/filepath"
"strings"
"unicode"
)
@@ -31,7 +32,7 @@ type Directory struct {
func isGoFile(f *os.FileInfo) bool {
return f.IsRegular() &&
!strings.HasPrefix(f.Name, ".") && // ignore .files
- pathutil.Ext(f.Name) == ".go"
+ filepath.Ext(f.Name) == ".go"
}
@@ -100,7 +101,13 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
return &Directory{depth, path, name, "", nil}
}
- list, _ := ioutil.ReadDir(path) // ignore errors
+ list, err := ioutil.ReadDir(path)
+ if err != nil {
+ // newDirTree is called with a path that should be a package
+ // directory; errors here should not happen, but if they do,
+ // we want to know about them
+ log.Printf("ioutil.ReadDir(%s): %s", path, err)
+ }
// determine number of subdirectories and if there are package files
ndirs := 0
@@ -116,7 +123,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
// though the directory doesn't contain any real package files - was bug)
if synopses[0] == "" {
// no "optimal" package synopsis yet; continue to collect synopses
- file, err := parser.ParseFile(fset, pathutil.Join(path, d.Name), nil,
+ file, err := parser.ParseFile(fset, filepath.Join(path, d.Name), nil,
parser.ParseComments|parser.PackageClauseOnly)
if err == nil {
hasPkgFiles = true
@@ -149,7 +156,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
i := 0
for _, d := range list {
if isPkgDir(d) {
- dd := b.newDirTree(fset, pathutil.Join(path, d.Name), d.Name, depth+1)
+ dd := b.newDirTree(fset, filepath.Join(path, d.Name), d.Name, depth+1)
if dd != nil {
dirs[i] = dd
i++
@@ -188,8 +195,16 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
// (i.e., in this case the tree may contain directories w/o any package files).
//
func newDirectory(root string, pathFilter func(string) bool, maxDepth int) *Directory {
- d, err := os.Lstat(root)
- if err != nil || !isPkgDir(d) {
+ // The root could be a symbolic link so use os.Stat not os.Lstat.
+ d, err := os.Stat(root)
+ // If we fail here, report detailed error messages; otherwise
+ // is is hard to see why a directory tree was not built.
+ switch {
+ case err != nil:
+ log.Printf("newDirectory(%s): %s", root, err)
+ return nil
+ case !isPkgDir(d):
+ log.Printf("newDirectory(%s): not a package directory", root)
return nil
}
if maxDepth < 0 {
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index c91dc33db..9dce5edf9 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -18,7 +18,8 @@ import (
"io/ioutil"
"log"
"os"
- pathutil "path"
+ "path"
+ "path/filepath"
"regexp"
"runtime"
"sort"
@@ -81,8 +82,8 @@ var (
func initHandlers() {
fsMap.Init(*pkgPath)
fileServer = http.FileServer(*goroot, "")
- cmdHandler = httpHandler{"/cmd/", pathutil.Join(*goroot, "src/cmd"), false}
- pkgHandler = httpHandler{"/pkg/", pathutil.Join(*goroot, "src/pkg"), true}
+ cmdHandler = httpHandler{"/cmd/", filepath.Join(*goroot, "src", "cmd"), false}
+ pkgHandler = httpHandler{"/pkg/", filepath.Join(*goroot, "src", "pkg"), true}
}
@@ -91,12 +92,13 @@ func registerPublicHandlers(mux *http.ServeMux) {
mux.Handle(pkgHandler.pattern, &pkgHandler)
mux.HandleFunc("/doc/codewalk/", codewalk)
mux.HandleFunc("/search", search)
+ mux.Handle("/robots.txt", fileServer)
mux.HandleFunc("/", serveFile)
}
func initFSTree() {
- fsTree.set(newDirectory(pathutil.Join(*goroot, *testDir), nil, -1))
+ fsTree.set(newDirectory(filepath.Join(*goroot, *testDir), nil, -1))
invalidateIndex()
}
@@ -147,8 +149,13 @@ func readDirList(filename string) ([]string, os.Error) {
}
// create a sorted list of valid directory names
filter := func(path string) bool {
- d, err := os.Lstat(path)
- return err == nil && isPkgDir(d)
+ d, e := os.Lstat(path)
+ if e != nil && err == nil {
+ // remember first error and return it from readDirList
+ // so we have at least some information if things go bad
+ err = e
+ }
+ return e == nil && isPkgDir(d)
}
list := canonicalizePaths(strings.Split(string(contents), "\n", -1), filter)
// for each parent path, remove all it's children q
@@ -160,7 +167,7 @@ func readDirList(filename string) ([]string, os.Error) {
i++
}
}
- return list[0:i], nil
+ return list[0:i], err
}
@@ -207,9 +214,10 @@ func initDirTrees() {
if *filter != "" {
list, err := readDirList(*filter)
if err != nil {
- log.Printf("%s", err)
- } else if len(list) == 0 {
- log.Printf("no directory paths in file %s", *filter)
+ log.Printf("readDirList(%s): %s", *filter, err)
+ }
+ if *verbose || len(list) == 0 {
+ log.Printf("found %d directory paths in file %s", len(list), *filter)
}
setPathFilter(list)
}
@@ -239,27 +247,30 @@ func initDirTrees() {
// ----------------------------------------------------------------------------
// Path mapping
-func absolutePath(path, defaultRoot string) string {
- abspath := fsMap.ToAbsolute(path)
+// Absolute paths are file system paths (backslash-separated on Windows),
+// but relative paths are always slash-separated.
+
+func absolutePath(relpath, defaultRoot string) string {
+ abspath := fsMap.ToAbsolute(relpath)
if abspath == "" {
// no user-defined mapping found; use default mapping
- abspath = pathutil.Join(defaultRoot, path)
+ abspath = filepath.Join(defaultRoot, filepath.FromSlash(relpath))
}
return abspath
}
-func relativePath(path string) string {
- relpath := fsMap.ToRelative(path)
+func relativeURL(abspath string) string {
+ relpath := fsMap.ToRelative(abspath)
if relpath == "" {
- // prefix must end in '/'
+ // prefix must end in a path separator
prefix := *goroot
- if len(prefix) > 0 && prefix[len(prefix)-1] != '/' {
- prefix += "/"
+ if len(prefix) > 0 && prefix[len(prefix)-1] != filepath.Separator {
+ prefix += string(filepath.Separator)
}
- if strings.HasPrefix(path, prefix) {
+ if strings.HasPrefix(abspath, prefix) {
// no user-defined mapping found; use default mapping
- relpath = path[len(prefix):]
+ relpath = filepath.ToSlash(abspath[len(prefix):])
}
}
// Only if path is an invalid absolute path is relpath == ""
@@ -474,7 +485,7 @@ func urlFmt(w io.Writer, format string, x ...interface{}) {
}
// map path
- relpath := relativePath(path)
+ relpath := relativeURL(path)
// convert to relative URLs so that they can also
// be used as relative file names in .txt templates
@@ -591,7 +602,7 @@ func dirslashFmt(w io.Writer, format string, x ...interface{}) {
// Template formatter for "localname" format.
func localnameFmt(w io.Writer, format string, x ...interface{}) {
- _, localname := pathutil.Split(x[0].(string))
+ _, localname := filepath.Split(x[0].(string))
template.HTMLEscape(w, []byte(localname))
}
@@ -623,7 +634,7 @@ var fmap = template.FormatterMap{
func readTemplate(name string) *template.Template {
- path := pathutil.Join(*goroot, "lib/godoc/"+name)
+ path := filepath.Join(*goroot, "lib", "godoc", name)
data, err := ioutil.ReadFile(path)
if err != nil {
log.Fatalf("ReadFile %s: %v", path, err)
@@ -760,14 +771,13 @@ func applyTemplate(t *template.Template, name string, data interface{}) []byte {
func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) {
- if canonical := pathutil.Clean(r.URL.Path) + "/"; r.URL.Path != canonical {
+ if canonical := path.Clean(r.URL.Path) + "/"; r.URL.Path != canonical {
http.Redirect(w, r, canonical, http.StatusMovedPermanently)
redirected = true
}
return
}
-
func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, title string) {
src, err := ioutil.ReadFile(abspath)
if err != nil {
@@ -778,7 +788,7 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit
var buf bytes.Buffer
buf.WriteString("<pre>")
- FormatText(&buf, src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))
+ FormatText(&buf, src, 1, filepath.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))
buf.WriteString("</pre>")
servePage(w, title+" "+relpath, "", "", buf.Bytes())
@@ -815,7 +825,7 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
// pick off special cases and hand the rest to the standard file server
switch r.URL.Path {
case "/":
- serveHTMLDoc(w, r, pathutil.Join(*goroot, "doc/root.html"), "doc/root.html")
+ serveHTMLDoc(w, r, filepath.Join(*goroot, "doc", "root.html"), "doc/root.html")
return
case "/doc/root.html":
@@ -824,9 +834,9 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
return
}
- switch pathutil.Ext(abspath) {
+ switch path.Ext(relpath) {
case ".html":
- if strings.HasSuffix(abspath, "/index.html") {
+ if strings.HasSuffix(relpath, "/index.html") {
// We'll show index.html for the directory.
// Use the dir/ version as canonical instead of dir/index.html.
http.Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len("index.html")], http.StatusMovedPermanently)
@@ -851,8 +861,8 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
if redirect(w, r) {
return
}
- if index := abspath + "/index.html"; isTextFile(index) {
- serveHTMLDoc(w, r, index, relativePath(index))
+ if index := filepath.Join(abspath, "index.html"); isTextFile(index) {
+ serveHTMLDoc(w, r, index, relativeURL(index))
return
}
serveDirectory(w, r, abspath, relpath)
@@ -948,13 +958,13 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
// the package with dirname, and the 3rd choice is a package
// that is not called "main" if there is exactly one such
// package. Otherwise, don't select a package.
- dirpath, dirname := pathutil.Split(abspath)
+ dirpath, dirname := filepath.Split(abspath)
// If the dirname is "go" we might be in a sub-directory for
// .go files - use the outer directory name instead for better
// results.
if dirname == "go" {
- _, dirname = pathutil.Split(pathutil.Clean(dirpath))
+ _, dirname = filepath.Split(filepath.Clean(dirpath))
}
var choice3 *ast.Package
@@ -995,7 +1005,7 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
ast.PackageExports(pkg)
}
if mode&genDoc != 0 {
- pdoc = doc.NewPackageDoc(pkg, pathutil.Clean(relpath)) // no trailing '/' in importpath
+ pdoc = doc.NewPackageDoc(pkg, path.Clean(relpath)) // no trailing '/' in importpath
} else {
past = ast.MergePackageFiles(pkg, ast.FilterUnassociatedComments)
}
@@ -1081,13 +1091,13 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
title = "Package " + info.PDoc.PackageName
case info.PDoc.PackageName == fakePkgName:
// assume that the directory name is the command name
- _, pkgname := pathutil.Split(pathutil.Clean(relpath))
+ _, pkgname := path.Split(path.Clean(relpath))
title = "Command " + pkgname
default:
title = "Command " + info.PDoc.PackageName
}
default:
- title = "Directory " + relativePath(info.Dirname)
+ title = "Directory " + relativeURL(info.Dirname)
if *showTimestamps {
subtitle = "Last update: " + time.SecondsToLocalTime(info.DirTime).String()
}
diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go
index 56f31f5cf..5af4d15cb 100644
--- a/src/cmd/godoc/index.go
+++ b/src/cmd/godoc/index.go
@@ -47,7 +47,7 @@ import (
"index/suffixarray"
"io/ioutil"
"os"
- "path"
+ "path/filepath"
"regexp"
"sort"
"strings"
@@ -718,7 +718,7 @@ var whitelisted = map[string]bool{
// of "permitted" files for indexing. The filename must
// be the directory-local name of the file.
func isWhitelisted(filename string) bool {
- key := path.Ext(filename)
+ key := filepath.Ext(filename)
if key == "" {
// file has no extension - use entire filename
key = filename
@@ -732,7 +732,7 @@ func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool)
return
}
- filename := path.Join(dirname, f.Name)
+ filename := filepath.Join(dirname, f.Name)
goFile := false
switch {
@@ -757,7 +757,7 @@ func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool)
if fast != nil {
// we've got a Go file to index
x.current = file
- dir, _ := path.Split(filename)
+ dir, _ := filepath.Split(filename)
pak := Pak{dir, fast.Name.Name}
x.file = &File{filename, pak}
ast.Walk(x, fast)
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index ea1e3c42e..1ebb80279 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -36,7 +36,7 @@ import (
"io"
"log"
"os"
- pathutil "path"
+ "path/filepath"
"regexp"
"runtime"
"strings"
@@ -314,14 +314,14 @@ func main() {
if len(path) > 0 && path[0] == '.' {
// assume cwd; don't assume -goroot
cwd, _ := os.Getwd() // ignore errors
- path = pathutil.Join(cwd, path)
+ path = filepath.Join(cwd, path)
}
relpath := path
abspath := path
- if !pathutil.IsAbs(path) {
+ if !filepath.IsAbs(path) {
abspath = absolutePath(path, pkgHandler.fsRoot)
} else {
- relpath = relativePath(path)
+ relpath = relativeURL(path)
}
var mode PageInfoMode
@@ -339,7 +339,7 @@ func main() {
if info.IsEmpty() {
// try again, this time assume it's a command
- if !pathutil.IsAbs(path) {
+ if !filepath.IsAbs(path) {
abspath = absolutePath(path, cmdHandler.fsRoot)
}
cmdInfo := cmdHandler.getPageInfo(abspath, relpath, "", mode)
diff --git a/src/cmd/godoc/mapping.go b/src/cmd/godoc/mapping.go
index 1d87bbc76..6ae9032e4 100644
--- a/src/cmd/godoc/mapping.go
+++ b/src/cmd/godoc/mapping.go
@@ -10,7 +10,8 @@ import (
"fmt"
"io"
"os"
- pathutil "path"
+ "path"
+ "path/filepath"
"sort"
"strings"
)
@@ -59,10 +60,10 @@ type mapping struct {
}
-// Init initializes the Mapping from a list of ':'-separated
-// paths. Empty paths are ignored; relative paths are assumed
-// to be relative to the current working directory and converted
-// to absolute paths. For each path of the form:
+// Init initializes the Mapping from a list of paths separated by
+// filepath.ListSeparator. Empty paths are ignored; relative paths
+// are assumed to be relative to the current working directory and
+// converted to absolute paths. For each path of the form:
//
// dirname/localname
//
@@ -71,7 +72,7 @@ type mapping struct {
// localname -> path
//
// is added to the Mapping object, in the order of occurrence.
-// For instance, the argument:
+// For instance, under Unix, the argument:
//
// /home/user:/home/build/public
//
@@ -81,12 +82,12 @@ type mapping struct {
// public -> /home/build/public
//
func (m *Mapping) Init(paths string) {
- pathlist := canonicalizePaths(strings.Split(paths, ":", -1), nil)
+ pathlist := canonicalizePaths(filepath.SplitList(paths), nil)
list := make([]mapping, len(pathlist))
// create mapping list
for i, path := range pathlist {
- _, prefix := pathutil.Split(path)
+ _, prefix := filepath.Split(path)
list[i] = mapping{prefix, path, new(RWValue)}
}
@@ -147,7 +148,7 @@ func (m *Mapping) Fprint(w io.Writer) {
func splitFirst(path string) (head, tail string) {
- i := strings.Index(path, "/")
+ i := strings.Index(path, string(filepath.Separator))
if i > 0 {
// 0 < i < len(path)
return path[0:i], path[i+1:]
@@ -156,22 +157,23 @@ func splitFirst(path string) (head, tail string) {
}
-// ToAbsolute maps a relative path to an absolute path using the Mapping
-// specified by the receiver. If the path cannot be mapped, the empty
-// string is returned.
+// ToAbsolute maps a slash-separated relative path to an absolute filesystem
+// path using the Mapping specified by the receiver. If the path cannot
+// be mapped, the empty string is returned.
//
-func (m *Mapping) ToAbsolute(path string) string {
- prefix, tail := splitFirst(path)
+func (m *Mapping) ToAbsolute(spath string) string {
+ fpath := filepath.FromSlash(spath)
+ prefix, tail := splitFirst(fpath)
for _, e := range m.list {
switch {
case e.prefix == prefix:
// use tail
case e.prefix == "":
- tail = path
+ tail = fpath
default:
continue // no match
}
- abspath := pathutil.Join(e.path, tail)
+ abspath := filepath.Join(e.path, tail)
if _, err := os.Stat(abspath); err == nil {
return abspath
}
@@ -181,15 +183,16 @@ func (m *Mapping) ToAbsolute(path string) string {
}
-// ToRelative maps an absolute path to a relative path using the Mapping
-// specified by the receiver. If the path cannot be mapped, the empty
-// string is returned.
+// ToRelative maps an absolute filesystem path to a relative slash-separated
+// path using the Mapping specified by the receiver. If the path cannot
+// be mapped, the empty string is returned.
//
-func (m *Mapping) ToRelative(path string) string {
+func (m *Mapping) ToRelative(fpath string) string {
for _, e := range m.list {
- if strings.HasPrefix(path, e.path) {
+ if strings.HasPrefix(fpath, e.path) {
+ spath := filepath.ToSlash(fpath)
// /absolute/prefix/foo -> prefix/foo
- return pathutil.Join(e.prefix, path[len(e.path):]) // Join will remove a trailing '/'
+ return path.Join(e.prefix, spath[len(e.path):]) // Join will remove a trailing '/'
}
}
return "" // no match
diff --git a/src/cmd/godoc/utils.go b/src/cmd/godoc/utils.go
index cc028cc4d..9517aee7a 100644
--- a/src/cmd/godoc/utils.go
+++ b/src/cmd/godoc/utils.go
@@ -10,7 +10,7 @@ import (
"io"
"io/ioutil"
"os"
- pathutil "path"
+ "path/filepath"
"sort"
"strings"
"sync"
@@ -60,10 +60,10 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {
continue // ignore empty paths (don't assume ".")
}
// len(path) > 0: normalize path
- if pathutil.IsAbs(path) {
- path = pathutil.Clean(path)
+ if filepath.IsAbs(path) {
+ path = filepath.Clean(path)
} else {
- path = pathutil.Join(cwd, path)
+ path = filepath.Join(cwd, path)
}
// we have a non-empty absolute path
if filter != nil && !filter(path) {
@@ -95,7 +95,7 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {
// atomically renames that file to the file named by filename.
//
func writeFileAtomically(filename string, data []byte) os.Error {
- f, err := ioutil.TempFile(cwd, filename)
+ f, err := ioutil.TempFile(filepath.Split(filename))
if err != nil {
return err
}
@@ -149,7 +149,7 @@ var textExt = map[string]bool{
//
func isTextFile(filename string) bool {
// if the extension is known, use it for decision making
- if isText, found := textExt[pathutil.Ext(filename)]; found {
+ if isText, found := textExt[filepath.Ext(filename)]; found {
return isText
}
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 41c12b88d..224aee717 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -15,7 +15,7 @@ import (
"go/token"
"io/ioutil"
"os"
- pathutil "path"
+ "path/filepath"
"strings"
)
@@ -181,7 +181,7 @@ func walkDir(path string) {
done <- true
}()
// walk the tree
- pathutil.Walk(path, v, v)
+ filepath.Walk(path, v, v)
close(v) // terminate error handler loop
<-done // wait for all errors to be reported
}
diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh
index 2f60a3e7b..3340c48f0 100755
--- a/src/cmd/gofmt/test.sh
+++ b/src/cmd/gofmt/test.sh
@@ -42,7 +42,7 @@ apply1() {
bug163.go | bug166.go | bug169.go | bug217.go | bug222.go | \
bug226.go | bug228.go | bug248.go | bug274.go | bug280.go | \
bug282.go | bug287.go | bug298.go | bug299.go | bug300.go | \
- bug302.go | bug306.go | bug322.go ) return ;;
+ bug302.go | bug306.go | bug322.go | bug324.go ) return ;;
esac
# the following directories are skipped because they contain test
# cases for syntax errors and thus won't parse in the first place:
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go
index 889f9d857..88befc0dc 100644
--- a/src/cmd/goinstall/download.go
+++ b/src/cmd/goinstall/download.go
@@ -9,7 +9,7 @@ package main
import (
"http"
"os"
- "path"
+ "path/filepath"
"regexp"
"strings"
)
@@ -42,7 +42,7 @@ func download(pkg string) (string, os.Error) {
return "", os.ErrorString("invalid path (contains ..)")
}
if m := bitbucket.FindStringSubmatch(pkg); m != nil {
- if err := vcsCheckout(&hg, root+m[1], "http://"+m[1], m[1]); err != nil {
+ if err := vcsCheckout(&hg, m[1], "http://"+m[1], m[1]); err != nil {
return "", err
}
return root + pkg, nil
@@ -58,7 +58,7 @@ 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, root+m[1], "https://"+m[1], m[1]); err != nil {
+ if err := vcsCheckout(v, m[1], "https://"+m[1], m[1]); err != nil {
return "", err
}
return root + pkg, nil
@@ -67,7 +67,7 @@ func download(pkg string) (string, os.Error) {
if strings.HasSuffix(m[1], ".git") {
return "", os.ErrorString("repository " + pkg + " should not have .git suffix")
}
- if err := vcsCheckout(&git, root+m[1], "http://"+m[1]+".git", m[1]); err != nil {
+ if err := vcsCheckout(&git, m[1], "http://"+m[1]+".git", m[1]); err != nil {
return "", err
}
return root + pkg, nil
@@ -75,7 +75,7 @@ func download(pkg string) (string, os.Error) {
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, root+m[1], "https://"+m[1], m[1]); err != nil {
+ if err := vcsCheckout(&bzr, m[1], "https://"+m[1], m[1]); err != nil {
return "", err
}
return root + pkg, nil
@@ -172,17 +172,18 @@ 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, dst, repo, dashpath string) os.Error {
- dir, err := os.Stat(dst + "/" + vcs.metadir)
+func vcsCheckout(vcs *vcs, pkgprefix, repo, dashpath string) os.Error {
+ dst := filepath.Join(root, filepath.FromSlash(pkgprefix))
+ dir, err := os.Stat(filepath.Join(dst, vcs.metadir))
if err == nil && !dir.IsDirectory() {
return os.ErrorString("not a directory: " + dst)
}
if err != nil {
- parent, _ := path.Split(dst)
+ parent, _ := filepath.Split(dst)
if err := os.MkdirAll(parent, 0777); err != nil {
return err
}
- if err := run("/", nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
+ if err := run(string(filepath.Separator), nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
return err
}
if err := vcs.updateRepo(dst); err != nil {
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index f13aeb3bc..34441be45 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -15,7 +15,7 @@ import (
"io"
"io/ioutil"
"os"
- "path"
+ "path/filepath"
"runtime"
"strings"
)
@@ -34,7 +34,7 @@ var (
parents = make(map[string]string)
root = runtime.GOROOT()
visit = make(map[string]status)
- logfile = path.Join(root, "goinstall.log")
+ logfile = filepath.Join(root, "goinstall.log")
installedPkgs = make(map[string]bool)
allpkg = flag.Bool("a", false, "install all previously installed packages")
@@ -59,7 +59,7 @@ func main() {
fmt.Fprintf(os.Stderr, "%s: no $GOROOT\n", argv0)
os.Exit(1)
}
- root += "/src/pkg/"
+ root += filepath.FromSlash("/src/pkg/")
// special case - "unsafe" is already installed
visit["unsafe"] = done
@@ -160,7 +160,7 @@ func install(pkg, parent string) {
dir = pkg
local = true
} else if isStandardPath(pkg) {
- dir = path.Join(root, pkg)
+ dir = filepath.Join(root, filepath.FromSlash(pkg))
local = true
} else {
var err os.Error
@@ -216,7 +216,8 @@ func install(pkg, parent string) {
// Is this a local path? /foo ./foo ../foo . ..
func isLocalPath(s string) bool {
- return strings.HasPrefix(s, "/") || strings.HasPrefix(s, "./") || strings.HasPrefix(s, "../") || s == "." || s == ".."
+ const sep = string(filepath.Separator)
+ return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".."
}
// Is this a standard package path? strings container/vector etc.
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
index 8d4d6c5d2..e2d99bb47 100644
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -44,6 +44,9 @@ func domake(dir, pkg string, local bool) (err os.Error) {
// 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) {
+ if !safeName(pkg) {
+ return nil, os.ErrorString("unsafe name: " + pkg)
+ }
dirInfo, err := scanDir(dir, false)
if err != nil {
return nil, err
@@ -58,16 +61,25 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
cgoFiles := dirInfo.cgoFiles
isCgo := make(map[string]bool, len(cgoFiles))
for _, file := range cgoFiles {
+ if !safeName(file) {
+ return nil, os.ErrorString("bad name: " + file)
+ }
isCgo[file] = true
}
oFiles := make([]string, 0, len(dirInfo.cFiles))
for _, file := range dirInfo.cFiles {
+ if !safeName(file) {
+ return nil, os.ErrorString("unsafe name: " + file)
+ }
oFiles = append(oFiles, file[:len(file)-2]+".o")
}
goFiles := make([]string, 0, len(dirInfo.goFiles))
for _, file := range dirInfo.goFiles {
+ if !safeName(file) {
+ return nil, os.ErrorString("unsafe name: " + file)
+ }
if !isCgo[file] {
goFiles = append(goFiles, file)
}
@@ -81,6 +93,17 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
return buf.Bytes(), nil
}
+var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+
+func safeName(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+ return false
+ }
+ }
+ return true
+}
+
// makedata is the data type for the makefileTemplate.
type makedata struct {
Pkg string // package import path
diff --git a/src/cmd/goinstall/parse.go b/src/cmd/goinstall/parse.go
index 679edfabc..014b8fcb2 100644
--- a/src/cmd/goinstall/parse.go
+++ b/src/cmd/goinstall/parse.go
@@ -7,13 +7,13 @@
package main
import (
- "path"
- "os"
- "log"
- "strings"
- "strconv"
"go/ast"
"go/parser"
+ "log"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
)
@@ -64,7 +64,7 @@ func scanDir(dir string, allowMain bool) (info *dirInfo, err os.Error) {
if !strings.HasSuffix(d.Name, ".go") || strings.HasSuffix(d.Name, "_test.go") {
continue
}
- filename := path.Join(dir, d.Name)
+ filename := filepath.Join(dir, d.Name)
pf, err := parser.ParseFile(fset, filename, nil, parser.ImportsOnly)
if err != nil {
return nil, err
diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c
index 702f104a6..a7e2c41af 100644
--- a/src/cmd/gopack/ar.c
+++ b/src/cmd/gopack/ar.c
@@ -109,7 +109,7 @@ typedef struct Hashchain
/* constants and flags */
char *man = "mrxtdpq";
-char *opt = "uvnbailoS";
+char *opt = "uvnbailogS";
char artemp[] = "/tmp/vXXXXX";
char movtemp[] = "/tmp/v1XXXXX";
char tailtemp[] = "/tmp/v2XXXXX";
diff --git a/src/cmd/gopack/doc.go b/src/cmd/gopack/doc.go
index 74c272fd2..08711e72e 100644
--- a/src/cmd/gopack/doc.go
+++ b/src/cmd/gopack/doc.go
@@ -12,10 +12,12 @@ It adds a special Go-specific section __.PKGDEF that collects all the
Go type information from the files in the archive; that section is
used by the compiler when importing the package during compilation.
-Usage: gopack [uvnbailo][mrxtdpq] archive files ...
+Usage: gopack [uvnbailogS][mrxtdpq] archive files ...
The new option 'g' causes gopack to maintain the __.PKGDEF section
as files are added to the archive.
+The new option 'S' forces gopack to mark the archive as safe.
+
*/
package documentation
diff --git a/src/cmd/gotest/doc.go b/src/cmd/gotest/doc.go
index 40c40fc1f..581eaaab9 100644
--- a/src/cmd/gotest/doc.go
+++ b/src/cmd/gotest/doc.go
@@ -20,7 +20,7 @@ They should have signature
func TestXXX(t *testing.T) { ... }
Benchmark functions can be written as well; they will be run only
-when the -benchmarks flag is provided. Benchmarks should have
+when the -test.bench flag is provided. Benchmarks should have
signature
func BenchmarkXXX(b *testing.B) { ... }
@@ -42,15 +42,15 @@ The resulting binary, called (for amd64) 6.out, has a couple of
arguments.
Usage:
- 6.out [-v] [-match pattern] [-benchmarks pattern]
-
-The -v flag causes the tests to be logged as they run. The -match
-flag causes only those tests whose names match the regular expression
-pattern to be run. By default all tests are run silently. If all
-the specified test pass, 6.out prints PASS and exits with a 0 exit
-code. If any tests fail, it prints FAIL and exits with a non-zero
-code. The -benchmarks flag is analogous to the -match flag, but
-applies to benchmarks. No benchmarks run by default.
+ 6.out [-test.v] [-test.run pattern] [-test.bench pattern]
+
+The -test.v flag causes the tests to be logged as they run. The
+-test.run flag causes only those tests whose names match the regular
+expression pattern to be run. By default all tests are run silently.
+If all the specified test pass, 6.out prints PASS and exits with a 0
+exit code. If any tests fail, it prints FAIL and exits with a
+non-zero code. The -test.bench flag is analogous to the -test.run
+flag, but applies to benchmarks. No benchmarks run by default.
*/
package documentation
diff --git a/src/cmd/govet/govet.go b/src/cmd/govet/govet.go
index 5619b12ba..ff6421de8 100644
--- a/src/cmd/govet/govet.go
+++ b/src/cmd/govet/govet.go
@@ -15,7 +15,7 @@ import (
"go/parser"
"go/token"
"os"
- "path"
+ "path/filepath"
"strconv"
"strings"
)
@@ -99,7 +99,7 @@ func doFile(name string, reader io.Reader) {
file.checkFile(name, parsedFile)
}
-// Visitor for path.Walk - trivial. Just calls doFile on each file.
+// Visitor for filepath.Walk - trivial. Just calls doFile on each file.
// TODO: if govet becomes richer, might want to process
// a directory (package) at a time.
type V struct{}
@@ -124,7 +124,7 @@ func walkDir(root string) {
}
done <- true
}()
- path.Walk(root, V{}, errors)
+ filepath.Walk(root, V{}, errors)
close(errors)
<-done
}
diff --git a/src/cmd/goyacc/Makefile b/src/cmd/goyacc/Makefile
index 54b8f3360..ac0f427cc 100644
--- a/src/cmd/goyacc/Makefile
+++ b/src/cmd/goyacc/Makefile
@@ -11,7 +11,7 @@ GOFILES=\
include ../../Make.cmd
units: goyacc units.y
- ./goyacc units.y
+ ./goyacc -p units_ units.y
$(GC) y.go
$(LD) -o units y.$O
diff --git a/src/cmd/goyacc/doc.go b/src/cmd/goyacc/doc.go
index 686f75745..5dd6abe69 100644
--- a/src/cmd/goyacc/doc.go
+++ b/src/cmd/goyacc/doc.go
@@ -17,7 +17,8 @@ Yacc adepts will have no trouble adapting to this form of the tool.
The file units.y in this directory is a yacc grammar for a version of
the Unix tool units, also written in Go and largely transliterated
-from the Plan 9 C version.
+from the Plan 9 C version. It needs the flag "-p units_" (see
+below).
The generated parser is reentrant. Parse expects to be given an
argument that conforms to the following interface:
@@ -31,8 +32,15 @@ Lex should return the token identifier, and place other token
information in lval (which replaces the usual yylval).
Error is equivalent to yyerror in the original yacc.
-Code inside the parser may refer to the variable yylex
+Code inside the parser may refer to the variable yylex,
which holds the yyLexer passed to Parse.
+Multiple grammars compiled into a single program should be placed in
+distinct packages. If that is impossible, the "-p prefix" flag to
+goyacc sets the prefix, by default yy, that begins the names of
+symbols, including types, the parser, and the lexer, generated and
+referenced by goyacc's generated code. Setting it to distinct values
+allows multiple grammars to be placed in a single package.
+
*/
package documentation
diff --git a/src/cmd/goyacc/goyacc.go b/src/cmd/goyacc/goyacc.go
index c9fa6bfb9..32816b700 100644
--- a/src/cmd/goyacc/goyacc.go
+++ b/src/cmd/goyacc/goyacc.go
@@ -153,9 +153,17 @@ var ftable *bufio.Writer // y.go file
var fcode = &bytes.Buffer{} // saved code
var foutput *bufio.Writer // y.output file
-var oflag string // -o [y.go] - y.go file
-var vflag string // -v [y.output] - y.output file
-var lflag bool // -l - disable line directives
+var oflag string // -o [y.go] - y.go file
+var vflag string // -v [y.output] - y.output file
+var lflag bool // -l - disable line directives
+var prefix string // name prefix for identifiers, default yy
+
+func init() {
+ flag.StringVar(&oflag, "o", "y.go", "parser output")
+ flag.StringVar(&prefix, "p", "yy", "name prefix to use in generated code")
+ flag.StringVar(&vflag, "v", "y.output", "create parsing tables")
+ flag.BoolVar(&lflag, "l", false, "disable line directives")
+}
var stacksize = 200
@@ -349,10 +357,6 @@ func setup() {
stderr = bufio.NewWriter(os.NewFile(2, "stderr"))
foutput = nil
- flag.StringVar(&oflag, "o", "", "parser output")
- flag.StringVar(&vflag, "v", "", "create parsing tables")
- flag.BoolVar(&lflag, "l", false, "disable line directives")
-
flag.Parse()
if flag.NArg() != 1 {
usage()
@@ -362,6 +366,7 @@ func setup() {
fmt.Fprintf(stderr, "yacc: stack size too small\n")
usage()
}
+ yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
openup()
defin(0, "$end")
@@ -506,20 +511,20 @@ outer:
}
// put out names of token names
- fmt.Fprintf(ftable, "var\tyyToknames\t =[]string {\n")
+ fmt.Fprintf(ftable, "var\t%sToknames\t =[]string {\n", prefix)
for i := TOKSTART; i <= ntokens; i++ {
fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name)
}
fmt.Fprintf(ftable, "}\n")
// put out names of state names
- fmt.Fprintf(ftable, "var\tyyStatenames\t =[]string {\n")
+ fmt.Fprintf(ftable, "var\t%sStatenames\t =[]string {\n", prefix)
// for i:=TOKSTART; i<=ntokens; i++ {
// fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name);
// }
fmt.Fprintf(ftable, "}\n")
- fmt.Fprintf(fcode, "switch yynt {\n")
+ fmt.Fprintf(fcode, "switch %snt {\n", prefix)
moreprod()
prdptr[0] = []int{NTBASE, start, 1, 0}
@@ -648,8 +653,8 @@ outer:
error("default action causes potential type clash")
}
fmt.Fprintf(fcode, "\ncase %v:", nprod)
- fmt.Fprintf(fcode, "\n\tYYVAL.%v = YYS[yypt-0].%v;",
- typeset[tempty], typeset[tempty])
+ fmt.Fprintf(fcode, "\n\t%sVAL.%v = %sS[%spt-0].%v;",
+ prefix, typeset[tempty], prefix, prefix, typeset[tempty])
}
moreprod()
prdptr[nprod] = make([]int, mem)
@@ -666,9 +671,9 @@ outer:
fmt.Fprintf(fcode, "\n\t}")
- fmt.Fprintf(ftable, "const yyEofCode = 1\n")
- fmt.Fprintf(ftable, "const yyErrCode = 2\n")
- fmt.Fprintf(ftable, "const yyMaxDepth = %v\n", stacksize)
+ fmt.Fprintf(ftable, "const %sEofCode = 1\n", prefix)
+ fmt.Fprintf(ftable, "const %sErrCode = 2\n", prefix)
+ fmt.Fprintf(ftable, "const %sMaxDepth = %v\n", prefix, stacksize)
//
// copy any postfix code
@@ -1034,7 +1039,7 @@ func cpyunion() {
if !lflag {
fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
}
- fmt.Fprintf(ftable, "type\tyySymType\tstruct")
+ fmt.Fprintf(ftable, "type\t%sSymType\tstruct", prefix)
level := 0
@@ -1197,7 +1202,7 @@ loop:
c = getrune(finput)
}
if c == '$' {
- fmt.Fprintf(fcode, "YYVAL")
+ fmt.Fprintf(fcode, "%sVAL", prefix)
// put out the proper tag...
if ntypes != 0 {
@@ -1258,7 +1263,7 @@ loop:
ungetrune(finput, c)
continue loop
}
- fmt.Fprintf(fcode, "YYS[yypt-%v]", max-j-1)
+ fmt.Fprintf(fcode, "%sS[%spt-%v]", prefix, prefix, max-j-1)
// put out the proper tag
if ntypes != 0 {
@@ -2067,7 +2072,7 @@ func output() {
var c, u, v int
fmt.Fprintf(ftable, "\n//line yacctab:1\n")
- fmt.Fprintf(ftable, "var\tyyExca = []int {\n")
+ fmt.Fprintf(ftable, "var\t%sExca = []int {\n", prefix)
noset := mkset()
@@ -2140,10 +2145,10 @@ func output() {
}
fmt.Fprintf(ftable, "}\n")
- fmt.Fprintf(ftable, "const\tyyNprod\t= %v\n", nprod)
- fmt.Fprintf(ftable, "const\tyyPrivate\t= %v\n", PRIVATE)
- fmt.Fprintf(ftable, "var\tyyTokenNames []string\n")
- fmt.Fprintf(ftable, "var\tyyStates []string\n")
+ fmt.Fprintf(ftable, "const\t%sNprod\t= %v\n", prefix, nprod)
+ fmt.Fprintf(ftable, "const\t%sPrivate\t= %v\n", prefix, PRIVATE)
+ fmt.Fprintf(ftable, "var\t%sTokenNames []string\n", prefix)
+ fmt.Fprintf(ftable, "var\t%sStates []string\n", prefix)
}
//
@@ -2718,10 +2723,10 @@ nextn:
// write out the optimized parser
//
func aoutput() {
- fmt.Fprintf(ftable, "const\tyyLast\t= %v\n", maxa+1)
- arout("yyAct", amem, maxa+1)
- arout("yyPact", indgo, nstate)
- arout("yyPgo", pgo, nnonter+1)
+ fmt.Fprintf(ftable, "const\t%sLast\t= %v\n", prefix, maxa+1)
+ arout("Act", amem, maxa+1)
+ arout("Pact", indgo, nstate)
+ arout("Pgo", pgo, nnonter+1)
}
//
@@ -2730,7 +2735,7 @@ func aoutput() {
func others() {
var i, j int
- arout("yyR1", levprd, nprod)
+ arout("R1", levprd, nprod)
aryfil(temp1, nprod, 0)
//
@@ -2739,7 +2744,7 @@ func others() {
for i = 1; i < nprod; i++ {
temp1[i] = len(prdptr[i]) - 2
}
- arout("yyR2", temp1, nprod)
+ arout("R2", temp1, nprod)
aryfil(temp1, nstate, -1000)
for i = 0; i <= ntokens; i++ {
@@ -2752,8 +2757,8 @@ func others() {
temp1[j] = -i
}
}
- arout("yyChk", temp1, nstate)
- arout("yyDef", defact, nstate)
+ arout("Chk", temp1, nstate)
+ arout("Def", defact, nstate)
// put out token translation tables
// table 1 has 0-256
@@ -2778,7 +2783,7 @@ func others() {
temp1[i] = YYLEXUNK
}
}
- arout("yyTok1", temp1, c+1)
+ arout("Tok1", temp1, c+1)
// table 2 has PRIVATE-PRIVATE+256
aryfil(temp1, 256, 0)
@@ -2797,10 +2802,10 @@ func others() {
}
}
}
- arout("yyTok2", temp1, c+1)
+ arout("Tok2", temp1, c+1)
// table 3 has everything else
- fmt.Fprintf(ftable, "var\tyyTok3\t= []int {\n")
+ fmt.Fprintf(ftable, "var\t%sTok3\t= []int {\n", prefix)
c = 0
for i = 1; i <= ntokens; i++ {
j = tokset[i].value
@@ -2829,13 +2834,14 @@ func others() {
// copy yaccpar
fmt.Fprintf(ftable, "\n//line yaccpar:1\n")
- parts := strings.Split(yaccpar, "yyrun()", 2)
+ parts := strings.Split(yaccpar, prefix+"run()", 2)
fmt.Fprintf(ftable, "%v", parts[0])
ftable.Write(fcode.Bytes())
fmt.Fprintf(ftable, "%v", parts[1])
}
func arout(s string, v []int, n int) {
+ s = prefix + s
fmt.Fprintf(ftable, "var\t%v\t= []int {\n", s)
for i := 0; i < n; i++ {
if i%10 == 0 {
@@ -3076,86 +3082,84 @@ func exit(status int) {
os.Exit(status)
}
-var yaccpar = `
+var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g
+var yaccpartext = `
/* parser for yacc output */
-var yyDebug = 0
+var $$Debug = 0
-type yyLexer interface {
- Lex(lval *yySymType) int
+type $$Lexer interface {
+ Lex(lval *$$SymType) int
Error(s string)
}
-const yyFlag = -1000
+const $$Flag = -1000
-func yyTokname(yyc int) string {
- if yyc > 0 && yyc <= len(yyToknames) {
- if yyToknames[yyc-1] != "" {
- return yyToknames[yyc-1]
+func $$Tokname(c int) string {
+ if c > 0 && c <= len($$Toknames) {
+ if $$Toknames[c-1] != "" {
+ return $$Toknames[c-1]
}
}
- return fmt.Sprintf("tok-%v", yyc)
+ return fmt.Sprintf("tok-%v", c)
}
-func yyStatname(yys int) string {
- if yys >= 0 && yys < len(yyStatenames) {
- if yyStatenames[yys] != "" {
- return yyStatenames[yys]
+func $$Statname(s int) string {
+ if s >= 0 && s < len($$Statenames) {
+ if $$Statenames[s] != "" {
+ return $$Statenames[s]
}
}
- return fmt.Sprintf("state-%v", yys)
+ return fmt.Sprintf("state-%v", s)
}
-func yylex1(yylex yyLexer, lval *yySymType) int {
- var yychar int
- var c int
-
- yychar = yylex.Lex(lval)
- if yychar <= 0 {
- c = yyTok1[0]
+func $$lex1(lex $$Lexer, lval *$$SymType) int {
+ c := 0
+ char := lex.Lex(lval)
+ if char <= 0 {
+ c = $$Tok1[0]
goto out
}
- if yychar < len(yyTok1) {
- c = yyTok1[yychar]
+ if char < len($$Tok1) {
+ c = $$Tok1[char]
goto out
}
- if yychar >= yyPrivate {
- if yychar < yyPrivate+len(yyTok2) {
- c = yyTok2[yychar-yyPrivate]
+ if char >= $$Private {
+ if char < $$Private+len($$Tok2) {
+ c = $$Tok2[char-$$Private]
goto out
}
}
- for i := 0; i < len(yyTok3); i += 2 {
- c = yyTok3[i+0]
- if c == yychar {
- c = yyTok3[i+1]
+ for i := 0; i < len($$Tok3); i += 2 {
+ c = $$Tok3[i+0]
+ if c == char {
+ c = $$Tok3[i+1]
goto out
}
}
- c = 0
out:
if c == 0 {
- c = yyTok2[1] /* unknown char */
+ c = $$Tok2[1] /* unknown char */
}
- if yyDebug >= 3 {
- fmt.Printf("lex %U %s\n", uint(yychar), yyTokname(c))
+ if $$Debug >= 3 {
+ fmt.Printf("lex %U %s\n", uint(char), $$Tokname(c))
}
return c
}
-func yyParse(yylex yyLexer) int {
- var yyn int
- var yylval yySymType
- var YYVAL yySymType
- YYS := make([]yySymType, yyMaxDepth)
+func $$Parse($$lex $$Lexer) int {
+ var $$n int
+ var $$lval $$SymType
+ var $$VAL $$SymType
+ $$S := make([]$$SymType, $$MaxDepth)
Nerrs := 0 /* number of errors */
Errflag := 0 /* error recovery flag */
- yystate := 0
- yychar := -1
- yyp := -1
- goto yystack
+ $$state := 0
+ $$char := -1
+ $$p := -1
+ goto $$stack
ret0:
return 0
@@ -3163,80 +3167,80 @@ ret0:
ret1:
return 1
-yystack:
+$$stack:
/* put a state and value onto the stack */
- if yyDebug >= 4 {
- fmt.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+ if $$Debug >= 4 {
+ fmt.Printf("char %v in %v\n", $$Tokname($$char), $$Statname($$state))
}
- yyp++
- if yyp >= len(YYS) {
- nyys := make([]yySymType, len(YYS)*2)
- copy(nyys, YYS)
- YYS = nyys
+ $$p++
+ if $$p >= len($$S) {
+ nyys := make([]$$SymType, len($$S)*2)
+ copy(nyys, $$S)
+ $$S = nyys
}
- YYS[yyp] = YYVAL
- YYS[yyp].yys = yystate
+ $$S[$$p] = $$VAL
+ $$S[$$p].yys = $$state
-yynewstate:
- yyn = yyPact[yystate]
- if yyn <= yyFlag {
- goto yydefault /* simple state */
+$$newstate:
+ $$n = $$Pact[$$state]
+ if $$n <= $$Flag {
+ goto $$default /* simple state */
}
- if yychar < 0 {
- yychar = yylex1(yylex, &yylval)
+ if $$char < 0 {
+ $$char = $$lex1($$lex, &$$lval)
}
- yyn += yychar
- if yyn < 0 || yyn >= yyLast {
- goto yydefault
+ $$n += $$char
+ if $$n < 0 || $$n >= $$Last {
+ goto $$default
}
- yyn = yyAct[yyn]
- if yyChk[yyn] == yychar { /* valid shift */
- yychar = -1
- YYVAL = yylval
- yystate = yyn
+ $$n = $$Act[$$n]
+ if $$Chk[$$n] == $$char { /* valid shift */
+ $$char = -1
+ $$VAL = $$lval
+ $$state = $$n
if Errflag > 0 {
Errflag--
}
- goto yystack
+ goto $$stack
}
-yydefault:
+$$default:
/* default state action */
- yyn = yyDef[yystate]
- if yyn == -2 {
- if yychar < 0 {
- yychar = yylex1(yylex, &yylval)
+ $$n = $$Def[$$state]
+ if $$n == -2 {
+ if $$char < 0 {
+ $$char = $$lex1($$lex, &$$lval)
}
/* look through exception table */
- yyxi := 0
+ xi := 0
for {
- if yyExca[yyxi+0] == -1 && yyExca[yyxi+1] == yystate {
+ if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state {
break
}
- yyxi += 2
+ xi += 2
}
- for yyxi += 2; ; yyxi += 2 {
- yyn = yyExca[yyxi+0]
- if yyn < 0 || yyn == yychar {
+ for xi += 2; ; xi += 2 {
+ $$n = $$Exca[xi+0]
+ if $$n < 0 || $$n == $$char {
break
}
}
- yyn = yyExca[yyxi+1]
- if yyn < 0 {
+ $$n = $$Exca[xi+1]
+ if $$n < 0 {
goto ret0
}
}
- if yyn == 0 {
+ if $$n == 0 {
/* error ... attempt to resume parsing */
switch Errflag {
case 0: /* brand new error */
- yylex.Error("syntax error")
+ $$lex.Error("syntax error")
Nerrs++
- if yyDebug >= 1 {
- fmt.Printf("%s", yyStatname(yystate))
- fmt.Printf("saw %s\n", yyTokname(yychar))
+ if $$Debug >= 1 {
+ fmt.Printf("%s", $$Statname($$state))
+ fmt.Printf("saw %s\n", $$Tokname($$char))
}
fallthrough
@@ -3244,64 +3248,64 @@ yydefault:
Errflag = 3
/* find a state where "error" is a legal shift action */
- for yyp >= 0 {
- yyn = yyPact[YYS[yyp].yys] + yyErrCode
- if yyn >= 0 && yyn < yyLast {
- yystate = yyAct[yyn] /* simulate a shift of "error" */
- if yyChk[yystate] == yyErrCode {
- goto yystack
+ for $$p >= 0 {
+ $$n = $$Pact[$$S[$$p].yys] + $$ErrCode
+ if $$n >= 0 && $$n < $$Last {
+ $$state = $$Act[$$n] /* simulate a shift of "error" */
+ if $$Chk[$$state] == $$ErrCode {
+ goto $$stack
}
}
- /* the current yyp has no shift onn "error", pop stack */
- if yyDebug >= 2 {
+ /* the current p has no shift onn "error", pop stack */
+ if $$Debug >= 2 {
fmt.Printf("error recovery pops state %d, uncovers %d\n",
- YYS[yyp].yys, YYS[yyp-1].yys)
+ $$S[$$p].yys, $$S[$$p-1].yys)
}
- yyp--
+ $$p--
}
/* there is no state on the stack with an error shift ... abort */
goto ret1
case 3: /* no shift yet; clobber input char */
- if yyDebug >= 2 {
- fmt.Printf("error recovery discards %s\n", yyTokname(yychar))
+ if $$Debug >= 2 {
+ fmt.Printf("error recovery discards %s\n", $$Tokname($$char))
}
- if yychar == yyEofCode {
+ if $$char == $$EofCode {
goto ret1
}
- yychar = -1
- goto yynewstate /* try again in the same state */
+ $$char = -1
+ goto $$newstate /* try again in the same state */
}
}
- /* reduction by production yyn */
- if yyDebug >= 2 {
- fmt.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+ /* reduction by production $$n */
+ if $$Debug >= 2 {
+ fmt.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
}
- yynt := yyn
- yypt := yyp
- _ = yypt // guard against "declared and not used"
+ $$nt := $$n
+ $$pt := $$p
+ _ = $$pt // guard against "declared and not used"
- yyp -= yyR2[yyn]
- YYVAL = YYS[yyp+1]
+ $$p -= $$R2[$$n]
+ $$VAL = $$S[$$p+1]
/* consult goto table to find next state */
- yyn = yyR1[yyn]
- yyg := yyPgo[yyn]
- yyj := yyg + YYS[yyp].yys + 1
+ $$n = $$R1[$$n]
+ $$g := $$Pgo[$$n]
+ $$j := $$g + $$S[$$p].yys + 1
- if yyj >= yyLast {
- yystate = yyAct[yyg]
+ if $$j >= $$Last {
+ $$state = $$Act[$$g]
} else {
- yystate = yyAct[yyj]
- if yyChk[yystate] != -yyn {
- yystate = yyAct[yyg]
+ $$state = $$Act[$$j]
+ if $$Chk[$$state] != -$$n {
+ $$state = $$Act[$$g]
}
}
// dummy call; replaced with literal code
- yyrun()
- goto yystack /* stack new state and value */
+ $$run()
+ goto $$stack /* stack new state and value */
}
`
diff --git a/src/cmd/goyacc/units.y b/src/cmd/goyacc/units.y
index a7d472fc6..5d3f9aca2 100644
--- a/src/cmd/goyacc/units.y
+++ b/src/cmd/goyacc/units.y
@@ -6,6 +6,9 @@
// Distributed under the terms of the Lucent Public License Version 1.02
// See http://plan9.bell-labs.com/plan9/license.html
+// Generate parser with prefix "units_":
+// goyacc -p "units_"
+
%{
// units.y
@@ -215,7 +218,7 @@ expr0:
type UnitsLex int
-func (UnitsLex) Lex(yylval *yySymType) int {
+func (UnitsLex) Lex(yylval *units_SymType) int {
var c, i int
c = peekrune
@@ -319,7 +322,7 @@ func main() {
continue
}
peekrune = ':'
- yyParse(UnitsLex(0))
+ units_Parse(UnitsLex(0))
}
/*
@@ -340,7 +343,7 @@ func main() {
}
peekrune = '?'
nerrors = 0
- yyParse(UnitsLex(0))
+ units_Parse(UnitsLex(0))
if nerrors != 0 {
continue
}
diff --git a/src/cmd/hgpatch/main.go b/src/cmd/hgpatch/main.go
index bd4b563f9..2dcb5234c 100644
--- a/src/cmd/hgpatch/main.go
+++ b/src/cmd/hgpatch/main.go
@@ -14,7 +14,7 @@ import (
"io/ioutil"
"os"
"patch"
- "path"
+ "path/filepath"
"sort"
"strings"
)
@@ -186,7 +186,7 @@ func main() {
// make parent directory for name, if necessary
func makeParent(name string) {
- parent, _ := path.Split(name)
+ parent, _ := filepath.Split(name)
chk(mkdirAll(parent, 0755))
}
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 0551232cf..a20b057ce 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -241,7 +241,7 @@ dynrelocsym(Sym *s)
{
Reloc *r;
- if(thechar == '8' && HEADTYPE == 10) { // Windows PE
+ if(HEADTYPE == Hwindows) {
Sym *rel, *targ;
rel = lookup(".rel", 0);
@@ -898,9 +898,9 @@ address(void)
segdata.rwx = 06;
segdata.vaddr = va;
segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
- if((thechar == '6' || thechar == '8') && HEADTYPE == 10) // Windows PE
+ if(HEADTYPE == Hwindows)
segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
- if(thechar == '8' && HEADTYPE == 2) { // Plan 9
+ if(HEADTYPE == Hplan9x32) {
segdata.vaddr = va = rnd(va, 4096);
segdata.fileoff = segtext.fileoff + segtext.filelen;
}
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index 5df3515f5..5ba4b7c64 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -772,6 +772,9 @@ enum {
KindUnsafePointer,
KindNoPointers = 1<<7,
+
+ // size of Type interface header + CommonType structure.
+ CommonSize = 2*PtrSize+ 4*PtrSize + 8,
};
static Reloc*
@@ -849,59 +852,59 @@ decodetype_size(Sym *s)
static Sym*
decodetype_arrayelem(Sym *s)
{
- return decode_reloc_sym(s, 5*PtrSize + 8); // 0x1c / 0x30
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
}
static vlong
decodetype_arraylen(Sym *s)
{
- return decode_inuxi(s->p + 6*PtrSize + 8, PtrSize);
+ return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize);
}
// Type.PtrType.elem
static Sym*
decodetype_ptrelem(Sym *s)
{
- return decode_reloc_sym(s, 5*PtrSize + 8); // 0x1c / 0x30
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
}
// Type.MapType.key, elem
static Sym*
decodetype_mapkey(Sym *s)
{
- return decode_reloc_sym(s, 5*PtrSize + 8); // 0x1c / 0x30
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
}
static Sym*
decodetype_mapvalue(Sym *s)
{
- return decode_reloc_sym(s, 6*PtrSize + 8); // 0x20 / 0x38
+ return decode_reloc_sym(s, CommonSize+PtrSize); // 0x20 / 0x38
}
// Type.ChanType.elem
static Sym*
decodetype_chanelem(Sym *s)
{
- return decode_reloc_sym(s, 5*PtrSize + 8); // 0x1c / 0x30
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
}
// Type.FuncType.dotdotdot
static int
decodetype_funcdotdotdot(Sym *s)
{
- return s->p[5*PtrSize + 8];
+ return s->p[CommonSize];
}
// Type.FuncType.in.len
static int
decodetype_funcincount(Sym *s)
{
- return decode_inuxi(s->p + 7*PtrSize + 8, 4);
+ return decode_inuxi(s->p + CommonSize+2*PtrSize, 4);
}
static int
decodetype_funcoutcount(Sym *s)
{
- return decode_inuxi(s->p + 8*PtrSize + 16, 4);
+ return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*4, 4);
}
static Sym*
@@ -909,7 +912,7 @@ decodetype_funcintype(Sym *s, int i)
{
Reloc *r;
- r = decode_reloc(s, 6*PtrSize + 8);
+ r = decode_reloc(s, CommonSize + PtrSize);
if (r == nil)
return nil;
return decode_reloc_sym(r->sym, r->add + i * PtrSize);
@@ -920,7 +923,7 @@ decodetype_funcouttype(Sym *s, int i)
{
Reloc *r;
- r = decode_reloc(s, 7*PtrSize + 16);
+ r = decode_reloc(s, CommonSize + 2*PtrSize + 2*4);
if (r == nil)
return nil;
return decode_reloc_sym(r->sym, r->add + i * PtrSize);
@@ -930,15 +933,18 @@ decodetype_funcouttype(Sym *s, int i)
static int
decodetype_structfieldcount(Sym *s)
{
- return decode_inuxi(s->p + 6*PtrSize + 8, 4); // 0x20 / 0x38
+ return decode_inuxi(s->p + CommonSize + PtrSize, 4);
}
-// Type.StructType.fields[]-> name, typ and offset. sizeof(structField) = 5*PtrSize
+enum {
+ StructFieldSize = 5*PtrSize
+};
+// Type.StructType.fields[]-> name, typ and offset.
static char*
decodetype_structfieldname(Sym *s, int i)
{
// go.string."foo" 0x28 / 0x40
- s = decode_reloc_sym(s, 6*PtrSize + 0x10 + i*5*PtrSize);
+ s = decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize);
if (s == nil) // embedded structs have a nil name.
return nil;
s = decode_reloc_sym(s, 0); // string."foo"
@@ -950,20 +956,20 @@ decodetype_structfieldname(Sym *s, int i)
static Sym*
decodetype_structfieldtype(Sym *s, int i)
{
- return decode_reloc_sym(s, 8*PtrSize + 0x10 + i*5*PtrSize); // 0x30 / 0x50
+ return decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize + 2*PtrSize);
}
static vlong
decodetype_structfieldoffs(Sym *s, int i)
{
- return decode_inuxi(s->p + 10*PtrSize + 0x10 + i*5*PtrSize, 4); // 0x38 / 0x60
+ return decode_inuxi(s->p + CommonSize + PtrSize + 2*4 + i*StructFieldSize + 4*PtrSize, 4);
}
// InterfaceTYpe.methods.len
static vlong
decodetype_ifacemethodcount(Sym *s)
{
- return decode_inuxi(s->p + 6*PtrSize + 8, 4);
+ return decode_inuxi(s->p + CommonSize + PtrSize, 4);
}
@@ -2302,7 +2308,7 @@ writegdbscript(void)
static void
align(vlong size)
{
- if((thechar == '6' || thechar == '8') && HEADTYPE == 10) // Only Windows PE need section align.
+ if(HEADTYPE == Hwindows) // Only Windows PE need section align.
strnput("", rnd(size, PEFILEALIGN) - size);
}
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index 2c6a6d084..3c1e230b4 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -550,6 +550,8 @@ mark(Sym *s)
if(s == S || s->reachable)
return;
+ if(strncmp(s->name, "weak.", 5) == 0)
+ return;
s->reachable = 1;
if(s->text)
marktext(s);
@@ -654,6 +656,37 @@ deadcode(void)
textp = nil;
else
last->next = nil;
+
+ for(i=0; i<NHASH; i++)
+ for(s = hash[i]; s != S; s = s->hash)
+ if(strncmp(s->name, "weak.", 5) == 0) {
+ s->special = 1; // do not lay out in data segment
+ s->reachable = 1;
+ }
+}
+
+void
+doweak(void)
+{
+ int i;
+ Sym *s, *t;
+
+ // resolve weak references only if
+ // target symbol will be in binary anyway.
+ for(i=0; i<NHASH; i++)
+ for(s = hash[i]; s != S; s = s->hash) {
+ if(strncmp(s->name, "weak.", 5) == 0) {
+ t = lookup(s->name+5, s->version);
+ if(t->type != 0 && t->reachable) {
+ s->value = t->value;
+ s->type = t->type;
+ } else {
+ s->type = SCONST;
+ s->value = 0;
+ }
+ continue;
+ }
+ }
}
void
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index c144d4295..e645502b3 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -31,6 +31,8 @@
#include "l.h"
#include "lib.h"
+#include "../../pkg/runtime/stack.h"
+
#include <ar.h>
int iconv(Fmt*);
@@ -1084,3 +1086,208 @@ be64(uchar *b)
Endian be = { be16, be32, be64 };
Endian le = { le16, le32, le64 };
+
+typedef struct Chain Chain;
+struct Chain
+{
+ Sym *sym;
+ Chain *up;
+ int limit; // limit on entry to sym
+};
+
+static int stkcheck(Chain*, int);
+static void stkprint(Chain*, int);
+static void stkbroke(Chain*, int);
+static Sym *morestack;
+static Sym *newstack;
+
+enum
+{
+ HasLinkRegister = (thechar == '5'),
+ CallSize = (!HasLinkRegister)*PtrSize, // bytes of stack required for a call
+};
+
+void
+dostkcheck(void)
+{
+ Chain ch;
+ Sym *s;
+
+ morestack = lookup("runtime.morestack", 0);
+ newstack = lookup("runtime.newstack", 0);
+
+ // First the nosplits on their own.
+ for(s = textp; s != nil; s = s->next) {
+ if(s->text == nil || s->text->link == nil || (s->text->textflag & NOSPLIT) == 0)
+ continue;
+ cursym = s;
+ ch.up = nil;
+ ch.sym = s;
+ ch.limit = StackLimit - CallSize;
+ stkcheck(&ch, 0);
+ s->stkcheck = 1;
+ }
+
+ // Check calling contexts.
+ // Some nosplits get called a little further down,
+ // like newproc and deferproc. We could hard-code
+ // that knowledge but it's more robust to look at
+ // the actual call sites.
+ for(s = textp; s != nil; s = s->next) {
+ if(s->text == nil || s->text->link == nil || (s->text->textflag & NOSPLIT) != 0)
+ continue;
+ cursym = s;
+ ch.up = nil;
+ ch.sym = s;
+ ch.limit = StackLimit - CallSize;
+ stkcheck(&ch, 0);
+ }
+}
+
+static int
+stkcheck(Chain *up, int depth)
+{
+ Chain ch, ch1;
+ Prog *p;
+ Sym *s;
+ int limit, prolog;
+
+ limit = up->limit;
+ s = up->sym;
+ p = s->text;
+
+ // Small optimization: don't repeat work at top.
+ if(s->stkcheck && limit == StackLimit-CallSize)
+ return 0;
+
+ if(depth > 100) {
+ diag("nosplit stack check too deep");
+ stkbroke(up, 0);
+ return -1;
+ }
+
+ if(p == nil || p->link == nil) {
+ // external function.
+ // should never be called directly.
+ // only diagnose the direct caller.
+ if(depth == 1)
+ diag("call to external function %s", s->name);
+ return -1;
+ }
+
+ if(limit < 0) {
+ stkbroke(up, limit);
+ return -1;
+ }
+
+ // morestack looks like it calls functions,
+ // but it switches the stack pointer first.
+ if(s == morestack)
+ return 0;
+
+ ch.up = up;
+ prolog = (s->text->textflag & NOSPLIT) == 0;
+ for(p = s->text; p != P; p = p->link) {
+ limit -= p->spadj;
+ if(prolog && p->spadj != 0) {
+ // The first stack adjustment in a function with a
+ // split-checking prologue marks the end of the
+ // prologue. Assuming the split check is correct,
+ // after the adjustment there should still be at least
+ // StackLimit bytes available below the stack pointer.
+ // If this is not the top call in the chain, no need
+ // to duplicate effort, so just stop.
+ if(depth > 0)
+ return 0;
+ prolog = 0;
+ limit = StackLimit;
+ }
+ if(limit < 0) {
+ stkbroke(up, limit);
+ return -1;
+ }
+ if(iscall(p)) {
+ limit -= CallSize;
+ ch.limit = limit;
+ if(p->to.type == D_BRANCH) {
+ // Direct call.
+ ch.sym = p->to.sym;
+ if(stkcheck(&ch, depth+1) < 0)
+ return -1;
+ } else {
+ // Indirect call. Assume it is a splitting function,
+ // so we have to make sure it can call morestack.
+ limit -= CallSize;
+ ch.sym = nil;
+ ch1.limit = limit;
+ ch1.up = &ch;
+ ch1.sym = morestack;
+ if(stkcheck(&ch1, depth+2) < 0)
+ return -1;
+ limit += CallSize;
+ }
+ limit += CallSize;
+ }
+
+ }
+ return 0;
+}
+
+static void
+stkbroke(Chain *ch, int limit)
+{
+ diag("nosplit stack overflow");
+ stkprint(ch, limit);
+}
+
+static void
+stkprint(Chain *ch, int limit)
+{
+ char *name;
+
+ if(ch->sym)
+ name = ch->sym->name;
+ else
+ name = "function pointer";
+
+ if(ch->up == nil) {
+ // top of chain. ch->sym != nil.
+ if(ch->sym->text->textflag & NOSPLIT)
+ print("\t%d\tassumed on entry to %s\n", ch->limit, name);
+ else
+ print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
+ } else {
+ stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
+ if(!HasLinkRegister)
+ print("\t%d\ton entry to %s\n", ch->limit, name);
+ }
+ if(ch->limit != limit)
+ print("\t%d\tafter %s uses %d\n", limit, name, ch->limit - limit);
+}
+
+int
+headtype(char *name)
+{
+ int i;
+
+ for(i=0; headers[i].name; i++)
+ if(strcmp(name, headers[i].name) == 0) {
+ headstring = headers[i].name;
+ return headers[i].val;
+ }
+ fprint(2, "unknown header type -H %s\n", name);
+ errorexit();
+ return -1; // not reached
+}
+
+void
+undef(void)
+{
+ int i;
+ Sym *s;
+
+ for(i=0; i<NHASH; i++)
+ for(s = hash[i]; s != S; s = s->hash)
+ if(s->type == SXREF)
+ diag("%s(%d): not defined", s->name, s->version);
+}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 16dfb0dc3..adde2c9ff 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -74,7 +74,6 @@ extern int nlibdir;
extern int cout;
EXTERN char* INITENTRY;
-EXTERN char thechar;
EXTERN char* thestring;
EXTERN Library* library;
EXTERN int libraryp;
@@ -167,6 +166,9 @@ void adddynlib(char*);
int archreloc(Reloc*, Sym*, vlong*);
void adddynsym(Sym*);
void addexport(void);
+void dostkcheck(void);
+void undef(void);
+void doweak(void);
int pathchar(void);
void* mal(uint32);
@@ -208,3 +210,36 @@ enum {
ArchiveObj,
Pkgdef
};
+
+/* executable header types */
+enum {
+ Hgarbunix = 0, // garbage unix
+ Hnoheader, // no header
+ Hunixcoff, // unix coff
+ Hrisc, // aif for risc os
+ Hplan9x32, // plan 9 32-bit format
+ Hplan9x64, // plan 9 64-bit format
+ Hmsdoscom, // MS-DOS .COM
+ Hnetbsd, // NetBSD
+ Hmsdosexe, // fake MS-DOS .EXE
+ Hixp1200, // IXP1200 (raw)
+ Helf, // ELF32
+ Hipaq, // ipaq
+ Hdarwin, // Apple Mach-O
+ Hlinux, // Linux ELF
+ Hnacl, // Google Native Client
+ Hfreebsd, // FreeBSD ELF
+ Hwindows, // MS Windows PE
+ Htiny // tiny (os image)
+};
+
+typedef struct Header Header;
+struct Header {
+ char *name;
+ int val;
+};
+
+EXTERN char* headstring;
+extern Header headers[];
+
+int headtype(char*);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 402e0ec63..c8d7c4a6d 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -276,7 +276,6 @@ asmbmacho(void)
vlong v, w;
vlong va;
int a, i;
- char *pkgroot;
MachoHdr *mh;
MachoSect *msect;
MachoSeg *ms;
@@ -428,12 +427,6 @@ asmbmacho(void)
ml->data[0] = 12; /* offset to string */
strcpy((char*)&ml->data[1], "/usr/lib/dyld");
- if(ndylib > 0) { /* add reference to where .so files are installed */
- pkgroot = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
- ml = newMachoLoad(0x80000000 | 0x1c, 1+(strlen(pkgroot)+1+7)/8*2); /* LC_RPATH */
- ml->data[0] = 12; /* offset of string from beginning of load */
- strcpy((char*)&ml->data[1], pkgroot);
- }
for(i=0; i<ndylib; i++) {
ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
ml->data[0] = 24; /* offset of string from beginning of load */
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index 2c34daab4..e72b0b2a0 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -500,6 +500,7 @@ asmbpe(void)
IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED;
if (pe64) {
fh.SizeOfOptionalHeader = sizeof(oh64);
+ fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
set(Magic, 0x20b); // PE32+
} else {
fh.SizeOfOptionalHeader = sizeof(oh);
@@ -525,8 +526,11 @@ asmbpe(void)
set(MinorSubsystemVersion, 0);
set(SizeOfImage, nextsectoff);
set(SizeOfHeaders, PEFILEHEADR);
- set(Subsystem, 3); // WINDOWS_CUI
- set(SizeOfStackReserve, 0x00200000);
+ if(strcmp(headstring, "windowsgui") == 0)
+ set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_GUI);
+ else
+ set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_CUI);
+ set(SizeOfStackReserve, 0x0040000);
set(SizeOfStackCommit, 0x00001000);
set(SizeOfHeapReserve, 0x00100000);
set(SizeOfHeapCommit, 0x00001000);
diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h
index 6dbf6a5be..2180fb88c 100644
--- a/src/cmd/ld/pe.h
+++ b/src/cmd/ld/pe.h
@@ -131,6 +131,9 @@ enum {
IMAGE_DIRECTORY_ENTRY_IAT = 12,
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13,
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14,
+
+ IMAGE_SUBSYSTEM_WINDOWS_GUI = 2,
+ IMAGE_SUBSYSTEM_WINDOWS_CUI = 3,
};
void peinit(void);
diff --git a/src/cmd/make.bash b/src/cmd/make.bash
deleted file mode 100755
index 63da74625..000000000
--- a/src/cmd/make.bash
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-set -e
-
-bash clean.bash
-
-eval $(gomake --no-print-directory -f ../Make.inc go-env)
-if [ -z "$O" ]; then
- echo 'missing $O - maybe no Make.$GOARCH?' 1>&2
- exit 1
-fi
-
-cd ${O}l
-bash mkenam
-gomake enam.o
-cd ..
-
-# Note: commands written in Go are not listed here.
-# They are in ../pkg/Makefile so that they can be built
-# after the Go libraries on which they depend.
-for i in cc ${O}l ${O}a ${O}c gc ${O}g cov godefs gopack gotest nm prof
-do
- echo; echo; echo %%%% making $i %%%%; echo
- cd $i
- gomake install
- cd ..
-done