summaryrefslogtreecommitdiff
path: root/src/cmd/cgo/main.go
blob: 8202b8e2bccf43e9889c49ce2299cd214c1cae47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// 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.

// Cgo; see gmp.go for an overview.

// TODO(rsc):
//	Emit correct line number annotations.
//	Make 6g understand the annotations.

package main

import (
	"fmt";
	"go/ast";
	"os";
)

func usage()	{ fmt.Fprint(os.Stderr, "usage: cgo [compiler options] file.go\n") }

var ptrSizeMap = map[string]int64{
	"386": 4,
	"amd64": 8,
	"arm": 4,
}

var expandName = map[string]string{
	"schar": "signed char",
	"uchar": "unsigned char",
	"ushort": "unsigned short",
	"uint": "unsigned int",
	"ulong": "unsigned long",
	"longlong": "long long",
	"ulonglong": "unsigned long long",
}

func main() {
	args := os.Args;
	if len(args) < 2 {
		usage();
		os.Exit(2);
	}
	gccOptions := args[1 : len(args)-1];
	input := args[len(args)-1];

	arch := os.Getenv("GOARCH");
	if arch == "" {
		fatal("$GOARCH is not set")
	}
	ptrSize, ok := ptrSizeMap[arch];
	if !ok {
		fatal("unknown architecture %s", arch)
	}

	// Clear locale variables so gcc emits English errors [sic].
	os.Setenv("LANG", "en_US.UTF-8");
	os.Setenv("LC_ALL", "C");
	os.Setenv("LC_CTYPE", "C");

	p := openProg(input);
	for _, cref := range p.Crefs {
		// Convert C.ulong to C.unsigned long, etc.
		if expand, ok := expandName[cref.Name]; ok {
			cref.Name = expand
		}
	}

	p.PtrSize = ptrSize;
	p.Preamble = p.Preamble + "\n" + builtinProlog;
	p.GccOptions = gccOptions;
	p.loadDebugInfo();
	p.Vardef = make(map[string]*Type);
	p.Funcdef = make(map[string]*FuncType);

	for _, cref := range p.Crefs {
		switch cref.Context {
		case "call":
			if !cref.TypeName {
				// Is an actual function call.
				*cref.Expr = &ast.Ident{Value: "_C_" + cref.Name};
				p.Funcdef[cref.Name] = cref.FuncType;
				break;
			}
			*cref.Expr = cref.Type.Go;
		case "expr":
			if cref.TypeName {
				error((*cref.Expr).Pos(), "type C.%s used as expression", cref.Name)
			}
			// Reference to C variable.
			// We declare a pointer and arrange to have it filled in.
			*cref.Expr = &ast.StarExpr{X: &ast.Ident{Value: "_C_" + cref.Name}};
			p.Vardef[cref.Name] = cref.Type;
		case "type":
			if !cref.TypeName {
				error((*cref.Expr).Pos(), "expression C.%s used as type", cref.Name)
			}
			*cref.Expr = cref.Type.Go;
		}
	}
	if nerrors > 0 {
		os.Exit(2)
	}

	p.PackagePath = os.Getenv("CGOPKGPATH") + "/" + p.Package;
	p.writeOutput(input);
}