mirror of
https://github.com/fumiama/gozel.git
synced 2026-06-05 00:10:24 +08:00
231 lines
6.8 KiB
Go
231 lines
6.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
)
|
|
|
|
var infhcache = make(map[string]string, 1024)
|
|
|
|
func infh(name string) string {
|
|
if s, ok := infhcache[name]; ok {
|
|
return s
|
|
}
|
|
s := " [" + name + "]"
|
|
infhcache[name] = s
|
|
return s
|
|
}
|
|
|
|
func scanHeader(name string, scan *bufio.Scanner) {
|
|
ln := 0
|
|
var regionfile *os.File
|
|
symtab := symbolTable{
|
|
"ZE_APICALL": symbol{symbolTypeConst, "ZE_APICALL", []string{""}},
|
|
"ZE_APIEXPORT": symbol{symbolTypeConst, "ZE_APIEXPORT", []string{""}},
|
|
"ZE_DLLEXPORT": symbol{symbolTypeConst, "ZE_DLLEXPORT", []string{""}},
|
|
}
|
|
fileheadersb := strings.Builder{}
|
|
region := ""
|
|
for scan.Scan() {
|
|
ln++
|
|
t := scan.Text()
|
|
switch {
|
|
// file headers
|
|
case strings.HasPrefix(t, "/*") || strings.HasPrefix(t, " *") || strings.HasPrefix(t, " */"):
|
|
fileheadersb.WriteString(t)
|
|
fileheadersb.WriteString("\n")
|
|
// pragma start
|
|
case strings.HasPrefix(t, "#pragma region "):
|
|
region = strings.TrimSpace(t[15:])
|
|
if region == "" {
|
|
panic(fmt.Sprintf("%s L%d: unexpected empty region", name, ln))
|
|
}
|
|
fmt.Println(infh(name), "scanning region", region)
|
|
_ = os.RemoveAll(name)
|
|
err := os.MkdirAll(name, 0755)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("%s L%d: cannot create region folder %s, err: %v", name, ln, region, err))
|
|
}
|
|
f, err := os.Create(path.Join(name, region+".go"))
|
|
if err != nil {
|
|
panic(fmt.Sprintf("%s L%d: cannot create region %s, err: %v", name, ln, region, err))
|
|
}
|
|
f.WriteString("// Code generated by gen. DO NOT EDIT.\n\n")
|
|
f.WriteString(fileheadersb.String())
|
|
f.WriteString("\n")
|
|
f.WriteString("package ")
|
|
f.WriteString(name)
|
|
f.WriteString("\n\n")
|
|
regionfile = f
|
|
// block barrier
|
|
case strings.HasPrefix(t, "///////////////////////////////////////////////////////////////////////////////"):
|
|
fmt.Println(" [scan] enter", region, "block")
|
|
ln = scanBlocks(name, scan, regionfile, ln, symtab)
|
|
fmt.Println(" [scan] leave", region, "block")
|
|
// pragma end
|
|
case strings.HasPrefix(t, "#pragma endregion"):
|
|
fmt.Println(infh(name), "close region", regionfile.Name())
|
|
_ = regionfile.Close()
|
|
regionfile = nil
|
|
// skip outer #
|
|
case strings.HasPrefix(t, "#") || t == "" || strings.HasPrefix(t, "// ") ||
|
|
strings.HasPrefix(t, "extern "):
|
|
fmt.Println(" [scan] skip", t)
|
|
continue
|
|
default:
|
|
panic(fmt.Sprintf("%s L%d: unexpected line %s", name, ln, t))
|
|
}
|
|
}
|
|
}
|
|
|
|
func checkSymbolName(
|
|
symtab symbolTable, ln int, name, sname, goname string,
|
|
sb *strings.Builder, f *os.File, eq func() symbol) {
|
|
if _, ok := symtab[sname]; ok {
|
|
panic(fmt.Sprintf("%s L%d: func #define %s has been defined", name, ln, sname))
|
|
}
|
|
symtab[sname] = eq()
|
|
if sb.Len() == 0 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected non-comment for symbol %s", name, ln, sname))
|
|
}
|
|
brief := " " + goname
|
|
if goname != sname {
|
|
brief = fmt.Sprint(brief, " (", sname, ")")
|
|
}
|
|
f.WriteString(strings.Replace(sb.String(), "/ @brief", brief, 1))
|
|
sb.Reset()
|
|
}
|
|
|
|
func scanBlocks(
|
|
name string, scan *bufio.Scanner, f *os.File,
|
|
ln int, symtab symbolTable,
|
|
) int {
|
|
sb := strings.Builder{}
|
|
skip2nextblk := false //TODO: check logic
|
|
ifdepth := 0
|
|
isparsing := func() bool {
|
|
//TODO: more condition
|
|
return ifdepth > 0
|
|
}
|
|
for scan.Scan() {
|
|
ln++
|
|
t := scan.Text()
|
|
switch {
|
|
// block end
|
|
case t == "":
|
|
if isparsing() {
|
|
continue
|
|
}
|
|
if sb.Len() != 0 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected non-0 sb at block end: %s", name, ln, &sb))
|
|
}
|
|
return ln
|
|
case skip2nextblk:
|
|
continue
|
|
// is definition's comment
|
|
case strings.HasPrefix(t, "/// "):
|
|
sb.WriteString(t)
|
|
sb.WriteString("\n")
|
|
case strings.HasPrefix(t, "#if"):
|
|
if len(t) <= 8 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected short #if", name, ln))
|
|
}
|
|
if t[3] == ' ' { // is platform related judgement
|
|
skip2nextblk = true
|
|
continue
|
|
}
|
|
if t[:8] != "#ifndef " {
|
|
panic(fmt.Sprintf("%s L%d: unexpected #if type %s", name, ln, t))
|
|
}
|
|
sname := strings.TrimSpace(t[8:])
|
|
_, ok := symtab[sname]
|
|
if ok {
|
|
ln = skip2endif(scan, ln)
|
|
continue
|
|
}
|
|
ifdepth++
|
|
case strings.HasPrefix(t, "#endif"):
|
|
ifdepth--
|
|
if ifdepth < 0 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected unpaired #endif", name, ln))
|
|
}
|
|
case strings.HasPrefix(t, "#define "):
|
|
if !strings.Contains(t, "(") { // is const define
|
|
argseval := trimEmptyStringArray(strings.Split(t[8:], " "))
|
|
if len(argseval) != 2 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected const #define line %s", name, ln, t))
|
|
}
|
|
sname := strings.TrimSpace(argseval[0])
|
|
val := strings.TrimSpace(argseval[1])
|
|
checkSymbolName(symtab, ln, name, sname, sname, &sb, f, func() symbol {
|
|
return newSymbolConst(sname, val)
|
|
})
|
|
f.WriteString("const ")
|
|
f.WriteString(sname)
|
|
f.WriteString(" = ")
|
|
f.WriteString(val)
|
|
f.WriteString("\n\n")
|
|
continue
|
|
}
|
|
sname, argseval, ok := strings.Cut(t[8:], "(")
|
|
if !ok {
|
|
panic(fmt.Sprintf("%s L%d: unexpected #define line %s", name, ln, t))
|
|
}
|
|
args, n, err := getInsideRoundBrakets(argseval)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("%s L%d: unexpected args bracket err: %v", name, ln, err))
|
|
}
|
|
sname = strings.TrimSpace(sname)
|
|
args = strings.TrimSpace(args)
|
|
eval := strings.TrimSpace(argseval[n+1:])
|
|
checkSymbolName(symtab, ln, name, sname, sname, &sb, f, func() symbol {
|
|
return newSymbolFunc(sname, args, eval)
|
|
})
|
|
f.WriteString("func ")
|
|
f.WriteString(sname)
|
|
f.WriteString("[T ~int | ~uint64 | ~uintptr](")
|
|
f.WriteString(strings.Join(strings.Split(args, ","), " T,"))
|
|
f.WriteString(" T) T {\n\treturn ")
|
|
f.WriteString(eval)
|
|
f.WriteString("\n}\n\n")
|
|
case strings.HasPrefix(t, "typedef "):
|
|
s, newln := get1sentence(t, scan, ln)
|
|
if newln < 0 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected sentence end from", name, ln))
|
|
}
|
|
ln = newln
|
|
typs := trimEmptyStringArray(strings.Split(s[8:], " "))
|
|
if len(typs) == 0 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected typdef line %s", name, ln, t))
|
|
}
|
|
if strings.TrimSpace(typs[0]) == "struct" {
|
|
if len(typs) != 3 || !strings.Contains(typs[1], "handle_t") ||
|
|
!strings.Contains(typs[2], "*") {
|
|
panic(fmt.Sprintf("%s L%d: unexpected typdef line %s", name, ln, t))
|
|
}
|
|
typs = typs[1:]
|
|
typs[0] = "uintptr"
|
|
typs[1] = strings.TrimPrefix(strings.TrimSpace(typs[1]), "*")
|
|
}
|
|
if len(typs) != 2 {
|
|
panic(fmt.Sprintf("%s L%d: unexpected typdef line %s", name, ln, t))
|
|
}
|
|
sname := strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(typs[1]), ";"))
|
|
val := us2camel(strings.TrimSuffix(sname, "_t"))
|
|
origtyp := strings.TrimSuffix(strings.TrimSpace(typs[0]), "_t")
|
|
checkSymbolName(symtab, ln, name, sname, val, &sb, f, func() symbol {
|
|
return newSymbolConst(sname, val)
|
|
})
|
|
f.WriteString("type ")
|
|
f.WriteString(val)
|
|
f.WriteString(" ")
|
|
f.WriteString(origtyp)
|
|
f.WriteString("\n\n")
|
|
}
|
|
}
|
|
return ln
|
|
}
|