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