Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(778)

Delta Between Two Patch Sets: src/cmd/cgo/gcc.go

Issue 3921043: code review 3921043: cgo: CGO_CFLAGS and CGO_LDFLAGS support (Closed)
Left Patch Set: code review 3921043: cgo: CGO_CFLAGS and CGO_LDFLAGS support Created 14 years, 2 months ago
Right Patch Set: code review 3921043: cgo: CGO_CFLAGS and CGO_LDFLAGS support Created 14 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/cmd/cgo/doc.go ('k') | src/cmd/cgo/main.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Annotate Ref in Prog with C types by parsing gcc debug output. 5 // Annotate Ref in Prog with C types by parsing gcc debug output.
6 // Conversion of debug output to Go types. 6 // Conversion of debug output to Go types.
7 7
8 package main 8 package main
9 9
10 import ( 10 import (
(...skipping 10 matching lines...) Expand all
21 "os" 21 "os"
22 "strconv" 22 "strconv"
23 "strings" 23 "strings"
24 "unicode" 24 "unicode"
25 ) 25 )
26 26
27 var debugDefine = flag.Bool("debug-define", false, "print relevant #defines") 27 var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
28 var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations") 28 var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")
29 29
30 var nameToC = map[string]string{ 30 var nameToC = map[string]string{
31 » "schar": "signed char", 31 » "schar": "signed char",
32 » "uchar": "unsigned char", 32 » "uchar": "unsigned char",
33 » "ushort": "unsigned short", 33 » "ushort": "unsigned short",
34 » "uint": "unsigned int", 34 » "uint": "unsigned int",
35 » "ulong": "unsigned long", 35 » "ulong": "unsigned long",
36 » "longlong": "long long", 36 » "longlong": "long long",
37 » "ulonglong": "unsigned long long", 37 » "ulonglong": "unsigned long long",
38 » "complexfloat": "float complex",
39 » "complexdouble": "double complex",
38 } 40 }
39 41
40 // cname returns the C name to use for C.s. 42 // cname returns the C name to use for C.s.
41 // The expansions are listed in nameToC and also 43 // The expansions are listed in nameToC and also
42 // struct_foo becomes "struct foo", and similarly for 44 // struct_foo becomes "struct foo", and similarly for
43 // union and enum. 45 // union and enum.
44 func cname(s string) string { 46 func cname(s string) string {
45 if t, ok := nameToC[s]; ok { 47 if t, ok := nameToC[s]; ok {
46 return t 48 return t
47 } 49 }
(...skipping 27 matching lines...) Expand all
75 fields := strings.Split(l, ":", 2) 77 fields := strings.Split(l, ":", 2)
76 if len(fields) != 2 { 78 if len(fields) != 2 {
77 fatal("%s: bad #cgo line: %s", srcfile, line) 79 fatal("%s: bad #cgo line: %s", srcfile, line)
78 } 80 }
79 81
80 k := fields[0] 82 k := fields[0]
81 v := strings.TrimSpace(fields[1]) 83 v := strings.TrimSpace(fields[1])
82 if k != "CFLAGS" && k != "LDFLAGS" { 84 if k != "CFLAGS" && k != "LDFLAGS" {
83 fatal("%s: unsupported #cgo option %s", srcfile, k) 85 fatal("%s: unsupported #cgo option %s", srcfile, k)
84 } 86 }
87 args, err := splitQuoted(v)
88 if err != nil {
89 fatal("%s: bad #cgo option %s: %s", srcfile, k, err.Stri ng())
90 }
85 if oldv, ok := p.CgoFlags[k]; ok { 91 if oldv, ok := p.CgoFlags[k]; ok {
86 p.CgoFlags[k] = oldv + " " + v 92 p.CgoFlags[k] = oldv + " " + v
87 } else { 93 } else {
88 p.CgoFlags[k] = v 94 p.CgoFlags[k] = v
89 } 95 }
90 if k == "CFLAGS" { 96 if k == "CFLAGS" {
91 » » » p.GccOptions = append(p.GccOptions, splitArgs(v)...) 97 » » » p.GccOptions = append(p.GccOptions, args...)
92 } 98 }
93 } 99 }
94 f.Preamble = strings.Join(linesOut, "\n") 100 f.Preamble = strings.Join(linesOut, "\n")
95 } 101 }
96 102
97 // splitArgs returns the string splitted in the same way 103 // splitQuoted splits the string s around each instance of one or more consecuti ve
98 // a shell splits arguments in the command line. 104 // white space characters while taking into account quotes and escaping, and
105 // returns an array of substrings of s or an empty list if s contains only white space.
106 // Single quotes and double quotes are recognized to prevent splitting within th e
107 // quoted region, and are removed from the resulting substrings. If a quote in s
108 // isn't closed err will be set and r will have the unclosed argument as the
109 // last element. The backslash is used for escaping.
99 // 110 //
100 // TODO(niemeyer): This looks like a handy function to have 111 // For example, the following string:
101 // available, and should probably be moved into the stdlib. 112 //
102 func splitArgs(s string) []string { 113 // `a b:"c d" 'e''f' "g\""`
103 » args := make([]string, 0, len(s)) 114 //
115 // Would be parsed as:
116 //
117 // []string{"a", "b:c d", "ef", `g"`}
118 //
119 func splitQuoted(s string) (r []string, err os.Error) {
120 » var args []string
104 arg := make([]int, len(s)) 121 arg := make([]int, len(s))
105 escaped := false 122 escaped := false
123 quoted := false
106 quote := 0 124 quote := 0
107 i := 0 125 i := 0
108 for _, rune := range s { 126 for _, rune := range s {
109 switch { 127 switch {
110 case escaped: 128 case escaped:
111 escaped = false 129 escaped = false
112 » » case rune == int('\\'): 130 » » case rune == '\\':
113 escaped = true 131 escaped = true
114 continue 132 continue
115 case quote != 0: 133 case quote != 0:
116 if rune == quote { 134 if rune == quote {
117 quote = 0 135 quote = 0
118 continue 136 continue
119 } 137 }
120 » » case rune == int('"') || rune == int('\''): 138 » » case rune == '"' || rune == '\'':
139 » » » quoted = true
121 quote = rune 140 quote = rune
122 continue 141 continue
123 case unicode.IsSpace(rune): 142 case unicode.IsSpace(rune):
124 » » » if i > 0 { 143 » » » if quoted || i > 0 {
144 » » » » quoted = false
125 args = append(args, string(arg[:i])) 145 args = append(args, string(arg[:i]))
126 i = 0 146 i = 0
127 } 147 }
128 continue 148 continue
129 } 149 }
130 arg[i] = rune 150 arg[i] = rune
131 i++ 151 i++
132 } 152 }
133 » if i > 0 { 153 » if quoted || i > 0 {
134 args = append(args, string(arg[:i])) 154 args = append(args, string(arg[:i]))
135 } 155 }
136 » return args 156 » if quote != 0 {
157 » » err = os.ErrorString("unclosed quote")
158 » } else if escaped {
159 » » err = os.ErrorString("unfinished escaping")
160 » }
161 » return args, err
137 } 162 }
138 163
139 // Translate rewrites f.AST, the original Go input, to remove 164 // Translate rewrites f.AST, the original Go input, to remove
140 // references to the imported package C, replacing them with 165 // references to the imported package C, replacing them with
141 // references to the equivalent Go types, functions, and variables. 166 // references to the equivalent Go types, functions, and variables.
142 func (p *Package) Translate(f *File) { 167 func (p *Package) Translate(f *File) {
143 for _, cref := range f.Ref { 168 for _, cref := range f.Ref {
144 // Convert C.ulong to C.unsigned long, etc. 169 // Convert C.ulong to C.unsigned long, etc.
145 cref.Name.C = cname(cref.Name.Go) 170 cref.Name.C = cname(cref.Name.Go)
146 } 171 }
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 names := make([]*Name, len(toSniff)) 302 names := make([]*Name, len(toSniff))
278 copy(names, toSniff) 303 copy(names, toSniff)
279 304
280 isConst := make([]bool, len(toSniff)) 305 isConst := make([]bool, len(toSniff))
281 for i := range isConst { 306 for i := range isConst {
282 isConst[i] = true // until proven otherwise 307 isConst[i] = true // until proven otherwise
283 } 308 }
284 309
285 for _, line := range strings.Split(stderr, "\n", -1) { 310 for _, line := range strings.Split(stderr, "\n", -1) {
286 if len(line) < 9 || line[0:9] != "cgo-test:" { 311 if len(line) < 9 || line[0:9] != "cgo-test:" {
287 » » » if len(line) > 8 && line[0:8] == "<stdin>:" { 312 » » » // the user will see any compiler errors when the code i s compiled later.
288 » » » » fatal("gcc produced unexpected output:\n%s\non i nput:\n%s", line, b.Bytes())
289 » » » }
290 continue 313 continue
291 } 314 }
292 line = line[9:] 315 line = line[9:]
293 colon := strings.Index(line, ":") 316 colon := strings.Index(line, ":")
294 if colon < 0 { 317 if colon < 0 {
295 continue 318 continue
296 } 319 }
297 i, err := strconv.Atoi(line[0:colon]) 320 i, err := strconv.Atoi(line[0:colon])
298 if err != nil { 321 if err != nil {
299 continue 322 continue
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " ")) 663 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
641 os.Stderr.Write(stdin) 664 os.Stderr.Write(stdin)
642 fmt.Fprint(os.Stderr, "EOF\n") 665 fmt.Fprint(os.Stderr, "EOF\n")
643 } 666 }
644 stdout, stderr, ok := run(stdin, args) 667 stdout, stderr, ok := run(stdin, args)
645 if *debugGcc { 668 if *debugGcc {
646 os.Stderr.Write(stdout) 669 os.Stderr.Write(stdout)
647 os.Stderr.Write(stderr) 670 os.Stderr.Write(stderr)
648 } 671 }
649 if !ok { 672 if !ok {
650 fmt.Fprint(os.Stderr, "Error running gcc:\n")
651 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
652 os.Stderr.Write(stdin)
653 fmt.Fprint(os.Stderr, "EOF\n")
654 os.Stderr.Write(stderr) 673 os.Stderr.Write(stderr)
655 os.Exit(2) 674 os.Exit(2)
656 } 675 }
657 return string(stdout), string(stderr) 676 return string(stdout), string(stderr)
658 } 677 }
659 678
660 // A typeConv is a translator from dwarf types to Go types 679 // A typeConv is a translator from dwarf types to Go types
661 // with equivalent memory layout. 680 // with equivalent memory layout.
662 type typeConv struct { 681 type typeConv struct {
663 // Cache of already-translated or in-progress types. 682 // Cache of already-translated or in-progress types.
664 m map[dwarf.Type]*Type 683 m map[dwarf.Type]*Type
665 typedef map[string]ast.Expr 684 typedef map[string]ast.Expr
666 685
667 // Predeclared types. 686 // Predeclared types.
668 bool ast.Expr 687 bool ast.Expr
669 byte ast.Expr // denotes padding 688 byte ast.Expr // denotes padding
670 int8, int16, int32, int64 ast.Expr 689 int8, int16, int32, int64 ast.Expr
671 uint8, uint16, uint32, uint64, uintptr ast.Expr 690 uint8, uint16, uint32, uint64, uintptr ast.Expr
672 float32, float64 ast.Expr 691 float32, float64 ast.Expr
692 complex64, complex128 ast.Expr
673 void ast.Expr 693 void ast.Expr
674 unsafePointer ast.Expr 694 unsafePointer ast.Expr
675 string ast.Expr 695 string ast.Expr
676 696
677 ptrSize int64 697 ptrSize int64
678 } 698 }
679 699
680 var tagGen int 700 var tagGen int
681 var typedef = make(map[string]ast.Expr) 701 var typedef = make(map[string]ast.Expr)
682 702
683 func (c *typeConv) Init(ptrSize int64) { 703 func (c *typeConv) Init(ptrSize int64) {
684 c.ptrSize = ptrSize 704 c.ptrSize = ptrSize
685 c.m = make(map[dwarf.Type]*Type) 705 c.m = make(map[dwarf.Type]*Type)
686 c.bool = c.Ident("bool") 706 c.bool = c.Ident("bool")
687 c.byte = c.Ident("byte") 707 c.byte = c.Ident("byte")
688 c.int8 = c.Ident("int8") 708 c.int8 = c.Ident("int8")
689 c.int16 = c.Ident("int16") 709 c.int16 = c.Ident("int16")
690 c.int32 = c.Ident("int32") 710 c.int32 = c.Ident("int32")
691 c.int64 = c.Ident("int64") 711 c.int64 = c.Ident("int64")
692 c.uint8 = c.Ident("uint8") 712 c.uint8 = c.Ident("uint8")
693 c.uint16 = c.Ident("uint16") 713 c.uint16 = c.Ident("uint16")
694 c.uint32 = c.Ident("uint32") 714 c.uint32 = c.Ident("uint32")
695 c.uint64 = c.Ident("uint64") 715 c.uint64 = c.Ident("uint64")
696 c.uintptr = c.Ident("uintptr") 716 c.uintptr = c.Ident("uintptr")
697 c.float32 = c.Ident("float32") 717 c.float32 = c.Ident("float32")
698 c.float64 = c.Ident("float64") 718 c.float64 = c.Ident("float64")
719 c.complex64 = c.Ident("complex64")
720 c.complex128 = c.Ident("complex128")
699 c.unsafePointer = c.Ident("unsafe.Pointer") 721 c.unsafePointer = c.Ident("unsafe.Pointer")
700 c.void = c.Ident("void") 722 c.void = c.Ident("void")
701 c.string = c.Ident("string") 723 c.string = c.Ident("string")
702 } 724 }
703 725
704 // base strips away qualifiers and typedefs to get the underlying type 726 // base strips away qualifiers and typedefs to get the underlying type
705 func base(dt dwarf.Type) dwarf.Type { 727 func base(dt dwarf.Type) dwarf.Type {
706 for { 728 for {
707 if d, ok := dt.(*dwarf.QualType); ok { 729 if d, ok := dt.(*dwarf.QualType); ok {
708 dt = d.Type 730 dt = d.Type
(...skipping 11 matching lines...) Expand all
720 // Map from dwarf text names to aliases we use in package "C". 742 // Map from dwarf text names to aliases we use in package "C".
721 var dwarfToName = map[string]string{ 743 var dwarfToName = map[string]string{
722 "long int": "long", 744 "long int": "long",
723 "long unsigned int": "ulong", 745 "long unsigned int": "ulong",
724 "unsigned int": "uint", 746 "unsigned int": "uint",
725 "short unsigned int": "ushort", 747 "short unsigned int": "ushort",
726 "short int": "short", 748 "short int": "short",
727 "long long int": "longlong", 749 "long long int": "longlong",
728 "long long unsigned int": "ulonglong", 750 "long long unsigned int": "ulonglong",
729 "signed char": "schar", 751 "signed char": "schar",
752 "float complex": "complexfloat",
753 "double complex": "complexdouble",
730 } 754 }
731 755
732 // Type returns a *Type with the same memory layout as 756 // Type returns a *Type with the same memory layout as
733 // dtype when used as the type of a variable or a struct field. 757 // dtype when used as the type of a variable or a struct field.
734 func (c *typeConv) Type(dtype dwarf.Type) *Type { 758 func (c *typeConv) Type(dtype dwarf.Type) *Type {
735 if t, ok := c.m[dtype]; ok { 759 if t, ok := c.m[dtype]; ok {
736 if t.Go == nil { 760 if t.Go == nil {
737 fatal("type conversion loop at %s", dtype) 761 fatal("type conversion loop at %s", dtype)
738 } 762 }
739 return t 763 return t
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 } 840 }
817 841
818 case *dwarf.FloatType: 842 case *dwarf.FloatType:
819 switch t.Size { 843 switch t.Size {
820 default: 844 default:
821 fatal("unexpected: %d-byte float type - %s", t.Size, dty pe) 845 fatal("unexpected: %d-byte float type - %s", t.Size, dty pe)
822 case 4: 846 case 4:
823 t.Go = c.float32 847 t.Go = c.float32
824 case 8: 848 case 8:
825 t.Go = c.float64 849 t.Go = c.float64
850 }
851 if t.Align = t.Size; t.Align >= c.ptrSize {
852 t.Align = c.ptrSize
853 }
854
855 case *dwarf.ComplexType:
856 switch t.Size {
857 default:
858 fatal("unexpected: %d-byte complex type - %s", t.Size, d type)
859 case 8:
860 t.Go = c.complex64
861 case 16:
862 t.Go = c.complex128
826 } 863 }
827 if t.Align = t.Size; t.Align >= c.ptrSize { 864 if t.Align = t.Size; t.Align >= c.ptrSize {
828 t.Align = c.ptrSize 865 t.Align = c.ptrSize
829 } 866 }
830 867
831 case *dwarf.FuncType: 868 case *dwarf.FuncType:
832 // No attempt at translation: would enable calls 869 // No attempt at translation: would enable calls
833 // directly between worlds, but we need to moderate those. 870 // directly between worlds, but we need to moderate those.
834 t.Go = c.uintptr 871 t.Go = c.uintptr
835 t.Align = c.ptrSize 872 t.Align = c.ptrSize
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
1130 off = dt.ByteSize 1167 off = dt.ByteSize
1131 } 1168 }
1132 if off != dt.ByteSize { 1169 if off != dt.ByteSize {
1133 fatal("struct size calculation error") 1170 fatal("struct size calculation error")
1134 } 1171 }
1135 buf.WriteString("}") 1172 buf.WriteString("}")
1136 csyntax = buf.String() 1173 csyntax = buf.String()
1137 expr = &ast.StructType{Fields: &ast.FieldList{List: fld}} 1174 expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
1138 return 1175 return
1139 } 1176 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b