305 lines
6.2 KiB
Go
305 lines
6.2 KiB
Go
// Copyright 2023 The Libc Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build ignore
|
|
// +build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func fail(rc int, msg string, args ...any) {
|
|
fmt.Fprintln(os.Stderr, strings.TrimSpace(fmt.Sprintf(msg, args...)))
|
|
os.Exit(rc)
|
|
}
|
|
|
|
func main() {
|
|
m, err := filepath.Glob("*.go")
|
|
if err != nil {
|
|
fail(1, "%s\n", err)
|
|
}
|
|
|
|
format := false
|
|
for _, fn := range m {
|
|
b, err := os.ReadFile(fn)
|
|
if err != nil {
|
|
fail(1, "%s\n", err)
|
|
}
|
|
|
|
a := strings.Split(string(b), "\n")
|
|
w := false
|
|
for i, v := range a {
|
|
if strings.HasPrefix(v, "func X") &&
|
|
strings.Contains(v, "*TLS") &&
|
|
!strings.Contains(v, "struct") &&
|
|
!strings.Contains(v, "interface{") &&
|
|
!strings.HasSuffix(v, ",") {
|
|
switch {
|
|
case strings.Contains(v, "}"):
|
|
x := strings.Index(v, "{")
|
|
if x < 0 {
|
|
panic(fmt.Errorf("%s: %q", fn, v))
|
|
}
|
|
|
|
h := v[:x+1]
|
|
t := v[x+1:]
|
|
ok, tl := traceLine(fn, h)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
a[i] = "\n\n" + h + "\n\t" + tl + "\n" + t
|
|
w = true
|
|
format = true
|
|
default:
|
|
if i+1 < len(a) && !strings.Contains(a[i+1], "__ccgo_strace") {
|
|
ok, tl := traceLine(fn, v)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
a[i] += "\n\t" + tl
|
|
w = true
|
|
format = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if w {
|
|
if err := os.WriteFile(fn, []byte(strings.Join(a, "\n")), 0660); err != nil {
|
|
fail(1, "%s\n", err)
|
|
}
|
|
}
|
|
}
|
|
if format {
|
|
if out, err := exec.Command("sh", "-c", "gofmt -w *.go").CombinedOutput(); err != nil {
|
|
fail(1, "%s FAIL err=%v\n", out, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// func Xaio_fsync(tls *TLS, op int32, cb uintptr) (r int32) {
|
|
func traceLine(fn, s string) (ok bool, _ string) {
|
|
ok = true
|
|
var b strings.Builder
|
|
parts := strings.Split(s, "(")
|
|
for i, v := range parts {
|
|
switch i {
|
|
case 0:
|
|
// "func Xaio_fsync"
|
|
case 1:
|
|
// "tls *TLS, op int32, cb uintptr) "
|
|
a := strings.Split(v, ",") // ["tls *TLS" "op int32" "cb uintptr) "]
|
|
b.WriteString(`if __ccgo_strace { trc("`)
|
|
var vals []string
|
|
for j, w := range a {
|
|
w = strings.TrimSpace(w)
|
|
if x := strings.Index(w, " "); x > 0 {
|
|
w := w[:x]
|
|
if w == "_" {
|
|
ok = false
|
|
}
|
|
if j != 0 {
|
|
b.WriteString(" ")
|
|
}
|
|
fmt.Fprintf(&b, "%s=%%v", w)
|
|
vals = append(vals, w)
|
|
}
|
|
}
|
|
fmt.Fprintf(&b, `, (%%v:)", %s, origin(2))`, strings.Join(vals, ", "))
|
|
case 2:
|
|
// "r int32) {"
|
|
x := strings.Index(v, " ")
|
|
if x < 1 {
|
|
panic(fmt.Errorf("%s: %q", fn, s))
|
|
}
|
|
|
|
r := v[:x]
|
|
fmt.Fprintf(&b, `; defer func() { trc("-> %%v", %s)}()`, r)
|
|
}
|
|
}
|
|
b.WriteString("}")
|
|
return ok, b.String()
|
|
}
|
|
|
|
func mustCopyDir(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool, srcNotExistsOk bool) (files int, bytes int64) {
|
|
file, bytes, err := copyDir(dst, src, canOverwrite, srcNotExistsOk)
|
|
if err != nil {
|
|
fail(1, "%s\n", err)
|
|
}
|
|
|
|
return file, bytes
|
|
}
|
|
|
|
func copyDir(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool, srcNotExistsOk bool) (files int, bytes int64, rerr error) {
|
|
dst = filepath.FromSlash(dst)
|
|
src = filepath.FromSlash(src)
|
|
si, err := os.Stat(src)
|
|
if err != nil {
|
|
if os.IsNotExist(err) && srcNotExistsOk {
|
|
err = nil
|
|
}
|
|
return 0, 0, err
|
|
}
|
|
|
|
if !si.IsDir() {
|
|
return 0, 0, fmt.Errorf("cannot copy a file: %s", src)
|
|
}
|
|
|
|
return files, bytes, filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if info.Mode()&os.ModeSymlink != 0 {
|
|
target, err := filepath.EvalSymlinks(path)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot evaluate symlink %s: %v", path, err)
|
|
}
|
|
|
|
if info, err = os.Stat(target); err != nil {
|
|
return fmt.Errorf("cannot stat %s: %v", target, err)
|
|
}
|
|
|
|
if info.IsDir() {
|
|
rel, err := filepath.Rel(src, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
dst2 := filepath.Join(dst, rel)
|
|
if err := os.MkdirAll(dst2, 0770); err != nil {
|
|
return err
|
|
}
|
|
|
|
f, b, err := copyDir(dst2, target, canOverwrite, srcNotExistsOk)
|
|
files += f
|
|
bytes += b
|
|
return err
|
|
}
|
|
|
|
path = target
|
|
}
|
|
|
|
rel, err := filepath.Rel(src, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if info.IsDir() {
|
|
return os.MkdirAll(filepath.Join(dst, rel), 0770)
|
|
}
|
|
|
|
n, err := copyFile(filepath.Join(dst, rel), path, canOverwrite)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
files++
|
|
bytes += n
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func mustCopyFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) int64 {
|
|
n, err := copyFile(dst, src, canOverwrite)
|
|
if err != nil {
|
|
fail(1, "%s\n", err)
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
func copyFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (n int64, rerr error) {
|
|
src = filepath.FromSlash(src)
|
|
si, err := os.Stat(src)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if si.IsDir() {
|
|
return 0, fmt.Errorf("cannot copy a directory: %s", src)
|
|
}
|
|
|
|
dst = filepath.FromSlash(dst)
|
|
if si.Size() == 0 {
|
|
return 0, os.Remove(dst)
|
|
}
|
|
|
|
dstDir := filepath.Dir(dst)
|
|
di, err := os.Stat(dstDir)
|
|
switch {
|
|
case err != nil:
|
|
if !os.IsNotExist(err) {
|
|
return 0, err
|
|
}
|
|
|
|
if err := os.MkdirAll(dstDir, 0770); err != nil {
|
|
return 0, err
|
|
}
|
|
case err == nil:
|
|
if !di.IsDir() {
|
|
return 0, fmt.Errorf("cannot create directory, file exists: %s", dst)
|
|
}
|
|
}
|
|
|
|
di, err = os.Stat(dst)
|
|
switch {
|
|
case err != nil && !os.IsNotExist(err):
|
|
return 0, err
|
|
case err == nil:
|
|
if di.IsDir() {
|
|
return 0, fmt.Errorf("cannot overwite a directory: %s", dst)
|
|
}
|
|
|
|
if canOverwrite != nil && !canOverwrite(dst, di) {
|
|
return 0, fmt.Errorf("cannot overwite: %s", dst)
|
|
}
|
|
}
|
|
|
|
s, err := os.Open(src)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
defer s.Close()
|
|
r := bufio.NewReader(s)
|
|
|
|
d, err := os.Create(dst)
|
|
|
|
defer func() {
|
|
if err := d.Close(); err != nil && rerr == nil {
|
|
rerr = err
|
|
return
|
|
}
|
|
|
|
if err := os.Chmod(dst, si.Mode()); err != nil && rerr == nil {
|
|
rerr = err
|
|
return
|
|
}
|
|
|
|
if err := os.Chtimes(dst, si.ModTime(), si.ModTime()); err != nil && rerr == nil {
|
|
rerr = err
|
|
return
|
|
}
|
|
}()
|
|
|
|
w := bufio.NewWriter(d)
|
|
|
|
defer func() {
|
|
if err := w.Flush(); err != nil && rerr == nil {
|
|
rerr = err
|
|
}
|
|
}()
|
|
|
|
return io.Copy(w, r)
|
|
}
|