Commit 22301e8c authored by Robert Griesemer's avatar Robert Griesemer

Some adjustments to godoc:

- work-around for incorrect import path
- added tmpl root in order to run against a goroot w/o templates
- clarifications

Daily snapshot of syntax-driven formatter. Some progress.

Updated gccgo Makefile.

TBR=r
OCL=28004
CL=28004
parent 7a98315c
...@@ -6,22 +6,12 @@ ...@@ -6,22 +6,12 @@
GO = /home/iant/go/bin/gccgo GO = /home/iant/go/bin/gccgo
LDFLAGS = -Wl,-R,/home/iant/go/lib LDFLAGS = -Wl,-R,/home/iant/go/lib,-static-libgo
PRETTY_OBJS = \ PRETTY_OBJS = \
ast.o \ astprinter.o \
compilation.o \ format.o \
globals.o \
object.o \
parser.o \
platform.o \
pretty.o \ pretty.o \
printer.o \
scanner.o \
type.o \
typechecker.o \
universe.o \
utils.o
pretty: $(PRETTY_OBJS) pretty: $(PRETTY_OBJS)
$(GO) $(LDFLAGS) -o $@ $(PRETTY_OBJS) $(GO) $(LDFLAGS) -o $@ $(PRETTY_OBJS)
...@@ -36,27 +26,7 @@ clean: ...@@ -36,27 +26,7 @@ clean:
rm -f pretty *.o *~ rm -f pretty *.o *~
pretty.o: platform.o printer.o compilation.o pretty.o: astprinter.o format.o
compilation.o: platform.o scanner.o parser.o ast.o typechecker.o
ast.o: scanner.o
scanner.o: utils.o
parser.o: scanner.o ast.o
platform.o: utils.o
printer.o: scanner.o ast.o
typechecker.o: ast.o universe.o globals.o type.o
universe.o: globals.o object.o type.o
object.o: globals.o
type.o: globals.o object.o
.SUFFIXES: .SUFFIXES:
.SUFFIXES: .go .o .SUFFIXES: .go .o
......
//string = // Copyright 2009 The Go Authors. All rights reserved.
// "%s"; // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
pointer = // ----------------------------------------------------------------------------
// Debugging
token.Token =
^ : "%s";
// Format file for printing AST nodes (package "ast").
ast;
// ----------------------------------------------------------------------------
// TODO should these be automatic?
Expr =
"expr ";
//*;
Stmt =
*; *;
array = Decl =
*; *;
//token.Token = // ----------------------------------------------------------------------------
// "token<%d>"; // this could be a Go-installed formatter // Comments
ast Comment =
; Text : "%s\n";
Comments = Comments =
"comments\n"; {*};
// ----------------------------------------------------------------------------
// Expressions & Types
Field =
{Names ", "} Type;
BadExpr =
"BAD EXPR";
Ident = Ident =
Value; Value;
Program = Elipsis =
"package " Name "\n\n" {Decls "\n\n"}; "...";
GenDecl = IntLit =
Doc Value : "%s";
Tok " (\n"
")\n"; FloatLit =
Value : "%s";
CharLit =
Value : "%s";
StringLit =
Value : "%s";
StringList =
{ Strings };
FuncLit =
"func ";
CompositeLit =
Type "{}";
ParenExpr =
"(" X ")";
SelectorExpr =
X "." Sel;
IndexExpr =
X "[" Index "]";
SliceExpr =
X "[" Begin " : " End "]";
TypeAssertExpr =
X ".(" Type ")";
CallExpr =
Fun "(" {Args} ")";
StarExpr =
"*" X;
UnaryExpr =
Op X;
BinaryExpr =
X Op Y;
KeyValueExpr =
Key ": " Value;
ArrayType =
"[" Len "]" Elt;
SliceType =
"[]" Elt;
StructType =
"struct {\n"
"}";
FuncType = FuncType =
"(" ")"; "(" {Params " "} ")";
// BUG take this one away and the code crashes
InterfaceType =
"interface {}";
MapType =
"map[" Key "]" Value;
ChanType =
"chan";
// ----------------------------------------------------------------------------
// Statements
BadStmt =
"BAD STMT";
DeclStmt =
Decl;
EmptyStmt =
;
LabeledStmt =
Label ":\t" Stmt;
ExprStmt =
X;
IncDecStmt =
X Tok;
AssignStmt =
"assignment " {Lhs ", "};
//{Lhs ", "} Tok {Rhs ", "};
GoStmt =
"go " Call;
ReturnStmt =
"return" {" " Results};
BranchStmt =
Tok [" " Label];
BlockStmt = BlockStmt =
"{\n" "}\n"; "{\n" {List ";\n"} "}\n";
IfStmt =
"if " "{" [Body] "}" [Else];
SwitchStmt =
"switch {}";
TypeSwitchStmt =
"switch {}";
SelectStmt =
"select {}";
ForStmt =
"for {}";
RangeStmt =
"range";
// ----------------------------------------------------------------------------
// Declarations
Spec =
*;
ImportSpec =
"import";
ValueSpec =
"value";
TypeSpec =
"type";
BadDecl =
"BAD DECL";
GenDecl =
Doc
Tok " (\n"
")\n";
FuncDecl = FuncDecl =
"func " Name Type [" " Body]; "func " ["(" Recv ") "] Name Type [" " Body];
Decl =
^; // ----------------------------------------------------------------------------
\ No newline at end of file // Program
Program =
Doc
"package " Name "\n\n"
{Decls "\n\n"};
...@@ -11,16 +11,17 @@ ...@@ -11,16 +11,17 @@
(strings), references to fields, and alternative, grouped, optional, (strings), references to fields, and alternative, grouped, optional,
and repetitive sub-expressions. and repetitive sub-expressions.
When printing a value, its type name is used to lookup the production When printing a value, its type name is used to look up the production
to be printed. Literal values are printed as is, field references are to be printed. Literal values are printed as is, field references are
resolved and the respective field value is printed instead (using its resolved and the respective field values are printed instead (using their
type-specific production), and alternative, grouped, optional, and type-specific productions), and alternative, grouped, optional, and
repetitive sub-expressions are printed depending on whether they contain repetitive sub-expressions are printed depending on whether they contain
"empty" fields or not. A field is empty if its value is nil. "empty" fields or not. A field is empty if its value is nil.
*/ */
package format package format
import ( import (
"flag";
"fmt"; "fmt";
"go/scanner"; "go/scanner";
"go/token"; "go/token";
...@@ -31,6 +32,10 @@ import ( ...@@ -31,6 +32,10 @@ import (
) )
// TODO remove once the code works
var debug = flag.Bool("d", false, "debug mode");
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Format representation // Format representation
...@@ -75,11 +80,6 @@ type ( ...@@ -75,11 +80,6 @@ type (
) )
// TODO If we had a basic accessor mechanism in the language (a field
// "f T" automatically implements a corresponding accessor "f() T", this
// could be expressed more easily by simply providing the field.
//
func (x *alternative) String() string { func (x *alternative) String() string {
return fmt.Sprintf("(%v | %v)", x.x, x.y); return fmt.Sprintf("(%v | %v)", x.x, x.y);
} }
...@@ -130,20 +130,20 @@ func (x *custom) String() string { ...@@ -130,20 +130,20 @@ func (x *custom) String() string {
Expression = Term { "|" Term } . Expression = Term { "|" Term } .
Term = Factor { Factor } . Term = Factor { Factor } .
Factor = string_literal | Field | Group | Option | Repetition . Factor = string_literal | Field | Group | Option | Repetition .
Field = ( "^" | "*" | Name ) [ ":" Expression ] . Field = ( "^" | "*" | Name ) [ ":" Expression ] .
Group = "(" Expression ")" . Group = "(" Expression ")" .
Option = "[" Expression "]" . Option = "[" Expression "]" .
Repetition = "{" Expression "}" . Repetition = "{" Expression "}" .
The syntax of white space, comments, identifiers, and string literals is The syntax of white space, comments, identifiers, and string literals is
the same as in Go. the same as in Go.
A production name corresponds to a Go type name of the form A production name corresponds to a Go type name of the form
PackageName.TypeName PackageName.TypeName
(for instance format.Format). A production of the form (for instance format.Format). A production of the form
Name; Name;
specifies a package name which is prepended to all subsequent production specifies a package name which is prepended to all subsequent production
...@@ -471,13 +471,23 @@ func fieldIndex(v reflect.StructValue, fieldname string) int { ...@@ -471,13 +471,23 @@ func fieldIndex(v reflect.StructValue, fieldname string) int {
} }
func getField(v reflect.StructValue, fieldname string) reflect.Value { func getField(v reflect.StructValue, i int) reflect.Value {
fld := v.Field(i);
if tmp, is_interface := fld.(reflect.InterfaceValue); is_interface {
// TODO do I have to check something for nil here?
fld = reflect.NewValue(tmp.Get());
}
return fld;
}
func getFieldByName(v reflect.StructValue, fieldname string) reflect.Value {
i := fieldIndex(v, fieldname); i := fieldIndex(v, fieldname);
if i < 0 { if i < 0 {
panicln("field not found:", fieldname); panicln("field not found:", fieldname);
} }
return v.Field(i); return getField(v, i);
} }
...@@ -521,6 +531,8 @@ func typename(value reflect.Value) string { ...@@ -521,6 +531,8 @@ func typename(value reflect.Value) string {
var defaults = map [int] expr { var defaults = map [int] expr {
reflect.ArrayKind: &field{"*", nil}, reflect.ArrayKind: &field{"*", nil},
reflect.DotDotDotKind: &field{"*", nil},
reflect.InterfaceKind: &field{"*", nil},
reflect.MapKind: &field{"*", nil}, reflect.MapKind: &field{"*", nil},
reflect.PtrKind: &field{"*", nil}, reflect.PtrKind: &field{"*", nil},
} }
...@@ -568,41 +580,53 @@ func printf(w io.Write, format []byte, value reflect.Value) { ...@@ -568,41 +580,53 @@ func printf(w io.Write, format []byte, value reflect.Value) {
} }
// Returns true if a non-empty field value was found. // TODO once 6g bug found
func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bool { func print(s string, a ...) {
debug := false; // enable for debugging /*
if debug { f0 := reflect.NewValue(a).(reflect.StructValue).Field(0);
fmt.Printf("print(%v, = %v, %v, %d)\n", w, fexpr, value.Interface(), index); if t, is_iface := f0.(reflect.InterfaceValue); is_iface {
f0 = reflect.NewValue(t.Get());
} }
*/
fmt.Printf(s, a)
}
func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index, level int) bool
// Returns true if a non-empty field value was found.
func (f Format) print0(w io.Write, fexpr expr, value reflect.Value, index, level int) bool {
if fexpr == nil { if fexpr == nil {
return true; return true;
} }
if value == nil {
panic("should not be possible");
}
switch t := fexpr.(type) { switch t := fexpr.(type) {
case *alternative: case *alternative:
// - print the contents of the first alternative with a non-empty field // - print the contents of the first alternative with a non-empty field
// - result is true if there is at least one non-empty field // - result is true if there is at least one non-empty field
b := false;
var buf io.ByteBuffer; var buf io.ByteBuffer;
if f.print(&buf, t.x, value, index) { if f.print(&buf, t.x, value, index, level) {
w.Write(buf.Data()); w.Write(buf.Data());
b = true; return true;
} else { } else {
buf.Reset(); buf.Reset();
if f.print(&buf, t.y, value, 0) { if f.print(&buf, t.y, value, 0, level) {
w.Write(buf.Data()); w.Write(buf.Data());
b = true; return true;
} }
} }
return b; return false;
case *sequence: case *sequence:
// - print the contents of the sequence // - print the contents of the sequence
// - result is true if there is no empty field // - result is true if there is no empty field
// TODO do we need to buffer here? why not? // TODO do we need to buffer here? why not?
b1 := f.print(w, t.x, value, index); b1 := f.print(w, t.x, value, index, level);
b2 := f.print(w, t.y, value, index); b2 := f.print(w, t.y, value, index, level);
return b1 && b2; return b1 && b2;
case *field: case *field:
...@@ -616,13 +640,10 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo ...@@ -616,13 +640,10 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo
case "*": case "*":
// indirect // indirect
if value.Addr() == nil { // TODO is this right?
return false;
}
switch v := value.(type) { switch v := value.(type) {
case reflect.PtrValue:
if v.Get() == nil {
return false;
}
value = v.Sub();
case reflect.ArrayValue: case reflect.ArrayValue:
if index < 0 || v.Len() <= index { if index < 0 || v.Len() <= index {
return false; return false;
...@@ -632,8 +653,14 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo ...@@ -632,8 +653,14 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo
case reflect.MapValue: case reflect.MapValue:
panic("reflection support for maps incomplete"); panic("reflection support for maps incomplete");
case reflect.PtrValue:
if v.Get() == nil { // TODO is this right?
return false;
}
value = v.Sub();
case reflect.InterfaceValue: case reflect.InterfaceValue:
if v.Get() == nil { if v.Get() == nil { // TODO is this right?
return false; return false;
} }
value = v.Value(); value = v.Value();
...@@ -642,10 +669,15 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo ...@@ -642,10 +669,15 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo
panic("not a ptr, array, map, or interface"); // TODO fix this panic("not a ptr, array, map, or interface"); // TODO fix this
} }
if value == nil {
fmt.Fprint(w, "NIL"); // TODO debugging
return false;
}
default: default:
// field // field
if s, is_struct := value.(reflect.StructValue); is_struct { if s, is_struct := value.(reflect.StructValue); is_struct {
value = getField(s, t.name); value = getFieldByName(s, t.name);
} else { } else {
panic ("not a struct"); // TODO fix this panic ("not a struct"); // TODO fix this
} }
...@@ -658,16 +690,7 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo ...@@ -658,16 +690,7 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo
fexpr = f.getFormat(value); fexpr = f.getFormat(value);
} }
return f.print(w, fexpr, value, index); return f.print(w, fexpr, value, index, level);
// BUG (6g?) crash with code below
/*
var buf io.ByteBuffer;
if f.print(&buf, fexpr, value, index) {
w.Write(buf.Data());
return true;
}
return false;
*/
case *literal: case *literal:
// - print the literal // - print the literal
...@@ -677,27 +700,20 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo ...@@ -677,27 +700,20 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo
case *option: case *option:
// print the contents of the option if it contains a non-empty field // print the contents of the option if it contains a non-empty field
//var foobar bool; // BUG w/o this declaration the code works!!!
var buf io.ByteBuffer; var buf io.ByteBuffer;
if f.print(&buf, t.x, value, 0) { if f.print(&buf, t.x, value, 0, level) {
w.Write(buf.Data()); w.Write(buf.Data());
return true;
} }
return false; return true;
case *repetition: case *repetition:
// print the contents of the repetition while there is a non-empty field // print the contents of the repetition while there is a non-empty field
b := false; var buf io.ByteBuffer;
for i := 0; ; i++ { for i := 0; f.print(&buf, t.x, value, i, level); i++ {
var buf io.ByteBuffer; w.Write(buf.Data());
if f.print(&buf, t.x, value, i) { buf.Reset();
w.Write(buf.Data());
b = true;
} else {
break;
}
} }
return b; return true;
case *custom: case *custom:
return t.f(w, value.Interface(), t.name); return t.f(w, value.Interface(), t.name);
...@@ -708,6 +724,34 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo ...@@ -708,6 +724,34 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo
} }
func printTrace(indent int, format string, a ...) {
const dots =
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ";
const n = len(dots);
i := 2*indent;
for ; i > n; i -= n {
fmt.Print(dots);
}
fmt.Print(dots[0 : i]);
fmt.Printf(format, a);
}
func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index, level int) bool {
if *debug {
printTrace(level, "%v, %d {\n", fexpr, /*value.Interface(), */index);
}
result := f.print0(w, fexpr, value, index, level+1);
if *debug {
printTrace(level, "} %v\n", result);
}
return result;
}
// TODO proper error reporting // TODO proper error reporting
// Fprint formats each argument according to the format f // Fprint formats each argument according to the format f
...@@ -716,13 +760,13 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo ...@@ -716,13 +760,13 @@ func (f Format) print(w io.Write, fexpr expr, value reflect.Value, index int) bo
func (f Format) Fprint(w io.Write, args ...) { func (f Format) Fprint(w io.Write, args ...) {
value := reflect.NewValue(args).(reflect.StructValue); value := reflect.NewValue(args).(reflect.StructValue);
for i := 0; i < value.Len(); i++ { for i := 0; i < value.Len(); i++ {
fld := value.Field(i); fld := getField(value, i);
f.print(w, f.getFormat(fld), fld, -1); f.print(w, f.getFormat(fld), fld, -1, 0);
} }
} }
// Fprint formats each argument according to the format f // Print formats each argument according to the format f
// and writes to standard output. // and writes to standard output.
// //
func (f Format) Print(args ...) { func (f Format) Print(args ...) {
...@@ -730,7 +774,7 @@ func (f Format) Print(args ...) { ...@@ -730,7 +774,7 @@ func (f Format) Print(args ...) {
} }
// Fprint formats each argument according to the format f // Sprint formats each argument according to the format f
// and returns the resulting string. // and returns the resulting string.
// //
func (f Format) Sprint(args ...) string { func (f Format) Sprint(args ...) string {
......
...@@ -52,11 +52,6 @@ import ( ...@@ -52,11 +52,6 @@ import (
) )
// TODO: tell flag package about usage string
const usageString =
"usage: godoc package [name ...]\n"
" godoc -http=:6060\n"
const Pkg = "/pkg/" // name for auto-generated package documentation tree const Pkg = "/pkg/" // name for auto-generated package documentation tree
...@@ -66,6 +61,7 @@ var ( ...@@ -66,6 +61,7 @@ var (
// file system roots // file system roots
goroot string; goroot string;
pkgroot = flag.String("pkgroot", "src/lib", "root package source directory (if unrooted, relative to goroot)"); pkgroot = flag.String("pkgroot", "src/lib", "root package source directory (if unrooted, relative to goroot)");
tmplroot = flag.String("tmplroot", "usr/gri/pretty", "root template directory (if unrooted, relative to goroot)");
// layout control // layout control
tabwidth = flag.Int("tabwidth", 4, "tab width"); tabwidth = flag.Int("tabwidth", 4, "tab width");
...@@ -81,7 +77,7 @@ func init() { ...@@ -81,7 +77,7 @@ func init() {
var err os.Error; var err os.Error;
goroot, err = os.Getenv("GOROOT"); goroot, err = os.Getenv("GOROOT");
if err != nil { if err != nil {
goroot = "/home/r/go-build/go"; goroot = "/home/r/go-release/go";
} }
flag.StringVar(&goroot, "goroot", goroot, "Go root directory"); flag.StringVar(&goroot, "goroot", goroot, "Go root directory");
} }
...@@ -312,13 +308,11 @@ var fmap = template.FormatterMap{ ...@@ -312,13 +308,11 @@ var fmap = template.FormatterMap{
} }
// TODO: const templateDir = "lib/godoc"
const templateDir = "usr/gri/pretty"
func readTemplate(name string) *template.Template { func readTemplate(name string) *template.Template {
data, err := ReadFile(templateDir + "/" + name); path := pathutil.Join(*tmplroot, name);
data, err := ReadFile(path);
if err != nil { if err != nil {
log.Exitf("ReadFile %s: %v", name, err); log.Exitf("ReadFile %s: %v", path, err);
} }
t, err1 := template.Parse(string(data), fmap); t, err1 := template.Parse(string(data), fmap);
if err1 != nil { if err1 != nil {
...@@ -461,7 +455,7 @@ func addFile(pmap map[string]*pakDesc, dirname, filename, importprefix string) { ...@@ -461,7 +455,7 @@ func addFile(pmap map[string]*pakDesc, dirname, filename, importprefix string) {
return; return;
} }
// determine package name // determine package name
path := dirname + "/" + filename; path := pathutil.Join(dirname, filename);
prog, errors := parse(path, parser.PackageClauseOnly); prog, errors := parse(path, parser.PackageClauseOnly);
if prog == nil { if prog == nil {
return; return;
...@@ -560,7 +554,17 @@ func (p *pakDesc) Doc() (*doc.PackageDoc, *parseErrors) { ...@@ -560,7 +554,17 @@ func (p *pakDesc) Doc() (*doc.PackageDoc, *parseErrors) {
if i == 0 { if i == 0 {
// first file - initialize doc // first file - initialize doc
r.Init(prog.Name.Value, p.importpath); // canonicalize importpath
// (e.g. such that "template/template" becomes just "template")
// TODO This should not be needed here as similar functionality
// is elsewhere, but w/o this fix the output is incorrect
// for, say: "godoc template/template". Temporary work-around.
path := p.importpath;
dir, name := pathutil.Split(pathutil.Clean(path));
if name == prog.Name.Value {
path = pathutil.Clean(dir);
}
r.Init(prog.Name.Value, path);
} }
i++; i++;
r.AddProgram(prog); r.AddProgram(prog);
...@@ -624,29 +628,31 @@ func findPackages(name string) *pakInfo { ...@@ -624,29 +628,31 @@ func findPackages(name string) *pakInfo {
info := new(pakInfo); info := new(pakInfo);
// Build list of packages. // Build list of packages.
pmap := make(map[string]*pakDesc);
// If the path names a directory, scan that directory // If the path names a directory, scan that directory
// for a package with the name matching the directory name. // for a package with the name matching the directory name.
// Otherwise assume it is a package name inside // Otherwise assume it is a package name inside
// a directory, so scan the parent. // a directory, so scan the parent.
pmap := make(map[string]*pakDesc);
cname := pathutil.Clean(name); cname := pathutil.Clean(name);
if cname == "" { if cname == "" {
cname = "." cname = "."
} }
dir := pathutil.Join(*pkgroot, cname); dir := pathutil.Join(*pkgroot, cname);
url := pathutil.Join(Pkg, cname);
if isDir(dir) { if isDir(dir) {
parent, pak := pathutil.Split(dir);
addDirectory(pmap, dir, cname, &info.Subdirs); addDirectory(pmap, dir, cname, &info.Subdirs);
paks := mapValues(pmap); paks := mapValues(pmap);
if len(paks) == 1 { if len(paks) == 1 {
p := paks[0]; p := paks[0];
_, pak := pathutil.Split(dir);
if p.dirname == dir && p.pakname == pak { if p.dirname == dir && p.pakname == pak {
info.Package = p; info.Package = p;
info.Path = cname; info.Path = cname;
return info; return info;
} }
} }
info.Packages = paks; info.Packages = paks;
if cname == "." { if cname == "." {
info.Path = ""; info.Path = "";
...@@ -656,12 +662,13 @@ func findPackages(name string) *pakInfo { ...@@ -656,12 +662,13 @@ func findPackages(name string) *pakInfo {
return info; return info;
} }
// Otherwise, have parentdir/pak. Look for package pak in dir. // Otherwise, have parentdir/pak. Look for package pak in parentdir.
parentdir, pak := pathutil.Split(dir); parentdir, _ := pathutil.Split(dir);
parentname, nam := pathutil.Split(cname); parentname, _ := pathutil.Split(cname);
if parentname == "" { if parentname == "" {
parentname = "." parentname = "."
} }
addDirectory(pmap, parentdir, parentname, nil); addDirectory(pmap, parentdir, parentname, nil);
if p, ok := pmap[cname]; ok { if p, ok := pmap[cname]; ok {
info.Package = p; info.Package = p;
...@@ -703,7 +710,11 @@ func LoggingHandler(h http.Handler) http.Handler { ...@@ -703,7 +710,11 @@ func LoggingHandler(h http.Handler) http.Handler {
func usage() { func usage() {
fmt.Fprintf(os.Stderr, usageString); fmt.Fprintf(os.Stderr,
"usage: godoc package [name ...]\n"
" godoc -http=:6060\n"
);
flag.PrintDefaults();
sys.Exit(1); sys.Exit(1);
} }
...@@ -736,6 +747,7 @@ func main() { ...@@ -736,6 +747,7 @@ func main() {
log.Stderrf("address = %s\n", *httpaddr); log.Stderrf("address = %s\n", *httpaddr);
log.Stderrf("goroot = %s\n", goroot); log.Stderrf("goroot = %s\n", goroot);
log.Stderrf("pkgroot = %s\n", *pkgroot); log.Stderrf("pkgroot = %s\n", *pkgroot);
log.Stderrf("tmplroot = %s\n", *tmplroot);
handler = LoggingHandler(handler); handler = LoggingHandler(handler);
} }
...@@ -774,7 +786,7 @@ func main() { ...@@ -774,7 +786,7 @@ func main() {
if flag.NArg() > 1 { if flag.NArg() > 1 {
args := flag.Args(); args := flag.Args();
doc.Filter(args[1:len(args)]); doc.Filter(args[1 : len(args)]);
} }
packageText.Execute(doc, os.Stdout); packageText.Execute(doc, os.Stdout);
......
...@@ -39,7 +39,7 @@ func init() { ...@@ -39,7 +39,7 @@ func init() {
func usage() { func usage() {
print("usage: pretty { flags } { files }\n"); fmt.Fprintf(os.Stderr, "usage: pretty { flags } { files }\n");
flag.PrintDefaults(); flag.PrintDefaults();
sys.Exit(0); sys.Exit(0);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment