Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
210c483635 | ||
|
|
8ca4212650 | ||
|
|
c91dba5ed6 | ||
|
|
c8de05f101 | ||
|
|
0ac7cde498 | ||
|
|
108829ad9c | ||
|
|
c5b96f4e9c | ||
|
|
4c2099d33e | ||
|
|
fe5de95008 | ||
|
|
4b0cfc0751 | ||
|
|
c2bf05942e | ||
|
|
df37f80c8e | ||
|
|
2c19d7218d | ||
|
|
34899e8d36 | ||
|
|
bf8c10ed25 | ||
|
|
93c33e08c2 | ||
|
|
3992dd1dd0 | ||
|
|
cab29c2be7 | ||
|
|
f582657ffd | ||
|
|
2823ac1aee | ||
|
|
289caa7cc2 | ||
|
|
0a8bad46b5 | ||
|
|
aa4f518262 | ||
|
|
f76fa879fc | ||
|
|
8d70aba1f5 | ||
|
|
a44bb35aec | ||
|
|
4fda2b656f | ||
|
|
e626d00fdf | ||
|
|
bf09e3c3ae | ||
|
|
753dcd3301 | ||
|
|
8b5dee510e | ||
|
|
9cb73fbf78 | ||
|
|
e6b4deb5c4 | ||
|
|
8848222728 | ||
|
|
3cd62994c7 | ||
|
|
dd93a97790 | ||
|
|
e40e2d2d14 | ||
|
|
26f8ce7b5a | ||
|
|
9a61e374b5 | ||
|
|
9b12e9819c | ||
|
|
5d0a91239c | ||
|
|
c848278690 | ||
|
|
2ebb929e2c | ||
|
|
b34334ba93 | ||
|
|
05a01cd803 | ||
|
|
9ac0c06f26 | ||
|
|
52af22b0e8 | ||
|
|
81cfc73b48 | ||
|
|
f892bfccdf | ||
|
|
dbed8fefac | ||
|
|
ca14637909 | ||
|
|
7db618fba5 | ||
|
|
29c74c09ce | ||
|
|
a2b5b9f97e | ||
|
|
6a05aa4e53 | ||
|
|
43fd5d233a | ||
|
|
0bd39ed035 | ||
|
|
1db8aad039 | ||
|
|
fb2d4267f5 | ||
|
|
d7b203ae08 | ||
|
|
3e07f2e3bc | ||
|
|
94cf6f6640 | ||
|
|
6da5fe4317 | ||
|
|
3a68dee850 | ||
|
|
2ccfa6a2e8 | ||
|
|
f7bf671050 | ||
|
|
4bff9cc3df | ||
|
|
13c68a0184 | ||
|
|
6d92949715 | ||
|
|
5cf31bd3f3 | ||
|
|
929d4c8d61 | ||
|
|
482f796bad | ||
|
|
d85f532ab1 | ||
|
|
b1654f7807 | ||
|
|
4f8526e527 | ||
|
|
4b568fc469 | ||
|
|
d06146ed97 | ||
|
|
8e0e809733 | ||
|
|
d1f33a6c4c | ||
|
|
b3e1b6fdbf | ||
|
|
0bd259403c | ||
|
|
c186846463 | ||
|
|
5f92c3b3fc | ||
|
|
0665091cef | ||
|
|
688d153427 | ||
|
|
bec5ba7a73 | ||
|
|
acedf4d6a3 | ||
|
|
5dd5494f93 | ||
|
|
f253e4fabe | ||
|
|
acd09d24d5 | ||
|
|
ceac95c81a | ||
|
|
47a05d0ea2 | ||
|
|
d2975479f2 | ||
|
|
3c238ffae7 | ||
|
|
69f8d1b717 | ||
|
|
45cd9e65d3 | ||
|
|
2e4b1d8c2b | ||
|
|
4e3b65188d | ||
|
|
0ab32e066b | ||
|
|
79d8b00b27 | ||
|
|
eb02c5a451 | ||
|
|
85509c777d | ||
|
|
27677f86e4 | ||
|
|
16174ca874 | ||
|
|
a4e9233231 | ||
|
|
4fdfafa17f | ||
|
|
c9a7dab419 | ||
|
|
8882d75132 | ||
|
|
f67b15b926 | ||
|
|
2d7958f726 | ||
|
|
36072584d0 | ||
|
|
2119e52f55 | ||
|
|
ca1aa6b663 | ||
|
|
10af671b76 | ||
|
|
a4ec6cce96 | ||
|
|
5082ba7102 | ||
|
|
7405e7001b | ||
|
|
4c70651b81 | ||
|
|
21b5b60278 | ||
|
|
0abc5ec452 | ||
|
|
b1d2d620fa | ||
|
|
af6e4abe84 | ||
|
|
45b4315842 | ||
|
|
d2cb96a9e5 | ||
|
|
a3ff845a14 |
63
.github/workflows/go.yml
vendored
63
.github/workflows/go.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
- macos-latest
|
- macos-latest
|
||||||
- ubuntu-24.04
|
- ubuntu-24.04
|
||||||
llvm: [18]
|
llvm: [18]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{matrix.os}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -26,17 +26,46 @@ jobs:
|
|||||||
if: startsWith(matrix.os, 'macos')
|
if: startsWith(matrix.os, 'macos')
|
||||||
run: |
|
run: |
|
||||||
brew update
|
brew update
|
||||||
brew install llvm@${{ matrix.llvm }} pkg-config bdw-gc openssl cjson sqlite python@3.12
|
brew install llvm@${{matrix.llvm}} pkg-config bdw-gc openssl
|
||||||
echo "$(brew --prefix llvm@${{ matrix.llvm }})/bin" >> $GITHUB_PATH
|
echo "$(brew --prefix llvm@${{matrix.llvm}})/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# Install optional deps for demos.
|
||||||
|
#
|
||||||
|
# NOTE: Keep this list updated as new deps are introduced.
|
||||||
|
opt_deps=(
|
||||||
|
cjson # for github.com/goplus/llgo/c/cjson
|
||||||
|
sqlite # for github.com/goplus/llgo/c/sqlite
|
||||||
|
python@3.12 # for github.com/goplus/llgo/py
|
||||||
|
)
|
||||||
|
brew install "${opt_deps[@]}"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
if: startsWith(matrix.os, 'ubuntu')
|
if: startsWith(matrix.os, 'ubuntu')
|
||||||
run: |
|
run: |
|
||||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{ matrix.llvm }} main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{matrix.llvm}} main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y llvm-${{ matrix.llvm }}-dev clang-${{ matrix.llvm }} lld-${{ matrix.llvm }} pkg-config libgc-dev libssl-dev libcjson-dev libsqlite3-dev python3.12-dev
|
sudo apt-get install -y llvm-${{matrix.llvm}}-dev clang-${{matrix.llvm}} lld-${{matrix.llvm}} pkg-config libgc-dev libssl-dev zlib1g-dev
|
||||||
echo "/usr/lib/llvm-${{ matrix.llvm }}/bin" >> $GITHUB_PATH
|
echo "/usr/lib/llvm-${{matrix.llvm}}/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# Install optional deps for demos.
|
||||||
|
#
|
||||||
|
# NOTE: Keep this list updated as new deps are introduced.
|
||||||
|
opt_deps=(
|
||||||
|
libcjson-dev # for github.com/goplus/llgo/c/cjson
|
||||||
|
libsqlite3-dev # for github.com/goplus/llgo/c/sqlite
|
||||||
|
python3.12-dev # for github.com/goplus/llgo/py
|
||||||
|
)
|
||||||
|
sudo apt-get install -y "${opt_deps[@]}"
|
||||||
|
|
||||||
|
- name: Install further optional dependencies for demos
|
||||||
|
run: |
|
||||||
|
wget -P ./_demo/llama2-c https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin
|
||||||
|
py_deps=(
|
||||||
|
numpy # for github.com/goplus/llgo/py/numpy
|
||||||
|
torch # for github.com/goplus/llgo/py/torch
|
||||||
|
)
|
||||||
|
pip3 install --break-system-packages "${py_deps[@]}"
|
||||||
|
|
||||||
- name: Clang information
|
- name: Clang information
|
||||||
run: |
|
run: |
|
||||||
@@ -53,27 +82,25 @@ jobs:
|
|||||||
run: go build -v ./...
|
run: go build -v ./...
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
if: matrix.os != 'macos-latest'
|
if: ${{!startsWith(matrix.os, 'macos')}}
|
||||||
run: go test -v ./...
|
run: go test -v ./...
|
||||||
|
|
||||||
- name: Test with coverage
|
- name: Test with coverage
|
||||||
if: matrix.os == 'macos-latest'
|
if: startsWith(matrix.os, 'macos')
|
||||||
run: go test -v -coverprofile="coverage.txt" -covermode=atomic ./...
|
run: go test -v -coverprofile="coverage.txt" -covermode=atomic ./...
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: go install ./...
|
run: go install ./...
|
||||||
|
|
||||||
- name: LLGO tests
|
- name: LLGO tests
|
||||||
if: matrix.os != 'ubuntu-latest'
|
if: ${{!startsWith(matrix.os, 'ubuntu')}}
|
||||||
run: |
|
run: |
|
||||||
echo "Test result on ${{ matrix.os }} with LLVM ${{ matrix.llvm }}" > result.md
|
echo "Test result on ${{matrix.os}} with LLVM ${{matrix.llvm}}" > result.md
|
||||||
LLGOROOT=$PWD bash .github/workflows/test_llgo.sh
|
bash .github/workflows/test_llgo.sh
|
||||||
|
|
||||||
- name: Test _demo and _pydemo
|
- name: Test demos
|
||||||
run: |
|
continue-on-error: true
|
||||||
set +e
|
run: bash .github/workflows/test_demo.sh
|
||||||
LLGOROOT=$PWD bash .github/workflows/test_demo.sh
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
- name: Show test result
|
- name: Show test result
|
||||||
run: cat result.md
|
run: cat result.md
|
||||||
@@ -83,10 +110,10 @@ jobs:
|
|||||||
if: false
|
if: false
|
||||||
with:
|
with:
|
||||||
filePath: result.md
|
filePath: result.md
|
||||||
comment_tag: test-result-on-${{ matrix.os }}-with-llvm-${{ matrix.llvm }}
|
comment_tag: test-result-on-${{matrix.os}}-with-llvm-${{matrix.llvm}}
|
||||||
|
|
||||||
- name: Upload coverage reports to Codecov
|
- name: Upload coverage reports to Codecov
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{secrets.CODECOV_TOKEN}}
|
||||||
slug: goplus/llgo
|
slug: goplus/llgo
|
||||||
|
|||||||
3
.github/workflows/test_demo.sh
vendored
3
.github/workflows/test_demo.sh
vendored
@@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
# llgo run subdirectories under _demo and _pydemo
|
# llgo run subdirectories under _demo and _pydemo
|
||||||
total=0
|
total=0
|
||||||
@@ -8,7 +9,7 @@ for d in ./_demo/* ./_pydemo/*; do
|
|||||||
total=$((total+1))
|
total=$((total+1))
|
||||||
if [ -d "$d" ]; then
|
if [ -d "$d" ]; then
|
||||||
echo "Testing $d"
|
echo "Testing $d"
|
||||||
if ! llgo run "$d"; then
|
if ! (cd "$d" && llgo run .); then
|
||||||
echo "FAIL"
|
echo "FAIL"
|
||||||
failed=$((failed+1))
|
failed=$((failed+1))
|
||||||
failed_cases="$failed_cases\n* :x: $d"
|
failed_cases="$failed_cases\n* :x: $d"
|
||||||
|
|||||||
2
.github/workflows/test_llgo.sh
vendored
2
.github/workflows/test_llgo.sh
vendored
@@ -1,8 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
export LLGOROOT=$PWD
|
|
||||||
|
|
||||||
testcmd=/tmp/test
|
testcmd=/tmp/test
|
||||||
llgo build -o $testcmd ./c/bdwgc/_test
|
llgo build -o $testcmd ./c/bdwgc/_test
|
||||||
cases=$($testcmd)
|
cases=$($testcmd)
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ builds:
|
|||||||
flags:
|
flags:
|
||||||
- -tags=darwin,amd64,byollvm
|
- -tags=darwin,amd64,byollvm
|
||||||
ldflags:
|
ldflags:
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
- -X github.com/goplus/llgo/x/env.buildVersion=v{{.Version}}
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
- -X github.com/goplus/llgo/x/env.buildTime={{.Date}}
|
||||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/local/opt/llvm@18/bin/llvm-config
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/local/opt/llvm@18/bin/llvm-config
|
||||||
env:
|
env:
|
||||||
- CC=o64-clang
|
- CC=o64-clang
|
||||||
@@ -36,8 +36,8 @@ builds:
|
|||||||
flags:
|
flags:
|
||||||
- -tags=darwin,arm64,byollvm
|
- -tags=darwin,arm64,byollvm
|
||||||
ldflags:
|
ldflags:
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
- -X github.com/goplus/llgo/x/env.buildVersion=v{{.Version}}
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
- -X github.com/goplus/llgo/x/env.buildTime={{.Date}}
|
||||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/opt/homebrew/opt/llvm@18/bin/llvm-config
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/opt/homebrew/opt/llvm@18/bin/llvm-config
|
||||||
env:
|
env:
|
||||||
- CC=oa64-clang
|
- CC=oa64-clang
|
||||||
@@ -52,8 +52,8 @@ builds:
|
|||||||
flags:
|
flags:
|
||||||
- -tags=linux,amd64,byollvm
|
- -tags=linux,amd64,byollvm
|
||||||
ldflags:
|
ldflags:
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
- -X github.com/goplus/llgo/x/env.buildVersion=v{{.Version}}
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
- -X github.com/goplus/llgo/x/env.buildTime={{.Date}}
|
||||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config
|
||||||
env:
|
env:
|
||||||
- CC=x86_64-linux-gnu-gcc
|
- CC=x86_64-linux-gnu-gcc
|
||||||
@@ -68,8 +68,8 @@ builds:
|
|||||||
flags:
|
flags:
|
||||||
- -tags=linux,arm64,byollvm
|
- -tags=linux,arm64,byollvm
|
||||||
ldflags:
|
ldflags:
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
- -X github.com/goplus/llgo/x/env.buildVersion=v{{.Version}}
|
||||||
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
- -X github.com/goplus/llgo/x/env.buildTime={{.Date}}
|
||||||
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config
|
||||||
env:
|
env:
|
||||||
- CC=aarch64-linux-gnu-gcc
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -269,13 +269,16 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [unicode/utf8](https://pkg.go.dev/unicode/utf8)
|
* [unicode/utf8](https://pkg.go.dev/unicode/utf8)
|
||||||
* [unicode/utf16](https://pkg.go.dev/unicode/utf16)
|
* [unicode/utf16](https://pkg.go.dev/unicode/utf16)
|
||||||
* [math](https://pkg.go.dev/math)
|
* [math](https://pkg.go.dev/math)
|
||||||
|
* [math/big](https://pkg.go.dev/math/big) (partially)
|
||||||
* [math/bits](https://pkg.go.dev/math/bits)
|
* [math/bits](https://pkg.go.dev/math/bits)
|
||||||
* [math/cmplx](https://pkg.go.dev/math/cmplx)
|
* [math/cmplx](https://pkg.go.dev/math/cmplx)
|
||||||
* [math/rand](https://pkg.go.dev/math/rand)
|
* [math/rand](https://pkg.go.dev/math/rand)
|
||||||
|
* [net/url](https://pkg.go.dev/net/url)
|
||||||
* [errors](https://pkg.go.dev/errors)
|
* [errors](https://pkg.go.dev/errors)
|
||||||
* [context](https://pkg.go.dev/context)
|
* [context](https://pkg.go.dev/context)
|
||||||
* [io](https://pkg.go.dev/io)
|
* [io](https://pkg.go.dev/io)
|
||||||
* [io/fs](https://pkg.go.dev/io/fs)
|
* [io/fs](https://pkg.go.dev/io/fs)
|
||||||
|
* [io/ioutil](https://pkg.go.dev/io/ioutil)
|
||||||
* [log](https://pkg.go.dev/log)
|
* [log](https://pkg.go.dev/log)
|
||||||
* [flag](https://pkg.go.dev/flag)
|
* [flag](https://pkg.go.dev/flag)
|
||||||
* [sort](https://pkg.go.dev/sort)
|
* [sort](https://pkg.go.dev/sort)
|
||||||
@@ -294,6 +297,7 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [fmt](https://pkg.go.dev/fmt) (partially)
|
* [fmt](https://pkg.go.dev/fmt) (partially)
|
||||||
* [reflect](https://pkg.go.dev/reflect) (partially)
|
* [reflect](https://pkg.go.dev/reflect) (partially)
|
||||||
* [time](https://pkg.go.dev/time) (partially)
|
* [time](https://pkg.go.dev/time) (partially)
|
||||||
|
* [encoding](https://pkg.go.dev/encoding)
|
||||||
* [encoding/binary](https://pkg.go.dev/encoding/binary)
|
* [encoding/binary](https://pkg.go.dev/encoding/binary)
|
||||||
* [encoding/hex](https://pkg.go.dev/encoding/hex)
|
* [encoding/hex](https://pkg.go.dev/encoding/hex)
|
||||||
* [encoding/base32](https://pkg.go.dev/encoding/base32)
|
* [encoding/base32](https://pkg.go.dev/encoding/base32)
|
||||||
@@ -303,9 +307,18 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [hash/adler32](https://pkg.go.dev/hash/adler32)
|
* [hash/adler32](https://pkg.go.dev/hash/adler32)
|
||||||
* [hash/crc32](https://pkg.go.dev/hash/crc32) (partially)
|
* [hash/crc32](https://pkg.go.dev/hash/crc32) (partially)
|
||||||
* [hash/crc64](https://pkg.go.dev/hash/crc64)
|
* [hash/crc64](https://pkg.go.dev/hash/crc64)
|
||||||
|
* [crypto](https://pkg.go.dev/crypto)
|
||||||
* [crypto/md5](https://pkg.go.dev/crypto/md5)
|
* [crypto/md5](https://pkg.go.dev/crypto/md5)
|
||||||
|
* [crypto/sha1](https://pkg.go.dev/crypto/sha1)
|
||||||
|
* [crypto/sha256](https://pkg.go.dev/crypto/sha256)
|
||||||
|
* [crypto/sha512](https://pkg.go.dev/crypto/sha512) (partially)
|
||||||
|
* [crypto/hmac](https://pkg.go.dev/crypto/hmac) (partially)
|
||||||
|
* [crypto/rand](https://pkg.go.dev/crypto/rand) (partially)
|
||||||
|
* [crypto/subtle](https://pkg.go.dev/crypto/subtle) (partially)
|
||||||
* [regexp](https://pkg.go.dev/regexp)
|
* [regexp](https://pkg.go.dev/regexp)
|
||||||
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
|
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
|
||||||
|
* [go/token](https://pkg.go.dev/go/token)
|
||||||
|
* [go/scanner](https://pkg.go.dev/go/scanner)
|
||||||
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
@@ -317,8 +330,7 @@ Here are the Go packages that can be imported correctly:
|
|||||||
- [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/)
|
- [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/)
|
||||||
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
|
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
|
||||||
- [OpenSSL 3.0+](https://www.openssl.org/)
|
- [OpenSSL 3.0+](https://www.openssl.org/)
|
||||||
- [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [github.com/goplus/llgo/c/cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson))
|
- [zlib 1.2+](https://www.zlib.net)
|
||||||
- [SQLite 3](https://www.sqlite.org) (optional, for [github.com/goplus/llgo/c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite))
|
|
||||||
- [Python 3.12+](https://www.python.org) (optional, for [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py))
|
- [Python 3.12+](https://www.python.org) (optional, for [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py))
|
||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
@@ -328,10 +340,9 @@ Follow these steps to generate the `llgo` command (its usage is the same as the
|
|||||||
### on macOS
|
### on macOS
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew update # execute if needed
|
brew update
|
||||||
brew install llvm@18 pkg-config bdw-gc openssl
|
brew install llvm@18 pkg-config bdw-gc openssl
|
||||||
brew install cjson sqlite python@3.12 # optional
|
brew install python@3.12 # optional
|
||||||
export PATH=$(brew --prefix llvm@18)/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.zshrc
|
|
||||||
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -340,10 +351,9 @@ go install -v github.com/goplus/llgo/cmd/llgo@latest
|
|||||||
```sh
|
```sh
|
||||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-18 main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-18 main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo apt-get update # execute if needed
|
sudo apt-get update
|
||||||
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev libssl-dev
|
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev libssl-dev zlib1g-dev
|
||||||
sudo apt-get install -y libcjson-dev libsqlite3-dev python3.12-dev # optional
|
sudo apt-get install -y python3.12-dev # optional
|
||||||
export PATH=/usr/lib/llvm-18/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.bashrc
|
|
||||||
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
34
_cmptest/_goparsedemo/parse.go
Normal file
34
_cmptest/_goparsedemo/parse.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fset := token.NewFileSet() // positions are relative to fset
|
||||||
|
|
||||||
|
src := `package foo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func bar() {
|
||||||
|
fmt.Println(time.Now())
|
||||||
|
}`
|
||||||
|
|
||||||
|
// Parse src but stop after processing the imports.
|
||||||
|
f, err := parser.ParseFile(fset, "", src, parser.ImportsOnly)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the imports from the file's AST.
|
||||||
|
for _, s := range f.Imports {
|
||||||
|
fmt.Println(s.Path.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
63
_cmptest/bigintdemo/fib.go
Normal file
63
_cmptest/bigintdemo/fib.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fib() {
|
||||||
|
// Initialize two big ints with the first two numbers in the sequence.
|
||||||
|
a := big.NewInt(0)
|
||||||
|
b := big.NewInt(1)
|
||||||
|
|
||||||
|
// Initialize limit as 10^99, the smallest integer with 100 digits.
|
||||||
|
var limit big.Int
|
||||||
|
limit.Exp(big.NewInt(10), big.NewInt(99), nil)
|
||||||
|
|
||||||
|
// Loop while a is smaller than 1e100.
|
||||||
|
for a.Cmp(&limit) < 0 {
|
||||||
|
// Compute the next Fibonacci number, storing it in a.
|
||||||
|
a.Add(a, b)
|
||||||
|
// Swap a and b so that b is the next number in the sequence.
|
||||||
|
a, b = b, a
|
||||||
|
}
|
||||||
|
fmt.Println(a) // 100-digit Fibonacci number
|
||||||
|
}
|
||||||
|
|
||||||
|
func abs() {
|
||||||
|
a := big.NewInt(64)
|
||||||
|
b := big.NewInt(-52)
|
||||||
|
a.Set(b)
|
||||||
|
a.Abs(a)
|
||||||
|
a.Set(big.NewInt(-164))
|
||||||
|
a.Abs(a)
|
||||||
|
fmt.Println("value: ", a.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func neg() {
|
||||||
|
fmt.Println("value: ", big.NewInt(-64).Neg(big.NewInt(-64)))
|
||||||
|
fmt.Println("value: ", big.NewInt(64).Neg(big.NewInt(64)))
|
||||||
|
fmt.Println("value: ", big.NewInt(0).Neg(big.NewInt(0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func calc() {
|
||||||
|
a := big.NewInt(64)
|
||||||
|
b := big.NewInt(-52)
|
||||||
|
c := big.NewInt(54)
|
||||||
|
fmt.Println("value:", a.Add(a, b))
|
||||||
|
fmt.Println("value:", a.Sub(b, c))
|
||||||
|
d := big.NewInt(10)
|
||||||
|
e := big.NewInt(4)
|
||||||
|
fmt.Println("value:", d.Mul(d, e))
|
||||||
|
}
|
||||||
|
|
||||||
|
func bitop() {
|
||||||
|
a := big.NewInt(4)
|
||||||
|
fmt.Println("value:", a.Lsh(a, 1))
|
||||||
|
b := big.NewInt(16)
|
||||||
|
fmt.Println("value:", b.Rsh(b, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bitop()
|
||||||
|
}
|
||||||
27
_cmptest/goscandemo/scan.go
Normal file
27
_cmptest/goscandemo/scan.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/scanner"
|
||||||
|
"go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// src is the input that we want to tokenize.
|
||||||
|
src := []byte("cos(x) + 1i*sin(x) // Euler")
|
||||||
|
|
||||||
|
// Initialize the scanner.
|
||||||
|
var s scanner.Scanner
|
||||||
|
fset := token.NewFileSet() // positions are relative to fset
|
||||||
|
file := fset.AddFile("", fset.Base(), len(src)) // register input "file"
|
||||||
|
s.Init(file, src, nil /* no error handler */, scanner.ScanComments)
|
||||||
|
|
||||||
|
// Repeated calls to Scan yield the token sequence found in the input.
|
||||||
|
for {
|
||||||
|
pos, tok, lit := s.Scan()
|
||||||
|
if tok == token.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\t%s\t%q\n", fset.Position(pos), tok, lit)
|
||||||
|
}
|
||||||
|
}
|
||||||
15
_cmptest/hmacdemo/hmac.go
Normal file
15
_cmptest/hmacdemo/hmac.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha1"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
h := hmac.New(sha1.New, []byte("<key>"))
|
||||||
|
io.WriteString(h, "The fog is getting thicker!")
|
||||||
|
io.WriteString(h, "And Leon's getting laaarger!")
|
||||||
|
fmt.Printf("%x", h.Sum(nil))
|
||||||
|
}
|
||||||
19
_cmptest/ioutildemo/ioutil.go
Normal file
19
_cmptest/ioutildemo/ioutil.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", b)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -10,5 +11,10 @@ func main() {
|
|||||||
h := md5.New()
|
h := md5.New()
|
||||||
io.WriteString(h, "The fog is getting thicker!")
|
io.WriteString(h, "The fog is getting thicker!")
|
||||||
io.WriteString(h, "And Leon's getting laaarger!")
|
io.WriteString(h, "And Leon's getting laaarger!")
|
||||||
fmt.Printf("%x", h.Sum(nil))
|
fmt.Printf("%x\n", h.Sum(nil))
|
||||||
|
|
||||||
|
h = crypto.MD5.New()
|
||||||
|
io.WriteString(h, "The fog is getting thicker!")
|
||||||
|
io.WriteString(h, "And Leon's getting laaarger!")
|
||||||
|
fmt.Printf("%x\n", h.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|||||||
14
_cmptest/sha1demo/sha1.go
Normal file
14
_cmptest/sha1demo/sha1.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
h := sha1.New()
|
||||||
|
io.WriteString(h, "The fog is getting thicker!")
|
||||||
|
io.WriteString(h, "And Leon's getting laaarger!")
|
||||||
|
fmt.Printf("%x", h.Sum(nil))
|
||||||
|
}
|
||||||
14
_cmptest/sha256demo/sha256.go
Normal file
14
_cmptest/sha256demo/sha256.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
h := sha256.New()
|
||||||
|
io.WriteString(h, "The fog is getting thicker!")
|
||||||
|
io.WriteString(h, "And Leon's getting laaarger!")
|
||||||
|
fmt.Printf("%x", h.Sum(nil))
|
||||||
|
}
|
||||||
14
_cmptest/sha512demo/sha512.go
Normal file
14
_cmptest/sha512demo/sha512.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha512"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
h := sha512.New()
|
||||||
|
io.WriteString(h, "The fog is getting thicker!")
|
||||||
|
io.WriteString(h, "And Leon's getting laaarger!")
|
||||||
|
fmt.Printf("%x", h.Sum(nil))
|
||||||
|
}
|
||||||
20
_cmptest/urldemo/url.go
Normal file
20
_cmptest/urldemo/url.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
u, err := url.Parse("http://foo.example.com/foo?bar=1")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
u.Scheme = "https"
|
||||||
|
u.Host = "bar.example.com"
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("bar", "2")
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
fmt.Println(u)
|
||||||
|
}
|
||||||
18
_demo/randcrypt/rand.go
Normal file
18
_demo/randcrypt/rand.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c := 10
|
||||||
|
b := make([]byte, c)
|
||||||
|
_, err := rand.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// The slice should now contain random bytes instead of only zeroes.
|
||||||
|
fmt.Printf("%x\n", b)
|
||||||
|
}
|
||||||
3
c/c.go
3
c/c.go
@@ -79,6 +79,9 @@ func AllocaNew[T any]() *T { return nil }
|
|||||||
//go:linkname Malloc C.malloc
|
//go:linkname Malloc C.malloc
|
||||||
func Malloc(size uintptr) Pointer
|
func Malloc(size uintptr) Pointer
|
||||||
|
|
||||||
|
//go:linkname Calloc C.calloc
|
||||||
|
func Calloc(num uintptr, size uintptr) Pointer
|
||||||
|
|
||||||
//go:linkname Free C.free
|
//go:linkname Free C.free
|
||||||
func Free(ptr Pointer)
|
func Free(ptr Pointer)
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
|
||||||
"github.com/goplus/llgo/c/clang"
|
|
||||||
)
|
|
||||||
|
|
||||||
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
|
||||||
depth := *(*c.Uint)(clientData)
|
|
||||||
printAST(cursor, depth+1)
|
|
||||||
return clang.ChildVisit_Continue
|
|
||||||
}
|
|
||||||
|
|
||||||
func printAST(cursor clang.Cursor, depth c.Uint) {
|
|
||||||
cursorKind := cursor.Kind.String()
|
|
||||||
|
|
||||||
cursorSpelling := cursor.String()
|
|
||||||
|
|
||||||
for i := c.Uint(0); i < depth; i++ {
|
|
||||||
c.Fputs(c.Str(" "), c.Stdout)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Printf(c.Str("%s: %s\n"), cursorKind.CStr(), cursorSpelling.CStr())
|
|
||||||
|
|
||||||
cursorKind.Dispose()
|
|
||||||
cursorSpelling.Dispose()
|
|
||||||
|
|
||||||
clang.VisitChildren(cursor, visit, c.Pointer(&depth))
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if c.Argc != 2 {
|
|
||||||
fmt.Fprintln(os.Stderr, "Usage: castdump <headerFile>")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sourceFile := *c.Advance(c.Argv, 1)
|
|
||||||
|
|
||||||
index := clang.CreateIndex(0, 0)
|
|
||||||
|
|
||||||
unit := index.ParseTranslationUnit(
|
|
||||||
sourceFile,
|
|
||||||
nil, 0,
|
|
||||||
nil, 0,
|
|
||||||
clang.TranslationUnit_None,
|
|
||||||
)
|
|
||||||
|
|
||||||
if unit == nil {
|
|
||||||
println("Unable to parse translation unit. Quitting.")
|
|
||||||
c.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor := unit.Cursor()
|
|
||||||
|
|
||||||
printAST(cursor, 0)
|
|
||||||
|
|
||||||
unit.Dispose()
|
|
||||||
index.Dispose()
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
type Context struct {
|
type Context struct {
|
||||||
namespaceName string
|
namespaceName string
|
||||||
className string
|
className string
|
||||||
|
unit *clang.TranslationUnit
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext() *Context {
|
func newContext() *Context {
|
||||||
@@ -26,23 +27,51 @@ func (c *Context) setClassName(name string) {
|
|||||||
c.className = name
|
c.className = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Context) setUnit(unit *clang.TranslationUnit) {
|
||||||
|
c.unit = unit
|
||||||
|
}
|
||||||
|
|
||||||
var context = newContext()
|
var context = newContext()
|
||||||
|
|
||||||
func print_cursor_info(cursor clang.Cursor) {
|
func printCursorLocation(cursor clang.Cursor) {
|
||||||
loc := cursor.Location()
|
loc := cursor.Location()
|
||||||
var file clang.File
|
var file clang.File
|
||||||
var line, column c.Uint
|
var line, column c.Uint
|
||||||
|
|
||||||
loc.SpellingLocation(&file, &line, &column, nil)
|
loc.SpellingLocation(&file, &line, &column, nil)
|
||||||
filename := file.FileName()
|
filename := file.FileName()
|
||||||
|
defer filename.Dispose()
|
||||||
|
|
||||||
c.Printf(c.Str("%s:%d:%d\n"), filename.CStr(), line, column)
|
c.Printf(c.Str("%s:%d:%d\n"), filename.CStr(), line, column)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printMarcoInfo(cursor clang.Cursor) {
|
||||||
|
printCursorLocation(cursor)
|
||||||
|
name := cursor.String()
|
||||||
|
c.Printf(c.Str("Marco Name: %s\n"), name.CStr())
|
||||||
|
ran := cursor.Extent()
|
||||||
|
var numTokens c.Uint
|
||||||
|
var tokens *clang.Token
|
||||||
|
context.unit.Tokenize(ran, &tokens, &numTokens)
|
||||||
|
c.Printf(c.Str("Content: "))
|
||||||
|
|
||||||
|
tokensSlice := unsafe.Slice(tokens, int(numTokens))
|
||||||
|
for _, tok := range tokensSlice {
|
||||||
|
tokStr := context.unit.Token(tok)
|
||||||
|
c.Printf(c.Str("%s "), tokStr.CStr())
|
||||||
|
tokStr.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Printf(c.Str("\n"))
|
||||||
|
println("--------------------------------")
|
||||||
|
}
|
||||||
|
func printFuncInfo(cursor clang.Cursor) {
|
||||||
|
printCursorLocation(cursor)
|
||||||
|
|
||||||
cursorStr := cursor.String()
|
cursorStr := cursor.String()
|
||||||
symbol := cursor.Mangling()
|
symbol := cursor.Mangling()
|
||||||
defer symbol.Dispose()
|
defer symbol.Dispose()
|
||||||
defer cursorStr.Dispose()
|
defer cursorStr.Dispose()
|
||||||
defer filename.Dispose()
|
|
||||||
|
|
||||||
if context.namespaceName != "" && context.className != "" {
|
if context.namespaceName != "" && context.className != "" {
|
||||||
fmt.Printf("%s:%s:", context.namespaceName, context.className)
|
fmt.Printf("%s:%s:", context.namespaceName, context.className)
|
||||||
@@ -51,7 +80,7 @@ func print_cursor_info(cursor clang.Cursor) {
|
|||||||
}
|
}
|
||||||
c.Printf(c.Str("%s\n"), cursorStr.CStr())
|
c.Printf(c.Str("%s\n"), cursorStr.CStr())
|
||||||
|
|
||||||
if cursor.Kind == clang.CXXMethod || cursor.Kind == clang.FunctionDecl {
|
if cursor.Kind == clang.CursorCXXMethod || cursor.Kind == clang.CursorFunctionDecl {
|
||||||
c.Printf(c.Str("symbol:%s\n"), symbol.CStr())
|
c.Printf(c.Str("symbol:%s\n"), symbol.CStr())
|
||||||
|
|
||||||
typeStr := cursor.ResultType().String()
|
typeStr := cursor.ResultType().String()
|
||||||
@@ -78,18 +107,20 @@ func print_cursor_info(cursor clang.Cursor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
||||||
if cursor.Kind == clang.Namespace {
|
if cursor.Kind == clang.CursorMacroDefinition {
|
||||||
|
printMarcoInfo(cursor)
|
||||||
|
} else if cursor.Kind == clang.CursorNamespace {
|
||||||
nameStr := cursor.String()
|
nameStr := cursor.String()
|
||||||
context.setNamespaceName(c.GoString(nameStr.CStr()))
|
context.setNamespaceName(c.GoString(nameStr.CStr()))
|
||||||
clang.VisitChildren(cursor, visit, nil)
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
context.setNamespaceName("")
|
context.setNamespaceName("")
|
||||||
} else if cursor.Kind == clang.ClassDecl {
|
} else if cursor.Kind == clang.CursorClassDecl {
|
||||||
nameStr := cursor.String()
|
nameStr := cursor.String()
|
||||||
context.setClassName(c.GoString(nameStr.CStr()))
|
context.setClassName(c.GoString(nameStr.CStr()))
|
||||||
clang.VisitChildren(cursor, visit, nil)
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
context.setClassName("")
|
context.setClassName("")
|
||||||
} else if cursor.Kind == clang.CXXMethod || cursor.Kind == clang.FunctionDecl {
|
} else if cursor.Kind == clang.CursorCXXMethod || cursor.Kind == clang.CursorFunctionDecl {
|
||||||
print_cursor_info(cursor)
|
printFuncInfo(cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return clang.ChildVisit_Continue
|
return clang.ChildVisit_Continue
|
||||||
@@ -105,7 +136,7 @@ func parse(filename *c.Char) {
|
|||||||
filename,
|
filename,
|
||||||
unsafe.SliceData(args), 3,
|
unsafe.SliceData(args), 3,
|
||||||
nil, 0,
|
nil, 0,
|
||||||
clang.TranslationUnit_None,
|
clang.DetailedPreprocessingRecord,
|
||||||
)
|
)
|
||||||
|
|
||||||
if unit == nil {
|
if unit == nil {
|
||||||
@@ -113,6 +144,7 @@ func parse(filename *c.Char) {
|
|||||||
c.Exit(1)
|
c.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.setUnit(unit)
|
||||||
cursor := unit.Cursor()
|
cursor := unit.Cursor()
|
||||||
|
|
||||||
clang.VisitChildren(cursor, visit, nil)
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
|
|||||||
@@ -33,8 +33,30 @@ void wrap_clang_getCursorType(CXCursor *cur, CXType *typ) { *typ = clang_getCurs
|
|||||||
|
|
||||||
void wrap_clang_getCursorResultType(CXCursor *cur, CXType *typ) { *typ = clang_getCursorResultType(*cur); }
|
void wrap_clang_getCursorResultType(CXCursor *cur, CXType *typ) { *typ = clang_getCursorResultType(*cur); }
|
||||||
|
|
||||||
|
void wrap_clang_getResultType(CXType *typ, CXType *resultTyp) { *resultTyp = clang_getResultType(*typ); }
|
||||||
|
|
||||||
|
int wrap_clang_getNumArgTypes(CXType *typ) { return clang_getNumArgTypes(*typ); }
|
||||||
|
|
||||||
|
void wrap_clang_getArgType(CXType *typ, unsigned i, CXType *argTyp) { *argTyp = clang_getArgType(*typ, i); }
|
||||||
|
|
||||||
|
long long wrap_clang_getEnumConstantDeclValue(CXCursor *cur) { return clang_getEnumConstantDeclValue(*cur); }
|
||||||
|
|
||||||
|
void wrap_clang_getPointeeType(CXType *pointerTyp, CXType *pointeeTyp) {
|
||||||
|
*pointeeTyp = clang_getPointeeType(*pointerTyp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap_clang_getArrayElementType(CXType *arrayTyp, CXType *elemTyp) {
|
||||||
|
*elemTyp = clang_getArrayElementType(*arrayTyp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap_clang_getCanonicalType(CXType *typ, CXType *canonicalType) { *canonicalType = clang_getCanonicalType(*typ); }
|
||||||
|
|
||||||
CXString wrap_clang_getTypeSpelling(CXType *typ) { return clang_getTypeSpelling(*typ); }
|
CXString wrap_clang_getTypeSpelling(CXType *typ) { return clang_getTypeSpelling(*typ); }
|
||||||
|
|
||||||
|
CXString wrap_clang_getTokenSpelling(CXTranslationUnit unit, CXToken *token) {
|
||||||
|
return clang_getTokenSpelling(unit, *token);
|
||||||
|
}
|
||||||
|
|
||||||
void wrap_clang_getCursorLocation(CXCursor *cur, CXSourceLocation *loc) { *loc = clang_getCursorLocation(*cur); }
|
void wrap_clang_getCursorLocation(CXCursor *cur, CXSourceLocation *loc) { *loc = clang_getCursorLocation(*cur); }
|
||||||
|
|
||||||
void wrap_clang_getSpellingLocation(CXSourceLocation *loc, CXFile *file, unsigned *line, unsigned *column,
|
void wrap_clang_getSpellingLocation(CXSourceLocation *loc, CXFile *file, unsigned *line, unsigned *column,
|
||||||
@@ -42,6 +64,16 @@ void wrap_clang_getSpellingLocation(CXSourceLocation *loc, CXFile *file, unsigne
|
|||||||
clang_getSpellingLocation(*loc, file, line, column, offset);
|
clang_getSpellingLocation(*loc, file, line, column, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CX_CXXAccessSpecifier wrap_clang_getCXXAccessSpecifier(CXCursor *cursor) {
|
||||||
|
return clang_getCXXAccessSpecifier(*cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap_clang_getCursorExtent(CXCursor *cur, CXSourceRange *range) { *range = clang_getCursorExtent(*cur); }
|
||||||
|
|
||||||
|
void wrap_clang_tokenize(CXTranslationUnit unit, CXSourceRange *Range, CXToken **Tokens, unsigned *NumTokens) {
|
||||||
|
clang_tokenize(unit, *Range, Tokens, NumTokens);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned wrap_clang_visitChildren(CXCursor *parent, wrap_CXCursorVisitor visitor, CXClientData client_data) {
|
unsigned wrap_clang_visitChildren(CXCursor *parent, wrap_CXCursorVisitor visitor, CXClientData client_data) {
|
||||||
wrap_data data = {client_data, visitor};
|
wrap_data data = {client_data, visitor};
|
||||||
return clang_visitChildren(*parent, wrap_visitor, CXClientData(&data));
|
return clang_visitChildren(*parent, wrap_visitor, CXClientData(&data));
|
||||||
|
|||||||
1022
c/clang/clang.go
1022
c/clang/clang.go
File diff suppressed because it is too large
Load Diff
41
c/libuv/_demo/async/async.go
Normal file
41
c/libuv/_demo/async/async.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/libuv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ensure(b bool, msg string) {
|
||||||
|
if !b {
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
loop := libuv.LoopNew()
|
||||||
|
defer loop.Close()
|
||||||
|
|
||||||
|
a := &libuv.Async{}
|
||||||
|
r := loop.Async(a, func(a *libuv.Async) {
|
||||||
|
println("async callback")
|
||||||
|
a.Close(nil) // or loop.Stop()
|
||||||
|
})
|
||||||
|
ensure(r == 0, "Async failed")
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
println("begin async task")
|
||||||
|
c.Usleep(100 * 1000)
|
||||||
|
println("send async event")
|
||||||
|
ensure(a.Send() == 0, "Send failed")
|
||||||
|
}()
|
||||||
|
|
||||||
|
loop.Run(libuv.RUN_DEFAULT)
|
||||||
|
println("done")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Expected Output:
|
||||||
|
begin async task
|
||||||
|
send async event
|
||||||
|
async callback
|
||||||
|
done
|
||||||
|
*/
|
||||||
@@ -13,11 +13,11 @@ const BUFFER_SIZE = 1024
|
|||||||
var (
|
var (
|
||||||
loop *libuv.Loop
|
loop *libuv.Loop
|
||||||
openReq libuv.Fs
|
openReq libuv.Fs
|
||||||
readReq libuv.Fs
|
|
||||||
closeReq libuv.Fs
|
closeReq libuv.Fs
|
||||||
|
|
||||||
buffer [BUFFER_SIZE]c.Char
|
buffer [BUFFER_SIZE]c.Char
|
||||||
iov libuv.Buf
|
iov libuv.Buf
|
||||||
|
file libuv.File
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -31,7 +31,11 @@ func main() {
|
|||||||
libuv.FsOpen(loop, &openReq, c.Str("example.txt"), os.O_RDONLY, 0, onOpen)
|
libuv.FsOpen(loop, &openReq, c.Str("example.txt"), os.O_RDONLY, 0, onOpen)
|
||||||
|
|
||||||
// Run the loop
|
// Run the loop
|
||||||
libuv.Run(loop, libuv.RUN_DEFAULT)
|
result := loop.Run(libuv.RUN_DEFAULT)
|
||||||
|
|
||||||
|
if result != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Error in Run: %s\n"), libuv.Strerror(libuv.Errno(result)))
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
@@ -39,59 +43,74 @@ func main() {
|
|||||||
|
|
||||||
func onOpen(req *libuv.Fs) {
|
func onOpen(req *libuv.Fs) {
|
||||||
// Check for errors
|
// Check for errors
|
||||||
if libuv.FsGetResult(req) < 0 {
|
if req.GetResult() < 0 {
|
||||||
c.Fprintf(c.Stderr, c.Str("Error opening file: %s\n"), libuv.Strerror(libuv.Errno(libuv.LoopClose(loop))))
|
c.Fprintf(c.Stderr, c.Str("Error opening file: %s\n"), libuv.Strerror(libuv.Errno(req.GetResult())))
|
||||||
libuv.LoopClose(loop)
|
loop.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the file descriptor
|
||||||
|
file = libuv.File(req.GetResult())
|
||||||
|
|
||||||
// Init buffer
|
// Init buffer
|
||||||
iov = libuv.InitBuf((*c.Char)(unsafe.Pointer(&buffer[0])), c.Uint(unsafe.Sizeof(buffer)))
|
iov = libuv.InitBuf((*c.Char)(unsafe.Pointer(&buffer[0])), c.Uint(unsafe.Sizeof(buffer)))
|
||||||
|
|
||||||
// Read the file
|
// Read the file
|
||||||
readRes := libuv.FsRead(loop, &readReq, libuv.File(libuv.FsGetResult(req)), &iov, 1, -1, onRead)
|
readFile()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func readFile() {
|
||||||
|
// Initialize the request every time
|
||||||
|
var readReq libuv.Fs
|
||||||
|
|
||||||
|
// Read the file
|
||||||
|
readRes := libuv.FsRead(loop, &readReq, file, &iov, 1, -1, onRead)
|
||||||
if readRes != 0 {
|
if readRes != 0 {
|
||||||
c.Printf(c.Str("Error in FsRead: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(readRes)), readRes)
|
c.Printf(c.Str("Error in FsRead: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(readRes)), readRes)
|
||||||
libuv.LoopClose(loop)
|
readReq.ReqCleanup()
|
||||||
return
|
loop.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func onRead(req *libuv.Fs) {
|
func onRead(req *libuv.Fs) {
|
||||||
|
// Cleanup the request
|
||||||
|
defer req.ReqCleanup()
|
||||||
// Check for errors
|
// Check for errors
|
||||||
if libuv.FsGetResult(req) < 0 {
|
if req.GetResult() < 0 {
|
||||||
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(libuv.Errno(libuv.FsGetResult(req))))
|
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(libuv.Errno(req.GetResult())))
|
||||||
libuv.LoopClose(loop)
|
} else if req.GetResult() == 0 {
|
||||||
} else if libuv.FsGetResult(req) == 0 {
|
|
||||||
c.Printf(c.Str("EOF\n"))
|
|
||||||
// Close the file
|
// Close the file
|
||||||
closeRes := libuv.FsClose(loop, &closeReq, libuv.File(libuv.FsGetResult(&openReq)), onClose)
|
closeRes := libuv.FsClose(loop, &closeReq, libuv.File(openReq.GetResult()), onClose)
|
||||||
if closeRes != 0 {
|
if closeRes != 0 {
|
||||||
// Print the content
|
|
||||||
c.Printf(c.Str("Error in FsClose: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(closeRes)), closeRes)
|
c.Printf(c.Str("Error in FsClose: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(closeRes)), closeRes)
|
||||||
libuv.LoopClose(loop)
|
loop.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.Printf(c.Str("Read %d bytes\n"), libuv.FsGetResult(req))
|
c.Printf(c.Str("Read %d bytes\n"), req.GetResult())
|
||||||
c.Printf(c.Str("Read content: %.*s\n"), libuv.FsGetResult(req), (*c.Char)(unsafe.Pointer(&buffer[0])))
|
c.Printf(c.Str("Read content: %.*s\n"), req.GetResult(), (*c.Char)(unsafe.Pointer(&buffer[0])))
|
||||||
libuv.LoopClose(loop)
|
// Read the file again
|
||||||
|
readFile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func onClose(req *libuv.Fs) {
|
func onClose(req *libuv.Fs) {
|
||||||
// Check for errors
|
// Check for errors
|
||||||
if libuv.FsGetResult(req) < 0 {
|
if req.GetResult() < 0 {
|
||||||
c.Fprintf(c.Stderr, c.Str("Error closing file: %s\n"), libuv.Strerror(libuv.Errno(libuv.FsGetResult(req))))
|
c.Fprintf(c.Stderr, c.Str("Error closing file: %s\n"), libuv.Strerror(libuv.Errno(req.GetResult())))
|
||||||
} else {
|
} else {
|
||||||
c.Printf(c.Str("\nFile closed successfully.\n"))
|
c.Printf(c.Str("\nFile closed successfully.\n"))
|
||||||
}
|
}
|
||||||
libuv.LoopClose(loop)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanup() {
|
func cleanup() {
|
||||||
// Cleanup the requests
|
// Cleanup the requests
|
||||||
libuv.FsReqCleanup(&openReq)
|
openReq.ReqCleanup()
|
||||||
libuv.FsReqCleanup(&readReq)
|
closeReq.ReqCleanup()
|
||||||
libuv.FsReqCleanup(&closeReq)
|
|
||||||
// Close the loop
|
// Close the loop
|
||||||
libuv.LoopClose(loop)
|
result := loop.Close()
|
||||||
|
if result != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Error in LoopClose: %s\n"), libuv.Strerror(libuv.Errno(result)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/libuv"
|
"github.com/goplus/llgo/c/libuv"
|
||||||
"github.com/goplus/llgo/c/net"
|
"github.com/goplus/llgo/c/net"
|
||||||
@@ -11,20 +9,18 @@ import (
|
|||||||
var DEFAULT_PORT c.Int = 8080
|
var DEFAULT_PORT c.Int = 8080
|
||||||
var DEFAULT_BACKLOG c.Int = 128
|
var DEFAULT_BACKLOG c.Int = 128
|
||||||
|
|
||||||
var loop *libuv.Loop
|
var (
|
||||||
|
Req *libuv.Write
|
||||||
type WriteReq struct {
|
|
||||||
Req libuv.Write
|
|
||||||
Buf libuv.Buf
|
Buf libuv.Buf
|
||||||
}
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Initialize the default event loop
|
// Initialize the default event loop
|
||||||
loop = libuv.DefaultLoop()
|
var loop = libuv.DefaultLoop()
|
||||||
|
|
||||||
// Initialize a TCP server
|
// Initialize a TCP server
|
||||||
var server libuv.Tcp
|
server := &libuv.Tcp{}
|
||||||
libuv.InitTcp(loop, &server)
|
libuv.InitTcp(loop, server)
|
||||||
|
|
||||||
// Set up the address to bind the server to
|
// Set up the address to bind the server to
|
||||||
var addr net.SockaddrIn
|
var addr net.SockaddrIn
|
||||||
@@ -32,22 +28,20 @@ func main() {
|
|||||||
c.Printf(c.Str("Listening on %s:%d\n"), c.Str("0.0.0.0"), DEFAULT_PORT)
|
c.Printf(c.Str("Listening on %s:%d\n"), c.Str("0.0.0.0"), DEFAULT_PORT)
|
||||||
|
|
||||||
// Bind the server to the specified address and port
|
// Bind the server to the specified address and port
|
||||||
(&server).Bind((*net.SockAddr)(c.Pointer(&addr)), 0)
|
server.Bind((*net.SockAddr)(c.Pointer(&addr)), 0)
|
||||||
res := (*libuv.Stream)(&server).Listen(DEFAULT_BACKLOG, OnNewConnection)
|
res := (*libuv.Stream)(server).Listen(DEFAULT_BACKLOG, OnNewConnection)
|
||||||
if res != 0 {
|
if res != 0 {
|
||||||
c.Fprintf(c.Stderr, c.Str("Listen error: %s\n"), libuv.Strerror((libuv.Errno(res))))
|
c.Fprintf(c.Stderr, c.Str("Listen error: %s\n"), libuv.Strerror(libuv.Errno(res)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start listening for incoming connections
|
// Start listening for incoming connections
|
||||||
libuv.Run(loop, libuv.RUN_DEFAULT)
|
loop.Run(libuv.RUN_DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FreeWriteReq(req *libuv.Write) {
|
func FreeWriteReq() {
|
||||||
wr := (*WriteReq)(c.Pointer(req))
|
// Free the buffer base.
|
||||||
// Free the buffer base and the WriteReq itself.
|
c.Free(c.Pointer(Buf.Base))
|
||||||
c.Free(c.Pointer(wr.Buf.Base))
|
|
||||||
c.Free(c.Pointer(wr))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func AllocBuffer(handle *libuv.Handle, suggestedSize uintptr, buf *libuv.Buf) {
|
func AllocBuffer(handle *libuv.Handle, suggestedSize uintptr, buf *libuv.Buf) {
|
||||||
@@ -58,29 +52,24 @@ func AllocBuffer(handle *libuv.Handle, suggestedSize uintptr, buf *libuv.Buf) {
|
|||||||
|
|
||||||
func EchoWrite(req *libuv.Write, status c.Int) {
|
func EchoWrite(req *libuv.Write, status c.Int) {
|
||||||
if status != 0 {
|
if status != 0 {
|
||||||
c.Fprintf(c.Stderr, c.Str("Write error: %s\n"), libuv.Strerror((libuv.Errno(status))))
|
c.Fprintf(c.Stderr, c.Str("Write error: %s\n"), libuv.Strerror(libuv.Errno(status)))
|
||||||
}
|
}
|
||||||
FreeWriteReq(req)
|
FreeWriteReq()
|
||||||
}
|
}
|
||||||
|
|
||||||
func EchoRead(client *libuv.Stream, nread c.Long, buf *libuv.Buf) {
|
func EchoRead(client *libuv.Stream, nread c.Long, buf *libuv.Buf) {
|
||||||
if nread > 0 {
|
if nread > 0 {
|
||||||
req := (*WriteReq)(c.Malloc(unsafe.Sizeof(WriteReq{})))
|
|
||||||
if req == nil {
|
|
||||||
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for write request\n"))
|
|
||||||
c.Free(c.Pointer(buf.Base))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Initialize the buffer with the data read.
|
// Initialize the buffer with the data read.
|
||||||
req.Buf = libuv.InitBuf(buf.Base, c.Uint(nread))
|
Buf = libuv.InitBuf(buf.Base, c.Uint(nread))
|
||||||
// Write the data back to the client.
|
// Write the data back to the client.
|
||||||
(&req.Req).Write(client, &req.Buf, 1, EchoWrite)
|
Req = &libuv.Write{}
|
||||||
|
Req.Write(client, &Buf, 1, EchoWrite)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if nread < 0 {
|
if nread < 0 {
|
||||||
// Handle read errors and EOF.
|
// Handle read errors and EOF.
|
||||||
if (libuv.Errno)(nread) != libuv.EOF {
|
if (libuv.Errno)(nread) != libuv.EOF {
|
||||||
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror((libuv.Errno)(nread)))
|
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(libuv.Errno(nread)))
|
||||||
}
|
}
|
||||||
(*libuv.Handle)(c.Pointer(client)).Close(nil)
|
(*libuv.Handle)(c.Pointer(client)).Close(nil)
|
||||||
}
|
}
|
||||||
@@ -97,7 +86,7 @@ func OnNewConnection(server *libuv.Stream, status c.Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for a new client.
|
// Allocate memory for a new client.
|
||||||
client := (*libuv.Tcp)(c.Malloc(unsafe.Sizeof(libuv.Tcp{})))
|
client := &libuv.Tcp{}
|
||||||
|
|
||||||
if client == nil {
|
if client == nil {
|
||||||
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for client\n"))
|
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for client\n"))
|
||||||
@@ -105,7 +94,7 @@ func OnNewConnection(server *libuv.Stream, status c.Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the client TCP handle.
|
// Initialize the client TCP handle.
|
||||||
if libuv.InitTcp(loop, client) < 0 {
|
if libuv.InitTcp(libuv.DefaultLoop(), client) < 0 {
|
||||||
c.Fprintf(c.Stderr, c.Str("Failed to initialize client\n"))
|
c.Fprintf(c.Stderr, c.Str("Failed to initialize client\n"))
|
||||||
c.Free(c.Pointer(client))
|
c.Free(c.Pointer(client))
|
||||||
return
|
return
|
||||||
|
|||||||
5
c/libuv/_wrap/libuv.c
Normal file
5
c/libuv/_wrap/libuv.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
int uv_tcp_get_io_watcher_fd (uv_tcp_t* handle) {
|
||||||
|
return handle->io_watcher.fd;
|
||||||
|
}
|
||||||
50
c/libuv/async.go
Normal file
50
c/libuv/async.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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 libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// struct uv_async_t
|
||||||
|
type Async struct {
|
||||||
|
Handle
|
||||||
|
// On macOS arm64, sizeof uv_async_t is 128 bytes.
|
||||||
|
// Handle is 92 bytes, so we need 36 bytes to fill the gap.
|
||||||
|
// Maybe reserve more for future use.
|
||||||
|
Unused [36]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedef void (*uv_async_cb)(uv_async_t* handle);
|
||||||
|
// llgo:type C
|
||||||
|
type AsyncCb func(*Async)
|
||||||
|
|
||||||
|
// int uv_async_init(uv_loop_t*, uv_async_t* async, uv_async_cb async_cb);
|
||||||
|
//
|
||||||
|
// llgo:link (*Loop).Async C.uv_async_init
|
||||||
|
func (loop *Loop) Async(a *Async, cb AsyncCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// int uv_async_send(uv_async_t* async);
|
||||||
|
//
|
||||||
|
// llgo:link (*Async).Send C.uv_async_send
|
||||||
|
func (a *Async) Send() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
103
c/libuv/fs.go
103
c/libuv/fs.go
@@ -69,7 +69,7 @@ type File c.Int
|
|||||||
/* Handle types. */
|
/* Handle types. */
|
||||||
|
|
||||||
type Fs struct {
|
type Fs struct {
|
||||||
Unused [0]byte
|
Unused [440]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type FsEvent struct {
|
type FsEvent struct {
|
||||||
@@ -106,29 +106,40 @@ type FsPollCb func(handle *FsPoll, status c.Int, events c.Int)
|
|||||||
|
|
||||||
/* Fs related function and method */
|
/* Fs related function and method */
|
||||||
|
|
||||||
//go:linkname FsGetType C.uv_fs_get_type
|
// llgo:link (*Fs).GetType C.uv_fs_get_type
|
||||||
func FsGetType(req *Fs) FsType
|
func (req *Fs) GetType() FsType {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsGetPath C.uv_fs_get_path
|
// llgo:link (*Fs).GetPath C.uv_fs_get_path
|
||||||
func FsGetPath(req *Fs) *c.Char
|
func (req *Fs) GetPath() *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsGetResult C.uv_fs_get_result
|
// llgo:link (*Fs).GetResult C.uv_fs_get_result
|
||||||
func FsGetResult(req *Fs) c.Int
|
func (req *Fs) GetResult() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsGetPtr C.uv_fs_get_ptr
|
// llgo:link (*Fs).GetPtr C.uv_fs_get_ptr
|
||||||
func FsGetPtr(req *Fs) c.Pointer
|
func (req *Fs) GetPtr() c.Pointer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsGetSystemError C.uv_fs_get_system_error
|
// llgo:link (*Fs).GetSystemError C.uv_fs_get_system_error
|
||||||
func FsGetSystemError(req *Fs) c.Int
|
func (req *Fs) GetSystemError() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsGetStatBuf C.uv_fs_get_statbuf
|
// llgo:link (*Fs).GetStatBuf C.uv_fs_get_statbuf
|
||||||
func FsGetStatBuf(req *Fs) *Stat
|
func (req *Fs) GetStatBuf() *Stat {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsReqCleanup C.uv_fs_req_cleanup
|
// llgo:link (*Fs).ReqCleanup C.uv_fs_req_cleanup
|
||||||
func FsReqCleanup(req *Fs)
|
func (req *Fs) ReqCleanup() {
|
||||||
|
// No return value needed for this method
|
||||||
//go:linkname DefaultLoop C.uv_default_loop
|
}
|
||||||
func DefaultLoop() *Loop
|
|
||||||
|
|
||||||
//go:linkname FsOpen C.uv_fs_open
|
//go:linkname FsOpen C.uv_fs_open
|
||||||
func FsOpen(loop *Loop, req *Fs, path *c.Char, flags c.Int, mode c.Int, cb FsCb) c.Int
|
func FsOpen(loop *Loop, req *Fs, path *c.Char, flags c.Int, mode c.Int, cb FsCb) c.Int
|
||||||
@@ -241,32 +252,56 @@ func FsLchown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb)
|
|||||||
//go:linkname FsLstat C.uv_fs_lstat
|
//go:linkname FsLstat C.uv_fs_lstat
|
||||||
func FsLstat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
func FsLstat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* FsEvent related function and method */
|
||||||
|
|
||||||
//go:linkname FsEventInit C.uv_fs_event_init
|
//go:linkname FsEventInit C.uv_fs_event_init
|
||||||
func FsEventInit(loop *Loop, handle *FsEvent) c.Int
|
func FsEventInit(loop *Loop, handle *FsEvent) c.Int
|
||||||
|
|
||||||
//go:linkname FsEventStart C.uv_fs_event_start
|
// llgo:link (*FsEvent).Start C.uv_fs_event_start
|
||||||
func FsEventStart(handle *FsEvent, cb FsEventCb, path *c.Char, flags c.Int) c.Int
|
func (handle *FsEvent) Start(cb FsEventCb, path *c.Char, flags c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsEventStop C.uv_fs_event_stop
|
// llgo:link (*FsEvent).Stop C.uv_fs_event_stop
|
||||||
func FsEventStop(handle *FsEvent) c.Int
|
func (handle *FsEvent) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsEventClose C.uv_fs_event_close
|
// llgo:link (*FsEvent).Close C.uv_fs_event_close
|
||||||
func FsEventClose(handle *FsEvent) c.Int
|
func (handle *FsEvent) Close() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsEventGetpath C.uv_fs_event_getpath
|
// llgo:link (*FsEvent).Getpath C.uv_fs_event_getpath
|
||||||
func FsEventGetpath(handle *FsEvent) *c.Char
|
func (handle *FsEvent) Getpath() *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* FsPoll related function and method */
|
||||||
|
|
||||||
//go:linkname FsPollInit C.uv_fs_poll_init
|
//go:linkname FsPollInit C.uv_fs_poll_init
|
||||||
func FsPollInit(loop *Loop, handle *FsPoll) c.Int
|
func FsPollInit(loop *Loop, handle *FsPoll) c.Int
|
||||||
|
|
||||||
//go:linkname FsPollStart C.uv_fs_poll_start
|
// llgo:link (*FsPoll).Start C.uv_fs_poll_start
|
||||||
func FsPollStart(handle *FsPoll, cb FsPollCb, path *c.Char, interval uint) c.Int
|
func (handle *FsPoll) Start(cb FsPollCb, path *c.Char, interval uint) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsPollStop C.uv_fs_poll_stop
|
// llgo:link (*FsPoll).Stop C.uv_fs_poll_stop
|
||||||
func FsPollStop(handle *FsPoll) c.Int
|
func (handle *FsPoll) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsPollClose C.uv_fs_poll_close
|
// llgo:link (*FsPoll).Close C.uv_fs_poll_close
|
||||||
func FsPollClose(handle *FsPoll) c.Int
|
func (handle *FsPoll) Close() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname FsPollGetPath C.uv_fs_poll_getpath
|
// llgo:link (*FsPoll).GetPath C.uv_fs_poll_getpath
|
||||||
func FsPollGetPath(handle *FsPoll) *c.Char
|
func (handle *FsPoll) GetPath() *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
337
c/libuv/libuv.go
337
c/libuv/libuv.go
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
LLGoPackage = "link: $(pkg-config --libs libuv); -luv"
|
LLGoPackage = "link: $(pkg-config --libs libuv); -luv"
|
||||||
|
LLGoFiles = "$(pkg-config --cflags libuv): _wrap/libuv.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
@@ -97,44 +98,12 @@ type Loop struct {
|
|||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handle struct {
|
|
||||||
Unused [96]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Stream struct {
|
|
||||||
Unused [264]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Poll struct {
|
type Poll struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Request types. */
|
/* Request types. */
|
||||||
|
|
||||||
type Req struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetAddrInfo struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetNameInfo struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Shutdown struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Write struct {
|
|
||||||
Unused [192]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Connect struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Buf struct {
|
type Buf struct {
|
||||||
Base *c.Char
|
Base *c.Char
|
||||||
Len uintptr
|
Len uintptr
|
||||||
@@ -157,24 +126,12 @@ type FreeFunc func(ptr c.Pointer)
|
|||||||
// llgo:type C
|
// llgo:type C
|
||||||
type AllocCb func(handle *Handle, suggestedSize uintptr, buf *Buf)
|
type AllocCb func(handle *Handle, suggestedSize uintptr, buf *Buf)
|
||||||
|
|
||||||
// llgo:type C
|
|
||||||
type ReadCb func(stream *Stream, nread c.Long, buf *Buf)
|
|
||||||
|
|
||||||
// llgo:type C
|
|
||||||
type WriteCb func(req *Write, status c.Int)
|
|
||||||
|
|
||||||
// llgo:type C
|
// llgo:type C
|
||||||
type GetaddrinfoCb func(req *GetAddrInfo, status c.Int, res *net.AddrInfo)
|
type GetaddrinfoCb func(req *GetAddrInfo, status c.Int, res *net.AddrInfo)
|
||||||
|
|
||||||
// llgo:type C
|
// llgo:type C
|
||||||
type GetnameinfoCb func(req *GetNameInfo, status c.Int, hostname *c.Char, service *c.Char)
|
type GetnameinfoCb func(req *GetNameInfo, status c.Int, hostname *c.Char, service *c.Char)
|
||||||
|
|
||||||
// llgo:type C
|
|
||||||
type ConnectionCb func(server *Stream, status c.Int)
|
|
||||||
|
|
||||||
// llgo:type C
|
|
||||||
type ShutdownCb func(req *Shutdown, status c.Int)
|
|
||||||
|
|
||||||
// llgo:type C
|
// llgo:type C
|
||||||
type WalkCb func(handle *Handle, arg c.Pointer)
|
type WalkCb func(handle *Handle, arg c.Pointer)
|
||||||
|
|
||||||
@@ -197,223 +154,88 @@ func ReplaceAllocator(mallocFunc MallocFunc, reallocFunc ReallocFunc, callocFunc
|
|||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
// llgo:link (*Shutdown).Shutdown C.uv_shutdown
|
|
||||||
func (shutdown *Shutdown) Shutdown(stream *Stream, shutdownCb ShutdownCb) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
/* Handle related function and method */
|
|
||||||
|
|
||||||
// llgo:link (*Handle).Ref C.uv_ref
|
|
||||||
func (handle *Handle) Ref() {}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).Unref C.uv_unref
|
|
||||||
func (handle *Handle) Unref() {}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).HasRef C.uv_has_ref
|
|
||||||
func (handle *Handle) HasRef() c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname HandleSize C.uv_handle_size
|
|
||||||
func HandleSize(handleType HandleType) uintptr
|
|
||||||
|
|
||||||
// llgo:link (*Handle).GetType C.uv_handle_get_type
|
|
||||||
func (handle *Handle) GetType() HandleType {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname HandleTypeName C.uv_handle_type_name
|
|
||||||
func HandleTypeName(handleType HandleType) *c.Char
|
|
||||||
|
|
||||||
// llgo:link (*Handle).GetData C.uv_handle_get_data
|
|
||||||
func (handle *Handle) GetData() c.Pointer {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).GetLoop C.uv_handle_get_loop
|
|
||||||
func (handle *Handle) GetLoop() *Loop {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).SetData C.uv_handle_set_data
|
|
||||||
func (handle *Handle) SetData(data c.Pointer) {}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).IsActive C.uv_is_active
|
|
||||||
func (handle *Handle) IsActive() c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).Close C.uv_close
|
|
||||||
func (handle *Handle) Close(closeCb CloseCb) {}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).SendBufferSize C.uv_send_buffer_size
|
|
||||||
func (handle *Handle) SendBufferSize(value *c.Int) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).RecvBufferSize C.uv_recv_buffer_size
|
|
||||||
func (handle *Handle) RecvBufferSize(value *c.Int) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).Fileno C.uv_fileno
|
|
||||||
func (handle *Handle) Fileno(fd *OsFd) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname Pipe C.uv_pipe
|
|
||||||
func Pipe(fds [2]File, readFlags c.Int, writeFlags c.Int) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname Socketpair C.uv_socketpair
|
|
||||||
func Socketpair(_type c.Int, protocol c.Int, socketVector [2]OsSock, flag0 c.Int, flag1 c.Int) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Handle).IsClosing C.uv_is_closing
|
|
||||||
func (handle *Handle) IsClosing() c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
/* Req related function and method */
|
|
||||||
|
|
||||||
//go:linkname ReqSize C.uv_req_size
|
|
||||||
func ReqSize(reqType ReqType) uintptr
|
|
||||||
|
|
||||||
// llgo:link (*Req).GetData C.uv_req_get_data
|
|
||||||
func (req *Req) GetData() c.Pointer {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Req).SetData C.uv_handle_set_data
|
|
||||||
func (req *Req) SetData(data c.Pointer) {}
|
|
||||||
|
|
||||||
// llgo:link (*Req).GetType C.uv_req_get_type
|
|
||||||
func (req *Req) GetType() ReqType {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname TypeName C.uv_req_type_name
|
|
||||||
func TypeName(reqType ReqType) *c.Char
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
/* Stream related function and method */
|
|
||||||
|
|
||||||
// llgo:link (*Stream).GetWriteQueueSize C.uv_stream_get_write_queue_size
|
|
||||||
func (stream *Stream) GetWriteQueueSize() uintptr {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).Listen C.uv_listen
|
|
||||||
func (stream *Stream) Listen(backlog c.Int, connectionCb ConnectionCb) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).Accept C.uv_accept
|
|
||||||
func (server *Stream) Accept(client *Stream) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).StartRead C.uv_read_start
|
|
||||||
func (stream *Stream) StartRead(allocCb AllocCb, readCb ReadCb) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).StopRead C.uv_read_stop
|
|
||||||
func (stream *Stream) StopRead() c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Write).Write C.uv_write
|
|
||||||
func (req *Write) Write(stream *Stream, bufs *Buf, nbufs c.Uint, writeCb WriteCb) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Write).Write2 C.uv_write2
|
|
||||||
func (req *Write) Write2(stream *Stream, bufs *Buf, nbufs c.Uint, sendStream *Stream, writeCb WriteCb) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).TryWrite C.uv_try_write
|
|
||||||
func (stream *Stream) TryWrite(bufs *Buf, nbufs c.Uint) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).TryWrite2 C.uv_try_write2
|
|
||||||
func (stream *Stream) TryWrite2(bufs *Buf, nbufs c.Uint, sendStream *Stream) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).IsReadable C.uv_is_readable
|
|
||||||
func (stream *Stream) IsReadable() c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).IsWritable C.uv_is_writable
|
|
||||||
func (stream *Stream) IsWritable() c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*Stream).SetBlocking C.uv_stream_set_blocking
|
|
||||||
func (stream *Stream) SetBlocking(blocking c.Int) c.Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
/* Loop related functions and method. */
|
/* Loop related functions and method. */
|
||||||
|
|
||||||
|
//go:linkname DefaultLoop C.uv_default_loop
|
||||||
|
func DefaultLoop() *Loop
|
||||||
|
|
||||||
//go:linkname LoopSize C.uv_loop_size
|
//go:linkname LoopSize C.uv_loop_size
|
||||||
func LoopSize() uintptr
|
func LoopSize() uintptr
|
||||||
|
|
||||||
//go:linkname Run C.uv_run
|
// llgo:link (*Loop).Run C.uv_run
|
||||||
func Run(loop *Loop, mode RunMode) c.Int
|
func (loop *Loop) Run(mode RunMode) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopAlive C.uv_loop_alive
|
// llgo:link (*Loop).Alive C.uv_loop_alive
|
||||||
func LoopAlive(loop *Loop) c.Int
|
func (loop *Loop) Alive() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopClose C.uv_loop_close
|
// void uv_stop(uv_loop_t *loop)
|
||||||
func LoopClose(loop *Loop) c.Int
|
//
|
||||||
|
// llgo:link (*Loop).Stop C.uv_stop
|
||||||
|
func (loop *Loop) Stop() {}
|
||||||
|
|
||||||
//go:linkname LoopConfigure C.uv_loop_configure
|
// llgo:link (*Loop).Close C.uv_loop_close
|
||||||
func LoopConfigure(loop *Loop, option LoopOption, arg c.Int) c.Int
|
func (loop *Loop) Close() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopDefault C.uv_default_loop
|
// llgo:link (*Loop).Configure C.uv_loop_configure
|
||||||
func LoopDefault() *Loop
|
func (loop *Loop) Configure(option LoopOption, arg c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopDelete C.uv_loop_delete
|
// llgo:link LoopDefault C.uv_default_loop
|
||||||
func LoopDelete(loop *Loop) c.Int
|
func LoopDefault() *Loop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopFork C.uv_loop_fork
|
// llgo:link (*Loop).Delete C.uv_loop_delete
|
||||||
func LoopFork(loop *Loop) c.Int
|
func (loop *Loop) Delete() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopInit C.uv_loop_init
|
// llgo:link (*Loop).Fork C.uv_loop_fork
|
||||||
func LoopInit(loop *Loop) c.Int
|
func (loop *Loop) Fork() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopNew C.uv_loop_new
|
// llgo:link (*Loop).Init C.uv_loop_init
|
||||||
func LoopNew() *Loop
|
func (loop *Loop) Init() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopNow C.uv_now
|
// llgo:link LoopNew C.uv_loop_new
|
||||||
func LoopNow(loop *Loop) c.UlongLong
|
func LoopNew() *Loop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopUpdateTime C.uv_update_time
|
// llgo:link (*Loop).Now C.uv_now
|
||||||
func LoopUpdateTime(loop *Loop)
|
func (loop *Loop) Now() c.UlongLong {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopBackendFd C.uv_backend_fd
|
// llgo:link (*Loop).UpdateTime C.uv_update_time
|
||||||
func LoopBackendFd(loop *Loop) c.Int
|
func (loop *Loop) UpdateTime() {
|
||||||
|
// No return value needed for this method
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopBackendTimeout C.uv_backend_timeout
|
// llgo:link (*Loop).BackendFd C.uv_backend_fd
|
||||||
func LoopBackendTimeout(loop *Loop) c.Int
|
func (loop *Loop) BackendFd() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname LoopWalk C.uv_walk
|
// llgo:link (*Loop).BackendTimeout C.uv_backend_timeout
|
||||||
func LoopWalk(loop *Loop, walkCb WalkCb, arg c.Pointer)
|
func (loop *Loop) BackendTimeout() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Walk C.uv_walk
|
||||||
|
func (loop *Loop) Walk(walkCb WalkCb, arg c.Pointer) {
|
||||||
|
// No return value needed for this method
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
@@ -429,28 +251,15 @@ func InitBuf(base *c.Char, len c.Uint) Buf
|
|||||||
//go:linkname PollInit C.uv_poll_init
|
//go:linkname PollInit C.uv_poll_init
|
||||||
func PollInit(loop *Loop, handle *Poll, fd OsFd) c.Int
|
func PollInit(loop *Loop, handle *Poll, fd OsFd) c.Int
|
||||||
|
|
||||||
//go:linkname PollStart C.uv_poll_start
|
|
||||||
func PollStart(handle *Poll, events c.Int, cb PollCb) c.Int
|
|
||||||
|
|
||||||
//go:linkname PollStop C.uv_poll_stop
|
|
||||||
func PollStop(handle *Poll) c.Int
|
|
||||||
|
|
||||||
//go:linkname PollInitSocket C.uv_poll_init_socket
|
//go:linkname PollInitSocket C.uv_poll_init_socket
|
||||||
func PollInitSocket(loop *Loop, handle *Poll, socket c.Int) c.Int
|
func PollInitSocket(loop *Loop, handle *Poll, socket c.Int) c.Int
|
||||||
|
|
||||||
// ----------------------------------------------
|
// llgo:link (*Poll).Start C.uv_poll_start
|
||||||
|
func (handle *Poll) Start(events c.Int, cb PollCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
/* Getaddrinfo related function and method */
|
// llgo:link (*Poll).Stop C.uv_poll_stop
|
||||||
|
func (handle *Poll) Stop() c.Int {
|
||||||
//go:linkname Getaddrinfo C.uv_getaddrinfo
|
return 0
|
||||||
func Getaddrinfo(loop *Loop, req *GetAddrInfo, getaddrinfoCb GetaddrinfoCb, node *c.Char, service *c.Char, hints *net.AddrInfo) c.Int
|
}
|
||||||
|
|
||||||
//go:linkname Freeaddrinfo C.uv_freeaddrinfo
|
|
||||||
func Freeaddrinfo(addrInfo *net.AddrInfo)
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
/* Getnameinfo related function and method */
|
|
||||||
|
|
||||||
//go:linkname Getnameinfo C.uv_getnameinfo
|
|
||||||
func Getnameinfo(loop *Loop, req *GetNameInfo, getnameinfoCb GetnameinfoCb, addr *net.SockAddr, flags c.Int) c.Int
|
|
||||||
|
|||||||
265
c/libuv/net.go
265
c/libuv/net.go
@@ -65,8 +65,22 @@ type UdpFlags c.Int
|
|||||||
|
|
||||||
/* Handle types. */
|
/* Handle types. */
|
||||||
|
|
||||||
|
// TODO(spongehah): Handle
|
||||||
|
type Handle struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [88]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Stream
|
||||||
|
type Stream struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [256]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Tcp
|
||||||
type Tcp struct {
|
type Tcp struct {
|
||||||
Unused [264]byte
|
Data c.Pointer
|
||||||
|
Unused [256]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Udp struct {
|
type Udp struct {
|
||||||
@@ -75,10 +89,38 @@ type Udp struct {
|
|||||||
|
|
||||||
/* Request types. */
|
/* Request types. */
|
||||||
|
|
||||||
|
type Req struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
type UdpSend struct {
|
type UdpSend struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Write
|
||||||
|
type Write struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [184]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Connect
|
||||||
|
type Connect struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [88]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAddrInfo struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetNameInfo struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Shutdown struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* Function type */
|
/* Function type */
|
||||||
@@ -95,6 +137,197 @@ type UdpSendCb func(req *UdpSend, status c.Int)
|
|||||||
// llgo:type C
|
// llgo:type C
|
||||||
type UdpRecvCb func(handle *Udp, nread c.Long, buf *Buf, addr *net.SockAddr, flags c.Uint)
|
type UdpRecvCb func(handle *Udp, nread c.Long, buf *Buf, addr *net.SockAddr, flags c.Uint)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ReadCb func(stream *Stream, nread c.Long, buf *Buf)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type WriteCb func(req *Write, status c.Int)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ConnectionCb func(server *Stream, status c.Int)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ShutdownCb func(req *Shutdown, status c.Int)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle related function and method */
|
||||||
|
|
||||||
|
//go:linkname HandleSize C.uv_handle_size
|
||||||
|
func HandleSize(handleType HandleType) uintptr
|
||||||
|
|
||||||
|
//go:linkname HandleTypeName C.uv_handle_type_name
|
||||||
|
func HandleTypeName(handleType HandleType) *c.Char
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Ref C.uv_ref
|
||||||
|
func (handle *Handle) Ref() {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Unref C.uv_unref
|
||||||
|
func (handle *Handle) Unref() {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).HasRef C.uv_has_ref
|
||||||
|
func (handle *Handle) HasRef() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).GetType C.uv_handle_get_type
|
||||||
|
func (handle *Handle) GetType() HandleType {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).GetData C.uv_handle_get_data
|
||||||
|
func (handle *Handle) GetData() c.Pointer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).GetLoop C.uv_handle_get_loop
|
||||||
|
func (handle *Handle) GetLoop() *Loop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).SetData C.uv_handle_set_data
|
||||||
|
func (handle *Handle) SetData(data c.Pointer) {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsActive C.uv_is_active
|
||||||
|
func (handle *Handle) IsActive() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Close C.uv_close
|
||||||
|
func (handle *Handle) Close(closeCb CloseCb) {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).SendBufferSize C.uv_send_buffer_size
|
||||||
|
func (handle *Handle) SendBufferSize(value *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).RecvBufferSize C.uv_recv_buffer_size
|
||||||
|
func (handle *Handle) RecvBufferSize(value *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Fileno C.uv_fileno
|
||||||
|
func (handle *Handle) Fileno(fd *OsFd) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsClosing C.uv_is_closing
|
||||||
|
func (handle *Handle) IsClosing() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsReadable C.uv_is_readable
|
||||||
|
func (handle *Handle) IsReadable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsWritable C.uv_is_writable
|
||||||
|
func (handle *Handle) IsWritable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Pipe C.uv_pipe
|
||||||
|
func Pipe(fds [2]File, readFlags c.Int, writeFlags c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Socketpair C.uv_socketpair
|
||||||
|
func Socketpair(_type c.Int, protocol c.Int, socketVector [2]OsSock, flag0 c.Int, flag1 c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Req related function and method */
|
||||||
|
|
||||||
|
//go:linkname ReqSize C.uv_req_size
|
||||||
|
func ReqSize(reqType ReqType) uintptr
|
||||||
|
|
||||||
|
//go:linkname TypeName C.uv_req_type_name
|
||||||
|
func TypeName(reqType ReqType) *c.Char
|
||||||
|
|
||||||
|
// llgo:link (*Req).GetData C.uv_req_get_data
|
||||||
|
func (req *Req) GetData() c.Pointer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Req).SetData C.uv_req_set_data
|
||||||
|
func (req *Req) SetData(data c.Pointer) {}
|
||||||
|
|
||||||
|
// llgo:link (*Req).GetType C.uv_req_get_type
|
||||||
|
func (req *Req) GetType() ReqType {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Stream related function and method */
|
||||||
|
|
||||||
|
// llgo:link (*Stream).GetWriteQueueSize C.uv_stream_get_write_queue_size
|
||||||
|
func (stream *Stream) GetWriteQueueSize() uintptr {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).Listen C.uv_listen
|
||||||
|
func (stream *Stream) Listen(backlog c.Int, connectionCb ConnectionCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).Accept C.uv_accept
|
||||||
|
func (server *Stream) Accept(client *Stream) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).StartRead C.uv_read_start
|
||||||
|
func (stream *Stream) StartRead(allocCb AllocCb, readCb ReadCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).StopRead C.uv_read_stop
|
||||||
|
func (stream *Stream) StopRead() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Write).Write C.uv_write
|
||||||
|
func (req *Write) Write(stream *Stream, bufs *Buf, nbufs c.Uint, writeCb WriteCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Write).Write2 C.uv_write2
|
||||||
|
func (req *Write) Write2(stream *Stream, bufs *Buf, nbufs c.Uint, sendStream *Stream, writeCb WriteCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).TryWrite C.uv_try_write
|
||||||
|
func (stream *Stream) TryWrite(bufs *Buf, nbufs c.Uint) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).TryWrite2 C.uv_try_write2
|
||||||
|
func (stream *Stream) TryWrite2(bufs *Buf, nbufs c.Uint, sendStream *Stream) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).IsReadable C.uv_is_readable
|
||||||
|
func (stream *Stream) IsReadable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).IsWritable C.uv_is_writable
|
||||||
|
func (stream *Stream) IsWritable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).SetBlocking C.uv_stream_set_blocking
|
||||||
|
func (stream *Stream) SetBlocking(blocking c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname StreamShutdown C.uv_shutdown
|
||||||
|
func StreamShutdown(shutdown *Shutdown, stream *Stream, shutdownCb ShutdownCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* Tcp related function and method */
|
/* Tcp related function and method */
|
||||||
@@ -145,6 +378,11 @@ func (tcp *Tcp) CloseReset(closeCb CloseCb) c.Int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).GetIoWatcherFd C.uv_tcp_get_io_watcher_fd
|
||||||
|
func (tcp *Tcp) GetIoWatcherFd() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname TcpConnect C.uv_tcp_connect
|
//go:linkname TcpConnect C.uv_tcp_connect
|
||||||
func TcpConnect(req *Connect, tcp *Tcp, addr *net.SockAddr, connectCb ConnectCb) c.Int
|
func TcpConnect(req *Connect, tcp *Tcp, addr *net.SockAddr, connectCb ConnectCb) c.Int
|
||||||
|
|
||||||
@@ -218,9 +456,6 @@ func (udp *Udp) SetTTL(ttl c.Int) c.Int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname Send C.uv_udp_send
|
|
||||||
func Send(req *UdpSend, udp *Udp, bufs *Buf, nbufs c.Uint, addr *net.SockAddr, sendCb UdpSendCb) c.Int
|
|
||||||
|
|
||||||
// llgo:link (*Udp).TrySend C.uv_udp_try_send
|
// llgo:link (*Udp).TrySend C.uv_udp_try_send
|
||||||
func (udp *Udp) TrySend(bufs *Buf, nbufs c.Uint, addr *net.SockAddr) c.Int {
|
func (udp *Udp) TrySend(bufs *Buf, nbufs c.Uint, addr *net.SockAddr) c.Int {
|
||||||
return 0
|
return 0
|
||||||
@@ -251,8 +486,13 @@ func (udp *Udp) GetSendQueueCount() uintptr {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:linkname Send C.uv_udp_send
|
||||||
|
func Send(req *UdpSend, udp *Udp, bufs *Buf, nbufs c.Uint, addr *net.SockAddr, sendCb UdpSendCb) c.Int
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* DNS related function and method */
|
||||||
|
|
||||||
//go:linkname Ip4Addr C.uv_ip4_addr
|
//go:linkname Ip4Addr C.uv_ip4_addr
|
||||||
func Ip4Addr(ip *c.Char, port c.Int, addr *net.SockaddrIn) c.Int
|
func Ip4Addr(ip *c.Char, port c.Int, addr *net.SockaddrIn) c.Int
|
||||||
|
|
||||||
@@ -273,3 +513,20 @@ func InetNtop(af c.Int, src c.Pointer, dst *c.Char, size uintptr) c.Int
|
|||||||
|
|
||||||
//go:linkname InetPton C.uv_inet_pton
|
//go:linkname InetPton C.uv_inet_pton
|
||||||
func InetPton(af c.Int, src *c.Char, dst c.Pointer) c.Int
|
func InetPton(af c.Int, src *c.Char, dst c.Pointer) c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Getaddrinfo related function and method */
|
||||||
|
|
||||||
|
//go:linkname Getaddrinfo C.uv_getaddrinfo
|
||||||
|
func Getaddrinfo(loop *Loop, req *GetAddrInfo, getaddrinfoCb GetaddrinfoCb, node *c.Char, service *c.Char, hints *net.AddrInfo) c.Int
|
||||||
|
|
||||||
|
//go:linkname Freeaddrinfo C.uv_freeaddrinfo
|
||||||
|
func Freeaddrinfo(addrInfo *net.AddrInfo)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Getnameinfo related function and method */
|
||||||
|
|
||||||
|
//go:linkname Getnameinfo C.uv_getnameinfo
|
||||||
|
func Getnameinfo(loop *Loop, req *GetNameInfo, getnameinfoCb GetnameinfoCb, addr *net.SockAddr, flags c.Int) c.Int
|
||||||
|
|||||||
@@ -26,8 +26,17 @@ type SignalCb func(handle *Signal, sigNum c.Int)
|
|||||||
//go:linkname SignalInit C.uv_signal_init
|
//go:linkname SignalInit C.uv_signal_init
|
||||||
func SignalInit(loop *Loop, handle *Signal) c.Int
|
func SignalInit(loop *Loop, handle *Signal) c.Int
|
||||||
|
|
||||||
//go:linkname SignalStart C.uv_signal_start
|
// llgo:link (*Signal).Start C.uv_signal_start
|
||||||
func SignalStart(handle *Signal, cb SignalCb, signum c.Int) c.Int
|
func (handle *Signal) Start(cb SignalCb, signum c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname SignalStartOneshot C.uv_signal_start_oneshot
|
// llgo:link (*Signal).StartOneshot C.uv_signal_start_oneshot
|
||||||
func SignalStartOneshot(handle *Signal, cb SignalCb, signum c.Int) c.Int
|
func (handle *Signal) StartOneshot(cb SignalCb, signum c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Signal).Stop C.uv_signal_stop
|
||||||
|
func (handle *Signal) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
/* Handle types. */
|
/* Handle types. */
|
||||||
|
|
||||||
|
// TODO(spongehah): Timer
|
||||||
type Timer struct {
|
type Timer struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|||||||
39
c/net/net.go
39
c/net/net.go
@@ -17,7 +17,7 @@
|
|||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
)
|
)
|
||||||
@@ -97,6 +97,13 @@ const (
|
|||||||
EAI_OVERFLOW /* argument buffer overflow */
|
EAI_OVERFLOW /* argument buffer overflow */
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ALIGNSIZE = unsafe.Sizeof(c.LongLong(0))
|
||||||
|
MAXSIZE = 128
|
||||||
|
PAD1_SIZE = ALIGNSIZE - unsafe.Sizeof(byte(0)) - unsafe.Sizeof(byte(0))
|
||||||
|
PAD2_SIZE = MAXSIZE - unsafe.Sizeof(byte(0)) - unsafe.Sizeof(byte(0)) - PAD1_SIZE - ALIGNSIZE
|
||||||
|
)
|
||||||
|
|
||||||
// (TODO) merge to inet
|
// (TODO) merge to inet
|
||||||
const INET_ADDRSTRLEN = 16
|
const INET_ADDRSTRLEN = 16
|
||||||
|
|
||||||
@@ -117,6 +124,14 @@ type SockaddrIn6 struct {
|
|||||||
ScopeId c.Uint
|
ScopeId c.Uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
pad1 [PAD1_SIZE]c.Char
|
||||||
|
align c.LongLong
|
||||||
|
pad2 [PAD2_SIZE]c.Char
|
||||||
|
}
|
||||||
|
|
||||||
type InAddr struct {
|
type InAddr struct {
|
||||||
Addr c.Uint
|
Addr c.Uint
|
||||||
}
|
}
|
||||||
@@ -171,6 +186,9 @@ func Send(c.Int, c.Pointer, uintptr, c.Int) c.Long
|
|||||||
//go:linkname Recv C.recv
|
//go:linkname Recv C.recv
|
||||||
func Recv(c.Int, c.Pointer, uintptr, c.Int) c.Long
|
func Recv(c.Int, c.Pointer, uintptr, c.Int) c.Long
|
||||||
|
|
||||||
|
//go:linkname SetSockOpt C.setsockopt
|
||||||
|
func SetSockOpt(socket c.Int, level c.Int, optionName c.Int, optionValue c.Pointer, sockLen c.Uint) c.Int
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type AddrInfo struct {
|
type AddrInfo struct {
|
||||||
@@ -196,8 +214,27 @@ func swapInt16(data uint16) uint16 {
|
|||||||
return (data << 8) | (data >> 8)
|
return (data << 8) | (data >> 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func swapInt32(data c.Uint) c.Uint {
|
||||||
|
return ((data & 0xff) << 24) |
|
||||||
|
((data & 0xff00) << 8) |
|
||||||
|
((data & 0xff0000) >> 8) |
|
||||||
|
((data & 0xff000000) >> 24)
|
||||||
|
}
|
||||||
|
|
||||||
func Htons(x uint16) uint16 {
|
func Htons(x uint16) uint16 {
|
||||||
return swapInt16(x)
|
return swapInt16(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Ntohs(x uint16) uint16 {
|
||||||
|
return swapInt16(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Htonl(x c.Uint) c.Uint {
|
||||||
|
return swapInt32(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ntohl(x c.Uint) c.Uint {
|
||||||
|
return swapInt32(x)
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
44
c/openssl/_demo/cbigintdemo/fib.go
Normal file
44
c/openssl/_demo/cbigintdemo/fib.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newInt(n openssl.BN_ULONG) *openssl.BIGNUM {
|
||||||
|
ret := openssl.BNNew()
|
||||||
|
ret.SetWord(n)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx := openssl.BN_CTXNew()
|
||||||
|
defer ctx.Free()
|
||||||
|
|
||||||
|
// Initialize two big ints with the first two numbers in the sequence.
|
||||||
|
a := newInt(0)
|
||||||
|
b := newInt(1)
|
||||||
|
defer a.Free()
|
||||||
|
defer b.Free()
|
||||||
|
|
||||||
|
// Initialize limit as 10^99, the smallest integer with 100 digits.
|
||||||
|
v10, v99 := newInt(10), newInt(99)
|
||||||
|
defer v10.Free()
|
||||||
|
defer v99.Free()
|
||||||
|
|
||||||
|
limit := openssl.BNNew()
|
||||||
|
defer limit.Free()
|
||||||
|
|
||||||
|
limit.Exp(v10, v99, ctx)
|
||||||
|
|
||||||
|
// Loop while a is smaller than 1e100.
|
||||||
|
for a.Cmp(limit) < 0 {
|
||||||
|
// Compute the next Fibonacci number, storing it in a.
|
||||||
|
a.Add(a, b)
|
||||||
|
// Swap a and b so that b is the next number in the sequence.
|
||||||
|
a, b = b, a
|
||||||
|
}
|
||||||
|
cstr := a.CStr()
|
||||||
|
c.Printf(c.Str("%s\n"), cstr) // 100-digit Fibonacci number
|
||||||
|
openssl.FreeCStr(cstr)
|
||||||
|
}
|
||||||
40
c/openssl/_demo/chmacdemo/hmac.go
Normal file
40
c/openssl/_demo/chmacdemo/hmac.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := "Hello, World!"
|
||||||
|
key := "123456"
|
||||||
|
var lenKey = len(key)
|
||||||
|
|
||||||
|
var digest = make([]byte, openssl.EVP_MAX_MD_SIZE)
|
||||||
|
var digestLen c.Uint
|
||||||
|
ctx := openssl.NewHMAC_CTX()
|
||||||
|
if ctx == nil {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("%s\n"), c.Str("Error creating HMAC_CTX"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer ctx.Free()
|
||||||
|
var ret c.Int = ctx.InitEx(unsafe.Pointer(unsafe.StringData(key)), c.Int(lenKey), openssl.EVP_sha256(), nil)
|
||||||
|
if ret == 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("%s\n"), c.Str("Error initializing HMAC_CTX"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ret = ctx.UpdateString(str)
|
||||||
|
if ret == 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("%s\n"), c.Str("Error updating HMAC_CTX"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ret = ctx.Final(unsafe.SliceData(digest), &digestLen)
|
||||||
|
if ret == 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("%s\n"), c.Str("Error finalizing HMAC_CTX"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("HMAC:%x\n", digest[:digestLen])
|
||||||
|
}
|
||||||
17
c/openssl/_demo/cranddemo/rand.go
Normal file
17
c/openssl/_demo/cranddemo/rand.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
b := make([]byte, 10)
|
||||||
|
|
||||||
|
openssl.RANDBytes(b)
|
||||||
|
fmt.Printf("%x\n", b)
|
||||||
|
|
||||||
|
openssl.RANDPrivBytes(b)
|
||||||
|
fmt.Printf("%x\n", b)
|
||||||
|
}
|
||||||
5
c/openssl/_wrap/openssl.c
Normal file
5
c/openssl/_wrap/openssl.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include <openssl/crypto.h>
|
||||||
|
|
||||||
|
void opensslFree(void *ptr) {
|
||||||
|
OPENSSL_free(ptr);
|
||||||
|
}
|
||||||
61
c/openssl/bio.go
Normal file
61
c/openssl/bio.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type BIO struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// BIO *BIO_new_mem_buf(const void *buf, int len);
|
||||||
|
//
|
||||||
|
//go:linkname BIONewMemBuf C.BIO_new_mem_buf
|
||||||
|
func BIONewMemBuf(buf unsafe.Pointer, len c.Int) *BIO
|
||||||
|
|
||||||
|
// int BIO_free(BIO *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIO).Free C.BIO_free
|
||||||
|
func (*BIO) Free() c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BIO_up_ref(BIO *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIO).UpRef C.BIO_up_ref
|
||||||
|
func (*BIO) UpRef() c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIO).ReadEx C.BIO_read_ex
|
||||||
|
func (*BIO) ReadEx(data unsafe.Pointer, dlen uintptr, readbytes *uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BIO_write(BIO *b, const void *data, int dlen);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIO).Write C.BIO_write
|
||||||
|
func (*BIO) Write(data unsafe.Pointer, dlen c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIO).WriteEx C.BIO_write_ex
|
||||||
|
func (*BIO) WriteEx(data unsafe.Pointer, dlen uintptr, written *uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
409
c/openssl/bn.go
Normal file
409
c/openssl/bn.go
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BN_ULONG = uint64
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type BN_CTX struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// BN_CTX *BN_CTX_new(void);
|
||||||
|
//
|
||||||
|
//go:linkname BN_CTXNew C.BN_CTX_new
|
||||||
|
func BN_CTXNew() *BN_CTX
|
||||||
|
|
||||||
|
// BN_CTX *BN_CTX_secure_new(void);
|
||||||
|
//
|
||||||
|
//go:linkname BN_CTXSecureNew C.BN_CTX_secure_new
|
||||||
|
func BN_CTXSecureNew() *BN_CTX
|
||||||
|
|
||||||
|
// BN_CTX *BN_CTX_new_ex(OSSL_LIB_CTX *ctx);
|
||||||
|
// BN_CTX *BN_CTX_secure_new_ex(OSSL_LIB_CTX *ctx);
|
||||||
|
|
||||||
|
// void BN_CTX_free(BN_CTX *c);
|
||||||
|
//
|
||||||
|
// llgo:link (*BN_CTX).Free C.BN_CTX_free
|
||||||
|
func (*BN_CTX) Free() {}
|
||||||
|
|
||||||
|
// void BN_CTX_start(BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BN_CTX).Start C.BN_CTX_start
|
||||||
|
func (*BN_CTX) Start() {}
|
||||||
|
|
||||||
|
// BIGNUM *BN_CTX_get(BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BN_CTX).Get C.BN_CTX_get
|
||||||
|
func (*BN_CTX) Get() *BIGNUM { return nil }
|
||||||
|
|
||||||
|
// void BN_CTX_end(BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BN_CTX).End C.BN_CTX_end
|
||||||
|
func (*BN_CTX) End() {}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type BIGNUM struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// BIGNUM *BN_new(void);
|
||||||
|
//
|
||||||
|
//go:linkname BNNew C.BN_new
|
||||||
|
func BNNew() *BIGNUM
|
||||||
|
|
||||||
|
// BIGNUM *BN_secure_new(void);
|
||||||
|
//
|
||||||
|
//go:linkname BNSecureNew C.BN_secure_new
|
||||||
|
func BNSecureNew() *BIGNUM
|
||||||
|
|
||||||
|
// void BN_free(BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Free C.BN_free
|
||||||
|
func (*BIGNUM) Free() {}
|
||||||
|
|
||||||
|
// void BN_clear_free(BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).ClearFree C.BN_clear_free
|
||||||
|
func (*BIGNUM) ClearFree() {}
|
||||||
|
|
||||||
|
// void BN_clear(BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Clear C.BN_clear
|
||||||
|
func (*BIGNUM) Clear() {}
|
||||||
|
|
||||||
|
// BIGNUM *BN_dup(const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Dup C.BN_dup
|
||||||
|
func (*BIGNUM) Dup() *BIGNUM { return nil }
|
||||||
|
|
||||||
|
// BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Copy C.BN_copy
|
||||||
|
func (*BIGNUM) Copy(b *BIGNUM) *BIGNUM { return nil }
|
||||||
|
|
||||||
|
// void BN_swap(BIGNUM *a, BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Swap C.BN_swap
|
||||||
|
func (*BIGNUM) Swap(b *BIGNUM) {}
|
||||||
|
|
||||||
|
// int BN_is_zero(const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).IsZero C.BN_is_zero
|
||||||
|
func (*BIGNUM) IsZero() c.Int { return 0 }
|
||||||
|
|
||||||
|
// void BN_zero_ex(BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SetZero C.BN_zero_ex
|
||||||
|
func (*BIGNUM) SetZero() {}
|
||||||
|
|
||||||
|
// int BN_is_one(const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).IsOne C.BN_is_one
|
||||||
|
func (*BIGNUM) IsOne() c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_is_odd(const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).IsOdd C.BN_is_odd
|
||||||
|
func (*BIGNUM) IsOdd() c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).AbsIsWord C.BN_abs_is_word
|
||||||
|
func (*BIGNUM) AbsIsWord(w BN_ULONG) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_is_word(const BIGNUM *a, const BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).IsWord C.BN_is_word
|
||||||
|
func (*BIGNUM) IsWord(w BN_ULONG) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_set_word(BIGNUM *a, BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SetWord C.BN_set_word
|
||||||
|
func (*BIGNUM) SetWord(w BN_ULONG) c.Int { return 0 }
|
||||||
|
|
||||||
|
// BN_ULONG BN_get_word(const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).GetWord C.BN_get_word
|
||||||
|
func (*BIGNUM) GetWord() BN_ULONG { return 0 }
|
||||||
|
|
||||||
|
// BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).ModWord C.BN_mod_word
|
||||||
|
func (*BIGNUM) ModWord(w BN_ULONG) BN_ULONG { return 0 }
|
||||||
|
|
||||||
|
// BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).DivWord C.BN_div_word
|
||||||
|
func (*BIGNUM) DivWord(w BN_ULONG) BN_ULONG { return 0 }
|
||||||
|
|
||||||
|
// int BN_mul_word(BIGNUM *a, BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).MulWord C.BN_mul_word
|
||||||
|
func (*BIGNUM) MulWord(w BN_ULONG) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_add_word(BIGNUM *a, BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).AddWord C.BN_add_word
|
||||||
|
func (*BIGNUM) AddWord(w BN_ULONG) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_sub_word(BIGNUM *a, BN_ULONG w);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SubWord C.BN_sub_word
|
||||||
|
func (*BIGNUM) SubWord(w BN_ULONG) c.Int { return 0 }
|
||||||
|
|
||||||
|
// char *BN_bn2hex(const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Bn2hex C.BN_bn2hex
|
||||||
|
func (*BIGNUM) Bn2hex() *c.Char { return nil }
|
||||||
|
|
||||||
|
// char *BN_bn2dec(const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Bn2dec C.BN_bn2dec
|
||||||
|
func (*BIGNUM) Bn2dec() *c.Char { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*BIGNUM).CStr C.BN_bn2dec
|
||||||
|
func (*BIGNUM) CStr() *c.Char { return nil }
|
||||||
|
|
||||||
|
// int BN_hex2bn(BIGNUM **a, const char *str);
|
||||||
|
//
|
||||||
|
//go:linkname BNHex2bn C.BN_hex2bn
|
||||||
|
func BNHex2bn(a **BIGNUM, str *c.Char) c.Int
|
||||||
|
|
||||||
|
// int BN_dec2bn(BIGNUM **a, const char *str);
|
||||||
|
//
|
||||||
|
//go:linkname BNDec2bn C.BN_dec2bn
|
||||||
|
func BNDec2bn(a **BIGNUM, str *c.Char) c.Int
|
||||||
|
|
||||||
|
// int BN_asc2bn(BIGNUM **a, const char *str);
|
||||||
|
//
|
||||||
|
//go:linkname BNAsc2bn C.BN_asc2bn
|
||||||
|
func BNAsc2bn(a **BIGNUM, str *c.Char) c.Int
|
||||||
|
|
||||||
|
// BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||||
|
//
|
||||||
|
//go:linkname BNBin2bn C.BN_bin2bn
|
||||||
|
func BNBin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM
|
||||||
|
|
||||||
|
// BIGNUM *BN_signed_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||||
|
//
|
||||||
|
//go:linkname BNSignedBin2bn C.BN_signed_bin2bn
|
||||||
|
func BNSignedBin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM
|
||||||
|
|
||||||
|
// int BN_bn2bin(const BIGNUM *a, unsigned char *to);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Bn2bin C.BN_bn2bin
|
||||||
|
func (bn *BIGNUM) Bn2bin(to *byte) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Bn2binpad C.BN_bn2binpad
|
||||||
|
func (bn *BIGNUM) Bn2binpad(to *byte, tolen c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_signed_bn2bin(const BIGNUM *a, unsigned char *to, int tolen);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SignedBn2bin C.BN_signed_bn2bin
|
||||||
|
func (bn *BIGNUM) SignedBn2bin(to *byte, tolen c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||||
|
//
|
||||||
|
//go:linkname BNLebin2bn C.BN_lebin2bn
|
||||||
|
func BNLebin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM
|
||||||
|
|
||||||
|
// BIGNUM *BN_signed_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||||
|
//
|
||||||
|
//go:linkname BNSignedLebin2bn C.BN_signed_lebin2bn
|
||||||
|
func BNSignedLebin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM
|
||||||
|
|
||||||
|
// int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Bn2lebinpad C.BN_bn2lebinpad
|
||||||
|
func (bn *BIGNUM) Bn2lebinpad(to *byte, tolen c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_signed_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SignedBn2lebin C.BN_signed_bn2lebin
|
||||||
|
func (bn *BIGNUM) SignedBn2lebin(to *byte, tolen c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||||
|
//
|
||||||
|
//go:linkname BNNative2bn C.BN_native2bn
|
||||||
|
func BNNative2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM
|
||||||
|
|
||||||
|
// BIGNUM *BN_signed_native2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||||
|
//
|
||||||
|
//go:linkname BNSignedNative2bn C.BN_signed_native2bn
|
||||||
|
func BNSignedNative2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM
|
||||||
|
|
||||||
|
// int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Bn2nativepad C.BN_bn2nativepad
|
||||||
|
func (bn *BIGNUM) Bn2nativepad(to *byte, tolen c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_signed_bn2native(const BIGNUM *a, unsigned char *to, int tolen);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SignedBn2native C.BN_signed_bn2native
|
||||||
|
func (bn *BIGNUM) SignedBn2native(to *byte, tolen c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||||
|
//
|
||||||
|
//go:linkname BNMpi2bn C.BN_mpi2bn
|
||||||
|
func BNMpi2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM
|
||||||
|
|
||||||
|
// int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Bn2mpi C.BN_bn2mpi
|
||||||
|
func (bn *BIGNUM) Bn2mpi(to *byte) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Sub C.BN_sub
|
||||||
|
func (*BIGNUM) Sub(a, b *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Add C.BN_add
|
||||||
|
func (*BIGNUM) Add(a, b *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Usub C.BN_usub
|
||||||
|
func (*BIGNUM) Usub(a, b *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Uadd C.BN_uadd
|
||||||
|
func (*BIGNUM) Uadd(a, b *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Mul C.BN_mul
|
||||||
|
func (*BIGNUM) Mul(r, a, b *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Sqr C.BN_sqr
|
||||||
|
func (*BIGNUM) Sqr(r, a *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
/** BN_set_negative sets sign of a BIGNUM
|
||||||
|
* \param b pointer to the BIGNUM object
|
||||||
|
* \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise
|
||||||
|
*/
|
||||||
|
// void BN_set_negative(BIGNUM *b, int n);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SetNegative C.BN_set_negative
|
||||||
|
func (*BIGNUM) SetNegative(n c.Int) {}
|
||||||
|
|
||||||
|
/** BN_is_negative returns 1 if the BIGNUM is negative
|
||||||
|
* \param b pointer to the BIGNUM object
|
||||||
|
* \return 1 if a < 0 and 0 otherwise
|
||||||
|
*/
|
||||||
|
// int BN_is_negative(const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).IsNegative C.BN_is_negative
|
||||||
|
func (*BIGNUM) IsNegative() c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Div C.BN_div
|
||||||
|
func (*BIGNUM) Div(rem, m, d *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Nnmod C.BN_nnmod
|
||||||
|
func (*BIGNUM) Nnmod(r, m, d *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_cmp(const BIGNUM *a, const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Cmp C.BN_cmp
|
||||||
|
func (*BIGNUM) Cmp(b *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Ucmp C.BN_ucmp
|
||||||
|
func (*BIGNUM) Ucmp(b *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_is_bit_set(const BIGNUM *a, int n);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).IsBitSet C.BN_is_bit_set
|
||||||
|
func (*BIGNUM) IsBitSet(n c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_set_bit(BIGNUM *a, int n);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).SetBit C.BN_set_bit
|
||||||
|
func (*BIGNUM) SetBit(n c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_clear_bit(BIGNUM *a, int n);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).ClearBit C.BN_clear_bit
|
||||||
|
func (*BIGNUM) ClearBit(n c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Lshift C.BN_lshift
|
||||||
|
func (*BIGNUM) Lshift(a *BIGNUM, n c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_lshift1(BIGNUM *r, const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Lshift1 C.BN_lshift1
|
||||||
|
func (*BIGNUM) Lshift1(a *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Rshift C.BN_rshift
|
||||||
|
func (*BIGNUM) Rshift(a *BIGNUM, n c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_rshift1(BIGNUM *r, const BIGNUM *a);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Rshift1 C.BN_rshift1
|
||||||
|
func (*BIGNUM) Rshift1(a *BIGNUM) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Exp C.BN_exp
|
||||||
|
func (*BIGNUM) Exp(a, p *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).ModExp C.BN_mod_exp
|
||||||
|
func (*BIGNUM) ModExp(a, p, m *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).Gcd C.BN_gcd
|
||||||
|
func (*BIGNUM) Gcd(a, b *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// int BN_are_coprime(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*BIGNUM).AreCoprime C.BN_are_coprime
|
||||||
|
func (*BIGNUM) AreCoprime(b *BIGNUM, ctx *BN_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type BN_GENCB struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
156
c/openssl/err.go
Normal file
156
c/openssl/err.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* The error code packs differently depending on if it records a system
|
||||||
|
* error or an OpenSSL error.
|
||||||
|
*
|
||||||
|
* A system error packs like this (we follow POSIX and only allow positive
|
||||||
|
* numbers that fit in an |int|):
|
||||||
|
*
|
||||||
|
* +-+-------------------------------------------------------------+
|
||||||
|
* |1| system error number |
|
||||||
|
* +-+-------------------------------------------------------------+
|
||||||
|
*
|
||||||
|
* An OpenSSL error packs like this:
|
||||||
|
*
|
||||||
|
* <---------------------------- 32 bits -------------------------->
|
||||||
|
* <--- 8 bits ---><------------------ 23 bits ----------------->
|
||||||
|
* +-+---------------+---------------------------------------------+
|
||||||
|
* |0| library | reason |
|
||||||
|
* +-+---------------+---------------------------------------------+
|
||||||
|
*
|
||||||
|
* A few of the reason bits are reserved as flags with special meaning:
|
||||||
|
*
|
||||||
|
* <5 bits-<>--------- 19 bits ----------------->
|
||||||
|
* +-------+-+-----------------------------------+
|
||||||
|
* | rflags| | reason |
|
||||||
|
* +-------+-+-----------------------------------+
|
||||||
|
* ^
|
||||||
|
* |
|
||||||
|
* ERR_RFLAG_FATAL = ERR_R_FATAL
|
||||||
|
*
|
||||||
|
* The reason flags are part of the overall reason code for practical
|
||||||
|
* reasons, as they provide an easy way to place different types of
|
||||||
|
* reason codes in different numeric ranges.
|
||||||
|
*
|
||||||
|
* The currently known reason flags are:
|
||||||
|
*
|
||||||
|
* ERR_RFLAG_FATAL Flags that the reason code is considered fatal.
|
||||||
|
* For backward compatibility reasons, this flag
|
||||||
|
* is also the code for ERR_R_FATAL (that reason
|
||||||
|
* code served the dual purpose of flag and reason
|
||||||
|
* code in one in pre-3.0 OpenSSL).
|
||||||
|
* ERR_RFLAG_COMMON Flags that the reason code is common to all
|
||||||
|
* libraries. All ERR_R_ macros must use this flag,
|
||||||
|
* and no other _R_ macro is allowed to use it.
|
||||||
|
*/
|
||||||
|
type Errno c.Ulong
|
||||||
|
|
||||||
|
// ERR_get_error returns the earliest error code from the thread's error queue and
|
||||||
|
// removes the entry. This function can be called repeatedly until there are no more
|
||||||
|
// error codes to return.
|
||||||
|
//
|
||||||
|
// unsigned long ERR_get_error(void);
|
||||||
|
//
|
||||||
|
//go:linkname ERRGetError C.ERR_get_error
|
||||||
|
func ERRGetError() Errno
|
||||||
|
|
||||||
|
// ERR_get_error_all() is the same as ERR_get_error(), but on success it additionally
|
||||||
|
// stores the filename, line number and function where the error occurred in *file,
|
||||||
|
// *line and *func, and also extra text and flags in *data, *flags. If any of those
|
||||||
|
// parameters are NULL, it will not be changed.
|
||||||
|
//
|
||||||
|
// unsigned long ERR_get_error_all(
|
||||||
|
// const char **file, int *line, const char **func, const char **data, int *flags);
|
||||||
|
//
|
||||||
|
//go:linkname ERRGetErrorAll C.ERR_get_error_all
|
||||||
|
func ERRGetErrorAll(
|
||||||
|
file **c.Char, line *c.Int, function **c.Char, data **c.Char, flags *c.Int) Errno
|
||||||
|
|
||||||
|
// unsigned long ERR_peek_error(void);
|
||||||
|
//
|
||||||
|
//go:linkname ERRPeekError C.ERR_peek_error
|
||||||
|
func ERRPeekError() Errno
|
||||||
|
|
||||||
|
// unsigned long ERR_peek_error_all(
|
||||||
|
// const char **file, int *line, const char **func, const char **data, int *flags);
|
||||||
|
//
|
||||||
|
//go:linkname ERRPeekErrorAll C.ERR_peek_error_all
|
||||||
|
func ERRPeekErrorAll(
|
||||||
|
file **c.Char, line *c.Int, function **c.Char, data **c.Char, flags *c.Int) Errno
|
||||||
|
|
||||||
|
// unsigned long ERR_peek_last_error(void);
|
||||||
|
//
|
||||||
|
//go:linkname ERRPeekLastError C.ERR_peek_last_error
|
||||||
|
func ERRPeekLastError() Errno
|
||||||
|
|
||||||
|
// unsigned long ERR_peek_last_error_all(
|
||||||
|
// const char **file, int *line, const char **func, const char **data, int *flags);
|
||||||
|
//
|
||||||
|
//go:linkname ERRPeekLastErrorAll C.ERR_peek_last_error_all
|
||||||
|
func ERRPeekLastErrorAll(
|
||||||
|
file **c.Char, line *c.Int, function **c.Char, data **c.Char, flags *c.Int) Errno
|
||||||
|
|
||||||
|
// void ERR_clear_error(void);
|
||||||
|
//
|
||||||
|
//go:linkname ERRClearError C.ERR_clear_error
|
||||||
|
func ERRClearError()
|
||||||
|
|
||||||
|
// ERR_error_string() generates a human-readable string representing the error code e,
|
||||||
|
// and places it at buf. buf must be at least 256 bytes long.
|
||||||
|
//
|
||||||
|
// char *ERR_error_string(unsigned long e, char *buf);
|
||||||
|
//
|
||||||
|
//go:linkname ERRErrorString C.ERR_error_string
|
||||||
|
func ERRErrorString(e Errno, buf *c.Char) *c.Char
|
||||||
|
|
||||||
|
// ERR_lib_error_string() and ERR_reason_error_string() return the library name and
|
||||||
|
// reason string respectively.
|
||||||
|
//
|
||||||
|
// const char *ERR_lib_error_string(unsigned long e);
|
||||||
|
//
|
||||||
|
//go:linkname ERRLibErrorString C.ERR_lib_error_string
|
||||||
|
func ERRLibErrorString(e Errno) *c.Char
|
||||||
|
|
||||||
|
// const char *ERR_reason_error_string(unsigned long e);
|
||||||
|
//
|
||||||
|
//go:linkname ERRReasonErrorString C.ERR_reason_error_string
|
||||||
|
func ERRReasonErrorString(e Errno) *c.Char
|
||||||
|
|
||||||
|
// void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u), void *u);
|
||||||
|
//
|
||||||
|
// [pid]:error:[error code]:[library name]:[function name]:[reason string]:[filename]:[line]:[optional text message]
|
||||||
|
//
|
||||||
|
//go:linkname ERRPrintErrorsCb C.ERR_print_errors_cb
|
||||||
|
func ERRPrintErrorsCb(cb func(str *c.Char, len uintptr, u unsafe.Pointer) c.Int, u unsafe.Pointer)
|
||||||
|
|
||||||
|
// void ERR_print_errors_fp(FILE *fp);
|
||||||
|
//
|
||||||
|
//go:linkname ERRPrintErrorsFp C.ERR_print_errors_fp
|
||||||
|
func ERRPrintErrorsFp(fp c.FilePtr)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
133
c/openssl/hmac.go
Normal file
133
c/openssl/hmac.go
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EVP_MAX_MD_SIZE = 64 /* longest known is SHA512 */
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type EVP_MD struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// const EVP_MD *EVP_sha1(void)
|
||||||
|
//
|
||||||
|
//go:linkname EVP_sha1 C.EVP_sha1
|
||||||
|
func EVP_sha1() *EVP_MD
|
||||||
|
|
||||||
|
// const EVP_MD *EVP_sha224(void)
|
||||||
|
//
|
||||||
|
//go:linkname EVP_sha224 C.EVP_sha224
|
||||||
|
func EVP_sha224() *EVP_MD
|
||||||
|
|
||||||
|
// func EVP_sha256() *EVP_MD
|
||||||
|
//
|
||||||
|
//go:linkname EVP_sha256 C.EVP_sha256
|
||||||
|
func EVP_sha256() *EVP_MD
|
||||||
|
|
||||||
|
// const EVP_MD *EVP_sha512_224(void)
|
||||||
|
//
|
||||||
|
//go:linkname EVP_sha512_224 C.EVP_sha512_224
|
||||||
|
func EVP_sha512_224() *EVP_MD
|
||||||
|
|
||||||
|
// const EVP_MD *EVP_sha512_256(void)
|
||||||
|
//
|
||||||
|
//go:linkname EVP_sha512_256 C.EVP_sha512_256
|
||||||
|
func EVP_sha512_256() *EVP_MD
|
||||||
|
|
||||||
|
// const EVP_MD *EVP_sha384(void)
|
||||||
|
//
|
||||||
|
//go:linkname EVP_sha384 C.EVP_sha384
|
||||||
|
func EVP_sha384() *EVP_MD
|
||||||
|
|
||||||
|
// const EVP_MD *EVP_sha512(void)
|
||||||
|
//
|
||||||
|
//go:linkname EVP_sha512 C.EVP_sha512
|
||||||
|
func EVP_sha512() *EVP_MD
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type HMAC_CTX struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 HMAC_CTX *HMAC_CTX_new(void);
|
||||||
|
//
|
||||||
|
//go:linkname NewHMAC_CTX C.HMAC_CTX_new
|
||||||
|
func NewHMAC_CTX() *HMAC_CTX
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void HMAC_CTX_free(HMAC_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).Free C.HMAC_CTX_free
|
||||||
|
func (ctx *HMAC_CTX) Free() {}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 size_t HMAC_size(const HMAC_CTX *e);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).Size C.HMAC_size
|
||||||
|
func (ctx *HMAC_CTX) Size() uintptr { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int HMAC_CTX_reset(HMAC_CTX *ctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).Reset C.HMAC_CTX_reset
|
||||||
|
func (ctx *HMAC_CTX) Reset() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_1_1_0 __owur int HMAC_Init(HMAC_CTX *ctx,
|
||||||
|
// const void *key, int len,
|
||||||
|
// const EVP_MD *md);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).Init C.HMAC_Init
|
||||||
|
func (ctx *HMAC_CTX) Init(key unsafe.Pointer, len c.Int, md *EVP_MD) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (ctx *HMAC_CTX) InitBytes(key []byte, md *EVP_MD) c.Int {
|
||||||
|
return ctx.Init(unsafe.Pointer(unsafe.SliceData(key)), c.Int(len(key)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *HMAC_CTX) InitString(key string, md *EVP_MD) c.Int {
|
||||||
|
return ctx.Init(unsafe.Pointer(unsafe.StringData(key)), c.Int(len(key)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
|
||||||
|
// const EVP_MD *md, ENGINE *impl);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).InitEx C.HMAC_Init_ex
|
||||||
|
func (ctx *HMAC_CTX) InitEx(key unsafe.Pointer, len c.Int, md *EVP_MD, impl unsafe.Pointer) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data,
|
||||||
|
// size_t len);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).Update C.HMAC_Update
|
||||||
|
func (ctx *HMAC_CTX) Update(data unsafe.Pointer, len uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (ctx *HMAC_CTX) UpdateBytes(data []byte) c.Int {
|
||||||
|
return ctx.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *HMAC_CTX) UpdateString(data string) c.Int {
|
||||||
|
return ctx.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int HMAC_Final(HMAC_CTX *ctx, unsigned char *md,
|
||||||
|
// unsigned int *len);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).Final C.HMAC_Final
|
||||||
|
func (ctx *HMAC_CTX) Final(md *byte, len *c.Uint) c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 __owur int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).Copy C.HMAC_CTX_copy
|
||||||
|
func (ctx *HMAC_CTX) Copy(sctx *HMAC_CTX) c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
|
||||||
|
//
|
||||||
|
// llgo:link (*HMAC_CTX).SetFlags C.HMAC_CTX_set_flags
|
||||||
|
func (ctx *HMAC_CTX) SetFlags(flags c.Ulong) {}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
@@ -16,8 +16,23 @@
|
|||||||
|
|
||||||
package openssl
|
package openssl
|
||||||
|
|
||||||
const (
|
import (
|
||||||
LLGoPackage = "link: $(pkg-config --libs openssl); -lssl -lcrypto"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoFiles = "$(pkg-config --cflags openssl): _wrap/openssl.c"
|
||||||
|
LLGoPackage = "link: $(pkg-config --libs openssl); -lssl -lcrypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Free C.opensslFree
|
||||||
|
func Free(ptr unsafe.Pointer)
|
||||||
|
|
||||||
|
//go:linkname FreeCStr C.opensslFree
|
||||||
|
func FreeCStr(ptr *c.Char)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
37
c/openssl/pem.go
Normal file
37
c/openssl/pem.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// typedef int (*pem_password_cb)(char *buf, int size, int rwflag, void *userdata);
|
||||||
|
//
|
||||||
|
// llgo:type C
|
||||||
|
type PemPasswordCb func(buf *c.Char, size, rwflag c.Int, userdata unsafe.Pointer) c.Int
|
||||||
|
|
||||||
|
// RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **x, pem_password_cb *cb, void *u);
|
||||||
|
//
|
||||||
|
//go:linkname PEMReadBioRSAPrivateKey C.PEM_read_bio_RSAPrivateKey
|
||||||
|
func PEMReadBioRSAPrivateKey(bp *BIO, x **RSA, cb PemPasswordCb, u unsafe.Pointer) *RSA
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
80
c/openssl/rand.go
Normal file
80
c/openssl/rand.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// int RAND_bytes(unsigned char *buf, int num);
|
||||||
|
//
|
||||||
|
//go:linkname RANDBufferWithLen C.RAND_bytes
|
||||||
|
func RANDBufferWithLen(buf *byte, num c.Int) c.Int
|
||||||
|
|
||||||
|
func RANDBytes(buf []byte) c.Int {
|
||||||
|
return RANDBufferWithLen(unsafe.SliceData(buf), c.Int(len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// int RAND_priv_bytes(unsigned char *buf, int num);
|
||||||
|
//
|
||||||
|
//go:linkname RANDPrivBufferWithLen C.RAND_priv_bytes
|
||||||
|
func RANDPrivBufferWithLen(buf *byte, num c.Int) c.Int
|
||||||
|
|
||||||
|
func RANDPrivBytes(buf []byte) c.Int {
|
||||||
|
return RANDPrivBufferWithLen(unsafe.SliceData(buf), c.Int(len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// void RAND_seed(const void *buf, int num);
|
||||||
|
//
|
||||||
|
//go:linkname RANDSeed C.RAND_seed
|
||||||
|
func RANDSeed(buf unsafe.Pointer, num c.Int)
|
||||||
|
|
||||||
|
// void RAND_keep_random_devices_open(int keep);
|
||||||
|
//
|
||||||
|
//go:linkname RANDKeepRandomDevicesOpen C.RAND_keep_random_devices_open
|
||||||
|
func RANDKeepRandomDevicesOpen(keep c.Int)
|
||||||
|
|
||||||
|
// int RAND_load_file(const char *file, long max_bytes);
|
||||||
|
//
|
||||||
|
//go:linkname RANDLoadFile C.RAND_load_file
|
||||||
|
func RANDLoadFile(file *c.Char, maxBytes c.Long) c.Int
|
||||||
|
|
||||||
|
// int RAND_write_file(const char *file);
|
||||||
|
//
|
||||||
|
//go:linkname RANDWriteFile C.RAND_write_file
|
||||||
|
func RANDWriteFile(file *c.Char) c.Int
|
||||||
|
|
||||||
|
// const char *RAND_file_name(char *file, size_t num);
|
||||||
|
//
|
||||||
|
//go:linkname RANDFileName C.RAND_file_name
|
||||||
|
func RANDFileName(file *c.Char, num uintptr) *c.Char
|
||||||
|
|
||||||
|
// int RAND_status(void);
|
||||||
|
//
|
||||||
|
//go:linkname RANDStatus C.RAND_status
|
||||||
|
func RANDStatus() c.Int
|
||||||
|
|
||||||
|
// int RAND_poll(void);
|
||||||
|
//
|
||||||
|
//go:linkname RANDPoll C.RAND_poll
|
||||||
|
func RANDPoll() c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
305
c/openssl/rsa.go
Normal file
305
c/openssl/rsa.go
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type RSA_METHOD struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 RSA_METHOD *RSA_meth_new(const char *name, int flags);
|
||||||
|
//
|
||||||
|
//go:linkname RSAMethNew C.RSA_meth_new
|
||||||
|
func RSAMethNew(name *byte, flags c.Int) *RSA_METHOD
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void RSA_meth_free(RSA_METHOD *meth);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA_METHOD).Free C.RSA_meth_free
|
||||||
|
func (*RSA_METHOD) Free() {}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0
|
||||||
|
// int RSA_meth_set_init(RSA_METHOD *rsa, int (*init) (RSA *rsa));
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA_METHOD).SetInit C.RSA_meth_set_init
|
||||||
|
func (*RSA_METHOD) SetInit(init func(rsa *RSA) c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0
|
||||||
|
// int RSA_meth_set_finish(RSA_METHOD *rsa, int (*finish) (RSA *rsa));
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA_METHOD).SetFinish C.RSA_meth_set_finish
|
||||||
|
func (*RSA_METHOD) SetFinish(finish func(rsa *RSA) c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_mod_exp(RSA_METHOD *rsa,
|
||||||
|
int (*mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa,
|
||||||
|
BN_CTX *ctx));
|
||||||
|
*/
|
||||||
|
// llgo:link (*RSA_METHOD).SetModExp C.RSA_meth_set_mod_exp
|
||||||
|
func (*RSA_METHOD) SetModExp(modExp func(
|
||||||
|
r0 *BIGNUM, i *BIGNUM, rsa *RSA, ctx *BN_CTX) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_bn_mod_exp(RSA_METHOD *rsa,
|
||||||
|
int (*bn_mod_exp) (BIGNUM *r,
|
||||||
|
const BIGNUM *a,
|
||||||
|
const BIGNUM *p,
|
||||||
|
const BIGNUM *m,
|
||||||
|
BN_CTX *ctx,
|
||||||
|
BN_MONT_CTX *m_ctx));
|
||||||
|
//-llgo:link (*RSA_METHOD).SetBnModExp C.RSA_meth_set_bn_mod_exp
|
||||||
|
func (*RSA_METHOD) SetBnModExp(bnModExp func(
|
||||||
|
r *BIGNUM, a *BIGNUM, p *BIGNUM, m *BIGNUM, ctx *BN_CTX, mCtx *BN_MONT_CTX) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_pub_enc(RSA_METHOD *rsa,
|
||||||
|
int (*pub_enc) (int flen, const unsigned char *from,
|
||||||
|
unsigned char *to, RSA *rsa,
|
||||||
|
int padding));
|
||||||
|
*/
|
||||||
|
// llgo:link (*RSA_METHOD).SetPubEnc C.RSA_meth_set_pub_enc
|
||||||
|
func (*RSA_METHOD) SetPubEnc(pubEnc func(
|
||||||
|
flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_pub_dec(RSA_METHOD *rsa,
|
||||||
|
int (*pub_dec) (int flen, const unsigned char *from,
|
||||||
|
unsigned char *to, RSA *rsa,
|
||||||
|
int padding));
|
||||||
|
*/
|
||||||
|
// llgo:link (*RSA_METHOD).SetPubDec C.RSA_meth_set_pub_dec
|
||||||
|
func (*RSA_METHOD) SetPubDec(pubDec func(
|
||||||
|
flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_priv_enc(RSA_METHOD *rsa,
|
||||||
|
int (*priv_enc) (int flen, const unsigned char *from,
|
||||||
|
unsigned char *to, RSA *rsa,
|
||||||
|
int padding));
|
||||||
|
*/
|
||||||
|
// llgo:link (*RSA_METHOD).SetPrivEnc C.RSA_meth_set_priv_enc
|
||||||
|
func (*RSA_METHOD) SetPrivEnc(privEnc func(
|
||||||
|
flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_priv_dec(RSA_METHOD *rsa,
|
||||||
|
int (*priv_dec) (int flen, const unsigned char *from,
|
||||||
|
unsigned char *to, RSA *rsa,
|
||||||
|
int padding));
|
||||||
|
*/
|
||||||
|
// llgo:link (*RSA_METHOD).SetPrivDec C.RSA_meth_set_priv_dec
|
||||||
|
func (*RSA_METHOD) SetPrivDec(privDec func(
|
||||||
|
flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_sign(RSA_METHOD *rsa,
|
||||||
|
int (*sign) (int type, const unsigned char *m,
|
||||||
|
unsigned int m_length,
|
||||||
|
unsigned char *sigret, unsigned int *siglen,
|
||||||
|
const RSA *rsa));
|
||||||
|
*/
|
||||||
|
// llgo:link (*RSA_METHOD).SetSign C.RSA_meth_set_sign
|
||||||
|
func (*RSA_METHOD) SetSign(sign func(
|
||||||
|
typ c.Int, msg *byte, mlen c.Uint,
|
||||||
|
sigret *byte, siglen *c.Uint, rsa *RSA) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_verify(RSA_METHOD *rsa,
|
||||||
|
int (*verify) (int dtype, const unsigned char *m,
|
||||||
|
unsigned int m_length,
|
||||||
|
const unsigned char *sigbuf,
|
||||||
|
unsigned int siglen, const RSA *rsa));
|
||||||
|
*/
|
||||||
|
// llgo:link (*RSA_METHOD).SetVerify C.RSA_meth_set_verify
|
||||||
|
func (*RSA_METHOD) SetVerify(verify func(
|
||||||
|
dtype c.Int, msg *byte, mlen c.Uint,
|
||||||
|
sigbuf *byte, siglen c.Uint, rsa *RSA) c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_keygen(RSA_METHOD *rsa,
|
||||||
|
int (*keygen) (RSA *rsa, int bits, BIGNUM *e,
|
||||||
|
BN_GENCB *cb));
|
||||||
|
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
|
||||||
|
int (*keygen) (RSA *rsa, int bits,
|
||||||
|
int primes, BIGNUM *e,
|
||||||
|
BN_GENCB *cb));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type RSA struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 RSA *RSA_new(void);
|
||||||
|
//
|
||||||
|
//go:linkname RSANew C.RSA_new
|
||||||
|
func RSANew() *RSA
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 RSA *RSA_new_method(ENGINE *engine);
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void RSA_free(RSA *r);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).Free C.RSA_free
|
||||||
|
func (*RSA) Free() {}
|
||||||
|
|
||||||
|
// "up" the RSA object's reference count
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_up_ref(RSA *r);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).UpRef C.RSA_up_ref
|
||||||
|
func (*RSA) UpRef() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_bits(const RSA *rsa);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).Bits C.RSA_bits
|
||||||
|
func (*RSA) Bits() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_size(const RSA *rsa);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).Size C.RSA_size
|
||||||
|
func (*RSA) Size() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_security_bits(const RSA *rsa);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).SecurityBits C.RSA_security_bits
|
||||||
|
func (*RSA) SecurityBits() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_flags(const RSA *r);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).Flags C.RSA_flags
|
||||||
|
func (*RSA) Flags() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void RSA_set_flags(RSA *r, int flags);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).SetFlags C.RSA_set_flags
|
||||||
|
func (*RSA) SetFlags(flags c.Int) {}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void RSA_clear_flags(RSA *r, int flags);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).ClearFlags C.RSA_clear_flags
|
||||||
|
func (*RSA) ClearFlags(flags c.Int) {}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_test_flags(const RSA *r, int flags);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).TestFlags C.RSA_test_flags
|
||||||
|
func (*RSA) TestFlags(flags c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_get_version(RSA *r);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).GetVersion C.RSA_get_version
|
||||||
|
func (*RSA) GetVersion() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_set_ex_data(RSA *r, int idx, void *arg);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).SetExData C.RSA_set_ex_data
|
||||||
|
func (*RSA) SetExData(idx c.Int, arg unsafe.Pointer) c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void *RSA_get_ex_data(const RSA *r, int idx);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).GetExData C.RSA_get_ex_data
|
||||||
|
func (*RSA) GetExData(idx c.Int) unsafe.Pointer { return nil }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).SetMethod C.RSA_set_method
|
||||||
|
func (*RSA) SetMethod(meth *RSA_METHOD) c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).GenerateKeyEx C.RSA_generate_key_ex
|
||||||
|
func (*RSA) GenerateKeyEx(bits c.Int, e *BIGNUM, cb *BN_GENCB) c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb);
|
||||||
|
//
|
||||||
|
// llgo:link (*RSA).GenerateMultiPrimeKey C.RSA_generate_multi_prime_key
|
||||||
|
func (*RSA) GenerateMultiPrimeKey(bits, primes c.Int, e *BIGNUM, cb *BN_GENCB) c.Int { return 0 }
|
||||||
|
|
||||||
|
/*
|
||||||
|
// next 4 return -1 on error
|
||||||
|
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||||
|
RSA *rsa, int padding);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||||
|
RSA *rsa, int padding);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||||
|
RSA *rsa, int padding);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||||
|
RSA *rsa, int padding);
|
||||||
|
*/
|
||||||
|
//go:linkname RSAPublicEncrypt C.RSA_public_encrypt
|
||||||
|
func RSAPublicEncrypt(flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname RSAPrivateEncrypt C.RSA_private_encrypt
|
||||||
|
func RSAPrivateEncrypt(flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname RSAPublicDecrypt C.RSA_public_decrypt
|
||||||
|
func RSAPublicDecrypt(flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname RSAPrivateDecrypt C.RSA_private_decrypt
|
||||||
|
func RSAPrivateDecrypt(flen c.Int, from *byte, to *byte, rsa *RSA, padding c.Int) c.Int
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_sign(
|
||||||
|
// int type, const unsigned char *m, unsigned int m_length,
|
||||||
|
// unsigned char *sigret, unsigned int *siglen, RSA *rsa);
|
||||||
|
//
|
||||||
|
//go:linkname RSASign C.RSA_sign
|
||||||
|
func RSASign(typ c.Int, msg *byte, mlen c.Uint, sigret *byte, siglen *c.Uint, rsa *RSA) c.Int
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int RSA_verify(int type, const unsigned char *m,
|
||||||
|
// unsigned int m_length,
|
||||||
|
// const unsigned char *sigbuf,
|
||||||
|
// unsigned int siglen, RSA *rsa);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
9
c/os/_os/os.c
Normal file
9
c/os/_os/os.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int llgoClearenv() {
|
||||||
|
extern char **environ;
|
||||||
|
if (environ != NULL) {
|
||||||
|
*environ = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -27,10 +27,6 @@ import (
|
|||||||
"github.com/goplus/llgo/c/syscall"
|
"github.com/goplus/llgo/c/syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
LLGoPackage = "decl"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PATH_MAX = C.PATH_MAX
|
PATH_MAX = C.PATH_MAX
|
||||||
)
|
)
|
||||||
@@ -150,9 +146,6 @@ func Putenv(env *c.Char) c.Int
|
|||||||
//go:linkname Unsetenv C.unsetenv
|
//go:linkname Unsetenv C.unsetenv
|
||||||
func Unsetenv(name *c.Char) c.Int
|
func Unsetenv(name *c.Char) c.Int
|
||||||
|
|
||||||
//go:linkname Clearenv C.clearenv
|
|
||||||
func Clearenv()
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Fchdir C.fchdir
|
//go:linkname Fchdir C.fchdir
|
||||||
|
|||||||
28
c/os/os_linux.go
Normal file
28
c/os/os_linux.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 os
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "decl"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Clearenv C.clearenv
|
||||||
|
func Clearenv()
|
||||||
29
c/os/os_other.go
Normal file
29
c/os/os_other.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 os
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoFiles = "_os/os.c"
|
||||||
|
LLGoPackage = "link"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Clearenv C.llgoClearenv
|
||||||
|
func Clearenv()
|
||||||
217
chore/_xtool/castdump/castdump.go
Normal file
217
chore/_xtool/castdump/castdump.go
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/clang"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Data struct {
|
||||||
|
Depth c.Uint
|
||||||
|
Unit *clang.TranslationUnit
|
||||||
|
}
|
||||||
|
|
||||||
|
var accessMap = map[clang.CXXAccessSpecifier]string{
|
||||||
|
clang.CXXInvalidAccessSpecifier: "invalid",
|
||||||
|
clang.CXXPublic: "public",
|
||||||
|
clang.CXXProtected: "protected",
|
||||||
|
clang.CXXPrivate: "private",
|
||||||
|
}
|
||||||
|
|
||||||
|
func printIndent(depth c.Uint) {
|
||||||
|
fmt.Print(strings.Repeat(" ", int(depth)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func accessToString(spec clang.CXXAccessSpecifier) string {
|
||||||
|
if str, ok := accessMap[spec]; ok {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
func visit(cursor, parent clang.Cursor, ClientData c.Pointer) clang.ChildVisitResult {
|
||||||
|
data := (*Data)(ClientData)
|
||||||
|
printAST(cursor, data)
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
func printType(t clang.Type, data *Data) {
|
||||||
|
printIndent(data.Depth)
|
||||||
|
|
||||||
|
typeSpell := t.String()
|
||||||
|
typeKind := t.Kind.String()
|
||||||
|
|
||||||
|
if t.Kind == clang.TypeInvalid {
|
||||||
|
} else if t.Kind == clang.TypeUnexposed {
|
||||||
|
c.Printf(c.Str("<UnexposedType|%s>: %s\n"), typeKind.CStr(), typeSpell.CStr())
|
||||||
|
} else if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin {
|
||||||
|
c.Printf(c.Str("<BuiltinType|%s>: %s\n"), typeKind.CStr(), typeSpell.CStr())
|
||||||
|
} else if t.Kind > clang.TypeComplex {
|
||||||
|
c.Printf(c.Str("<ComplexType|%s>: %s\n"), typeKind.CStr(), typeSpell.CStr())
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Depth++
|
||||||
|
switch t.Kind {
|
||||||
|
case clang.TypePointer:
|
||||||
|
printType(t.PointeeType(), data)
|
||||||
|
case clang.TypeIncompleteArray, clang.TypeVariableArray, clang.TypeDependentSizedArray, clang.TypeConstantArray:
|
||||||
|
printType(t.ArrayElementType(), data)
|
||||||
|
case clang.TypeTypedef:
|
||||||
|
printType(t.CanonicalType(), data)
|
||||||
|
case clang.TypeFunctionProto:
|
||||||
|
printType(t.ResultType(), data)
|
||||||
|
for i := 0; i < int(t.NumArgTypes()); i++ {
|
||||||
|
printType(t.ArgType(c.Uint(i)), data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.Depth--
|
||||||
|
|
||||||
|
typeKind.Dispose()
|
||||||
|
typeSpell.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
func printLocation(cursor clang.Cursor) {
|
||||||
|
loc := cursor.Location()
|
||||||
|
var file clang.File
|
||||||
|
var line, column c.Uint
|
||||||
|
|
||||||
|
loc.SpellingLocation(&file, &line, &column, nil)
|
||||||
|
filename := file.FileName()
|
||||||
|
defer filename.Dispose()
|
||||||
|
|
||||||
|
c.Printf(c.Str("(Loc:%s:%d:%d)\n"), filename.CStr(), line, column)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printAccess(cursor clang.Cursor) {
|
||||||
|
kind := cursor.Kind.String()
|
||||||
|
spell := cursor.String()
|
||||||
|
defer kind.Dispose()
|
||||||
|
defer spell.Dispose()
|
||||||
|
|
||||||
|
c.Printf(c.Str("%s: %s %s"), kind.CStr(), spell.CStr(), c.AllocaCStr(accessToString(cursor.CXXAccessSpecifier())))
|
||||||
|
printLocation(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printMacro(cursor clang.Cursor, unit *clang.TranslationUnit) {
|
||||||
|
kind := cursor.Kind.String()
|
||||||
|
defer kind.Dispose()
|
||||||
|
|
||||||
|
c.Printf(c.Str("%s: "), kind.CStr())
|
||||||
|
ran := cursor.Extent()
|
||||||
|
var numTokens c.Uint
|
||||||
|
var tokens *clang.Token
|
||||||
|
unit.Tokenize(ran, &tokens, &numTokens)
|
||||||
|
tokensSlice := unsafe.Slice(tokens, int(numTokens))
|
||||||
|
for _, tok := range tokensSlice {
|
||||||
|
tokStr := unit.Token(tok)
|
||||||
|
c.Printf(c.Str("%s "), tokStr.CStr())
|
||||||
|
tokStr.Dispose()
|
||||||
|
}
|
||||||
|
printLocation(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printFunc(cursor clang.Cursor, data *Data) {
|
||||||
|
kind := cursor.Kind.String()
|
||||||
|
spell := cursor.String()
|
||||||
|
symbol := cursor.Mangling()
|
||||||
|
defer symbol.Dispose()
|
||||||
|
defer kind.Dispose()
|
||||||
|
defer spell.Dispose()
|
||||||
|
|
||||||
|
c.Printf(c.Str("%s: %s (Symbol: %s)"), kind.CStr(), spell.CStr(), symbol.CStr())
|
||||||
|
printLocation(cursor)
|
||||||
|
printType(cursor.Type(), data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printEnumConstant(cursor clang.Cursor) {
|
||||||
|
kind := cursor.Kind.String()
|
||||||
|
spell := cursor.String()
|
||||||
|
defer kind.Dispose()
|
||||||
|
defer spell.Dispose()
|
||||||
|
|
||||||
|
c.Printf(c.Str("%s: %s:%lld"), kind.CStr(), spell.CStr(), cursor.EnumConstantDeclValue())
|
||||||
|
printLocation(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printDefault(cursor clang.Cursor, data *Data) {
|
||||||
|
kind := cursor.Kind.String()
|
||||||
|
spell := cursor.String()
|
||||||
|
defer kind.Dispose()
|
||||||
|
defer spell.Dispose()
|
||||||
|
|
||||||
|
// node which has type
|
||||||
|
if cursor.Type().Kind != clang.TypeInvalid {
|
||||||
|
c.Printf(c.Str("%s: %s"), kind.CStr(), spell.CStr())
|
||||||
|
printLocation(cursor)
|
||||||
|
printType(cursor.Type(), data)
|
||||||
|
} else {
|
||||||
|
c.Printf(c.Str("%s: %s\n"), kind.CStr(), spell.CStr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printAST(cursor clang.Cursor, data *Data) {
|
||||||
|
kind := cursor.Kind.String()
|
||||||
|
spell := cursor.String()
|
||||||
|
|
||||||
|
printIndent(data.Depth)
|
||||||
|
|
||||||
|
switch cursor.Kind {
|
||||||
|
case clang.CursorCXXAccessSpecifier:
|
||||||
|
printAccess(cursor)
|
||||||
|
case clang.CursorMacroDefinition:
|
||||||
|
printMacro(cursor, data.Unit)
|
||||||
|
case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor:
|
||||||
|
printFunc(cursor, data)
|
||||||
|
case clang.CursorEnumConstantDecl:
|
||||||
|
printEnumConstant(cursor)
|
||||||
|
default:
|
||||||
|
printDefault(cursor, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Depth++
|
||||||
|
clang.VisitChildren(cursor, visit, c.Pointer(data))
|
||||||
|
data.Depth--
|
||||||
|
|
||||||
|
kind.Dispose()
|
||||||
|
spell.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if c.Argc != 2 {
|
||||||
|
fmt.Fprintln(os.Stderr, "Usage: castdump <headerFile>")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
args := make([]*c.Char, 3)
|
||||||
|
args[0] = c.Str("-x")
|
||||||
|
args[1] = c.Str("c++")
|
||||||
|
args[2] = c.Str("-std=c++11")
|
||||||
|
|
||||||
|
sourceFile := *c.Advance(c.Argv, 1)
|
||||||
|
index := clang.CreateIndex(0, 0)
|
||||||
|
unit := index.ParseTranslationUnit(
|
||||||
|
sourceFile,
|
||||||
|
unsafe.SliceData(args), 3,
|
||||||
|
nil, 0,
|
||||||
|
clang.DetailedPreprocessingRecord,
|
||||||
|
)
|
||||||
|
defer index.Dispose()
|
||||||
|
defer unit.Dispose()
|
||||||
|
|
||||||
|
if unit == nil {
|
||||||
|
println("Unable to parse translation unit. Quitting.")
|
||||||
|
c.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := unit.Cursor()
|
||||||
|
|
||||||
|
Data := &Data{
|
||||||
|
Depth: 0,
|
||||||
|
Unit: unit,
|
||||||
|
}
|
||||||
|
printAST(cursor, Data)
|
||||||
|
}
|
||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -61,11 +60,11 @@ func main() {
|
|||||||
|
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
filepaths := generateHeaderFilePath(conf.CFlags, conf.Include)
|
filepaths := genHeaderFilePath(conf.CFlags, conf.Include)
|
||||||
astInfos, err := parse.ParseHeaderFile(filepaths)
|
headerInfos, err := parse.ParseHeaderFile(filepaths, conf.TrimPrefixes)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
symbolInfo := getCommonSymbols(symbols, astInfos, conf.TrimPrefixes)
|
symbolInfo := getCommonSymbols(symbols, headerInfos, conf.TrimPrefixes)
|
||||||
|
|
||||||
err = genSymbolTableFile(symbolInfo)
|
err = genSymbolTableFile(symbolInfo)
|
||||||
check(err)
|
check(err)
|
||||||
@@ -77,8 +76,8 @@ func check(err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDylibSymbols(lib string) ([]types.CPPSymbol, error) {
|
func parseDylibSymbols(lib string) ([]*nm.Symbol, error) {
|
||||||
dylibPath, err := generateDylibPath(lib)
|
dylibPath, err := genDylibPath(lib)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to generate dylib path")
|
return nil, errors.New("failed to generate dylib path")
|
||||||
}
|
}
|
||||||
@@ -88,22 +87,15 @@ func parseDylibSymbols(lib string) ([]types.CPPSymbol, error) {
|
|||||||
return nil, errors.New("failed to list symbols in dylib")
|
return nil, errors.New("failed to list symbols in dylib")
|
||||||
}
|
}
|
||||||
|
|
||||||
var symbols []types.CPPSymbol
|
var symbols []*nm.Symbol
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
for _, sym := range file.Symbols {
|
symbols = append(symbols, file.Symbols...)
|
||||||
demangleName := decodeSymbolName(sym.Name)
|
|
||||||
symbols = append(symbols, types.CPPSymbol{
|
|
||||||
Symbol: sym,
|
|
||||||
DemangleName: demangleName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return symbols, nil
|
return symbols, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateDylibPath(lib string) (string, error) {
|
func genDylibPath(lib string) (string, error) {
|
||||||
output := lib
|
output := lib
|
||||||
libPath := ""
|
libPath := ""
|
||||||
libName := ""
|
libName := ""
|
||||||
@@ -123,31 +115,20 @@ func generateDylibPath(lib string) (string, error) {
|
|||||||
return dylibPath, nil
|
return dylibPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeSymbolName(symbolName string) string {
|
func decodeSymbol(symbolName string) string {
|
||||||
if symbolName == "" {
|
if symbolName == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
demangled := llvm.ItaniumDemangle(symbolName, true)
|
demangled := llvm.ItaniumDemangle(symbolName, true)
|
||||||
if demangled == nil {
|
if demangled == nil {
|
||||||
return symbolName
|
return symbolName
|
||||||
}
|
}
|
||||||
defer c.Free(unsafe.Pointer(demangled))
|
defer c.Free(unsafe.Pointer(demangled))
|
||||||
|
|
||||||
demangleName := c.GoString(demangled)
|
demangleName := c.GoString(demangled)
|
||||||
if demangleName == "" {
|
return strings.TrimSpace(demangleName)
|
||||||
return symbolName
|
|
||||||
}
|
|
||||||
|
|
||||||
decodedName := strings.TrimSpace(demangleName)
|
|
||||||
decodedName = strings.ReplaceAll(decodedName,
|
|
||||||
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const",
|
|
||||||
"std::string")
|
|
||||||
|
|
||||||
return decodedName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateHeaderFilePath(cflags string, files []string) []string {
|
func genHeaderFilePath(cflags string, files []string) []string {
|
||||||
prefixPath := cflags
|
prefixPath := cflags
|
||||||
prefixPath = strings.TrimPrefix(prefixPath, "-I")
|
prefixPath = strings.TrimPrefix(prefixPath, "-I")
|
||||||
var includePaths []string
|
var includePaths []string
|
||||||
@@ -157,77 +138,23 @@ func generateHeaderFilePath(cflags string, files []string) []string {
|
|||||||
return includePaths
|
return includePaths
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCommonSymbols(dylibSymbols []types.CPPSymbol, astInfoList []types.ASTInformation, prefix []string) []types.SymbolInfo {
|
func getCommonSymbols(dylibSymbols []*nm.Symbol, symbolMap map[string]string, prefix []string) []*types.SymbolInfo {
|
||||||
var commonSymbols []types.SymbolInfo
|
var commonSymbols []*types.SymbolInfo
|
||||||
functionNameMap := make(map[string]int)
|
for _, dylibSym := range dylibSymbols {
|
||||||
|
symName := strings.TrimPrefix(dylibSym.Name, "_")
|
||||||
for _, astInfo := range astInfoList {
|
if goName, ok := symbolMap[symName]; ok {
|
||||||
for _, dylibSym := range dylibSymbols {
|
symbolInfo := &types.SymbolInfo{
|
||||||
if strings.TrimPrefix(dylibSym.Name, "_") == astInfo.Symbol {
|
Mangle: symName,
|
||||||
cppName := generateCPPName(astInfo)
|
CPP: decodeSymbol(dylibSym.Name),
|
||||||
functionNameMap[cppName]++
|
Go: goName,
|
||||||
symbolInfo := types.SymbolInfo{
|
|
||||||
Mangle: strings.TrimPrefix(dylibSym.Name, "_"),
|
|
||||||
CPP: cppName,
|
|
||||||
Go: generateMangle(astInfo, functionNameMap[cppName], prefix),
|
|
||||||
}
|
|
||||||
commonSymbols = append(commonSymbols, symbolInfo)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
commonSymbols = append(commonSymbols, symbolInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return commonSymbols
|
return commonSymbols
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateCPPName(astInfo types.ASTInformation) string {
|
func genSymbolTableFile(symbolInfos []*types.SymbolInfo) error {
|
||||||
cppName := astInfo.Name
|
|
||||||
if astInfo.Class != "" {
|
|
||||||
cppName = astInfo.Class + "::" + astInfo.Name
|
|
||||||
}
|
|
||||||
return cppName
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateMangle(astInfo types.ASTInformation, count int, prefixes []string) string {
|
|
||||||
astInfo.Class = removePrefix(astInfo.Class, prefixes)
|
|
||||||
astInfo.Name = removePrefix(astInfo.Name, prefixes)
|
|
||||||
res := ""
|
|
||||||
if astInfo.Class != "" {
|
|
||||||
if astInfo.Class == astInfo.Name {
|
|
||||||
res = "(*" + astInfo.Class + ")." + "Init"
|
|
||||||
if count > 1 {
|
|
||||||
res += "__" + strconv.Itoa(count-1)
|
|
||||||
}
|
|
||||||
} else if astInfo.Name == "~"+astInfo.Class {
|
|
||||||
res = "(*" + astInfo.Class + ")." + "Dispose"
|
|
||||||
if count > 1 {
|
|
||||||
res += "__" + strconv.Itoa(count-1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res = "(*" + astInfo.Class + ")." + astInfo.Name
|
|
||||||
if count > 1 {
|
|
||||||
res += "__" + strconv.Itoa(count-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res = astInfo.Name
|
|
||||||
if count > 1 {
|
|
||||||
res += "__" + strconv.Itoa(count-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func removePrefix(str string, prefixes []string) string {
|
|
||||||
for _, prefix := range prefixes {
|
|
||||||
if strings.HasPrefix(str, prefix) {
|
|
||||||
return strings.TrimPrefix(str, prefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
func genSymbolTableFile(symbolInfos []types.SymbolInfo) error {
|
|
||||||
// keep open follow code block can run successfully
|
// keep open follow code block can run successfully
|
||||||
for i := range symbolInfos {
|
for i := range symbolInfos {
|
||||||
println("symbol", symbolInfos[i].Go)
|
println("symbol", symbolInfos[i].Go)
|
||||||
@@ -269,6 +196,7 @@ func genSymbolTableFile(symbolInfos []types.SymbolInfo) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readExistingSymbolTable(fileName string) (map[string]types.SymbolInfo, error) {
|
func readExistingSymbolTable(fileName string) (map[string]types.SymbolInfo, error) {
|
||||||
existingSymbols := make(map[string]types.SymbolInfo)
|
existingSymbols := make(map[string]types.SymbolInfo)
|
||||||
|
|
||||||
|
|||||||
@@ -3,23 +3,27 @@ package parse
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/clang"
|
"github.com/goplus/llgo/c/clang"
|
||||||
"github.com/goplus/llgo/chore/llcppg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
namespaceName string
|
namespaceName string
|
||||||
className string
|
className string
|
||||||
astInfo []types.ASTInformation
|
prefixes []string
|
||||||
|
symbolMap map[string]string
|
||||||
currentFile string
|
currentFile string
|
||||||
|
nameCounts map[string]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext() *Context {
|
func newContext(prefixes []string) *Context {
|
||||||
return &Context{
|
return &Context{
|
||||||
astInfo: make([]types.ASTInformation, 0),
|
prefixes: prefixes,
|
||||||
|
symbolMap: make(map[string]string),
|
||||||
|
nameCounts: make(map[string]int),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,70 +39,83 @@ func (c *Context) setCurrentFile(filename string) {
|
|||||||
c.currentFile = filename
|
c.currentFile = filename
|
||||||
}
|
}
|
||||||
|
|
||||||
var context = newContext()
|
func (c *Context) removePrefix(str string) string {
|
||||||
|
for _, prefix := range c.prefixes {
|
||||||
|
if strings.HasPrefix(str, prefix) {
|
||||||
|
return strings.TrimPrefix(str, prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
func collectFuncInfo(cursor clang.Cursor) types.ASTInformation {
|
func (c *Context) genGoName(name string) string {
|
||||||
|
class := c.removePrefix(c.className)
|
||||||
|
name = c.removePrefix(name)
|
||||||
|
|
||||||
info := types.ASTInformation{
|
var baseName string
|
||||||
Namespace: context.namespaceName,
|
if class == "" {
|
||||||
Class: context.className,
|
baseName = name
|
||||||
|
} else {
|
||||||
|
baseName = c.genMethodName(class, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return c.addSuffix(baseName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) genMethodName(class, name string) string {
|
||||||
|
prefix := "(*" + class + ")."
|
||||||
|
if class == name {
|
||||||
|
return prefix + "Init"
|
||||||
|
}
|
||||||
|
if name == "~"+class {
|
||||||
|
return prefix + "Dispose"
|
||||||
|
}
|
||||||
|
return prefix + name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) addSuffix(name string) string {
|
||||||
|
c.nameCounts[name]++
|
||||||
|
count := c.nameCounts[name]
|
||||||
|
if count > 1 {
|
||||||
|
return name + "__" + strconv.Itoa(count-1)
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = newContext([]string{})
|
||||||
|
|
||||||
|
func collectFuncInfo(cursor clang.Cursor) {
|
||||||
cursorStr := cursor.String()
|
cursorStr := cursor.String()
|
||||||
symbol := cursor.Mangling()
|
symbol := cursor.Mangling()
|
||||||
|
|
||||||
info.Name = c.GoString(cursorStr.CStr())
|
name := c.GoString(cursorStr.CStr())
|
||||||
|
symbolName := c.GoString(symbol.CStr())
|
||||||
info.Symbol = c.GoString(symbol.CStr())
|
if len(symbolName) >= 1 && symbolName[0] == '_' {
|
||||||
if len(info.Symbol) >= 1 {
|
symbolName = symbolName[1:]
|
||||||
if info.Symbol[0] == '_' {
|
|
||||||
info.Symbol = info.Symbol[1:]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer symbol.Dispose()
|
defer symbol.Dispose()
|
||||||
defer cursorStr.Dispose()
|
defer cursorStr.Dispose()
|
||||||
|
|
||||||
if context.namespaceName != "" {
|
goName := context.genGoName(name)
|
||||||
info.Namespace = context.namespaceName
|
context.symbolMap[symbolName] = goName
|
||||||
}
|
|
||||||
if context.className != "" {
|
|
||||||
info.Class = context.className
|
|
||||||
}
|
|
||||||
|
|
||||||
typeStr := cursor.ResultType().String()
|
|
||||||
defer typeStr.Dispose()
|
|
||||||
info.ReturnType = c.GoString(typeStr.CStr())
|
|
||||||
|
|
||||||
info.Parameters = make([]types.Parameter, cursor.NumArguments())
|
|
||||||
for i := 0; i < int(cursor.NumArguments()); i++ {
|
|
||||||
argCurSor := cursor.Argument(c.Uint(i))
|
|
||||||
argType := argCurSor.Type().String()
|
|
||||||
argName := argCurSor.String()
|
|
||||||
info.Parameters[i] = types.Parameter{
|
|
||||||
Name: c.GoString(argName.CStr()),
|
|
||||||
Type: c.GoString(argType.CStr()),
|
|
||||||
}
|
|
||||||
|
|
||||||
argType.Dispose()
|
|
||||||
argName.Dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
return info
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
||||||
if cursor.Kind == clang.Namespace {
|
if cursor.Kind == clang.CursorNamespace {
|
||||||
nameStr := cursor.String()
|
nameStr := cursor.String()
|
||||||
|
defer nameStr.Dispose()
|
||||||
|
|
||||||
context.setNamespaceName(c.GoString(nameStr.CStr()))
|
context.setNamespaceName(c.GoString(nameStr.CStr()))
|
||||||
clang.VisitChildren(cursor, visit, nil)
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
context.setNamespaceName("")
|
context.setNamespaceName("")
|
||||||
} else if cursor.Kind == clang.ClassDecl {
|
} else if cursor.Kind == clang.CursorClassDecl {
|
||||||
nameStr := cursor.String()
|
nameStr := cursor.String()
|
||||||
|
defer nameStr.Dispose()
|
||||||
|
|
||||||
context.setClassName(c.GoString(nameStr.CStr()))
|
context.setClassName(c.GoString(nameStr.CStr()))
|
||||||
clang.VisitChildren(cursor, visit, nil)
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
context.setClassName("")
|
context.setClassName("")
|
||||||
} else if cursor.Kind == clang.CXXMethod || cursor.Kind == clang.FunctionDecl || cursor.Kind == clang.Constructor || cursor.Kind == clang.Destructor {
|
} else if cursor.Kind == clang.CursorCXXMethod || cursor.Kind == clang.CursorFunctionDecl || cursor.Kind == clang.CursorConstructor || cursor.Kind == clang.CursorDestructor {
|
||||||
loc := cursor.Location()
|
loc := cursor.Location()
|
||||||
var file clang.File
|
var file clang.File
|
||||||
var line, column c.Uint
|
var line, column c.Uint
|
||||||
@@ -107,9 +124,7 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
|
|||||||
filename := file.FileName()
|
filename := file.FileName()
|
||||||
|
|
||||||
if c.Strcmp(filename.CStr(), c.AllocaCStr(context.currentFile)) == 0 {
|
if c.Strcmp(filename.CStr(), c.AllocaCStr(context.currentFile)) == 0 {
|
||||||
info := collectFuncInfo(cursor)
|
collectFuncInfo(cursor)
|
||||||
info.Location = c.GoString(filename.CStr()) + ":" + strconv.Itoa(int(line)) + ":" + strconv.Itoa(int(column))
|
|
||||||
context.astInfo = append(context.astInfo, info)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer filename.Dispose()
|
defer filename.Dispose()
|
||||||
@@ -118,14 +133,13 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
|
|||||||
return clang.ChildVisit_Continue
|
return clang.ChildVisit_Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHeaderFile(filepaths []string) ([]types.ASTInformation, error) {
|
func ParseHeaderFile(filepaths []string, prefixes []string) (map[string]string, error) {
|
||||||
|
|
||||||
index := clang.CreateIndex(0, 0)
|
index := clang.CreateIndex(0, 0)
|
||||||
args := make([]*c.Char, 3)
|
args := make([]*c.Char, 3)
|
||||||
args[0] = c.Str("-x")
|
args[0] = c.Str("-x")
|
||||||
args[1] = c.Str("c++")
|
args[1] = c.Str("c++")
|
||||||
args[2] = c.Str("-std=c++11")
|
args[2] = c.Str("-std=c++11")
|
||||||
context = newContext()
|
context = newContext(prefixes)
|
||||||
|
|
||||||
for _, filename := range filepaths {
|
for _, filename := range filepaths {
|
||||||
unit := index.ParseTranslationUnit(
|
unit := index.ParseTranslationUnit(
|
||||||
@@ -149,5 +163,5 @@ func ParseHeaderFile(filepaths []string) ([]types.ASTInformation, error) {
|
|||||||
|
|
||||||
index.Dispose()
|
index.Dispose()
|
||||||
|
|
||||||
return context.astInfo, nil
|
return context.symbolMap, nil
|
||||||
}
|
}
|
||||||
|
|||||||
292
chore/llcppg/ast/ast.go
Normal file
292
chore/llcppg/ast/ast.go
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* 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 ast
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
type Node interface {
|
||||||
|
}
|
||||||
|
|
||||||
|
type Expr interface {
|
||||||
|
Node
|
||||||
|
exprNode()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Decl interface {
|
||||||
|
Node
|
||||||
|
declNode()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stmt interface {
|
||||||
|
Node
|
||||||
|
stmtNode()
|
||||||
|
}
|
||||||
|
|
||||||
|
type PPD interface { // preprocessing directive
|
||||||
|
Node
|
||||||
|
ppdNode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Expressions (Types are also expressions)
|
||||||
|
|
||||||
|
type TypeKind uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
Int TypeKind = iota
|
||||||
|
Char
|
||||||
|
Float
|
||||||
|
Complex
|
||||||
|
Bool
|
||||||
|
)
|
||||||
|
|
||||||
|
type TypeFlag uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
Signed TypeFlag = 1 << iota
|
||||||
|
Unsigned
|
||||||
|
Long
|
||||||
|
LongLong
|
||||||
|
Double
|
||||||
|
Short
|
||||||
|
)
|
||||||
|
|
||||||
|
// [signed/unsigned/short/long/long long/double] [int]/char/float/complex/bool
|
||||||
|
type BuiltinType struct {
|
||||||
|
Kind TypeKind
|
||||||
|
Flags TypeFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*BuiltinType) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// Name
|
||||||
|
type Ident struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Ident) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
type Tag int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Struct Tag = iota
|
||||||
|
Union
|
||||||
|
Enum
|
||||||
|
Class
|
||||||
|
)
|
||||||
|
|
||||||
|
// struct/union/enum/class Name
|
||||||
|
type TagExpr struct {
|
||||||
|
Tag Tag
|
||||||
|
Name *Ident
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TagExpr) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// (X)
|
||||||
|
type ParenExpr struct {
|
||||||
|
X Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ParenExpr) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// Parent::X
|
||||||
|
type ScopingExpr struct {
|
||||||
|
Parent Expr
|
||||||
|
X Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ScopingExpr) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// X*
|
||||||
|
type PointerType struct {
|
||||||
|
X Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*PointerType) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// X&
|
||||||
|
type ReferenceType struct {
|
||||||
|
X Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ReferenceType) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// Elt[Len]
|
||||||
|
// Elt[]
|
||||||
|
type ArrayType struct {
|
||||||
|
Elt Expr
|
||||||
|
Len Expr // optional
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ArrayType) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
type Comment struct {
|
||||||
|
Text string // comment text (excluding '\n' for //-style comments)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Comment) exprNode() {}
|
||||||
|
|
||||||
|
type CommentGroup struct {
|
||||||
|
List []*Comment // len(List) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CommentGroup) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
Doc *CommentGroup // associated documentation; or nil
|
||||||
|
Type Expr // field/method/parameter type; or nil
|
||||||
|
Names []*Ident // field/method/(type) parameter names; or nil
|
||||||
|
Comment *CommentGroup // line comments; or nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Field) exprNode() {}
|
||||||
|
|
||||||
|
type FieldList struct {
|
||||||
|
List []*Field // field list; or nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FieldList) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// Ret (*)(Params)
|
||||||
|
type FuncType struct {
|
||||||
|
Params *FieldList
|
||||||
|
Ret Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FuncType) exprNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// Template<Arg1, Arg2, ...>
|
||||||
|
type InstantiationType struct {
|
||||||
|
Template Expr
|
||||||
|
Args *FieldList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*InstantiationType) exprNode() {}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Declarations
|
||||||
|
|
||||||
|
type Location struct {
|
||||||
|
File string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeclBase struct {
|
||||||
|
Doc *CommentGroup // associated documentation; or nil
|
||||||
|
Loc *Location
|
||||||
|
Parent Expr // namespace or class
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// typedef Type Name;
|
||||||
|
type TypedefDecl struct {
|
||||||
|
DeclBase
|
||||||
|
Type Expr
|
||||||
|
Name *Ident
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TypedefDecl) declNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
type EnumItem struct {
|
||||||
|
Name *Ident
|
||||||
|
Value Expr // optional
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EnumItem) exprNode() {}
|
||||||
|
|
||||||
|
// enum Name { Item1, Item2, ... };
|
||||||
|
type EnumTypeDecl struct {
|
||||||
|
DeclBase
|
||||||
|
Name *Ident
|
||||||
|
Items []*EnumItem
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EnumTypeDecl) declNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// Ret Name(Params);
|
||||||
|
type FuncDecl struct {
|
||||||
|
DeclBase
|
||||||
|
Name *Ident
|
||||||
|
Type *FuncType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FuncDecl) declNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
// struct/union/class Name { Field1, Field2, ... };
|
||||||
|
type TypeDecl struct {
|
||||||
|
DeclBase
|
||||||
|
Tag Tag
|
||||||
|
Fields *FieldList
|
||||||
|
Methods []*FuncDecl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TypeDecl) declNode() {}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// AST File
|
||||||
|
|
||||||
|
type Include struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Include) ppdNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
type Macro struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Macro) ppdNode() {}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Decls []Decl `json:"decls"`
|
||||||
|
Includes []*Include `json:"includes,omitempty"`
|
||||||
|
Macros []*Macro `json:"macros,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
@@ -59,8 +59,21 @@ llcppsigfetch - # read config from stdin
|
|||||||
|
|
||||||
It fetches information of C/C++ symbols and print to stdout. Its format is as follows:
|
It fetches information of C/C++ symbols and print to stdout. Its format is as follows:
|
||||||
|
|
||||||
```
|
```json
|
||||||
TODO: see llgo/xtool/clang/ast
|
[
|
||||||
|
{
|
||||||
|
"path": "/path/to/file.h",
|
||||||
|
"doc": {
|
||||||
|
"decls": [],
|
||||||
|
"macros": [],
|
||||||
|
"includes": [
|
||||||
|
{
|
||||||
|
"path": "incfile.h"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### gogensig
|
### gogensig
|
||||||
@@ -69,252 +82,3 @@ TODO: see llgo/xtool/clang/ast
|
|||||||
gogensig ast-file
|
gogensig ast-file
|
||||||
gogensig - # read AST from stdin
|
gogensig - # read AST from stdin
|
||||||
```
|
```
|
||||||
|
|
||||||
## Overall
|
|
||||||
|
|
||||||
### Process
|
|
||||||
|
|
||||||
1. The Parsing Module reads `llcppg.cfg` to obtain dynamic libraries, header files, and the package name. After parsing, it writes the generated `llcppg.symb.json` path into `llcppg.cfg`.
|
|
||||||
2. The Function Declaration Generation Module reads `llcppg.cfg` to get the package name, header files, and the previously generated `llcppg.symb.json`. After parsing, it generates the function prototype `llcppg.function.json`.
|
|
||||||
3. Reads the previously generated `llcppg.information.json`, stores it as a structure, and uses gogen to generate code based on the structure.
|
|
||||||
|
|
||||||
## Parsing Module
|
|
||||||
|
|
||||||
### Input
|
|
||||||
|
|
||||||
Obtains the paths to header files and dynamic library files by reading the JSON file `llcppg.cfg`.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "inih",
|
|
||||||
"cflags": "$(pkg-config --cflags INIReader)",
|
|
||||||
"include": [
|
|
||||||
"INIReader.h",
|
|
||||||
"AnotherHeaderFile.h"
|
|
||||||
],
|
|
||||||
"libs": "$(pkg-config --libs INIReader)",
|
|
||||||
"trimPrefixes": ["Ini", "INI"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
llcppsymg config-file
|
|
||||||
```
|
|
||||||
|
|
||||||
### Implementation Steps
|
|
||||||
|
|
||||||
1. Parse dylib and store:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// types.go
|
|
||||||
type CPPSymbol struct {
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// parser_dylib.go
|
|
||||||
func parseDylibSymbols(lib string) ([]common.CPPSymbol, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Parse header files and store:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// common.go
|
|
||||||
type ASTInformation struct {
|
|
||||||
Namespace string `json:"namespace"`
|
|
||||||
Class string `json:"class"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
BaseClasses []string `json:"baseClasses"`
|
|
||||||
ReturnType string `json:"returnType"`
|
|
||||||
Location string `json:"location"`
|
|
||||||
Parameters []Parameter `json:"parameters"`
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Parameter struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// parser_ast.go
|
|
||||||
func parseHeaderFile(config types.Config) ([]common.ASTInformation, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Cross-reference data from the first two steps to get the final output
|
|
||||||
|
|
||||||
```go
|
|
||||||
// common.go
|
|
||||||
type SymbolInfo struct {
|
|
||||||
Mangle string `json:"mangle"` // C++ Symbol
|
|
||||||
CPP string `json:"c++"` // C++ function name
|
|
||||||
Go string `json:"go"` // Go function name
|
|
||||||
}
|
|
||||||
|
|
||||||
// common_symbols.go
|
|
||||||
func getCommonSymbols(dylibSymbols []common.CPPSymbol, astInfoList []common.ASTInformation) []common.SymbolInfo {
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Generate `llcppg.symb.json` file and store the JSON file path into `llcppg.cfg`
|
|
||||||
|
|
||||||
```go
|
|
||||||
func generateJSON([]CommonSymbolInfo)
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Example `llcppg.symb.json` file
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"FunctionName": "A::B::C",
|
|
||||||
"Symbol": "_ZN9INIReaderC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
|
|
||||||
"Location": "a.h",
|
|
||||||
"UserFunctionName": "CFromA"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Function Declaration Generation Module
|
|
||||||
|
|
||||||
### Input
|
|
||||||
|
|
||||||
No input required, directly reads the `llcppg.cfg` file
|
|
||||||
|
|
||||||
### Implementation Steps
|
|
||||||
|
|
||||||
1. Execute the executable
|
|
||||||
|
|
||||||
```bash
|
|
||||||
llcppsigfetch config-file
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Parse header files
|
|
||||||
|
|
||||||
```go
|
|
||||||
// common.go
|
|
||||||
type ASTInformation struct {
|
|
||||||
Namespace string `json:"namespace"`
|
|
||||||
Class string `json:"class"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
BaseClasses []string `json:"baseClasses"`
|
|
||||||
ReturnType string `json:"returnType"`
|
|
||||||
Location string `json:"location"`
|
|
||||||
Parameters []Parameter `json:"parameters"`
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Parameter struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// parser_ast.go
|
|
||||||
func ParseHeaderFile(filePath string) ([]common.ASTInformation, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Generate the final JSON mapping file `llcppg.information.json`
|
|
||||||
|
|
||||||
```go
|
|
||||||
func GenerateJSONFile(info []common.ASTInformation)
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"functionName": "A::B::C",
|
|
||||||
"symbol": "_ZN9INIReaderC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
|
|
||||||
"location": "a.h",
|
|
||||||
"returnType": "int",
|
|
||||||
"userFunctionName": "CFromA",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"arg1": "int"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"arg2": "*char"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Code Generation Module
|
|
||||||
|
|
||||||
### Input
|
|
||||||
|
|
||||||
No input required, directly reads `llcppg.information.json` file
|
|
||||||
|
|
||||||
### Implementation Steps
|
|
||||||
|
|
||||||
1. Execute the executable
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gogensig ast-file
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Parse JSON file
|
|
||||||
|
|
||||||
```go
|
|
||||||
// common.go
|
|
||||||
type HeaderFileInfo struct {
|
|
||||||
FunctionName string `json:"functionName"`
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
Location string `json:"location"`
|
|
||||||
UserFunctionName string `json:"userFunctionName"`
|
|
||||||
Parameters map[string]string `json:"parameters"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse_json.go
|
|
||||||
func ParseJSON(jsonFilePath string) ([]common.HeaderFileInfo, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Generate code using the parsed structure with gogen
|
|
||||||
|
|
||||||
```go
|
|
||||||
// generator.go
|
|
||||||
func GenerateCode(info []common.HeaderFileInfo) {
|
|
||||||
pkg := gogen.NewPackage("", PackageName, nil)
|
|
||||||
cm := comment(fmt.Sprintf("llgo:link %s %s", funcName1, symbol1))
|
|
||||||
pkg.NewFunc(recv, funcName, params, results, variadic).SetComments(pkg, cm).BodyStart(pkg).End()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Output
|
|
||||||
|
|
||||||
1. Directory structure
|
|
||||||
|
|
||||||
```bash
|
|
||||||
package_name/
|
|
||||||
├── _demo
|
|
||||||
├── demo1.go
|
|
||||||
└── llgo_link.go
|
|
||||||
└── a.go
|
|
||||||
└── b.go
|
|
||||||
└── c.go
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that `demo1.go` file needs to be written by the user
|
|
||||||
|
|
||||||
2. `llgo_link.go` is responsible for linking configuration
|
|
||||||
|
|
||||||
```go
|
|
||||||
package inih
|
|
||||||
const (
|
|
||||||
LLGoFiles = "$(pkg-config --cflags INIReader): _wrap/reader.cpp"
|
|
||||||
LLGoPackage = "link: $(pkg-config --libs inih INIReader); -linih -lINIReader"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Example content for `a.go`
|
|
||||||
|
|
||||||
```go
|
|
||||||
package inih
|
|
||||||
import (
|
|
||||||
_ "unsafe"
|
|
||||||
"github.com/goplus/llgo/c"
|
|
||||||
)
|
|
||||||
//go:linkname Parse C.ini_parse
|
|
||||||
func Parse(filename *c.Char, handler func(user c.Pointer, section *c.Char, name *c.Char, value *c.Char) c.Int, user c.Pointer) c.Int
|
|
||||||
|
|
||||||
//go:linkname ParseFile C.ini_parse_file
|
|
||||||
func ParseFile(file c.FilePtr, handler func(user c.Pointer, section *c.Char, name *c.Char, value *c.Char) c.Int, user c.Pointer) c.Int
|
|
||||||
|
|
||||||
//go:linkname ParseString C.ini_parse_string
|
|
||||||
func ParseString(str *c.Char, handler func(user c.Pointer, section *c.Char, name *c.Char, value *c.Char) c.Int, user c.Pointer) c.Int
|
|
||||||
```
|
|
||||||
@@ -16,10 +16,6 @@
|
|||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/goplus/llgo/xtool/nm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config represents a configuration for the llcppg tool.
|
// Config represents a configuration for the llcppg tool.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -29,27 +25,6 @@ type Config struct {
|
|||||||
TrimPrefixes []string `json:"trimPrefixes"`
|
TrimPrefixes []string `json:"trimPrefixes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CPPSymbol struct {
|
|
||||||
DemangleName string
|
|
||||||
*nm.Symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
type ASTInformation struct {
|
|
||||||
Namespace string `json:"namespace"`
|
|
||||||
Class string `json:"class"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
BaseClasses []string `json:"baseClasses"`
|
|
||||||
ReturnType string `json:"returnType"`
|
|
||||||
Location string `json:"location"`
|
|
||||||
Parameters []Parameter `json:"parameters"`
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Parameter struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SymbolInfo struct {
|
type SymbolInfo struct {
|
||||||
Mangle string `json:"mangle"` // C++ Symbol
|
Mangle string `json:"mangle"` // C++ Symbol
|
||||||
CPP string `json:"c++"` // C++ function name
|
CPP string `json:"c++"` // C++ function name
|
||||||
|
|||||||
@@ -543,10 +543,12 @@ _llgo_0:
|
|||||||
|
|
||||||
define void @"main.init#7"() {
|
define void @"main.init#7"() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load ptr, ptr @"map[_llgo_int]_llgo_string", align 8
|
%0 = load ptr, ptr @_llgo_int, align 8
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeMap"(ptr %0, i64 0)
|
%1 = load ptr, ptr @_llgo_string, align 8
|
||||||
%2 = icmp ne ptr %1, null
|
%2 = load ptr, ptr @"map[_llgo_int]_llgo_string", align 8
|
||||||
call void @main.assert(i1 %2)
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeMap"(ptr %2, i64 0)
|
||||||
|
%4 = icmp ne ptr %3, null
|
||||||
|
call void @main.assert(i1 %4)
|
||||||
call void @main.assert(i1 true)
|
call void @main.assert(i1 true)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ func main() {
|
|||||||
make4()
|
make4()
|
||||||
make5()
|
make5()
|
||||||
make6()
|
make6()
|
||||||
|
make7()
|
||||||
}
|
}
|
||||||
|
|
||||||
func make1() {
|
func make1() {
|
||||||
@@ -113,3 +114,15 @@ func make6() {
|
|||||||
println(k, v)
|
println(k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func make7() {
|
||||||
|
type N int
|
||||||
|
m := map[N]string{
|
||||||
|
1: "hello",
|
||||||
|
2: "world",
|
||||||
|
}
|
||||||
|
for k, v := range m {
|
||||||
|
println(k, v)
|
||||||
|
}
|
||||||
|
println(m[1])
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ source_filename = "main"
|
|||||||
@"main.init$guard" = global i1 false, align 1
|
@"main.init$guard" = global i1 false, align 1
|
||||||
@__llgo_argc = global i32 0, align 4
|
@__llgo_argc = global i32 0, align 4
|
||||||
@__llgo_argv = global ptr null, align 8
|
@__llgo_argv = global ptr null, align 8
|
||||||
|
@_llgo_int = linkonce global ptr null, align 8
|
||||||
@"map[_llgo_int]_llgo_int" = linkonce global ptr null, align 8
|
@"map[_llgo_int]_llgo_int" = linkonce global ptr null, align 8
|
||||||
@0 = private unnamed_addr constant [7 x i8] c"topbits", align 1
|
@0 = private unnamed_addr constant [7 x i8] c"topbits", align 1
|
||||||
@1 = private unnamed_addr constant [4 x i8] c"keys", align 1
|
@1 = private unnamed_addr constant [4 x i8] c"keys", align 1
|
||||||
@@ -36,24 +37,32 @@ _llgo_0:
|
|||||||
store ptr %1, ptr @__llgo_argv, align 8
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%2 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
%2 = load ptr, ptr @_llgo_int, align 8
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeMap"(ptr %2, i64 2)
|
%3 = load ptr, ptr @_llgo_int, align 8
|
||||||
%4 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
%4 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
||||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeMap"(ptr %4, i64 2)
|
||||||
store i64 23, ptr %5, align 4
|
%6 = load ptr, ptr @_llgo_int, align 8
|
||||||
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.MapAssign"(ptr %4, ptr %3, ptr %5)
|
%7 = load ptr, ptr @_llgo_int, align 8
|
||||||
store i64 100, ptr %6, align 4
|
%8 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
||||||
%7 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
store i64 23, ptr %9, align 4
|
||||||
store i64 7, ptr %8, align 4
|
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.MapAssign"(ptr %8, ptr %5, ptr %9)
|
||||||
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.MapAssign"(ptr %7, ptr %3, ptr %8)
|
store i64 100, ptr %10, align 4
|
||||||
store i64 29, ptr %9, align 4
|
%11 = load ptr, ptr @_llgo_int, align 8
|
||||||
%10 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
%12 = load ptr, ptr @_llgo_int, align 8
|
||||||
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
%13 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
||||||
store i64 23, ptr %11, align 4
|
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.MapAccess1"(ptr %10, ptr %3, ptr %11)
|
store i64 7, ptr %14, align 4
|
||||||
%13 = load i64, ptr %12, align 4
|
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.MapAssign"(ptr %13, ptr %5, ptr %14)
|
||||||
%14 = call i32 (ptr, ...) @printf(ptr @5, i64 %13)
|
store i64 29, ptr %15, align 4
|
||||||
|
%16 = load ptr, ptr @_llgo_int, align 8
|
||||||
|
%17 = load ptr, ptr @_llgo_int, align 8
|
||||||
|
%18 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
||||||
|
%19 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
store i64 23, ptr %19, align 4
|
||||||
|
%20 = call ptr @"github.com/goplus/llgo/internal/runtime.MapAccess1"(ptr %18, ptr %5, ptr %19)
|
||||||
|
%21 = load i64, ptr %20, align 4
|
||||||
|
%22 = call i32 (ptr, ...) @printf(ptr @5, i64 %21)
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,109 +70,119 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
|||||||
|
|
||||||
define void @"main.init$after"() {
|
define void @"main.init$after"() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
%0 = load ptr, ptr @_llgo_int, align 8
|
||||||
%1 = icmp eq ptr %0, null
|
%1 = icmp eq ptr %0, null
|
||||||
br i1 %1, label %_llgo_1, label %_llgo_2
|
br i1 %1, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
store ptr %2, ptr @_llgo_int, align 8
|
||||||
%4 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 0
|
|
||||||
store ptr @0, ptr %5, align 8
|
|
||||||
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1
|
|
||||||
store i64 7, ptr %6, align 4
|
|
||||||
%7 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %4, align 8
|
|
||||||
%8 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %8, i32 0, i32 0
|
|
||||||
store ptr null, ptr %9, align 8
|
|
||||||
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %8, i32 0, i32 1
|
|
||||||
store i64 0, ptr %10, align 4
|
|
||||||
%11 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %8, align 8
|
|
||||||
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 40)
|
|
||||||
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.ArrayOf"(i64 8, ptr %12)
|
|
||||||
%14 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %7, ptr %13, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %11, i1 false)
|
|
||||||
%15 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%16 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %15, i32 0, i32 0
|
|
||||||
store ptr @1, ptr %16, align 8
|
|
||||||
%17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %15, i32 0, i32 1
|
|
||||||
store i64 4, ptr %17, align 4
|
|
||||||
%18 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %15, align 8
|
|
||||||
%19 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %19, i32 0, i32 0
|
|
||||||
store ptr null, ptr %20, align 8
|
|
||||||
%21 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %19, i32 0, i32 1
|
|
||||||
store i64 0, ptr %21, align 4
|
|
||||||
%22 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %19, align 8
|
|
||||||
%23 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
|
||||||
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.ArrayOf"(i64 8, ptr %23)
|
|
||||||
%25 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %18, ptr %24, i64 8, %"github.com/goplus/llgo/internal/runtime.String" %22, i1 false)
|
|
||||||
%26 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 0
|
|
||||||
store ptr @2, ptr %27, align 8
|
|
||||||
%28 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 1
|
|
||||||
store i64 5, ptr %28, align 4
|
|
||||||
%29 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %26, align 8
|
|
||||||
%30 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 0
|
|
||||||
store ptr null, ptr %31, align 8
|
|
||||||
%32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 1
|
|
||||||
store i64 0, ptr %32, align 4
|
|
||||||
%33 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %30, align 8
|
|
||||||
%34 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
|
||||||
%35 = call ptr @"github.com/goplus/llgo/internal/runtime.ArrayOf"(i64 8, ptr %34)
|
|
||||||
%36 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %29, ptr %35, i64 72, %"github.com/goplus/llgo/internal/runtime.String" %33, i1 false)
|
|
||||||
%37 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%38 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %37, i32 0, i32 0
|
|
||||||
store ptr @3, ptr %38, align 8
|
|
||||||
%39 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %37, i32 0, i32 1
|
|
||||||
store i64 8, ptr %39, align 4
|
|
||||||
%40 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %37, align 8
|
|
||||||
%41 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%42 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %41, i32 0, i32 0
|
|
||||||
store ptr null, ptr %42, align 8
|
|
||||||
%43 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %41, i32 0, i32 1
|
|
||||||
store i64 0, ptr %43, align 4
|
|
||||||
%44 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %41, align 8
|
|
||||||
%45 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 44)
|
|
||||||
%46 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %40, ptr %45, i64 136, %"github.com/goplus/llgo/internal/runtime.String" %44, i1 false)
|
|
||||||
%47 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %47, i32 0, i32 0
|
|
||||||
store ptr @4, ptr %48, align 8
|
|
||||||
%49 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %47, i32 0, i32 1
|
|
||||||
store i64 4, ptr %49, align 4
|
|
||||||
%50 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %47, align 8
|
|
||||||
%51 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 224)
|
|
||||||
%52 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %51, i64 0
|
|
||||||
store %"github.com/goplus/llgo/internal/abi.StructField" %14, ptr %52, align 8
|
|
||||||
%53 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %51, i64 1
|
|
||||||
store %"github.com/goplus/llgo/internal/abi.StructField" %25, ptr %53, align 8
|
|
||||||
%54 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %51, i64 2
|
|
||||||
store %"github.com/goplus/llgo/internal/abi.StructField" %36, ptr %54, align 8
|
|
||||||
%55 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %51, i64 3
|
|
||||||
store %"github.com/goplus/llgo/internal/abi.StructField" %46, ptr %55, align 8
|
|
||||||
%56 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
|
||||||
%57 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, i32 0, i32 0
|
|
||||||
store ptr %51, ptr %57, align 8
|
|
||||||
%58 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, i32 0, i32 1
|
|
||||||
store i64 4, ptr %58, align 4
|
|
||||||
%59 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, i32 0, i32 2
|
|
||||||
store i64 4, ptr %59, align 4
|
|
||||||
%60 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, align 8
|
|
||||||
%61 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %50, i64 144, %"github.com/goplus/llgo/internal/runtime.Slice" %60)
|
|
||||||
%62 = call ptr @"github.com/goplus/llgo/internal/runtime.MapOf"(ptr %2, ptr %3, ptr %61, i64 4)
|
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.SetDirectIface"(ptr %62)
|
|
||||||
store ptr %62, ptr @"map[_llgo_int]_llgo_int", align 8
|
|
||||||
br label %_llgo_2
|
br label %_llgo_2
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
%3 = load ptr, ptr @"map[_llgo_int]_llgo_int", align 8
|
||||||
|
%4 = icmp eq ptr %3, null
|
||||||
|
br i1 %4, label %_llgo_3, label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_2
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
||||||
|
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
||||||
|
%7 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %7, i32 0, i32 0
|
||||||
|
store ptr @0, ptr %8, align 8
|
||||||
|
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %7, i32 0, i32 1
|
||||||
|
store i64 7, ptr %9, align 4
|
||||||
|
%10 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %7, align 8
|
||||||
|
%11 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %11, i32 0, i32 0
|
||||||
|
store ptr null, ptr %12, align 8
|
||||||
|
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %11, i32 0, i32 1
|
||||||
|
store i64 0, ptr %13, align 4
|
||||||
|
%14 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %11, align 8
|
||||||
|
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 40)
|
||||||
|
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.ArrayOf"(i64 8, ptr %15)
|
||||||
|
%17 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %10, ptr %16, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %14, i1 false)
|
||||||
|
%18 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 0
|
||||||
|
store ptr @1, ptr %19, align 8
|
||||||
|
%20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 1
|
||||||
|
store i64 4, ptr %20, align 4
|
||||||
|
%21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %18, align 8
|
||||||
|
%22 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 0
|
||||||
|
store ptr null, ptr %23, align 8
|
||||||
|
%24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 1
|
||||||
|
store i64 0, ptr %24, align 4
|
||||||
|
%25 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %22, align 8
|
||||||
|
%26 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
||||||
|
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.ArrayOf"(i64 8, ptr %26)
|
||||||
|
%28 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %21, ptr %27, i64 8, %"github.com/goplus/llgo/internal/runtime.String" %25, i1 false)
|
||||||
|
%29 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %29, i32 0, i32 0
|
||||||
|
store ptr @2, ptr %30, align 8
|
||||||
|
%31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %29, i32 0, i32 1
|
||||||
|
store i64 5, ptr %31, align 4
|
||||||
|
%32 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %29, align 8
|
||||||
|
%33 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%34 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %33, i32 0, i32 0
|
||||||
|
store ptr null, ptr %34, align 8
|
||||||
|
%35 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %33, i32 0, i32 1
|
||||||
|
store i64 0, ptr %35, align 4
|
||||||
|
%36 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %33, align 8
|
||||||
|
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34)
|
||||||
|
%38 = call ptr @"github.com/goplus/llgo/internal/runtime.ArrayOf"(i64 8, ptr %37)
|
||||||
|
%39 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %32, ptr %38, i64 72, %"github.com/goplus/llgo/internal/runtime.String" %36, i1 false)
|
||||||
|
%40 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%41 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %40, i32 0, i32 0
|
||||||
|
store ptr @3, ptr %41, align 8
|
||||||
|
%42 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %40, i32 0, i32 1
|
||||||
|
store i64 8, ptr %42, align 4
|
||||||
|
%43 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %40, align 8
|
||||||
|
%44 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%45 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %44, i32 0, i32 0
|
||||||
|
store ptr null, ptr %45, align 8
|
||||||
|
%46 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %44, i32 0, i32 1
|
||||||
|
store i64 0, ptr %46, align 4
|
||||||
|
%47 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %44, align 8
|
||||||
|
%48 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 44)
|
||||||
|
%49 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %43, ptr %48, i64 136, %"github.com/goplus/llgo/internal/runtime.String" %47, i1 false)
|
||||||
|
%50 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 0
|
||||||
|
store ptr @4, ptr %51, align 8
|
||||||
|
%52 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 1
|
||||||
|
store i64 4, ptr %52, align 4
|
||||||
|
%53 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %50, align 8
|
||||||
|
%54 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 224)
|
||||||
|
%55 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %54, i64 0
|
||||||
|
store %"github.com/goplus/llgo/internal/abi.StructField" %17, ptr %55, align 8
|
||||||
|
%56 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %54, i64 1
|
||||||
|
store %"github.com/goplus/llgo/internal/abi.StructField" %28, ptr %56, align 8
|
||||||
|
%57 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %54, i64 2
|
||||||
|
store %"github.com/goplus/llgo/internal/abi.StructField" %39, ptr %57, align 8
|
||||||
|
%58 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %54, i64 3
|
||||||
|
store %"github.com/goplus/llgo/internal/abi.StructField" %49, ptr %58, align 8
|
||||||
|
%59 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||||
|
%60 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %59, i32 0, i32 0
|
||||||
|
store ptr %54, ptr %60, align 8
|
||||||
|
%61 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %59, i32 0, i32 1
|
||||||
|
store i64 4, ptr %61, align 4
|
||||||
|
%62 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %59, i32 0, i32 2
|
||||||
|
store i64 4, ptr %62, align 4
|
||||||
|
%63 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %59, align 8
|
||||||
|
%64 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %53, i64 144, %"github.com/goplus/llgo/internal/runtime.Slice" %63)
|
||||||
|
%65 = call ptr @"github.com/goplus/llgo/internal/runtime.MapOf"(ptr %5, ptr %6, ptr %64, i64 4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.SetDirectIface"(ptr %65)
|
||||||
|
store ptr %65, ptr @"map[_llgo_int]_llgo_int", align 8
|
||||||
|
br label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_3, %_llgo_2
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.MapOf"(ptr, ptr, ptr, i64)
|
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.MapOf"(ptr, ptr, ptr, i64)
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String", i64, %"github.com/goplus/llgo/internal/runtime.Slice")
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String", i64, %"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1)
|
declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1)
|
||||||
|
|||||||
@@ -282,3 +282,68 @@ func TestErrVarOf(t *testing.T) {
|
|||||||
g := &ssa.Global{Pkg: ssaPkg}
|
g := &ssa.Global{Pkg: ssaPkg}
|
||||||
ctx.varOf(nil, g)
|
ctx.varOf(nil, g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContextResolveLinkname(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
context *context
|
||||||
|
input string
|
||||||
|
want string
|
||||||
|
panics bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Normal",
|
||||||
|
context: &context{
|
||||||
|
link: map[string]string{
|
||||||
|
"foo": "C.bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
input: "foo",
|
||||||
|
want: "bar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MultipleLinks",
|
||||||
|
context: &context{
|
||||||
|
link: map[string]string{
|
||||||
|
"foo1": "C.bar1",
|
||||||
|
"foo2": "C.bar2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
input: "foo2",
|
||||||
|
want: "bar2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NoLink",
|
||||||
|
context: &context{link: map[string]string{}},
|
||||||
|
input: "foo",
|
||||||
|
want: "foo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "InvalidLink",
|
||||||
|
context: &context{
|
||||||
|
link: map[string]string{
|
||||||
|
"foo": "invalid.bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
input: "foo",
|
||||||
|
panics: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if tt.panics {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Error("want panic")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
got := tt.context.resolveLinkname(tt.input)
|
||||||
|
if !tt.panics {
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("got %q, want %q", got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl/blocks"
|
"github.com/goplus/llgo/cl/blocks"
|
||||||
"github.com/goplus/llgo/internal/typepatch"
|
"github.com/goplus/llgo/internal/typepatch"
|
||||||
@@ -97,8 +98,9 @@ type context struct {
|
|||||||
patches Patches
|
patches Patches
|
||||||
blkInfos []blocks.Info
|
blkInfos []blocks.Info
|
||||||
|
|
||||||
inits []func()
|
inits []func()
|
||||||
phis []func()
|
phis []func()
|
||||||
|
initAfter func()
|
||||||
|
|
||||||
state pkgState
|
state pkgState
|
||||||
inCFunc bool
|
inCFunc bool
|
||||||
@@ -291,9 +293,9 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
instrs = instrs[:last]
|
instrs = instrs[:last]
|
||||||
} else if p.state != pkgHasPatch {
|
} else if p.state != pkgHasPatch {
|
||||||
// TODO(xsw): confirm pyMod don't need to call AfterInit
|
// TODO(xsw): confirm pyMod don't need to call AfterInit
|
||||||
p.inits = append(p.inits, func() {
|
p.initAfter = func() {
|
||||||
pkg.AfterInit(b, ret)
|
pkg.AfterInit(b, ret)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
} else if doMainInit {
|
} else if doMainInit {
|
||||||
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
||||||
@@ -812,6 +814,7 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
|
|||||||
ctx.initPyModule()
|
ctx.initPyModule()
|
||||||
ctx.initFiles(pkgPath, files)
|
ctx.initFiles(pkgPath, files)
|
||||||
ret.SetPatch(ctx.patchType)
|
ret.SetPatch(ctx.patchType)
|
||||||
|
ret.SetResolveLinkname(ctx.resolveLinkname)
|
||||||
|
|
||||||
if hasPatch {
|
if hasPatch {
|
||||||
skips := ctx.skips
|
skips := ctx.skips
|
||||||
@@ -835,6 +838,10 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
|
|||||||
ini()
|
ini()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if fn := ctx.initAfter; fn != nil {
|
||||||
|
ctx.initAfter = nil
|
||||||
|
fn()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -904,4 +911,15 @@ func (p *context) patchType(typ types.Type) types.Type {
|
|||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *context) resolveLinkname(name string) string {
|
||||||
|
if link, ok := p.link[name]; ok {
|
||||||
|
prefix, ltarget, _ := strings.Cut(link, ".")
|
||||||
|
if prefix != "C" {
|
||||||
|
panic("resolveLinkname: invalid link: " + link)
|
||||||
|
}
|
||||||
|
return ltarget
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ func (p *context) stringData(b llssa.Builder, args []ssa.Value) (ret llssa.Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// func funcAddr(fn any) unsafe.Pointer
|
// func funcAddr(fn any) unsafe.Pointer
|
||||||
func (p *context) funcAddr(b llssa.Builder, args []ssa.Value) llssa.Expr {
|
func (p *context) funcAddr(_ llssa.Builder, args []ssa.Value) llssa.Expr {
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
if fn, ok := args[0].(*ssa.MakeInterface); ok {
|
if fn, ok := args[0].(*ssa.MakeInterface); ok {
|
||||||
if fnDecl, ok := fn.X.(*ssa.Function); ok {
|
if fnDecl, ok := fn.X.(*ssa.Function); ok {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ type StringView = string
|
|||||||
|
|
||||||
// String represents a C++ std::string object.
|
// String represents a C++ std::string object.
|
||||||
type String struct {
|
type String struct {
|
||||||
Unused [3]uintptr
|
Unused [3 * unsafe.Sizeof(0)]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// llgo:link (*String).InitEmpty C.stdStringInitEmpty
|
// llgo:link (*String).InitEmpty C.stdStringInitEmpty
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
How to support a C/C++ Library
|
How to support a C/C++ Library
|
||||||
=====
|
=====
|
||||||
|
## Symbol Visibility
|
||||||
|
When llgo needs to link C or C++ libraries, symbol visibility is a crucial concept. It determines how C/C++ functions and methods are linked and utilized within llgo. Symbol visibility significantly impacts the handling of symbols in llgo bindings: visible symbols can typically be directly linked, while invisible symbols require wrapper functions.
|
||||||
|
|
||||||
|
The accessibility of symbols, particularly destructors, in dynamic libraries depends on their definition method. For instance, destructors that are explicitly declared in header files and implemented as non-inline functions in .cpp files typically appear in the dynamic library's symbol table, making them visible and directly linkable.
|
||||||
|
|
||||||
|
**Visible Symbols:** These are symbols that can be found in the dynamic library. They typically represent public API functions and methods.
|
||||||
|
|
||||||
|
* Example: A class constructor explicitly declared in the header and implemented in a .cpp file.
|
||||||
|
|
||||||
|
* Example: A non-inline destructor declared in the header and implemented in a .cpp file.
|
||||||
|
|
||||||
|
**Invisible Symbols:** These are symbols that cannot be found in the dynamic library. This may include inline functions, templates, or certain constructors and destructors.
|
||||||
|
|
||||||
|
* Example: A default constructor not explicitly declared.
|
||||||
|
|
||||||
|
* Example: An inline destructor or a compiler-generated default destructor.
|
||||||
|
|
||||||
## Support a C Library
|
## Support a C Library
|
||||||
|
|
||||||
@@ -27,7 +43,7 @@ int ini_parse(const char* filename, ini_handler handler, void* user);
|
|||||||
|
|
||||||
3. Create the corresponding Go file
|
3. Create the corresponding Go file
|
||||||
|
|
||||||
```c
|
```bash
|
||||||
inih/
|
inih/
|
||||||
├── _demo
|
├── _demo
|
||||||
├── inih_demo
|
├── inih_demo
|
||||||
@@ -296,46 +312,6 @@ func ParseError() c.Int
|
|||||||
Unused [32]byte
|
Unused [32]byte
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- Constructor
|
|
||||||
|
|
||||||
- Constructor is explicitly declared in the class (can find the corresponding symbol in the dynamic library):
|
|
||||||
|
|
||||||
Bind to the `InitFromBuffer` method of the struct and call it in the `NewReaderFile` function to initialize the class and return the class for Go to use.
|
|
||||||
|
|
||||||
```go
|
|
||||||
// NewReaderFile creates a new INIReader instance.
|
|
||||||
func NewReaderFile(fileName *std.String) (ret Reader) {
|
|
||||||
ret.InitFromFile(fileName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
class INIReader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit INIReader(const char *buffer, size_t buffer_size);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// llgo:link (*Reader).InitFromBuffer C._ZN9INIReaderC1EPKcm
|
|
||||||
func (r *Reader) InitFromBuffer(buffer *c.Char, bufferSize uintptr) {}
|
|
||||||
```
|
|
||||||
- Constructor is not explicitly declared in the class (cannot find the corresponding symbol in the dynamic library)
|
|
||||||
|
|
||||||
If the destructor is not explicitly declared in the source code, the compiler will automatically generate a default destructor. Use `extern "C"` to wrap it in cppWrap.cpp:
|
|
||||||
|
|
||||||
```c
|
|
||||||
extern "C" void INIReaderInit(INIReader* r)
|
|
||||||
{
|
|
||||||
r->INIReader();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Link in Go:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// llgo:link (*Reader).INIReaderInit C.INIReaderInit
|
|
||||||
func (r *Reader) INIReaderInit() {}
|
|
||||||
```
|
|
||||||
- Class Methods
|
- Class Methods
|
||||||
|
|
||||||
For general methods of the class, directly use `llgo:link` to link:
|
For general methods of the class, directly use `llgo:link` to link:
|
||||||
@@ -346,22 +322,65 @@ func ParseError() c.Int
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
- Constructor
|
||||||
|
|
||||||
|
- Explicitly Constructor:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class INIReader {
|
||||||
|
public:
|
||||||
|
// Construct INIReader and parse given filename.
|
||||||
|
INI_API explicit INIReader(const std::string &filename);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Bind to the `InitFromFile` method of the struct and call it in the `NewReaderFile` function to initialize the class and return the class for Go to use.
|
||||||
|
|
||||||
|
The following long string starting with `_ZN9INI` is the corresponding function prototype in the symbol table for `INIReader(const std::string &filename)`
|
||||||
|
```go
|
||||||
|
// llgo:link (*Reader).InitFromFile C._ZN9INIReaderC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
|
||||||
|
func (r *Reader) InitFromFile(fileName *std.String) {}
|
||||||
|
|
||||||
|
// NewReaderFile creates a new INIReader instance.
|
||||||
|
func NewReaderFile(fileName *std.String) (ret Reader) {
|
||||||
|
ret.InitFromFile(fileName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Implicitly Constructor
|
||||||
|
|
||||||
|
In typical implementations of the inih library, directly invoking implicit constructors to instantiate reader objects is not recommended. For detailed examples of how bindings effectively handle non-exported symbols, please refer to the [Templates and Inlines](#templates-and-inlines) section.
|
||||||
|
|
||||||
Template or inline methods of the class will be introduced in the next section.
|
|
||||||
- Destructor
|
- Destructor
|
||||||
|
|
||||||
Similar to the constructor process, after creating the class, use `defer` to call it explicitly:
|
Explicitly declared and non-inline destructors can be directly linked, consistent with the linking method of general class methods (see "Class Methods" section). For destructors that do not appear in the dynamic library's symbol table, a wrapper layer implementation is required. This wrapper in the C++ wrapper file (e.g., cppWrap.cpp) looks like:
|
||||||
|
|
||||||
```go
|
```cpp
|
||||||
|
extern "C" {
|
||||||
|
void INIReaderDispose(INIReader* r) {
|
||||||
|
r->~INIReader();
|
||||||
|
}
|
||||||
|
} // extern "C"
|
||||||
|
```
|
||||||
|
This wrapper function explicitly calls the object's destructor. By using extern "C", we ensure that this function can be called by C code, allowing Go to link to it.
|
||||||
|
In the Go file:
|
||||||
|
```go
|
||||||
|
// llgo:link (*Reader).Dispose C.INIReaderDispose
|
||||||
|
func (r *Reader) Dispose() {}
|
||||||
|
```
|
||||||
|
Here we link the Go Dispose method to the C++ wrapped INIReaderDispose function.
|
||||||
|
In actual usage:
|
||||||
|
We use defer to ensure that the Dispose method is called when the reader object goes out of scope, thus properly releasing resources.
|
||||||
|
```go
|
||||||
reader := inih.NewReader(c.Str(buf), uintptr(len(buf)))
|
reader := inih.NewReader(c.Str(buf), uintptr(len(buf)))
|
||||||
defer reader.Dispose()
|
defer reader.Dispose()
|
||||||
```
|
```
|
||||||
|
This situation is analogous to the handling of inline functions and templates described in the following section.
|
||||||
|
|
||||||
#### Templates and Inlines
|
#### Templates and Inlines
|
||||||
|
|
||||||
Templates or inlines do not generate symbols in dynamic libraries (dylib) (default constructors and destructors). To ensure that you can use C style symbols to link template or inline functions, create a C++ file and wrap it with `extern "C"`, then bind the functions directly in Go.
|
Templates or inlines do not generate symbols in dynamic libraries (dylib) (default constructors and destructors). To ensure that you can use C style symbols to link template or inline functions, create a C++ file and wrap it with `extern "C"`, then bind the functions directly in Go.
|
||||||
|
|
||||||
```c
|
```cpp
|
||||||
// Using std::string as an example, not needed for migrating inih
|
// Using std::string as an example, not needed for migrating inih
|
||||||
extern "C" void stdStringInitFromCStrLen(std::string* s, const char* cstr, size_t len) {
|
extern "C" void stdStringInitFromCStrLen(std::string* s, const char* cstr, size_t len) {
|
||||||
new(s) std::string(cstr, len);
|
new(s) std::string(cstr, len);
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -7,7 +7,7 @@ require (
|
|||||||
github.com/goplus/llvm v0.8.0
|
github.com/goplus/llvm v0.8.0
|
||||||
github.com/goplus/mod v0.13.12
|
github.com/goplus/mod v0.13.12
|
||||||
github.com/qiniu/x v1.13.10
|
github.com/qiniu/x v1.13.10
|
||||||
golang.org/x/tools v0.22.0
|
golang.org/x/tools v0.19.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -10,5 +10,5 @@ golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
|||||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||||
|
|||||||
612
internal/build/_overlay/go/parser/resolver.go
Normal file
612
internal/build/_overlay/go/parser/resolver.go
Normal file
@@ -0,0 +1,612 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const debugResolve = false
|
||||||
|
|
||||||
|
// resolveFile walks the given file to resolve identifiers within the file
|
||||||
|
// scope, updating ast.Ident.Obj fields with declaration information.
|
||||||
|
//
|
||||||
|
// If declErr is non-nil, it is used to report declaration errors during
|
||||||
|
// resolution. tok is used to format position in error messages.
|
||||||
|
func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string)) {
|
||||||
|
pkgScope := ast.NewScope(nil)
|
||||||
|
r := &resolver{
|
||||||
|
handle: handle,
|
||||||
|
declErr: declErr,
|
||||||
|
topScope: pkgScope,
|
||||||
|
pkgScope: pkgScope,
|
||||||
|
depth: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, decl := range file.Decls {
|
||||||
|
ast.Walk(r, decl)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.closeScope()
|
||||||
|
assert(r.topScope == nil, "unbalanced scopes")
|
||||||
|
assert(r.labelScope == nil, "unbalanced label scopes")
|
||||||
|
|
||||||
|
// resolve global identifiers within the same file
|
||||||
|
i := 0
|
||||||
|
for _, ident := range r.unresolved {
|
||||||
|
// i <= index for current ident
|
||||||
|
assert(ident.Obj == unresolved, "object already resolved")
|
||||||
|
ident.Obj = r.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel
|
||||||
|
if ident.Obj == nil {
|
||||||
|
r.unresolved[i] = ident
|
||||||
|
i++
|
||||||
|
} else if debugResolve {
|
||||||
|
pos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos()
|
||||||
|
r.trace("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.Scope = r.pkgScope
|
||||||
|
file.Unresolved = r.unresolved[0:i]
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxScopeDepth int = 1e3
|
||||||
|
|
||||||
|
type resolver struct {
|
||||||
|
handle *token.File
|
||||||
|
declErr func(token.Pos, string)
|
||||||
|
|
||||||
|
// Ordinary identifier scopes
|
||||||
|
pkgScope *ast.Scope // pkgScope.Outer == nil
|
||||||
|
topScope *ast.Scope // top-most scope; may be pkgScope
|
||||||
|
unresolved []*ast.Ident // unresolved identifiers
|
||||||
|
depth int // scope depth
|
||||||
|
|
||||||
|
// Label scopes
|
||||||
|
// (maintained by open/close LabelScope)
|
||||||
|
labelScope *ast.Scope // label scope for current function
|
||||||
|
targetStack [][]*ast.Ident // stack of unresolved labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) trace(format string, args ...any) {
|
||||||
|
fmt.Println(strings.Repeat(". ", r.depth) + r.sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) sprintf(format string, args ...any) string {
|
||||||
|
for i, arg := range args {
|
||||||
|
switch arg := arg.(type) {
|
||||||
|
case token.Pos:
|
||||||
|
args[i] = r.handle.Position(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) openScope(pos token.Pos) {
|
||||||
|
r.depth++
|
||||||
|
if r.depth > maxScopeDepth {
|
||||||
|
panic(bailout{pos: pos, msg: "exceeded max scope depth during object resolution"})
|
||||||
|
}
|
||||||
|
if debugResolve {
|
||||||
|
r.trace("opening scope @%v", pos)
|
||||||
|
}
|
||||||
|
r.topScope = ast.NewScope(r.topScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) closeScope() {
|
||||||
|
r.depth--
|
||||||
|
if debugResolve {
|
||||||
|
r.trace("closing scope")
|
||||||
|
}
|
||||||
|
r.topScope = r.topScope.Outer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) openLabelScope() {
|
||||||
|
r.labelScope = ast.NewScope(r.labelScope)
|
||||||
|
r.targetStack = append(r.targetStack, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) closeLabelScope() {
|
||||||
|
// resolve labels
|
||||||
|
n := len(r.targetStack) - 1
|
||||||
|
scope := r.labelScope
|
||||||
|
for _, ident := range r.targetStack[n] {
|
||||||
|
ident.Obj = scope.Lookup(ident.Name)
|
||||||
|
if ident.Obj == nil && r.declErr != nil {
|
||||||
|
r.declErr(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pop label scope
|
||||||
|
r.targetStack = r.targetStack[0:n]
|
||||||
|
r.labelScope = r.labelScope.Outer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) declare(decl, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
|
||||||
|
for _, ident := range idents {
|
||||||
|
if ident.Obj != nil {
|
||||||
|
panic(fmt.Sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
|
||||||
|
}
|
||||||
|
obj := ast.NewObj(kind, ident.Name)
|
||||||
|
// remember the corresponding declaration for redeclaration
|
||||||
|
// errors and global variable resolution/typechecking phase
|
||||||
|
obj.Decl = decl
|
||||||
|
obj.Data = data
|
||||||
|
// Identifiers (for receiver type parameters) are written to the scope, but
|
||||||
|
// never set as the resolved object. See issue #50956.
|
||||||
|
if _, ok := decl.(*ast.Ident); !ok {
|
||||||
|
ident.Obj = obj
|
||||||
|
}
|
||||||
|
if ident.Name != "_" {
|
||||||
|
if debugResolve {
|
||||||
|
r.trace("declaring %s@%v", ident.Name, ident.Pos())
|
||||||
|
}
|
||||||
|
if alt := scope.Insert(obj); alt != nil && r.declErr != nil {
|
||||||
|
prevDecl := ""
|
||||||
|
if pos := alt.Pos(); pos.IsValid() {
|
||||||
|
prevDecl = r.sprintf("\n\tprevious declaration at %v", pos)
|
||||||
|
}
|
||||||
|
r.declErr(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) shortVarDecl(decl *ast.AssignStmt) {
|
||||||
|
// Go spec: A short variable declaration may redeclare variables
|
||||||
|
// provided they were originally declared in the same block with
|
||||||
|
// the same type, and at least one of the non-blank variables is new.
|
||||||
|
n := 0 // number of new variables
|
||||||
|
for _, x := range decl.Lhs {
|
||||||
|
if ident, isIdent := x.(*ast.Ident); isIdent {
|
||||||
|
assert(ident.Obj == nil, "identifier already declared or resolved")
|
||||||
|
obj := ast.NewObj(ast.Var, ident.Name)
|
||||||
|
// remember corresponding assignment for other tools
|
||||||
|
obj.Decl = decl
|
||||||
|
ident.Obj = obj
|
||||||
|
if ident.Name != "_" {
|
||||||
|
if debugResolve {
|
||||||
|
r.trace("declaring %s@%v", ident.Name, ident.Pos())
|
||||||
|
}
|
||||||
|
if alt := r.topScope.Insert(obj); alt != nil {
|
||||||
|
ident.Obj = alt // redeclaration
|
||||||
|
} else {
|
||||||
|
n++ // new declaration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n == 0 && r.declErr != nil {
|
||||||
|
r.declErr(decl.Lhs[0].Pos(), "no new variables on left side of :=")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The unresolved object is a sentinel to mark identifiers that have been added
|
||||||
|
// to the list of unresolved identifiers. The sentinel is only used for verifying
|
||||||
|
// internal consistency.
|
||||||
|
var unresolved = new(ast.Object)
|
||||||
|
|
||||||
|
// If x is an identifier, resolve attempts to resolve x by looking up
|
||||||
|
// the object it denotes. If no object is found and collectUnresolved is
|
||||||
|
// set, x is marked as unresolved and collected in the list of unresolved
|
||||||
|
// identifiers.
|
||||||
|
func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) {
|
||||||
|
if ident.Obj != nil {
|
||||||
|
panic(r.sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
|
||||||
|
}
|
||||||
|
// '_' should never refer to existing declarations, because it has special
|
||||||
|
// handling in the spec.
|
||||||
|
if ident.Name == "_" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for s := r.topScope; s != nil; s = s.Outer {
|
||||||
|
if obj := s.Lookup(ident.Name); obj != nil {
|
||||||
|
if debugResolve {
|
||||||
|
r.trace("resolved %v:%s to %v", ident.Pos(), ident.Name, obj)
|
||||||
|
}
|
||||||
|
assert(obj.Name != "", "obj with no name")
|
||||||
|
// Identifiers (for receiver type parameters) are written to the scope,
|
||||||
|
// but never set as the resolved object. See issue #50956.
|
||||||
|
if _, ok := obj.Decl.(*ast.Ident); !ok {
|
||||||
|
ident.Obj = obj
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// all local scopes are known, so any unresolved identifier
|
||||||
|
// must be found either in the file scope, package scope
|
||||||
|
// (perhaps in another file), or universe scope --- collect
|
||||||
|
// them so that they can be resolved later
|
||||||
|
if collectUnresolved {
|
||||||
|
ident.Obj = unresolved
|
||||||
|
r.unresolved = append(r.unresolved, ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) walkExprs(list []ast.Expr) {
|
||||||
|
for _, node := range list {
|
||||||
|
ast.Walk(r, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) walkLHS(list []ast.Expr) {
|
||||||
|
for _, expr := range list {
|
||||||
|
expr := unparen(expr)
|
||||||
|
if _, ok := expr.(*ast.Ident); !ok && expr != nil {
|
||||||
|
ast.Walk(r, expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) walkStmts(list []ast.Stmt) {
|
||||||
|
for _, stmt := range list {
|
||||||
|
ast.Walk(r, stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Visit(node ast.Node) ast.Visitor {
|
||||||
|
if debugResolve && node != nil {
|
||||||
|
r.trace("node %T@%v", node, node.Pos())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch n := node.(type) {
|
||||||
|
|
||||||
|
// Expressions.
|
||||||
|
case *ast.Ident:
|
||||||
|
r.resolve(n, true)
|
||||||
|
|
||||||
|
case *ast.FuncLit:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
r.walkFuncType(n.Type)
|
||||||
|
r.walkBody(n.Body)
|
||||||
|
|
||||||
|
case *ast.SelectorExpr:
|
||||||
|
ast.Walk(r, n.X)
|
||||||
|
// Note: don't try to resolve n.Sel, as we don't support qualified
|
||||||
|
// resolution.
|
||||||
|
|
||||||
|
case *ast.StructType:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
r.walkFieldList(n.Fields, ast.Var)
|
||||||
|
|
||||||
|
case *ast.FuncType:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
r.walkFuncType(n)
|
||||||
|
|
||||||
|
case *ast.CompositeLit:
|
||||||
|
if n.Type != nil {
|
||||||
|
ast.Walk(r, n.Type)
|
||||||
|
}
|
||||||
|
for _, e := range n.Elts {
|
||||||
|
if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
|
||||||
|
// See issue #45160: try to resolve composite lit keys, but don't
|
||||||
|
// collect them as unresolved if resolution failed. This replicates
|
||||||
|
// existing behavior when resolving during parsing.
|
||||||
|
if ident, _ := kv.Key.(*ast.Ident); ident != nil {
|
||||||
|
r.resolve(ident, false)
|
||||||
|
} else {
|
||||||
|
ast.Walk(r, kv.Key)
|
||||||
|
}
|
||||||
|
ast.Walk(r, kv.Value)
|
||||||
|
} else {
|
||||||
|
ast.Walk(r, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.InterfaceType:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
r.walkFieldList(n.Methods, ast.Fun)
|
||||||
|
|
||||||
|
// Statements
|
||||||
|
case *ast.LabeledStmt:
|
||||||
|
r.declare(n, nil, r.labelScope, ast.Lbl, n.Label)
|
||||||
|
ast.Walk(r, n.Stmt)
|
||||||
|
|
||||||
|
case *ast.AssignStmt:
|
||||||
|
r.walkExprs(n.Rhs)
|
||||||
|
if n.Tok == token.DEFINE {
|
||||||
|
r.shortVarDecl(n)
|
||||||
|
} else {
|
||||||
|
r.walkExprs(n.Lhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.BranchStmt:
|
||||||
|
// add to list of unresolved targets
|
||||||
|
if n.Tok != token.FALLTHROUGH && n.Label != nil {
|
||||||
|
depth := len(r.targetStack) - 1
|
||||||
|
r.targetStack[depth] = append(r.targetStack[depth], n.Label)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.BlockStmt:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
r.walkStmts(n.List)
|
||||||
|
|
||||||
|
case *ast.IfStmt:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
if n.Init != nil {
|
||||||
|
ast.Walk(r, n.Init)
|
||||||
|
}
|
||||||
|
ast.Walk(r, n.Cond)
|
||||||
|
ast.Walk(r, n.Body)
|
||||||
|
if n.Else != nil {
|
||||||
|
ast.Walk(r, n.Else)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.CaseClause:
|
||||||
|
r.walkExprs(n.List)
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
r.walkStmts(n.Body)
|
||||||
|
|
||||||
|
case *ast.SwitchStmt:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
if n.Init != nil {
|
||||||
|
ast.Walk(r, n.Init)
|
||||||
|
}
|
||||||
|
if n.Tag != nil {
|
||||||
|
// The scope below reproduces some unnecessary behavior of the parser,
|
||||||
|
// opening an extra scope in case this is a type switch. It's not needed
|
||||||
|
// for expression switches.
|
||||||
|
// TODO: remove this once we've matched the parser resolution exactly.
|
||||||
|
if n.Init != nil {
|
||||||
|
r.openScope(n.Tag.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
}
|
||||||
|
ast.Walk(r, n.Tag)
|
||||||
|
}
|
||||||
|
if n.Body != nil {
|
||||||
|
r.walkStmts(n.Body.List)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.TypeSwitchStmt:
|
||||||
|
if n.Init != nil {
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
ast.Walk(r, n.Init)
|
||||||
|
}
|
||||||
|
r.openScope(n.Assign.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
ast.Walk(r, n.Assign)
|
||||||
|
// s.Body consists only of case clauses, so does not get its own
|
||||||
|
// scope.
|
||||||
|
if n.Body != nil {
|
||||||
|
r.walkStmts(n.Body.List)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.CommClause:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
if n.Comm != nil {
|
||||||
|
ast.Walk(r, n.Comm)
|
||||||
|
}
|
||||||
|
r.walkStmts(n.Body)
|
||||||
|
|
||||||
|
case *ast.SelectStmt:
|
||||||
|
// as for switch statements, select statement bodies don't get their own
|
||||||
|
// scope.
|
||||||
|
if n.Body != nil {
|
||||||
|
r.walkStmts(n.Body.List)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.ForStmt:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
if n.Init != nil {
|
||||||
|
ast.Walk(r, n.Init)
|
||||||
|
}
|
||||||
|
if n.Cond != nil {
|
||||||
|
ast.Walk(r, n.Cond)
|
||||||
|
}
|
||||||
|
if n.Post != nil {
|
||||||
|
ast.Walk(r, n.Post)
|
||||||
|
}
|
||||||
|
ast.Walk(r, n.Body)
|
||||||
|
|
||||||
|
case *ast.RangeStmt:
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
ast.Walk(r, n.X)
|
||||||
|
var lhs []ast.Expr
|
||||||
|
if n.Key != nil {
|
||||||
|
lhs = append(lhs, n.Key)
|
||||||
|
}
|
||||||
|
if n.Value != nil {
|
||||||
|
lhs = append(lhs, n.Value)
|
||||||
|
}
|
||||||
|
if len(lhs) > 0 {
|
||||||
|
if n.Tok == token.DEFINE {
|
||||||
|
// Note: we can't exactly match the behavior of object resolution
|
||||||
|
// during the parsing pass here, as it uses the position of the RANGE
|
||||||
|
// token for the RHS OpPos. That information is not contained within
|
||||||
|
// the AST.
|
||||||
|
as := &ast.AssignStmt{
|
||||||
|
Lhs: lhs,
|
||||||
|
Tok: token.DEFINE,
|
||||||
|
TokPos: n.TokPos,
|
||||||
|
Rhs: []ast.Expr{&ast.UnaryExpr{Op: token.RANGE, X: n.X}},
|
||||||
|
}
|
||||||
|
// TODO(rFindley): this walkLHS reproduced the parser resolution, but
|
||||||
|
// is it necessary? By comparison, for a normal AssignStmt we don't
|
||||||
|
// walk the LHS in case there is an invalid identifier list.
|
||||||
|
r.walkLHS(lhs)
|
||||||
|
r.shortVarDecl(as)
|
||||||
|
} else {
|
||||||
|
r.walkExprs(lhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.Walk(r, n.Body)
|
||||||
|
|
||||||
|
// Declarations
|
||||||
|
case *ast.GenDecl:
|
||||||
|
switch n.Tok {
|
||||||
|
case token.CONST, token.VAR:
|
||||||
|
for i, spec := range n.Specs {
|
||||||
|
spec := spec.(*ast.ValueSpec)
|
||||||
|
kind := ast.Con
|
||||||
|
if n.Tok == token.VAR {
|
||||||
|
kind = ast.Var
|
||||||
|
}
|
||||||
|
r.walkExprs(spec.Values)
|
||||||
|
if spec.Type != nil {
|
||||||
|
ast.Walk(r, spec.Type)
|
||||||
|
}
|
||||||
|
r.declare(spec, i, r.topScope, kind, spec.Names...)
|
||||||
|
}
|
||||||
|
case token.TYPE:
|
||||||
|
for _, spec := range n.Specs {
|
||||||
|
spec := spec.(*ast.TypeSpec)
|
||||||
|
// Go spec: The scope of a type identifier declared inside a function begins
|
||||||
|
// at the identifier in the TypeSpec and ends at the end of the innermost
|
||||||
|
// containing block.
|
||||||
|
r.declare(spec, nil, r.topScope, ast.Typ, spec.Name)
|
||||||
|
if spec.TypeParams != nil {
|
||||||
|
r.openScope(spec.Pos())
|
||||||
|
r.walkTParams(spec.TypeParams)
|
||||||
|
r.closeScope()
|
||||||
|
}
|
||||||
|
ast.Walk(r, spec.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.FuncDecl:
|
||||||
|
// Open the function scope.
|
||||||
|
r.openScope(n.Pos())
|
||||||
|
defer r.closeScope()
|
||||||
|
|
||||||
|
r.walkRecv(n.Recv)
|
||||||
|
|
||||||
|
// Type parameters are walked normally: they can reference each other, and
|
||||||
|
// can be referenced by normal parameters.
|
||||||
|
if n.Type.TypeParams != nil {
|
||||||
|
r.walkTParams(n.Type.TypeParams)
|
||||||
|
// TODO(rFindley): need to address receiver type parameters.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve and declare parameters in a specific order to get duplicate
|
||||||
|
// declaration errors in the correct location.
|
||||||
|
r.resolveList(n.Type.Params)
|
||||||
|
r.resolveList(n.Type.Results)
|
||||||
|
r.declareList(n.Recv, ast.Var)
|
||||||
|
r.declareList(n.Type.Params, ast.Var)
|
||||||
|
r.declareList(n.Type.Results, ast.Var)
|
||||||
|
|
||||||
|
r.walkBody(n.Body)
|
||||||
|
if n.Recv == nil && n.Name.Name != "init" {
|
||||||
|
r.declare(n, nil, r.pkgScope, ast.Fun, n.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) walkFuncType(typ *ast.FuncType) {
|
||||||
|
// typ.TypeParams must be walked separately for FuncDecls.
|
||||||
|
r.resolveList(typ.Params)
|
||||||
|
r.resolveList(typ.Results)
|
||||||
|
r.declareList(typ.Params, ast.Var)
|
||||||
|
r.declareList(typ.Results, ast.Var)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) resolveList(list *ast.FieldList) {
|
||||||
|
if list == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, f := range list.List {
|
||||||
|
if f.Type != nil {
|
||||||
|
ast.Walk(r, f.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind) {
|
||||||
|
if list == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, f := range list.List {
|
||||||
|
r.declare(f, nil, r.topScope, kind, f.Names...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) walkRecv(recv *ast.FieldList) {
|
||||||
|
// If our receiver has receiver type parameters, we must declare them before
|
||||||
|
// trying to resolve the rest of the receiver, and avoid re-resolving the
|
||||||
|
// type parameter identifiers.
|
||||||
|
if recv == nil || len(recv.List) == 0 {
|
||||||
|
return // nothing to do
|
||||||
|
}
|
||||||
|
typ := recv.List[0].Type
|
||||||
|
if ptr, ok := typ.(*ast.StarExpr); ok {
|
||||||
|
typ = ptr.X
|
||||||
|
}
|
||||||
|
|
||||||
|
var declareExprs []ast.Expr // exprs to declare
|
||||||
|
var resolveExprs []ast.Expr // exprs to resolve
|
||||||
|
switch typ := typ.(type) {
|
||||||
|
case *ast.IndexExpr:
|
||||||
|
declareExprs = []ast.Expr{typ.Index}
|
||||||
|
resolveExprs = append(resolveExprs, typ.X)
|
||||||
|
case *ast.IndexListExpr:
|
||||||
|
declareExprs = typ.Indices
|
||||||
|
resolveExprs = append(resolveExprs, typ.X)
|
||||||
|
default:
|
||||||
|
resolveExprs = append(resolveExprs, typ)
|
||||||
|
}
|
||||||
|
for _, expr := range declareExprs {
|
||||||
|
if id, _ := expr.(*ast.Ident); id != nil {
|
||||||
|
r.declare(expr, nil, r.topScope, ast.Typ, id)
|
||||||
|
} else {
|
||||||
|
// The receiver type parameter expression is invalid, but try to resolve
|
||||||
|
// it anyway for consistency.
|
||||||
|
resolveExprs = append(resolveExprs, expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, expr := range resolveExprs {
|
||||||
|
if expr != nil {
|
||||||
|
ast.Walk(r, expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The receiver is invalid, but try to resolve it anyway for consistency.
|
||||||
|
for _, f := range recv.List[1:] {
|
||||||
|
if f.Type != nil {
|
||||||
|
ast.Walk(r, f.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) {
|
||||||
|
if list == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.resolveList(list)
|
||||||
|
r.declareList(list, kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
// walkTParams is like walkFieldList, but declares type parameters eagerly so
|
||||||
|
// that they may be resolved in the constraint expressions held in the field
|
||||||
|
// Type.
|
||||||
|
func (r *resolver) walkTParams(list *ast.FieldList) {
|
||||||
|
r.declareList(list, ast.Typ)
|
||||||
|
r.resolveList(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) walkBody(body *ast.BlockStmt) {
|
||||||
|
if body == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.openLabelScope()
|
||||||
|
defer r.closeLabelScope()
|
||||||
|
r.walkStmts(body.List)
|
||||||
|
}
|
||||||
@@ -757,7 +757,13 @@ func findDylibDep(exe, lib string) string {
|
|||||||
type none struct{}
|
type none struct{}
|
||||||
|
|
||||||
var hasAltPkg = map[string]none{
|
var hasAltPkg = map[string]none{
|
||||||
|
"crypto/hmac": {},
|
||||||
"crypto/md5": {},
|
"crypto/md5": {},
|
||||||
|
"crypto/rand": {},
|
||||||
|
"crypto/sha1": {},
|
||||||
|
"crypto/sha256": {},
|
||||||
|
"crypto/sha512": {},
|
||||||
|
"crypto/subtle": {},
|
||||||
"fmt": {},
|
"fmt": {},
|
||||||
"hash/crc32": {},
|
"hash/crc32": {},
|
||||||
"internal/abi": {},
|
"internal/abi": {},
|
||||||
@@ -768,6 +774,7 @@ var hasAltPkg = map[string]none{
|
|||||||
"internal/syscall/execenv": {},
|
"internal/syscall/execenv": {},
|
||||||
"internal/syscall/unix": {},
|
"internal/syscall/unix": {},
|
||||||
"math": {},
|
"math": {},
|
||||||
|
"math/big": {},
|
||||||
"math/cmplx": {},
|
"math/cmplx": {},
|
||||||
"math/rand": {},
|
"math/rand": {},
|
||||||
"reflect": {},
|
"reflect": {},
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
package build
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed _overlay/go/parser/resolver.go
|
||||||
|
var go_parser_resolver string
|
||||||
|
|
||||||
var overlayFiles = map[string]string{
|
var overlayFiles = map[string]string{
|
||||||
"math/exp_amd64.go": "package math;",
|
"math/exp_amd64.go": "package math;",
|
||||||
|
"go/parser/resolver.go": go_parser_resolver,
|
||||||
}
|
}
|
||||||
|
|||||||
72
internal/lib/crypto/hmac/hmac.go
Normal file
72
internal/lib/crypto/hmac/hmac.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package hmac
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/subtle"
|
||||||
|
"hash"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type eface struct {
|
||||||
|
_type unsafe.Pointer
|
||||||
|
funcPtr *unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func funcOf(a any) unsafe.Pointer {
|
||||||
|
e := (*eface)(unsafe.Pointer(&a))
|
||||||
|
return *e.funcPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type digest openssl.HMAC_CTX
|
||||||
|
|
||||||
|
func (d *digest) Size() int { panic("todo: hmac.(*digest).Size") }
|
||||||
|
|
||||||
|
func (d *digest) BlockSize() int { panic("todo: hmac.(*digest).BlockSize") }
|
||||||
|
|
||||||
|
func (d *digest) Reset() {
|
||||||
|
(*openssl.HMAC_CTX)(d).Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||||
|
(*openssl.HMAC_CTX)(d).UpdateBytes(p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Sum(in []byte) []byte {
|
||||||
|
const Size = openssl.EVP_MAX_MD_SIZE
|
||||||
|
var digestLen c.Uint
|
||||||
|
hash := (*[Size]byte)(c.Alloca(Size))
|
||||||
|
(*openssl.HMAC_CTX)(d).Final(&hash[0], &digestLen)
|
||||||
|
return append(in, hash[:digestLen]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new HMAC hash using the given [hash.Hash] type and key.
|
||||||
|
// New functions like sha256.New from [crypto/sha256] can be used as h.
|
||||||
|
// h must return a new Hash every time it is called.
|
||||||
|
// Note that unlike other hash implementations in the standard library,
|
||||||
|
// the returned Hash does not implement [encoding.BinaryMarshaler]
|
||||||
|
// or [encoding.BinaryUnmarshaler].
|
||||||
|
func New(h func() hash.Hash, key []byte) hash.Hash {
|
||||||
|
var md *openssl.EVP_MD
|
||||||
|
switch funcOf(h) {
|
||||||
|
case c.Func(sha256.New):
|
||||||
|
md = openssl.EVP_sha256()
|
||||||
|
default:
|
||||||
|
panic("todo: hmac.New: unsupported hash function")
|
||||||
|
}
|
||||||
|
ctx := openssl.NewHMAC_CTX()
|
||||||
|
ctx.InitBytes(key, md)
|
||||||
|
return (*digest)(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal compares two MACs for equality without leaking timing information.
|
||||||
|
func Equal(mac1, mac2 []byte) bool {
|
||||||
|
// We don't have to be constant time if the lengths of the MACs are
|
||||||
|
// different as that suggests that a completely different hash function
|
||||||
|
// was used.
|
||||||
|
return subtle.ConstantTimeCompare(mac1, mac2) == 1
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ package md5
|
|||||||
|
|
||||||
// llgo:skipall
|
// llgo:skipall
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
"hash"
|
"hash"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -25,6 +26,10 @@ import (
|
|||||||
"github.com/goplus/llgo/c/openssl"
|
"github.com/goplus/llgo/c/openssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
crypto.RegisterHash(crypto.MD5, New)
|
||||||
|
}
|
||||||
|
|
||||||
// The blocksize of MD5 in bytes.
|
// The blocksize of MD5 in bytes.
|
||||||
const BlockSize = 64
|
const BlockSize = 64
|
||||||
|
|
||||||
|
|||||||
105
internal/lib/crypto/rand/rand.go
Normal file
105
internal/lib/crypto/rand/rand.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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 rand
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
"github.com/qiniu/x/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type rndReader struct{}
|
||||||
|
|
||||||
|
func (rndReader) Read(p []byte) (n int, err error) {
|
||||||
|
return Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader is a global, shared instance of a cryptographically
|
||||||
|
// secure random number generator.
|
||||||
|
var Reader io.Reader = rndReader{}
|
||||||
|
|
||||||
|
type opensslError struct {
|
||||||
|
file *c.Char
|
||||||
|
line c.Int
|
||||||
|
flags c.Int
|
||||||
|
function *c.Char
|
||||||
|
data *c.Char
|
||||||
|
err openssl.Errno
|
||||||
|
}
|
||||||
|
|
||||||
|
// [error code]:[library name]:[function name]:[reason string]:[[filename:line]]: [text message]
|
||||||
|
func (p *opensslError) Error() string {
|
||||||
|
const bufsize = 1024
|
||||||
|
buf := (*c.Char)(c.Alloca(bufsize))
|
||||||
|
lib := openssl.ERRLibErrorString(p.err)
|
||||||
|
reason := openssl.ERRReasonErrorString(p.err)
|
||||||
|
n := uintptr(c.Snprintf(
|
||||||
|
buf, bufsize,
|
||||||
|
c.Str("%d:%s:%s:%s:[%s:%d]: "),
|
||||||
|
p.err, lib, p.function, reason, p.file, p.line))
|
||||||
|
n += c.Strlen(openssl.ERRErrorString(p.err, c.Advance(buf, n)))
|
||||||
|
return c.GoString(buf, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getError() *opensslError {
|
||||||
|
ret := new(opensslError)
|
||||||
|
err := openssl.ERRGetErrorAll(&ret.file, &ret.line, &ret.function, &ret.data, &ret.flags)
|
||||||
|
if err == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func getErrors() error {
|
||||||
|
var errs errors.List
|
||||||
|
for openssl.ERRPeekError() != 0 {
|
||||||
|
errs.Add(getError())
|
||||||
|
}
|
||||||
|
return errs.ToError()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read is a helper function that calls Reader.Read using io.ReadFull.
|
||||||
|
// On return, n == len(b) if and only if err == nil.
|
||||||
|
func Read(b []byte) (n int, err error) {
|
||||||
|
if openssl.RANDBytes(b) != 0 {
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
return 0, getErrors()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
// batched returns a function that calls f to populate a []byte by chunking it
|
||||||
|
// into subslices of, at most, readMax bytes.
|
||||||
|
func batched(f func([]byte) error, readMax int) func([]byte) error {
|
||||||
|
return func(out []byte) error {
|
||||||
|
for len(out) > 0 {
|
||||||
|
read := len(out)
|
||||||
|
if read > readMax {
|
||||||
|
read = readMax
|
||||||
|
}
|
||||||
|
if err := f(out[:read]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out = out[read:]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
98
internal/lib/crypto/rand/util.go
Normal file
98
internal/lib/crypto/rand/util.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Prime returns a number of the given bit length that is prime with high probability.
|
||||||
|
// Prime will return error for any error returned by rand.Read or if bits < 2.
|
||||||
|
func Prime(rand io.Reader, bits int) (*big.Int, error) {
|
||||||
|
if bits < 2 {
|
||||||
|
return nil, errors.New("crypto/rand: prime size must be at least 2-bit")
|
||||||
|
}
|
||||||
|
|
||||||
|
b := uint(bits % 8)
|
||||||
|
if b == 0 {
|
||||||
|
b = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes := make([]byte, (bits+7)/8)
|
||||||
|
p := new(big.Int)
|
||||||
|
|
||||||
|
for {
|
||||||
|
if _, err := io.ReadFull(rand, bytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear bits in the first byte to make sure the candidate has a size <= bits.
|
||||||
|
bytes[0] &= uint8(int(1<<b) - 1)
|
||||||
|
// Don't let the value be too small, i.e, set the most significant two bits.
|
||||||
|
// Setting the top two bits, rather than just the top bit,
|
||||||
|
// means that when two of these values are multiplied together,
|
||||||
|
// the result isn't ever one bit short.
|
||||||
|
if b >= 2 {
|
||||||
|
bytes[0] |= 3 << (b - 2)
|
||||||
|
} else {
|
||||||
|
// Here b==1, because b cannot be zero.
|
||||||
|
bytes[0] |= 1
|
||||||
|
if len(bytes) > 1 {
|
||||||
|
bytes[1] |= 0x80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make the value odd since an even number this large certainly isn't prime.
|
||||||
|
bytes[len(bytes)-1] |= 1
|
||||||
|
|
||||||
|
p.SetBytes(bytes)
|
||||||
|
if p.ProbablyPrime(20) {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int returns a uniform random value in [0, max). It panics if max <= 0.
|
||||||
|
func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
|
||||||
|
if max.Sign() <= 0 {
|
||||||
|
panic("crypto/rand: argument to Int is <= 0")
|
||||||
|
}
|
||||||
|
n = new(big.Int)
|
||||||
|
n.Sub(max, n.SetUint64(1))
|
||||||
|
// bitLen is the maximum bit length needed to encode a value < max.
|
||||||
|
bitLen := n.BitLen()
|
||||||
|
if bitLen == 0 {
|
||||||
|
// the only valid result is 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// k is the maximum byte length needed to encode a value < max.
|
||||||
|
k := (bitLen + 7) / 8
|
||||||
|
// b is the number of bits in the most significant byte of max-1.
|
||||||
|
b := uint(bitLen % 8)
|
||||||
|
if b == 0 {
|
||||||
|
b = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes := make([]byte, k)
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, err = io.ReadFull(rand, bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear bits in the first byte to increase the probability
|
||||||
|
// that the candidate is < max.
|
||||||
|
bytes[0] &= uint8(int(1<<b) - 1)
|
||||||
|
|
||||||
|
n.SetBytes(bytes)
|
||||||
|
if n.Cmp(max) < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
73
internal/lib/crypto/sha1/sha1.go
Normal file
73
internal/lib/crypto/sha1/sha1.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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 sha1
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"hash"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
crypto.RegisterHash(crypto.SHA1, New)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The blocksize of SHA-1 in bytes.
|
||||||
|
const BlockSize = 64
|
||||||
|
|
||||||
|
// The size of a SHA-1 checksum in bytes.
|
||||||
|
const Size = 20
|
||||||
|
|
||||||
|
type digest struct {
|
||||||
|
ctx openssl.SHA_CTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Size() int { return Size }
|
||||||
|
|
||||||
|
func (d *digest) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
func (d *digest) Reset() {
|
||||||
|
d.ctx.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||||
|
d.ctx.UpdateBytes(p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Sum(in []byte) []byte {
|
||||||
|
hash := (*[Size]byte)(c.Alloca(Size))
|
||||||
|
d.ctx.Final((*byte)(unsafe.Pointer(hash)))
|
||||||
|
return append(in, hash[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new hash.Hash computing the SHA1 checksum.
|
||||||
|
func New() hash.Hash {
|
||||||
|
d := new(digest)
|
||||||
|
d.ctx.Init()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum returns the SHA-1 checksum of the data.
|
||||||
|
func Sum(data []byte) (ret [Size]byte) {
|
||||||
|
openssl.SHA1Bytes(data, &ret[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
64
internal/lib/crypto/sha256/sha224.go
Normal file
64
internal/lib/crypto/sha256/sha224.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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 sha256
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hash"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The size of a SHA224 checksum in bytes.
|
||||||
|
const Size224 = 28
|
||||||
|
|
||||||
|
type digest224 struct {
|
||||||
|
ctx openssl.SHA224_CTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest224) Size() int { return Size224 }
|
||||||
|
|
||||||
|
func (d *digest224) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
func (d *digest224) Reset() {
|
||||||
|
d.ctx.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest224) Write(p []byte) (nn int, err error) {
|
||||||
|
d.ctx.UpdateBytes(p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest224) Sum(in []byte) []byte {
|
||||||
|
hash := (*[Size]byte)(c.Alloca(Size))
|
||||||
|
d.ctx.Final((*byte)(unsafe.Pointer(hash)))
|
||||||
|
return append(in, hash[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New224 returns a new hash.Hash computing the SHA224 checksum.
|
||||||
|
func New224() hash.Hash {
|
||||||
|
d := new(digest224)
|
||||||
|
d.ctx.Init()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum224 returns the SHA224 checksum of the data.
|
||||||
|
func Sum224(data []byte) (ret [Size224]byte) {
|
||||||
|
openssl.SHA224Bytes(data, &ret[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
74
internal/lib/crypto/sha256/sha256.go
Normal file
74
internal/lib/crypto/sha256/sha256.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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 sha256
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"hash"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
crypto.RegisterHash(crypto.SHA224, New224)
|
||||||
|
crypto.RegisterHash(crypto.SHA256, New)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The blocksize of SHA256 and SHA224 in bytes.
|
||||||
|
const BlockSize = 64
|
||||||
|
|
||||||
|
// The size of a SHA256 checksum in bytes.
|
||||||
|
const Size = 32
|
||||||
|
|
||||||
|
type digest256 struct {
|
||||||
|
ctx openssl.SHA256_CTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest256) Size() int { return Size }
|
||||||
|
|
||||||
|
func (d *digest256) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
func (d *digest256) Reset() {
|
||||||
|
d.ctx.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest256) Write(p []byte) (nn int, err error) {
|
||||||
|
d.ctx.UpdateBytes(p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest256) Sum(in []byte) []byte {
|
||||||
|
hash := (*[Size]byte)(c.Alloca(Size))
|
||||||
|
d.ctx.Final((*byte)(unsafe.Pointer(hash)))
|
||||||
|
return append(in, hash[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new hash.Hash computing the SHA256 checksum.
|
||||||
|
func New() hash.Hash {
|
||||||
|
d := new(digest256)
|
||||||
|
d.ctx.Init()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum256 returns the SHA256 checksum of the data.
|
||||||
|
func Sum256(data []byte) (ret [Size]byte) {
|
||||||
|
openssl.SHA256Bytes(data, &ret[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
59
internal/lib/crypto/sha512/sha384.go
Normal file
59
internal/lib/crypto/sha512/sha384.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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 sha512
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hash"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type digest384 struct {
|
||||||
|
ctx openssl.SHA384_CTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest384) Size() int { return Size384 }
|
||||||
|
|
||||||
|
func (d *digest384) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
func (d *digest384) Reset() {
|
||||||
|
d.ctx.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest384) Write(p []byte) (nn int, err error) {
|
||||||
|
d.ctx.UpdateBytes(p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest384) Sum(in []byte) []byte {
|
||||||
|
hash := (*[Size]byte)(c.Alloca(Size))
|
||||||
|
d.ctx.Final((*byte)(unsafe.Pointer(hash)))
|
||||||
|
return append(in, hash[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New384() hash.Hash {
|
||||||
|
d := new(digest384)
|
||||||
|
d.ctx.Init()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sum384(data []byte) (ret [Size384]byte) {
|
||||||
|
openssl.SHA384Bytes(data, &ret[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
102
internal/lib/crypto/sha512/sha512.go
Normal file
102
internal/lib/crypto/sha512/sha512.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* 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 sha512
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"hash"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
crypto.RegisterHash(crypto.SHA384, New384)
|
||||||
|
crypto.RegisterHash(crypto.SHA512, New)
|
||||||
|
crypto.RegisterHash(crypto.SHA512_224, New512_224)
|
||||||
|
crypto.RegisterHash(crypto.SHA512_256, New512_256)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Size is the size, in bytes, of a SHA-512 checksum.
|
||||||
|
Size = 64
|
||||||
|
|
||||||
|
// Size224 is the size, in bytes, of a SHA-512/224 checksum.
|
||||||
|
Size224 = 28
|
||||||
|
|
||||||
|
// Size256 is the size, in bytes, of a SHA-512/256 checksum.
|
||||||
|
Size256 = 32
|
||||||
|
|
||||||
|
// Size384 is the size, in bytes, of a SHA-384 checksum.
|
||||||
|
Size384 = 48
|
||||||
|
|
||||||
|
// BlockSize is the block size, in bytes, of the SHA-512/224,
|
||||||
|
// SHA-512/256, SHA-384 and SHA-512 hash functions.
|
||||||
|
BlockSize = 128
|
||||||
|
)
|
||||||
|
|
||||||
|
type digest512 struct {
|
||||||
|
ctx openssl.SHA512_CTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest512) Size() int { return Size }
|
||||||
|
|
||||||
|
func (d *digest512) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
func (d *digest512) Reset() {
|
||||||
|
d.ctx.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest512) Write(p []byte) (nn int, err error) {
|
||||||
|
d.ctx.UpdateBytes(p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest512) Sum(in []byte) []byte {
|
||||||
|
hash := (*[Size]byte)(c.Alloca(Size))
|
||||||
|
d.ctx.Final((*byte)(unsafe.Pointer(hash)))
|
||||||
|
return append(in, hash[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() hash.Hash {
|
||||||
|
d := new(digest512)
|
||||||
|
d.ctx.Init()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sum512(data []byte) (ret [Size]byte) {
|
||||||
|
openssl.SHA512Bytes(data, &ret[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func New512_224() hash.Hash {
|
||||||
|
panic("todo: crypto/sha512.New512_224")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sum512_224(data []byte) [Size224]byte {
|
||||||
|
panic("todo: crypto/sha512.Sum512_224")
|
||||||
|
}
|
||||||
|
|
||||||
|
func New512_256() hash.Hash {
|
||||||
|
panic("todo: crypto/sha512.New512_256")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sum512_256(data []byte) [Size256]byte {
|
||||||
|
panic("todo: crypto/sha512.Sum512_256")
|
||||||
|
}
|
||||||
22
internal/lib/crypto/subtle/xor.go
Normal file
22
internal/lib/crypto/subtle/xor.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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 subtle
|
||||||
|
|
||||||
|
// llgo:skip XORBytes
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
220
internal/lib/internal/fmtsort/sort.go
Normal file
220
internal/lib/internal/fmtsort/sort.go
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package fmtsort provides a general stable ordering mechanism
|
||||||
|
// for maps, on behalf of the fmt and text/template packages.
|
||||||
|
// It is not guaranteed to be efficient and works only for types
|
||||||
|
// that are valid map keys.
|
||||||
|
package fmtsort
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Note: Throughout this package we avoid calling reflect.Value.Interface as
|
||||||
|
// it is not always legal to do so and it's easier to avoid the issue than to face it.
|
||||||
|
|
||||||
|
// SortedMap represents a map's keys and values. The keys and values are
|
||||||
|
// aligned in index order: Value[i] is the value in the map corresponding to Key[i].
|
||||||
|
type SortedMap struct {
|
||||||
|
Key []reflect.Value
|
||||||
|
Value []reflect.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SortedMap) Len() int { return len(o.Key) }
|
||||||
|
func (o *SortedMap) Less(i, j int) bool { return compare(o.Key[i], o.Key[j]) < 0 }
|
||||||
|
func (o *SortedMap) Swap(i, j int) {
|
||||||
|
o.Key[i], o.Key[j] = o.Key[j], o.Key[i]
|
||||||
|
o.Value[i], o.Value[j] = o.Value[j], o.Value[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort accepts a map and returns a SortedMap that has the same keys and
|
||||||
|
// values but in a stable sorted order according to the keys, modulo issues
|
||||||
|
// raised by unorderable key values such as NaNs.
|
||||||
|
//
|
||||||
|
// The ordering rules are more general than with Go's < operator:
|
||||||
|
//
|
||||||
|
// - when applicable, nil compares low
|
||||||
|
// - ints, floats, and strings order by <
|
||||||
|
// - NaN compares less than non-NaN floats
|
||||||
|
// - bool compares false before true
|
||||||
|
// - complex compares real, then imag
|
||||||
|
// - pointers compare by machine address
|
||||||
|
// - channel values compare by machine address
|
||||||
|
// - structs compare each field in turn
|
||||||
|
// - arrays compare each element in turn.
|
||||||
|
// Otherwise identical arrays compare by length.
|
||||||
|
// - interface values compare first by reflect.Type describing the concrete type
|
||||||
|
// and then by concrete value as described in the previous rules.
|
||||||
|
func Sort(mapValue reflect.Value) *SortedMap {
|
||||||
|
if mapValue.Type().Kind() != reflect.Map {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Note: this code is arranged to not panic even in the presence
|
||||||
|
// of a concurrent map update. The runtime is responsible for
|
||||||
|
// yelling loudly if that happens. See issue 33275.
|
||||||
|
n := mapValue.Len()
|
||||||
|
key := make([]reflect.Value, 0, n)
|
||||||
|
value := make([]reflect.Value, 0, n)
|
||||||
|
iter := mapValue.MapRange()
|
||||||
|
for iter.Next() {
|
||||||
|
key = append(key, iter.Key())
|
||||||
|
value = append(value, iter.Value())
|
||||||
|
}
|
||||||
|
sorted := &SortedMap{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
sort.Stable(sorted)
|
||||||
|
return sorted
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare compares two values of the same type. It returns -1, 0, 1
|
||||||
|
// according to whether a > b (1), a == b (0), or a < b (-1).
|
||||||
|
// If the types differ, it returns -1.
|
||||||
|
// See the comment on Sort for the comparison rules.
|
||||||
|
func compare(aVal, bVal reflect.Value) int {
|
||||||
|
aType, bType := aVal.Type(), bVal.Type()
|
||||||
|
if aType != bType {
|
||||||
|
return -1 // No good answer possible, but don't return 0: they're not equal.
|
||||||
|
}
|
||||||
|
switch aVal.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
a, b := aVal.Int(), bVal.Int()
|
||||||
|
switch {
|
||||||
|
case a < b:
|
||||||
|
return -1
|
||||||
|
case a > b:
|
||||||
|
return 1
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
a, b := aVal.Uint(), bVal.Uint()
|
||||||
|
switch {
|
||||||
|
case a < b:
|
||||||
|
return -1
|
||||||
|
case a > b:
|
||||||
|
return 1
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
a, b := aVal.String(), bVal.String()
|
||||||
|
switch {
|
||||||
|
case a < b:
|
||||||
|
return -1
|
||||||
|
case a > b:
|
||||||
|
return 1
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return floatCompare(aVal.Float(), bVal.Float())
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
a, b := aVal.Complex(), bVal.Complex()
|
||||||
|
if c := floatCompare(real(a), real(b)); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return floatCompare(imag(a), imag(b))
|
||||||
|
case reflect.Bool:
|
||||||
|
a, b := aVal.Bool(), bVal.Bool()
|
||||||
|
switch {
|
||||||
|
case a == b:
|
||||||
|
return 0
|
||||||
|
case a:
|
||||||
|
return 1
|
||||||
|
default:
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
case reflect.Pointer, reflect.UnsafePointer:
|
||||||
|
a, b := aVal.Pointer(), bVal.Pointer()
|
||||||
|
switch {
|
||||||
|
case a < b:
|
||||||
|
return -1
|
||||||
|
case a > b:
|
||||||
|
return 1
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
case reflect.Chan:
|
||||||
|
if c, ok := nilCompare(aVal, bVal); ok {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
ap, bp := aVal.Pointer(), bVal.Pointer()
|
||||||
|
switch {
|
||||||
|
case ap < bp:
|
||||||
|
return -1
|
||||||
|
case ap > bp:
|
||||||
|
return 1
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < aVal.NumField(); i++ {
|
||||||
|
if c := compare(aVal.Field(i), bVal.Field(i)); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
case reflect.Array:
|
||||||
|
for i := 0; i < aVal.Len(); i++ {
|
||||||
|
if c := compare(aVal.Index(i), bVal.Index(i)); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
case reflect.Interface:
|
||||||
|
if c, ok := nilCompare(aVal, bVal); ok {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type()))
|
||||||
|
if c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return compare(aVal.Elem(), bVal.Elem())
|
||||||
|
default:
|
||||||
|
// Certain types cannot appear as keys (maps, funcs, slices), but be explicit.
|
||||||
|
panic("bad type in compare: " + aType.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nilCompare checks whether either value is nil. If not, the boolean is false.
|
||||||
|
// If either value is nil, the boolean is true and the integer is the comparison
|
||||||
|
// value. The comparison is defined to be 0 if both are nil, otherwise the one
|
||||||
|
// nil value compares low. Both arguments must represent a chan, func,
|
||||||
|
// interface, map, pointer, or slice.
|
||||||
|
func nilCompare(aVal, bVal reflect.Value) (int, bool) {
|
||||||
|
if aVal.IsNil() {
|
||||||
|
if bVal.IsNil() {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if bVal.IsNil() {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// floatCompare compares two floating-point values. NaNs compare low.
|
||||||
|
func floatCompare(a, b float64) int {
|
||||||
|
switch {
|
||||||
|
case isNaN(a):
|
||||||
|
return -1 // No good answer if b is a NaN so don't bother checking.
|
||||||
|
case isNaN(b):
|
||||||
|
return 1
|
||||||
|
case a < b:
|
||||||
|
return -1
|
||||||
|
case a > b:
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNaN(a float64) bool {
|
||||||
|
return a != a
|
||||||
|
}
|
||||||
456
internal/lib/math/big/int.go
Normal file
456
internal/lib/math/big/int.go
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
/*
|
||||||
|
* 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 big
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Word represents a single digit of a multi-precision unsigned integer.
|
||||||
|
type Word openssl.BN_ULONG
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO(xsw): share ctx
|
||||||
|
func ctxGet() *openssl.BN_CTX {
|
||||||
|
return openssl.BN_CTXNew()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ctxPut(ctx *openssl.BN_CTX) {
|
||||||
|
ctx.Free()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Int openssl.BIGNUM
|
||||||
|
|
||||||
|
// Sign returns:
|
||||||
|
//
|
||||||
|
// -1 if x < 0
|
||||||
|
// 0 if x == 0
|
||||||
|
// +1 if x > 0
|
||||||
|
func (x *Int) Sign() int {
|
||||||
|
a := (*openssl.BIGNUM)(x)
|
||||||
|
if a.IsNegative() != 0 {
|
||||||
|
return -1
|
||||||
|
} else if a.IsZero() != 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInt64 sets z to x and returns z.
|
||||||
|
func (z *Int) SetInt64(x int64) *Int {
|
||||||
|
a := (*openssl.BIGNUM)(z)
|
||||||
|
if x < 0 {
|
||||||
|
a.SetWord(openssl.BN_ULONG(-x))
|
||||||
|
a.SetNegative(1)
|
||||||
|
} else {
|
||||||
|
a.SetWord(openssl.BN_ULONG(x))
|
||||||
|
a.SetNegative(0)
|
||||||
|
}
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUint64 sets z to x and returns z.
|
||||||
|
func (z *Int) SetUint64(x uint64) *Int {
|
||||||
|
a := (*openssl.BIGNUM)(z)
|
||||||
|
a.SetWord(openssl.BN_ULONG(x))
|
||||||
|
a.SetNegative(0)
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInt allocates and returns a new Int set to x.
|
||||||
|
func NewInt(x int64) *Int {
|
||||||
|
z := (*Int)(openssl.BNNew())
|
||||||
|
return z.SetInt64(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets z to x and returns z.
|
||||||
|
func (z *Int) Set(x *Int) *Int {
|
||||||
|
if z != x {
|
||||||
|
a := (*openssl.BIGNUM)(z)
|
||||||
|
b := (*openssl.BIGNUM)(x)
|
||||||
|
a.Copy(b)
|
||||||
|
}
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abs sets z to |x| (the absolute value of x) and returns z.
|
||||||
|
func (z *Int) Abs(x *Int) *Int {
|
||||||
|
z.Set(x)
|
||||||
|
a := (*openssl.BIGNUM)(z)
|
||||||
|
a.SetNegative(0)
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neg sets z to -x and returns z.
|
||||||
|
func (z *Int) Neg(x *Int) *Int {
|
||||||
|
z.Set(x)
|
||||||
|
a := (*openssl.BIGNUM)(z)
|
||||||
|
if a.IsNegative() != 0 {
|
||||||
|
a.SetNegative(0)
|
||||||
|
} else {
|
||||||
|
a.SetNegative(1)
|
||||||
|
}
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bits provides raw (unchecked but fast) access to x by returning its
|
||||||
|
// absolute value as a little-endian Word slice. The result and x share
|
||||||
|
// the same underlying array.
|
||||||
|
// Bits is intended to support implementation of missing low-level Int
|
||||||
|
// functionality outside this package; it should be avoided otherwise.
|
||||||
|
func (x *Int) Bits() []Word {
|
||||||
|
panic("todo big.Bits")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBits provides raw (unchecked but fast) access to z by setting its
|
||||||
|
// value to abs, interpreted as a little-endian Word slice, and returning
|
||||||
|
// z. The result and abs share the same underlying array.
|
||||||
|
// SetBits is intended to support implementation of missing low-level Int
|
||||||
|
// functionality outside this package; it should be avoided otherwise.
|
||||||
|
func (z *Int) SetBits(abs []Word) *Int {
|
||||||
|
panic("todo big.SetBits")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sets z to the sum x+y and returns z.
|
||||||
|
func (z *Int) Add(x, y *Int) *Int {
|
||||||
|
(*openssl.BIGNUM)(z).Add((*openssl.BIGNUM)(x), (*openssl.BIGNUM)(y))
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub sets z to the difference x-y and returns z.
|
||||||
|
func (z *Int) Sub(x, y *Int) *Int {
|
||||||
|
(*openssl.BIGNUM)(z).Sub((*openssl.BIGNUM)(x), (*openssl.BIGNUM)(y))
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mul sets z to the product x*y and returns z.
|
||||||
|
func (z *Int) Mul(x, y *Int) *Int {
|
||||||
|
panic("todo big.Mul")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulRange sets z to the product of all integers
|
||||||
|
// in the range [a, b] inclusively and returns z.
|
||||||
|
// If a > b (empty range), the result is 1.
|
||||||
|
func (z *Int) MulRange(a, b int64) *Int {
|
||||||
|
panic("todo big.MulRange")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binomial sets z to the binomial coefficient C(n, k) and returns z.
|
||||||
|
func (z *Int) Binomial(n, k int64) *Int {
|
||||||
|
panic("todo big.Binomial")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quo sets z to the quotient x/y for y != 0 and returns z.
|
||||||
|
// If y == 0, a division-by-zero run-time panic occurs.
|
||||||
|
// Quo implements truncated division (like Go); see QuoRem for more details.
|
||||||
|
func (z *Int) Quo(x, y *Int) *Int {
|
||||||
|
panic("todo big.Quo")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rem sets z to the remainder x%y for y != 0 and returns z.
|
||||||
|
// If y == 0, a division-by-zero run-time panic occurs.
|
||||||
|
// Rem implements truncated modulus (like Go); see QuoRem for more details.
|
||||||
|
func (z *Int) Rem(x, y *Int) *Int {
|
||||||
|
panic("todo big.Rem")
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuoRem sets z to the quotient x/y and r to the remainder x%y
|
||||||
|
// and returns the pair (z, r) for y != 0.
|
||||||
|
// If y == 0, a division-by-zero run-time panic occurs.
|
||||||
|
//
|
||||||
|
// QuoRem implements T-division and modulus (like Go):
|
||||||
|
//
|
||||||
|
// q = x/y with the result truncated to zero
|
||||||
|
// r = x - y*q
|
||||||
|
//
|
||||||
|
// (See Daan Leijen, “Division and Modulus for Computer Scientists”.)
|
||||||
|
// See DivMod for Euclidean division and modulus (unlike Go).
|
||||||
|
func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
|
||||||
|
panic("todo big.QuoRem")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Div sets z to the quotient x/y for y != 0 and returns z.
|
||||||
|
// If y == 0, a division-by-zero run-time panic occurs.
|
||||||
|
// Div implements Euclidean division (unlike Go); see DivMod for more details.
|
||||||
|
func (z *Int) Div(x, y *Int) *Int {
|
||||||
|
panic("todo big.Div")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mod sets z to the modulus x%y for y != 0 and returns z.
|
||||||
|
// If y == 0, a division-by-zero run-time panic occurs.
|
||||||
|
// Mod implements Euclidean modulus (unlike Go); see DivMod for more details.
|
||||||
|
func (z *Int) Mod(x, y *Int) *Int {
|
||||||
|
panic("todo big.Mod")
|
||||||
|
}
|
||||||
|
|
||||||
|
// DivMod sets z to the quotient x div y and m to the modulus x mod y
|
||||||
|
// and returns the pair (z, m) for y != 0.
|
||||||
|
// If y == 0, a division-by-zero run-time panic occurs.
|
||||||
|
//
|
||||||
|
// DivMod implements Euclidean division and modulus (unlike Go):
|
||||||
|
//
|
||||||
|
// q = x div y such that
|
||||||
|
// m = x - y*q with 0 <= m < |y|
|
||||||
|
//
|
||||||
|
// (See Raymond T. Boute, “The Euclidean definition of the functions
|
||||||
|
// div and mod”. ACM Transactions on Programming Languages and
|
||||||
|
// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
|
||||||
|
// ACM press.)
|
||||||
|
// See QuoRem for T-division and modulus (like Go).
|
||||||
|
func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) {
|
||||||
|
panic("big.DivMod")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmp compares x and y and returns:
|
||||||
|
//
|
||||||
|
// -1 if x < y
|
||||||
|
// 0 if x == y
|
||||||
|
// +1 if x > y
|
||||||
|
func (x *Int) Cmp(y *Int) (r int) {
|
||||||
|
return int((*openssl.BIGNUM)(x).Cmp((*openssl.BIGNUM)(y)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CmpAbs compares the absolute values of x and y and returns:
|
||||||
|
//
|
||||||
|
// -1 if |x| < |y|
|
||||||
|
// 0 if |x| == |y|
|
||||||
|
// +1 if |x| > |y|
|
||||||
|
func (x *Int) CmpAbs(y *Int) int {
|
||||||
|
return int((*openssl.BIGNUM)(x).Ucmp((*openssl.BIGNUM)(y)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns the int64 representation of x.
|
||||||
|
// If x cannot be represented in an int64, the result is undefined.
|
||||||
|
func (x *Int) Int64() int64 {
|
||||||
|
panic("todo big.Int64")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 returns the uint64 representation of x.
|
||||||
|
// If x cannot be represented in a uint64, the result is undefined.
|
||||||
|
func (x *Int) Uint64() uint64 {
|
||||||
|
panic("todo big.Uint64")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsInt64 reports whether x can be represented as an int64.
|
||||||
|
func (x *Int) IsInt64() bool {
|
||||||
|
panic("todo big.IsInt64")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUint64 reports whether x can be represented as a uint64.
|
||||||
|
func (x *Int) IsUint64() bool {
|
||||||
|
panic("todo big.IsUint64")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 returns the float64 value nearest x,
|
||||||
|
// and an indication of any rounding that occurred.
|
||||||
|
// TODO(xsw):
|
||||||
|
/*
|
||||||
|
func (x *Int) Float64() (float64, Accuracy) {
|
||||||
|
panic("todo big.Float64")
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// SetString sets z to the value of s, interpreted in the given base,
|
||||||
|
// and returns z and a boolean indicating success. The entire string
|
||||||
|
// (not just a prefix) must be valid for success. If SetString fails,
|
||||||
|
// the value of z is undefined but the returned value is nil.
|
||||||
|
//
|
||||||
|
// The base argument must be 0 or a value between 2 and MaxBase.
|
||||||
|
// For base 0, the number prefix determines the actual base: A prefix of
|
||||||
|
// “0b” or “0B” selects base 2, “0”, “0o” or “0O” selects base 8,
|
||||||
|
// and “0x” or “0X” selects base 16. Otherwise, the selected base is 10
|
||||||
|
// and no prefix is accepted.
|
||||||
|
//
|
||||||
|
// For bases <= 36, lower and upper case letters are considered the same:
|
||||||
|
// The letters 'a' to 'z' and 'A' to 'Z' represent digit values 10 to 35.
|
||||||
|
// For bases > 36, the upper case letters 'A' to 'Z' represent the digit
|
||||||
|
// values 36 to 61.
|
||||||
|
//
|
||||||
|
// For base 0, an underscore character “_” may appear between a base
|
||||||
|
// prefix and an adjacent digit, and between successive digits; such
|
||||||
|
// underscores do not change the value of the number.
|
||||||
|
// Incorrect placement of underscores is reported as an error if there
|
||||||
|
// are no other errors. If base != 0, underscores are not recognized
|
||||||
|
// and act like any other character that is not a valid digit.
|
||||||
|
func (z *Int) SetString(s string, base int) (*Int, bool) {
|
||||||
|
panic("todo big.SetString")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBytes interprets buf as the bytes of a big-endian unsigned
|
||||||
|
// integer, sets z to that value, and returns z.
|
||||||
|
func (z *Int) SetBytes(buf []byte) *Int {
|
||||||
|
panic("todo big.SetBytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the absolute value of x as a big-endian byte slice.
|
||||||
|
//
|
||||||
|
// To use a fixed length slice, or a preallocated one, use FillBytes.
|
||||||
|
func (x *Int) Bytes() []byte {
|
||||||
|
panic("todo big.Bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FillBytes sets buf to the absolute value of x, storing it as a zero-extended
|
||||||
|
// big-endian byte slice, and returns buf.
|
||||||
|
//
|
||||||
|
// If the absolute value of x doesn't fit in buf, FillBytes will panic.
|
||||||
|
func (x *Int) FillBytes(buf []byte) []byte {
|
||||||
|
panic("todo big.FillBytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitLen returns the length of the absolute value of x in bits.
|
||||||
|
// The bit length of 0 is 0.
|
||||||
|
func (x *Int) BitLen() int {
|
||||||
|
panic("todo big.BitLen")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrailingZeroBits returns the number of consecutive least significant zero
|
||||||
|
// bits of |x|.
|
||||||
|
func (x *Int) TrailingZeroBits() uint {
|
||||||
|
panic("todo big.TrailingZeroBits")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
|
||||||
|
// If m == nil or m == 0, z = x**y unless y <= 0 then z = 1. If m != 0, y < 0,
|
||||||
|
// and x and m are not relatively prime, z is unchanged and nil is returned.
|
||||||
|
//
|
||||||
|
// Modular exponentiation of inputs of a particular size is not a
|
||||||
|
// cryptographically constant-time operation.
|
||||||
|
func (z *Int) Exp(x, y, m *Int) *Int {
|
||||||
|
ctx := ctxGet()
|
||||||
|
mbn := (*openssl.BIGNUM)(m)
|
||||||
|
if mbn == nil || mbn.IsZero() != 0 {
|
||||||
|
(*openssl.BIGNUM)(z).Exp((*openssl.BIGNUM)(x), (*openssl.BIGNUM)(y), ctx)
|
||||||
|
} else {
|
||||||
|
(*openssl.BIGNUM)(z).ModExp((*openssl.BIGNUM)(x), (*openssl.BIGNUM)(y), mbn, ctx)
|
||||||
|
}
|
||||||
|
ctxPut(ctx)
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCD sets z to the greatest common divisor of a and b and returns z.
|
||||||
|
// If x or y are not nil, GCD sets their value such that z = a*x + b*y.
|
||||||
|
//
|
||||||
|
// a and b may be positive, zero or negative. (Before Go 1.14 both had
|
||||||
|
// to be > 0.) Regardless of the signs of a and b, z is always >= 0.
|
||||||
|
//
|
||||||
|
// If a == b == 0, GCD sets z = x = y = 0.
|
||||||
|
//
|
||||||
|
// If a == 0 and b != 0, GCD sets z = |b|, x = 0, y = sign(b) * 1.
|
||||||
|
//
|
||||||
|
// If a != 0 and b == 0, GCD sets z = |a|, x = sign(a) * 1, y = 0.
|
||||||
|
func (z *Int) GCD(x, y, a, b *Int) *Int {
|
||||||
|
panic("todo big.GCD")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rand sets z to a pseudo-random number in [0, n) and returns z.
|
||||||
|
//
|
||||||
|
// As this uses the math/rand package, it must not be used for
|
||||||
|
// security-sensitive work. Use crypto/rand.Int instead.
|
||||||
|
func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
|
||||||
|
panic("todo big.Rand")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModInverse sets z to the multiplicative inverse of g in the ring ℤ/nℤ
|
||||||
|
// and returns z. If g and n are not relatively prime, g has no multiplicative
|
||||||
|
// inverse in the ring ℤ/nℤ. In this case, z is unchanged and the return value
|
||||||
|
// is nil. If n == 0, a division-by-zero run-time panic occurs.
|
||||||
|
func (z *Int) ModInverse(g, n *Int) *Int {
|
||||||
|
panic("todo big.ModInverse")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jacobi returns the Jacobi symbol (x/y), either +1, -1, or 0.
|
||||||
|
// The y argument must be an odd integer.
|
||||||
|
func Jacobi(x, y *Int) int {
|
||||||
|
panic("todo big.Jacobi")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModSqrt sets z to a square root of x mod p if such a square root exists, and
|
||||||
|
// returns z. The modulus p must be an odd prime. If x is not a square mod p,
|
||||||
|
// ModSqrt leaves z unchanged and returns nil. This function panics if p is
|
||||||
|
// not an odd integer, its behavior is undefined if p is odd but not prime.
|
||||||
|
func (z *Int) ModSqrt(x, p *Int) *Int {
|
||||||
|
panic("todo big.ModSqrt")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lsh sets z = x << n and returns z.
|
||||||
|
func (z *Int) Lsh(x *Int, n uint) *Int {
|
||||||
|
a := (*openssl.BIGNUM)(z)
|
||||||
|
b := (*openssl.BIGNUM)(x)
|
||||||
|
a.Lshift(b, c.Int(n))
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rsh sets z = x >> n and returns z.
|
||||||
|
func (z *Int) Rsh(x *Int, n uint) *Int {
|
||||||
|
a := (*openssl.BIGNUM)(z)
|
||||||
|
b := (*openssl.BIGNUM)(x)
|
||||||
|
a.Rshift(b, c.Int(n))
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit returns the value of the i'th bit of x. That is, it
|
||||||
|
// returns (x>>i)&1. The bit index i must be >= 0.
|
||||||
|
func (x *Int) Bit(i int) uint {
|
||||||
|
panic("todo big.Bit")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBit sets z to x, with x's i'th bit set to b (0 or 1).
|
||||||
|
// That is, if b is 1 SetBit sets z = x | (1 << i);
|
||||||
|
// if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1,
|
||||||
|
// SetBit will panic.
|
||||||
|
func (z *Int) SetBit(x *Int, i int, b uint) *Int {
|
||||||
|
panic("todo big.SetBit")
|
||||||
|
}
|
||||||
|
|
||||||
|
// And sets z = x & y and returns z.
|
||||||
|
func (z *Int) And(x, y *Int) *Int {
|
||||||
|
panic("todo big.And")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AndNot sets z = x &^ y and returns z.
|
||||||
|
func (z *Int) AndNot(x, y *Int) *Int {
|
||||||
|
panic("todo big.AndNot")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or sets z = x | y and returns z.
|
||||||
|
func (z *Int) Or(x, y *Int) *Int {
|
||||||
|
panic("todo big.Or")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Xor sets z = x ^ y and returns z.
|
||||||
|
func (z *Int) Xor(x, y *Int) *Int {
|
||||||
|
panic("todo big.Xor")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not sets z = ^x and returns z.
|
||||||
|
func (z *Int) Not(x *Int) *Int {
|
||||||
|
panic("todo big.Not")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sqrt sets z to ⌊√x⌋, the largest integer such that z² ≤ x, and returns z.
|
||||||
|
// It panics if x is negative.
|
||||||
|
func (z *Int) Sqrt(x *Int) *Int {
|
||||||
|
panic("todo big.Sqrt")
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
70
internal/lib/math/big/intconv.go
Normal file
70
internal/lib/math/big/intconv.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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 big
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Text returns the string representation of x in the given base.
|
||||||
|
// Base must be between 2 and 62, inclusive. The result uses the
|
||||||
|
// lower-case letters 'a' to 'z' for digit values 10 to 35, and
|
||||||
|
// the upper-case letters 'A' to 'Z' for digit values 36 to 61.
|
||||||
|
// No prefix (such as "0x") is added to the string. If x is a nil
|
||||||
|
// pointer it returns "<nil>".
|
||||||
|
func (x *Int) Text(base int) string {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append appends the string representation of x, as generated by
|
||||||
|
// x.Text(base), to buf and returns the extended buffer.
|
||||||
|
func (x *Int) Append(buf []byte, base int) []byte {
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// String returns the decimal representation of x as generated by
|
||||||
|
// x.Text(10).
|
||||||
|
func (x *Int) String() string {
|
||||||
|
// TODO(xsw): can optimize it?
|
||||||
|
cstr := (*openssl.BIGNUM)(x).CStr()
|
||||||
|
ret := c.GoString(cstr)
|
||||||
|
openssl.FreeCStr(cstr)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Format implements fmt.Formatter. It accepts the formats
|
||||||
|
// 'b' (binary), 'o' (octal with 0 prefix), 'O' (octal with 0o prefix),
|
||||||
|
// 'd' (decimal), 'x' (lowercase hexadecimal), and
|
||||||
|
// 'X' (uppercase hexadecimal).
|
||||||
|
// Also supported are the full suite of package fmt's format
|
||||||
|
// flags for integral types, including '+' and ' ' for sign
|
||||||
|
// control, '#' for leading zero in octal and for hexadecimal,
|
||||||
|
// a leading "0x" or "0X" for "%#x" and "%#X" respectively,
|
||||||
|
// specification of minimum digits precision, output field
|
||||||
|
// width, space or zero padding, and '-' for left or right
|
||||||
|
// justification.
|
||||||
|
func (x *Int) Format(s fmt.State, ch rune) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan is a support routine for fmt.Scanner; it sets z to the value of
|
||||||
|
// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
|
||||||
|
// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
|
||||||
|
func (z *Int) Scan(s fmt.ScanState, ch rune) error {
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -98,11 +98,11 @@ type Once struct {
|
|||||||
func (o *Once) Do(f func()) {
|
func (o *Once) Do(f func()) {
|
||||||
if !o.done {
|
if !o.done {
|
||||||
o.m.Lock()
|
o.m.Lock()
|
||||||
defer o.m.Unlock()
|
|
||||||
if !o.done {
|
if !o.done {
|
||||||
o.done = true
|
o.done = true
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
o.m.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,14 +70,16 @@ func (w WaitStatus) StopSignal() Signal {
|
|||||||
return Signal(w>>shift) & 0xFF
|
return Signal(w>>shift) & 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO(xsw):
|
|
||||||
func (w WaitStatus) TrapCause() int {
|
func (w WaitStatus) TrapCause() int {
|
||||||
if w.StopSignal() != SIGTRAP {
|
/*
|
||||||
return -1
|
if w.StopSignal() != SIGTRAP {
|
||||||
}
|
return -1
|
||||||
return int(w>>shift) >> 8
|
}
|
||||||
|
|
||||||
|
return int(w>>shift) >> 8
|
||||||
|
*/
|
||||||
|
panic("todo: syscall.WaitStatus.TrapCause")
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *syscall.Rusage) (wpid int, err error) {
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *syscall.Rusage) (wpid int, err error) {
|
||||||
var status c.Int
|
var status c.Int
|
||||||
|
|||||||
@@ -154,6 +154,9 @@ func (b Builder) abiMethodOf(mPkg *types.Package, mName string, mSig *types.Sign
|
|||||||
|
|
||||||
func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signature, name, abiTyp, ifn llvm.Value) (ret Expr, tfn llvm.Value) {
|
func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signature, name, abiTyp, ifn llvm.Value) (ret Expr, tfn llvm.Value) {
|
||||||
fullName := FuncName(mPkg, mName, mSig.Recv())
|
fullName := FuncName(mPkg, mName, mSig.Recv())
|
||||||
|
if b.Pkg.fnlink != nil {
|
||||||
|
fullName = b.Pkg.fnlink(fullName)
|
||||||
|
}
|
||||||
tfn = b.Pkg.NewFunc(fullName, mSig, InGo).impl // TODO(xsw): use rawType to speed up
|
tfn = b.Pkg.NewFunc(fullName, mSig, InGo).impl // TODO(xsw): use rawType to speed up
|
||||||
if ifn.IsNil() {
|
if ifn.IsNil() {
|
||||||
ifn = tfn
|
ifn = tfn
|
||||||
@@ -411,6 +414,9 @@ func (b Builder) abiType(t types.Type) Expr {
|
|||||||
b.loadType(t.Elem())
|
b.loadType(t.Elem())
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
b.abiType(t.Elem())
|
b.abiType(t.Elem())
|
||||||
|
case *types.Map:
|
||||||
|
b.abiType(t.Key())
|
||||||
|
b.abiType(t.Elem())
|
||||||
}
|
}
|
||||||
g := b.loadType(t)
|
g := b.loadType(t)
|
||||||
return b.Load(g.Expr)
|
return b.Load(g.Expr)
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ func (b Builder) Defer(kind DoAction, fn Expr, args ...Expr) {
|
|||||||
case DeferAlways:
|
case DeferAlways:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
default:
|
default:
|
||||||
panic("todo: DeferInLoop is not supported")
|
panic("todo: DeferInLoop is not supported - " + b.Func.Name())
|
||||||
}
|
}
|
||||||
self.stmts = append(self.stmts, func(bits Expr) {
|
self.stmts = append(self.stmts, func(bits Expr) {
|
||||||
switch kind {
|
switch kind {
|
||||||
|
|||||||
@@ -586,6 +586,7 @@ type aPackage struct {
|
|||||||
named map[types.Type]Expr
|
named map[types.Type]Expr
|
||||||
afterb unsafe.Pointer
|
afterb unsafe.Pointer
|
||||||
patch func(types.Type) types.Type
|
patch func(types.Type) types.Type
|
||||||
|
fnlink func(string) string
|
||||||
|
|
||||||
iRoutine int
|
iRoutine int
|
||||||
}
|
}
|
||||||
@@ -658,6 +659,11 @@ func (p Package) SetPatch(fn func(types.Type) types.Type) {
|
|||||||
p.patch = fn
|
p.patch = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetResolveLinkname sets a function to resolve linkname.
|
||||||
|
func (p Package) SetResolveLinkname(fn func(string) string) {
|
||||||
|
p.fnlink = fn
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
func (p Package) afterBuilder() Builder {
|
func (p Package) afterBuilder() Builder {
|
||||||
|
|||||||
Reference in New Issue
Block a user