var debugDefine … var debugGcc … var nameToC … var incomplete … // cname returns the C name to use for C.s. // The expansions are listed in nameToC and also // struct_foo becomes "struct foo", and similarly for // union and enum. func cname(s string) string { … } // ProcessCgoDirectives processes the import C preamble: // 1. discards all #cgo CFLAGS, LDFLAGS, nocallback and noescape directives, // so they don't make their way into _cgo_export.h. // 2. parse the nocallback and noescape directives. func (f *File) ProcessCgoDirectives() { … } // addToFlag appends args to flag. func (p *Package) addToFlag(flag string, args []string) { … } // splitQuoted splits the string s around each instance of one or more consecutive // white space characters while taking into account quotes and escaping, and // returns an array of substrings of s or an empty list if s contains only white space. // Single quotes and double quotes are recognized to prevent splitting within the // quoted region, and are removed from the resulting substrings. If a quote in s // isn't closed err will be set and r will have the unclosed argument as the // last element. The backslash is used for escaping. // // For example, the following string: // // `a b:"c d" 'e''f' "g\""` // // Would be parsed as: // // []string{"a", "b:c d", "ef", `g"`} func splitQuoted(s string) (r []string, err error) { … } // Translate rewrites f.AST, the original Go input, to remove // references to the imported package C, replacing them with // references to the equivalent Go types, functions, and variables. func (p *Package) Translate(f *File) { … } // loadDefines coerces gcc into spitting out the #defines in use // in the file f and saves relevant renamings in f.Name[name].Define. // Returns true if env:CC is Clang func (f *File) loadDefines(gccOptions []string) bool { … } // guessKinds tricks gcc into revealing the kind of each // name xxx for the references C.xxx in the Go input. // The kind is either a constant, type, or variable. func (p *Package) guessKinds(f *File) []*Name { … } // loadDWARF parses the DWARF debug information generated // by gcc to learn the details of the constants, variables, and types // being referred to as C.xxx. func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) { … } // recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children. func (p *Package) recordTypedefs(dtype dwarf.Type, pos token.Pos) { … } func (p *Package) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[dwarf.Type]bool) { … } // prepareNames finalizes the Kind field of not-type names and sets // the mangled name of all names. func (p *Package) prepareNames(f *File) { … } // mangleName does name mangling to translate names // from the original Go source files to the names // used in the final Go files generated by cgo. func (p *Package) mangleName(n *Name) { … } func (f *File) isMangledName(s string) bool { … } // rewriteCalls rewrites all calls that pass pointers to check that // they follow the rules for passing pointers between Go and C. // This reports whether the package needs to import unsafe as _cgo_unsafe. func (p *Package) rewriteCalls(f *File) bool { … } // rewriteCall rewrites one call to add pointer checks. // If any pointer checks are required, we rewrite the call into a // function literal that calls _cgoCheckPointer for each pointer // argument and then calls the original function. // This returns the rewritten call and whether the package needs to // import unsafe as _cgo_unsafe. // If it returns the empty string, the call did not need to be rewritten. func (p *Package) rewriteCall(f *File, call *Call) (string, bool) { … } // needsPointerCheck reports whether the type t needs a pointer check. // This is true if t is a pointer and if the value to which it points // might contain a pointer. func (p *Package) needsPointerCheck(f *File, t ast.Expr, arg ast.Expr) bool { … } // hasPointer is used by needsPointerCheck. If top is true it returns // whether t is or contains a pointer that might point to a pointer. // If top is false it reports whether t is or contains a pointer. // f may be nil. func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool { … } // mangle replaces references to C names in arg with the mangled names, // rewriting calls when it finds them. // It removes the corresponding references in f.Ref and f.Calls, so that we // don't try to do the replacement again in rewriteRef or rewriteCall. // If addPosition is true, add position info to the idents of C names in arg. func (p *Package) mangle(f *File, arg *ast.Expr, addPosition bool) (ast.Expr, bool) { … } // checkIndex checks whether arg has the form &a[i], possibly inside // type conversions. If so, then in the general case it writes // // _cgoIndexNN := a // _cgoNN := &cgoIndexNN[i] // with type conversions, if any // // to sb, and writes // // _cgoCheckPointer(_cgoNN, _cgoIndexNN) // // to sbCheck, and returns true. If a is a simple variable or field reference, // it writes // // _cgoIndexNN := &a // // and dereferences the uses of _cgoIndexNN. Taking the address avoids // making a copy of an array. // // This tells _cgoCheckPointer to check the complete contents of the // slice or array being indexed, but no other part of the memory allocation. func (p *Package) checkIndex(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool { … } // checkAddr checks whether arg has the form &x, possibly inside type // conversions. If so, it writes // // _cgoBaseNN := &x // _cgoNN := _cgoBaseNN // with type conversions, if any // // to sb, and writes // // _cgoCheckPointer(_cgoBaseNN, true) // // to sbCheck, and returns true. This tells _cgoCheckPointer to check // just the contents of the pointer being passed, not any other part // of the memory allocation. This is run after checkIndex, which looks // for the special case of &a[i], which requires different checks. func (p *Package) checkAddr(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool { … } // checkSlice checks whether arg has the form x[i:j], possibly inside // type conversions. If so, it writes // // _cgoSliceNN := x[i:j] // _cgoNN := _cgoSliceNN // with type conversions, if any // // to sb, and writes // // _cgoCheckPointer(_cgoSliceNN, true) // // to sbCheck, and returns true. This tells _cgoCheckPointer to check // just the contents of the slice being passed, not any other part // of the memory allocation. func (p *Package) checkSlice(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool { … } // checkUnsafeStringData checks for a call to unsafe.StringData. // The result of that call can't contain a pointer so there is // no need to call _cgoCheckPointer. func (p *Package) checkUnsafeStringData(arg ast.Expr) bool { … } // isType reports whether the expression is definitely a type. // This is conservative--it returns false for an unknown identifier. func (p *Package) isType(t ast.Expr) bool { … } // isUnsafeData reports whether the expression is unsafe.StringData // or unsafe.SliceData. We can ignore these when checking for pointers // because they don't change whether or not their argument contains // any Go pointers. If onlyStringData is true we only check for StringData. func (p *Package) isUnsafeData(x ast.Expr, onlyStringData bool) bool { … } // isVariable reports whether x is a variable, possibly with field references. func (p *Package) isVariable(x ast.Expr) bool { … } // rewriteUnsafe returns a version of t with references to unsafe.Pointer // rewritten to use _cgo_unsafe.Pointer instead. func (p *Package) rewriteUnsafe(t ast.Expr) ast.Expr { … } // rewriteRef rewrites all the C.xxx references in f.AST to refer to the // Go equivalents, now that we have figured out the meaning of all // the xxx. In *godefs mode, rewriteRef replaces the names // with full definitions instead of mangled names. func (p *Package) rewriteRef(f *File) { … } // rewriteName returns the expression used to rewrite a reference. // If addPosition is true, add position info in the ident name. func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr { … } // gofmtPos returns the gofmt-formatted string for an AST node, // with a comment setting the position before the node. func gofmtPos(n ast.Expr, pos token.Pos) string { … } // checkGCCBaseCmd returns the start of the compiler command line. // It uses $CC if set, or else $GCC, or else the compiler recorded // during the initial build as defaultCC. // defaultCC is defined in zdefaultcc.go, written by cmd/dist. // // The compiler command line is split into arguments on whitespace. Quotes // are understood, so arguments may contain whitespace. // // checkGCCBaseCmd confirms that the compiler exists in PATH, returning // an error if it does not. func checkGCCBaseCmd() ([]string, error) { … } // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". func gccMachine() []string { … } func gccTmp() string { … } // gccCmd returns the gcc command line to use for compiling // the input. func (p *Package) gccCmd() []string { … } // gccDebug runs gcc -gdwarf-2 over the C program stdin and // returns the corresponding DWARF data and, if present, debug data block. func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) { … } // gccDefines runs gcc -E -dM -xc - over the C program stdin // and returns the corresponding standard output, which is the // #defines that gcc encountered while processing the input // and its included files. func gccDefines(stdin []byte, gccOptions []string) string { … } // gccErrors runs gcc over the C program stdin and returns // the errors that gcc prints. That is, this function expects // gcc to fail. func (p *Package) gccErrors(stdin []byte, extraArgs ...string) string { … } // runGcc runs the gcc command line args with stdin on standard input. // If the command exits with a non-zero exit status, runGcc prints // details about what was run and exits. // Otherwise runGcc returns the data written to standard output and standard error. // Note that for some of the uses we expect useful data back // on standard error, but for those uses gcc must still exit 0. func runGcc(stdin []byte, args []string) (string, string) { … } type typeConv … var tagGen … var typedef … var goIdent … var unionWithPointer … var anonymousStructTag … func (c *typeConv) Init(ptrSize, intSize int64) { … } // base strips away qualifiers and typedefs to get the underlying type. func base(dt dwarf.Type) dwarf.Type { … } // unqual strips away qualifiers from a DWARF type. // In general we don't care about top-level qualifiers. func unqual(dt dwarf.Type) dwarf.Type { … } var dwarfToName … const signedDelta … // String returns the current type representation. Format arguments // are assembled within this method so that any changes in mutable // values are taken into account. func (tr *TypeRepr) String() string { … } // Empty reports whether the result of String would be "". func (tr *TypeRepr) Empty() bool { … } // Set modifies the type representation. // If fargs are provided, repr is used as a format for fmt.Sprintf. // Otherwise, repr is used unprocessed as the type representation. func (tr *TypeRepr) Set(repr string, fargs ...interface{ … } // FinishType completes any outstanding type mapping work. // In particular, it resolves incomplete pointer types. func (c *typeConv) FinishType(pos token.Pos) { … } // Type returns a *Type with the same memory layout as // dtype when used as the type of a variable or a struct field. func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { … } // loadType recursively loads the requested dtype and its dependency graph. func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Type { … } // isStructUnionClass reports whether the type described by the Go syntax x // is a struct, union, or class with a tag. func isStructUnionClass(x ast.Expr) bool { … } // FuncArg returns a Go type with the same memory layout as // dtype when used as the type of a C function argument. func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { … } // FuncType returns the Go type analogous to dtype. // There is no guarantee about matching memory layout. func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType { … } // Identifier func (c *typeConv) Ident(s string) *ast.Ident { … } // Opaque type of n bytes. func (c *typeConv) Opaque(n int64) ast.Expr { … } // Expr for integer n. func (c *typeConv) intExpr(n int64) ast.Expr { … } // Add padding of given size to fld. func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) { … } // Struct conversion: return Go and (gc) C syntax for type. func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) { … } // dwarfHasPointer reports whether the DWARF type dt contains a pointer. func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool { … } func upper(s string) string { … } // godefsFields rewrites field names for use in Go or C definitions. // It strips leading common prefixes (like tv_ in tv_sec, tv_usec) // converts names to upper case, and rewrites _ into Pad_godefs_n, // so that all fields are exported. func godefsFields(fld []*ast.Field) { … } // fieldPrefix returns the prefix that should be removed from all the // field names when generating the C or Go code. For generated // C, we leave the names as is (tv_sec, tv_usec), since that's what // people are used to seeing in C. For generated Go code, such as // package syscall's data structures, we drop a common prefix // (so sec, usec, which will get turned into Sec, Usec for exporting). func fieldPrefix(fld []*ast.Field) string { … } // anonymousStructTypedef reports whether dt is a C typedef for an anonymous // struct. func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool { … } // badPointerTypedef reports whether dt is a C typedef that should not be // considered a pointer in Go. A typedef is bad if C code sometimes stores // non-pointers in this type. // TODO: Currently our best solution is to find these manually and list them as // they come up. A better solution is desired. // Note: DEPRECATED. There is now a better solution. Search for incomplete in this file. func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { … } // badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be _cgopackage.Incomplete. func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool { … } // badStructPointerTypedef is like badVoidPointerTypedef but for structs. func (c *typeConv) badStructPointerTypedef(name string, dt *dwarf.StructType) bool { … } // baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef // as badPointerTypedef reports. func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool { … } func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool { … } func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool { … } func (c *typeConv) badEGLType(dt *dwarf.TypedefType) bool { … } var jniTypes …