-
Notifications
You must be signed in to change notification settings - Fork 121
/
main.go
127 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
127
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 <[email protected]>
Based on a C99 compiler front end by Jan Mercl <[email protected]>
`
func init() {
if *debug {
log.SetFlags(log.Lshortfile)
} else {
log.SetFlags(0)
}
flag.Usage = func() {
fmt.Print(logo)
fmt.Printf("Usage: %s package1.yml [package2.yml] ...\n", os.Args[0])
fmt.Printf("See https://github.com/xlab/c-for-go for examples and documentation.\n\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
}