syncfiles/gen/scriptmap.go
2022-03-22 19:05:13 -04:00

137 lines
3.0 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"sort"
)
type regionmap struct {
regions []int
charmap int
}
type regionmaps []regionmap
func (s regionmaps) Len() int { return len(s) }
func (s regionmaps) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s regionmaps) Less(i, j int) bool {
x := s[i]
y := s[j]
switch {
case len(y.regions) == 0:
return true
case len(x.regions) == 0:
return false
default:
return x.regions[0] < y.regions[0]
}
}
type scriptmap struct {
script int
regions []regionmap
}
type scriptmaps []*scriptmap
func (s scriptmaps) Len() int { return len(s) }
func (s scriptmaps) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s scriptmaps) Less(i, j int) bool { return s[i].script < s[j].script }
// genMap generates a map from scripts and regions to charmaps.
func genMap(d *scriptdata) []*scriptmap {
m := make(map[int]*scriptmap)
var r []*scriptmap
for i, cm := range d.charmaps {
s := m[cm.script]
if s == nil {
s = &scriptmap{script: cm.script}
m[cm.script] = s
r = append(r, s)
}
var rgs []int
if len(cm.regions) != 0 {
rgs = make([]int, len(cm.regions))
copy(rgs, cm.regions)
sort.Ints(rgs)
}
s.regions = append(s.regions, regionmap{
regions: cm.regions,
charmap: i,
})
}
for _, s := range r {
sort.Sort(regionmaps(s.regions))
}
sort.Sort(scriptmaps(r))
return r
}
// writeMap writes out a C function that returns the correct character map for a
// given script and region.
func writeMap(d *scriptdata, m []*scriptmap, filename string) error {
if !flagQuiet {
fmt.Fprintln(os.Stderr, "Writing:", filename)
}
fp, err := os.Create(filename)
if err != nil {
return err
}
defer fp.Close()
w := bufio.NewWriter(fp)
w.WriteString(header)
w.WriteString(
"#include \"src/convert.h\"\n" +
"int GetCharmap(int script, int region) {\n" +
"switch (script) {\n")
for _, s := range m {
fmt.Fprintf(w, "case %d: /* %s */\n", s.script, d.scripts.values[s.script])
if len(s.regions) == 1 && len(s.regions[0].regions) == 0 {
r := s.regions[0]
fmt.Fprintf(w, "return %d; /* %s */\n", r.charmap, d.charmaps[r.charmap].name)
} else {
w.WriteString("switch (region) {\n")
var hasdefault bool
for _, r := range s.regions {
if len(r.regions) == 0 {
w.WriteString("default:\n")
hasdefault = true
} else {
for _, rg := range r.regions {
fmt.Fprintf(w, "case %d: /* %s */\n", rg, d.regions.values[rg])
}
}
fmt.Fprintf(w, "return %d; /* %s */\n", r.charmap, d.charmaps[r.charmap].name)
}
if !hasdefault {
w.WriteString("default:\nreturn -1;\n")
}
w.WriteString("}\n")
}
}
w.WriteString(
"default:\n" +
"return -1;\n" +
"}\n" +
"}\n")
if err := w.Flush(); err != nil {
return err
}
if err := fp.Close(); err != nil {
return err
}
cmd := exec.Command("clang-format", "-i", filename)
if err := cmd.Run(); err != nil {
fmt.Fprintln(os.Stderr, "Warning: clang-format failed:", err)
}
return nil
}