mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t gmp.go:205:2: call mpz_init C value func(mpz_ptr) void gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void gmp.go:221:2: call mpz_init C value func(mpz_ptr) void gmp.go:227:7: call size_t C type size_t gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void R=r DELTA=938 (628 added, 308 deleted, 2 changed) OCL=34733 CL=34791
This commit is contained in:
parent
92f773dc77
commit
6a2602de91
7 changed files with 638 additions and 310 deletions
288
src/cmd/cgo/ast.go
Normal file
288
src/cmd/cgo/ast.go
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
// 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.
|
||||
|
||||
// Parse input AST and prepare Prog structure.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"debug/dwarf";
|
||||
"fmt";
|
||||
"go/ast";
|
||||
"go/doc";
|
||||
"go/parser";
|
||||
"go/scanner";
|
||||
"os";
|
||||
)
|
||||
|
||||
// A Cref refers to an expression of the form C.xxx in the AST.
|
||||
type Cref struct {
|
||||
Name string;
|
||||
Expr *ast.Expr;
|
||||
Context string; // "type", "expr", or "call"
|
||||
TypeName bool; // whether xxx is a C type name
|
||||
DebugType dwarf.Type; // the type of xxx
|
||||
}
|
||||
|
||||
// A Prog collects information about a cgo program.
|
||||
type Prog struct {
|
||||
AST *ast.File; // parsed AST
|
||||
Preamble string; // C preamble (doc comment on import "C")
|
||||
Crefs []*Cref;
|
||||
}
|
||||
|
||||
func openProg(name string) *Prog {
|
||||
p := new(Prog);
|
||||
var err os.Error;
|
||||
p.AST, err = parser.ParsePkgFile("", name, parser.ParseComments);
|
||||
if err != nil {
|
||||
if list, ok := err.(scanner.ErrorList); ok {
|
||||
// If err is a scanner.ErrorList, its String will print just
|
||||
// the first error and then (+n more errors).
|
||||
// Instead, turn it into a new Error that will return
|
||||
// details for all the errors.
|
||||
for _, e := range list {
|
||||
fmt.Fprintln(os.Stderr, e);
|
||||
}
|
||||
os.Exit(2);
|
||||
}
|
||||
fatal("parsing %s: %s", name, err);
|
||||
}
|
||||
|
||||
// Find the import "C" line and get any extra C preamble.
|
||||
found := false;
|
||||
for _, d := range p.AST.Decls {
|
||||
d, ok := d.(*ast.GenDecl);
|
||||
if !ok {
|
||||
continue;
|
||||
}
|
||||
for _, s := range d.Specs {
|
||||
s, ok := s.(*ast.ImportSpec);
|
||||
if !ok {
|
||||
continue;
|
||||
}
|
||||
if len(s.Path) != 1 || string(s.Path[0].Value) != `"C"` {
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
if s.Name != nil {
|
||||
error(s.Path[0].Pos(), `cannot rename import "C"`);
|
||||
}
|
||||
if s.Doc != nil {
|
||||
p.Preamble += doc.CommentText(s.Doc) + "\n";
|
||||
}
|
||||
else if len(d.Specs) == 1 && d.Doc != nil {
|
||||
p.Preamble += doc.CommentText(d.Doc) + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
error(noPos, `cannot find import "C"`);
|
||||
}
|
||||
|
||||
// Accumulate pointers to uses of C.x.
|
||||
p.Crefs = make([]*Cref, 0, 8);
|
||||
walk(p.AST, p, "prog");
|
||||
return p;
|
||||
}
|
||||
|
||||
func walk(x interface{}, p *Prog, context string) {
|
||||
switch n := x.(type) {
|
||||
case *ast.Expr:
|
||||
if sel, ok := (*n).(*ast.SelectorExpr); ok {
|
||||
// For now, assume that the only instance of capital C is
|
||||
// when used as the imported package identifier.
|
||||
// The parser should take care of scoping in the future,
|
||||
// so that we will be able to distinguish a "top-level C"
|
||||
// from a local C.
|
||||
if l, ok := sel.X.(*ast.Ident); ok && l.Value == "C" {
|
||||
i := len(p.Crefs);
|
||||
if i >= cap(p.Crefs) {
|
||||
new := make([]*Cref, 2*i);
|
||||
for j, v := range p.Crefs {
|
||||
new[j] = v;
|
||||
}
|
||||
p.Crefs = new;
|
||||
}
|
||||
p.Crefs = p.Crefs[0:i+1];
|
||||
p.Crefs[i] = &Cref{
|
||||
Name: sel.Sel.Value,
|
||||
Expr: n,
|
||||
Context: context
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
walk(*n, p, context);
|
||||
|
||||
// everything else just recurs
|
||||
default:
|
||||
error(noPos, "unexpected type %T in walk", x);
|
||||
panic();
|
||||
|
||||
case nil:
|
||||
|
||||
// These are ordered and grouped to match ../../pkg/go/ast/ast.go
|
||||
case *ast.Field:
|
||||
walk(&n.Type, p, "type");
|
||||
case *ast.BadExpr:
|
||||
case *ast.Ident:
|
||||
case *ast.Ellipsis:
|
||||
case *ast.BasicLit:
|
||||
case *ast.StringList:
|
||||
case *ast.FuncLit:
|
||||
walk(n.Type, p, "type");
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.CompositeLit:
|
||||
walk(&n.Type, p, "type");
|
||||
walk(n.Elts, p, "expr");
|
||||
case *ast.ParenExpr:
|
||||
walk(&n.X, p, context);
|
||||
case *ast.SelectorExpr:
|
||||
walk(&n.X, p, "selector");
|
||||
case *ast.IndexExpr:
|
||||
walk(&n.X, p, "expr");
|
||||
walk(&n.Index, p, "expr");
|
||||
if n.End != nil {
|
||||
walk(&n.End, p, "expr");
|
||||
}
|
||||
case *ast.TypeAssertExpr:
|
||||
walk(&n.X, p, "expr");
|
||||
walk(&n.Type, p, "type");
|
||||
case *ast.CallExpr:
|
||||
walk(&n.Fun, p, "call");
|
||||
walk(n.Args, p, "expr");
|
||||
case *ast.StarExpr:
|
||||
walk(&n.X, p, context);
|
||||
case *ast.UnaryExpr:
|
||||
walk(&n.X, p, "expr");
|
||||
case *ast.BinaryExpr:
|
||||
walk(&n.X, p, "expr");
|
||||
walk(&n.Y, p, "expr");
|
||||
case *ast.KeyValueExpr:
|
||||
walk(&n.Key, p, "expr");
|
||||
walk(&n.Value, p, "expr");
|
||||
|
||||
case *ast.ArrayType:
|
||||
walk(&n.Len, p, "expr");
|
||||
walk(&n.Elt, p, "type");
|
||||
case *ast.StructType:
|
||||
walk(n.Fields, p, "field");
|
||||
case *ast.FuncType:
|
||||
walk(n.Params, p, "field");
|
||||
walk(n.Results, p, "field");
|
||||
case *ast.InterfaceType:
|
||||
walk(n.Methods, p, "field");
|
||||
case *ast.MapType:
|
||||
walk(&n.Key, p, "type");
|
||||
walk(&n.Value, p, "type");
|
||||
case *ast.ChanType:
|
||||
walk(&n.Value, p, "type");
|
||||
|
||||
case *ast.BadStmt:
|
||||
case *ast.DeclStmt:
|
||||
walk(n.Decl, p, "decl");
|
||||
case *ast.EmptyStmt:
|
||||
case *ast.LabeledStmt:
|
||||
walk(n.Stmt, p, "stmt");
|
||||
case *ast.ExprStmt:
|
||||
walk(&n.X, p, "expr");
|
||||
case *ast.IncDecStmt:
|
||||
walk(&n.X, p, "expr");
|
||||
case *ast.AssignStmt:
|
||||
walk(n.Lhs, p, "expr");
|
||||
walk(n.Rhs, p, "expr");
|
||||
case *ast.GoStmt:
|
||||
walk(&n.Call, p, "expr");
|
||||
case *ast.DeferStmt:
|
||||
walk(&n.Call, p, "expr");
|
||||
case *ast.ReturnStmt:
|
||||
walk(n.Results, p, "expr");
|
||||
case *ast.BranchStmt:
|
||||
case *ast.BlockStmt:
|
||||
walk(n.List, p, "stmt");
|
||||
case *ast.IfStmt:
|
||||
walk(n.Init, p, "stmt");
|
||||
walk(&n.Cond, p, "expr");
|
||||
walk(n.Body, p, "stmt");
|
||||
walk(n.Else, p, "stmt");
|
||||
case *ast.CaseClause:
|
||||
walk(n.Values, p, "expr");
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.SwitchStmt:
|
||||
walk(n.Init, p, "stmt");
|
||||
walk(&n.Tag, p, "expr");
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.TypeCaseClause:
|
||||
walk(n.Types, p, "type");
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.TypeSwitchStmt:
|
||||
walk(n.Init, p, "stmt");
|
||||
walk(n.Assign, p, "stmt");
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.CommClause:
|
||||
walk(n.Lhs, p, "expr");
|
||||
walk(n.Rhs, p, "expr");
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.SelectStmt:
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.ForStmt:
|
||||
walk(n.Init, p, "stmt");
|
||||
walk(&n.Cond, p, "expr");
|
||||
walk(n.Post, p, "stmt");
|
||||
walk(n.Body, p, "stmt");
|
||||
case *ast.RangeStmt:
|
||||
walk(&n.Key, p, "expr");
|
||||
walk(&n.Value, p, "expr");
|
||||
walk(&n.X, p, "expr");
|
||||
walk(n.Body, p, "stmt");
|
||||
|
||||
case *ast.ImportSpec:
|
||||
case *ast.ValueSpec:
|
||||
walk(&n.Type, p, "type");
|
||||
walk(n.Values, p, "expr");
|
||||
case *ast.TypeSpec:
|
||||
walk(&n.Type, p, "type");
|
||||
|
||||
case *ast.BadDecl:
|
||||
case *ast.GenDecl:
|
||||
walk(n.Specs, p, "spec");
|
||||
case *ast.FuncDecl:
|
||||
if n.Recv != nil {
|
||||
walk(n.Recv, p, "field");
|
||||
}
|
||||
walk(n.Type, p, "type");
|
||||
walk(n.Body, p, "stmt");
|
||||
|
||||
case *ast.File:
|
||||
walk(n.Decls, p, "decl");
|
||||
|
||||
case *ast.Package:
|
||||
for _, f := range n.Files {
|
||||
walk(f, p, "file");
|
||||
}
|
||||
|
||||
case []ast.Decl:
|
||||
for _, d := range n {
|
||||
walk(d, p, context);
|
||||
}
|
||||
case []ast.Expr:
|
||||
for i := range n {
|
||||
walk(&n[i], p, context);
|
||||
}
|
||||
case []*ast.Field:
|
||||
for _, f := range n {
|
||||
walk(f, p, context);
|
||||
}
|
||||
case []ast.Stmt:
|
||||
for _, s := range n {
|
||||
walk(s, p, context);
|
||||
}
|
||||
case []ast.Spec:
|
||||
for _, s := range n {
|
||||
walk(s, p, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue