1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
16 // run runs the command argv, feeding in stdin on standard input.
17 // It returns the output to standard output and standard error.
18 // ok indicates whether the command exited successfully.
19 func run(stdin
[]byte, argv
[]string) (stdout
, stderr
[]byte, ok
bool) {
20 if i
:= find(argv
, "-xc"); i
>= 0 && argv
[len(argv
)-1] == "-" {
21 // Some compilers have trouble with standard input.
22 // Others have trouble with -xc.
23 // Avoid both problems by writing a file with a .c extension.
24 f
, err
:= ioutil
.TempFile("", "cgo-gcc-input-")
30 if err
:= ioutil
.WriteFile(name
+".c", stdin
, 0666); err
!= nil {
35 defer os
.Remove(name
+ ".c")
37 // Build new argument list without -xc and trailing -.
38 new := append(argv
[:i
:i
], argv
[i
+1:len(argv
)-1]...)
40 // Since we are going to write the file to a temporary directory,
41 // we will need to add -I . explicitly to the command line:
42 // any #include "foo" before would have looked in the current
43 // directory as the directory "holding" standard input, but now
44 // the temporary directory holds the input.
45 // We've also run into compilers that reject "-I." but allow "-I", ".",
46 // so be sure to use two arguments.
47 // This matters mainly for people invoking cgo -godefs by hand.
48 new = append(new, "-I", ".")
50 // Finish argument list with path to C file.
51 new = append(new, name
+".c")
57 p
:= exec
.Command(argv
[0], argv
[1:]...)
58 p
.Stdin
= bytes
.NewReader(stdin
)
59 var bout
, berr bytes
.Buffer
63 if _
, ok
:= err
.(*exec
.ExitError
); err
!= nil && !ok
{
66 ok
= p
.ProcessState
.Success()
67 stdout
, stderr
= bout
.Bytes(), berr
.Bytes()
71 func find(argv
[]string, target
string) int {
72 for i
, arg
:= range argv
{
80 func lineno(pos token
.Pos
) string {
81 return fset
.Position(pos
).String()
84 // Die with an error message.
85 func fatalf(msg
string, args
...interface{}) {
86 // If we've already printed other errors, they might have
87 // caused the fatal condition. Assume they're enough.
89 fmt
.Fprintf(os
.Stderr
, msg
+"\n", args
...)
96 func error_(pos token
.Pos
, msg
string, args
...interface{}) {
99 fmt
.Fprintf(os
.Stderr
, "%s: ", fset
.Position(pos
).String())
101 fmt
.Fprintf(os
.Stderr
, msg
, args
...)
102 fmt
.Fprintf(os
.Stderr
, "\n")
105 // isName reports whether s is a valid C identifier
106 func isName(s
string) bool {
107 for i
, v
:= range s
{
108 if v
!= '_' && (v
< 'A' || v
> 'Z') && (v
< 'a' || v
> 'z') && (v
< '0' || v
> '9') {
111 if i
== 0 && '0' <= v
&& v
<= '9' {
118 func creat(name
string) *os
.File
{
119 f
, err
:= os
.Create(name
)
126 func slashToUnderscore(c rune
) rune
{
127 if c
== '/' || c
== '\\' || c
== ':' {