...

Source file src/cmd/cgo/util.go

     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.
     4	
     5	package main
     6	
     7	import (
     8		"bytes"
     9		"fmt"
    10		"go/token"
    11		"io/ioutil"
    12		"os"
    13		"os/exec"
    14	)
    15	
    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-")
    25			if err != nil {
    26				fatalf("%s", err)
    27			}
    28			name := f.Name()
    29			f.Close()
    30			if err := ioutil.WriteFile(name+".c", stdin, 0666); err != nil {
    31				os.Remove(name)
    32				fatalf("%s", err)
    33			}
    34			defer os.Remove(name)
    35			defer os.Remove(name + ".c")
    36	
    37			// Build new argument list without -xc and trailing -.
    38			new := append(argv[:i:i], argv[i+1:len(argv)-1]...)
    39	
    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", ".")
    49	
    50			// Finish argument list with path to C file.
    51			new = append(new, name+".c")
    52	
    53			argv = new
    54			stdin = nil
    55		}
    56	
    57		p := exec.Command(argv[0], argv[1:]...)
    58		p.Stdin = bytes.NewReader(stdin)
    59		var bout, berr bytes.Buffer
    60		p.Stdout = &bout
    61		p.Stderr = &berr
    62		// Disable escape codes in clang error messages.
    63		p.Env = append(os.Environ(), "TERM=dumb")
    64		err := p.Run()
    65		if _, ok := err.(*exec.ExitError); err != nil && !ok {
    66			fatalf("%s", err)
    67		}
    68		ok = p.ProcessState.Success()
    69		stdout, stderr = bout.Bytes(), berr.Bytes()
    70		return
    71	}
    72	
    73	func find(argv []string, target string) int {
    74		for i, arg := range argv {
    75			if arg == target {
    76				return i
    77			}
    78		}
    79		return -1
    80	}
    81	
    82	func lineno(pos token.Pos) string {
    83		return fset.Position(pos).String()
    84	}
    85	
    86	// Die with an error message.
    87	func fatalf(msg string, args ...interface{}) {
    88		// If we've already printed other errors, they might have
    89		// caused the fatal condition. Assume they're enough.
    90		if nerrors == 0 {
    91			fmt.Fprintf(os.Stderr, msg+"\n", args...)
    92		}
    93		os.Exit(2)
    94	}
    95	
    96	var nerrors int
    97	
    98	func error_(pos token.Pos, msg string, args ...interface{}) {
    99		nerrors++
   100		if pos.IsValid() {
   101			fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String())
   102		} else {
   103			fmt.Fprintf(os.Stderr, "cgo: ")
   104		}
   105		fmt.Fprintf(os.Stderr, msg, args...)
   106		fmt.Fprintf(os.Stderr, "\n")
   107	}
   108	
   109	// isName reports whether s is a valid C identifier
   110	func isName(s string) bool {
   111		for i, v := range s {
   112			if v != '_' && (v < 'A' || v > 'Z') && (v < 'a' || v > 'z') && (v < '0' || v > '9') {
   113				return false
   114			}
   115			if i == 0 && '0' <= v && v <= '9' {
   116				return false
   117			}
   118		}
   119		return s != ""
   120	}
   121	
   122	func creat(name string) *os.File {
   123		f, err := os.Create(name)
   124		if err != nil {
   125			fatalf("%s", err)
   126		}
   127		return f
   128	}
   129	
   130	func slashToUnderscore(c rune) rune {
   131		if c == '/' || c == '\\' || c == ':' {
   132			c = '_'
   133		}
   134		return c
   135	}
   136	

View as plain text