From d8026833dc509852a8c7da315050e93a3c6a6a45 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Thu, 25 Jul 2024 18:46:40 +0800 Subject: [PATCH] llcppg --- c/cjson/cjson.go | 16 +++- chore/_xtool/llcppsigfetch/llcppsigfetch.go | 21 +++++ chore/_xtool/llcppsymg/llcppsymg.go | 57 +++++++++++++ chore/gogensig/gogensig.go | 21 +++++ chore/llcppg/design.md | 5 +- chore/llcppg/llcppg.go | 92 +++++++++++++++++++++ chore/llcppg/types/types.go | 26 ++++++ 7 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 chore/_xtool/llcppsigfetch/llcppsigfetch.go create mode 100644 chore/_xtool/llcppsymg/llcppsymg.go create mode 100644 chore/gogensig/gogensig.go create mode 100644 chore/llcppg/llcppg.go create mode 100644 chore/llcppg/types/types.go diff --git a/c/cjson/cjson.go b/c/cjson/cjson.go index 03a8e5ec..56936469 100644 --- a/c/cjson/cjson.go +++ b/c/cjson/cjson.go @@ -17,7 +17,7 @@ package cjson import ( - _ "unsafe" + "unsafe" "github.com/goplus/llgo/c" ) @@ -31,6 +31,20 @@ type JSON struct { Unused [0]byte } +//go:linkname Parse C.cJSON_Parse +func Parse(value *c.Char) *JSON + +//go:linkname ParseWithLength C.cJSON_ParseWithLength +func ParseWithLength(value *byte, valueLength uintptr) *JSON + +func ParseBytes(value []byte) *JSON { + return ParseWithLength(unsafe.SliceData(value), uintptr(len(value))) +} + +func ParseString(value string) *JSON { + return ParseWithLength(unsafe.StringData(value), uintptr(len(value))) +} + //go:linkname Null C.cJSON_CreateNull func Null() *JSON diff --git a/chore/_xtool/llcppsigfetch/llcppsigfetch.go b/chore/_xtool/llcppsigfetch/llcppsigfetch.go new file mode 100644 index 00000000..30190a18 --- /dev/null +++ b/chore/_xtool/llcppsigfetch/llcppsigfetch.go @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +func main() { + // TODO(xsw): implement llcppsigfetch tool +} diff --git a/chore/_xtool/llcppsymg/llcppsymg.go b/chore/_xtool/llcppsymg/llcppsymg.go new file mode 100644 index 00000000..ea60dffe --- /dev/null +++ b/chore/_xtool/llcppsymg/llcppsymg.go @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "fmt" + "io" + "os" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/cjson" +) + +func main() { + cfgFile := "llcppg.cfg" + if len(os.Args) > 1 { + cfgFile = os.Args[1] + } + + var data []byte + var err error + if cfgFile == "-" { + data, err = io.ReadAll(os.Stdin) + } else { + data, err = os.ReadFile(cfgFile) + } + check(err) + + conf := cjson.ParseBytes(data) + if conf == nil { + fmt.Fprintln(os.Stderr, "Failed to parse config file:", cfgFile) + os.Exit(1) + } + defer conf.Delete() + + c.Printf(c.Str("%s"), conf.Print()) +} + +func check(err error) { + if err != nil { + panic(err) + } +} diff --git a/chore/gogensig/gogensig.go b/chore/gogensig/gogensig.go new file mode 100644 index 00000000..2079aaa2 --- /dev/null +++ b/chore/gogensig/gogensig.go @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +func main() { + // TODO(xsw): implement gogensig tool +} diff --git a/chore/llcppg/design.md b/chore/llcppg/design.md index 5c841675..7cecf46a 100644 --- a/chore/llcppg/design.md +++ b/chore/llcppg/design.md @@ -45,8 +45,7 @@ It generates a symbol table file named `llcppg.symb.json`. Its file format is as "mangle": "_ZN9INIReaderC1EPKcm", "c++": "INIReader::INIReader(char const*, unsigned long)", "go": "(*Reader).Init__0" - }, - ... + } ] ``` @@ -60,7 +59,7 @@ llcppsigfetch - # read config from stdin It fetches information of C/C++ symbols and print to stdout. Its format is as follows: -```json +``` TODO: see llgo/xtool/clang/ast ``` diff --git a/chore/llcppg/llcppg.go b/chore/llcppg/llcppg.go new file mode 100644 index 00000000..471b6c6c --- /dev/null +++ b/chore/llcppg/llcppg.go @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + "os/exec" + + "github.com/goplus/llgo/chore/llcppg/types" + "github.com/goplus/llgo/xtool/env" +) + +func llcppsymg(conf []byte) error { + cmd := exec.Command("llcppsymg", "-") + cmd.Stdin = bytes.NewReader(conf) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func llcppsigfetch(conf []byte, out io.Writer) { + cmd := exec.Command("llcppsigfetch", "-") + cmd.Stdin = bytes.NewReader(conf) + cmd.Stdout = out + cmd.Stderr = os.Stderr + err := cmd.Run() + check(err) +} + +func gogensig(in io.Reader) error { + cmd := exec.Command("gogensig") + cmd.Stdin = in + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func main() { + cfgFile := "llcppg.cfg" + if len(os.Args) > 1 { + cfgFile = os.Args[1] + } + if cfgFile == "-h" || cfgFile == "--help" { + fmt.Fprintln(os.Stderr, "Usage: llcppg [config-file]") + return + } + + f, err := os.Open(cfgFile) + check(err) + defer f.Close() + + var conf types.Config + json.NewDecoder(f).Decode(&conf) + conf.CFlags = env.ExpandEnv(conf.CFlags) + conf.Libs = env.ExpandEnv(conf.Libs) + + b, err := json.MarshalIndent(&conf, "", " ") + check(err) + + err = llcppsymg(b) + check(err) + + r, w := io.Pipe() + go llcppsigfetch(b, w) + + err = gogensig(r) + check(err) +} + +func check(err error) { + if err != nil { + panic(err) + } +} diff --git a/chore/llcppg/types/types.go b/chore/llcppg/types/types.go new file mode 100644 index 00000000..2e39bbdd --- /dev/null +++ b/chore/llcppg/types/types.go @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package types + +// Config represents a configuration for the llcppg tool. +type Config struct { + Name string `json:"name"` + CFlags string `json:"cflags"` + Libs string `json:"libs"` + Include []string `json:"include"` + TrimPrefixes []string `json:"trimPrefixes"` +}