Commit 5a1d3323 authored by Robert Griesemer's avatar Robert Griesemer

1) Change default gofmt default settings for

                  parsing and printing to new syntax.

                  Use -oldparser to parse the old syntax,
                  use -oldprinter to print the old syntax.

               2) Change default gofmt formatting settings
                  to use tabs for indentation only and to use
                  spaces for alignment. This will make the code
                  alignment insensitive to an editor's tabwidth.

                  Use -spaces=false to use tabs for alignment.

               3) Manually changed src/exp/parser/parser_test.go
                  so that it doesn't try to parse the parser's
                  source files using the old syntax (they have
                  new syntax now).

               4) gofmt -w src misc test/bench

	       1st set of files.

R=rsc
CC=agl, golang-dev, iant, ken2, r
https://golang.org/cl/180047
parent 34356e9a
...@@ -10,33 +10,33 @@ ...@@ -10,33 +10,33 @@
package main package main
import ( import (
big "gmp"; big "gmp"
"runtime"; "runtime"
) )
func fibber(c chan *big.Int, out chan string, n int64) { func fibber(c chan *big.Int, out chan string, n int64) {
// Keep the fibbers in dedicated operating system // Keep the fibbers in dedicated operating system
// threads, so that this program tests coordination // threads, so that this program tests coordination
// between pthreads and not just goroutines. // between pthreads and not just goroutines.
runtime.LockOSThread(); runtime.LockOSThread()
i := big.NewInt(n); i := big.NewInt(n)
if n == 0 { if n == 0 {
c <- i c <- i
} }
for { for {
j := <-c; j := <-c
out <- j.String(); out <- j.String()
i.Add(i, j); i.Add(i, j)
c <- i; c <- i
} }
} }
func main() { func main() {
c := make(chan *big.Int); c := make(chan *big.Int)
out := make(chan string); out := make(chan string)
go fibber(c, out, 0); go fibber(c, out, 0)
go fibber(c, out, 1); go fibber(c, out, 1)
for i := 0; i < 200; i++ { for i := 0; i < 200; i++ {
println(<-out) println(<-out)
} }
......
...@@ -104,8 +104,8 @@ package gmp ...@@ -104,8 +104,8 @@ package gmp
import "C" import "C"
import ( import (
"os"; "os"
"unsafe"; "unsafe"
) )
/* /*
...@@ -115,12 +115,12 @@ import ( ...@@ -115,12 +115,12 @@ import (
// An Int represents a signed multi-precision integer. // An Int represents a signed multi-precision integer.
// The zero value for an Int represents the value 0. // The zero value for an Int represents the value 0.
type Int struct { type Int struct {
i C.mpz_t; i C.mpz_t
init bool; init bool
} }
// NewInt returns a new Int initialized to x. // NewInt returns a new Int initialized to x.
func NewInt(x int64) *Int { return new(Int).SetInt64(x) } func NewInt(x int64) *Int { return new(Int).SetInt64(x) }
// Int promises that the zero value is a 0, but in gmp // Int promises that the zero value is a 0, but in gmp
// the zero value is a crash. To bridge the gap, the // the zero value is a crash. To bridge the gap, the
...@@ -132,65 +132,65 @@ func (z *Int) doinit() { ...@@ -132,65 +132,65 @@ func (z *Int) doinit() {
if z.init { if z.init {
return return
} }
z.init = true; z.init = true
C.mpz_init(&z.i[0]); C.mpz_init(&z.i[0])
} }
// Bytes returns z's representation as a big-endian byte array. // Bytes returns z's representation as a big-endian byte array.
func (z *Int) Bytes() []byte { func (z *Int) Bytes() []byte {
b := make([]byte, (z.Len()+7)/8); b := make([]byte, (z.Len()+7)/8)
n := C.size_t(len(b)); n := C.size_t(len(b))
C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0]); C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
return b[0:n]; return b[0:n]
} }
// Len returns the length of z in bits. 0 is considered to have length 1. // Len returns the length of z in bits. 0 is considered to have length 1.
func (z *Int) Len() int { func (z *Int) Len() int {
z.doinit(); z.doinit()
return int(C.mpz_sizeinbase(&z.i[0], 2)); return int(C.mpz_sizeinbase(&z.i[0], 2))
} }
// Set sets z = x and returns z. // Set sets z = x and returns z.
func (z *Int) Set(x *Int) *Int { func (z *Int) Set(x *Int) *Int {
z.doinit(); z.doinit()
C.mpz_set(&z.i[0], &x.i[0]); C.mpz_set(&z.i[0], &x.i[0])
return z; return z
} }
// SetBytes interprets b as the bytes of a big-endian integer // SetBytes interprets b as the bytes of a big-endian integer
// and sets z to that value. // and sets z to that value.
func (z *Int) SetBytes(b []byte) *Int { func (z *Int) SetBytes(b []byte) *Int {
z.doinit(); z.doinit()
if len(b) == 0 { if len(b) == 0 {
z.SetInt64(0) z.SetInt64(0)
} else { } else {
C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0])) C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
} }
return z; return z
} }
// SetInt64 sets z = x and returns z. // SetInt64 sets z = x and returns z.
func (z *Int) SetInt64(x int64) *Int { func (z *Int) SetInt64(x int64) *Int {
z.doinit(); z.doinit()
// TODO(rsc): more work on 32-bit platforms // TODO(rsc): more work on 32-bit platforms
C.mpz_set_si(&z.i[0], C.long(x)); C.mpz_set_si(&z.i[0], C.long(x))
return z; return z
} }
// SetString interprets s as a number in the given base // SetString interprets s as a number in the given base
// and sets z to that value. The base must be in the range [2,36]. // and sets z to that value. The base must be in the range [2,36].
// SetString returns an error if s cannot be parsed or the base is invalid. // SetString returns an error if s cannot be parsed or the base is invalid.
func (z *Int) SetString(s string, base int) os.Error { func (z *Int) SetString(s string, base int) os.Error {
z.doinit(); z.doinit()
if base < 2 || base > 36 { if base < 2 || base > 36 {
return os.EINVAL return os.EINVAL
} }
p := C.CString(s); p := C.CString(s)
defer C.free(unsafe.Pointer(p)); defer C.free(unsafe.Pointer(p))
if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 { if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
return os.EINVAL return os.EINVAL
} }
return z; return z
} }
// String returns the decimal representation of z. // String returns the decimal representation of z.
...@@ -198,18 +198,18 @@ func (z *Int) String() string { ...@@ -198,18 +198,18 @@ func (z *Int) String() string {
if z == nil { if z == nil {
return "nil" return "nil"
} }
z.doinit(); z.doinit()
p := C.mpz_get_str(nil, 10, &z.i[0]); p := C.mpz_get_str(nil, 10, &z.i[0])
s := C.GoString(p); s := C.GoString(p)
C.free(unsafe.Pointer(p)); C.free(unsafe.Pointer(p))
return s; return s
} }
func (z *Int) destroy() { func (z *Int) destroy() {
if z.init { if z.init {
C.mpz_clear(&z.i[0]) C.mpz_clear(&z.i[0])
} }
z.init = false; z.init = false
} }
...@@ -219,103 +219,103 @@ func (z *Int) destroy() { ...@@ -219,103 +219,103 @@ func (z *Int) destroy() {
// Add sets z = x + y and returns z. // Add sets z = x + y and returns z.
func (z *Int) Add(x, y *Int) *Int { func (z *Int) Add(x, y *Int) *Int {
x.doinit(); x.doinit()
y.doinit(); y.doinit()
z.doinit(); z.doinit()
C.mpz_add(&z.i[0], &x.i[0], &y.i[0]); C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
return z; return z
} }
// Sub sets z = x - y and returns z. // Sub sets z = x - y and returns z.
func (z *Int) Sub(x, y *Int) *Int { func (z *Int) Sub(x, y *Int) *Int {
x.doinit(); x.doinit()
y.doinit(); y.doinit()
z.doinit(); z.doinit()
C.mpz_sub(&z.i[0], &x.i[0], &y.i[0]); C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
return z; return z
} }
// Mul sets z = x * y and returns z. // Mul sets z = x * y and returns z.
func (z *Int) Mul(x, y *Int) *Int { func (z *Int) Mul(x, y *Int) *Int {
x.doinit(); x.doinit()
y.doinit(); y.doinit()
z.doinit(); z.doinit()
C.mpz_mul(&z.i[0], &x.i[0], &y.i[0]); C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
return z; return z
} }
// Div sets z = x / y, rounding toward zero, and returns z. // Div sets z = x / y, rounding toward zero, and returns z.
func (z *Int) Div(x, y *Int) *Int { func (z *Int) Div(x, y *Int) *Int {
x.doinit(); x.doinit()
y.doinit(); y.doinit()
z.doinit(); z.doinit()
C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0]); C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
return z; return z
} }
// Mod sets z = x % y and returns z. // Mod sets z = x % y and returns z.
// Like the result of the Go % operator, z has the same sign as x. // Like the result of the Go % operator, z has the same sign as x.
func (z *Int) Mod(x, y *Int) *Int { func (z *Int) Mod(x, y *Int) *Int {
x.doinit(); x.doinit()
y.doinit(); y.doinit()
z.doinit(); z.doinit()
C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0]); C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
return z; return z
} }
// Lsh sets z = x << s and returns z. // Lsh sets z = x << s and returns z.
func (z *Int) Lsh(x *Int, s uint) *Int { func (z *Int) Lsh(x *Int, s uint) *Int {
x.doinit(); x.doinit()
z.doinit(); z.doinit()
C.mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s)); C.mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
return z; return z
} }
// Rsh sets z = x >> s and returns z. // Rsh sets z = x >> s and returns z.
func (z *Int) Rsh(x *Int, s uint) *Int { func (z *Int) Rsh(x *Int, s uint) *Int {
x.doinit(); x.doinit()
z.doinit(); z.doinit()
C.mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s)); C.mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
return z; return z
} }
// Exp sets z = x^y % m and returns z. // Exp sets z = x^y % m and returns z.
// If m == nil, Exp sets z = x^y. // If m == nil, Exp sets z = x^y.
func (z *Int) Exp(x, y, m *Int) *Int { func (z *Int) Exp(x, y, m *Int) *Int {
m.doinit(); m.doinit()
x.doinit(); x.doinit()
y.doinit(); y.doinit()
z.doinit(); z.doinit()
if m == nil { if m == nil {
C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0])) C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
} else { } else {
C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0]) C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
} }
return z; return z
} }
func (z *Int) Int64() int64 { func (z *Int) Int64() int64 {
if !z.init { if !z.init {
return 0 return 0
} }
return int64(C.mpz_get_si(&z.i[0])); return int64(C.mpz_get_si(&z.i[0]))
} }
// Neg sets z = -x and returns z. // Neg sets z = -x and returns z.
func (z *Int) Neg(x *Int) *Int { func (z *Int) Neg(x *Int) *Int {
x.doinit(); x.doinit()
z.doinit(); z.doinit()
C.mpz_neg(&z.i[0], &x.i[0]); C.mpz_neg(&z.i[0], &x.i[0])
return z; return z
} }
// Abs sets z to the absolute value of x and returns z. // Abs sets z to the absolute value of x and returns z.
func (z *Int) Abs(x *Int) *Int { func (z *Int) Abs(x *Int) *Int {
x.doinit(); x.doinit()
z.doinit(); z.doinit()
C.mpz_abs(&z.i[0], &x.i[0]); C.mpz_abs(&z.i[0], &x.i[0])
return z; return z
} }
...@@ -330,24 +330,24 @@ func (z *Int) Abs(x *Int) *Int { ...@@ -330,24 +330,24 @@ func (z *Int) Abs(x *Int) *Int {
// +1 if x > y // +1 if x > y
// //
func CmpInt(x, y *Int) int { func CmpInt(x, y *Int) int {
x.doinit(); x.doinit()
y.doinit(); y.doinit()
switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); { switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
case cmp < 0: case cmp < 0:
return -1 return -1
case cmp == 0: case cmp == 0:
return 0 return 0
} }
return +1; return +1
} }
// DivModInt sets q = x / y and r = x % y. // DivModInt sets q = x / y and r = x % y.
func DivModInt(q, r, x, y *Int) { func DivModInt(q, r, x, y *Int) {
q.doinit(); q.doinit()
r.doinit(); r.doinit()
x.doinit(); x.doinit()
y.doinit(); y.doinit()
C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0]); C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0])
} }
// GcdInt sets d to the greatest common divisor of a and b, // GcdInt sets d to the greatest common divisor of a and b,
...@@ -355,18 +355,18 @@ func DivModInt(q, r, x, y *Int) { ...@@ -355,18 +355,18 @@ func DivModInt(q, r, x, y *Int) {
// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y. // If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
// If either a or b is not positive, GcdInt sets d = x = y = 0. // If either a or b is not positive, GcdInt sets d = x = y = 0.
func GcdInt(d, x, y, a, b *Int) { func GcdInt(d, x, y, a, b *Int) {
d.doinit(); d.doinit()
x.doinit(); x.doinit()
y.doinit(); y.doinit()
a.doinit(); a.doinit()
b.doinit(); b.doinit()
C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0]); C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
} }
// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime. // ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
// If it returns true, z is prime with probability 1 - 1/4^n. // If it returns true, z is prime with probability 1 - 1/4^n.
// If it returns false, z is not prime. // If it returns false, z is not prime.
func (z *Int) ProbablyPrime(n int) bool { func (z *Int) ProbablyPrime(n int) bool {
z.doinit(); z.doinit()
return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0; return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
} }
...@@ -38,67 +38,67 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -38,67 +38,67 @@ POSSIBILITY OF SUCH DAMAGE.
package main package main
import ( import (
big "gmp"; big "gmp"
"fmt"; "fmt"
"runtime"; "runtime"
) )
var ( var (
tmp1 = big.NewInt(0); tmp1 = big.NewInt(0)
tmp2 = big.NewInt(0); tmp2 = big.NewInt(0)
numer = big.NewInt(1); numer = big.NewInt(1)
accum = big.NewInt(0); accum = big.NewInt(0)
denom = big.NewInt(1); denom = big.NewInt(1)
ten = big.NewInt(10); ten = big.NewInt(10)
) )
func extractDigit() int64 { func extractDigit() int64 {
if big.CmpInt(numer, accum) > 0 { if big.CmpInt(numer, accum) > 0 {
return -1 return -1
} }
tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum); tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum)
big.DivModInt(tmp1, tmp2, tmp1, denom); big.DivModInt(tmp1, tmp2, tmp1, denom)
tmp2.Add(tmp2, numer); tmp2.Add(tmp2, numer)
if big.CmpInt(tmp2, denom) >= 0 { if big.CmpInt(tmp2, denom) >= 0 {
return -1 return -1
} }
return tmp1.Int64(); return tmp1.Int64()
} }
func nextTerm(k int64) { func nextTerm(k int64) {
y2 := k*2 + 1; y2 := k*2 + 1
accum.Add(accum, tmp1.Lsh(numer, 1)); accum.Add(accum, tmp1.Lsh(numer, 1))
accum.Mul(accum, tmp1.SetInt64(y2)); accum.Mul(accum, tmp1.SetInt64(y2))
numer.Mul(numer, tmp1.SetInt64(k)); numer.Mul(numer, tmp1.SetInt64(k))
denom.Mul(denom, tmp1.SetInt64(y2)); denom.Mul(denom, tmp1.SetInt64(y2))
} }
func eliminateDigit(d int64) { func eliminateDigit(d int64) {
accum.Sub(accum, tmp1.Mul(denom, tmp1.SetInt64(d))); accum.Sub(accum, tmp1.Mul(denom, tmp1.SetInt64(d)))
accum.Mul(accum, ten); accum.Mul(accum, ten)
numer.Mul(numer, ten); numer.Mul(numer, ten)
} }
func main() { func main() {
i := 0; i := 0
k := int64(0); k := int64(0)
for { for {
d := int64(-1); d := int64(-1)
for d < 0 { for d < 0 {
k++; k++
nextTerm(k); nextTerm(k)
d = extractDigit(); d = extractDigit()
} }
eliminateDigit(d); eliminateDigit(d)
fmt.Printf("%c", d+'0'); fmt.Printf("%c", d+'0')
if i++; i%50 == 0 { if i++; i%50 == 0 {
fmt.Printf("\n"); fmt.Printf("\n")
if i >= 1000 { if i >= 1000 {
break break
} }
} }
} }
fmt.Printf("\n%d calls; bit sizes: %d %d %d\n", runtime.Cgocalls(), numer.Len(), accum.Len(), denom.Len()); fmt.Printf("\n%d calls; bit sizes: %d %d %d\n", runtime.Cgocalls(), numer.Len(), accum.Len(), denom.Len())
} }
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
package main package main
import ( import (
"runtime"; "runtime"
"stdio"; "stdio"
"strconv"; "strconv"
) )
const N = 10 const N = 10
...@@ -19,25 +19,25 @@ func link(left chan<- int, right <-chan int) { ...@@ -19,25 +19,25 @@ func link(left chan<- int, right <-chan int) {
// Keep the links in dedicated operating system // Keep the links in dedicated operating system
// threads, so that this program tests coordination // threads, so that this program tests coordination
// between pthreads and not just goroutines. // between pthreads and not just goroutines.
runtime.LockOSThread(); runtime.LockOSThread()
for { for {
v := <-right; v := <-right
stdio.Puts(strconv.Itoa(v)); stdio.Puts(strconv.Itoa(v))
left <- 1+v; left <- 1+v
} }
} }
func main() { func main() {
leftmost := make(chan int); leftmost := make(chan int)
var left chan int; var left chan int
right := leftmost; right := leftmost
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
left, right = right, make(chan int); left, right = right, make(chan int)
go link(left, right); go link(left, right)
} }
for i := 0; i < R; i++ { for i := 0; i < R; i++ {
right <- 0; right <- 0
x := <-leftmost; x := <-leftmost
stdio.Puts(strconv.Itoa(x)); stdio.Puts(strconv.Itoa(x))
} }
} }
...@@ -10,38 +10,38 @@ ...@@ -10,38 +10,38 @@
package main package main
import ( import (
"runtime"; "runtime"
"stdio"; "stdio"
"strconv"; "strconv"
) )
func fibber(c, out chan int64, i int64) { func fibber(c, out chan int64, i int64) {
// Keep the fibbers in dedicated operating system // Keep the fibbers in dedicated operating system
// threads, so that this program tests coordination // threads, so that this program tests coordination
// between pthreads and not just goroutines. // between pthreads and not just goroutines.
runtime.LockOSThread(); runtime.LockOSThread()
if i == 0 { if i == 0 {
c <- i c <- i
} }
for { for {
j := <-c; j := <-c
stdio.Puts(strconv.Itoa64(j)); stdio.Puts(strconv.Itoa64(j))
out <- j; out <- j
<-out; <-out
i += j; i += j
c <- i; c <- i
} }
} }
func main() { func main() {
c := make(chan int64); c := make(chan int64)
out := make(chan int64); out := make(chan int64)
go fibber(c, out, 0); go fibber(c, out, 0)
go fibber(c, out, 1); go fibber(c, out, 1)
<-out; <-out
for i := 0; i < 90; i++ { for i := 0; i < 90; i++ {
out <- 1; out <- 1
<-out; <-out
} }
} }
...@@ -35,8 +35,8 @@ func (f *File) WriteString(s string) { ...@@ -35,8 +35,8 @@ func (f *File) WriteString(s string) {
*/ */
func Puts(s string) { func Puts(s string) {
p := C.CString(s); p := C.CString(s)
C.puts(p); C.puts(p)
C.free(unsafe.Pointer(p)); C.free(unsafe.Pointer(p))
C.fflushstdout(); C.fflushstdout()
} }
...@@ -7,57 +7,57 @@ ...@@ -7,57 +7,57 @@
package main package main
import ( import (
"fmt"; "fmt"
"go/ast"; "go/ast"
"go/doc"; "go/doc"
"go/parser"; "go/parser"
"go/scanner"; "go/scanner"
"os"; "os"
) )
// A Cref refers to an expression of the form C.xxx in the AST. // A Cref refers to an expression of the form C.xxx in the AST.
type Cref struct { type Cref struct {
Name string; Name string
Expr *ast.Expr; Expr *ast.Expr
Context string; // "type", "expr", or "call" Context string // "type", "expr", or "call"
TypeName bool; // whether xxx is a C type name TypeName bool // whether xxx is a C type name
Type *Type; // the type of xxx Type *Type // the type of xxx
FuncType *FuncType; FuncType *FuncType
} }
// A Prog collects information about a cgo program. // A Prog collects information about a cgo program.
type Prog struct { type Prog struct {
AST *ast.File; // parsed AST AST *ast.File // parsed AST
Preamble string; // C preamble (doc comment on import "C") Preamble string // C preamble (doc comment on import "C")
PackagePath string; PackagePath string
Package string; Package string
Crefs []*Cref; Crefs []*Cref
Typedef map[string]ast.Expr; Typedef map[string]ast.Expr
Vardef map[string]*Type; Vardef map[string]*Type
Funcdef map[string]*FuncType; Funcdef map[string]*FuncType
PtrSize int64; PtrSize int64
GccOptions []string; GccOptions []string
} }
// A Type collects information about a type in both the C and Go worlds. // A Type collects information about a type in both the C and Go worlds.
type Type struct { type Type struct {
Size int64; Size int64
Align int64; Align int64
C string; C string
Go ast.Expr; Go ast.Expr
} }
// A FuncType collects information about a function type in both the C and Go worlds. // A FuncType collects information about a function type in both the C and Go worlds.
type FuncType struct { type FuncType struct {
Params []*Type; Params []*Type
Result *Type; Result *Type
Go *ast.FuncType; Go *ast.FuncType
} }
func openProg(name string) *Prog { func openProg(name string) *Prog {
p := new(Prog); p := new(Prog)
var err os.Error; var err os.Error
p.AST, err = parser.ParsePkgFile("", name, parser.ParseComments); p.AST, err = parser.ParsePkgFile("", name, parser.ParseComments)
if err != nil { if err != nil {
if list, ok := err.(scanner.ErrorList); ok { if list, ok := err.(scanner.ErrorList); ok {
// If err is a scanner.ErrorList, its String will print just // If err is a scanner.ErrorList, its String will print just
...@@ -67,32 +67,32 @@ func openProg(name string) *Prog { ...@@ -67,32 +67,32 @@ func openProg(name string) *Prog {
for _, e := range list { for _, e := range list {
fmt.Fprintln(os.Stderr, e) fmt.Fprintln(os.Stderr, e)
} }
os.Exit(2); os.Exit(2)
} }
fatal("parsing %s: %s", name, err); fatal("parsing %s: %s", name, err)
} }
p.Package = p.AST.Name.Value; p.Package = p.AST.Name.Value
// Find the import "C" line and get any extra C preamble. // Find the import "C" line and get any extra C preamble.
// Delete the import "C" line along the way. // Delete the import "C" line along the way.
sawC := false; sawC := false
w := 0; w := 0
for _, decl := range p.AST.Decls { for _, decl := range p.AST.Decls {
d, ok := decl.(*ast.GenDecl); d, ok := decl.(*ast.GenDecl)
if !ok { if !ok {
p.AST.Decls[w] = decl; p.AST.Decls[w] = decl
w++; w++
continue; continue
} }
ws := 0; ws := 0
for _, spec := range d.Specs { for _, spec := range d.Specs {
s, ok := spec.(*ast.ImportSpec); s, ok := spec.(*ast.ImportSpec)
if !ok || len(s.Path) != 1 || string(s.Path[0].Value) != `"C"` { if !ok || len(s.Path) != 1 || string(s.Path[0].Value) != `"C"` {
d.Specs[ws] = spec; d.Specs[ws] = spec
ws++; ws++
continue; continue
} }
sawC = true; sawC = true
if s.Name != nil { if s.Name != nil {
error(s.Path[0].Pos(), `cannot rename import "C"`) error(s.Path[0].Pos(), `cannot rename import "C"`)
} }
...@@ -105,20 +105,20 @@ func openProg(name string) *Prog { ...@@ -105,20 +105,20 @@ func openProg(name string) *Prog {
if ws == 0 { if ws == 0 {
continue continue
} }
d.Specs = d.Specs[0:ws]; d.Specs = d.Specs[0:ws]
p.AST.Decls[w] = d; p.AST.Decls[w] = d
w++; w++
} }
p.AST.Decls = p.AST.Decls[0:w]; p.AST.Decls = p.AST.Decls[0:w]
if !sawC { if !sawC {
error(noPos, `cannot find import "C"`) error(noPos, `cannot find import "C"`)
} }
// Accumulate pointers to uses of C.x. // Accumulate pointers to uses of C.x.
p.Crefs = make([]*Cref, 0, 8); p.Crefs = make([]*Cref, 0, 8)
walk(p.AST, p, "prog"); walk(p.AST, p, "prog")
return p; return p
} }
func walk(x interface{}, p *Prog, context string) { func walk(x interface{}, p *Prog, context string) {
...@@ -131,29 +131,29 @@ func walk(x interface{}, p *Prog, context string) { ...@@ -131,29 +131,29 @@ func walk(x interface{}, p *Prog, context string) {
// so that we will be able to distinguish a "top-level C" // so that we will be able to distinguish a "top-level C"
// from a local C. // from a local C.
if l, ok := sel.X.(*ast.Ident); ok && l.Value == "C" { if l, ok := sel.X.(*ast.Ident); ok && l.Value == "C" {
i := len(p.Crefs); i := len(p.Crefs)
if i >= cap(p.Crefs) { if i >= cap(p.Crefs) {
new := make([]*Cref, 2*i); new := make([]*Cref, 2*i)
for j, v := range p.Crefs { for j, v := range p.Crefs {
new[j] = v new[j] = v
} }
p.Crefs = new; p.Crefs = new
} }
p.Crefs = p.Crefs[0 : i+1]; p.Crefs = p.Crefs[0 : i+1]
p.Crefs[i] = &Cref{ p.Crefs[i] = &Cref{
Name: sel.Sel.Value, Name: sel.Sel.Value,
Expr: n, Expr: n,
Context: context, Context: context,
}; }
break; break
} }
} }
walk(*n, p, context); walk(*n, p, context)
// everything else just recurs // everything else just recurs
default: default:
error(noPos, "unexpected type %T in walk", x); error(noPos, "unexpected type %T in walk", x)
panic(); panic()
case nil: case nil:
...@@ -166,54 +166,54 @@ func walk(x interface{}, p *Prog, context string) { ...@@ -166,54 +166,54 @@ func walk(x interface{}, p *Prog, context string) {
case *ast.BasicLit: case *ast.BasicLit:
case *ast.StringList: case *ast.StringList:
case *ast.FuncLit: case *ast.FuncLit:
walk(n.Type, p, "type"); walk(n.Type, p, "type")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.CompositeLit: case *ast.CompositeLit:
walk(&n.Type, p, "type"); walk(&n.Type, p, "type")
walk(n.Elts, p, "expr"); walk(n.Elts, p, "expr")
case *ast.ParenExpr: case *ast.ParenExpr:
walk(&n.X, p, context) walk(&n.X, p, context)
case *ast.SelectorExpr: case *ast.SelectorExpr:
walk(&n.X, p, "selector") walk(&n.X, p, "selector")
case *ast.IndexExpr: case *ast.IndexExpr:
walk(&n.X, p, "expr"); walk(&n.X, p, "expr")
walk(&n.Index, p, "expr"); walk(&n.Index, p, "expr")
case *ast.SliceExpr: case *ast.SliceExpr:
walk(&n.X, p, "expr"); walk(&n.X, p, "expr")
walk(&n.Index, p, "expr"); walk(&n.Index, p, "expr")
if n.End != nil { if n.End != nil {
walk(&n.End, p, "expr") walk(&n.End, p, "expr")
} }
case *ast.TypeAssertExpr: case *ast.TypeAssertExpr:
walk(&n.X, p, "expr"); walk(&n.X, p, "expr")
walk(&n.Type, p, "type"); walk(&n.Type, p, "type")
case *ast.CallExpr: case *ast.CallExpr:
walk(&n.Fun, p, "call"); walk(&n.Fun, p, "call")
walk(n.Args, p, "expr"); walk(n.Args, p, "expr")
case *ast.StarExpr: case *ast.StarExpr:
walk(&n.X, p, context) walk(&n.X, p, context)
case *ast.UnaryExpr: case *ast.UnaryExpr:
walk(&n.X, p, "expr") walk(&n.X, p, "expr")
case *ast.BinaryExpr: case *ast.BinaryExpr:
walk(&n.X, p, "expr"); walk(&n.X, p, "expr")
walk(&n.Y, p, "expr"); walk(&n.Y, p, "expr")
case *ast.KeyValueExpr: case *ast.KeyValueExpr:
walk(&n.Key, p, "expr"); walk(&n.Key, p, "expr")
walk(&n.Value, p, "expr"); walk(&n.Value, p, "expr")
case *ast.ArrayType: case *ast.ArrayType:
walk(&n.Len, p, "expr"); walk(&n.Len, p, "expr")
walk(&n.Elt, p, "type"); walk(&n.Elt, p, "type")
case *ast.StructType: case *ast.StructType:
walk(n.Fields, p, "field") walk(n.Fields, p, "field")
case *ast.FuncType: case *ast.FuncType:
walk(n.Params, p, "field"); walk(n.Params, p, "field")
walk(n.Results, p, "field"); walk(n.Results, p, "field")
case *ast.InterfaceType: case *ast.InterfaceType:
walk(n.Methods, p, "field") walk(n.Methods, p, "field")
case *ast.MapType: case *ast.MapType:
walk(&n.Key, p, "type"); walk(&n.Key, p, "type")
walk(&n.Value, p, "type"); walk(&n.Value, p, "type")
case *ast.ChanType: case *ast.ChanType:
walk(&n.Value, p, "type") walk(&n.Value, p, "type")
...@@ -228,8 +228,8 @@ func walk(x interface{}, p *Prog, context string) { ...@@ -228,8 +228,8 @@ func walk(x interface{}, p *Prog, context string) {
case *ast.IncDecStmt: case *ast.IncDecStmt:
walk(&n.X, p, "expr") walk(&n.X, p, "expr")
case *ast.AssignStmt: case *ast.AssignStmt:
walk(n.Lhs, p, "expr"); walk(n.Lhs, p, "expr")
walk(n.Rhs, p, "expr"); walk(n.Rhs, p, "expr")
case *ast.GoStmt: case *ast.GoStmt:
walk(n.Call, p, "expr") walk(n.Call, p, "expr")
case *ast.DeferStmt: case *ast.DeferStmt:
...@@ -240,45 +240,45 @@ func walk(x interface{}, p *Prog, context string) { ...@@ -240,45 +240,45 @@ func walk(x interface{}, p *Prog, context string) {
case *ast.BlockStmt: case *ast.BlockStmt:
walk(n.List, p, "stmt") walk(n.List, p, "stmt")
case *ast.IfStmt: case *ast.IfStmt:
walk(n.Init, p, "stmt"); walk(n.Init, p, "stmt")
walk(&n.Cond, p, "expr"); walk(&n.Cond, p, "expr")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
walk(n.Else, p, "stmt"); walk(n.Else, p, "stmt")
case *ast.CaseClause: case *ast.CaseClause:
walk(n.Values, p, "expr"); walk(n.Values, p, "expr")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.SwitchStmt: case *ast.SwitchStmt:
walk(n.Init, p, "stmt"); walk(n.Init, p, "stmt")
walk(&n.Tag, p, "expr"); walk(&n.Tag, p, "expr")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.TypeCaseClause: case *ast.TypeCaseClause:
walk(n.Types, p, "type"); walk(n.Types, p, "type")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.TypeSwitchStmt: case *ast.TypeSwitchStmt:
walk(n.Init, p, "stmt"); walk(n.Init, p, "stmt")
walk(n.Assign, p, "stmt"); walk(n.Assign, p, "stmt")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.CommClause: case *ast.CommClause:
walk(n.Lhs, p, "expr"); walk(n.Lhs, p, "expr")
walk(n.Rhs, p, "expr"); walk(n.Rhs, p, "expr")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.SelectStmt: case *ast.SelectStmt:
walk(n.Body, p, "stmt") walk(n.Body, p, "stmt")
case *ast.ForStmt: case *ast.ForStmt:
walk(n.Init, p, "stmt"); walk(n.Init, p, "stmt")
walk(&n.Cond, p, "expr"); walk(&n.Cond, p, "expr")
walk(n.Post, p, "stmt"); walk(n.Post, p, "stmt")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.RangeStmt: case *ast.RangeStmt:
walk(&n.Key, p, "expr"); walk(&n.Key, p, "expr")
walk(&n.Value, p, "expr"); walk(&n.Value, p, "expr")
walk(&n.X, p, "expr"); walk(&n.X, p, "expr")
walk(n.Body, p, "stmt"); walk(n.Body, p, "stmt")
case *ast.ImportSpec: case *ast.ImportSpec:
case *ast.ValueSpec: case *ast.ValueSpec:
walk(&n.Type, p, "type"); walk(&n.Type, p, "type")
walk(n.Values, p, "expr"); walk(n.Values, p, "expr")
case *ast.TypeSpec: case *ast.TypeSpec:
walk(&n.Type, p, "type") walk(&n.Type, p, "type")
...@@ -289,7 +289,7 @@ func walk(x interface{}, p *Prog, context string) { ...@@ -289,7 +289,7 @@ func walk(x interface{}, p *Prog, context string) {
if n.Recv != nil { if n.Recv != nil {
walk(n.Recv, p, "field") walk(n.Recv, p, "field")
} }
walk(n.Type, p, "type"); walk(n.Type, p, "type")
if n.Body != nil { if n.Body != nil {
walk(n.Body, p, "stmt") walk(n.Body, p, "stmt")
} }
......
This diff is collapsed.
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
package main package main
import ( import (
"fmt"; "fmt"
"go/ast"; "go/ast"
"os"; "os"
) )
func usage() { fmt.Fprint(os.Stderr, "usage: cgo [compiler options] file.go\n") } func usage() { fmt.Fprint(os.Stderr, "usage: cgo [compiler options] file.go\n") }
var ptrSizeMap = map[string]int64{ var ptrSizeMap = map[string]int64{
"386": 4, "386": 4,
...@@ -35,29 +35,29 @@ var expandName = map[string]string{ ...@@ -35,29 +35,29 @@ var expandName = map[string]string{
} }
func main() { func main() {
args := os.Args; args := os.Args
if len(args) < 2 { if len(args) < 2 {
usage(); usage()
os.Exit(2); os.Exit(2)
} }
gccOptions := args[1 : len(args)-1]; gccOptions := args[1 : len(args)-1]
input := args[len(args)-1]; input := args[len(args)-1]
arch := os.Getenv("GOARCH"); arch := os.Getenv("GOARCH")
if arch == "" { if arch == "" {
fatal("$GOARCH is not set") fatal("$GOARCH is not set")
} }
ptrSize, ok := ptrSizeMap[arch]; ptrSize, ok := ptrSizeMap[arch]
if !ok { if !ok {
fatal("unknown architecture %s", arch) fatal("unknown architecture %s", arch)
} }
// Clear locale variables so gcc emits English errors [sic]. // Clear locale variables so gcc emits English errors [sic].
os.Setenv("LANG", "en_US.UTF-8"); os.Setenv("LANG", "en_US.UTF-8")
os.Setenv("LC_ALL", "C"); os.Setenv("LC_ALL", "C")
os.Setenv("LC_CTYPE", "C"); os.Setenv("LC_CTYPE", "C")
p := openProg(input); p := openProg(input)
for _, cref := range p.Crefs { for _, cref := range p.Crefs {
// Convert C.ulong to C.unsigned long, etc. // Convert C.ulong to C.unsigned long, etc.
if expand, ok := expandName[cref.Name]; ok { if expand, ok := expandName[cref.Name]; ok {
...@@ -65,42 +65,42 @@ func main() { ...@@ -65,42 +65,42 @@ func main() {
} }
} }
p.PtrSize = ptrSize; p.PtrSize = ptrSize
p.Preamble = p.Preamble + "\n" + builtinProlog; p.Preamble = p.Preamble + "\n" + builtinProlog
p.GccOptions = gccOptions; p.GccOptions = gccOptions
p.loadDebugInfo(); p.loadDebugInfo()
p.Vardef = make(map[string]*Type); p.Vardef = make(map[string]*Type)
p.Funcdef = make(map[string]*FuncType); p.Funcdef = make(map[string]*FuncType)
for _, cref := range p.Crefs { for _, cref := range p.Crefs {
switch cref.Context { switch cref.Context {
case "call": case "call":
if !cref.TypeName { if !cref.TypeName {
// Is an actual function call. // Is an actual function call.
*cref.Expr = &ast.Ident{Value: "_C_" + cref.Name}; *cref.Expr = &ast.Ident{Value: "_C_" + cref.Name}
p.Funcdef[cref.Name] = cref.FuncType; p.Funcdef[cref.Name] = cref.FuncType
break; break
} }
*cref.Expr = cref.Type.Go; *cref.Expr = cref.Type.Go
case "expr": case "expr":
if cref.TypeName { if cref.TypeName {
error((*cref.Expr).Pos(), "type C.%s used as expression", cref.Name) error((*cref.Expr).Pos(), "type C.%s used as expression", cref.Name)
} }
// Reference to C variable. // Reference to C variable.
// We declare a pointer and arrange to have it filled in. // We declare a pointer and arrange to have it filled in.
*cref.Expr = &ast.StarExpr{X: &ast.Ident{Value: "_C_" + cref.Name}}; *cref.Expr = &ast.StarExpr{X: &ast.Ident{Value: "_C_" + cref.Name}}
p.Vardef[cref.Name] = cref.Type; p.Vardef[cref.Name] = cref.Type
case "type": case "type":
if !cref.TypeName { if !cref.TypeName {
error((*cref.Expr).Pos(), "expression C.%s used as type", cref.Name) error((*cref.Expr).Pos(), "expression C.%s used as type", cref.Name)
} }
*cref.Expr = cref.Type.Go; *cref.Expr = cref.Type.Go
} }
} }
if nerrors > 0 { if nerrors > 0 {
os.Exit(2) os.Exit(2)
} }
p.PackagePath = os.Getenv("CGOPKGPATH") + "/" + p.Package; p.PackagePath = os.Getenv("CGOPKGPATH") + "/" + p.Package
p.writeOutput(input); p.writeOutput(input)
} }
...@@ -5,78 +5,78 @@ ...@@ -5,78 +5,78 @@
package main package main
import ( import (
"fmt"; "fmt"
"go/ast"; "go/ast"
"go/printer"; "go/printer"
"os"; "os"
"strings"; "strings"
) )
func creat(name string) *os.File { func creat(name string) *os.File {
f, err := os.Open(name, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666); f, err := os.Open(name, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
if err != nil { if err != nil {
fatal("%s", err) fatal("%s", err)
} }
return f; return f
} }
// writeOutput creates output files to be compiled by 6g, 6c, and gcc. // writeOutput 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.) // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Prog) writeOutput(srcfile string) { func (p *Prog) writeOutput(srcfile string) {
pkgroot := os.Getenv("GOROOT") + "/pkg/" + os.Getenv("GOOS") + "_" + os.Getenv("GOARCH"); pkgroot := os.Getenv("GOROOT") + "/pkg/" + os.Getenv("GOOS") + "_" + os.Getenv("GOARCH")
base := srcfile; base := srcfile
if strings.HasSuffix(base, ".go") { if strings.HasSuffix(base, ".go") {
base = base[0 : len(base)-3] base = base[0 : len(base)-3]
} }
fgo1 := creat(base + ".cgo1.go"); fgo1 := creat(base + ".cgo1.go")
fgo2 := creat(base + ".cgo2.go"); fgo2 := creat(base + ".cgo2.go")
fc := creat(base + ".cgo3.c"); fc := creat(base + ".cgo3.c")
fgcc := creat(base + ".cgo4.c"); fgcc := creat(base + ".cgo4.c")
// Write Go output: Go input with rewrites of C.xxx to _C_xxx. // Write Go output: Go input with rewrites of C.xxx to _C_xxx.
fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n"); fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n")
fmt.Fprintf(fgo1, "//line %s:1\n", srcfile); fmt.Fprintf(fgo1, "//line %s:1\n", srcfile)
printer.Fprint(fgo1, p.AST); printer.Fprint(fgo1, p.AST)
// Write second Go output: definitions of _C_xxx. // Write second Go output: definitions of _C_xxx.
// In a separate file so that the import of "unsafe" does not // In a separate file so that the import of "unsafe" does not
// pollute the original file. // pollute the original file.
fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n"); fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n")
fmt.Fprintf(fgo2, "package %s\n\n", p.Package); fmt.Fprintf(fgo2, "package %s\n\n", p.Package)
fmt.Fprintf(fgo2, "import \"unsafe\"\n\n"); fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n"); fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
for name, def := range p.Typedef { for name, def := range p.Typedef {
fmt.Fprintf(fgo2, "type %s ", name); fmt.Fprintf(fgo2, "type %s ", name)
printer.Fprint(fgo2, def); printer.Fprint(fgo2, def)
fmt.Fprintf(fgo2, "\n"); fmt.Fprintf(fgo2, "\n")
} }
fmt.Fprintf(fgo2, "type _C_void [0]byte\n"); fmt.Fprintf(fgo2, "type _C_void [0]byte\n")
// While we process the vars and funcs, also write 6c and gcc output. // While we process the vars and funcs, also write 6c and gcc output.
// Gcc output starts with the preamble. // Gcc output starts with the preamble.
fmt.Fprintf(fgcc, "%s\n", p.Preamble); fmt.Fprintf(fgcc, "%s\n", p.Preamble)
fmt.Fprintf(fgcc, "%s\n", gccProlog); fmt.Fprintf(fgcc, "%s\n", gccProlog)
fmt.Fprintf(fc, cProlog, pkgroot, pkgroot, pkgroot, pkgroot, p.Package, p.Package); fmt.Fprintf(fc, cProlog, pkgroot, pkgroot, pkgroot, pkgroot, p.Package, p.Package)
for name, def := range p.Vardef { for name, def := range p.Vardef {
fmt.Fprintf(fc, "#pragma dynld %s·_C_%s %s \"%s/%s_%s.so\"\n", p.Package, name, name, pkgroot, p.PackagePath, base); fmt.Fprintf(fc, "#pragma dynld %s·_C_%s %s \"%s/%s_%s.so\"\n", p.Package, name, name, pkgroot, p.PackagePath, base)
fmt.Fprintf(fgo2, "var _C_%s ", name); fmt.Fprintf(fgo2, "var _C_%s ", name)
printer.Fprint(fgo2, &ast.StarExpr{X: def.Go}); printer.Fprint(fgo2, &ast.StarExpr{X: def.Go})
fmt.Fprintf(fgo2, "\n"); fmt.Fprintf(fgo2, "\n")
} }
fmt.Fprintf(fc, "\n"); fmt.Fprintf(fc, "\n")
for name, def := range p.Funcdef { for name, def := range p.Funcdef {
// Go func declaration. // Go func declaration.
d := &ast.FuncDecl{ d := &ast.FuncDecl{
Name: &ast.Ident{Value: "_C_" + name}, Name: &ast.Ident{Value: "_C_" + name},
Type: def.Go, Type: def.Go,
}; }
printer.Fprint(fgo2, d); printer.Fprint(fgo2, d)
fmt.Fprintf(fgo2, "\n"); fmt.Fprintf(fgo2, "\n")
if name == "CString" || name == "GoString" { if name == "CString" || name == "GoString" {
// The builtins are already defined in the C prolog. // The builtins are already defined in the C prolog.
...@@ -88,86 +88,86 @@ func (p *Prog) writeOutput(srcfile string) { ...@@ -88,86 +88,86 @@ func (p *Prog) writeOutput(srcfile string) {
// These assumptions are checked by the gccProlog. // These assumptions are checked by the gccProlog.
// Also assumes that 6c convention is to word-align the // Also assumes that 6c convention is to word-align the
// input and output parameters. // input and output parameters.
structType := "struct {\n"; structType := "struct {\n"
off := int64(0); off := int64(0)
npad := 0; npad := 0
for i, t := range def.Params { for i, t := range def.Params {
if off%t.Align != 0 { if off%t.Align != 0 {
pad := t.Align - off%t.Align; pad := t.Align - off%t.Align
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad); structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
off += pad; off += pad
npad++; npad++
} }
structType += fmt.Sprintf("\t\t%s p%d;\n", t.C, i); structType += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
off += t.Size; off += t.Size
} }
if off%p.PtrSize != 0 { if off%p.PtrSize != 0 {
pad := p.PtrSize - off%p.PtrSize; pad := p.PtrSize - off%p.PtrSize
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad); structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
off += pad; off += pad
npad++; npad++
} }
if t := def.Result; t != nil { if t := def.Result; t != nil {
if off%t.Align != 0 { if off%t.Align != 0 {
pad := t.Align - off%t.Align; pad := t.Align - off%t.Align
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad); structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
off += pad; off += pad
npad++; npad++
} }
structType += fmt.Sprintf("\t\t%s r;\n", t.C); structType += fmt.Sprintf("\t\t%s r;\n", t.C)
off += t.Size; off += t.Size
} }
if off%p.PtrSize != 0 { if off%p.PtrSize != 0 {
pad := p.PtrSize - off%p.PtrSize; pad := p.PtrSize - off%p.PtrSize
structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad); structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
off += pad; off += pad
npad++; npad++
} }
if len(def.Params) == 0 && def.Result == nil { if len(def.Params) == 0 && def.Result == nil {
structType += "\t\tchar unused;\n"; // avoid empty struct structType += "\t\tchar unused;\n" // avoid empty struct
off++; off++
} }
structType += "\t}"; structType += "\t}"
argSize := off; argSize := off
// C wrapper calls into gcc, passing a pointer to the argument frame. // C wrapper calls into gcc, passing a pointer to the argument frame.
// Also emit #pragma to get a pointer to the gcc wrapper. // Also emit #pragma to get a pointer to the gcc wrapper.
fmt.Fprintf(fc, "#pragma dynld _cgo_%s _cgo_%s \"%s/%s_%s.so\"\n", name, name, pkgroot, p.PackagePath, base); fmt.Fprintf(fc, "#pragma dynld _cgo_%s _cgo_%s \"%s/%s_%s.so\"\n", name, name, pkgroot, p.PackagePath, base)
fmt.Fprintf(fc, "void (*_cgo_%s)(void*);\n", name); fmt.Fprintf(fc, "void (*_cgo_%s)(void*);\n", name)
fmt.Fprintf(fc, "\n"); fmt.Fprintf(fc, "\n")
fmt.Fprintf(fc, "void\n"); fmt.Fprintf(fc, "void\n")
fmt.Fprintf(fc, "%s·_C_%s(struct{uint8 x[%d];}p)\n", p.Package, name, argSize); fmt.Fprintf(fc, "%s·_C_%s(struct{uint8 x[%d];}p)\n", p.Package, name, argSize)
fmt.Fprintf(fc, "{\n"); fmt.Fprintf(fc, "{\n")
fmt.Fprintf(fc, "\tcgocall(_cgo_%s, &p);\n", name); fmt.Fprintf(fc, "\tcgocall(_cgo_%s, &p);\n", name)
fmt.Fprintf(fc, "}\n"); fmt.Fprintf(fc, "}\n")
fmt.Fprintf(fc, "\n"); fmt.Fprintf(fc, "\n")
// Gcc wrapper unpacks the C argument struct // Gcc wrapper unpacks the C argument struct
// and calls the actual C function. // and calls the actual C function.
fmt.Fprintf(fgcc, "void\n"); fmt.Fprintf(fgcc, "void\n")
fmt.Fprintf(fgcc, "_cgo_%s(void *v)\n", name); fmt.Fprintf(fgcc, "_cgo_%s(void *v)\n", name)
fmt.Fprintf(fgcc, "{\n"); fmt.Fprintf(fgcc, "{\n")
fmt.Fprintf(fgcc, "\t%s *a = v;\n", structType); fmt.Fprintf(fgcc, "\t%s *a = v;\n", structType)
fmt.Fprintf(fgcc, "\t"); fmt.Fprintf(fgcc, "\t")
if def.Result != nil { if def.Result != nil {
fmt.Fprintf(fgcc, "a->r = ") fmt.Fprintf(fgcc, "a->r = ")
} }
fmt.Fprintf(fgcc, "%s(", name); fmt.Fprintf(fgcc, "%s(", name)
for i := range def.Params { for i := range def.Params {
if i > 0 { if i > 0 {
fmt.Fprintf(fgcc, ", ") fmt.Fprintf(fgcc, ", ")
} }
fmt.Fprintf(fgcc, "a->p%d", i); fmt.Fprintf(fgcc, "a->p%d", i)
} }
fmt.Fprintf(fgcc, ");\n"); fmt.Fprintf(fgcc, ");\n")
fmt.Fprintf(fgcc, "}\n"); fmt.Fprintf(fgcc, "}\n")
fmt.Fprintf(fgcc, "\n"); fmt.Fprintf(fgcc, "\n")
} }
fgo1.Close(); fgo1.Close()
fgo2.Close(); fgo2.Close()
fc.Close(); fc.Close()
fgcc.Close(); fgcc.Close()
} }
const gccProlog = ` const gccProlog = `
......
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
package main package main
import ( import (
"exec"; "exec"
"fmt"; "fmt"
"go/token"; "go/token"
"io/ioutil"; "io/ioutil"
"os"; "os"
) )
// A ByteReaderAt implements io.ReadAt using a slice of bytes. // A ByteReaderAt implements io.ReadAt using a slice of bytes.
...@@ -19,76 +19,76 @@ func (r ByteReaderAt) ReadAt(p []byte, off int64) (n int, err os.Error) { ...@@ -19,76 +19,76 @@ func (r ByteReaderAt) ReadAt(p []byte, off int64) (n int, err os.Error) {
if off >= int64(len(r)) || off < 0 { if off >= int64(len(r)) || off < 0 {
return 0, os.EOF return 0, os.EOF
} }
return copy(p, r[off:]), nil; return copy(p, r[off:]), nil
} }
// run runs the command argv, feeding in stdin on standard input. // run runs the command argv, feeding in stdin on standard input.
// It returns the output to standard output and standard error. // It returns the output to standard output and standard error.
// ok indicates whether the command exited successfully. // ok indicates whether the command exited successfully.
func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
cmd, err := exec.LookPath(argv[0]); cmd, err := exec.LookPath(argv[0])
if err != nil { if err != nil {
fatal("exec %s: %s", argv[0], err) fatal("exec %s: %s", argv[0], err)
} }
r0, w0, err := os.Pipe(); r0, w0, err := os.Pipe()
if err != nil { if err != nil {
fatal("%s", err) fatal("%s", err)
} }
r1, w1, err := os.Pipe(); r1, w1, err := os.Pipe()
if err != nil { if err != nil {
fatal("%s", err) fatal("%s", err)
} }
r2, w2, err := os.Pipe(); r2, w2, err := os.Pipe()
if err != nil { if err != nil {
fatal("%s", err) fatal("%s", err)
} }
pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2}); pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})
if err != nil { if err != nil {
fatal("%s", err) fatal("%s", err)
} }
r0.Close(); r0.Close()
w1.Close(); w1.Close()
w2.Close(); w2.Close()
c := make(chan bool); c := make(chan bool)
go func() { go func() {
w0.Write(stdin); w0.Write(stdin)
w0.Close(); w0.Close()
c <- true; c <- true
}(); }()
var xstdout []byte; // TODO(rsc): delete after 6g can take address of out parameter var xstdout []byte // TODO(rsc): delete after 6g can take address of out parameter
go func() { go func() {
xstdout, _ = ioutil.ReadAll(r1); xstdout, _ = ioutil.ReadAll(r1)
r1.Close(); r1.Close()
c <- true; c <- true
}(); }()
stderr, _ = ioutil.ReadAll(r2); stderr, _ = ioutil.ReadAll(r2)
r2.Close(); r2.Close()
<-c; <-c
<-c; <-c
stdout = xstdout; stdout = xstdout
w, err := os.Wait(pid, 0); w, err := os.Wait(pid, 0)
if err != nil { if err != nil {
fatal("%s", err) fatal("%s", err)
} }
ok = w.Exited() && w.ExitStatus() == 0; ok = w.Exited() && w.ExitStatus() == 0
return; return
} }
// Die with an error message. // Die with an error message.
func fatal(msg string, args ...) { func fatal(msg string, args ...) {
fmt.Fprintf(os.Stderr, msg+"\n", args); fmt.Fprintf(os.Stderr, msg+"\n", args)
os.Exit(2); os.Exit(2)
} }
var nerrors int var nerrors int
var noPos token.Position var noPos token.Position
func error(pos token.Position, msg string, args ...) { func error(pos token.Position, msg string, args ...) {
nerrors++; nerrors++
if pos.IsValid() { if pos.IsValid() {
fmt.Fprintf(os.Stderr, "%s: ", pos) fmt.Fprintf(os.Stderr, "%s: ", pos)
} }
fmt.Fprintf(os.Stderr, msg, args); fmt.Fprintf(os.Stderr, msg, args)
fmt.Fprintf(os.Stderr, "\n"); fmt.Fprintf(os.Stderr, "\n")
} }
...@@ -5,15 +5,15 @@ ...@@ -5,15 +5,15 @@
package main package main
import ( import (
"bytes"; "bytes"
"ebnf"; "ebnf"
"flag"; "flag"
"fmt"; "fmt"
"go/scanner"; "go/scanner"
"io/ioutil"; "io/ioutil"
"os"; "os"
"path"; "path"
"strings"; "strings"
) )
...@@ -21,29 +21,29 @@ var start = flag.String("start", "Start", "name of start production") ...@@ -21,29 +21,29 @@ var start = flag.String("start", "Start", "name of start production")
func usage() { func usage() {
fmt.Fprintf(os.Stderr, "usage: ebnflint [flags] [filename]\n"); fmt.Fprintf(os.Stderr, "usage: ebnflint [flags] [filename]\n")
flag.PrintDefaults(); flag.PrintDefaults()
os.Exit(1); os.Exit(1)
} }
// Markers around EBNF sections in .html files // Markers around EBNF sections in .html files
var ( var (
open = strings.Bytes(`<pre class="ebnf">`); open = strings.Bytes(`<pre class="ebnf">`)
close = strings.Bytes(`</pre>`); close = strings.Bytes(`</pre>`)
) )
func extractEBNF(src []byte) []byte { func extractEBNF(src []byte) []byte {
var buf bytes.Buffer; var buf bytes.Buffer
for { for {
// i = beginning of EBNF text // i = beginning of EBNF text
i := bytes.Index(src, open); i := bytes.Index(src, open)
if i < 0 { if i < 0 {
break // no EBNF found - we are done break // no EBNF found - we are done
} }
i += len(open); i += len(open)
// write as many newlines as found in the excluded text // write as many newlines as found in the excluded text
// to maintain correct line numbers in error messages // to maintain correct line numbers in error messages
...@@ -54,27 +54,27 @@ func extractEBNF(src []byte) []byte { ...@@ -54,27 +54,27 @@ func extractEBNF(src []byte) []byte {
} }
// j = end of EBNF text (or end of source) // j = end of EBNF text (or end of source)
j := bytes.Index(src[i:], close); // close marker j := bytes.Index(src[i:], close) // close marker
if j < 0 { if j < 0 {
j = len(src) - i j = len(src) - i
} }
j += i; j += i
// copy EBNF text // copy EBNF text
buf.Write(src[i:j]); buf.Write(src[i:j])
// advance // advance
src = src[j:]; src = src[j:]
} }
return buf.Bytes(); return buf.Bytes()
} }
func main() { func main() {
flag.Parse(); flag.Parse()
var filename string; var filename string
switch flag.NArg() { switch flag.NArg() {
case 0: case 0:
filename = "/dev/stdin" filename = "/dev/stdin"
...@@ -84,7 +84,7 @@ func main() { ...@@ -84,7 +84,7 @@ func main() {
usage() usage()
} }
src, err := ioutil.ReadFile(filename); src, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
scanner.PrintError(os.Stderr, err) scanner.PrintError(os.Stderr, err)
} }
...@@ -93,7 +93,7 @@ func main() { ...@@ -93,7 +93,7 @@ func main() {
src = extractEBNF(src) src = extractEBNF(src)
} }
grammar, err := ebnf.Parse(filename, src); grammar, err := ebnf.Parse(filename, src)
if err != nil { if err != nil {
scanner.PrintError(os.Stderr, err) scanner.PrintError(os.Stderr, err)
} }
......
...@@ -84,7 +84,7 @@ func sliceslice1(old []any, lb int, width int) (ary []any) ...@@ -84,7 +84,7 @@ func sliceslice1(old []any, lb int, width int) (ary []any)
func sliceslice(old []any, lb int, hb int, width int) (ary []any) func sliceslice(old []any, lb int, hb int, width int) (ary []any)
func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any) func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
func closure() // has args, but compiler fills in func closure() // has args, but compiler fills in
// only used on 32-bit // only used on 32-bit
func int64div(int64, int64) int64 func int64div(int64, int64) int64
......
This diff is collapsed.
This diff is collapsed.
...@@ -26,74 +26,74 @@ ...@@ -26,74 +26,74 @@
package main package main
import ( import (
"bytes"; "bytes"
"flag"; "flag"
"fmt"; "fmt"
"http"; "http"
"io"; "io"
"log"; "log"
"os"; "os"
"time"; "time"
) )
var ( var (
// periodic sync // periodic sync
syncCmd = flag.String("sync", "", "sync command; disabled if empty"); syncCmd = flag.String("sync", "", "sync command; disabled if empty")
syncMin = flag.Int("sync_minutes", 0, "sync interval in minutes; disabled if <= 0"); syncMin = flag.Int("sync_minutes", 0, "sync interval in minutes; disabled if <= 0")
syncDelay delayTime; // actual sync delay in minutes; usually syncDelay == syncMin, but delay may back off exponentially syncDelay delayTime // actual sync delay in minutes; usually syncDelay == syncMin, but delay may back off exponentially
// server control // server control
httpaddr = flag.String("http", "", "HTTP service address (e.g., ':6060')"); httpaddr = flag.String("http", "", "HTTP service address (e.g., ':6060')")
// layout control // layout control
html = flag.Bool("html", false, "print HTML in command-line mode"); html = flag.Bool("html", false, "print HTML in command-line mode")
) )
func exec(c *http.Conn, args []string) (status int) { func exec(c *http.Conn, args []string) (status int) {
r, w, err := os.Pipe(); r, w, err := os.Pipe()
if err != nil { if err != nil {
log.Stderrf("os.Pipe(): %v\n", err); log.Stderrf("os.Pipe(): %v\n", err)
return 2; return 2
} }
bin := args[0]; bin := args[0]
fds := []*os.File{nil, w, w}; fds := []*os.File{nil, w, w}
if *verbose { if *verbose {
log.Stderrf("executing %v", args) log.Stderrf("executing %v", args)
} }
pid, err := os.ForkExec(bin, args, os.Environ(), goroot, fds); pid, err := os.ForkExec(bin, args, os.Environ(), goroot, fds)
defer r.Close(); defer r.Close()
w.Close(); w.Close()
if err != nil { if err != nil {
log.Stderrf("os.ForkExec(%q): %v\n", bin, err); log.Stderrf("os.ForkExec(%q): %v\n", bin, err)
return 2; return 2
} }
var buf bytes.Buffer; var buf bytes.Buffer
io.Copy(&buf, r); io.Copy(&buf, r)
wait, err := os.Wait(pid, 0); wait, err := os.Wait(pid, 0)
if err != nil { if err != nil {
os.Stderr.Write(buf.Bytes()); os.Stderr.Write(buf.Bytes())
log.Stderrf("os.Wait(%d, 0): %v\n", pid, err); log.Stderrf("os.Wait(%d, 0): %v\n", pid, err)
return 2; return 2
} }
status = wait.ExitStatus(); status = wait.ExitStatus()
if !wait.Exited() || status > 1 { if !wait.Exited() || status > 1 {
os.Stderr.Write(buf.Bytes()); os.Stderr.Write(buf.Bytes())
log.Stderrf("executing %v failed (exit status = %d)", args, status); log.Stderrf("executing %v failed (exit status = %d)", args, status)
return; return
} }
if *verbose { if *verbose {
os.Stderr.Write(buf.Bytes()) os.Stderr.Write(buf.Bytes())
} }
if c != nil { if c != nil {
c.SetHeader("content-type", "text/plain; charset=utf-8"); c.SetHeader("content-type", "text/plain; charset=utf-8")
c.Write(buf.Bytes()); c.Write(buf.Bytes())
} }
return; return
} }
...@@ -101,7 +101,7 @@ func exec(c *http.Conn, args []string) (status int) { ...@@ -101,7 +101,7 @@ func exec(c *http.Conn, args []string) (status int) {
const maxDirDepth = 24 const maxDirDepth = 24
func dosync(c *http.Conn, r *http.Request) { func dosync(c *http.Conn, r *http.Request) {
args := []string{"/bin/sh", "-c", *syncCmd}; args := []string{"/bin/sh", "-c", *syncCmd}
switch exec(c, args) { switch exec(c, args) {
case 0: case 0:
// sync succeeded and some files have changed; // sync succeeded and some files have changed;
...@@ -109,12 +109,12 @@ func dosync(c *http.Conn, r *http.Request) { ...@@ -109,12 +109,12 @@ func dosync(c *http.Conn, r *http.Request) {
// TODO(gri): The directory tree may be temporarily out-of-sync. // TODO(gri): The directory tree may be temporarily out-of-sync.
// Consider keeping separate time stamps so the web- // Consider keeping separate time stamps so the web-
// page can indicate this discrepancy. // page can indicate this discrepancy.
fsTree.set(newDirectory(".", maxDirDepth)); fsTree.set(newDirectory(".", maxDirDepth))
fallthrough; fallthrough
case 1: case 1:
// sync failed because no files changed; // sync failed because no files changed;
// don't change the package tree // don't change the package tree
syncDelay.set(*syncMin) // revert to regular sync schedule syncDelay.set(*syncMin) // revert to regular sync schedule
default: default:
// sync failed because of an error - back off exponentially, but try at least once a day // sync failed because of an error - back off exponentially, but try at least once a day
syncDelay.backoff(24 * 60) syncDelay.backoff(24 * 60)
...@@ -125,23 +125,23 @@ func dosync(c *http.Conn, r *http.Request) { ...@@ -125,23 +125,23 @@ func dosync(c *http.Conn, r *http.Request) {
func usage() { func usage() {
fmt.Fprintf(os.Stderr, fmt.Fprintf(os.Stderr,
"usage: godoc package [name ...]\n"+ "usage: godoc package [name ...]\n"+
" godoc -http=:6060\n"); " godoc -http=:6060\n")
flag.PrintDefaults(); flag.PrintDefaults()
os.Exit(2); os.Exit(2)
} }
func loggingHandler(h http.Handler) http.Handler { func loggingHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(c *http.Conn, req *http.Request) { return http.HandlerFunc(func(c *http.Conn, req *http.Request) {
log.Stderrf("%s\t%s", c.RemoteAddr, req.URL); log.Stderrf("%s\t%s", c.RemoteAddr, req.URL)
h.ServeHTTP(c, req); h.ServeHTTP(c, req)
}) })
} }
func main() { func main() {
flag.Usage = usage; flag.Usage = usage
flag.Parse(); flag.Parse()
// Check usage: either server and no args, or command line and args // Check usage: either server and no args, or command line and args
if (*httpaddr != "") != (flag.NArg() == 0) { if (*httpaddr != "") != (flag.NArg() == 0) {
...@@ -156,23 +156,23 @@ func main() { ...@@ -156,23 +156,23 @@ func main() {
log.Exitf("chdir %s: %v", goroot, err) log.Exitf("chdir %s: %v", goroot, err)
} }
readTemplates(); readTemplates()
if *httpaddr != "" { if *httpaddr != "" {
// HTTP server mode. // HTTP server mode.
var handler http.Handler = http.DefaultServeMux; var handler http.Handler = http.DefaultServeMux
if *verbose { if *verbose {
log.Stderrf("Go Documentation Server\n"); log.Stderrf("Go Documentation Server\n")
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("cmdroot = %s\n", *cmdroot); log.Stderrf("cmdroot = %s\n", *cmdroot)
log.Stderrf("pkgroot = %s\n", *pkgroot); log.Stderrf("pkgroot = %s\n", *pkgroot)
log.Stderrf("tmplroot = %s\n", *tmplroot); log.Stderrf("tmplroot = %s\n", *tmplroot)
log.Stderrf("tabwidth = %d\n", *tabwidth); log.Stderrf("tabwidth = %d\n", *tabwidth)
handler = loggingHandler(handler); handler = loggingHandler(handler)
} }
registerPublicHandlers(http.DefaultServeMux); registerPublicHandlers(http.DefaultServeMux)
if *syncCmd != "" { if *syncCmd != "" {
http.Handle("/debug/sync", http.HandlerFunc(dosync)) http.Handle("/debug/sync", http.HandlerFunc(dosync))
} }
...@@ -180,39 +180,39 @@ func main() { ...@@ -180,39 +180,39 @@ func main() {
// Initialize directory tree with corresponding timestamp. // Initialize directory tree with corresponding timestamp.
// Do it in two steps: // Do it in two steps:
// 1) set timestamp right away so that the indexer is kicked on // 1) set timestamp right away so that the indexer is kicked on
fsTree.set(nil); fsTree.set(nil)
// 2) compute initial directory tree in a goroutine so that launch is quick // 2) compute initial directory tree in a goroutine so that launch is quick
go func() { fsTree.set(newDirectory(".", maxDirDepth)) }(); go func() { fsTree.set(newDirectory(".", maxDirDepth)) }()
// Start sync goroutine, if enabled. // Start sync goroutine, if enabled.
if *syncCmd != "" && *syncMin > 0 { if *syncCmd != "" && *syncMin > 0 {
syncDelay.set(*syncMin); // initial sync delay syncDelay.set(*syncMin) // initial sync delay
go func() { go func() {
for { for {
dosync(nil, nil); dosync(nil, nil)
delay, _ := syncDelay.get(); delay, _ := syncDelay.get()
if *verbose { if *verbose {
log.Stderrf("next sync in %dmin", delay.(int)) log.Stderrf("next sync in %dmin", delay.(int))
} }
time.Sleep(int64(delay.(int)) * 60e9); time.Sleep(int64(delay.(int)) * 60e9)
} }
}(); }()
} }
// Start indexing goroutine. // Start indexing goroutine.
go indexer(); go indexer()
// The server may have been restarted; always wait 1sec to // The server may have been restarted; always wait 1sec to
// give the forking server a chance to shut down and release // give the forking server a chance to shut down and release
// the http port. // the http port.
// TODO(gri): Do we still need this? // TODO(gri): Do we still need this?
time.Sleep(1e9); time.Sleep(1e9)
// Start http server. // Start http server.
if err := http.ListenAndServe(*httpaddr, handler); err != nil { if err := http.ListenAndServe(*httpaddr, handler); err != nil {
log.Exitf("ListenAndServe %s: %v", *httpaddr, err) log.Exitf("ListenAndServe %s: %v", *httpaddr, err)
} }
return; return
} }
// Command line mode. // Command line mode.
...@@ -220,7 +220,7 @@ func main() { ...@@ -220,7 +220,7 @@ func main() {
packageText = packageHTML packageText = packageHTML
} }
info := pkgHandler.getPageInfo(flag.Arg(0)); info := pkgHandler.getPageInfo(flag.Arg(0))
if info.PDoc == nil && info.Dirs == nil { if info.PDoc == nil && info.Dirs == nil {
// try again, this time assume it's a command // try again, this time assume it's a command
...@@ -228,8 +228,8 @@ func main() { ...@@ -228,8 +228,8 @@ func main() {
} }
if info.PDoc != nil && flag.NArg() > 1 { if info.PDoc != nil && flag.NArg() > 1 {
args := flag.Args(); args := flag.Args()
info.PDoc.Filter(args[1:]); info.PDoc.Filter(args[1:])
} }
if err := packageText.Execute(info, os.Stdout); err != nil { if err := packageText.Execute(info, os.Stdout); err != nil {
......
...@@ -10,44 +10,44 @@ ...@@ -10,44 +10,44 @@
package main package main
import ( import (
"bytes"; "bytes"
"go/ast"; "go/ast"
"go/printer"; "go/printer"
"fmt"; "fmt"
"strings"; "strings"
) )
type Snippet struct { type Snippet struct {
Line int; Line int
Text string; Text string
} }
type snippetStyler struct { type snippetStyler struct {
Styler; // defined in godoc.go Styler // defined in godoc.go
highlight *ast.Ident; // identifier to highlight highlight *ast.Ident // identifier to highlight
} }
func (s *snippetStyler) LineTag(line int) (text []uint8, tag printer.HTMLTag) { func (s *snippetStyler) LineTag(line int) (text []uint8, tag printer.HTMLTag) {
return // no LineTag for snippets return // no LineTag for snippets
} }
func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) { func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
text = strings.Bytes(id.Value); text = strings.Bytes(id.Value)
if s.highlight == id { if s.highlight == id {
tag = printer.HTMLTag{"<span class=highlight>", "</span>"} tag = printer.HTMLTag{"<span class=highlight>", "</span>"}
} }
return; return
} }
func newSnippet(decl ast.Decl, id *ast.Ident) *Snippet { func newSnippet(decl ast.Decl, id *ast.Ident) *Snippet {
var buf bytes.Buffer; var buf bytes.Buffer
writeNode(&buf, decl, true, &snippetStyler{highlight: id}); writeNode(&buf, decl, true, &snippetStyler{highlight: id})
return &Snippet{id.Pos().Line, buf.String()}; return &Snippet{id.Pos().Line, buf.String()}
} }
...@@ -70,32 +70,32 @@ func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec { ...@@ -70,32 +70,32 @@ func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
} }
} }
} }
return nil; return nil
} }
func genSnippet(d *ast.GenDecl, id *ast.Ident) *Snippet { func genSnippet(d *ast.GenDecl, id *ast.Ident) *Snippet {
s := findSpec(d.Specs, id); s := findSpec(d.Specs, id)
if s == nil { if s == nil {
return nil // declaration doesn't contain id - exit gracefully return nil // declaration doesn't contain id - exit gracefully
} }
// only use the spec containing the id for the snippet // only use the spec containing the id for the snippet
dd := &ast.GenDecl{d.Doc, d.Position, d.Tok, d.Lparen, []ast.Spec{s}, d.Rparen}; dd := &ast.GenDecl{d.Doc, d.Position, d.Tok, d.Lparen, []ast.Spec{s}, d.Rparen}
return newSnippet(dd, id); return newSnippet(dd, id)
} }
func funcSnippet(d *ast.FuncDecl, id *ast.Ident) *Snippet { func funcSnippet(d *ast.FuncDecl, id *ast.Ident) *Snippet {
if d.Name != id { if d.Name != id {
return nil // declaration doesn't contain id - exit gracefully return nil // declaration doesn't contain id - exit gracefully
} }
// only use the function signature for the snippet // only use the function signature for the snippet
dd := &ast.FuncDecl{d.Doc, d.Recv, d.Name, d.Type, nil}; dd := &ast.FuncDecl{d.Doc, d.Recv, d.Name, d.Type, nil}
return newSnippet(dd, id); return newSnippet(dd, id)
} }
...@@ -118,5 +118,5 @@ func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) { ...@@ -118,5 +118,5 @@ func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) {
fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Value), fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Value),
} }
} }
return; return
} }
...@@ -11,35 +11,35 @@ ...@@ -11,35 +11,35 @@
package main package main
import ( import (
"bytes"; "bytes"
"fmt"; "fmt"
"go/scanner"; "go/scanner"
"go/token"; "go/token"
"io"; "io"
"strings"; "strings"
) )
type ebnfParser struct { type ebnfParser struct {
out io.Writer; // parser output out io.Writer // parser output
src []byte; // parser source src []byte // parser source
scanner scanner.Scanner; scanner scanner.Scanner
prev int; // offset of previous token prev int // offset of previous token
pos token.Position; // token position pos token.Position // token position
tok token.Token; // one token look-ahead tok token.Token // one token look-ahead
lit []byte; // token literal lit []byte // token literal
} }
func (p *ebnfParser) flush() { func (p *ebnfParser) flush() {
p.out.Write(p.src[p.prev:p.pos.Offset]); p.out.Write(p.src[p.prev:p.pos.Offset])
p.prev = p.pos.Offset; p.prev = p.pos.Offset
} }
func (p *ebnfParser) next() { func (p *ebnfParser) next() {
p.flush(); p.flush()
p.pos, p.tok, p.lit = p.scanner.Scan(); p.pos, p.tok, p.lit = p.scanner.Scan()
if p.tok.IsKeyword() { if p.tok.IsKeyword() {
// TODO Should keyword mapping always happen outside scanner? // TODO Should keyword mapping always happen outside scanner?
// Or should there be a flag to scanner to enable keyword mapping? // Or should there be a flag to scanner to enable keyword mapping?
...@@ -54,38 +54,38 @@ func (p *ebnfParser) Error(pos token.Position, msg string) { ...@@ -54,38 +54,38 @@ func (p *ebnfParser) Error(pos token.Position, msg string) {
func (p *ebnfParser) errorExpected(pos token.Position, msg string) { func (p *ebnfParser) errorExpected(pos token.Position, msg string) {
msg = "expected " + msg; msg = "expected " + msg
if pos.Offset == p.pos.Offset { if pos.Offset == p.pos.Offset {
// the error happened at the current position; // the error happened at the current position;
// make the error message more specific // make the error message more specific
msg += ", found '" + p.tok.String() + "'"; msg += ", found '" + p.tok.String() + "'"
if p.tok.IsLiteral() { if p.tok.IsLiteral() {
msg += " " + string(p.lit) msg += " " + string(p.lit)
} }
} }
p.Error(pos, msg); p.Error(pos, msg)
} }
func (p *ebnfParser) expect(tok token.Token) token.Position { func (p *ebnfParser) expect(tok token.Token) token.Position {
pos := p.pos; pos := p.pos
if p.tok != tok { if p.tok != tok {
p.errorExpected(pos, "'"+tok.String()+"'") p.errorExpected(pos, "'"+tok.String()+"'")
} }
p.next(); // make progress in any case p.next() // make progress in any case
return pos; return pos
} }
func (p *ebnfParser) parseIdentifier(def bool) { func (p *ebnfParser) parseIdentifier(def bool) {
name := string(p.lit); name := string(p.lit)
p.expect(token.IDENT); p.expect(token.IDENT)
if def { if def {
fmt.Fprintf(p.out, `<a id="%s">%s</a>`, name, name) fmt.Fprintf(p.out, `<a id="%s">%s</a>`, name, name)
} else { } else {
fmt.Fprintf(p.out, `<a href="#%s" class="noline">%s</a>`, name, name) fmt.Fprintf(p.out, `<a href="#%s" class="noline">%s</a>`, name, name)
} }
p.prev += len(name); // skip identifier when calling flush p.prev += len(name) // skip identifier when calling flush
} }
...@@ -95,32 +95,32 @@ func (p *ebnfParser) parseTerm() bool { ...@@ -95,32 +95,32 @@ func (p *ebnfParser) parseTerm() bool {
p.parseIdentifier(false) p.parseIdentifier(false)
case token.STRING: case token.STRING:
p.next(); p.next()
if p.tok == token.ELLIPSIS { if p.tok == token.ELLIPSIS {
p.next(); p.next()
p.expect(token.STRING); p.expect(token.STRING)
} }
case token.LPAREN: case token.LPAREN:
p.next(); p.next()
p.parseExpression(); p.parseExpression()
p.expect(token.RPAREN); p.expect(token.RPAREN)
case token.LBRACK: case token.LBRACK:
p.next(); p.next()
p.parseExpression(); p.parseExpression()
p.expect(token.RBRACK); p.expect(token.RBRACK)
case token.LBRACE: case token.LBRACE:
p.next(); p.next()
p.parseExpression(); p.parseExpression()
p.expect(token.RBRACE); p.expect(token.RBRACE)
default: default:
return false return false
} }
return true; return true
} }
...@@ -132,70 +132,70 @@ func (p *ebnfParser) parseSequence() { ...@@ -132,70 +132,70 @@ func (p *ebnfParser) parseSequence() {
func (p *ebnfParser) parseExpression() { func (p *ebnfParser) parseExpression() {
for { for {
p.parseSequence(); p.parseSequence()
if p.tok != token.OR { if p.tok != token.OR {
break break
} }
p.next(); p.next()
} }
} }
func (p *ebnfParser) parseProduction() { func (p *ebnfParser) parseProduction() {
p.parseIdentifier(true); p.parseIdentifier(true)
p.expect(token.ASSIGN); p.expect(token.ASSIGN)
p.parseExpression(); p.parseExpression()
p.expect(token.PERIOD); p.expect(token.PERIOD)
} }
func (p *ebnfParser) parse(out io.Writer, src []byte) { func (p *ebnfParser) parse(out io.Writer, src []byte) {
// initialize ebnfParser // initialize ebnfParser
p.out = out; p.out = out
p.src = src; p.src = src
p.scanner.Init("", src, p, 0); p.scanner.Init("", src, p, 0)
p.next(); // initializes pos, tok, lit p.next() // initializes pos, tok, lit
// process source // process source
for p.tok != token.EOF { for p.tok != token.EOF {
p.parseProduction() p.parseProduction()
} }
p.flush(); p.flush()
} }
// Markers around EBNF sections // Markers around EBNF sections
var ( var (
openTag = strings.Bytes(`<pre class="ebnf">`); openTag = strings.Bytes(`<pre class="ebnf">`)
closeTag = strings.Bytes(`</pre>`); closeTag = strings.Bytes(`</pre>`)
) )
func linkify(out io.Writer, src []byte) { func linkify(out io.Writer, src []byte) {
for len(src) > 0 { for len(src) > 0 {
n := len(src); n := len(src)
// i: beginning of EBNF text (or end of source) // i: beginning of EBNF text (or end of source)
i := bytes.Index(src, openTag); i := bytes.Index(src, openTag)
if i < 0 { if i < 0 {
i = n - len(openTag) i = n - len(openTag)
} }
i += len(openTag); i += len(openTag)
// j: end of EBNF text (or end of source) // j: end of EBNF text (or end of source)
j := bytes.Index(src[i:n], closeTag); // close marker j := bytes.Index(src[i:n], closeTag) // close marker
if j < 0 { if j < 0 {
j = n - i j = n - i
} }
j += i; j += i
// write text before EBNF // write text before EBNF
out.Write(src[0:i]); out.Write(src[0:i])
// parse and write EBNF // parse and write EBNF
var p ebnfParser; var p ebnfParser
p.parse(out, src[i:j]); p.parse(out, src[i:j])
// advance // advance
src = src[j:n]; src = src[j:n]
} }
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
package flate package flate
import ( import (
"bytes"; "bytes"
"reflect"; "reflect"
"testing"; "testing"
) )
// The Huffman code lengths used by the fixed-format Huffman blocks. // The Huffman code lengths used by the fixed-format Huffman blocks.
...@@ -45,9 +45,9 @@ var fixedHuffmanBits = [...]int{ ...@@ -45,9 +45,9 @@ var fixedHuffmanBits = [...]int{
} }
type InitDecoderTest struct { type InitDecoderTest struct {
in []int; in []int
out huffmanDecoder; out huffmanDecoder
ok bool; ok bool
} }
var initDecoderTests = []*InitDecoderTest{ var initDecoderTests = []*InitDecoderTest{
...@@ -115,10 +115,10 @@ var initDecoderTests = []*InitDecoderTest{ ...@@ -115,10 +115,10 @@ var initDecoderTests = []*InitDecoderTest{
func TestInitDecoder(t *testing.T) { func TestInitDecoder(t *testing.T) {
for i, tt := range initDecoderTests { for i, tt := range initDecoderTests {
var h huffmanDecoder; var h huffmanDecoder
if h.init(tt.in) != tt.ok { if h.init(tt.in) != tt.ok {
t.Errorf("test %d: init = %v", i, !tt.ok); t.Errorf("test %d: init = %v", i, !tt.ok)
continue; continue
} }
if !reflect.DeepEqual(&h, &tt.out) { if !reflect.DeepEqual(&h, &tt.out) {
t.Errorf("test %d:\nhave %v\nwant %v", i, h, tt.out) t.Errorf("test %d:\nhave %v\nwant %v", i, h, tt.out)
...@@ -127,9 +127,9 @@ func TestInitDecoder(t *testing.T) { ...@@ -127,9 +127,9 @@ func TestInitDecoder(t *testing.T) {
} }
func TestUncompressedSource(t *testing.T) { func TestUncompressedSource(t *testing.T) {
decoder := NewInflater(bytes.NewBuffer([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11})); decoder := NewInflater(bytes.NewBuffer([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11}))
output := make([]byte, 1); output := make([]byte, 1)
n, error := decoder.Read(output); n, error := decoder.Read(output)
if n != 1 || error != nil { if n != 1 || error != nil {
t.Fatalf("decoder.Read() = %d, %v, want 1, nil", n, error) t.Fatalf("decoder.Read() = %d, %v, want 1, nil", n, error)
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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