mirror of
https://github.com/glebarez/go-sqlite.git
synced 2025-10-04 15:32:46 +08:00
303 lines
5.8 KiB
Go
303 lines
5.8 KiB
Go
// Copyright 2017 The Sqlite Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"go/format"
|
|
"go/scanner"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
|
|
"log"
|
|
|
|
"github.com/cznic/cc"
|
|
"github.com/cznic/ccgo"
|
|
"github.com/cznic/ccir"
|
|
"github.com/cznic/internal/buffer"
|
|
"github.com/cznic/strutil"
|
|
"github.com/cznic/xc"
|
|
)
|
|
|
|
var (
|
|
cpp = flag.Bool("cpp", false, "")
|
|
dict = xc.Dict
|
|
errLimit = flag.Int("errlimit", 10, "")
|
|
filter = flag.String("re", "", "")
|
|
ndebug = flag.Bool("ndebug", false, "")
|
|
noexec = flag.Bool("noexec", false, "")
|
|
oLog = flag.Bool("log", false, "")
|
|
trace = flag.Bool("trc", false, "")
|
|
yydebug = flag.Int("yydebug", 0, "")
|
|
)
|
|
|
|
const (
|
|
prologue = `/*
|
|
|
|
%s
|
|
*/
|
|
|
|
// Code generated by ccgo DO NOT EDIT.
|
|
|
|
package bin
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"path"
|
|
"runtime"
|
|
"unsafe"
|
|
|
|
"github.com/cznic/crt"
|
|
"github.com/edsrzf/mmap-go"
|
|
|
|
)
|
|
|
|
const minAlloc = 2<<5
|
|
|
|
var (
|
|
inf = math.Inf(1)
|
|
)
|
|
|
|
func ftrace(s string, args ...interface{}) {
|
|
_, fn, fl, _ := runtime.Caller(1)
|
|
fmt.Fprintf(os.Stderr, "# %%s:%%d: %%v\n", path.Base(fn), fl, fmt.Sprintf(s, args...))
|
|
os.Stderr.Sync()
|
|
}
|
|
|
|
func Init(heapSize, heapReserve int) int {
|
|
heap, err := mmap.MapRegion(nil, heapSize+heapReserve, mmap.RDWR, mmap.ANON, 0)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
tls := crt.NewTLS()
|
|
crt.RegisterHeap(unsafe.Pointer(&heap[0]), int64(heapSize+heapReserve))
|
|
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
|
|
return int(Xinit(tls, int32(heapSize)))
|
|
}
|
|
`
|
|
)
|
|
|
|
func findRepo(s string) string {
|
|
s = filepath.FromSlash(s)
|
|
for _, v := range strings.Split(strutil.Gopath(), string(os.PathListSeparator)) {
|
|
p := filepath.Join(v, "src", s)
|
|
fi, err := os.Lstat(p)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
if fi.IsDir() {
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if p, err = filepath.Rel(wd, p); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return p
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func errStr(err error) string {
|
|
switch x := err.(type) {
|
|
case scanner.ErrorList:
|
|
if len(x) != 1 {
|
|
x.RemoveMultiples()
|
|
}
|
|
var b bytes.Buffer
|
|
for i, v := range x {
|
|
if i != 0 {
|
|
b.WriteByte('\n')
|
|
}
|
|
b.WriteString(v.Error())
|
|
if i == 9 {
|
|
fmt.Fprintf(&b, "\n\t... and %v more errors", len(x)-10)
|
|
break
|
|
}
|
|
}
|
|
return b.String()
|
|
default:
|
|
return err.Error()
|
|
}
|
|
}
|
|
|
|
func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit, []byte) {
|
|
ndbg := ""
|
|
if *ndebug {
|
|
ndbg = "#define NDEBUG 1"
|
|
}
|
|
var build []*cc.TranslationUnit
|
|
tus = append(tus, []string{ccir.CRT0Path})
|
|
for _, src := range tus {
|
|
model, err := ccir.NewModel()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
ast, err := cc.Parse(
|
|
fmt.Sprintf(`
|
|
%s
|
|
#define _CCGO 1
|
|
#define __arch__ %s
|
|
#define __os__ %s
|
|
#include <builtin.h>
|
|
%s
|
|
`, ndbg, runtime.GOARCH, runtime.GOOS, predef),
|
|
src,
|
|
model,
|
|
append([]cc.Opt{
|
|
cc.AllowCompatibleTypedefRedefinitions(),
|
|
cc.EnableEmptyStructs(),
|
|
cc.EnableImplicitFuncDef(),
|
|
cc.EnableNonConstStaticInitExpressions(),
|
|
cc.EnableWideBitFieldTypes(),
|
|
cc.ErrLimit(*errLimit),
|
|
cc.SysIncludePaths([]string{ccir.LibcIncludePath}),
|
|
}, opts...)...,
|
|
)
|
|
if err != nil {
|
|
log.Fatal(errStr(err))
|
|
}
|
|
|
|
build = append(build, ast)
|
|
}
|
|
|
|
var out buffer.Bytes
|
|
if err := ccgo.New(build, &out); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return build, out.Bytes()
|
|
}
|
|
|
|
func macros(buf io.Writer, ast *cc.TranslationUnit) {
|
|
fmt.Fprintf(buf, `const (
|
|
`)
|
|
var a []string
|
|
for k, v := range ast.Macros {
|
|
if v.Value != nil && v.Type.Kind() != cc.Bool {
|
|
switch fn := v.DefTok.Position().Filename; {
|
|
case
|
|
fn == "builtin.h",
|
|
fn == "<predefine>",
|
|
strings.HasPrefix(fn, "predefined_"):
|
|
// ignore
|
|
default:
|
|
a = append(a, string(dict.S(k)))
|
|
}
|
|
}
|
|
}
|
|
sort.Strings(a)
|
|
for _, v := range a {
|
|
m := ast.Macros[dict.SID(v)]
|
|
if m.Value == nil {
|
|
log.Fatal("TODO")
|
|
}
|
|
|
|
switch t := m.Type; t.Kind() {
|
|
case
|
|
cc.Int, cc.UInt, cc.Long, cc.ULong, cc.LongLong, cc.ULongLong,
|
|
cc.Float, cc.LongDouble, cc.Bool:
|
|
fmt.Fprintf(buf, "X%s = %v\n", v, m.Value)
|
|
case cc.Ptr:
|
|
switch t := t.Element(); t.Kind() {
|
|
case cc.Char:
|
|
fmt.Fprintf(buf, "X%s = %q\n", v, dict.S(int(m.Value.(cc.StringLitID))))
|
|
default:
|
|
log.Fatalf("%v", t.Kind())
|
|
}
|
|
default:
|
|
log.Fatalf("%v", t.Kind())
|
|
}
|
|
}
|
|
|
|
a = a[:0]
|
|
for _, v := range ast.Declarations.Identifiers {
|
|
switch x := v.Node.(type) {
|
|
case *cc.DirectDeclarator:
|
|
d := x.TopDeclarator()
|
|
id, _ := d.Identifier()
|
|
if x.EnumVal == nil {
|
|
break
|
|
}
|
|
|
|
a = append(a, string(dict.S(id)))
|
|
default:
|
|
log.Fatalf("%T", x)
|
|
}
|
|
}
|
|
sort.Strings(a)
|
|
for _, v := range a {
|
|
dd := ast.Declarations.Identifiers[dict.SID(v)].Node.(*cc.DirectDeclarator)
|
|
fmt.Fprintf(buf, "X%s = %v\n", v, dd.EnumVal)
|
|
}
|
|
fmt.Fprintf(buf, ")\n")
|
|
}
|
|
|
|
func main() {
|
|
const repo = "sqlite.org/sqlite-amalgamation-3180000/"
|
|
|
|
log.SetFlags(log.Lshortfile | log.Lmicroseconds)
|
|
flag.Parse()
|
|
pth := findRepo(repo)
|
|
if pth == "" {
|
|
log.Fatalf("repository not found: %v", repo)
|
|
return
|
|
}
|
|
|
|
asta, src := build(
|
|
`
|
|
#define HAVE_USLEEP 1
|
|
#define SQLITE_DEBUG 1
|
|
#define SQLITE_ENABLE_API_ARMOR 1
|
|
#define SQLITE_ENABLE_MEMSYS5 1
|
|
#define SQLITE_USE_URI 1
|
|
`,
|
|
[][]string{
|
|
{"main.c"},
|
|
{filepath.Join(pth, "sqlite3.c")},
|
|
},
|
|
cc.EnableAnonymousStructFields(),
|
|
cc.IncludePaths([]string{pth}),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
lic, err := ioutil.ReadFile("SQLITE-LICENSE")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Fprintf(&b, prologue, lic)
|
|
macros(&b, asta[0])
|
|
b.Write(src)
|
|
b2, err := format.Source(b.Bytes())
|
|
if err != nil {
|
|
b2 = b.Bytes()
|
|
}
|
|
if err := os.MkdirAll("internal/bin", 0775); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if err := ioutil.WriteFile(fmt.Sprintf("internal/bin/bin_%s_%s.go", runtime.GOOS, runtime.GOARCH), b2, 0664); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|