1
0
mirror of https://github.com/fumiama/gozel.git synced 2026-06-06 00:40:23 +08:00
Files
gozel/gen/scan.go
2026-03-15 00:34:33 +08:00

127 lines
3.1 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{""}},
}
for scan.Scan() {
ln++
t := scan.Text()
switch {
// 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\npackage ")
f.WriteString(name)
f.WriteString("\n")
regionfile = f
// block barrier
case strings.HasPrefix(t, "///////////////////////////////////////////////////////////////////////////////"):
regionfile.WriteString(t)
regionfile.WriteString("\n")
ln = scanblocks(name, scan, regionfile, ln, symtab)
// pragma end
case strings.HasPrefix(t, "#pragma endregion"):
fmt.Println(infh(name), "close region", regionfile.Name())
_ = regionfile.Close()
regionfile = nil
}
}
}
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"):
}
}
return ln
}