github.com/aergoio/aergo@v1.3.1/cmd/aergoluac/util/luac_util.go (about)

     1  package util
     2  
     3  /*
     4  #cgo CFLAGS: -I${SRCDIR}/../../../libtool/include/luajit-2.1
     5  #cgo LDFLAGS: ${SRCDIR}/../../../libtool/lib/libluajit-5.1.a -lm
     6  
     7  #include <stdlib.h>
     8  #include <lualib.h>
     9  #include "compile.h"
    10  */
    11  import "C"
    12  import (
    13  	"bufio"
    14  	"bytes"
    15  	"encoding/binary"
    16  	"errors"
    17  	"fmt"
    18  	"github.com/aergoio/aergo/cmd/aergoluac/encoding"
    19  	"io/ioutil"
    20  	"os"
    21  	"runtime"
    22  	"unsafe"
    23  )
    24  
    25  func NewLState() *C.lua_State {
    26  	L := C.luac_vm_newstate()
    27  	if L == nil {
    28  		runtime.GC()
    29  		L = C.luac_vm_newstate()
    30  	}
    31  	return L
    32  }
    33  
    34  func CloseLState(L *C.lua_State) {
    35  	if L != nil {
    36  		C.luac_vm_close(L)
    37  	}
    38  }
    39  
    40  func Compile(L *C.lua_State, code string) ([]byte, error) {
    41  	cstr := C.CString(code)
    42  	defer C.free(unsafe.Pointer(cstr))
    43  	if errMsg := C.vm_loadstring(L, cstr); errMsg != nil {
    44  		return nil, errors.New(C.GoString(errMsg))
    45  	}
    46  	if errMsg := C.vm_stringdump(L); errMsg != nil {
    47  		return nil, errors.New(C.GoString(errMsg))
    48  	}
    49  	return dumpToBytes(L), nil
    50  }
    51  
    52  func CompileFromFile(srcFileName, outFileName, abiFileName string) error {
    53  	cSrcFileName := C.CString(srcFileName)
    54  	cOutFileName := C.CString(outFileName)
    55  	cAbiFileName := C.CString(abiFileName)
    56  	L := C.luac_vm_newstate()
    57  	defer C.free(unsafe.Pointer(cSrcFileName))
    58  	defer C.free(unsafe.Pointer(cOutFileName))
    59  	defer C.free(unsafe.Pointer(cAbiFileName))
    60  	defer C.luac_vm_close(L)
    61  
    62  	if errMsg := C.vm_compile(L, cSrcFileName, cOutFileName, cAbiFileName); errMsg != nil {
    63  		return errors.New(C.GoString(errMsg))
    64  	}
    65  	return nil
    66  }
    67  
    68  func DumpFromFile(srcFileName string) error {
    69  	cSrcFileName := C.CString(srcFileName)
    70  	L := C.luac_vm_newstate()
    71  	defer C.free(unsafe.Pointer(cSrcFileName))
    72  	defer C.luac_vm_close(L)
    73  
    74  	if errMsg := C.vm_loadfile(L, cSrcFileName); errMsg != nil {
    75  		return errors.New(C.GoString(errMsg))
    76  	}
    77  	if errMsg := C.vm_stringdump(L); errMsg != nil {
    78  		return errors.New(C.GoString(errMsg))
    79  	}
    80  
    81  	fmt.Println(encoding.EncodeCode(dumpToBytes(L)))
    82  	return nil
    83  }
    84  
    85  func DumpFromStdin() error {
    86  	fi, err := os.Stdin.Stat()
    87  	if err != nil {
    88  		return err
    89  	}
    90  	var buf []byte
    91  	if (fi.Mode() & os.ModeCharDevice) == 0 {
    92  		buf, err = ioutil.ReadAll(os.Stdin)
    93  		if err != nil {
    94  			return err
    95  		}
    96  	} else {
    97  		var bBuf bytes.Buffer
    98  		scanner := bufio.NewScanner(os.Stdin)
    99  		for scanner.Scan() {
   100  			bBuf.WriteString(scanner.Text() + "\n")
   101  		}
   102  		if err = scanner.Err(); err != nil {
   103  			return err
   104  		}
   105  		buf = bBuf.Bytes()
   106  	}
   107  	srcCode := C.CString(string(buf))
   108  	L := C.luac_vm_newstate()
   109  	defer C.free(unsafe.Pointer(srcCode))
   110  	defer C.luac_vm_close(L)
   111  
   112  	if errMsg := C.vm_loadstring(L, srcCode); errMsg != nil {
   113  		return errors.New(C.GoString(errMsg))
   114  	}
   115  	if errMsg := C.vm_stringdump(L); errMsg != nil {
   116  		return errors.New(C.GoString(errMsg))
   117  	}
   118  	fmt.Println(encoding.EncodeCode(dumpToBytes(L)))
   119  	return nil
   120  }
   121  
   122  func dumpToBytes(L *C.lua_State) []byte {
   123  	var s *C.char
   124  	var l C.size_t
   125  	b := make([]byte, 4)
   126  	s = C.lua_tolstring(L, -2, &l)
   127  	binary.LittleEndian.PutUint32(b, uint32(l))
   128  	b = append(b, C.GoBytes(unsafe.Pointer(s), C.int(l))...)
   129  	s = C.lua_tolstring(L, -1, &l)
   130  	b = append(b, C.GoBytes(unsafe.Pointer(s), C.int(l))...)
   131  	return b
   132  }