mxutil.mx raw
1 // Package mxutil holds the io/string helpers and target globals shared by
2 // the stage4 compiler packages (driver, types, ssa, emit).
3 package mxutil
4
5 import "unsafe"
6
7 //export write
8 func cWrite(fd int32, buf unsafe.Pointer, count uint32) (n int32)
9
10 //export mxc_readfile
11 func cReadfile(path unsafe.Pointer, pathLen int32, buf unsafe.Pointer, bufCap int32) (n int32)
12
13 //export mxc_filesize
14 func cFilesize(path unsafe.Pointer, pathLen int32) (n int32)
15
16 // Target triple components for the current compile.
17 var TargetOS string
18 var TargetArch string
19
20 // ImportSeg records one source file's import specs and the concat line its
21 // body starts at. The SSA builder uses this to give each file its own
22 // pkg-name scope: two files may bind the same local name to different
23 // packages, and the hoisted+deduped import block in the concat destroys
24 // that association.
25 type ImportSeg struct {
26 OutStart int32
27 Specs []string // raw specs as written: `"path"` or `alias "path"`
28 }
29
30 var ConcatImportSegs []ImportSeg
31
32 func SetTarget(os, arch string) {
33 TargetOS = os
34 TargetArch = arch
35 }
36
37 func ResetConcatImportSegs() {
38 ConcatImportSegs = nil
39 }
40
41 func AppendConcatImportSeg(seg ImportSeg) {
42 push(ConcatImportSegs, seg)
43 }
44
45 func WriteStr(fd int32, s string) {
46 if len(s) > 0 {
47 cWrite(fd, unsafe.Pointer(unsafe.SliceData([]byte(s))), uint32(len(s)))
48 }
49 }
50
51 func FileExists(path string) (ok bool) {
52 if len(path) == 0 {
53 return false
54 }
55 pp := unsafe.Pointer(unsafe.SliceData([]byte(path)))
56 pl := int32(len(path))
57 return cFilesize(pp, pl) >= 0
58 }
59
60 func ReadFile(path string) (data []byte, ok bool) {
61 if len(path) == 0 {
62 return nil, false
63 }
64 pp := unsafe.Pointer(unsafe.SliceData([]byte(path)))
65 pl := int32(len(path))
66 sz := cFilesize(pp, pl)
67 if sz < 0 {
68 return nil, false
69 }
70 if sz == 0 {
71 sz = 65536
72 }
73 buf := []byte{:sz}
74 n := cReadfile(pp, pl,
75 unsafe.Pointer(unsafe.SliceData(buf)), sz)
76 if n < 0 {
77 return nil, false
78 }
79 return buf[:n], true
80 }
81
82 func SplitLines(s string) (ss []string) {
83 var result []string
84 start := int32(0)
85 for i := int32(0); i < int32(len(s)); i++ {
86 if s[i] == '\n' {
87 if i > start {
88 push(result, s[start:i])
89 }
90 start = i + 1
91 }
92 }
93 if start < int32(len(s)) {
94 push(result, s[start:])
95 }
96 return result
97 }
98
99 func HasPrefix(s, prefix string) (ok bool) {
100 return len(s) >= len(prefix) && s[:len(prefix)] == prefix
101 }
102
103 func HasSuffix(s, suffix string) (ok bool) {
104 return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
105 }
106
107 func TrimSpace(s string) (sv string) {
108 i := int32(0)
109 for i < int32(len(s)) && (s[i] == ' ' || s[i] == '\t' || s[i] == '\n' || s[i] == '\r') {
110 i++
111 }
112 j := int32(len(s))
113 for j > i && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n' || s[j-1] == '\r') {
114 j--
115 }
116 return s[i:j]
117 }
118
119 func JoinPath(a, b string) (s string) {
120 if len(a) == 0 {
121 return b
122 }
123 if a[len(a)-1] == '/' {
124 return a | b
125 }
126 return a | "/" | b
127 }
128
129 func ExtractQuoted(s string) (sv string) {
130 start := int32(-1)
131 for i := int32(0); i < int32(len(s)); i++ {
132 if s[i] == '"' {
133 if start < 0 {
134 start = i + 1
135 } else {
136 return s[start:i]
137 }
138 }
139 }
140 return ""
141 }
142