diff options
-rw-r--r-- | doc/go1.1.html | 12 | ||||
-rw-r--r-- | include/libc.h | 10 | ||||
-rw-r--r-- | src/cmd/5c/peep.c | 2 | ||||
-rw-r--r-- | src/cmd/5l/l.h | 2 | ||||
-rw-r--r-- | src/cmd/5l/obj.c | 100 | ||||
-rw-r--r-- | src/cmd/6l/l.h | 6 | ||||
-rw-r--r-- | src/cmd/6l/obj.c | 99 | ||||
-rw-r--r-- | src/cmd/8l/l.h | 3 | ||||
-rw-r--r-- | src/cmd/8l/obj.c | 96 | ||||
-rw-r--r-- | src/cmd/cc/cc.h | 2 | ||||
-rw-r--r-- | src/cmd/cc/lex.c | 117 | ||||
-rw-r--r-- | src/cmd/cc/sub.c | 6 | ||||
-rw-r--r-- | src/cmd/gc/go.h | 2 | ||||
-rw-r--r-- | src/cmd/gc/lex.c | 128 | ||||
-rw-r--r-- | src/cmd/go/build.go | 16 | ||||
-rw-r--r-- | src/cmd/ld/lib.c | 28 | ||||
-rw-r--r-- | src/cmd/ld/lib.h | 5 | ||||
-rw-r--r-- | src/lib9/flag.c | 300 |
18 files changed, 606 insertions, 328 deletions
diff --git a/doc/go1.1.html b/doc/go1.1.html index 55c76562e..4aa5fa55d 100644 --- a/doc/go1.1.html +++ b/doc/go1.1.html @@ -18,6 +18,18 @@ TODO TODO: more +<h3 id="gc-flag">Command-line flag parsing</h3> + +<p> +In the gc toolchain, the compilers and linkers now use the +same command-line flag parsing rules as the Go flag package, a departure +from the traditional Unix flag parsing. This may affect scripts that invoke +the tool directly. +For example, +<code>go tool 6c -Fw -Dfoo</code> must now be written +<code>go tool 6c -F -w -D foo</code>. +</p> + <h3 id="int">Size of int on 64-bit platforms</h3> <p> diff --git a/include/libc.h b/include/libc.h index 42c653cf5..9486b1143 100644 --- a/include/libc.h +++ b/include/libc.h @@ -292,6 +292,16 @@ extern char* getgoversion(void); extern char* getgoarm(void); extern char* getgo386(void); +extern void flagcount(char*, char*, int*); +extern void flagint32(char*, char*, int32*); +extern void flagint64(char*, char*, int64*); +extern void flagstr(char*, char*, char**); +extern void flagparse(int*, char***, void (*usage)(void)); +extern void flagfn0(char*, char*, void(*fn)(void)); +extern void flagfn1(char*, char*, void(*fn)(char*)); +extern void flagfn2(char*, char*, void(*fn)(char*, char*)); +extern void flagprint(int); + #ifdef _WIN32 #ifndef _WIN64 diff --git a/src/cmd/5c/peep.c b/src/cmd/5c/peep.c index cdfb9d7f6..2f902e02a 100644 --- a/src/cmd/5c/peep.c +++ b/src/cmd/5c/peep.c @@ -824,7 +824,7 @@ xtramodes(Reg *r, Adr *a) Adr v; p = r->prog; - if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG) /* byte load */ + if(p->as == AMOVB && p->from.type == D_OREG) /* byte load */ return 0; v = *a; v.type = D_REG; diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index 16f7e5892..5b05932fd 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -286,7 +286,7 @@ EXTERN Prog* curp; EXTERN Sym* cursym; EXTERN Sym* datap; EXTERN int32 elfdatsize; -EXTERN char debug[128]; +EXTERN int debug[128]; EXTERN Sym* etextp; EXTERN char* noname; EXTERN Prog* lastp; diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c index 74ac6ecb4..4e2b4d44e 100644 --- a/src/cmd/5l/obj.c +++ b/src/cmd/5l/obj.c @@ -66,17 +66,9 @@ Header headers[] = { */ void -usage(void) -{ - fprint(2, "usage: 5l [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-D data] [-R rnd] [-r path] [-o out] main.5\n"); - errorexit(); -} - -void main(int argc, char *argv[]) { - int c; - char *p, *name, *val; + char *p; Sym *s; Binit(&bso, 1, OWRITE); @@ -98,61 +90,41 @@ main(int argc, char *argv[]) if(goarm == 5) debug['F'] = 1; - ARGBEGIN { - default: - c = ARGC(); - if(c == 'l') - usage(); - if(c >= 0 && c < sizeof(debug)) - debug[c]++; - break; - case 'o': - outfile = EARGF(usage()); - break; - case 'E': - INITENTRY = EARGF(usage()); - break; - case 'I': - debug['I'] = 1; // denote cmdline interpreter override - interpreter = EARGF(usage()); - break; - case 'L': - Lflag(EARGF(usage())); - break; - case 'T': - INITTEXT = atolwhex(EARGF(usage())); - break; - case 'D': - INITDAT = atolwhex(EARGF(usage())); - break; - case 'R': - INITRND = atolwhex(EARGF(usage())); - break; - case 'r': - rpath = EARGF(usage()); - break; - case 'H': - HEADTYPE = headtype(EARGF(usage())); - /* do something about setting INITTEXT */ - break; - case 'V': - print("%cl version %s\n", thechar, getgoversion()); - errorexit(); - case 'X': - name = EARGF(usage()); - val = EARGF(usage()); - addstrdata(name, val); - break; - case 'B': - val = EARGF(usage()); - addbuildinfo(val); - break; - case 'k': - tracksym = EARGF(usage()); - break; - } ARGEND - - USED(argc); + flagcount("1", "use alternate profiling code", &debug['1']); + flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); + flagstr("E", "sym: entry symbol", &INITENTRY); + flagint32("D", "addr: data address", &INITDAT); + flagcount("G", "debug pseudo-ops", &debug['G']); + flagfn1("I", "interp: set ELF interp", setinterp); + flagfn1("L", "dir: add dir to library path", Lflag); + flagfn1("H", "head: header type", setheadtype); + flagcount("K", "add stack underflow checks", &debug['K']); + flagcount("M", "disable software div/mod", &debug['M']); + flagcount("O", "print pc-line tables", &debug['O']); + flagcount("P", "debug code generation", &debug['P']); + flagint32("R", "rnd: address rounding", &INITRND); + flagint32("T", "addr: text address", &INITTEXT); + flagfn0("V", "print version and exit", doversion); + flagcount("W", "disassemble input", &debug['W']); + flagfn2("X", "name value: define string data", addstrdata); + flagcount("Z", "clear stack frame on entry", &debug['Z']); + flagcount("a", "disassemble output", &debug['a']); + flagcount("b", "race detection", &debug['b']); + flagcount("c", "dump call graph", &debug['c']); + flagcount("d", "disable dynamic executable", &debug['d']); + flagcount("f", "ignore version mismatch", &debug['f']); + flagcount("g", "disable go package data checks", &debug['g']); + flagstr("k", "sym: set field tracking symbol", &tracksym); + flagcount("n", "dump symbol table", &debug['n']); + flagstr("o", "outfile: set output file", &outfile); + flagcount("p", "insert profiling code", &debug['p']); + flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); + flagcount("s", "disable symbol table", &debug['s']); + flagcount("u", "reject unsafe packages", &debug['u']); + flagcount("v", "print link trace", &debug['v']); + flagcount("w", "disable DWARF generation", &debug['w']); + + flagparse(&argc, &argv, usage); if(argc != 1) usage(); diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index 9f18b475c..054ae5e02 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -317,8 +317,8 @@ enum EXTERN int32 HEADR; EXTERN int32 HEADTYPE; EXTERN int32 INITRND; -EXTERN vlong INITTEXT; -EXTERN vlong INITDAT; +EXTERN int64 INITTEXT; +EXTERN int64 INITDAT; EXTERN char* INITENTRY; /* entry point */ EXTERN char* pcstr; EXTERN Auto* curauto; @@ -327,7 +327,7 @@ EXTERN Prog* curp; EXTERN Sym* cursym; EXTERN Sym* datap; EXTERN vlong elfdatsize; -EXTERN char debug[128]; +EXTERN int debug[128]; EXTERN char literal[32]; EXTERN Sym* textp; EXTERN Sym* etextp; diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index 08db03c4a..56f3df768 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -67,23 +67,11 @@ Header headers[] = { * -Hnetbsd -Tx -Rx is NetBSD elf-exec * -Hopenbsd -Tx -Rx is OpenBSD elf-exec * -Hwindows -Tx -Rx is MS Windows PE32+ - * - * options used: 189BLQSWabcjlnpsvz */ void -usage(void) -{ - fprint(2, "usage: 6l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.6\n"); - exits("usage"); -} - -void main(int argc, char *argv[]) { - int c; - char *name, *val; - Binit(&bso, 1, OWRITE); listinit(); memset(debug, 0, sizeof(debug)); @@ -96,58 +84,41 @@ main(int argc, char *argv[]) INITENTRY = 0; nuxiinit(); - ARGBEGIN { - default: - c = ARGC(); - if(c == 'l') - usage(); - if(c >= 0 && c < sizeof(debug)) - debug[c]++; - break; - case 'o': /* output to (next arg) */ - outfile = EARGF(usage()); - break; - case 'E': - INITENTRY = EARGF(usage()); - break; - case 'H': - HEADTYPE = headtype(EARGF(usage())); - break; - case 'I': - debug['I'] = 1; // denote cmdline interpreter override - interpreter = EARGF(usage()); - break; - case 'L': - Lflag(EARGF(usage())); - break; - case 'T': - INITTEXT = atolwhex(EARGF(usage())); - break; - case 'D': - INITDAT = atolwhex(EARGF(usage())); - break; - case 'R': - INITRND = atolwhex(EARGF(usage())); - break; - case 'r': - rpath = EARGF(usage()); - break; - case 'V': - print("%cl version %s\n", thechar, getgoversion()); - errorexit(); - case 'X': - name = EARGF(usage()); - val = EARGF(usage()); - addstrdata(name, val); - break; - case 'B': - val = EARGF(usage()); - addbuildinfo(val); - break; - case 'k': - tracksym = EARGF(usage()); - break; - } ARGEND + flagcount("1", "use alternate profiling code", &debug['1']); + flagcount("8", "assume 64-bit addresses", &debug['8']); + flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); + flagint64("D", "addr: data address", &INITDAT); + flagstr("E", "sym: entry symbol", &INITENTRY); + flagfn1("I", "interp: set ELF interp", setinterp); + flagfn1("L", "dir: add dir to library path", Lflag); + flagfn1("H", "head: header type", setheadtype); + flagcount("K", "add stack underflow checks", &debug['K']); + flagcount("O", "print pc-line tables", &debug['O']); + flagcount("Q", "debug byte-register code gen", &debug['Q']); + flagint32("R", "rnd: address rounding", &INITRND); + flagcount("S", "check type signatures", &debug['S']); + flagint64("T", "addr: text address", &INITTEXT); + flagfn0("V", "print version and exit", doversion); + flagcount("W", "disassemble input", &debug['W']); + flagfn2("X", "name value: define string data", addstrdata); + flagcount("Z", "clear stack frame on entry", &debug['Z']); + flagcount("a", "disassemble output", &debug['a']); + flagcount("b", "race detection", &debug['b']); + flagcount("c", "dump call graph", &debug['c']); + flagcount("d", "disable dynamic executable", &debug['d']); + flagcount("f", "ignore version mismatch", &debug['f']); + flagcount("g", "disable go package data checks", &debug['g']); + flagstr("k", "sym: set field tracking symbol", &tracksym); + flagcount("n", "dump symbol table", &debug['n']); + flagstr("o", "outfile: set output file", &outfile); + flagcount("p", "insert profiling code", &debug['p']); + flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); + flagcount("s", "disable symbol table", &debug['s']); + flagcount("u", "reject unsafe packages", &debug['u']); + flagcount("v", "print link trace", &debug['v']); + flagcount("w", "disable DWARF generation", &debug['w']); + + flagparse(&argc, &argv, usage); if(argc != 1) usage(); diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index 26f0eb016..8452e4bd4 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -283,7 +283,7 @@ EXTERN Prog* curp; EXTERN Sym* cursym; EXTERN Sym* datap; EXTERN int32 elfdatsize; -EXTERN char debug[128]; +EXTERN int debug[128]; EXTERN char literal[32]; EXTERN Sym* etextp; EXTERN Prog* firstp; @@ -296,7 +296,6 @@ EXTERN int maxop; EXTERN int nerrors; EXTERN char* noname; EXTERN int32 pc; -EXTERN char* interpreter; EXTERN char* rpath; EXTERN int32 spsize; EXTERN Sym* symlist; diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index 66f1205e5..5d32dfee7 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -77,18 +77,8 @@ Header headers[] = { */ void -usage(void) -{ - fprint(2, "usage: 8l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.8\n"); - exits("usage"); -} - -void main(int argc, char *argv[]) { - int c; - char *name, *val; - Binit(&bso, 1, OWRITE); listinit(); memset(debug, 0, sizeof(debug)); @@ -101,58 +91,40 @@ main(int argc, char *argv[]) INITENTRY = 0; nuxiinit(); - ARGBEGIN { - default: - c = ARGC(); - if(c == 'l') - usage(); - if(c >= 0 && c < sizeof(debug)) - debug[c]++; - break; - case 'o': /* output to (next arg) */ - outfile = EARGF(usage()); - break; - case 'E': - INITENTRY = EARGF(usage()); - break; - case 'H': - HEADTYPE = headtype(EARGF(usage())); - break; - case 'I': - debug['I'] = 1; // denote cmdline interpreter override - interpreter = EARGF(usage()); - break; - case 'L': - Lflag(EARGF(usage())); - break; - case 'T': - INITTEXT = atolwhex(EARGF(usage())); - break; - case 'D': - INITDAT = atolwhex(EARGF(usage())); - break; - case 'R': - INITRND = atolwhex(EARGF(usage())); - break; - case 'r': - rpath = EARGF(usage()); - break; - case 'V': - print("%cl version %s\n", thechar, getgoversion()); - errorexit(); - case 'X': - name = EARGF(usage()); - val = EARGF(usage()); - addstrdata(name, val); - break; - case 'B': - val = EARGF(usage()); - addbuildinfo(val); - break; - case 'k': - tracksym = EARGF(usage()); - break; - } ARGEND + flagcount("1", "use alternate profiling code", &debug['1']); + flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); + flagstr("E", "sym: entry symbol", &INITENTRY); + flagint32("D", "addr: data address", &INITDAT); + flagfn1("I", "interp: set ELF interp", setinterp); + flagfn1("L", "dir: add dir to library path", Lflag); + flagfn1("H", "head: header type", setheadtype); + flagcount("K", "add stack underflow checks", &debug['K']); + flagcount("O", "print pc-line tables", &debug['O']); + flagcount("Q", "debug byte-register code gen", &debug['Q']); + flagint32("R", "rnd: address rounding", &INITRND); + flagcount("S", "check type signatures", &debug['S']); + flagint32("T", "addr: text address", &INITTEXT); + flagfn0("V", "print version and exit", doversion); + flagcount("W", "disassemble input", &debug['W']); + flagfn2("X", "name value: define string data", addstrdata); + flagcount("Z", "clear stack frame on entry", &debug['Z']); + flagcount("a", "disassemble output", &debug['a']); + flagcount("b", "race detection", &debug['b']); + flagcount("c", "dump call graph", &debug['c']); + flagcount("d", "disable dynamic executable", &debug['d']); + flagcount("f", "ignore version mismatch", &debug['f']); + flagcount("g", "disable go package data checks", &debug['g']); + flagstr("k", "sym: set field tracking symbol", &tracksym); + flagstr("o", "outfile: set output file", &outfile); + flagcount("p", "insert profiling code", &debug['p']); + flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); + flagcount("s", "disable symbol table", &debug['s']); + flagcount("n", "dump symbol table", &debug['n']); + flagcount("u", "reject unsafe packages", &debug['u']); + flagcount("v", "print link trace", &debug['v']); + flagcount("w", "disable DWARF generation", &debug['w']); + + flagparse(&argc, &argv, usage); if(argc != 1) usage(); diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h index 3a0147e9f..6153bf9f7 100644 --- a/src/cmd/cc/cc.h +++ b/src/cmd/cc/cc.h @@ -474,7 +474,7 @@ EXTERN int autobn; EXTERN int32 autoffset; EXTERN int blockno; EXTERN Decl* dclstack; -EXTERN char debug[256]; +EXTERN int debug[256]; EXTERN Hist* ehist; EXTERN int32 firstbit; EXTERN Sym* firstarg; diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c index 653c298a2..b5408cf9e 100644 --- a/src/cmd/cc/lex.c +++ b/src/cmd/cc/lex.c @@ -86,10 +86,37 @@ pathchar(void) */ void +usage(void) +{ + print("usage: %cc [options] file.c...\n", thechar); + flagprint(1); + errorexit(); +} + +void +dospim(void) +{ + thechar = '0'; + thestring = "spim"; +} + +char **defs; +int ndef; + +void +dodef(char *p) +{ + if(ndef%8 == 0) + defs = allocn(defs, ndef*sizeof(char *), + 8*sizeof(char *)); + defs[ndef++] = p; + dodefine(p); +} + +void main(int argc, char *argv[]) { - char **defs, *p; - int c, ndef; + int c; ensuresymb(NSYMB); memset(debug, 0, sizeof(debug)); @@ -103,46 +130,56 @@ main(int argc, char *argv[]) defs = nil; outfile = 0; setinclude("."); - ARGBEGIN { - default: - c = ARGC(); - if(c >= 0 && c < sizeof(debug)) - debug[c]++; - break; - case 'l': /* for little-endian mips */ - if(thechar != 'v'){ - print("can only use -l with vc\n"); - errorexit(); - } - thechar = '0'; - thestring = "spim"; - break; - - case 'o': - outfile = ARGF(); - break; + flagcount("+", "pass -+ to preprocessor", &debug['+']); + flagcount(".", "pass -. to preprocessor", &debug['.']); + flagcount("<", "debug shift", &debug['<']); + flagcount("A", "debug alignment", &debug['A']); + flagcount("B", "allow pre-ANSI code", &debug['B']); + if(thechar == '5') + flagcount("C", "debug constant propagation", &debug['C']); + flagfn1("D", "name[=value]: add #define", dodef); + flagcount("F", "enable print format checks", &debug['F']); + if(thechar == '5') + flagcount("H", "debug shift propagation", &debug['H']); + flagfn1("I", "dir: add dir to include path", setinclude); + flagcount("L", "debug lexer", &debug['L']); + flagcount("M", "debug move generation", &debug['M']); + flagcount("N", "disable optimizations", &debug['N']); + flagcount("P", "debug peephole optimizer", &debug['P']); + flagcount("Q", "print exported Go definitions", &debug['Q']); + flagcount("R", "debug register optimizer", &debug['R']); + flagcount("S", "print assembly", &debug['S']); + flagcount("T", "enable type signatures", &debug['T']); + flagcount("V", "enable pointer type checks", &debug['V']); + flagcount("W", "debug switch generation", &debug['W']); + flagcount("X", "abort on error", &debug['X']); + flagcount("Y", "debug index generation", &debug['Y']); + flagcount("Z", "skip code generation", &debug['Z']); + flagcount("a", "print acid definitions", &debug['a']); + flagcount("c", "debug constant evaluation", &debug['c']); + flagcount("d", "debug declarations", &debug['d']); + flagcount("e", "debug macro expansion", &debug['e']); + flagcount("f", "debug pragmas", &debug['f']); + flagcount("g", "debug code generation", &debug['g']); + flagcount("i", "debug initialization", &debug['i']); + if(thechar == 'v') + flagfn0("l", "little-endian mips mode", dospim); + flagcount("m", "debug multiplication", &debug['m']); + flagcount("n", "print acid/Go to file, not stdout", &debug['n']); + flagstr("o", "file: set output file", &outfile); + flagcount("p", "invoke C preprocessor", &debug['p']); + flagcount("q", "print Go definitions", &debug['q']); + flagcount("s", "print #define assembly offsets", &debug['s']); + flagcount("t", "debug code generation", &debug['t']); + flagcount("w", "enable warnings", &debug['w']); + flagcount("v", "increase debug verbosity", &debug['v']); + + flagparse(&argc, &argv, usage); + + if(argc < 1 && outfile == 0) + usage(); - case 'D': - p = ARGF(); - if(p) { - if(ndef%8 == 0) - defs = allocn(defs, ndef*sizeof(char *), - 8*sizeof(char *)); - defs[ndef++] = p; - dodefine(p); - } - break; - - case 'I': - p = ARGF(); - setinclude(p); - break; - } ARGEND - if(argc < 1 && outfile == 0) { - print("usage: %cc [-options] files\n", thechar); - errorexit(); - } if(argc > 1){ print("can't compile multiple files\n"); errorexit(); diff --git a/src/cmd/cc/sub.c b/src/cmd/cc/sub.c index 424e2763a..9f124cb82 100644 --- a/src/cmd/cc/sub.c +++ b/src/cmd/cc/sub.c @@ -847,12 +847,6 @@ simplifyshift(Node *n) c2 = n->left->left->right->vconst; c3 = n->left->right->vconst; -/* - if(debug['h']) - print("%.3o %d %d %d #%.ux\n", - (s1<<3)|s2, c1, c2, topbit(c3), c3); -*/ - o = n->op; switch((s1<<3)|s2) { case 000: /* (((e <<u c2) & c3) <<u c1) */ diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 79149f4d0..59f5e7388 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -841,7 +841,7 @@ EXTERN int safemode; EXTERN char namebuf[NSYMB]; EXTERN char lexbuf[NSYMB]; EXTERN char litbuf[NSYMB]; -EXTERN char debug[256]; +EXTERN int debug[256]; EXTERN Sym* hash[NHASH]; EXTERN Sym* importmyname; // my name for package EXTERN Pkg* localpkg; // package being compiled diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index d7f9e42f4..1073b985c 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -133,42 +133,8 @@ enum void usage(void) { - print("gc: usage: %cg [flags] file.go...\n", thechar); - print("flags:\n"); - // -A allow use of "any" type, for bootstrapping - // -B disable bounds checking - // -E print imported declarations - // -K warn when lineno is zero - // -M print arguments to gmove - // -P print peephole diagnostics - // -R print optimizer diagnostics - // -g print code generation diagnostics - // -i print line history - // -j print variables to be initialized at runtime - // -r print generated helper functions - // -s print redundant types in composite literals - // -v print more information with -P or -R - // -y print declarations in cannedimports (used with -d) - // -% print non-static initializers - // -+ indicate that the runtime is being compiled - print(" -D PATH interpret local imports relative to this import path\n"); - print(" -I DIR search for packages in DIR\n"); - print(" -L show full path in file:line prints\n"); - print(" -N disable optimizations\n"); - print(" -S print the assembly language\n"); - print(" -V print the compiler version\n"); - print(" -W print the parse tree after typing\n"); - print(" -d print declarations\n"); - print(" -e no limit on number of errors printed\n"); - print(" -f print stack frame structure\n"); - print(" -h panic on an error\n"); - print(" -l disable inlining\n"); - print(" -m print optimization decisions\n"); - print(" -o file specify output file\n"); - print(" -p assumed import path for this code\n"); - print(" -u disable package unsafe\n"); - print(" -w print type checking details\n"); - print(" -x print lex tokens\n"); + print("usage: %cg [options] file.go...\n", thechar); + flagprint(1); exits("usage"); } @@ -186,10 +152,22 @@ fault(int s) fatal("fault"); } +void +doversion(void) +{ + char *p; + + p = expstring(); + if(strcmp(p, "X:none") == 0) + p = ""; + print("%cg version %s%s%s\n", thechar, getgoversion(), *p ? " " : "", p); + exits(0); +} + int main(int argc, char *argv[]) { - int i, c; + int i; NodeList *l; char *p; @@ -244,40 +222,44 @@ main(int argc, char *argv[]) setexp(); outfile = nil; - ARGBEGIN { - default: - c = ARGC(); - if(c >= 0 && c < sizeof(debug)) - debug[c]++; - break; - - case 'o': - outfile = EARGF(usage()); - break; - - case 'p': - myimportpath = EARGF(usage()); - break; - - case 'u': - safemode = 1; - break; - - case 'D': - localimport = EARGF(usage()); - break; - - case 'I': - addidir(EARGF(usage())); - break; - - case 'V': - p = expstring(); - if(strcmp(p, "X:none") == 0) - p = ""; - print("%cg version %s%s%s\n", thechar, getgoversion(), *p ? " " : "", p); - exits(0); - } ARGEND + flagcount("+", "compiling runtime", &compiling_runtime); + flagcount("%", "debug non-static initializers", &debug['%']); + flagcount("A", "for bootstrapping, allow 'any' type", &debug['A']); + flagcount("B", "disable bounds checking", &debug['B']); + flagstr("D", "path: set relative path for local imports", &localimport); + flagcount("E", "debug symbol export", &debug['E']); + flagfn1("I", "dir: add dir to import search path", addidir); + flagcount("K", "debug missing line numbers", &debug['K']); + flagcount("L", "use full (long) path in error messages", &debug['L']); + flagcount("M", "debug move generation", &debug['M']); + flagcount("N", "disable optimizations", &debug['N']); + flagcount("P", "debug peephole optimizer", &debug['P']); + flagcount("R", "debug register optimizer", &debug['R']); + flagcount("S", "print assembly listing", &debug['S']); + flagfn0("V", "print compiler version", doversion); + flagcount("W", "debug parse tree after type checking", &debug['W']); + flagcount("b", "enable race detector", &debug['b']); + flagcount("complete", "compiling complete package (no C or assembly)", &pure_go); + flagcount("d", "debug declarations", &debug['d']); + flagcount("e", "no limit on number of errors reported", &debug['e']); + flagcount("f", "debug stack frames", &debug['f']); + flagcount("g", "debug code generation", &debug['g']); + flagcount("h", "halt on error", &debug['h']); + flagcount("i", "debug line number stack", &debug['i']); + flagcount("j", "debug runtime-initialized variables", &debug['j']); + flagcount("l", "disable inlining", &debug['l']); + flagcount("m", "print optimization decisions", &debug['m']); + flagstr("o", "obj: set output file", &outfile); + flagstr("p", "path: set expected package import path", &myimportpath); + flagcount("r", "debug generated wrappers", &debug['r']); + flagcount("s", "warn about composite literals that can be simplified", &debug['s']); + flagcount("u", "reject unsafe code", &safemode); + flagcount("v", "increase debug verbosity", &debug['v']); + flagcount("w", "debug type checking", &debug['w']); + flagcount("x", "debug lexer", &debug['x']); + flagcount("y", "debug declarations in canned imports (with -d)", &debug['y']); + + flagparse(&argc, &argv, usage); if(debug['b']) { racepkg = mkpkg(strlit("runtime/race")); @@ -294,10 +276,6 @@ main(int argc, char *argv[]) if(argc < 1) usage(); - // special flags used during build. - compiling_runtime = debug['+']; // detect compilation of package runtime - pure_go = debug['=']; // package is completely go (no C or assembly) - pathname = mal(1000); if(getwd(pathname, 999) == 0) strcpy(pathname, "/???"); diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index dbe4b2b33..5975e0bfc 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1333,7 +1333,7 @@ func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g } } if extFiles == 0 { - gcargs = append(gcargs, "-=") + gcargs = append(gcargs, "-complete") } args := stringList(tool(archChar+"g"), "-o", ofile, buildGcflags, gcargs, "-D", p.localPrefix, importArgs) @@ -1345,7 +1345,7 @@ func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { sfile = mkAbs(p.Dir, sfile) - return b.run(p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj, "-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile) + return b.run(p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) } func (gcToolchain) pkgpath(basedir string, p *Package) string { @@ -1383,7 +1383,7 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) cfile = mkAbs(p.Dir, cfile) - args := stringList(tool(archChar+"c"), "-FVw", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile) + args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile) return b.run(p.Dir, p.ImportPath, args) } @@ -1419,9 +1419,9 @@ func (gccgcToolchain) gc(b *builder, p *Package, obj string, importArgs []string func (gccgcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { sfile = mkAbs(p.Dir, sfile) - defs := []string{"-DGOOS_" + goos, "-DGOARCH_" + goarch} + defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { - defs = append(defs, `-DGOPKGPATH="`+pkgpath+`"`) + defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) } return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, defs, sfile) } @@ -1486,9 +1486,9 @@ func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions [] func (gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) cfile = mkAbs(p.Dir, cfile) - defs := []string{"-DGOOS_" + goos, "-DGOARCH_" + goarch} + defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { - defs = append(defs, `-DGOPKGPATH="`+pkgpath+`"`) + defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) } return b.run(p.Dir, p.ImportPath, "gcc", "-Wall", "-g", "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) @@ -1894,7 +1894,7 @@ func raceInit() { } buildGcflags = append(buildGcflags, "-b") buildLdflags = append(buildLdflags, "-b") - buildCcflags = append(buildCcflags, "-DRACE") + buildCcflags = append(buildCcflags, "-D", "RACE") buildContext.InstallTag = "race" buildContext.BuildTags = append(buildContext.BuildTags, "race") } diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index 4e1d79a50..4b91af6eb 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -1503,6 +1503,34 @@ cwrite(void *buf, int n) } void +usage(void) +{ + fprint(2, "usage: %cl [options] main.%c\n", thechar, thechar); + flagprint(2); + exits("usage"); +} + +void +setheadtype(char *s) +{ + HEADTYPE = headtype(s); +} + +void +setinterp(char *s) +{ + debug['I'] = 1; // denote cmdline interpreter override + interpreter = s; +} + +void +doversion(void) +{ + print("%cl version %s\n", thechar, getgoversion()); + errorexit(); +} + +void genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) { Auto *a; diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 13009d2a3..cc9e2dac6 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -136,6 +136,7 @@ EXTERN int havedynamic; EXTERN int iscgo; EXTERN int elfglobalsymndx; EXTERN char* tracksym; +EXTERN char* interpreter; EXTERN Segment segtext; EXTERN Segment segdata; @@ -224,6 +225,9 @@ void dostkcheck(void); void undef(void); void doweak(void); void setpersrc(Sym*); +void doversion(void); +void usage(void); +void setinterp(char*); int pathchar(void); void* mal(uint32); @@ -291,6 +295,7 @@ EXTERN char* headstring; extern Header headers[]; int headtype(char*); +void setheadtype(char*); int Yconv(Fmt*); diff --git a/src/lib9/flag.c b/src/lib9/flag.c new file mode 100644 index 000000000..39441b908 --- /dev/null +++ b/src/lib9/flag.c @@ -0,0 +1,300 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <u.h> +#include <libc.h> + +// Flag hash. +typedef struct Flag Flag; + +struct Flag +{ + char *name; + int namelen; + char *desc; + int iscount; + void (*set)(char*, void*); + void (*set2)(char*, char*, void*); + void *arg; + Flag *next; + Flag *allnext; +}; + +static Flag *curflag; + +static Flag *fhash[512]; +static Flag *first, *last; + +// FNV-1 hash. http://isthe.com/chongo/tech/comp/fnv/ +static uint32 +fnv(char *p, int n) +{ + uint32 h; + + h = 2166136261U; + while(n-- > 0) + h = (h*16777619) ^ (uchar)*p++; + return h; +} + +static Flag* +lookflag(char *name, int namelen, int creat) +{ + uint32 h; + Flag *f; + + h = fnv(name, namelen) & (nelem(fhash)-1); + for(f=fhash[h]; f; f=f->next) { + if(f->namelen == namelen && memcmp(f->name, name, namelen) == 0) { + if(creat) + sysfatal("multiple definitions of flag -%s", name); + return f; + } + } + + if(!creat) + return nil; + + f = malloc(sizeof *f); + if(f == nil) + sysfatal("out of memory"); + memset(f, 0, sizeof *f); + f->name = name; + f->namelen = namelen; + f->next = fhash[h]; + if(first == nil) + first = f; + else + last->allnext = f; + last = f; + fhash[h] = f; + return f; +} + +static void +count(char *arg, void *p) +{ + int *ip; + + ip = p; + if(arg != nil) + *ip = atoi(arg); + else + (*ip)++; +} + +void +flagcount(char *name, char *desc, int *p) +{ + Flag *f; + + f = lookflag(name, strlen(name), 1); + f->desc = desc; + f->iscount = 1; + f->set = count; + f->arg = p; +} + +static void +atollwhex(char *s, void *p) +{ + char *t; + + *(int64*)p = strtoll(s, &t, 0); + if(*s == '\0' || *t != '\0') + sysfatal("invalid numeric argument -%s=%s", curflag->name, s); +} + +void +flagint64(char *name, char *desc, int64 *p) +{ + Flag *f; + + f = lookflag(name, strlen(name), 1); + f->desc = desc; + f->set = atollwhex; + f->arg = p; +} + +static void +atolwhex(char *s, void *p) +{ + char *t; + + *(int32*)p = strtol(s, &t, 0); + if(*s == '\0' || *t != '\0') + sysfatal("invalid numeric argument -%s=%s", curflag->name, s); +} + +void +flagint32(char *name, char *desc, int32 *p) +{ + Flag *f; + + f = lookflag(name, strlen(name), 1); + f->desc = desc; + f->set = atolwhex; + f->arg = p; +} + +static void +string(char *s, void *p) +{ + *(char**)p = s; +} + +void +flagstr(char *name, char *desc, char **p) +{ + + Flag *f; + + f = lookflag(name, strlen(name), 1); + f->desc = desc; + f->set = string; + f->arg = p; +} + +static void +fn0(char *s, void *p) +{ + USED(s); + ((void(*)(void))p)(); +} + +void +flagfn0(char *name, char *desc, void (*fn)(void)) +{ + Flag *f; + + f = lookflag(name, strlen(name), 1); + f->desc = desc; + f->set = fn0; + f->arg = fn; + f->iscount = 1; +} + +static void +fn1(char *s, void *p) +{ + ((void(*)(char*))p)(s); +} + +void +flagfn1(char *name, char *desc, void (*fn)(char*)) +{ + Flag *f; + + f = lookflag(name, strlen(name), 1); + f->desc = desc; + f->set = fn1; + f->arg = fn; +} + +static void +fn2(char *s, char *t, void *p) +{ + ((void(*)(char*, char*))p)(s, t); +} + +void +flagfn2(char *name, char *desc, void (*fn)(char*, char*)) +{ + Flag *f; + + f = lookflag(name, strlen(name), 1); + f->desc = desc; + f->set2 = fn2; + f->arg = fn; +} + +void +flagparse(int *argcp, char ***argvp, void (*usage)(void)) +{ + int argc; + char **argv, *p, *q; + char *name; + int namelen; + Flag *f; + + argc = *argcp; + argv = *argvp; + + __fixargv0(); + argv0 = argv[0]; + argc--; + argv++; + + while(argc > 0) { + p = *argv; + // stop before non-flag or - + if(*p != '-' || p[1] == '\0') + break; + argc--; + argv++; + // stop after -- + if(p[1] == '-' && p[2] == '\0') { + break; + } + + // turn --foo into -foo + if(p[1] == '-' && p[2] != '-') + p++; + + // allow -flag=arg if present + name = p+1; + q = strchr(name, '='); + if(q != nil) + namelen = q++ - name; + else + namelen = strlen(name); + f = lookflag(name, namelen, 0); + if(f == nil) { + if(strcmp(p, "-h") == 0 || strcmp(p, "-help") == 0 || strcmp(p, "-?") == 0) + usage(); + sysfatal("unknown flag %s", p); + } + curflag = f; + + // otherwise consume next argument if non-boolean + if(!f->iscount && q == nil) { + if(argc-- == 0) + sysfatal("missing argument to flag %s", p); + q = *argv++; + } + + // and another if we need two + if(f->set2 != nil) { + if(argc-- == 0) + sysfatal("missing second argument to flag %s", p); + f->set2(q, *argv++, f->arg); + continue; + } + + f->set(q, f->arg); + } + + *argcp = argc; + *argvp = argv; +} + +void +flagprint(int fd) +{ + Flag *f; + char *p, *q; + + for(f=first; f; f=f->allnext) { + p = f->desc; + if(p == nil || *p == '\0') // undocumented flag + continue; + q = strstr(p, ": "); + if(q) + fprint(fd, " -%s %.*s\n \t%s\n", f->name, utfnlen(p, q-p), p, q+2); + else if(f->namelen > 1) + fprint(fd, " -%s\n \t%s\n", f->name, p); + else + fprint(fd, " -%s\t%s\n", f->name, p); + } +} |