104 lines
1.9 KiB
Go
104 lines
1.9 KiB
Go
package build
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"git.akyoto.dev/cli/q/build/elf"
|
|
"git.akyoto.dev/cli/q/cli/log"
|
|
)
|
|
|
|
// Build describes a compiler build.
|
|
type Build struct {
|
|
ExecutableName string
|
|
ExecutablePath string
|
|
WriteExecutable bool
|
|
}
|
|
|
|
// New creates a new build.
|
|
func New(directory string) (*Build, error) {
|
|
directory, err := filepath.Abs(directory)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
file, err := os.Open(directory)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer file.Close()
|
|
files, err := file.Readdirnames(0)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, name := range files {
|
|
log.Info.Println(name)
|
|
}
|
|
|
|
executableName := filepath.Base(directory)
|
|
|
|
build := &Build{
|
|
ExecutableName: executableName,
|
|
ExecutablePath: filepath.Join(directory, executableName),
|
|
WriteExecutable: true,
|
|
}
|
|
|
|
return build, nil
|
|
}
|
|
|
|
// Run parses the input files and generates an executable file.
|
|
func (build *Build) Run() error {
|
|
code := build.Compile()
|
|
|
|
if build.WriteExecutable {
|
|
return writeToDisk(build.ExecutablePath, code)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Compile compiles all the functions.
|
|
func (build *Build) Compile() []byte {
|
|
return []byte{
|
|
0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1
|
|
0xbf, 0x01, 0x00, 0x00, 0x00, // mov edi, 1
|
|
0xbe, 0xa2, 0x00, 0x40, 0x00, // mov esi, 0x4000a2
|
|
0xba, 0x06, 0x00, 0x00, 0x00, // mov edx, 6
|
|
0x0f, 0x05, // syscall
|
|
|
|
0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, 60
|
|
0xbf, 0x00, 0x00, 0x00, 0x00, // mov edi, 0
|
|
0x0f, 0x05, // syscall
|
|
|
|
'H', 'e', 'l', 'l', 'o', '\n',
|
|
}
|
|
}
|
|
|
|
// writeToDisk writes the executable file to disk.
|
|
func writeToDisk(filePath string, code []byte) error {
|
|
file, err := os.Create(filePath)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
buffer := bufio.NewWriter(file)
|
|
executable := elf.New(code)
|
|
executable.Write(buffer)
|
|
buffer.Flush()
|
|
|
|
err = file.Close()
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.Chmod(filePath, 0755)
|
|
}
|