Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fc97794e8 | ||
|
|
df2ba37687 | ||
|
|
85b16b2a54 | ||
|
|
eeabc6b61a | ||
|
|
2b3dafed61 | ||
|
|
7232fc36ab | ||
|
|
a8e1fd1054 | ||
|
|
c248a50338 | ||
|
|
fa0ca23798 | ||
|
|
ed224cf912 | ||
|
|
b51df25371 | ||
|
|
db8cc8eb7b | ||
|
|
a027e9fe14 | ||
|
|
b882ca809a | ||
|
|
daf0a9dc9a | ||
|
|
f2dafa7544 | ||
|
|
7fe22875a6 | ||
|
|
3da3c8ecd8 | ||
|
|
1cf57508b0 | ||
|
|
f8bacfcc67 | ||
|
|
9daa77c1a4 | ||
|
|
c4775dd313 | ||
|
|
ae87cb031e | ||
|
|
3c049f25ee | ||
|
|
85a90b62b7 | ||
|
|
10b0124951 | ||
|
|
c0d7ff9543 | ||
|
|
74012d4869 | ||
|
|
830c40440f | ||
|
|
21a2f71ad9 | ||
|
|
cf75e3e664 | ||
|
|
ffc307323a | ||
|
|
ff0aec28c5 | ||
|
|
31394b03ae | ||
|
|
2ab93cb385 | ||
|
|
172b396dc9 | ||
|
|
9b82d08087 | ||
|
|
410617f73b | ||
|
|
ade0d38a7c | ||
|
|
3ce55a2ac4 | ||
|
|
cc6e4dbec0 | ||
|
|
2935ae7bf1 | ||
|
|
96e418e63b | ||
|
|
e4a84dcfe9 | ||
|
|
9ea91cfce3 | ||
|
|
8c7f0cf988 | ||
|
|
afa9a00259 | ||
|
|
a0ee11c300 | ||
|
|
6e02dace18 | ||
|
|
93bac6f26f | ||
|
|
8657fbd810 | ||
|
|
68203be004 | ||
|
|
b2323ef2e7 | ||
|
|
70b017fb72 | ||
|
|
607e3bbc11 | ||
|
|
315c9285de | ||
|
|
c22427b8fd | ||
|
|
2fcfac9e84 | ||
|
|
7cc857233f | ||
|
|
f85aa09784 | ||
|
|
0b0cecc2a9 | ||
|
|
3b5b9c9587 | ||
|
|
cbe190fa70 | ||
|
|
9156466351 | ||
|
|
f79caf095d | ||
|
|
d31dcd13fc | ||
|
|
552224bbfe | ||
|
|
5ba01674fb | ||
|
|
7390afc5e1 | ||
|
|
85ec23d552 | ||
|
|
007064c0ac | ||
|
|
fd53756170 | ||
|
|
9e6dd9f23d | ||
|
|
ef8be6c7c2 | ||
|
|
de4b5b70da | ||
|
|
9edeee4b3f | ||
|
|
767a0cc1fd | ||
|
|
ae09247e34 | ||
|
|
a3ea4798bc | ||
|
|
af54a22d16 | ||
|
|
b026bfc71b | ||
|
|
80d80ad8aa | ||
|
|
dbecf33924 | ||
|
|
2b08e3604d | ||
|
|
7d3a672c2b | ||
|
|
022e46ae38 | ||
|
|
3f930d228e | ||
|
|
5eba370f7b | ||
|
|
e138951e9e | ||
|
|
5cd18d7275 | ||
|
|
d7ff5a53a7 | ||
|
|
aa14bb6fdf | ||
|
|
c275f682a9 | ||
|
|
08894025bc | ||
|
|
b063a48520 | ||
|
|
858d38d314 | ||
|
|
f5875d09e9 | ||
|
|
34db181686 | ||
|
|
be55ea2b0b | ||
|
|
aa0dd4d10d | ||
|
|
39533e4209 | ||
|
|
4bba3bf1d2 | ||
|
|
2d29d1549a | ||
|
|
c7a078f17f | ||
|
|
2cf92037e9 | ||
|
|
452ee7a103 | ||
|
|
68f70af2f3 | ||
|
|
11682e487e | ||
|
|
4d006230f9 | ||
|
|
a32f4bb05c | ||
|
|
6d4e260127 | ||
|
|
45404b5bcf | ||
|
|
861551b2ba | ||
|
|
aac820a8d5 | ||
|
|
a5ff25b0fe | ||
|
|
b81638794f | ||
|
|
88cfeb2791 | ||
|
|
d0b57535ed | ||
|
|
528add4702 | ||
|
|
dd47971877 | ||
|
|
d51a99c8e2 | ||
|
|
e192f01dc3 | ||
|
|
aedaf57249 | ||
|
|
222e58e76e | ||
|
|
c8fc80f4a0 | ||
|
|
1ed180887d | ||
|
|
d6a38a567f | ||
|
|
ae9c3276bc | ||
|
|
35d34cd4e8 | ||
|
|
4f45824632 | ||
|
|
532da174dd | ||
|
|
dbe13feba2 | ||
|
|
1c93061a7f | ||
|
|
0e371930e6 | ||
|
|
06bd748bd6 | ||
|
|
b64775772b | ||
|
|
5f76314085 | ||
|
|
57588ea936 | ||
|
|
3f344b55bb | ||
|
|
e4ae0980b4 | ||
|
|
e41da0d697 | ||
|
|
ce3955d393 | ||
|
|
22a2cc564f | ||
|
|
2b19513a05 | ||
|
|
60f8fe6f41 | ||
|
|
a2fd010521 | ||
|
|
a36d5b6302 | ||
|
|
2c14dc16dd | ||
|
|
4c7f3f7972 | ||
|
|
794df59265 | ||
|
|
3dd71713c2 | ||
|
|
c0777d1a0a | ||
|
|
55392cb047 | ||
|
|
070eedda18 | ||
|
|
ae6ec78dc3 | ||
|
|
9fe1b2a565 | ||
|
|
f374419be3 | ||
|
|
0ff25cb116 | ||
|
|
d7e50f352a | ||
|
|
aa9254eeb0 | ||
|
|
c1eba336a8 | ||
|
|
a5d7fc484a | ||
|
|
7a294e6d4e | ||
|
|
2f79417d0d | ||
|
|
73b42f924d | ||
|
|
ccf915e798 | ||
|
|
62ffa14f10 | ||
|
|
5d7840a34c | ||
|
|
fd14f6ff73 | ||
|
|
88962f9358 | ||
|
|
5bec1729f1 | ||
|
|
f3662fc152 | ||
|
|
c5047186dd | ||
|
|
1e39bd8336 | ||
|
|
e58de234ac | ||
|
|
903cc181c4 | ||
|
|
2183a098c3 | ||
|
|
1d4cba9180 | ||
|
|
ed724c5280 | ||
|
|
fbd13ac42c | ||
|
|
ea6eab557b | ||
|
|
a1cb2a0589 | ||
|
|
5de5a8ca94 | ||
|
|
274026d338 | ||
|
|
3875bc34bd |
7
.github/workflows/go.yml
vendored
7
.github/workflows/go.yml
vendored
@@ -5,16 +5,17 @@ name: Go
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "main" ]
|
branches: [ "*" ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "main" ]
|
branches: [ "*" ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest, ubuntu-latest]
|
# os: [macos-latest, ubuntu-latest]
|
||||||
|
os: [macos-latest]
|
||||||
llvm: [18]
|
llvm: [18]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
40
.github/workflows/populate_darwin_sysroot.sh
vendored
Executable file
40
.github/workflows/populate_darwin_sysroot.sh
vendored
Executable file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TMPDIR="$(mktemp -d)"
|
||||||
|
export TMPDIR
|
||||||
|
trap 'rm -rf "${TMPDIR}"' EXIT
|
||||||
|
|
||||||
|
DARWIN_AMD64_LLVM_PREFIX=.sysroot/darwin/amd64/usr/local/opt/llvm@18
|
||||||
|
DARWIN_ARM64_LLVM_PREFIX=.sysroot/darwin/arm64/opt/homebrew/opt/llvm@18
|
||||||
|
mkdir -p "${DARWIN_AMD64_LLVM_PREFIX}" "${DARWIN_ARM64_LLVM_PREFIX}"
|
||||||
|
|
||||||
|
BREW_LLVM_FORMULA_JSON="$(mktemp)"
|
||||||
|
curl -fsSL https://formulae.brew.sh/api/formula/llvm.json > "${BREW_LLVM_FORMULA_JSON}"
|
||||||
|
BREW_LLVM_AMD64_BOTTLE_URL=$(jq -r '.bottle.stable.files.sonoma.url' "${BREW_LLVM_FORMULA_JSON}")
|
||||||
|
BREW_LLVM_ARM64_BOTTLE_URL=$(jq -r '.bottle.stable.files.arm64_sonoma.url' "${BREW_LLVM_FORMULA_JSON}")
|
||||||
|
curl -fsSL -H "Authorization: Bearer QQ==" "${BREW_LLVM_AMD64_BOTTLE_URL}" | tar -xzf - --strip-components=2 -C "${DARWIN_AMD64_LLVM_PREFIX}"
|
||||||
|
curl -fsSL -H "Authorization: Bearer QQ==" "${BREW_LLVM_ARM64_BOTTLE_URL}" | tar -xzf - --strip-components=2 -C "${DARWIN_ARM64_LLVM_PREFIX}"
|
||||||
|
|
||||||
|
patch_homebrew_lib_dir() {
|
||||||
|
local LIB_DIR="$1"
|
||||||
|
local HOMEBREW_PREFIX="$2"
|
||||||
|
for DYLIB_FILE in "${LIB_DIR}"/*.dylib; do
|
||||||
|
if [[ -f "${DYLIB_FILE}" ]]; then
|
||||||
|
ID=$(otool -D "${DYLIB_FILE}" | grep '@@HOMEBREW_PREFIX@@' | awk '{print $1}')
|
||||||
|
if [[ -n "${ID}" ]]; then
|
||||||
|
NEW_ID=${ID/'@@HOMEBREW_PREFIX@@'/${HOMEBREW_PREFIX}}
|
||||||
|
install_name_tool -id "${NEW_ID}" "${DYLIB_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEPS=$(otool -L "${DYLIB_FILE}" | grep '@@HOMEBREW_PREFIX@@' | awk '{print $1}')
|
||||||
|
for DEP in ${DEPS}; do
|
||||||
|
NEW_DEP=${DEP/'@@HOMEBREW_PREFIX@@'/${HOMEBREW_PREFIX}}
|
||||||
|
install_name_tool -change "${DEP}" "${NEW_DEP}" "${DYLIB_FILE}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
patch_homebrew_lib_dir "${DARWIN_AMD64_LLVM_PREFIX}/lib" /usr/lib
|
||||||
|
patch_homebrew_lib_dir "${DARWIN_ARM64_LLVM_PREFIX}/lib" /opt/homebrew
|
||||||
143
.github/workflows/populate_linux_sysroot.sh
vendored
Executable file
143
.github/workflows/populate_linux_sysroot.sh
vendored
Executable file
@@ -0,0 +1,143 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TMPDIR="$(mktemp -d)"
|
||||||
|
export TMPDIR
|
||||||
|
trap 'rm -rf "${TMPDIR}"' EXIT
|
||||||
|
|
||||||
|
LINUX_AMD64_PREFIX=.sysroot/linux/amd64
|
||||||
|
LINUX_ARM64_PREFIX=.sysroot/linux/arm64
|
||||||
|
mkdir -p "${LINUX_AMD64_PREFIX}" "${LINUX_ARM64_PREFIX}"
|
||||||
|
|
||||||
|
POPULATE_LINUX_SYSROOT_SCRIPT="$(mktemp)"
|
||||||
|
cat > "${POPULATE_LINUX_SYSROOT_SCRIPT}" << EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y lsb-release gnupg2 wget rsync
|
||||||
|
|
||||||
|
echo "deb http://apt.llvm.org/\$(lsb_release -cs)/ llvm-toolchain-\$(lsb_release -cs)-18 main" | tee /etc/apt/sources.list.d/llvm.list
|
||||||
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y llvm-18-dev
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "\$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
exclude_list=()
|
||||||
|
include_list=()
|
||||||
|
|
||||||
|
exclude_list+=(--exclude "/bin")
|
||||||
|
exclude_list+=(--exclude "/boot")
|
||||||
|
exclude_list+=(--exclude "/boot*")
|
||||||
|
exclude_list+=(--exclude "/dev")
|
||||||
|
exclude_list+=(--exclude "/etc")
|
||||||
|
exclude_list+=(--exclude "/home")
|
||||||
|
exclude_list+=(--exclude "/lib/dhcpd")
|
||||||
|
exclude_list+=(--exclude "/lib/firmware")
|
||||||
|
exclude_list+=(--exclude "/lib/hdparm")
|
||||||
|
exclude_list+=(--exclude "/lib/ifupdown")
|
||||||
|
exclude_list+=(--exclude "/lib/modules")
|
||||||
|
exclude_list+=(--exclude "/lib/modprobe.d")
|
||||||
|
exclude_list+=(--exclude "/lib/modules-load.d")
|
||||||
|
exclude_list+=(--exclude "/lib/resolvconf")
|
||||||
|
exclude_list+=(--exclude "/lib/startpar")
|
||||||
|
exclude_list+=(--exclude "/lib/systemd")
|
||||||
|
exclude_list+=(--exclude "/lib/terminfo")
|
||||||
|
exclude_list+=(--exclude "/lib/udev")
|
||||||
|
exclude_list+=(--exclude "/lib/xtables")
|
||||||
|
exclude_list+=(--exclude "/lib/ssl/private")
|
||||||
|
exclude_list+=(--exclude "/lost+found")
|
||||||
|
exclude_list+=(--exclude "/media")
|
||||||
|
exclude_list+=(--exclude "/mnt")
|
||||||
|
exclude_list+=(--exclude "/proc")
|
||||||
|
exclude_list+=(--exclude "/root")
|
||||||
|
exclude_list+=(--exclude "/run")
|
||||||
|
exclude_list+=(--exclude "/sbin")
|
||||||
|
exclude_list+=(--exclude "/srv")
|
||||||
|
exclude_list+=(--exclude "/sys")
|
||||||
|
exclude_list+=(--exclude "/tmp")
|
||||||
|
exclude_list+=(--exclude "/usr/bin")
|
||||||
|
exclude_list+=(--exclude "/usr/games")
|
||||||
|
exclude_list+=(--exclude "/usr/sbin")
|
||||||
|
exclude_list+=(--exclude "/usr/share")
|
||||||
|
exclude_list+=(--exclude "/usr/src")
|
||||||
|
exclude_list+=(--exclude "/usr/local/bin")
|
||||||
|
exclude_list+=(--exclude "/usr/local/etc")
|
||||||
|
exclude_list+=(--exclude "/usr/local/games")
|
||||||
|
exclude_list+=(--exclude "/usr/local/man")
|
||||||
|
exclude_list+=(--exclude "/usr/local/sbin")
|
||||||
|
exclude_list+=(--exclude "/usr/local/share")
|
||||||
|
exclude_list+=(--exclude "/usr/local/src")
|
||||||
|
exclude_list+=(--exclude "/usr/lib/ssl/private")
|
||||||
|
exclude_list+=(--exclude "/var")
|
||||||
|
exclude_list+=(--exclude "/snap")
|
||||||
|
exclude_list+=(--exclude "*python*")
|
||||||
|
|
||||||
|
include_list+=(--include "*.a")
|
||||||
|
include_list+=(--include "*.so")
|
||||||
|
include_list+=(--include "*.so.*")
|
||||||
|
include_list+=(--include "*.h")
|
||||||
|
include_list+=(--include "*.hh")
|
||||||
|
include_list+=(--include "*.hpp")
|
||||||
|
include_list+=(--include "*.hxx")
|
||||||
|
include_list+=(--include "*.pc")
|
||||||
|
include_list+=(--include "*.def")
|
||||||
|
include_list+=(--include "*.inc")
|
||||||
|
include_list+=(--include "/lib")
|
||||||
|
include_list+=(--include "/lib32")
|
||||||
|
include_list+=(--include "/lib64")
|
||||||
|
include_list+=(--include "/libx32")
|
||||||
|
include_list+=(--include "*/")
|
||||||
|
|
||||||
|
do-sync() {
|
||||||
|
from=\$1
|
||||||
|
to=\$2
|
||||||
|
|
||||||
|
args=()
|
||||||
|
args+=(-a)
|
||||||
|
args+=(-z)
|
||||||
|
args+=(-m)
|
||||||
|
args+=(-d)
|
||||||
|
args+=(-h)
|
||||||
|
args+=(--keep-dirlinks)
|
||||||
|
args+=("--info=progress2")
|
||||||
|
args+=(--delete)
|
||||||
|
args+=(--prune-empty-dirs)
|
||||||
|
args+=(--sparse)
|
||||||
|
args+=(--links)
|
||||||
|
args+=(--copy-unsafe-links)
|
||||||
|
args+=("\${exclude_list[@]}")
|
||||||
|
args+=("\${include_list[@]}")
|
||||||
|
args+=(--exclude "*")
|
||||||
|
args+=("\${from}")
|
||||||
|
args+=("\${to}")
|
||||||
|
|
||||||
|
echo "\${args[@]}"
|
||||||
|
rsync "\${args[@]}"
|
||||||
|
|
||||||
|
exit \$?
|
||||||
|
}
|
||||||
|
|
||||||
|
do-sync / /sysroot/
|
||||||
|
EOF
|
||||||
|
chmod +x "${POPULATE_LINUX_SYSROOT_SCRIPT}"
|
||||||
|
|
||||||
|
populate_linux_sysroot() {
|
||||||
|
local ARCH="$1"
|
||||||
|
local PREFIX="$2"
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
--platform "linux/${ARCH}" \
|
||||||
|
-v "$(pwd)/${PREFIX}":/sysroot \
|
||||||
|
-v "${POPULATE_LINUX_SYSROOT_SCRIPT}":/populate_linux_sysroot.sh \
|
||||||
|
debian:bullseye \
|
||||||
|
/populate_linux_sysroot.sh
|
||||||
|
}
|
||||||
|
populate_linux_sysroot amd64 "${LINUX_AMD64_PREFIX}"
|
||||||
|
populate_linux_sysroot arm64 "${LINUX_ARM64_PREFIX}"
|
||||||
58
.github/workflows/release-build.yml
vendored
Normal file
58
.github/workflows/release-build.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
name: Release Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
populate-darwin-sysroot:
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Populate Darwin sysroot
|
||||||
|
run: bash .github/workflows/populate_darwin_sysroot.sh
|
||||||
|
- name: Create Darwin sysroot tarball
|
||||||
|
run: tar -czvf .sysroot/darwin.tar.gz -C .sysroot darwin
|
||||||
|
- name: Upload Darwin sysroot tarball
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: darwin-sysroot-tarball
|
||||||
|
path: .sysroot/darwin.tar.gz
|
||||||
|
compression-level: 0
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: populate-darwin-sysroot
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.20.x
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
- name: Download Darwin sysroot tarball
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: darwin-sysroot-tarball
|
||||||
|
path: .sysroot
|
||||||
|
- name: Populate Darwin sysroot
|
||||||
|
run: tar -xzvf .sysroot/darwin.tar.gz -C .sysroot
|
||||||
|
- name: Populate Linux sysroot
|
||||||
|
run: bash .github/workflows/populate_linux_sysroot.sh
|
||||||
|
- name: Run GoReleaser
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{github.token}}
|
||||||
|
run: |
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
-e GITHUB_TOKEN=${GITHUB_TOKEN} \
|
||||||
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
|
-v $(pwd):/go/src/llgo \
|
||||||
|
-w /go/src/llgo \
|
||||||
|
ghcr.io/goreleaser/goreleaser-cross:v1.22 \
|
||||||
|
release --clean --skip nfpm,snapcraft
|
||||||
2
.github/workflows/test_demo.sh
vendored
2
.github/workflows/test_demo.sh
vendored
@@ -8,7 +8,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 -v "$d"; then
|
if ! llgo run "$d"; 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
@@ -4,7 +4,7 @@ set -e
|
|||||||
export LLGOROOT=$PWD
|
export LLGOROOT=$PWD
|
||||||
|
|
||||||
testcmd=/tmp/test
|
testcmd=/tmp/test
|
||||||
llgo build -o $testcmd ./_test
|
llgo build -o $testcmd ./c/bdwgc/_test
|
||||||
cases=$($testcmd)
|
cases=$($testcmd)
|
||||||
total=$(echo "$cases" | wc -l | tr -d ' ')
|
total=$(echo "$cases" | wc -l | tr -d ' ')
|
||||||
failed=0
|
failed=0
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -35,3 +35,7 @@ build.dir/
|
|||||||
|
|
||||||
# Go workspace file
|
# Go workspace file
|
||||||
go.work*
|
go.work*
|
||||||
|
|
||||||
|
# GoReleaser
|
||||||
|
.dist/
|
||||||
|
.sysroot/
|
||||||
|
|||||||
145
.goreleaser.yaml
Normal file
145
.goreleaser.yaml
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
dist: .dist
|
||||||
|
|
||||||
|
env:
|
||||||
|
- SYSROOT_DARWIN_AMD64={{.Env.PWD}}/.sysroot/darwin/amd64
|
||||||
|
- SYSROOT_DARWIN_ARM64={{.Env.PWD}}/.sysroot/darwin/arm64
|
||||||
|
- SYSROOT_LINUX_AMD64={{.Env.PWD}}/.sysroot/linux/amd64
|
||||||
|
- SYSROOT_LINUX_ARM64={{.Env.PWD}}/.sysroot/linux/arm64
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CGO_CXXFLAGS=-std=c++17
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod download
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- id: llgo-darwin-amd64
|
||||||
|
main: ./cmd/llgo
|
||||||
|
flags:
|
||||||
|
- -tags=darwin,amd64,byollvm
|
||||||
|
ldflags:
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/local/opt/llvm@18/bin/llvm-config
|
||||||
|
env:
|
||||||
|
- CC=o64-clang
|
||||||
|
- CXX=o64-clang++
|
||||||
|
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@18/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||||
|
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@18/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-18 -lz -lm
|
||||||
|
targets:
|
||||||
|
- darwin_amd64
|
||||||
|
mod_timestamp: "{{.CommitTimestamp}}"
|
||||||
|
- id: llgo-darwin-arm64
|
||||||
|
main: ./cmd/llgo
|
||||||
|
flags:
|
||||||
|
- -tags=darwin,arm64,byollvm
|
||||||
|
ldflags:
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/opt/homebrew/opt/llvm@18/bin/llvm-config
|
||||||
|
env:
|
||||||
|
- CC=oa64-clang
|
||||||
|
- CXX=oa64-clang++
|
||||||
|
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@18/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||||
|
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@18/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-18 -lz -lm
|
||||||
|
targets:
|
||||||
|
- darwin_arm64
|
||||||
|
mod_timestamp: "{{.CommitTimestamp}}"
|
||||||
|
- id: llgo-linux-amd64
|
||||||
|
main: ./cmd/llgo
|
||||||
|
flags:
|
||||||
|
- -tags=linux,amd64,byollvm
|
||||||
|
ldflags:
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
- CXX=x86_64-linux-gnu-g++
|
||||||
|
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -I{{.Env.SYSROOT_LINUX_AMD64}}/usr/include/llvm-18 -I{{.Env.SYSROOT_LINUX_AMD64}}/usr/include/llvm-c-18 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||||
|
- CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/usr/lib/llvm-18/lib -lLLVM-18
|
||||||
|
targets:
|
||||||
|
- linux_amd64
|
||||||
|
mod_timestamp: "{{.CommitTimestamp}}"
|
||||||
|
- id: llgo-linux-arm64
|
||||||
|
main: ./cmd/llgo
|
||||||
|
flags:
|
||||||
|
- -tags=linux,arm64,byollvm
|
||||||
|
ldflags:
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}}
|
||||||
|
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
- CXX=aarch64-linux-gnu-g++
|
||||||
|
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -I{{.Env.SYSROOT_LINUX_ARM64}}/usr/include/llvm-18 -I{{.Env.SYSROOT_LINUX_ARM64}}/usr/include/llvm-c-18 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||||
|
- CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/usr/lib/llvm-18/lib -lLLVM-18
|
||||||
|
targets:
|
||||||
|
- linux_arm64
|
||||||
|
mod_timestamp: "{{.CommitTimestamp}}"
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- format: tar.gz
|
||||||
|
name_template: >-
|
||||||
|
{{.ProjectName}}{{.Version}}.{{.Os}}-{{.Arch}}
|
||||||
|
{{- if .Arm}}v{{.Arm}}{{end}}
|
||||||
|
files:
|
||||||
|
- LICENSE
|
||||||
|
- README.md
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: "{{.ProjectName}}{{.Version}}.checksums.txt"
|
||||||
|
|
||||||
|
nfpms:
|
||||||
|
- package_name: llgo
|
||||||
|
vendor: goplus
|
||||||
|
homepage: https://github.com/goplus/llgo
|
||||||
|
maintainer: Aofei Sheng <aofei@aofeisheng.com>
|
||||||
|
description: |
|
||||||
|
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a
|
||||||
|
subproject of the Go+ project.
|
||||||
|
|
||||||
|
LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities such as:
|
||||||
|
|
||||||
|
- Game development
|
||||||
|
- AI and data science
|
||||||
|
- WebAssembly
|
||||||
|
- Embedded development
|
||||||
|
- ...
|
||||||
|
license: Apache-2.0
|
||||||
|
formats:
|
||||||
|
- deb
|
||||||
|
- rpm
|
||||||
|
file_name_template: >-
|
||||||
|
{{.ProjectName}}{{.Version}}.{{.Os}}-{{.Arch}}
|
||||||
|
{{- if .Arm}}v{{.Arm}}{{end}}
|
||||||
|
bindir: /usr/local/bin
|
||||||
|
|
||||||
|
snapcrafts:
|
||||||
|
- name: llgo
|
||||||
|
title: A Go compiler based on LLVM
|
||||||
|
summary: A Go compiler based on LLVM
|
||||||
|
description: |
|
||||||
|
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a
|
||||||
|
subproject of the Go+ project.
|
||||||
|
|
||||||
|
LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities such as:
|
||||||
|
|
||||||
|
- Game development
|
||||||
|
- AI and data science
|
||||||
|
- WebAssembly
|
||||||
|
- Embedded development
|
||||||
|
- ...
|
||||||
|
license: Apache-2.0
|
||||||
|
confinement: classic
|
||||||
|
name_template: >-
|
||||||
|
{{.ProjectName}}{{.Version}}.{{.Os}}-{{.Arch}}
|
||||||
|
{{- if .Arm}}v{{.Arm}}{{end}}
|
||||||
|
|
||||||
|
snapshot:
|
||||||
|
name_template: '{{trimprefix .Summary "v"}}'
|
||||||
|
|
||||||
|
release:
|
||||||
|
prerelease: auto
|
||||||
78
README.md
78
README.md
@@ -27,12 +27,13 @@ LLGo := Go + C + Python
|
|||||||
LLGo is compatible with C and Python through the language's **Application Binary Interface (ABI)**, while LLGo is compatible with Go through its **syntax (source code)**.
|
LLGo is compatible with C and Python through the language's **Application Binary Interface (ABI)**, while LLGo is compatible with Go through its **syntax (source code)**.
|
||||||
|
|
||||||
|
|
||||||
## C standard libary support
|
## C/C++ standard libary support
|
||||||
|
|
||||||
You can import a C standard library in LLGo!
|
You can import a C/C++ standard library in LLGo!
|
||||||
|
|
||||||
* [c](https://pkg.go.dev/github.com/goplus/llgo/c)
|
* [c](https://pkg.go.dev/github.com/goplus/llgo/c)
|
||||||
* [c/os](https://pkg.go.dev/github.com/goplus/llgo/c/os)
|
* [c/os](https://pkg.go.dev/github.com/goplus/llgo/c/os)
|
||||||
|
* [c/syscall](https://pkg.go.dev/github.com/goplus/llgo/c/syscall)
|
||||||
* [c/math](https://pkg.go.dev/github.com/goplus/llgo/c/math)
|
* [c/math](https://pkg.go.dev/github.com/goplus/llgo/c/math)
|
||||||
* [c/math/cmplx](https://pkg.go.dev/github.com/goplus/llgo/c/math/cmplx)
|
* [c/math/cmplx](https://pkg.go.dev/github.com/goplus/llgo/c/math/cmplx)
|
||||||
* [c/math/rand](https://pkg.go.dev/github.com/goplus/llgo/c/math/rand)
|
* [c/math/rand](https://pkg.go.dev/github.com/goplus/llgo/c/math/rand)
|
||||||
@@ -40,6 +41,8 @@ You can import a C standard library in LLGo!
|
|||||||
* [c/pthread/sync](https://pkg.go.dev/github.com/goplus/llgo/c/pthread/sync)
|
* [c/pthread/sync](https://pkg.go.dev/github.com/goplus/llgo/c/pthread/sync)
|
||||||
* [c/sync/atomic](https://pkg.go.dev/github.com/goplus/llgo/c/sync/atomic)
|
* [c/sync/atomic](https://pkg.go.dev/github.com/goplus/llgo/c/sync/atomic)
|
||||||
* [c/time](https://pkg.go.dev/github.com/goplus/llgo/c/time)
|
* [c/time](https://pkg.go.dev/github.com/goplus/llgo/c/time)
|
||||||
|
* [c/socket](https://pkg.go.dev/github.com/goplus/llgo/c/socket)
|
||||||
|
* [cpp/std](https://pkg.go.dev/github.com/goplus/llgo/cpp/std)
|
||||||
|
|
||||||
Here is a simple example:
|
Here is a simple example:
|
||||||
|
|
||||||
@@ -69,6 +72,45 @@ llgo run .
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## How support C/C++ and Python
|
||||||
|
|
||||||
|
LLGo use `go:linkname` to link an extern symbol througth its ABI:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import _ "unsafe" // for go:linkname
|
||||||
|
|
||||||
|
//go:linkname Sqrt C.sqrt
|
||||||
|
func Sqrt(x float64) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
You can directly integrate it into [your own code](_demo/linkname/linkname.go):
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe" // for go:linkname
|
||||||
|
|
||||||
|
//go:linkname Sqrt C.sqrt
|
||||||
|
func Sqrt(x float64) float64
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println("sqrt(2) =", Sqrt(2))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or put it into a package (see [c/math](c/math/math.go)):
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/c/math"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println("sqrt(2) =", math.Sqrt(2))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Python support
|
## Python support
|
||||||
|
|
||||||
You can import a Python library in LLGo!
|
You can import a Python library in LLGo!
|
||||||
@@ -172,9 +214,12 @@ The currently supported libraries include:
|
|||||||
* [c/cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson)
|
* [c/cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson)
|
||||||
* [c/clang](https://pkg.go.dev/github.com/goplus/llgo/c/clang)
|
* [c/clang](https://pkg.go.dev/github.com/goplus/llgo/c/clang)
|
||||||
* [c/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
* [c/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
||||||
|
* [c/lua](https://pkg.go.dev/github.com/goplus/llgo/c/lua)
|
||||||
|
* [c/neco](https://pkg.go.dev/github.com/goplus/llgo/c/neco)
|
||||||
* [c/raylib](https://pkg.go.dev/github.com/goplus/llgo/c/raylib)
|
* [c/raylib](https://pkg.go.dev/github.com/goplus/llgo/c/raylib)
|
||||||
* [c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
* [c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
||||||
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
||||||
|
* [cpp/inih](https://pkg.go.dev/github.com/goplus/llgo/cpp/inih)
|
||||||
|
|
||||||
Here are some examples related to them:
|
Here are some examples related to them:
|
||||||
|
|
||||||
@@ -186,7 +231,7 @@ Here are some examples related to them:
|
|||||||
|
|
||||||
## Go syntax support
|
## Go syntax support
|
||||||
|
|
||||||
All Go syntax is already supported. Here are some examples:
|
All Go syntax (not including `cgo`) is already supported. Here are some examples:
|
||||||
|
|
||||||
* [concat](_demo/concat/concat.go): define a variadic function
|
* [concat](_demo/concat/concat.go): define a variadic function
|
||||||
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
|
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
|
||||||
@@ -222,15 +267,21 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [math](https://pkg.go.dev/math)
|
* [math](https://pkg.go.dev/math)
|
||||||
* [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)
|
||||||
|
* [errors](https://pkg.go.dev/errors)
|
||||||
|
* [context](https://pkg.go.dev/context)
|
||||||
|
* [io](https://pkg.go.dev/io)
|
||||||
|
* [io/fs](https://pkg.go.dev/io/fs)
|
||||||
|
* [log](https://pkg.go.dev/log)
|
||||||
|
* [flag](https://pkg.go.dev/flag)
|
||||||
* [sort](https://pkg.go.dev/sort)
|
* [sort](https://pkg.go.dev/sort)
|
||||||
* [strconv](https://pkg.go.dev/strconv)
|
* [strconv](https://pkg.go.dev/strconv)
|
||||||
|
* [strings](https://pkg.go.dev/strings)
|
||||||
* [sync/atomic](https://pkg.go.dev/sync/atomic)
|
* [sync/atomic](https://pkg.go.dev/sync/atomic)
|
||||||
* [sync](https://pkg.go.dev/sync) (partially)
|
* [sync](https://pkg.go.dev/sync) (partially)
|
||||||
* [syscall](https://pkg.go.dev/syscall) (partially)
|
* [syscall](https://pkg.go.dev/syscall) (partially)
|
||||||
* [errors](https://pkg.go.dev/errors) (partially)
|
* [runtime](https://pkg.go.dev/runtime) (partially)
|
||||||
* [io](https://pkg.go.dev/io) (partially)
|
|
||||||
* [io/fs](https://pkg.go.dev/io/fs) (partially)
|
|
||||||
* [os](https://pkg.go.dev/os) (partially)
|
* [os](https://pkg.go.dev/os) (partially)
|
||||||
|
* [os/exec](https://pkg.go.dev/os/exec) (partially)
|
||||||
* [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)
|
||||||
@@ -259,10 +310,7 @@ brew update # execute if needed
|
|||||||
brew install llvm@18 pkg-config libgc
|
brew install llvm@18 pkg-config libgc
|
||||||
brew install cjson sqlite python@3.12 # optional
|
brew install cjson sqlite 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
|
export PATH=$(brew --prefix llvm@18)/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.zshrc
|
||||||
git clone https://github.com/goplus/llgo.git
|
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||||
cd llgo
|
|
||||||
export LLGOROOT="/path/to/llgo" # Replace this with the root directory of the llgo project
|
|
||||||
go install -v ./...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### on Linux (Debian/Ubuntu)
|
### on Linux (Debian/Ubuntu)
|
||||||
@@ -274,10 +322,7 @@ sudo apt-get update # execute if needed
|
|||||||
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev
|
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev
|
||||||
sudo apt-get install -y libcjson-dev libsqlite3-dev python3.12-dev # optional
|
sudo apt-get install -y libcjson-dev libsqlite3-dev 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
|
export PATH=/usr/lib/llvm-18/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.bashrc
|
||||||
git clone https://github.com/goplus/llgo.git
|
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||||
cd llgo
|
|
||||||
export LLGOROOT="/path/to/llgo" # Replace this with the root directory of the llgo project
|
|
||||||
go install -v ./...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### on Windows
|
### on Windows
|
||||||
@@ -296,8 +341,9 @@ TODO
|
|||||||
How do I generate these tools?
|
How do I generate these tools?
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export CC=clang CXX=clang++ # only for go build; optional if you have other compatible compilers
|
git clone https://github.com/goplus/llgo.git
|
||||||
go install -v ./... # compile all tools except pydump
|
cd llgo
|
||||||
|
go install -v ./chore/... # compile all tools except pydump
|
||||||
cd chore/_xtool
|
cd chore/_xtool
|
||||||
llgo install ./... # compile pydump
|
llgo install ./... # compile pydump
|
||||||
go install github.com/goplus/hdq/chore/pysigfetch@v0.8.1 # compile pysigfetch
|
go install github.com/goplus/hdq/chore/pysigfetch@v0.8.1 # compile pysigfetch
|
||||||
|
|||||||
19
_cmptest/_timeout/timer.go
Normal file
19
_cmptest/_timeout/timer.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var c chan int
|
||||||
|
|
||||||
|
func handle(int) {}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
select {
|
||||||
|
case m := <-c:
|
||||||
|
handle(m)
|
||||||
|
case <-time.After(10 * time.Second):
|
||||||
|
fmt.Println("timed out")
|
||||||
|
}
|
||||||
|
}
|
||||||
39
_cmptest/ctxcancel/ctx.go
Normal file
39
_cmptest/ctxcancel/ctx.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// gen generates integers in a separate goroutine and
|
||||||
|
// sends them to the returned channel.
|
||||||
|
// The callers of gen need to cancel the context once
|
||||||
|
// they are done consuming generated integers not to leak
|
||||||
|
// the internal goroutine started by gen.
|
||||||
|
gen := func(ctx context.Context) <-chan int {
|
||||||
|
dst := make(chan int)
|
||||||
|
n := 1
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return // returning not to leak the goroutine
|
||||||
|
case dst <- n:
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel() // cancel when we are finished consuming integers
|
||||||
|
|
||||||
|
for n := range gen(ctx) {
|
||||||
|
fmt.Println(n)
|
||||||
|
if n == 5 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
_cmptest/flagdemo/flagdemo.go
Normal file
21
_cmptest/flagdemo/flagdemo.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("args:", os.Args[1:])
|
||||||
|
if len(os.Args) == 1 {
|
||||||
|
os.Args = []string{"flagdemo", "-cpu", "100"}
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose := flag.Bool("v", false, "verbose")
|
||||||
|
cpu := flag.Int("cpu", 1, "cpu number")
|
||||||
|
host := flag.String("host", ":8888", "host")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
fmt.Println("host:", *host, "cpu:", *cpu, "verbose:", *verbose)
|
||||||
|
}
|
||||||
30
_cmptest/osproc/exec.go
Normal file
30
_cmptest/osproc/exec.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ls := "ls"
|
||||||
|
args := []string{ls, "-l"}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
ls = "dir"
|
||||||
|
args = []string{ls}
|
||||||
|
}
|
||||||
|
lspath, _ := exec.LookPath(ls)
|
||||||
|
if lspath != "" {
|
||||||
|
ls = lspath
|
||||||
|
}
|
||||||
|
proc, err := os.StartProcess(ls, args, &os.ProcAttr{
|
||||||
|
Files: []*os.File{nil, os.Stdout, os.Stderr},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("os.StartProcess error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
proc.Wait()
|
||||||
|
fmt.Println("proc.Wait done")
|
||||||
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println(strconv.Itoa(-123))
|
fmt.Println(strconv.Itoa(-123))
|
||||||
|
fmt.Println(strings.Split("abc,def,123", ","))
|
||||||
}
|
}
|
||||||
|
|||||||
11
_demo/cexec/exec.go
Normal file
11
_demo/cexec/exec.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ls := c.Str("ls")
|
||||||
|
os.Execlp(ls, ls, c.Str("-l"), nil)
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
77
_demo/fcntl/fcntl.go
Normal file
77
_demo/fcntl/fcntl.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
filename := c.Str("testfile.txt")
|
||||||
|
data := c.Str("Hello, os!")
|
||||||
|
var buffer [20]c.Char
|
||||||
|
|
||||||
|
// Open a file, O_CREAT|O_WRONLY|O_TRUNC means create, write only, or clear the file
|
||||||
|
fd := os.Open(filename, os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||||
|
if fd == -1 {
|
||||||
|
c.Printf(c.Str("open error\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writing data to a file
|
||||||
|
bytesWritten := os.Write(fd, c.Pointer(data), c.Strlen(data))
|
||||||
|
if bytesWritten == -1 {
|
||||||
|
c.Printf(c.Str("write error\n"))
|
||||||
|
os.Close(fd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("Written %ld bytes to %s\n"), bytesWritten, filename)
|
||||||
|
|
||||||
|
// Get file status flags
|
||||||
|
flags := os.Fcntl(fd, os.F_GETFL)
|
||||||
|
if flags == -1 {
|
||||||
|
c.Printf(c.Str("os error\n"))
|
||||||
|
os.Close(fd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("File flags: %d\n"), flags)
|
||||||
|
|
||||||
|
// Set the file status flag to non-blocking mode
|
||||||
|
if os.Fcntl(fd, os.F_SETFL, flags|os.O_NONBLOCK) == -1 {
|
||||||
|
c.Printf(c.Str("os error\n"))
|
||||||
|
os.Close(fd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("set file status successfully\n"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
c.Printf(c.Str("111"))
|
||||||
|
// Close file
|
||||||
|
os.Close(fd)
|
||||||
|
|
||||||
|
// Reopen the file, O_RDONLY means read-only
|
||||||
|
fd = os.Open(filename, os.O_RDONLY)
|
||||||
|
if fd == -1 {
|
||||||
|
c.Printf(c.Str("open error\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reading data from a file
|
||||||
|
// &buffer[:][0]
|
||||||
|
// unsafe.SliceData(buffer[:])
|
||||||
|
bytesRead := os.Read(fd, c.Pointer(unsafe.SliceData(buffer[:])), unsafe.Sizeof(buffer)-1)
|
||||||
|
if bytesRead == -1 {
|
||||||
|
c.Printf(c.Str("read error\n"))
|
||||||
|
os.Close(fd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the buffer is null-terminated
|
||||||
|
buffer[bytesRead] = c.Char(0)
|
||||||
|
c.Printf(c.Str("Read %ld bytes: %s\n"), bytesRead, &buffer[0])
|
||||||
|
|
||||||
|
// Close file
|
||||||
|
os.Close(fd)
|
||||||
|
}
|
||||||
@@ -9,5 +9,5 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Expected output:
|
/* Expected output:
|
||||||
Hello World
|
Hello world
|
||||||
*/
|
*/
|
||||||
|
|||||||
10
_demo/linkname/linkname.go
Normal file
10
_demo/linkname/linkname.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe" // for go:linkname
|
||||||
|
|
||||||
|
//go:linkname Sqrt C.sqrt
|
||||||
|
func Sqrt(x float64) float64
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println("sqrt(2) =", Sqrt(2))
|
||||||
|
}
|
||||||
9
_demo/logdemo/log.go
Normal file
9
_demo/logdemo/log.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.Println("Hello")
|
||||||
|
}
|
||||||
18
_demo/osexec/exec.go
Normal file
18
_demo/osexec/exec.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ls := "ls"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
ls = "dir"
|
||||||
|
}
|
||||||
|
cmd := exec.Command(ls)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Run()
|
||||||
|
}
|
||||||
19
_demo/oslookpath/lookpath.go
Normal file
19
_demo/oslookpath/lookpath.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ls := "ls"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
ls = "dir"
|
||||||
|
}
|
||||||
|
lspath, _ := exec.LookPath(ls)
|
||||||
|
if lspath != "" {
|
||||||
|
ls = lspath
|
||||||
|
}
|
||||||
|
fmt.Println(ls)
|
||||||
|
}
|
||||||
32
_demo/socket/client/client.go
Normal file
32
_demo/socket/client/client.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
"github.com/goplus/llgo/c/socket"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sockfd := socket.Socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
msg := c.Str("Hello, World!")
|
||||||
|
defer os.Close(sockfd)
|
||||||
|
|
||||||
|
server := socket.GetHostByName(c.Str("localhost"))
|
||||||
|
if server == nil {
|
||||||
|
c.Perror(c.Str("hostname get error"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
servAddr := &socket.SockaddrIn{}
|
||||||
|
servAddr.Family = socket.AF_INET
|
||||||
|
servAddr.Port = socket.Htons(uint16(1234))
|
||||||
|
c.Memcpy(unsafe.Pointer(&servAddr.Addr.Addr), unsafe.Pointer(*server.AddrList), uintptr(server.Length))
|
||||||
|
|
||||||
|
if res := socket.Connect(sockfd, (*socket.SockAddr)(unsafe.Pointer(servAddr)), c.Uint(16)); res < 0 {
|
||||||
|
c.Perror(c.Str("connect error"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
os.Write(sockfd, unsafe.Pointer(msg), c.Strlen(msg))
|
||||||
|
}
|
||||||
43
_demo/socket/server/server.go
Normal file
43
_demo/socket/server/server.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
"github.com/goplus/llgo/c/socket"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var buffer [256]c.Char
|
||||||
|
|
||||||
|
sockfd := socket.Socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
defer os.Close(sockfd)
|
||||||
|
|
||||||
|
servAddr := &socket.SockaddrIn{
|
||||||
|
Family: socket.AF_INET,
|
||||||
|
Port: socket.Htons(uint16(1234)),
|
||||||
|
Addr: socket.InAddr{Addr: 0x00000000},
|
||||||
|
Zero: [8]c.Char{0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
}
|
||||||
|
if res := socket.Bind(sockfd, servAddr, c.Uint(unsafe.Sizeof(*servAddr))); res < 0 {
|
||||||
|
c.Perror(c.Str("bind error"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if socket.Listen(sockfd, 5) < 0 {
|
||||||
|
c.Printf(c.Str("listen error"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("Listening on port 1234...\n"))
|
||||||
|
|
||||||
|
cliAddr, clilen := &socket.SockaddrIn{}, c.Uint(unsafe.Sizeof(servAddr))
|
||||||
|
|
||||||
|
newsockfd := socket.Accept(sockfd, cliAddr, &clilen)
|
||||||
|
defer os.Close(newsockfd)
|
||||||
|
c.Printf(c.Str("Connection accepted."))
|
||||||
|
|
||||||
|
os.Read(newsockfd, unsafe.Pointer(unsafe.SliceData(buffer[:])), 256)
|
||||||
|
c.Printf(c.Str("Received: %s"), &buffer[0])
|
||||||
|
|
||||||
|
}
|
||||||
26
_demo/sysexec/exec.go
Normal file
26
_demo/sysexec/exec.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ls := "ls"
|
||||||
|
args := []string{ls, "-l"}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
ls = "dir"
|
||||||
|
args = []string{ls}
|
||||||
|
}
|
||||||
|
lspath, _ := exec.LookPath(ls)
|
||||||
|
if lspath != "" {
|
||||||
|
ls = lspath
|
||||||
|
}
|
||||||
|
err := syscall.Exec(ls, args, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("syscall.Exec error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
11
_demo/timedur/timedur.go
Normal file
11
_demo/timedur/timedur.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := time.Now().Add(time.Second * 5)
|
||||||
|
fmt.Println(time.Until(t))
|
||||||
|
}
|
||||||
@@ -3,9 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/_test/testing"
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/bdwgc"
|
"github.com/goplus/llgo/c/bdwgc"
|
||||||
|
"github.com/goplus/llgo/c/bdwgc/_test/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ------ Test malloc ------
|
// ------ Test malloc ------
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/goplus/llgo/_test/testing"
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/bdwgc/_test/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
Binary file not shown.
Binary file not shown.
12
c/c.go
12
c/c.go
@@ -68,6 +68,9 @@ func Alloca(size uintptr) Pointer
|
|||||||
//go:linkname AllocaCStr llgo.allocaCStr
|
//go:linkname AllocaCStr llgo.allocaCStr
|
||||||
func AllocaCStr(s string) *Char
|
func AllocaCStr(s string) *Char
|
||||||
|
|
||||||
|
//go:linkname AllocaCStrs llgo.allocaCStrs
|
||||||
|
func AllocaCStrs(strs []string, endWithNil bool) **Char
|
||||||
|
|
||||||
// TODO(xsw):
|
// TODO(xsw):
|
||||||
// llgo:link AllocaNew llgo.allocaNew
|
// llgo:link AllocaNew llgo.allocaNew
|
||||||
func AllocaNew[T any]() *T { return nil }
|
func AllocaNew[T any]() *T { return nil }
|
||||||
@@ -212,6 +215,15 @@ func Fputs(s *Char, fp FilePtr) Int
|
|||||||
//go:linkname Fflush C.fflush
|
//go:linkname Fflush C.fflush
|
||||||
func Fflush(fp FilePtr) Int
|
func Fflush(fp FilePtr) Int
|
||||||
|
|
||||||
|
//go:linkname Fopen C.fopen
|
||||||
|
func Fopen(c *Char, mod *Char) FilePtr
|
||||||
|
|
||||||
|
//go:linkname Fclose C.fclose
|
||||||
|
func Fclose(fp FilePtr) Int
|
||||||
|
|
||||||
|
//go:linkname Perror C.perror
|
||||||
|
func Perror(s *Char)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Time C.time
|
//go:linkname Time C.time
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/clang"
|
"github.com/goplus/llgo/c/clang"
|
||||||
)
|
)
|
||||||
@@ -13,6 +16,7 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
|
|||||||
|
|
||||||
func printAST(cursor clang.Cursor, depth c.Uint) {
|
func printAST(cursor clang.Cursor, depth c.Uint) {
|
||||||
cursorKind := cursor.Kind.String()
|
cursorKind := cursor.Kind.String()
|
||||||
|
|
||||||
cursorSpelling := cursor.String()
|
cursorSpelling := cursor.String()
|
||||||
|
|
||||||
for i := c.Uint(0); i < depth; i++ {
|
for i := c.Uint(0); i < depth; i++ {
|
||||||
@@ -28,9 +32,16 @@ func printAST(cursor clang.Cursor, depth c.Uint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
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)
|
index := clang.CreateIndex(0, 0)
|
||||||
|
|
||||||
unit := index.ParseTranslationUnit(
|
unit := index.ParseTranslationUnit(
|
||||||
c.Str("todo"),
|
sourceFile,
|
||||||
nil, 0,
|
nil, 0,
|
||||||
nil, 0,
|
nil, 0,
|
||||||
clang.TranslationUnit_None,
|
clang.TranslationUnit_None,
|
||||||
@@ -42,6 +53,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cursor := unit.Cursor()
|
cursor := unit.Cursor()
|
||||||
|
|
||||||
printAST(cursor, 0)
|
printAST(cursor, 0)
|
||||||
|
|
||||||
unit.Dispose()
|
unit.Dispose()
|
||||||
|
|||||||
29
c/clang/_wrap/cursor.cpp
Normal file
29
c/clang/_wrap/cursor.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <clang-c/Index.h>
|
||||||
|
|
||||||
|
typedef enum CXChildVisitResult(* wrap_CXCursorVisitor) (CXCursor *cursor, CXCursor *parent, CXClientData client_data);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CXClientData data;
|
||||||
|
wrap_CXCursorVisitor visitor;
|
||||||
|
} wrap_data;
|
||||||
|
|
||||||
|
CXChildVisitResult wrap_visitor(CXCursor cursor, CXCursor parent, CXClientData data) {
|
||||||
|
wrap_data *d = (wrap_data*)(data);
|
||||||
|
return d->visitor(&cursor,&parent,d->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
CXString wrap_clang_getCursorSpelling(CXCursor *cur) {
|
||||||
|
return clang_getCursorSpelling(*cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned wrap_clang_visitChildren(CXCursor *parent,
|
||||||
|
wrap_CXCursorVisitor visitor,
|
||||||
|
CXClientData client_data) {
|
||||||
|
wrap_data data = {client_data,visitor};
|
||||||
|
return clang_visitChildren(*parent,wrap_visitor,CXClientData(&data));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
7
c/clang/_wrap/llgo_check.cpp
Normal file
7
c/clang/_wrap/llgo_check.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <clang-c/Index.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("sizeof(clang.Cursor) = %lu\n", sizeof(CXCursor));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
16
c/clang/_wrap/llgo_check.go
Normal file
16
c/clang/_wrap/llgo_check.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/clang"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoCFlags = "-I$(llvm-config --includedir)"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.Str("sizeof(clang.Cursor) = %lu\n"), unsafe.Sizeof(clang.Cursor{}))
|
||||||
|
}
|
||||||
@@ -38,13 +38,13 @@ type String struct {
|
|||||||
/**
|
/**
|
||||||
* Retrieve the character data associated with the given string.
|
* Retrieve the character data associated with the given string.
|
||||||
*/
|
*/
|
||||||
// llgo:link C.clang_getCString
|
// llgo:link String.CStr C.clang_getCString
|
||||||
func (String) CStr() *c.Char { return nil }
|
func (String) CStr() *c.Char { return nil }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free the given string.
|
* Free the given string.
|
||||||
*/
|
*/
|
||||||
// llgo:link C.clang_disposeString
|
// llgo:link String.Dispose C.clang_disposeString
|
||||||
func (String) Dispose() {}
|
func (String) Dispose() {}
|
||||||
|
|
||||||
type StringSet struct {
|
type StringSet struct {
|
||||||
@@ -55,5 +55,5 @@ type StringSet struct {
|
|||||||
/**
|
/**
|
||||||
* Free the given string set.
|
* Free the given string set.
|
||||||
*/
|
*/
|
||||||
// llgo:link C.clang_disposeStringSet
|
// llgo:link (*StringSet).Dispose C.clang_disposeStringSet
|
||||||
func (*StringSet) Dispose() {}
|
func (*StringSet) Dispose() {}
|
||||||
|
|||||||
@@ -17,12 +17,13 @@
|
|||||||
package clang
|
package clang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
LLGoFiles = "$(llvm-config --cflags): _wrap/cursor.cpp"
|
||||||
LLGoPackage = "link: -L$(llvm-config --libdir) -lclang; -lclang"
|
LLGoPackage = "link: -L$(llvm-config --libdir) -lclang; -lclang"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ type TranslationUnit struct {
|
|||||||
/**
|
/**
|
||||||
* Destroy the specified CXTranslationUnit object.
|
* Destroy the specified CXTranslationUnit object.
|
||||||
*/
|
*/
|
||||||
// llgo:linke (*TranslationUnit).Dispose C.clang_disposeTranslationUnit
|
// llgo:link (*TranslationUnit).Dispose C.clang_disposeTranslationUnit
|
||||||
func (*TranslationUnit) Dispose() {}
|
func (*TranslationUnit) Dispose() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,7 +173,7 @@ func (*TranslationUnit) Cursor() (ret Cursor) {
|
|||||||
type CursorKind c.Int
|
type CursorKind c.Int
|
||||||
|
|
||||||
/* for debug/testing */
|
/* for debug/testing */
|
||||||
// llgo:link (CursorKind).String C.clang_getCursorKindSpelling
|
// llgo:link CursorKind.String C.clang_getCursorKindSpelling
|
||||||
func (CursorKind) String() (ret String) {
|
func (CursorKind) String() (ret String) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -204,11 +205,15 @@ type Cursor struct {
|
|||||||
/**
|
/**
|
||||||
* Retrieve a name for the entity referenced by this cursor.
|
* Retrieve a name for the entity referenced by this cursor.
|
||||||
*/
|
*/
|
||||||
// llgo:link C.clang_getCursorSpelling
|
// llgo:link (*Cursor).wrapString C.wrap_clang_getCursorSpelling
|
||||||
func (Cursor) String() (ret String) {
|
func (*Cursor) wrapString() (ret String) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Cursor) String() (ret String) {
|
||||||
|
return c.wrapString()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes how the traversal of the children of a particular
|
* Describes how the traversal of the children of a particular
|
||||||
* cursor should proceed after visiting a particular child cursor.
|
* cursor should proceed after visiting a particular child cursor.
|
||||||
@@ -257,10 +262,31 @@ const (
|
|||||||
* \returns a non-zero value if the traversal was terminated
|
* \returns a non-zero value if the traversal was terminated
|
||||||
* prematurely by the visitor returning \c CXChildVisit_Break.
|
* prematurely by the visitor returning \c CXChildVisit_Break.
|
||||||
*/
|
*/
|
||||||
//go:linkname VisitChildren C.clang_visitChildren
|
//go:linkname wrapVisitChildren C.wrap_clang_visitChildren
|
||||||
func VisitChildren(
|
func wrapVisitChildren(
|
||||||
cusor Cursor,
|
cusor *Cursor,
|
||||||
visitor func(cursor, parent Cursor, clientData ClientData) ChildVisitResult,
|
fn wrapVisitor,
|
||||||
clientData ClientData) c.Uint {
|
clientData ClientData) c.Uint {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//llgo:type C
|
||||||
|
type wrapVisitor func(cursor, parent *Cursor, clientData ClientData) ChildVisitResult
|
||||||
|
|
||||||
|
type wrapData struct {
|
||||||
|
data ClientData
|
||||||
|
fn Visitor
|
||||||
|
}
|
||||||
|
|
||||||
|
func VisitChildren(
|
||||||
|
root Cursor,
|
||||||
|
fn Visitor,
|
||||||
|
clientData ClientData) c.Uint {
|
||||||
|
return wrapVisitChildren(&root, func(cursor, parent *Cursor, data ClientData) ChildVisitResult {
|
||||||
|
p := (*wrapData)(data)
|
||||||
|
return p.fn(*cursor, *parent, p.data)
|
||||||
|
}, unsafe.Pointer(&wrapData{clientData, fn}))
|
||||||
|
}
|
||||||
|
|
||||||
|
//llgo:type C
|
||||||
|
type Visitor func(cursor, parent Cursor, clientData ClientData) ChildVisitResult
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
60
c/lua/_demo/coroutine/coroutine.go
Normal file
60
c/lua/_demo/coroutine/coroutine.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func coroutineFunc(L *lua.State) {
|
||||||
|
L.Loadstring(c.Str(`
|
||||||
|
function coro_func()
|
||||||
|
for i = 1, 5 do
|
||||||
|
coroutine.yield(i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`))
|
||||||
|
L.Pcall(0, 0, 0)
|
||||||
|
L.Getglobal(c.Str("coro_func"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
|
||||||
|
coroutineFunc(L) // Load and get the coroutine function
|
||||||
|
|
||||||
|
co := L.Newthread() // Create a new coroutine/thread
|
||||||
|
L.Pushvalue(-2) // Move the function to the top of the stack
|
||||||
|
L.Xmove(co, 1) // Move the function to the new coroutine
|
||||||
|
|
||||||
|
var nres c.Int
|
||||||
|
var status c.Int
|
||||||
|
|
||||||
|
c.Printf(c.Str("Resuming coroutine...\n"))
|
||||||
|
// Resume coroutine and handle yields
|
||||||
|
for {
|
||||||
|
status = co.Resume(nil, 0, &nres)
|
||||||
|
c.Printf(c.Str("Resuming coroutine %d...\n"), status)
|
||||||
|
if status == lua.YIELD {
|
||||||
|
yieldValue := co.Tointeger(-1)
|
||||||
|
c.Printf(c.Str("Yield value: %d\n"), yieldValue)
|
||||||
|
co.Pop(1) // Clean up the stack
|
||||||
|
|
||||||
|
// Check if the coroutine is yieldable
|
||||||
|
if co.Isyieldable() != 0 {
|
||||||
|
c.Printf(c.Str("Coroutine is yieldable.\n"))
|
||||||
|
} else {
|
||||||
|
c.Printf(c.Str("Coroutine is not yieldable.\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the final status of the coroutine
|
||||||
|
finalStatus := co.Status()
|
||||||
|
c.Printf(c.Str("Final status of coroutine: %d\n"), finalStatus)
|
||||||
|
}
|
||||||
21
c/lua/_demo/error/error.go
Normal file
21
c/lua/_demo/error/error.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
L.Openlibs()
|
||||||
|
if res := L.Loadstring(c.Str("function doubleNumber(x) ! return x * 2 end")); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
error: [string "function doubleNumber(x) ! return x * 2 end"]:1: unexpected symbol near '!'
|
||||||
|
*/
|
||||||
32
c/lua/_demo/funccall-concat/funccall.go
Normal file
32
c/lua/_demo/funccall-concat/funccall.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
if res := L.Dostring(c.Str("function combineParams(num, str) return 'Result: ' .. str .. ' ' .. num end")); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
L.Getglobal(c.Str("combineParams"))
|
||||||
|
L.Pushnumber(3.14159)
|
||||||
|
L.Pushstring(c.Str("Hello, World!"))
|
||||||
|
if res := L.Pcall(2, 1, 0); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
if res := L.Isstring(-1); res != 0 {
|
||||||
|
result := L.Tostring(-1)
|
||||||
|
c.Printf(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
Result: Hello, World! 3.14159
|
||||||
|
*/
|
||||||
39
c/lua/_demo/funccall-number/funccall.go
Normal file
39
c/lua/_demo/funccall-number/funccall.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
if res := L.Loadstring(c.Str("function doubleNumber(x) return x * 2 end")); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
if res := L.Pcall(0, 0, 0); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
L.Getglobal(c.Str("doubleNumber"))
|
||||||
|
L.Pushnumber(10)
|
||||||
|
|
||||||
|
if res := L.Pcall(1, 1, 0); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
if res := L.Isnumber(-1); res != 0 {
|
||||||
|
result := L.Tointeger(-1)
|
||||||
|
c.Printf(c.Str("result: %lld\n"), result)
|
||||||
|
} else {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
result: 20
|
||||||
|
*/
|
||||||
48
c/lua/_demo/funccall-string/funccall.go
Normal file
48
c/lua/_demo/funccall-string/funccall.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
code := c.Str(
|
||||||
|
`function processStrings(a, b, c)
|
||||||
|
print('Received string a: ' .. a)
|
||||||
|
print('Received string b: ', b)
|
||||||
|
print('Received string c (formatted): ' .. c)
|
||||||
|
return a .. b .. c
|
||||||
|
end`)
|
||||||
|
|
||||||
|
if res := L.Dostring(code); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
L.Getglobal(c.Str("processStrings"))
|
||||||
|
|
||||||
|
L.Pushstring(c.Str("Hello, World!"))
|
||||||
|
L.Pushlstring(c.Str(`Hello Lua In LLGO`), 17)
|
||||||
|
L.Pushfstring(c.Str(`Hello %s In %d`), c.Str("LLGO"), 2024)
|
||||||
|
|
||||||
|
if res := L.Pcall(3, 1, 0); res != lua.OK {
|
||||||
|
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
if res := L.Isstring(-1); res != 0 {
|
||||||
|
result := L.Tostring(-1)
|
||||||
|
c.Printf(c.Str("result: %s\n"), result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
Received string a: Hello, World!
|
||||||
|
Received string b: Hello Lua In LLGO
|
||||||
|
Received string c (formatted): Hello LLGO In 2024
|
||||||
|
result: Hello, World!Hello Lua In LLGOHello LLGO In 2024
|
||||||
|
*/
|
||||||
21
c/lua/_demo/hello/hello.go
Normal file
21
c/lua/_demo/hello/hello.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
L.Openlibs()
|
||||||
|
if res := L.Dostring(c.Str("print('hello world')")); res != lua.OK {
|
||||||
|
println("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
hello world
|
||||||
|
*/
|
||||||
26
c/lua/_demo/loadcall/loadcall.go
Normal file
26
c/lua/_demo/loadcall/loadcall.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
if res := L.Loadstring(c.Str("print('hello world')")); res != lua.OK {
|
||||||
|
println("error")
|
||||||
|
}
|
||||||
|
if res := L.Pcall(0, 0, 0); res != lua.OK {
|
||||||
|
println("error")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
hello world
|
||||||
|
*/
|
||||||
104
c/lua/_demo/stack/stack.go
Normal file
104
c/lua/_demo/stack/stack.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
// printStack prints the current stack of the given Lua state.
|
||||||
|
func printStack(L *lua.State, stateName *c.Char) {
|
||||||
|
top := L.Gettop()
|
||||||
|
c.Printf(c.Str("%s stack (top=%d):"), stateName, top)
|
||||||
|
for i := 1; i <= int(top); i++ {
|
||||||
|
c.Printf(c.Str("%s "), L.Tostring(c.Int(i)))
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Create a new Lua state and open libraries
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
L.Openlibs()
|
||||||
|
|
||||||
|
// Push initial values onto the stack
|
||||||
|
L.Pushstring(c.Str("Hello"))
|
||||||
|
L.Pushstring(c.Str("LLGO"))
|
||||||
|
L.Pushnumber(2024)
|
||||||
|
|
||||||
|
// Print initial stack
|
||||||
|
c.Printf(c.Str("Initial stack:\n"))
|
||||||
|
printStack(L, c.Str("L1"))
|
||||||
|
|
||||||
|
// Use absindex to ensure the index is positive
|
||||||
|
idx := -2
|
||||||
|
absIdx := L.Absindex(c.Int(idx))
|
||||||
|
c.Printf(c.Str("Absolute index of 'LLGO': %d\n"), absIdx)
|
||||||
|
|
||||||
|
// Copy 'LLGO' to the top of the stack
|
||||||
|
L.Pushvalue(absIdx)
|
||||||
|
c.Printf(c.Str("\nAfter pushing 'LLGO' to the top:\n"))
|
||||||
|
printStack(L, c.Str("L1"))
|
||||||
|
|
||||||
|
// Rotate stack elements
|
||||||
|
L.Rotate(c.Int(1), c.Int(-1))
|
||||||
|
c.Printf(c.Str("\nAfter rotating the stack:\n"))
|
||||||
|
printStack(L, c.Str("L1"))
|
||||||
|
|
||||||
|
// Copy the top element to index 2
|
||||||
|
L.Copy(c.Int(-1), c.Int(2))
|
||||||
|
c.Printf(c.Str("\nAfter copying the top element to index 2:\n"))
|
||||||
|
printStack(L, c.Str("L1"))
|
||||||
|
|
||||||
|
// Check if we can grow the stack
|
||||||
|
if L.Checkstack(c.Int(2)) == 0 {
|
||||||
|
c.Printf(c.Str("Cannot grow stack\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push additional elements
|
||||||
|
L.Pushnumber(3.14)
|
||||||
|
L.Pushstring(c.Str("Lua"))
|
||||||
|
c.Printf(c.Str("\nAfter pushing more elements:\n"))
|
||||||
|
printStack(L, c.Str("L1"))
|
||||||
|
|
||||||
|
// Set the top of the stack, clearing extra elements
|
||||||
|
L.Settop(c.Int(5))
|
||||||
|
c.Printf(c.Str("\nAfter setting top to 5:\n"))
|
||||||
|
printStack(L, c.Str("L1"))
|
||||||
|
|
||||||
|
// Create a second Lua state
|
||||||
|
L1 := lua.Newstate()
|
||||||
|
defer L1.Close()
|
||||||
|
|
||||||
|
// Move two elements to the new state
|
||||||
|
L.Xmove(L1, c.Int(2))
|
||||||
|
c.Printf(c.Str("\nAfter moving two elements to L1:\n"))
|
||||||
|
printStack(L, c.Str("L1"))
|
||||||
|
printStack(L1, c.Str("L2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
Initial stack:
|
||||||
|
L1 stack (top=3):Hello LLGO 2024.0
|
||||||
|
Absolute index of 'LLGO': 2
|
||||||
|
|
||||||
|
After pushing 'LLGO' to the top:
|
||||||
|
L1 stack (top=4):Hello LLGO 2024.0 LLGO
|
||||||
|
|
||||||
|
After rotating the stack:
|
||||||
|
L1 stack (top=4):LLGO 2024.0 LLGO Hello
|
||||||
|
|
||||||
|
After copying the top element to index 2:
|
||||||
|
L1 stack (top=4):LLGO Hello LLGO Hello
|
||||||
|
|
||||||
|
After pushing more elements:
|
||||||
|
L1 stack (top=6):LLGO Hello LLGO Hello 3.14 Lua
|
||||||
|
|
||||||
|
After setting top to 5:
|
||||||
|
L1 stack (top=5):LLGO Hello LLGO Hello 3.14
|
||||||
|
|
||||||
|
After moving two elements to L1:
|
||||||
|
L1 stack (top=3):LLGO Hello LLGO
|
||||||
|
L2 stack (top=2):Hello 3.14
|
||||||
|
*/
|
||||||
60
c/lua/_demo/table/table.go
Normal file
60
c/lua/_demo/table/table.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func printTable(L *lua.State) {
|
||||||
|
L.Pushnil()
|
||||||
|
for L.Next(-2) != 0 {
|
||||||
|
key := L.Tostring(-2)
|
||||||
|
value := L.Tostring(-1)
|
||||||
|
c.Printf(c.Str("%s - %s\n"), key, value)
|
||||||
|
L.Pop(1)
|
||||||
|
}
|
||||||
|
L.Pop(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
|
||||||
|
L.Newtable()
|
||||||
|
|
||||||
|
L.Pushstring(c.Str("name"))
|
||||||
|
L.Pushstring(c.Str("John"))
|
||||||
|
L.Settable(-3)
|
||||||
|
|
||||||
|
L.Pushstring(c.Str("age"))
|
||||||
|
L.Pushnumber(30)
|
||||||
|
L.Settable(-3)
|
||||||
|
|
||||||
|
L.Pushstring(c.Str("John Doe"))
|
||||||
|
L.Setfield(-2, c.Str("fullname"))
|
||||||
|
|
||||||
|
L.Getfield(-1, c.Str("name"))
|
||||||
|
c.Printf(c.Str("%s\n"), L.Tostring(-1))
|
||||||
|
L.Pop(1)
|
||||||
|
|
||||||
|
L.Pushstring(c.Str("age"))
|
||||||
|
L.Gettable(-2)
|
||||||
|
age := int(L.Tonumber(-1))
|
||||||
|
c.Printf(c.Str("Age: %d\n"), age)
|
||||||
|
L.Pop(1)
|
||||||
|
|
||||||
|
c.Printf(c.Str("All entries in the table:\n"))
|
||||||
|
printTable(L)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
John
|
||||||
|
Age: 30
|
||||||
|
All entries in the table:
|
||||||
|
age - 30.0
|
||||||
|
fullname - John Doe
|
||||||
|
name - John
|
||||||
|
*/
|
||||||
101
c/lua/lauxlib.go
Normal file
101
c/lua/lauxlib.go
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// /* global table */
|
||||||
|
|
||||||
|
// /* extra error code for 'luaL_loadfilex' */
|
||||||
|
|
||||||
|
// /* key, in the registry, for table of loaded modules */
|
||||||
|
|
||||||
|
// /* key, in the registry, for table of preloaded loaders */
|
||||||
|
|
||||||
|
// /* predefined references */
|
||||||
|
|
||||||
|
// llgo:link (*State).Loadfilex C.luaL_loadfilex
|
||||||
|
func (L *State) Loadfilex(filename *c.Char, mode *c.Char) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (L *State) Loadfile(filename *c.Char) c.Int { return L.Loadfilex(filename, nil) }
|
||||||
|
|
||||||
|
// llgo:link (*State).Loadstring C.luaL_loadstring
|
||||||
|
func (L *State) Loadstring(s *c.Char) c.Int { return 0 }
|
||||||
|
|
||||||
|
//go:linkname Newstate C.luaL_newstate
|
||||||
|
func Newstate() *State
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** ===============================================================
|
||||||
|
// ** some useful macros
|
||||||
|
// ** ===============================================================
|
||||||
|
// */
|
||||||
|
|
||||||
|
func (L *State) Dofile(filename *c.Char) c.Int {
|
||||||
|
if loadResult := L.Loadfile(filename); loadResult != 0 {
|
||||||
|
return loadResult
|
||||||
|
}
|
||||||
|
return L.Pcall(c.Int(0), c.Int(MULTRET), c.Int(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (L *State) Dostring(str *c.Char) c.Int {
|
||||||
|
if loadResult := L.Loadstring(str); loadResult != 0 {
|
||||||
|
return loadResult
|
||||||
|
}
|
||||||
|
return L.Pcall(c.Int(0), c.Int(MULTRET), c.Int(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Perform arithmetic operations on lua_Integer values with wrap-around
|
||||||
|
// ** semantics, as the Lua core does.
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /* push the value used to represent failure/error */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** {======================================================
|
||||||
|
// ** Generic Buffer manipulation
|
||||||
|
// ** =======================================================
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /* }====================================================== */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** {======================================================
|
||||||
|
// ** File handles for IO library
|
||||||
|
// ** =======================================================
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
|
||||||
|
// ** initial structure 'luaL_Stream' (it may contain other fields
|
||||||
|
// ** after that initial structure).
|
||||||
|
// */
|
||||||
|
|
||||||
|
// #define LUA_FILEHANDLE "FILE*"
|
||||||
|
|
||||||
|
// /* }====================================================== */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** {==================================================================
|
||||||
|
// ** "Abstraction Layer" for basic report of messages and errors
|
||||||
|
// ** ===================================================================
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /* print a string */
|
||||||
|
|
||||||
|
// /* print a newline and flush the output */
|
||||||
|
|
||||||
|
// /* print an error message */
|
||||||
|
|
||||||
|
// /* }================================================================== */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** {============================================================
|
||||||
|
// ** Compatibility with deprecated conversions
|
||||||
|
// ** =============================================================
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /* }============================================================ */
|
||||||
495
c/lua/lua.go
Normal file
495
c/lua/lua.go
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
package lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link: $(pkg-config --libs lua); -llua -lm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// /* mark for precompiled code ('<esc>Lua') */
|
||||||
|
|
||||||
|
// /* option for multiple returns in 'lua_pcall' and 'lua_call' */
|
||||||
|
const (
|
||||||
|
MULTRET = -1
|
||||||
|
)
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Pseudo-indices
|
||||||
|
// ** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
|
||||||
|
// ** space after that to help overflow detection)
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /* thread status */
|
||||||
|
const (
|
||||||
|
OK = 0
|
||||||
|
YIELD = 1
|
||||||
|
ERRRUN = 2
|
||||||
|
ERRSYNTAX = 3
|
||||||
|
ERRMEM = 4
|
||||||
|
ERRERR = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
type State struct {
|
||||||
|
Unused [8]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** basic types
|
||||||
|
// */
|
||||||
|
const (
|
||||||
|
NONE = int(-1)
|
||||||
|
NIL = int(0)
|
||||||
|
BOOLEAN = int(1)
|
||||||
|
LIGHTUSERDATA = int(2)
|
||||||
|
NUMBER = int(3)
|
||||||
|
STRING = int(4)
|
||||||
|
TABLE = int(5)
|
||||||
|
FUNCTION = int(6)
|
||||||
|
USERDATA = int(7)
|
||||||
|
THREAD = int(8)
|
||||||
|
UMTYPES = int(9)
|
||||||
|
)
|
||||||
|
|
||||||
|
// /* minimum Lua stack available to a C function */
|
||||||
|
const (
|
||||||
|
MINSTACK = 20
|
||||||
|
)
|
||||||
|
|
||||||
|
// /* predefined values in the registry */
|
||||||
|
const (
|
||||||
|
RIDX_MAINTHREAD = 1
|
||||||
|
RIDX_GLOBALS = 2
|
||||||
|
RIDX_LAST = RIDX_GLOBALS
|
||||||
|
)
|
||||||
|
|
||||||
|
// /* type of numbers in Lua */
|
||||||
|
type Number = c.Double
|
||||||
|
|
||||||
|
// /* type for integer functions */
|
||||||
|
// TODO(zzy):consider dynamic size
|
||||||
|
|
||||||
|
type Integer = c.Int
|
||||||
|
|
||||||
|
// /* unsigned integer type */
|
||||||
|
type Unsigned = c.Uint
|
||||||
|
|
||||||
|
// /* type for continuation-function contexts */
|
||||||
|
// TODO(zzy): Context may not be c.Int
|
||||||
|
type KContext c.Int
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Type for C functions registered with Lua
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Type for continuation functions
|
||||||
|
// */
|
||||||
|
|
||||||
|
// TODO(zzy): KFunction does not currently support
|
||||||
|
type KFunction func(L *State, status c.Int, ctx KContext) c.Int
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Type for functions that read/write blocks when loading/dumping Lua chunks
|
||||||
|
// */
|
||||||
|
|
||||||
|
// typedef const char * (*lua_Reader) (State *L, void *ud, size_t *sz);
|
||||||
|
// typedef int (*lua_Writer) (State *L, const void *p, size_t sz, void *ud);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Type for memory-allocation functions
|
||||||
|
// */
|
||||||
|
|
||||||
|
// typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Type for warning functions
|
||||||
|
// */
|
||||||
|
|
||||||
|
// typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Type used by the debug API to collect debug information
|
||||||
|
// */
|
||||||
|
|
||||||
|
// typedef struct lua_Debug lua_Debug;
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Functions to be called by the debugger in specific events
|
||||||
|
// */
|
||||||
|
|
||||||
|
// typedef void (*lua_Hook) (State *L, lua_Debug *ar);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** generic extra include file
|
||||||
|
// */
|
||||||
|
|
||||||
|
// #if defined(LUA_USER_H)
|
||||||
|
// #include LUA_USER_H
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** RCS ident string
|
||||||
|
// */
|
||||||
|
|
||||||
|
// extern const char lua_ident[];
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** state manipulation
|
||||||
|
// */
|
||||||
|
// llgo:link (*State).Close C.lua_close
|
||||||
|
func (L *State) Close() {}
|
||||||
|
|
||||||
|
// State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||||
|
// State *(lua_newthread) (State *L);
|
||||||
|
|
||||||
|
// llgo:link (*State).Newthread C.lua_newthread
|
||||||
|
func (L *State) Newthread() *State { return nil }
|
||||||
|
|
||||||
|
// int (lua_closethread) (State *L, State *from);
|
||||||
|
// int (lua_resetthread) (State *L); /* Deprecated! */
|
||||||
|
// lua_CFunction (lua_atpanic) (State *L, lua_CFunction panicf);
|
||||||
|
// lua_Number (lua_version) (State *L);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** basic stack manipulation
|
||||||
|
// */
|
||||||
|
|
||||||
|
// llgo:link (*State).Absindex C.lua_absindex
|
||||||
|
func (L *State) Absindex(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Gettop C.lua_gettop
|
||||||
|
func (L *State) Gettop() c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Settop C.lua_settop
|
||||||
|
func (L *State) Settop(idx c.Int) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushvalue C.lua_pushvalue
|
||||||
|
func (L *State) Pushvalue(idx c.Int) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Rotate C.lua_rotate
|
||||||
|
func (L *State) Rotate(idx c.Int, n c.Int) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Copy C.lua_copy
|
||||||
|
func (L *State) Copy(fromidx c.Int, toidx c.Int) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Checkstack C.lua_checkstack
|
||||||
|
func (L *State) Checkstack(n c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Xmove C.lua_xmove
|
||||||
|
func (L *State) Xmove(to *State, n c.Int) {}
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** access functions (stack -> C)
|
||||||
|
// */
|
||||||
|
// LUA_API int (lua_isinteger) (State *L, int idx);
|
||||||
|
// llgo:link (*State).Isinteger C.lua_isinteger
|
||||||
|
func (L *State) Isinteger(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Isnumber C.lua_isnumber
|
||||||
|
func (L *State) Isnumber(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Isstring C.lua_isstring
|
||||||
|
func (L *State) Isstring(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// TODO(zzy):add to demo
|
||||||
|
// llgo:link (*State).Type C.lua_type
|
||||||
|
func (L *State) Type(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// TODO(zzy)
|
||||||
|
// llgo:link (*State).Typename C.lua_typename
|
||||||
|
func (L *State) Typename(tp c.Int) *c.Char { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*State).Tonumberx C.lua_tonumberx
|
||||||
|
func (L *State) Tonumberx(idx c.Int, isnum *c.Int) Number { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Tointegerx C.lua_tointegerx
|
||||||
|
func (L *State) Tointegerx(idx c.Int, isnum *c.Int) Integer { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Toboolean C.lua_toboolean
|
||||||
|
func (L *State) Toboolean(idx c.Int) bool { return false }
|
||||||
|
|
||||||
|
// llgo:link (*State).Tolstring C.lua_tolstring
|
||||||
|
func (L *State) Tolstring(idx c.Int, len *c.Ulong) *c.Char { return nil }
|
||||||
|
|
||||||
|
// LUA_API int (lua_iscfunction) (State *L, int idx);
|
||||||
|
// LUA_API int (lua_isuserdata) (State *L, int idx);
|
||||||
|
|
||||||
|
// LUA_API lua_Unsigned (lua_rawlen) (State *L, int idx);
|
||||||
|
// LUA_API lua_CFunction (lua_tocfunction) (State *L, int idx);
|
||||||
|
// LUA_API void *(lua_touserdata) (State *L, int idx);
|
||||||
|
// LUA_API State *(lua_tothread) (State *L, int idx);
|
||||||
|
// LUA_API const void *(lua_topointer) (State *L, int idx);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Comparison and arithmetic functions
|
||||||
|
// */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** push functions (C -> stack)
|
||||||
|
// */
|
||||||
|
// llgo:link (*State).Pushnil C.lua_pushnil
|
||||||
|
func (L *State) Pushnil() {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushnumber C.lua_pushnumber
|
||||||
|
func (L *State) Pushnumber(n Number) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushinteger C.lua_pushinteger
|
||||||
|
func (L *State) Pushinteger(n Integer) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushstring C.lua_pushstring
|
||||||
|
func (L *State) Pushstring(s *c.Char) *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushlstring C.lua_pushlstring
|
||||||
|
func (L *State) Pushlstring(s *c.Char, len c.Ulong) *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushfstring C.lua_pushfstring
|
||||||
|
func (L *State) Pushfstring(format *c.Char, __llgo_va_list ...any) *c.Char { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushboolean C.lua_pushboolean
|
||||||
|
func (L *State) Pushboolean(b c.Int) {}
|
||||||
|
|
||||||
|
//const char *(lua_pushvfstring) (State *L, const char *fmt,va_list argp);
|
||||||
|
//void (lua_pushcclosure) (State *L, lua_CFunction fn, int n);
|
||||||
|
//void (lua_pushlightuserdata) (State *L, void *p);
|
||||||
|
//int (lua_pushthread) (State *L);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** get functions (Lua -> stack)
|
||||||
|
// */
|
||||||
|
|
||||||
|
// llgo:link (*State).Getglobal C.lua_getglobal
|
||||||
|
func (L *State) Getglobal(name *c.Char) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Gettable C.lua_gettable
|
||||||
|
func (L *State) Gettable(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Getfield C.lua_getfield
|
||||||
|
func (L *State) Getfield(idx c.Int, k *c.Char) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Createtable C.lua_createtable
|
||||||
|
func (L *State) Createtable(narr c.Int, nrec c.Int) {}
|
||||||
|
|
||||||
|
// LUA_API int (lua_geti) (State *L, int idx, lua_Integer n);
|
||||||
|
// LUA_API int (lua_rawget) (State *L, int idx);
|
||||||
|
// LUA_API int (lua_rawgeti) (State *L, int idx, lua_Integer n);
|
||||||
|
// LUA_API int (lua_rawgetp) (State *L, int idx, const void *p);
|
||||||
|
|
||||||
|
// LUA_API void *(lua_newuserdatauv) (State *L, size_t sz, int nuvalue);
|
||||||
|
// LUA_API int (lua_getmetatable) (State *L, int objindex);
|
||||||
|
// LUA_API int (lua_getiuservalue) (State *L, int idx, int n);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** set functions (stack -> Lua)
|
||||||
|
// */
|
||||||
|
|
||||||
|
// TODO(zzy):add to demo
|
||||||
|
// llgo:link (*State).Setglobal C.lua_setglobal
|
||||||
|
func (L *State) Setglobal(name *c.Char) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Settable C.lua_settable
|
||||||
|
func (L *State) Settable(idx c.Int) {}
|
||||||
|
|
||||||
|
// llgo:link (*State).Setfield C.lua_setfield
|
||||||
|
func (L *State) Setfield(idx c.Int, k *c.Char) {}
|
||||||
|
|
||||||
|
//void (lua_seti) (State *L, int idx, lua_Integer n);
|
||||||
|
//void (lua_rawset) (State *L, int idx);
|
||||||
|
//void (lua_rawseti) (State *L, int idx, lua_Integer n);
|
||||||
|
//void (lua_rawsetp) (State *L, int idx, const void *p);
|
||||||
|
//int (lua_setmetatable) (State *L, int objindex);
|
||||||
|
//int (lua_setiuservalue) (State *L, int idx, int n);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** 'load' and 'call' functions (load and run Lua code)
|
||||||
|
// */
|
||||||
|
|
||||||
|
// llgo:link (*State).Pcallk C.lua_pcallk
|
||||||
|
func (L *State) Pcallk(nargs c.Int, nresults c.Int, errfunc c.Int, ctx KContext, k *KFunction) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (L *State) Pcall(nargs c.Int, nresults c.Int, errfunc c.Int) c.Int {
|
||||||
|
return L.Pcallk(nargs, nresults, errfunc, KContext(c.Int(0)), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// void (lua_callk) (State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
|
||||||
|
// #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
|
||||||
|
|
||||||
|
// int (lua_load) (State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode);
|
||||||
|
|
||||||
|
// int (lua_dump) (State *L, lua_Writer writer, void *data, int strip);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** coroutine functions
|
||||||
|
// */
|
||||||
|
|
||||||
|
// llgo:link (*State).Resume C.lua_resume
|
||||||
|
func (L *State) Resume(from *State, narg c.Int, nres *c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Status C.lua_status
|
||||||
|
func (L *State) Status() c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Isyieldable C.lua_isyieldable
|
||||||
|
func (L *State) Isyieldable() c.Int { return 0 }
|
||||||
|
|
||||||
|
// TODO(zzy)
|
||||||
|
// int (lua_yieldk) (State *L, int nresults, lua_KContext ctx, lua_KFunction k);
|
||||||
|
// #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Warning-related functions
|
||||||
|
// */
|
||||||
|
|
||||||
|
//void (lua_setwarnf) (State *L, lua_WarnFunction f, void *ud);
|
||||||
|
//void (lua_warning) (State *L, const char *msg, int tocont);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** garbage-collection function and options
|
||||||
|
// */
|
||||||
|
|
||||||
|
const (
|
||||||
|
GCSTOP = 0
|
||||||
|
GCRESTART = 1
|
||||||
|
GCCOLLECT = 2
|
||||||
|
GCCOUNT = 3
|
||||||
|
GCCOUNTB = 4
|
||||||
|
GCSTEP = 5
|
||||||
|
GCSETPAUSE = 6
|
||||||
|
GCSETSTEPMUL = 7
|
||||||
|
GCISRUNNING = 9
|
||||||
|
GCGEN = 10
|
||||||
|
GCINC = 11
|
||||||
|
)
|
||||||
|
|
||||||
|
// LUA_API int (lua_gc) (State *L, int what, ...);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** miscellaneous functions
|
||||||
|
// */
|
||||||
|
// llgo:link (*State).Next C.lua_next
|
||||||
|
func (L *State) Next(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// LUA_API int (lua_error) (State *L);
|
||||||
|
|
||||||
|
// LUA_API void (lua_concat) (State *L, int n);
|
||||||
|
// LUA_API void (lua_len) (State *L, int idx);
|
||||||
|
|
||||||
|
// LUA_API size_t (lua_stringtonumber) (State *L, const char *s);
|
||||||
|
|
||||||
|
// LUA_API lua_Alloc (lua_getallocf) (State *L, void **ud);
|
||||||
|
// LUA_API void (lua_setallocf) (State *L, lua_Alloc f, void *ud);
|
||||||
|
|
||||||
|
// LUA_API void (lua_toclose) (State *L, int idx);
|
||||||
|
// LUA_API void (lua_closeslot) (State *L, int idx);
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** {==============================================================
|
||||||
|
// ** some useful macros
|
||||||
|
// ** ===============================================================
|
||||||
|
// */
|
||||||
|
|
||||||
|
func (L *State) Tonumber(idx c.Int) Number { return L.Tonumberx(idx, nil) }
|
||||||
|
func (L *State) Tostring(idx c.Int) *c.Char { return L.Tolstring(idx, nil) }
|
||||||
|
func (L *State) Tointeger(idx c.Int) Integer { return L.Tointegerx(idx, nil) }
|
||||||
|
func (L *State) Pop(n c.Int) { L.Settop(-(n) - 1) }
|
||||||
|
func (L *State) Newtable() { L.Createtable(0, 0) }
|
||||||
|
func (L *State) Isfunction(n c.Int) bool { return L.Type(n) == c.Int(FUNCTION) }
|
||||||
|
func (L *State) Istable(n c.Int) bool { return L.Type(n) == c.Int(TABLE) }
|
||||||
|
func (L *State) Islightuserdata(n c.Int) bool { return L.Type(n) == c.Int(LIGHTUSERDATA) }
|
||||||
|
func (L *State) Isnil(n c.Int) bool { return L.Type(n) == c.Int(NIL) }
|
||||||
|
func (L *State) Isboolean(n c.Int) bool { return L.Type(n) == c.Int(BOOLEAN) }
|
||||||
|
func (L *State) Isthread(n c.Int) bool { return L.Type(n) == c.Int(THREAD) }
|
||||||
|
func (L *State) Isnone(n c.Int) bool { return L.Type(n) == c.Int(NONE) }
|
||||||
|
func (L *State) Isnoneornil(n c.Int) bool { return L.Type(n) <= 0 }
|
||||||
|
|
||||||
|
// #define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
|
||||||
|
|
||||||
|
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||||
|
|
||||||
|
// #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
|
||||||
|
|
||||||
|
// #define lua_pushliteral(L, s) lua_pushstring(L, "" s)
|
||||||
|
|
||||||
|
// #define lua_pushglobaltable(L) ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
|
||||||
|
|
||||||
|
// #define lua_insert(L,idx) lua_rotate(L, (idx), 1)
|
||||||
|
|
||||||
|
// #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
|
||||||
|
|
||||||
|
// #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
|
||||||
|
|
||||||
|
// /* }============================================================== */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** {==============================================================
|
||||||
|
// ** compatibility macros
|
||||||
|
// ** ===============================================================
|
||||||
|
// */
|
||||||
|
|
||||||
|
// #define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1)
|
||||||
|
// #define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1)
|
||||||
|
// #define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1)
|
||||||
|
|
||||||
|
// #define LUA_NUMTAGS LUA_NUMTYPES
|
||||||
|
|
||||||
|
// /* }============================================================== */
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** {======================================================================
|
||||||
|
// ** Debug API
|
||||||
|
// ** =======================================================================
|
||||||
|
// */
|
||||||
|
// /*
|
||||||
|
// ** Event codes
|
||||||
|
// */
|
||||||
|
|
||||||
|
const (
|
||||||
|
HOOKCALL = 0
|
||||||
|
HOOKRET = 1
|
||||||
|
HOOKLINE = 2
|
||||||
|
HOOKCOUNT = 3
|
||||||
|
HOOKTAILCALL = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** Event masks
|
||||||
|
// */
|
||||||
|
// #define LUA_MASKCALL (1 << LUA_HOOKCALL)
|
||||||
|
// #define LUA_MASKRET (1 << LUA_HOOKRET)
|
||||||
|
// #define LUA_MASKLINE (1 << LUA_HOOKLINE)
|
||||||
|
// #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MASKCALL = 1 << HOOKCOUNT
|
||||||
|
MASKRET = 1 << HOOKRET
|
||||||
|
MASKLINE = 1 << HOOKLINE
|
||||||
|
MASKCOUNT = 1 << HOOKCOUNT
|
||||||
|
)
|
||||||
|
|
||||||
|
// LUA_API int (lua_getstack) (State *L, int level, lua_Debug *ar);
|
||||||
|
// LUA_API int (lua_getinfo) (State *L, const char *what, lua_Debug *ar);
|
||||||
|
// LUA_API const char *(lua_getlocal) (State *L, const lua_Debug *ar, int n);
|
||||||
|
// LUA_API const char *(lua_setlocal) (State *L, const lua_Debug *ar, int n);
|
||||||
|
// LUA_API const char *(lua_getupvalue) (State *L, int funcindex, int n);
|
||||||
|
// LUA_API const char *(lua_setupvalue) (State *L, int funcindex, int n);
|
||||||
|
|
||||||
|
// LUA_API void *(lua_upvalueid) (State *L, int fidx, int n);
|
||||||
|
// LUA_API void (lua_upvaluejoin) (State *L, int fidx1, int n1, int fidx2, int n2);
|
||||||
|
|
||||||
|
// LUA_API void (lua_sethook) (State *L, lua_Hook func, int mask, int count);
|
||||||
|
// LUA_API lua_Hook (lua_gethook) (State *L);
|
||||||
|
// LUA_API int (lua_gethookmask) (State *L);
|
||||||
|
// LUA_API int (lua_gethookcount) (State *L);
|
||||||
|
|
||||||
|
// LUA_API int (lua_setcstacklimit) (State *L, unsigned int limit);
|
||||||
|
|
||||||
|
// struct lua_Debug
|
||||||
|
// /* }====================================================================== */
|
||||||
8
c/lua/lualib.go
Normal file
8
c/lua/lualib.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// llgo:link (*State).Openlibs C.luaL_openlibs
|
||||||
|
func (L *State) Openlibs() {}
|
||||||
34
c/neco/_demo/cgen/_c/gen.c
Normal file
34
c/neco/_demo/cgen/_c/gen.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "../../../_wrap/neco.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void coroutine(int argc, void *argv[]) {
|
||||||
|
// Yield each int to the caller, one at a time.
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
neco_gen_yield(&i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __neco_main() {
|
||||||
|
|
||||||
|
// Create a new generator coroutine that is used to send ints.
|
||||||
|
neco_gen *gen;
|
||||||
|
neco_gen_start(&gen, sizeof(int), coroutine, 0);
|
||||||
|
|
||||||
|
// Iterate over each int until the generator is closed.
|
||||||
|
int i;
|
||||||
|
while (neco_gen_next(gen, &i) != NECO_CLOSED) {
|
||||||
|
printf("%d\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This coroutine no longer needs the generator.
|
||||||
|
neco_gen_release(gen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static void _neco_main() { __neco_exit_prog(__neco_main()); }
|
||||||
|
void run_main() {
|
||||||
|
neco_env_setpaniconerror(true);
|
||||||
|
neco_env_setcanceltype(NECO_CANCEL_ASYNC);
|
||||||
|
int ret = neco_start(_neco_main, 0);
|
||||||
|
fprintf(stderr, "neco_start: %s (code %d)\n", neco_strerror(ret), ret);
|
||||||
|
};
|
||||||
19
c/neco/_demo/cgen/cgen.go
Normal file
19
c/neco/_demo/cgen/cgen.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
_ "github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoFiles = "_c/gen.c; ../../_wrap/neco.c"
|
||||||
|
LLGoPackage = "link"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
runMain()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname runMain C.run_main
|
||||||
|
func runMain()
|
||||||
37
c/neco/_demo/gen/gen.go
Normal file
37
c/neco/_demo/gen/gen.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/neco"
|
||||||
|
)
|
||||||
|
|
||||||
|
func coroutine(argc c.Int, argv *c.Pointer) {
|
||||||
|
// Yield each int to the caller, one at a time.
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
neco.GenYield(unsafe.Pointer(&i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func necoMain(argc c.Int, argv *c.Pointer) {
|
||||||
|
// Create a new generator coroutine that is used to send ints.
|
||||||
|
var gen *neco.Gen
|
||||||
|
neco.GenStart(&gen, unsafe.Sizeof(0), coroutine, 0)
|
||||||
|
|
||||||
|
// Iterate over each int until the generator is closed.
|
||||||
|
var i int
|
||||||
|
for neco.GenNext(gen, unsafe.Pointer(&i)) != neco.CLOSED {
|
||||||
|
c.Printf(c.Str("%d\n"), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
neco.GenRelease(gen)
|
||||||
|
neco.ExitProg(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
neco.EnvSetpaniconerror(true)
|
||||||
|
neco.EnvSetcanceltype(neco.CANCEL_ASYNC)
|
||||||
|
var ret = neco.Start(necoMain, 0)
|
||||||
|
c.Fprintf(c.Stderr, c.Str("neco_start: %s (code %d)\n"), neco.Strerror(ret), ret)
|
||||||
|
}
|
||||||
8762
c/neco/_wrap/neco.c
Normal file
8762
c/neco/_wrap/neco.c
Normal file
File diff suppressed because it is too large
Load Diff
453
c/neco/_wrap/neco.h
Normal file
453
c/neco/_wrap/neco.h
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
// https://github.com/tidwall/neco
|
||||||
|
//
|
||||||
|
// Copyright 2024 Joshua J Baker. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// Neco -- Coroutine library for C
|
||||||
|
|
||||||
|
#ifndef NECO_H
|
||||||
|
#define NECO_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// basic operations
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup BasicOperations Basic operations
|
||||||
|
/// Neco provides standard operations for starting a coroutine, sleeping,
|
||||||
|
/// suspending, resuming, yielding to another coroutine, joining/waiting for
|
||||||
|
/// child coroutines, and exiting a running coroutine.
|
||||||
|
/// @{
|
||||||
|
int neco_start(void(*coroutine)(int argc, void *argv[]), int argc, ...);
|
||||||
|
int neco_startv(void(*coroutine)(int argc, void *argv[]), int argc, void *argv[]);
|
||||||
|
int neco_yield(void);
|
||||||
|
int neco_sleep(int64_t nanosecs);
|
||||||
|
int neco_sleep_dl(int64_t deadline);
|
||||||
|
int neco_join(int64_t id);
|
||||||
|
int neco_join_dl(int64_t id, int64_t deadline);
|
||||||
|
int neco_suspend(void);
|
||||||
|
int neco_suspend_dl(int64_t deadline);
|
||||||
|
int neco_resume(int64_t id);
|
||||||
|
void neco_exit(void);
|
||||||
|
int64_t neco_getid(void);
|
||||||
|
int64_t neco_lastid(void);
|
||||||
|
int64_t neco_starterid(void);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// channels
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Channels Channels
|
||||||
|
/// Channels allow for sending and receiving values between coroutines.
|
||||||
|
/// By default, sends and receives will block until the other side is ready.
|
||||||
|
/// This allows the coroutines to synchronize without using locks or condition
|
||||||
|
/// variables.
|
||||||
|
/// @{
|
||||||
|
typedef struct neco_chan neco_chan;
|
||||||
|
|
||||||
|
int neco_chan_make(neco_chan **chan, size_t data_size, size_t capacity);
|
||||||
|
int neco_chan_retain(neco_chan *chan);
|
||||||
|
int neco_chan_release(neco_chan *chan);
|
||||||
|
int neco_chan_send(neco_chan *chan, void *data);
|
||||||
|
int neco_chan_send_dl(neco_chan *chan, void *data, int64_t deadline);
|
||||||
|
int neco_chan_broadcast(neco_chan *chan, void *data);
|
||||||
|
int neco_chan_recv(neco_chan *chan, void *data);
|
||||||
|
int neco_chan_recv_dl(neco_chan *chan, void *data, int64_t deadline);
|
||||||
|
int neco_chan_tryrecv(neco_chan *chan, void *data);
|
||||||
|
int neco_chan_close(neco_chan *chan);
|
||||||
|
int neco_chan_select(int nchans, ...);
|
||||||
|
int neco_chan_select_dl(int64_t deadline, int nchans, ...);
|
||||||
|
int neco_chan_selectv(int nchans, neco_chan *chans[]);
|
||||||
|
int neco_chan_selectv_dl(int nchans, neco_chan *chans[], int64_t deadline);
|
||||||
|
int neco_chan_tryselect(int nchans, ...);
|
||||||
|
int neco_chan_tryselectv(int nchans, neco_chan *chans[]);
|
||||||
|
int neco_chan_case(neco_chan *chan, void *data);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// generators
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Generators Generators
|
||||||
|
/// A generator is a specialized iterator-bound coroutine that can produce a
|
||||||
|
/// sequence of values to be iterated over.
|
||||||
|
/// @{
|
||||||
|
typedef struct neco_gen neco_gen;
|
||||||
|
|
||||||
|
int neco_gen_start(neco_gen **gen, size_t data_size, void(*coroutine)(int argc, void *argv[]), int argc, ...);
|
||||||
|
int neco_gen_startv(neco_gen **gen, size_t data_size, void(*coroutine)(int argc, void *argv[]), int argc, void *argv[]);
|
||||||
|
int neco_gen_retain(neco_gen *gen);
|
||||||
|
int neco_gen_release(neco_gen *gen);
|
||||||
|
int neco_gen_yield(void *data);
|
||||||
|
int neco_gen_yield_dl(void *data, int64_t deadline);
|
||||||
|
int neco_gen_next(neco_gen *gen, void *data);
|
||||||
|
int neco_gen_next_dl(neco_gen *gen, void *data, int64_t deadline);
|
||||||
|
int neco_gen_close(neco_gen *gen);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// synchronization mechanisms
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Mutexes Mutexes
|
||||||
|
/// A mutex is synchronization mechanism that blocks access to variables by
|
||||||
|
/// multiple coroutines at once. This enforces exclusive access by a coroutine
|
||||||
|
/// to a variable or set of variables and helps to avoid data inconsistencies
|
||||||
|
/// due to race conditions.
|
||||||
|
/// @{
|
||||||
|
typedef struct { _Alignas(16) char _[48]; } neco_mutex;
|
||||||
|
|
||||||
|
#define NECO_MUTEX_INITIALIZER { 0 }
|
||||||
|
|
||||||
|
int neco_mutex_init(neco_mutex *mutex);
|
||||||
|
int neco_mutex_lock(neco_mutex *mutex);
|
||||||
|
int neco_mutex_lock_dl(neco_mutex *mutex, int64_t deadline);
|
||||||
|
int neco_mutex_trylock(neco_mutex *mutex);
|
||||||
|
int neco_mutex_unlock(neco_mutex *mutex);
|
||||||
|
int neco_mutex_rdlock(neco_mutex *mutex);
|
||||||
|
int neco_mutex_rdlock_dl(neco_mutex *mutex, int64_t deadline);
|
||||||
|
int neco_mutex_tryrdlock(neco_mutex *mutex);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// @defgroup WaitGroups WaitGroups
|
||||||
|
/// A WaitGroup waits for a multiple coroutines to finish.
|
||||||
|
/// The main coroutine calls neco_waitgroup_add() to set the number of
|
||||||
|
/// coroutines to wait for. Then each of the coroutines runs and calls
|
||||||
|
/// neco_waitgroup_done() when complete.
|
||||||
|
/// At the same time, neco_waitgroup_wait() can be used to block until all
|
||||||
|
/// coroutines are completed.
|
||||||
|
/// @{
|
||||||
|
typedef struct { _Alignas(16) char _[48]; } neco_waitgroup;
|
||||||
|
|
||||||
|
#define NECO_WAITGROUP_INITIALIZER { 0 }
|
||||||
|
|
||||||
|
int neco_waitgroup_init(neco_waitgroup *waitgroup);
|
||||||
|
int neco_waitgroup_add(neco_waitgroup *waitgroup, int delta);
|
||||||
|
int neco_waitgroup_done(neco_waitgroup *waitgroup);
|
||||||
|
int neco_waitgroup_wait(neco_waitgroup *waitgroup);
|
||||||
|
int neco_waitgroup_wait_dl(neco_waitgroup *waitgroup, int64_t deadline);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// @defgroup CondVar Condition variables
|
||||||
|
/// A condition variable is a synchronization mechanism that allows coroutines
|
||||||
|
/// to suspend execution until some condition is true.
|
||||||
|
/// @{
|
||||||
|
typedef struct { _Alignas(16) char _[48]; } neco_cond;
|
||||||
|
#define NECO_COND_INITIALIZER { 0 }
|
||||||
|
|
||||||
|
int neco_cond_init(neco_cond *cond);
|
||||||
|
int neco_cond_signal(neco_cond *cond);
|
||||||
|
int neco_cond_broadcast(neco_cond *cond);
|
||||||
|
int neco_cond_wait(neco_cond *cond, neco_mutex *mutex);
|
||||||
|
int neco_cond_wait_dl(neco_cond *cond, neco_mutex *mutex, int64_t deadline);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// file descriptors
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Posix Posix wrappers
|
||||||
|
/// Functions that work like their Posix counterpart but do not block, allowing
|
||||||
|
/// for usage in a Neco coroutine.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
// wrappers for various posix operations.
|
||||||
|
ssize_t neco_read(int fd, void *data, size_t nbytes);
|
||||||
|
ssize_t neco_read_dl(int fd, void *data, size_t nbytes, int64_t deadline);
|
||||||
|
ssize_t neco_write(int fd, const void *data, size_t nbytes);
|
||||||
|
ssize_t neco_write_dl(int fd, const void *data, size_t nbytes, int64_t deadline);
|
||||||
|
int neco_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||||
|
int neco_accept_dl(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int64_t deadline);
|
||||||
|
int neco_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
int neco_connect_dl(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int64_t deadline);
|
||||||
|
int neco_getaddrinfo(const char *node, const char *service,
|
||||||
|
const struct addrinfo *hints, struct addrinfo **res);
|
||||||
|
int neco_getaddrinfo_dl(const char *node, const char *service,
|
||||||
|
const struct addrinfo *hints, struct addrinfo **res, int64_t deadline);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// @defgroup Posix2 File descriptor helpers
|
||||||
|
/// Functions for working with file descriptors.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
// utility for enabling non-blocking on existing file descriptors
|
||||||
|
int neco_setnonblock(int fd, bool nonblock, bool *oldnonblock);
|
||||||
|
|
||||||
|
// wait for a file descriptor to be readable or writeable.
|
||||||
|
#define NECO_WAIT_READ 1
|
||||||
|
#define NECO_WAIT_WRITE 2
|
||||||
|
|
||||||
|
int neco_wait(int fd, int mode);
|
||||||
|
int neco_wait_dl(int fd, int mode, int64_t deadline);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// networking
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Networking Networking utilities
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
int neco_serve(const char *network, const char *address);
|
||||||
|
int neco_serve_dl(const char *network, const char *address, int64_t deadline);
|
||||||
|
int neco_dial(const char *network, const char *address);
|
||||||
|
int neco_dial_dl(const char *network, const char *address, int64_t deadline);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cancelation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Cancelation Cancelation
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
int neco_cancel(int64_t id);
|
||||||
|
int neco_cancel_dl(int64_t id, int64_t deadline);
|
||||||
|
|
||||||
|
#define NECO_CANCEL_ASYNC 1
|
||||||
|
#define NECO_CANCEL_INLINE 2
|
||||||
|
#define NECO_CANCEL_ENABLE 3
|
||||||
|
#define NECO_CANCEL_DISABLE 4
|
||||||
|
|
||||||
|
int neco_setcanceltype(int type, int *oldtype);
|
||||||
|
int neco_setcancelstate(int state, int *oldstate);
|
||||||
|
|
||||||
|
#define neco_cleanup_push(routine, arg) {__neco_c0(&(char[32]){0},routine,arg);
|
||||||
|
#define neco_cleanup_pop(execute) __neco_c1(execute);}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// random number generator
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Random Random number generator
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
#define NECO_CSPRNG 0 // Cryptographically secure pseudorandom number generator
|
||||||
|
#define NECO_PRNG 1 // Pseudorandom number generator (non-crypto, faster)
|
||||||
|
|
||||||
|
int neco_rand_setseed(int64_t seed, int64_t *oldseed);
|
||||||
|
int neco_rand(void *data, size_t nbytes, int attr);
|
||||||
|
int neco_rand_dl(void *data, size_t nbytes, int attr, int64_t deadline);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// signal handling
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Signals Signals
|
||||||
|
/// Allows for signals, such as SIGINT (Ctrl-C), to be intercepted or ignored.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
int neco_signal_watch(int signo);
|
||||||
|
int neco_signal_wait(void);
|
||||||
|
int neco_signal_wait_dl(int64_t deadline);
|
||||||
|
int neco_signal_unwatch(int signo);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// background worker
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Worker Background worker
|
||||||
|
/// Run arbitrary code in a background worker thread
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
int neco_work(int64_t pin, void(*work)(void *udata), void *udata);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Stats and information
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Stats Stats and information
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
typedef struct neco_stats {
|
||||||
|
size_t coroutines; ///< Number of active coroutines
|
||||||
|
size_t sleepers; ///< Number of sleeping coroutines
|
||||||
|
size_t evwaiters; ///< Number of coroutines waiting on I/O events
|
||||||
|
size_t sigwaiters; ///<
|
||||||
|
size_t senders; ///<
|
||||||
|
size_t receivers; ///<
|
||||||
|
size_t locked; ///<
|
||||||
|
size_t waitgroupers; ///<
|
||||||
|
size_t condwaiters; ///<
|
||||||
|
size_t suspended; ///<
|
||||||
|
size_t workers; ///< Number of background worker threads
|
||||||
|
} neco_stats;
|
||||||
|
|
||||||
|
int neco_getstats(neco_stats *stats);
|
||||||
|
int neco_is_main_thread(void);
|
||||||
|
const char *neco_switch_method(void);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// global behaviors
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup GlobalFuncs Global environment
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
void neco_env_setallocator(void *(*malloc)(size_t), void *(*realloc)(void*, size_t), void (*free)(void*));
|
||||||
|
void neco_env_setpaniconerror(bool paniconerror);
|
||||||
|
void neco_env_setcanceltype(int type);
|
||||||
|
void neco_env_setcancelstate(int state);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// time and duration
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Time Time
|
||||||
|
/// Functions for working with time.
|
||||||
|
///
|
||||||
|
/// The following defines are available for convenience.
|
||||||
|
///
|
||||||
|
/// ```c
|
||||||
|
/// #define NECO_NANOSECOND INT64_C(1)
|
||||||
|
/// #define NECO_MICROSECOND INT64_C(1000)
|
||||||
|
/// #define NECO_MILLISECOND INT64_C(1000000)
|
||||||
|
/// #define NECO_SECOND INT64_C(1000000000)
|
||||||
|
/// #define NECO_MINUTE INT64_C(60000000000)
|
||||||
|
/// #define NECO_HOUR INT64_C(3600000000000)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
#define NECO_NANOSECOND INT64_C(1)
|
||||||
|
#define NECO_MICROSECOND INT64_C(1000)
|
||||||
|
#define NECO_MILLISECOND INT64_C(1000000)
|
||||||
|
#define NECO_SECOND INT64_C(1000000000)
|
||||||
|
#define NECO_MINUTE INT64_C(60000000000)
|
||||||
|
#define NECO_HOUR INT64_C(3600000000000)
|
||||||
|
|
||||||
|
int64_t neco_now(void);
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// errors
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup ErrorFuncs Error handling
|
||||||
|
/// Functions for working with [Neco errors](./API.md#neco-errors).
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
#define NECO_OK 0 ///< Successful result (no error)
|
||||||
|
#define NECO_ERROR -1 ///< System error (check errno)
|
||||||
|
#define NECO_INVAL -2 ///< Invalid argument
|
||||||
|
#define NECO_PERM -3 ///< Operation not permitted
|
||||||
|
#define NECO_NOMEM -4 ///< Cannot allocate memory
|
||||||
|
#define NECO_EOF -5 ///< End of file or stream (neco_stream_*)
|
||||||
|
#define NECO_NOTFOUND -6 ///< No such coroutine (neco_cancel)
|
||||||
|
#define NECO_NOSIGWATCH -7 ///< Not watching on a signal
|
||||||
|
#define NECO_CLOSED -8 ///< Channel is closed
|
||||||
|
#define NECO_EMPTY -9 ///< Channel is empty (neco_chan_tryrecv)
|
||||||
|
#define NECO_TIMEDOUT -10 ///< Deadline has elapsed (neco_*_dl)
|
||||||
|
#define NECO_CANCELED -11 ///< Operation canceled (by neco_cancel)
|
||||||
|
#define NECO_BUSY -12 ///< Resource busy (mutex_trylock)
|
||||||
|
#define NECO_NEGWAITGRP -13 ///< Negative waitgroup counter
|
||||||
|
#define NECO_GAIERROR -14 ///< Error with getaddrinfo (check neco_gai_error)
|
||||||
|
#define NECO_UNREADFAIL -15 ///< Failed to unread byte (neco_stream_unread_byte)
|
||||||
|
#define NECO_PARTIALWRITE -16 ///< Failed to write all data (neco_stream_flush)
|
||||||
|
#define NECO_NOTGENERATOR -17 ///< Coroutine is not a generator (neco_gen_yield)
|
||||||
|
#define NECO_NOTSUSPENDED -18 ///< Coroutine is not suspended (neco_resume)
|
||||||
|
|
||||||
|
const char *neco_strerror(ssize_t errcode);
|
||||||
|
int neco_lasterr(void);
|
||||||
|
int neco_gai_lasterr(void);
|
||||||
|
int neco_panic(const char *fmt, ...);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// streama
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// @defgroup Streams Streams and Buffered I/O
|
||||||
|
/// Create a Neco stream from a file descriptor using neco_stream_make() or
|
||||||
|
/// a buffered stream using neco_stream_make_buffered().
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
typedef struct neco_stream neco_stream;
|
||||||
|
|
||||||
|
int neco_stream_make(neco_stream **stream, int fd);
|
||||||
|
int neco_stream_make_buffered(neco_stream **stream, int fd);
|
||||||
|
int neco_stream_close(neco_stream *stream);
|
||||||
|
int neco_stream_close_dl(neco_stream *stream, int64_t deadline);
|
||||||
|
ssize_t neco_stream_read(neco_stream *stream, void *data, size_t nbytes);
|
||||||
|
ssize_t neco_stream_read_dl(neco_stream *stream, void *data, size_t nbytes, int64_t deadline);
|
||||||
|
ssize_t neco_stream_write(neco_stream *stream, const void *data, size_t nbytes);
|
||||||
|
ssize_t neco_stream_write_dl(neco_stream *stream, const void *data, size_t nbytes, int64_t deadline);
|
||||||
|
ssize_t neco_stream_readfull(neco_stream *stream, void *data, size_t nbytes);
|
||||||
|
ssize_t neco_stream_readfull_dl(neco_stream *stream, void *data, size_t nbytes, int64_t deadline);
|
||||||
|
int neco_stream_read_byte(neco_stream *stream);
|
||||||
|
int neco_stream_read_byte_dl(neco_stream *stream, int64_t deadline);
|
||||||
|
int neco_stream_unread_byte(neco_stream *stream);
|
||||||
|
int neco_stream_flush(neco_stream *stream);
|
||||||
|
int neco_stream_flush_dl(neco_stream *stream, int64_t deadline);
|
||||||
|
ssize_t neco_stream_buffered_read_size(neco_stream *stream);
|
||||||
|
ssize_t neco_stream_buffered_write_size(neco_stream *stream);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// happy convenience macro
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// int neco_main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define neco_main \
|
||||||
|
__neco_main(int argc, char *argv[]); \
|
||||||
|
static void _neco_main(int argc, void *argv[]) { \
|
||||||
|
(void)argc; \
|
||||||
|
__neco_exit_prog(__neco_main(*(int*)argv[0], *(char***)argv[1])); \
|
||||||
|
} \
|
||||||
|
int main(int argc, char *argv[]) { \
|
||||||
|
neco_env_setpaniconerror(true); \
|
||||||
|
neco_env_setcanceltype(NECO_CANCEL_ASYNC); \
|
||||||
|
int ret = neco_start(_neco_main, 2, &argc, &argv); \
|
||||||
|
fprintf(stderr, "neco_start: %s (code %d)\n", neco_strerror(ret), ret); \
|
||||||
|
return -1; \
|
||||||
|
}; \
|
||||||
|
int __neco_main
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// private functions, not to be call directly
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void __neco_c0(void*,void(*)(void*),void*);
|
||||||
|
void __neco_c1(int);
|
||||||
|
void __neco_exit_prog(int);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef EAI_SYSTEM
|
||||||
|
#define EAI_SYSTEM 11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // NECO_H
|
||||||
81
c/neco/neco.go
Normal file
81
c/neco/neco.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package neco
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoFiles = "_wrap/neco.c"
|
||||||
|
LLGoPackage = "link"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OK = 0 ///< Successful result (no error)
|
||||||
|
ERROR = -1 ///< System error (check errno)
|
||||||
|
INVAL = -2 ///< Invalid argument
|
||||||
|
PERM = -3 ///< Operation not permitted
|
||||||
|
NOMEM = -4 ///< Cannot allocate memory
|
||||||
|
EOF = -5 ///< End of file or stream (neco_stream_*)
|
||||||
|
NOTFOUND = -6 ///< No such coroutine (neco_cancel)
|
||||||
|
NOSIGWATCH = -7 ///< Not watching on a signal
|
||||||
|
CLOSED = -8 ///< Channel is closed
|
||||||
|
EMPTY = -9 ///< Channel is empty (neco_chan_tryrecv)
|
||||||
|
TIMEDOUT = -10 ///< Deadline has elapsed (neco_*_dl)
|
||||||
|
CANCELED = -11 ///< Operation canceled (by neco_cancel)
|
||||||
|
BUSY = -12 ///< Resource busy (mutex_trylock)
|
||||||
|
NEGWAITGRP = -13 ///< Negative waitgroup counter
|
||||||
|
GAIERROR = -14 ///< Error with getaddrinfo (check neco_gai_error)
|
||||||
|
UNREADFAIL = -15 ///< Failed to unread byte (neco_stream_unread_byte)
|
||||||
|
PARTIALWRITE = -16 ///< Failed to write all data (neco_stream_flush)
|
||||||
|
NOTGENERATOR = -17 ///< Coroutine is not a generator (neco_gen_yield)
|
||||||
|
NOTSUSPENDED = -18 ///< Coroutine is not suspended (neco_resume)
|
||||||
|
|
||||||
|
CANCEL_ASYNC = 1
|
||||||
|
CANCEL_INLINE = 2
|
||||||
|
CANCEL_ENABLE = 3
|
||||||
|
CANCEL_DISABLE = 4
|
||||||
|
|
||||||
|
EAI_SYSTEM = 11
|
||||||
|
|
||||||
|
NANOSECOND = int64(1)
|
||||||
|
MICROSECOND = int64(1000)
|
||||||
|
MILLISECOND = int64(1000000)
|
||||||
|
SECOND = int64(1000000000)
|
||||||
|
MINUTE = int64(60000000000)
|
||||||
|
HOUR = int64(3600000000000)
|
||||||
|
)
|
||||||
|
|
||||||
|
// generator
|
||||||
|
type Gen struct{}
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type Coro = func(argc c.Int, argv *c.Pointer)
|
||||||
|
|
||||||
|
//go:linkname GenYield C.neco_gen_yield
|
||||||
|
func GenYield(data c.Pointer) c.Int
|
||||||
|
|
||||||
|
//go:linkname GenNext C.neco_gen_next
|
||||||
|
func GenNext(gen *Gen, data c.Pointer) c.Int
|
||||||
|
|
||||||
|
//go:linkname GenStart C.neco_gen_start
|
||||||
|
func GenStart(gen **Gen, dataSize uintptr, co Coro, argc c.Int, __llgo_va_list ...any) c.Int
|
||||||
|
|
||||||
|
//go:linkname GenRelease C.neco_gen_release
|
||||||
|
func GenRelease(gen *Gen) c.Int
|
||||||
|
|
||||||
|
//go:linkname ExitProg C.__neco_exit_prog
|
||||||
|
func ExitProg(code c.Int)
|
||||||
|
|
||||||
|
//go:linkname EnvSetpaniconerror C.neco_env_setpaniconerror
|
||||||
|
func EnvSetpaniconerror(paniconerror bool)
|
||||||
|
|
||||||
|
//go:linkname EnvSetcanceltype C.neco_env_setcanceltype
|
||||||
|
func EnvSetcanceltype(type_ c.Int)
|
||||||
|
|
||||||
|
//go:linkname Strerror C.neco_strerror
|
||||||
|
func Strerror(errcode c.Int) *c.Char
|
||||||
|
|
||||||
|
//go:linkname Start C.neco_start
|
||||||
|
func Start(co Coro, argc c.Int, __llgo_va_list ...any) c.Int
|
||||||
153
c/os/os.go
153
c/os/os.go
@@ -24,6 +24,7 @@ import (
|
|||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -34,13 +35,39 @@ const (
|
|||||||
PATH_MAX = C.PATH_MAX
|
PATH_MAX = C.PATH_MAX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
/* get file status flags */
|
||||||
|
F_GETFL = 3
|
||||||
|
/* set file status flags */
|
||||||
|
F_SETFL = 4
|
||||||
|
|
||||||
|
/* open for reading only */
|
||||||
|
O_RDONLY = 0x0000
|
||||||
|
/* open for writing only */
|
||||||
|
O_WRONLY = 0x0001
|
||||||
|
/* open for reading and writing */
|
||||||
|
O_RDWR = 0x0002
|
||||||
|
/* mask for above modes */
|
||||||
|
O_ACCMODE = 0x0003
|
||||||
|
|
||||||
|
/* no delay */
|
||||||
|
O_NONBLOCK = 0x00000004
|
||||||
|
/* create if nonexistant */
|
||||||
|
O_CREAT = 0x00000200
|
||||||
|
/* truncate to zero length */
|
||||||
|
O_TRUNC = 0x00000400
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ModeT C.mode_t
|
ModeT C.mode_t
|
||||||
UidT C.uid_t
|
UidT C.uid_t
|
||||||
GidT C.gid_t
|
GidT C.gid_t
|
||||||
OffT C.off_t
|
OffT C.off_t
|
||||||
DevT C.dev_t
|
DevT C.dev_t
|
||||||
StatT C.struct_stat
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
StatT = syscall.Stat_t
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname Errno errno
|
//go:linkname Errno errno
|
||||||
@@ -104,8 +131,8 @@ func Chroot(path *c.Char) c.Int
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Environ C.environ
|
//go:linkname Environ environ
|
||||||
func Environ() **c.Char
|
var Environ **c.Char
|
||||||
|
|
||||||
//go:linkname Getenv C.getenv
|
//go:linkname Getenv C.getenv
|
||||||
func Getenv(name *c.Char) *c.Char
|
func Getenv(name *c.Char) *c.Char
|
||||||
@@ -142,7 +169,7 @@ func Fstatat(dirfd c.Int, path *c.Char, buf *StatT, flags c.Int) c.Int
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Open C.open
|
//go:linkname Open C.open
|
||||||
func Open(path *c.Char, flags c.Int, mode ModeT) c.Int
|
func Open(path *c.Char, flags c.Int, __llgo_va_list ...any) c.Int
|
||||||
|
|
||||||
//go:linkname Openat C.openat
|
//go:linkname Openat C.openat
|
||||||
func Openat(dirfd c.Int, path *c.Char, flags c.Int, mode ModeT) c.Int
|
func Openat(dirfd c.Int, path *c.Char, flags c.Int, mode ModeT) c.Int
|
||||||
@@ -150,6 +177,9 @@ func Openat(dirfd c.Int, path *c.Char, flags c.Int, mode ModeT) c.Int
|
|||||||
//go:linkname Creat C.creat
|
//go:linkname Creat C.creat
|
||||||
func Creat(path *c.Char, mode ModeT) c.Int
|
func Creat(path *c.Char, mode ModeT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Fcntl C.fcntl
|
||||||
|
func Fcntl(a c.Int, b c.Int, __llgo_va_list ...any) c.Int
|
||||||
|
|
||||||
//go:linkname Dup C.dup
|
//go:linkname Dup C.dup
|
||||||
func Dup(fd c.Int) c.Int
|
func Dup(fd c.Int) c.Int
|
||||||
|
|
||||||
@@ -204,18 +234,79 @@ func Isatty(fd c.Int) c.Int
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Execl(const char *path, const char *arg0, ..., /*, (char *)0, */)
|
||||||
|
//
|
||||||
|
// Execl requires the full path of the program to be provided.
|
||||||
|
//
|
||||||
|
//go:linkname Execl C.execl
|
||||||
|
func Execl(path *c.Char, __llgo_va_list ...any) c.Int
|
||||||
|
|
||||||
|
// Execle(const char *path, const char *arg0, ..., /* (char *)0, char *const envp[] */)
|
||||||
|
//
|
||||||
|
//go:linkname Execle C.execle
|
||||||
|
func Execle(path *c.Char, __llgo_va_list ...any) c.Int
|
||||||
|
|
||||||
|
// Execlp(const char *file, const char *arg0, ..., /*, (char *)0, */)
|
||||||
|
//
|
||||||
|
// Execlp only needs to provide the program name and it will search for the program in the
|
||||||
|
// paths specified in the PATH environment variable.
|
||||||
|
//
|
||||||
|
//go:linkname Execlp C.execlp
|
||||||
|
func Execlp(file *c.Char, __llgo_va_list ...any) c.Int
|
||||||
|
|
||||||
|
//go:linkname Execv C.execv
|
||||||
|
func Execv(path *c.Char, argv **c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Execve C.execve
|
||||||
|
func Execve(path *c.Char, argv **c.Char, envp **c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Execvp C.execvp
|
||||||
|
func Execvp(file *c.Char, argv **c.Char) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type PidT c.Int
|
||||||
|
|
||||||
|
//go:linkname Fork C.fork
|
||||||
|
func Fork() PidT
|
||||||
|
|
||||||
|
//go:linkname Getpid C.getpid
|
||||||
|
func Getpid() PidT
|
||||||
|
|
||||||
|
//go:linkname Getppid C.getppid
|
||||||
|
func Getppid() PidT
|
||||||
|
|
||||||
//go:linkname Kill C.kill
|
//go:linkname Kill C.kill
|
||||||
func Kill(pid c.Int, sig c.Int) c.Int
|
func Kill(pid PidT, sig c.Int) c.Int
|
||||||
|
|
||||||
|
// If wait() returns due to a stopped or terminated child process, the process ID
|
||||||
|
// of the child is returned to the calling process. Otherwise, a value of -1 is
|
||||||
|
// returned and errno is set to indicate the error.
|
||||||
|
//
|
||||||
|
//go:linkname Wait C.wait
|
||||||
|
func Wait(statLoc *c.Int) PidT
|
||||||
|
|
||||||
|
// If wait3(), wait4(), or waitpid() returns due to a stopped or terminated child
|
||||||
|
// process, the process ID of the child is returned to the calling process. If
|
||||||
|
// there are no children not previously awaited, -1 is returned with errno set to
|
||||||
|
// [ECHILD]. Otherwise, if WNOHANG is specified and there are no stopped or exited
|
||||||
|
// children, 0 is returned. If an error is detected or a caught signal aborts the
|
||||||
|
// call, a value of -1 is returned and errno is set to indicate the error.
|
||||||
|
//
|
||||||
|
//go:linkname Wait3 C.wait3
|
||||||
|
func Wait3(statLoc *c.Int, options c.Int, rusage *syscall.Rusage) PidT
|
||||||
|
|
||||||
|
//go:linkname Wait4 C.wait4
|
||||||
|
func Wait4(pid PidT, statLoc *c.Int, options c.Int, rusage *syscall.Rusage) PidT
|
||||||
|
|
||||||
|
//go:linkname Waitpid C.waitpid
|
||||||
|
func Waitpid(pid PidT, statLoc *c.Int, options c.Int) PidT
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Exit C.exit
|
//go:linkname Exit C.exit
|
||||||
func Exit(c.Int)
|
func Exit(c.Int)
|
||||||
|
|
||||||
//go:linkname Getpid C.getpid
|
|
||||||
func Getpid() c.Int
|
|
||||||
|
|
||||||
//go:linkname Getppid C.getppid
|
|
||||||
func Getppid() c.Int
|
|
||||||
|
|
||||||
//go:linkname Getuid C.getuid
|
//go:linkname Getuid C.getuid
|
||||||
func Getuid() UidT
|
func Getuid() UidT
|
||||||
|
|
||||||
@@ -229,3 +320,43 @@ func Getgid() GidT
|
|||||||
func Getegid() GidT
|
func Getegid() GidT
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Getrlimit C.getrlimit
|
||||||
|
func Getrlimit(resource c.Int, rlp *syscall.Rlimit) c.Int
|
||||||
|
|
||||||
|
//go:linkname Setrlimit C.setrlimit
|
||||||
|
func Setrlimit(resource c.Int, rlp *syscall.Rlimit) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Upon successful completion, the value 0 is returned; otherwise the value -1
|
||||||
|
// is returned and the global variable errno is set to indicate the error.
|
||||||
|
//
|
||||||
|
//go:linkname Sysctl C.sysctl
|
||||||
|
func Sysctl(
|
||||||
|
name *c.Int, namelen c.Uint,
|
||||||
|
oldp c.Pointer, oldlenp *uintptr,
|
||||||
|
newp c.Pointer, newlen uintptr) c.Int
|
||||||
|
|
||||||
|
//go:linkname Sysctlbyname C.sysctlbyname
|
||||||
|
func Sysctlbyname(
|
||||||
|
name *c.Char, oldp c.Pointer, oldlenp *uintptr,
|
||||||
|
newp c.Pointer, newlen uintptr) c.Int
|
||||||
|
|
||||||
|
// The sysctlnametomib() function accepts an ASCII representation of the
|
||||||
|
// name, looks up the integer name vector, and returns the numeric repre-
|
||||||
|
// sentation in the mib array pointed to by mibp. The number of elements
|
||||||
|
// in the mib array is given by the location specified by sizep before the
|
||||||
|
// call, and that location gives the number of entries copied after a suc-
|
||||||
|
// cessful call. The resulting mib and size may be used in subsequent
|
||||||
|
// sysctl() calls to get the data associated with the requested ASCII
|
||||||
|
// name. This interface is intended for use by applications that want to
|
||||||
|
// repeatedly request the same variable (the sysctl() function runs in
|
||||||
|
// about a third the time as the same request made via the sysctlbyname()
|
||||||
|
// function). The sysctlnametomib() function is also useful for fetching
|
||||||
|
// mib prefixes and then adding a final component.
|
||||||
|
//
|
||||||
|
//go:linkname Sysctlnametomib C.sysctlnametomib
|
||||||
|
func Sysctlnametomib(name *c.Char, mibp *c.Int, sizep *uintptr) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
Binary file not shown.
30
c/raylib/README.md
Normal file
30
c/raylib/README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# LLGo wrapper of raysan5/raylib
|
||||||
|
|
||||||
|
## How to install
|
||||||
|
|
||||||
|
### on macOS (Homebrew)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install raylib
|
||||||
|
```
|
||||||
|
|
||||||
|
### on Linux (Debian/Ubuntu)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
TODO
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demos
|
||||||
|
|
||||||
|
The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it):
|
||||||
|
|
||||||
|
- [tetris](_demo/tetris/tetris.go): tetris powered by raylib
|
||||||
|
|
||||||
|
### How to run demos
|
||||||
|
|
||||||
|
To run the demos in directory `_demo`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd <demo-directory> # eg. cd _demo/tetris
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
Binary file not shown.
Binary file not shown.
144
c/socket/socket.go
Normal file
144
c/socket/socket.go
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* 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 socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = true
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AF_UNSPEC = 0 // unspecified
|
||||||
|
AF_UNIX = 1 // local to host (pipes)
|
||||||
|
AF_LOCAL = AF_UNIX // backward compatibility
|
||||||
|
AF_INET = 2 // internetwork: UDP, TCP, etc.
|
||||||
|
AF_IMPLINK = 3 // arpanet imp addresses
|
||||||
|
AF_PUP = 4 // pup protocols: e.g. BSP
|
||||||
|
AF_CHAOS = 5 // mit CHAOS protocols
|
||||||
|
AF_NS = 6 // XEROX NS protocols
|
||||||
|
AF_ISO = 7 // ISO protocols
|
||||||
|
AF_OSI = AF_ISO
|
||||||
|
AF_ECMA = 8 // European computer manufacturers
|
||||||
|
AF_DATAKIT = 9 // datakit protocols
|
||||||
|
AF_CCITT = 10 // CCITT protocols, X.25 etc
|
||||||
|
AF_SNA = 11 // IBM SNA
|
||||||
|
AF_DECnet = 12 // DECnet
|
||||||
|
AF_DLI = 13 // DEC Direct data link interface
|
||||||
|
AF_LAT = 14 // LAT
|
||||||
|
AF_HYLINK = 15 // NSC Hyperchannel
|
||||||
|
AF_APPLETALK = 16 // Apple Talk
|
||||||
|
AF_ROUTE = 17 // Internal Routing Protocol
|
||||||
|
AF_LINK = 18 // Link layer interface
|
||||||
|
pseudo_AF_XTP = 19 // eXpress Transfer Protocol (no AF)
|
||||||
|
AF_COIP = 20 // connection-oriented IP, aka ST II
|
||||||
|
AF_CNT = 21 // Computer Network Technology
|
||||||
|
pseudo_AF_RTIP = 22 // Help Identify RTIP packets
|
||||||
|
AF_IPX = 23 // Novell Internet Protocol
|
||||||
|
AF_SIP = 24 // Simple Internet Protocol
|
||||||
|
pseudo_AF_PIP = 25 // Help Identify PIP packets
|
||||||
|
AF_NDRV = 27 // Network Driver 'raw' access
|
||||||
|
AF_ISDN = 28 // Integrated Services Digital Network
|
||||||
|
AF_E164 = AF_ISDN // CCITT E.164 recommendation
|
||||||
|
pseudo_AF_KEY = 29 // Internal key-management function
|
||||||
|
AF_INET6 = 30 // IPv6
|
||||||
|
AF_NATM = 31 // native ATM access
|
||||||
|
AF_SYSTEM = 32 // Kernel event messages
|
||||||
|
AF_NETBIOS = 33 // NetBIOS
|
||||||
|
AF_PPP = 34 // PPP communication protocol
|
||||||
|
pseudo_AF_HDRCMPLT = 35 // Used by BPF to not rewrite headers in interface output routine
|
||||||
|
AF_RESERVED_36 = 36 // Reserved for internal usage
|
||||||
|
AF_IEEE80211 = 37 // IEEE 802.11 protocol
|
||||||
|
AF_UTUN = 38
|
||||||
|
AF_VSOCK = 40 // VM Sockets
|
||||||
|
AF_MAX = 41
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SOCK_STREAM = 1 // stream socket
|
||||||
|
SOCK_DGRAM = 2 // datagram socket
|
||||||
|
SOCK_RAW = 3 // raw-protocol interface
|
||||||
|
SOCK_RDM = 4 // reliably-delivered message
|
||||||
|
SOCK_SEQPACKET = 5 // sequenced packet stream
|
||||||
|
)
|
||||||
|
|
||||||
|
// (TODO) merge to inet
|
||||||
|
const INET_ADDRSTRLEN = 16
|
||||||
|
|
||||||
|
type SockaddrIn struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Addr InAddr
|
||||||
|
Zero [8]c.Char
|
||||||
|
}
|
||||||
|
|
||||||
|
type InAddr struct {
|
||||||
|
Addr c.Uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type SockAddr struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Data [14]c.Char
|
||||||
|
}
|
||||||
|
|
||||||
|
// (TODO) merge to netdb
|
||||||
|
type Hostent struct {
|
||||||
|
Name *c.Char // official name of host
|
||||||
|
Aliases **c.Char // null-terminated array of alternate names for the host
|
||||||
|
AddrType c.Int // host address type
|
||||||
|
Length c.Int // length of address
|
||||||
|
AddrList **c.Char // null-terminated array of addresses for the host
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Socket C.socket
|
||||||
|
func Socket(domain c.Int, typ c.Int, protocol c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Bind C.bind
|
||||||
|
func Bind(sockfd c.Int, addr *SockaddrIn, addrlen c.Uint) c.Int
|
||||||
|
|
||||||
|
//go:linkname Connect C.connect
|
||||||
|
func Connect(sockfd c.Int, addr *SockAddr, addrlen c.Uint) c.Int
|
||||||
|
|
||||||
|
//go:linkname Listen C.listen
|
||||||
|
func Listen(sockfd c.Int, backlog c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Accept C.accept
|
||||||
|
func Accept(sockfd c.Int, addr *SockaddrIn, addrlen *c.Uint) c.Int
|
||||||
|
|
||||||
|
// (TODO) merge to netdb
|
||||||
|
//
|
||||||
|
//go:linkname GetHostByName C.gethostbyname
|
||||||
|
func GetHostByName(name *c.Char) *Hostent
|
||||||
|
|
||||||
|
// (TODO) merge to inet
|
||||||
|
//
|
||||||
|
//go:linkname InetNtop C.inet_ntop
|
||||||
|
func InetNtop(af c.Int, src c.Pointer, dst *c.Char, size c.Uint) *c.Char
|
||||||
|
|
||||||
|
func SwapInt16(data uint16) uint16 {
|
||||||
|
return (data << 8) | (data >> 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Htons(x uint16) uint16 {
|
||||||
|
return SwapInt16(x)
|
||||||
|
}
|
||||||
Binary file not shown.
27
c/syscall/syscall.go
Normal file
27
c/syscall/syscall.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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 syscall
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "decl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Errno = uintptr
|
||||||
|
|
||||||
|
// A Signal is a number describing a process signal.
|
||||||
|
// It implements the os.Signal interface.
|
||||||
|
type Signal = int
|
||||||
10
c/syscall/unix/at_sysnum_darwin.go
Normal file
10
c/syscall/unix/at_sysnum_darwin.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 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 unix
|
||||||
|
|
||||||
|
const AT_REMOVEDIR = 0x80
|
||||||
|
const AT_SYMLINK_NOFOLLOW = 0x0020
|
||||||
|
|
||||||
|
const UTIME_OMIT = -0x2
|
||||||
10
c/syscall/unix/at_sysnum_dragonfly.go
Normal file
10
c/syscall/unix/at_sysnum_dragonfly.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 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 unix
|
||||||
|
|
||||||
|
const AT_REMOVEDIR = 0x2
|
||||||
|
const AT_SYMLINK_NOFOLLOW = 0x1
|
||||||
|
|
||||||
|
const UTIME_OMIT = -0x1
|
||||||
12
c/syscall/unix/at_sysnum_freebsd.go
Normal file
12
c/syscall/unix/at_sysnum_freebsd.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// 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 unix
|
||||||
|
|
||||||
|
const (
|
||||||
|
AT_REMOVEDIR = 0x800
|
||||||
|
AT_SYMLINK_NOFOLLOW = 0x200
|
||||||
|
|
||||||
|
UTIME_OMIT = -0x2
|
||||||
|
)
|
||||||
14
c/syscall/unix/at_sysnum_linux.go
Normal file
14
c/syscall/unix/at_sysnum_linux.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// 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 unix
|
||||||
|
|
||||||
|
const (
|
||||||
|
AT_EACCESS = 0x200
|
||||||
|
AT_FDCWD = -0x64
|
||||||
|
AT_REMOVEDIR = 0x200
|
||||||
|
AT_SYMLINK_NOFOLLOW = 0x100
|
||||||
|
|
||||||
|
UTIME_OMIT = 0x3ffffffe
|
||||||
|
)
|
||||||
10
c/syscall/unix/at_sysnum_netbsd.go
Normal file
10
c/syscall/unix/at_sysnum_netbsd.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 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 unix
|
||||||
|
|
||||||
|
const AT_REMOVEDIR = 0x800
|
||||||
|
const AT_SYMLINK_NOFOLLOW = 0x200
|
||||||
|
|
||||||
|
const UTIME_OMIT = (1 << 30) - 2
|
||||||
10
c/syscall/unix/at_sysnum_openbsd.go
Normal file
10
c/syscall/unix/at_sysnum_openbsd.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 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 unix
|
||||||
|
|
||||||
|
const AT_REMOVEDIR = 0x08
|
||||||
|
const AT_SYMLINK_NOFOLLOW = 0x02
|
||||||
|
|
||||||
|
const UTIME_OMIT = -0x1
|
||||||
21
c/syscall/unix/unix.go
Normal file
21
c/syscall/unix/unix.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "decl"
|
||||||
|
)
|
||||||
1153
c/syscall/zerrors_aix_ppc64.go
Normal file
1153
c/syscall/zerrors_aix_ppc64.go
Normal file
File diff suppressed because it is too large
Load Diff
1279
c/syscall/zerrors_darwin_amd64.go
Normal file
1279
c/syscall/zerrors_darwin_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1291
c/syscall/zerrors_darwin_arm64.go
Normal file
1291
c/syscall/zerrors_darwin_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1392
c/syscall/zerrors_dragonfly_amd64.go
Normal file
1392
c/syscall/zerrors_dragonfly_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1580
c/syscall/zerrors_freebsd_386.go
Normal file
1580
c/syscall/zerrors_freebsd_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_amd64.go
Normal file
1581
c/syscall/zerrors_freebsd_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1580
c/syscall/zerrors_freebsd_arm.go
Normal file
1580
c/syscall/zerrors_freebsd_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_arm64.go
Normal file
1581
c/syscall/zerrors_freebsd_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_riscv64.go
Normal file
1581
c/syscall/zerrors_freebsd_riscv64.go
Normal file
File diff suppressed because it is too large
Load Diff
1355
c/syscall/zerrors_linux_386.go
Normal file
1355
c/syscall/zerrors_linux_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1356
c/syscall/zerrors_linux_amd64.go
Normal file
1356
c/syscall/zerrors_linux_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1368
c/syscall/zerrors_linux_arm.go
Normal file
1368
c/syscall/zerrors_linux_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
1632
c/syscall/zerrors_linux_arm64.go
Normal file
1632
c/syscall/zerrors_linux_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1931
c/syscall/zerrors_linux_loong64.go
Normal file
1931
c/syscall/zerrors_linux_loong64.go
Normal file
File diff suppressed because it is too large
Load Diff
1639
c/syscall/zerrors_linux_mips.go
Normal file
1639
c/syscall/zerrors_linux_mips.go
Normal file
File diff suppressed because it is too large
Load Diff
1622
c/syscall/zerrors_linux_mips64.go
Normal file
1622
c/syscall/zerrors_linux_mips64.go
Normal file
File diff suppressed because it is too large
Load Diff
1622
c/syscall/zerrors_linux_mips64le.go
Normal file
1622
c/syscall/zerrors_linux_mips64le.go
Normal file
File diff suppressed because it is too large
Load Diff
1639
c/syscall/zerrors_linux_mipsle.go
Normal file
1639
c/syscall/zerrors_linux_mipsle.go
Normal file
File diff suppressed because it is too large
Load Diff
1687
c/syscall/zerrors_linux_ppc64.go
Normal file
1687
c/syscall/zerrors_linux_ppc64.go
Normal file
File diff suppressed because it is too large
Load Diff
1711
c/syscall/zerrors_linux_ppc64le.go
Normal file
1711
c/syscall/zerrors_linux_ppc64le.go
Normal file
File diff suppressed because it is too large
Load Diff
1686
c/syscall/zerrors_linux_riscv64.go
Normal file
1686
c/syscall/zerrors_linux_riscv64.go
Normal file
File diff suppressed because it is too large
Load Diff
1747
c/syscall/zerrors_linux_s390x.go
Normal file
1747
c/syscall/zerrors_linux_s390x.go
Normal file
File diff suppressed because it is too large
Load Diff
1575
c/syscall/zerrors_netbsd_386.go
Normal file
1575
c/syscall/zerrors_netbsd_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1565
c/syscall/zerrors_netbsd_amd64.go
Normal file
1565
c/syscall/zerrors_netbsd_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user