]> Cypherpunks repositories - gostls13.git/commitdiff
remove lots of accumulated crud:
authorRobert Griesemer <gri@golang.org>
Wed, 22 Apr 2009 01:37:48 +0000 (18:37 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 22 Apr 2009 01:37:48 +0000 (18:37 -0700)
- delete utility files which contained functionality that is now elsewhere
  (or saved the files away for now)
- cleanup Makefile (remove unnecessary deps)
- minor adjustments to godoc, fixed a couple of bugs
- make pretty.go self-contained

TBR=r
DELTA=625  (81 added, 510 deleted, 34 changed)
OCL=27700
CL=27702

usr/gri/pretty/Makefile
usr/gri/pretty/astprinter.go
usr/gri/pretty/compilation.go [deleted file]
usr/gri/pretty/docprinter.go
usr/gri/pretty/godoc.go
usr/gri/pretty/package.html
usr/gri/pretty/platform.go [deleted file]
usr/gri/pretty/pretty.go
usr/gri/pretty/selftest2.go
usr/gri/pretty/typechecker.go [deleted file]
usr/gri/pretty/utils.go [deleted file]

index 3546aaa212f18bf6562044add0aa880d3f8603be..c00163fb64f39336ac9ee577badd1a5a4538bf0d 100644 (file)
@@ -23,28 +23,16 @@ smoketest: pretty
        ./test.sh astprinter.go
 
 install: pretty godoc untab
-       cp pretty $(HOME)/bin/pretty
        cp godoc $(HOME)/bin/godoc
+       cp pretty $(HOME)/bin/pretty
        cp untab $(HOME)/bin/untab
 
 clean:
        rm -f pretty untab godoc *.6 *.a 6.out *~
 
-godoc.6:       docprinter.6 compilation.6 comment.6
-
-pretty.6:       platform.6 astprinter.6 compilation.6
-
-compilation.6:  platform.6 typechecker.6
-
-symboltable.6:
-
-platform.6:     utils.6
-
-astprinter.6:   utils.6 symboltable.6
-
-docprinter.6:  astprinter.6
+godoc.6:       astprinter.6 comment.6 docprinter.6
 
-comment.6:
+pretty.6:       astprinter.6
 
 %.6:   %.go
        $(G) $(F) $<
index 70662e5f76cefadfa86b3b7c04bba11a0a37c59c..033cb1a3ac56ff26660386a7121c2b16107feaf7 100644 (file)
@@ -5,17 +5,12 @@
 package astPrinter
 
 import (
-       "container/vector";
        "flag";
        "fmt";
        "go/ast";
        "go/token";
        "io";
        "os";
-       "strings";
-       "tabwriter";
-       "unicode";
-       "utf8";
 )
 
 
@@ -56,16 +51,9 @@ func assert(pred bool) {
 }
 
 
-// TODO this should be an AST method
-func isExported(name *ast.Ident) bool {
-       ch, len := utf8.DecodeRuneInString(name.Value, 0);
-       return unicode.IsUpper(ch);
-}
-
-
 func hasExportedNames(names []*ast.Ident) bool {
        for i, name := range names {
-               if isExported(name) {
+               if name.IsExported() {
                        return true;
                }
        }
@@ -315,7 +303,7 @@ func (P *Printer) TaggedString(pos token.Position, tag, s, endtag string) {
        nlcount := 0;
        if P.full {
                for ; P.hasComment(pos); P.nextComments() {
-                       // we have a comment group that comes before the string
+                       // we have a comment that comes before the string
                        comment := P.comments[P.cindex];
                        ctext := string(comment.Text);  // TODO get rid of string conversion here
 
@@ -508,7 +496,7 @@ func (P *Printer) Idents(list []*ast.Ident, full bool) int {
                        P.separator = blank;
                        P.state = inside_list;
                }
-               if full || isExported(x) {
+               if full || x.IsExported() {
                        P.Expr(x);
                        n++;
                }
diff --git a/usr/gri/pretty/compilation.go b/usr/gri/pretty/compilation.go
deleted file mode 100644 (file)
index b03d6b3..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-// 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.
-
-package Compilation
-
-import (
-       "container/vector";
-       "fmt";
-       "go/ast";
-       "go/parser";
-       "go/scanner";
-       "go/token";
-       "os";
-       "platform";
-       "sort";
-       "typechecker";
-       "utf8";
-       "utils";
-)
-
-
-func assert(b bool) {
-       if !b {
-               panic("assertion failed");
-       }
-}
-
-
-type Flags struct {
-       Verbose bool;
-       Deps bool;
-       Columns bool;
-}
-
-
-type Error struct {
-       Pos token.Position;
-       Msg string;
-}
-
-
-type ErrorList []Error
-
-func (list ErrorList) Len() int { return len(list); }
-func (list ErrorList) Less(i, j int) bool { return list[i].Pos.Offset < list[j].Pos.Offset; }
-func (list ErrorList) Swap(i, j int) { list[i], list[j] = list[j], list[i]; }
-
-
-type errorHandler struct {
-       filename string;
-       columns bool;
-       errline int;
-       errors vector.Vector;
-}
-
-
-func (h *errorHandler) Init(filename string, columns bool) {
-       h.filename = filename;
-       h.columns = columns;
-       h.errors.Init(0);
-}
-
-
-func (h *errorHandler) Error(pos token.Position, msg string) {
-       // only report errors that are on a new line
-       // in the hope to avoid most follow-up errors
-       if pos.Line == h.errline {
-               return;
-       }
-
-       // report error
-       fmt.Printf("%s:%d:", h.filename, pos.Line);
-       if h.columns {
-               fmt.Printf("%d:", pos.Column);
-       }
-       fmt.Printf(" %s\n", msg);
-
-       // collect the error
-       h.errors.Push(Error{pos, msg});
-       h.errline = pos.Line;
-}
-
-
-func Compile(filename string, flags *Flags) (*ast.Program, ErrorList) {
-       src, os_err := os.Open(filename, os.O_RDONLY, 0);
-       defer src.Close();
-       if os_err != nil {
-               fmt.Printf("cannot open %s (%s)\n", filename, os_err.String());
-               return nil, nil;
-       }
-
-       var err errorHandler;
-       err.Init(filename, flags.Columns);
-
-       mode := parser.ParseComments;
-       if flags.Verbose {
-               mode |= parser.Trace;
-       }
-       prog, ok2 := parser.Parse(src, &err, mode);
-
-       if ok2 {
-               TypeChecker.CheckProgram(&err, prog);
-       }
-
-       // convert error list and sort it
-       errors := make(ErrorList, err.errors.Len());
-       for i := 0; i < err.errors.Len(); i++ {
-               errors[i] = err.errors.At(i).(Error);
-       }
-       sort.Sort(errors);
-
-       return prog, errors;
-}
-
-
-func fileExists(name string) bool {
-       dir, err := os.Stat(name);
-       return err == nil;
-}
-
-/*
-func printDep(localset map [string] bool, wset *vector.Vector, decl ast.Decl2) {
-       src := decl.Val.(*ast.BasicLit).Val;
-       src = src[1 : len(src) - 1];  // strip "'s
-
-       // ignore files when they are seen a 2nd time
-       dummy, found := localset[src];
-       if !found {
-               localset[src] = true;
-               if fileExists(src + ".go") {
-                       wset.Push(src);
-                       fmt.Printf(" %s.6", src);
-               } else if
-                       fileExists(Platform.GOROOT + "/pkg/" + src + ".6") ||
-                       fileExists(Platform.GOROOT + "/pkg/" + src + ".a") {
-
-               } else {
-                       // TODO should collect these and print later
-                       //print("missing file: ", src, "\n");
-               }
-       }
-}
-*/
-
-
-func addDeps(globalset map [string] bool, wset *vector.Vector, src_file string, flags *Flags) {
-       dummy, found := globalset[src_file];
-       if !found {
-               globalset[src_file] = true;
-
-               prog, errors := Compile(src_file, flags);
-               if errors == nil || len(errors) > 0 {
-                       return;
-               }
-
-               nimports := len(prog.Decls);
-               if nimports > 0 {
-                       fmt.Printf("%s.6:\t", src_file);
-
-                       localset := make(map [string] bool);
-                       for i := 0; i < nimports; i++ {
-                               decl := prog.Decls[i];
-                               panic();
-                               /*
-                               assert(decl.Tok == scanner.IMPORT);
-                               if decl.List == nil {
-                                       printDep(localset, wset, decl);
-                               } else {
-                                       for j := 0; j < decl.List.Len(); j++ {
-                                               printDep(localset, wset, decl.List.At(j).(*ast.Decl));
-                                       }
-                               }
-                               */
-                       }
-                       print("\n\n");
-               }
-       }
-}
-
-
-func ComputeDeps(src_file string, flags *Flags) {
-       panic("dependency printing currently disabled");
-       globalset := make(map [string] bool);
-       wset := vector.New(0);
-       wset.Push(Utils.TrimExt(src_file, ".go"));
-       for wset.Len() > 0 {
-               addDeps(globalset, wset, wset.Pop().(string), flags);
-       }
-}
index 9f053e4d4926d2f55745280339d60dcaea30a20c..87b973e275796046e41ac0cf3873504c59783ed9 100644 (file)
@@ -16,10 +16,6 @@ import (
        "regexp";
        "sort";
        "strings";
-       "unicode";
-       "utf8";
-
-       "astprinter";
 )
 
 
index 300081ec64cb4b14e0b9101367253db0a4181644..3f91d6510ebf94a635a1ef9bb9e849fceae328e7 100644 (file)
@@ -53,36 +53,30 @@ import (
 )
 
 
-// TODO
-// - uniform use of path, filename, dirname, pakname, etc.
-// - fix weirdness with double-/'s in paths
-// - split http service into its own source file
-
 // TODO: tell flag package about usage string
 const usageString =
        "usage: godoc package [name ...]\n"
        "       godoc -http=:6060\n"
 
-var (
-       goroot string;
+const Pkg = "/pkg/"    // name for auto-generated package documentation tree
 
+
+var (
        verbose = flag.Bool("v", false, "verbose mode");
 
-       // server control
-       httpaddr = flag.String("http", "", "HTTP service address (e.g., ':6060')");
+       // file system roots
+       goroot string;
+       pkgroot = flag.String("pkgroot", "src/lib", "root package source directory (if unrooted, relative to goroot)");
 
        // layout control
        tabwidth = flag.Int("tabwidth", 4, "tab width");
        usetabs = flag.Bool("tabs", false, "align with tabs instead of spaces");
-
        html = flag.Bool("html", false, "print HTML in command-line mode");
 
-       pkgroot = flag.String("pkgroot", "src/lib", "root package source directory (if unrooted, relative to goroot)");
+       // server control
+       httpaddr = flag.String("http", "", "HTTP service address (e.g., ':6060')");
 )
 
-const (
-       Pkg = "/pkg/"   // name for auto-generated package documentation tree
-)
 
 func init() {
        var err os.Error;
@@ -140,13 +134,16 @@ type rawError struct {
        msg string;
 }
 
+
 type rawErrorVector struct {
        vector.Vector;
 }
 
+
 func (v *rawErrorVector) At(i int) rawError { return v.Vector.At(i).(rawError) }
 func (v *rawErrorVector) Less(i, j int) bool { return v.At(i).pos.Offset < v.At(j).pos.Offset; }
 
+
 func (v *rawErrorVector) Error(pos token.Position, msg string) {
        // only collect errors that are on a new line
        // in the hope to avoid most follow-up errors
@@ -167,17 +164,20 @@ type parseError struct {
        msg string;     // error message
 }
 
+
 // All the errors in the parsed file, plus surrounding source code.
 // Each error has a slice giving the source text preceding it
 // (starting where the last error occurred).  The final element in list[]
 // has msg = "", to give the remainder of the source code.
 // This data structure is handed to the templates parseerror.txt and parseerror.html.
+//
 type parseErrors struct {
        filename string;        // path to file
        list []parseError;      // the errors
        src []byte;     // the file's entire source code
 }
 
+
 // Parses a file (path) and returns the corresponding AST and
 // a sorted list (by file position) of errors, if any.
 //
@@ -425,12 +425,15 @@ func serveFile(c *http.Conn, req *http.Request) {
 
        case req.Url.Path == "/doc/root.html":
                // hide landing page from its real name
+               // TODO why - there is no reason for this (remove eventually)
                http.NotFound(c, req);
 
        case pathutil.Ext(req.Url.Path) == ".go":
-               serveGoSource(c, req.Url.Path[1:len(req.Url.Path)]);
+               serveGoSource(c, req.Url.Path[1 : len(req.Url.Path)]);  // strip leading '/' from name
 
        default:
+               // TODO not good enough - don't want to download files
+               // want to see them
                fileServer.ServeHTTP(c, req);
        }
 }
@@ -611,13 +614,13 @@ func servePackageList(c *http.Conn, info *pakInfo) {
 
 // Return package or packages named by name.
 // Name is either an import string or a directory,
-// like you'd see in $GOROOT/pkg/ once the 6g
-// tools can handle a hierarchy there.
+// like you'd see in $GOROOT/pkg/.
 //
 // Examples:
 //     "math"  - single package made up of directory
 //     "container"     - directory listing
 //     "container/vector"      - single package in container directory
+//
 func findPackages(name string) *pakInfo {
        info := new(pakInfo);
 
@@ -733,6 +736,7 @@ func main() {
                        log.Stderrf("Go Documentation Server\n");
                        log.Stderrf("address = %s\n", *httpaddr);
                        log.Stderrf("goroot = %s\n", goroot);
+                       log.Stderrf("pkgroot = %s\n", *pkgroot);
                        handler = LoggingHandler(handler);
                }
 
index 5e3cbc40bdf618b40b3a4476485923032e1c936a..f9fd763739f168e5d588233c8ebb3df00ee06c24 100644 (file)
        {.end}
 {.end}
 {.section Types}
-       <hr />
        {.repeated section @}
+               <hr />
                <h2>type {.section Type}{Name|html}{.end}</h2>
-               {Doc}
-               <p><code>{Decl|html}</code></p>
+               {Doc|html-comment}
+               <p><pre>{Decl|html}</pre></p>
                {.repeated section Factories}
                        <h3>func {Name|html}</h3>
                        <p><code>{Decl|html}</code></p>
diff --git a/usr/gri/pretty/platform.go b/usr/gri/pretty/platform.go
deleted file mode 100644 (file)
index cbd4678..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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.
-
-package Platform
-
-import IO "io"
-import OS "os"
-import Utils "utils"
-
-
-// ----------------------------------------------------------------------------
-// Environment
-
-var
-       GOARCH,
-       GOOS,
-       GOROOT,
-       USER string;
-
-func init() {
-       var e OS.Error;
-
-       GOARCH, e = OS.Getenv("GOARCH");
-       GOOS, e = OS.Getenv("GOOS");
-       GOROOT, e = OS.Getenv("GOROOT");
-       USER, e = OS.Getenv("USER");
-}
-
-
-// ----------------------------------------------------------------------------
-// I/O
-
-const (
-       MAGIC_obj_file = "@gri-go.7@v0";  // make it clear that it cannot be a source file
-       Src_file_ext = ".go";
-       Obj_file_ext = ".7";
-)
-
-func readfile(filename string) ([]byte, OS.Error) {
-       f, err := OS.Open(filename, OS.O_RDONLY, 0);
-       if err != nil {
-               return []byte{}, err;
-       }
-       var buf [1<<20]byte;
-       n, err1 := IO.FullRead(f, &buf);
-       f.Close();
-       if err1 == IO.ErrEOF {
-               err1 = nil;
-       }
-       return buf[0:n], err1;
-}
-
-func writefile(name, data string) OS.Error {
-       fd, err := OS.Open(name, OS.O_WRONLY, 0);
-       if err != nil {
-               return err;
-       }
-       n, err1 := IO.WriteString(fd, data);
-       fd.Close();
-       return err1;
-}
-
-func ReadObjectFile(filename string) ([]byte, bool) {
-       data, err := readfile(filename + Obj_file_ext);
-       magic := MAGIC_obj_file;  // TODO remove once len(constant) works
-       if err == nil && len(data) >= len(magic) && string(data[0 : len(magic)]) == magic {
-               return data, true;
-       }
-       return []byte{}, false;
-}
-
-
-func ReadSourceFile(name string) ([]byte, bool) {
-       name = Utils.TrimExt(name, Src_file_ext) + Src_file_ext;
-       data, err := readfile(name);
-       return data, err == nil;
-}
-
-
-func WriteObjectFile(name string, data string) bool {
-       name = Utils.TrimExt(Utils.BaseName(name), Src_file_ext) + Obj_file_ext;
-       return writefile(name, data) != nil;
-}
index 2db790d939715a4a8405ec51234d72da7e1e3c89..c342b72c29ea94e40a2d96e68def16bccd4ee98e 100644 (file)
@@ -5,31 +5,37 @@
 package main
 
 import (
-       "astprinter";
-       "compilation";
        "flag";
+       "fmt";
        "go/ast";
+       "go/parser";
+       "go/token";
+       "io";
+       "log";
        "os";
-       "platform";
        "tabwriter";
+
+       "astprinter";
 )
 
 
 var (
-       flags Compilation.Flags;
+       columnsDefault bool;
+
+       // operation modes
+       columns = flag.Bool("columns", columnsDefault, "report column no. in error messages");
        silent = flag.Bool("s", false, "silent mode: no pretty print output");
+       verbose = flag.Bool("v", false, "verbose mode: trace parsing");
 
        // layout control
-       html = flag.Bool("html", false, "generate html");
-       tabwidth = flag.Int("pretty_tabwidth", 4, "tab width");
-       usetabs = flag.Bool("pretty_usetabs", false, "align with tabs instead of blanks");
+       tabwidth = flag.Int("tabwidth", 4, "tab width");
+       usetabs = flag.Bool("usetabs", false, "align with tabs instead of blanks");
 )
 
 
 func init() {
-       flag.BoolVar(&flags.Verbose, "v", false, "verbose mode: trace parsing");
-       flag.BoolVar(&flags.Deps, "d", false, "print dependency information only");
-       flag.BoolVar(&flags.Columns, "columns", Platform.USER == "gri", "print column info in error messages");
+       user, err := os.Getenv("USER");
+       columnsDefault = user == "gri";
 }
 
 
@@ -40,47 +46,90 @@ func usage() {
 }
 
 
-func print(prog *ast.Program) {
-       // initialize tabwriter for nicely aligned output
+// TODO(gri) use library function for this once it exists
+func readFile(filename string) ([]byte, os.Error) {
+       f, err := os.Open(filename, os.O_RDONLY, 0);
+       if err != nil {
+               return nil, err;
+       }
+       defer f.Close();
+       var b io.ByteBuffer;
+       if n, err := io.Copy(f, &b); err != nil {
+               return nil, err;
+       }
+       return b.Data(), nil;
+}
+
+
+// TODO(gri) move this function into tabwriter.go? (also used in godoc)
+func makeTabwriter(writer io.Write) *tabwriter.Writer {
        padchar := byte(' ');
        if *usetabs {
                padchar = '\t';
        }
-       writer := tabwriter.NewWriter(os.Stdout, *tabwidth, 1, padchar, tabwriter.FilterHTML);
+       return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, tabwriter.FilterHTML);
+}
+
 
-       // initialize printer
-       var printer astPrinter.Printer;
-       printer.Init(writer, nil, prog.Comments, *html);
+// TODO(gri) move this into parser as default handler
+type ErrorHandler struct {
+       filename string;
+       lastline int;
+       columns bool;
+}
 
-       printer.DoProgram(prog);
 
-       // flush any pending output
-       writer.Flush();
+func (h *ErrorHandler) Error(pos token.Position, msg string) {
+       // only report errors that are on a new line
+       // in the hope to avoid most follow-up errors
+       if pos.Line == h.lastline {
+               return;
+       }
+
+       // report error
+       fmt.Printf("%s:%d:", h.filename, pos.Line);
+       if h.columns {
+               fmt.Printf("%d:", pos.Column);
+       }
+       fmt.Printf(" %s\n", msg);
 }
 
 
 func main() {
+       // handle flags
        flag.Parse();
-
        if flag.NFlag() == 0 && flag.NArg() == 0 {
                usage();
        }
 
+       // determine parsing mode
+       mode := parser.ParseComments;
+       if *verbose {
+               mode |= parser.Trace;
+       }
+
        // process files
        for i := 0; i < flag.NArg(); i++ {
-               src_file := flag.Arg(i);
-
-               if flags.Deps {
-                       Compilation.ComputeDeps(src_file, &flags);
-
-               } else {
-                       prog, errors := Compilation.Compile(src_file, &flags);
-                       if errors == nil || len(errors) > 0 {
-                               sys.Exit(1);
-                       }
-                       if !*silent {
-                               print(prog);
-                       }
+               filename := flag.Arg(i);
+
+               src, err := readFile(filename);
+               if err != nil {
+                       log.Stderrf("ReadFile %s: %v", filename, err);
+                       continue;
+               }
+
+               prog, ok := parser.Parse(src, &ErrorHandler{filename, 0, false}, mode);
+               if !ok {
+                       log.Stderr("Parse %s: syntax errors", filename);
+                       continue;
+               }
+
+               if !*silent {
+                       var printer astPrinter.Printer;
+                       writer := makeTabwriter(os.Stdout);
+                       printer.Init(writer, nil, nil /*prog.Comments*/, false);
+                       printer.DoProgram(prog);
+                       writer.Flush();
                }
        }
 }
index a3de38b1b1daecd69df6e83d290bcc51a9796c70..783d72d9c31c340ad65890fefdea29c41f0e2ffa 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 import (
-       "vector";  // not needed
+       "container/vector";  // not needed
        "utf8";  // not needed
        Fmt "fmt"
 )
diff --git a/usr/gri/pretty/typechecker.go b/usr/gri/pretty/typechecker.go
deleted file mode 100644 (file)
index 4dde63b..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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.
-
-package TypeChecker
-
-import (
-       "go/ast";
-       "go/scanner";
-       "go/token";
-)
-
-
-type state struct {
-       // setup
-       err scanner.ErrorHandler;
-}
-
-
-func (s *state) Init(err scanner.ErrorHandler) {
-       s.err = err;
-}
-
-
-// ----------------------------------------------------------------------------
-// Support
-
-func unimplemented() {
-       panic("unimplemented");
-}
-
-
-func unreachable() {
-       panic("unreachable");
-}
-
-
-func assert(pred bool) {
-       if !pred {
-               panic("assertion failed");
-       }
-}
-
-
-func (s *state) Error(pos token.Position, msg string) {
-       s.err.Error(pos, msg);
-}
-
-
-// ----------------------------------------------------------------------------
-
-func (s *state) CheckType() {
-}
-
-
-/*
-func (s *state) CheckDeclaration(d *AST.Decl) {
-       if d.Tok != token.FUNC && d.List != nil {
-               // group of parenthesized declarations
-               for i := 0; i < d.List.Len(); i++ {
-                       s.CheckDeclaration(d.List.At(i).(*AST.Decl))
-               }
-
-       } else {
-               // single declaration
-               switch d.Tok {
-               case token.IMPORT:
-               case token.CONST:
-               case token.VAR:
-               case token.TYPE:
-               case token.FUNC:
-               default:
-                       unreachable();
-               }
-       }
-}
-*/
-
-
-func (s *state) CheckProgram(p *ast.Program) {
-       for i := 0; i < len(p.Decls); i++ {
-               //s.CheckDeclaration(p.Decls[i].(*AST.Decl));
-       }
-}
-
-
-// ----------------------------------------------------------------------------
-
-func CheckProgram(err scanner.ErrorHandler, p *ast.Program) {
-       var s state;
-       s.Init(err);
-       s.CheckProgram(p);
-}
diff --git a/usr/gri/pretty/utils.go b/usr/gri/pretty/utils.go
deleted file mode 100644 (file)
index baacc75..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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.
-
-package Utils
-
-
-func BaseName(s string) string {
-       // TODO this is not correct for non-ASCII strings!
-       i := len(s) - 1;
-       for i >= 0 && s[i] != '/' {
-               if s[i] > 128 {
-                       panic("non-ASCII string");
-               }
-               i--;
-       }
-       return s[i + 1 : len(s)];
-}
-
-
-func cleanPath(s string) string {
-       for i := 0; i < len(s); i++ {
-               if s[i] == '/' {
-                       i++;
-                       j := i;
-                       for j < len(s) && s[j] == '/' {
-                               j++;
-                       }
-                       if j > i {  // more then one '/'
-                               return s[0 : i] + cleanPath(s[j : len(s)]);
-                       }
-               }
-       }
-       return s;
-}
-
-
-// Reduce sequences of multiple '/'s into a single '/' and
-// strip any trailing '/' (may result in the empty string).
-func SanitizePath(s string) string {
-       s = cleanPath(s);
-       if s[len(s)-1] == '/' {  // strip trailing '/'
-               s = s[0 : len(s)-1];
-       }
-       return s;
-}
-
-
-func Contains(s, sub string, pos int) bool {
-       end := pos + len(sub);
-       return pos >= 0 && end <= len(s) && s[pos : end] == sub;
-}
-
-
-func TrimExt(s, ext string) string {
-       i := len(s) - len(ext);
-       if i >= 0 && s[i : len(s)] == ext {
-               s = s[0 : i];
-       }
-       return s;
-}
-
-
-func IntToString(x, base int) string {
-       x0 := x;
-       if x < 0 {
-               x = -x;
-               if x < 0 {
-                       panic("smallest int not handled");
-               }
-       } else if x == 0 {
-               return "0";
-       }
-
-       // x > 0
-       hex := "0123456789ABCDEF";
-       var buf [32] byte;
-       i := len(buf);
-       for x > 0 {
-               i--;
-               buf[i] = hex[x % base];
-               x /= base;
-       }
-
-       if x0 < 0 {
-               i--;
-               buf[i] = '-';
-       }
-
-       return string(buf[i : len(buf)]);
-}