forked from xlab/c-for-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
126 lines (116 loc) · 3.15 KB
/
main.go
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"sync"
"time"
"github.com/tj/go-spin"
)
var (
outputPath = flag.String("out", "", "Specify a `dir` for the output.")
noCGO = flag.Bool("nocgo", false, "Do not include a cgo-specific header in resulting files.")
ccDefs = flag.Bool("ccdefs", false, "Use built-in defines from a hosted C-compiler.")
ccIncl = flag.Bool("ccincl", false, "Use built-in sys include paths from a hosted C-compiler.")
maxMem = flag.String("maxmem", "0x7fffffff", "Specifies platform's memory cap the generated code.")
fancy = flag.Bool("fancy", true, "Enable fancy output in the term.")
nostamp = flag.Bool("nostamp", false, "Disable printing timestamps in the output files.")
debug = flag.Bool("debug", false, "Enable some debug info.")
)
const logo = `Copyright (c) 2015-2017 Maxim Kupriianov <max@kc.vc>
Based on a C99 compiler front end by Jan Mercl <0xjnml@gmail.com>
`
func init() {
if *debug {
log.SetFlags(log.Lshortfile)
} else {
log.SetFlags(0)
}
flag.Usage = func() {
fmt.Println(logo)
fmt.Printf("Usage: %s package1.yml [package2.yml] ...\n", os.Args[0])
fmt.Println("See https://github.com/xlab/c-for-go for examples and documentation.\n")
fmt.Println("Options:")
flag.PrintDefaults()
}
flag.Parse()
if len(flag.Args()) == 0 {
flag.Usage()
fmt.Println()
log.Fatalln("[ERR] no package configuration files have been provided.")
}
}
func main() {
s := spin.New()
var wg sync.WaitGroup
doneChan := make(chan struct{})
for _, cfgPath := range getConfigPaths() {
if *fancy {
wg.Add(1)
go func() {
for {
select {
case <-doneChan:
doneChan = make(chan struct{})
fmt.Printf("\r \033[36mprocessing %s\033[m done.\n", cfgPath)
wg.Done()
return
default:
fmt.Printf("\r \033[36mprocessing %s\033[m %s", cfgPath, s.Next())
time.Sleep(100 * time.Millisecond)
}
}
}()
}
var t0 time.Time
if *debug {
t0 = time.Now()
}
process, err := NewProcess(cfgPath, *outputPath)
if err != nil {
log.Fatalln("[ERR]", err)
}
process.Generate(*noCGO)
if err := process.Flush(*noCGO); err != nil {
log.Fatalln("[ERR]", err)
}
if *debug {
fmt.Printf("done in %v\n", time.Now().Sub(t0))
}
if *fancy {
close(doneChan)
wg.Wait()
}
}
}
func getConfigPaths() (paths []string) {
for _, path := range flag.Args() {
if info, err := os.Stat(path); err != nil {
log.Fatalln("[ERR] cannot locate the specified path:", path)
} else if info.IsDir() {
if path, ok := configFromDir(path); ok {
paths = append(paths, path)
continue
}
log.Fatalln("[ERR] cannot find any config file in:", path)
}
paths = append(paths, path)
}
return
}
func configFromDir(path string) (string, bool) {
possibleNames := []string{"c-for-go.yaml", "c-for-go.yml"}
if base := filepath.Base(path); len(base) > 0 {
possibleNames = append(possibleNames,
fmt.Sprintf("%s.yaml", base), fmt.Sprintf("%s.yml", base))
}
for _, name := range possibleNames {
path := filepath.Join(path, name)
if info, err := os.Stat(path); err == nil && !info.IsDir() {
return path, true
}
}
return "", false
}