bump to modernc.org/sqlite v1.29.7 (#2850)

This commit is contained in:
kim 2024-04-17 17:10:51 +01:00 committed by GitHub
parent c67bbe5ba0
commit b3f2d44143
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
120 changed files with 631479 additions and 58069 deletions

10
go.mod
View file

@ -2,7 +2,7 @@ module github.com/superseriousbusiness/gotosocial
go 1.21 go 1.21
replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.5-concurrency-workaround replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.7-concurrency-workaround
toolchain go1.21.3 toolchain go1.21.3
@ -210,10 +210,10 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.7.0 // indirect golang.org/x/arch v0.7.0 // indirect
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
golang.org/x/mod v0.14.0 // indirect golang.org/x/mod v0.16.0 // indirect
golang.org/x/sync v0.6.0 // indirect golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.19.0 // indirect golang.org/x/sys v0.19.0 // indirect
golang.org/x/tools v0.17.0 // indirect golang.org/x/tools v0.19.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
google.golang.org/grpc v1.63.0 // indirect google.golang.org/grpc v1.63.0 // indirect
@ -221,9 +221,9 @@ require (
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.41.0 // indirect modernc.org/libc v1.49.3 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect modernc.org/token v1.1.0 // indirect
) )

34
go.sum
View file

@ -369,8 +369,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -716,8 +716,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.5-concurrency-workaround h1:cyYnGCVJ0zLW2Q0pCepy++ERHegWcKpl5JD1MiTKUuw= gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.7-concurrency-workaround h1:N4h6T8jb9BZTor6d4XJYaKYEh3KNAydpuydR2N1hPRc=
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.5-concurrency-workaround/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.7-concurrency-workaround/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk=
go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
@ -806,8 +806,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -979,8 +979,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1103,16 +1103,26 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk=
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA=
modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg=
modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View file

@ -4,17 +4,22 @@
package buildutil package buildutil
// This logic was copied from stringsFlag from $GOROOT/src/cmd/go/build.go. // This duplicated logic must be kept in sync with that from go build:
// $GOROOT/src/cmd/go/internal/work/build.go (tagsFlag.Set)
// $GOROOT/src/cmd/go/internal/base/flag.go (StringsFlag.Set)
// $GOROOT/src/cmd/internal/quoted/quoted.go (isSpaceByte, Split)
import "fmt" import (
"fmt"
"strings"
)
const TagsFlagDoc = "a list of `build tags` to consider satisfied during the build. " + const TagsFlagDoc = "a list of `build tags` to consider satisfied during the build. " +
"For more information about build tags, see the description of " + "For more information about build tags, see the description of " +
"build constraints in the documentation for the go/build package" "build constraints in the documentation for the go/build package"
// TagsFlag is an implementation of the flag.Value and flag.Getter interfaces that parses // TagsFlag is an implementation of the flag.Value and flag.Getter interfaces that parses
// a flag value in the same manner as go build's -tags flag and // a flag value the same as go build's -tags flag and populates a []string slice.
// populates a []string slice.
// //
// See $GOROOT/src/go/build/doc.go for description of build tags. // See $GOROOT/src/go/build/doc.go for description of build tags.
// See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag. // See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag.
@ -25,19 +30,32 @@ const TagsFlagDoc = "a list of `build tags` to consider satisfied during the bui
type TagsFlag []string type TagsFlag []string
func (v *TagsFlag) Set(s string) error { func (v *TagsFlag) Set(s string) error {
var err error // See $GOROOT/src/cmd/go/internal/work/build.go (tagsFlag.Set)
*v, err = splitQuotedFields(s) // For compatibility with Go 1.12 and earlier, allow "-tags='a b c'" or even just "-tags='a'".
if *v == nil { if strings.Contains(s, " ") || strings.Contains(s, "'") {
*v = []string{} var err error
*v, err = splitQuotedFields(s)
if *v == nil {
*v = []string{}
}
return err
} }
return err
// Starting in Go 1.13, the -tags flag is a comma-separated list of build tags.
*v = []string{}
for _, s := range strings.Split(s, ",") {
if s != "" {
*v = append(*v, s)
}
}
return nil
} }
func (v *TagsFlag) Get() interface{} { return *v } func (v *TagsFlag) Get() interface{} { return *v }
func splitQuotedFields(s string) ([]string, error) { func splitQuotedFields(s string) ([]string, error) {
// Split fields allowing '' or "" around elements. // See $GOROOT/src/cmd/internal/quoted/quoted.go (Split)
// Quotes further inside the string do not count. // This must remain in sync with that logic.
var f []string var f []string
for len(s) > 0 { for len(s) > 0 {
for len(s) > 0 && isSpaceByte(s[0]) { for len(s) > 0 && isSpaceByte(s[0]) {
@ -76,5 +94,7 @@ func (v *TagsFlag) String() string {
} }
func isSpaceByte(c byte) bool { func isSpaceByte(c byte) bool {
// See $GOROOT/src/cmd/internal/quoted/quoted.go (isSpaceByte, Split)
// This list must remain in sync with that.
return c == ' ' || c == '\t' || c == '\n' || c == '\r' return c == ' ' || c == '\t' || c == '\n' || c == '\r'
} }

View file

@ -47,7 +47,7 @@ import (
func Find(importPath, srcDir string) (filename, path string) { func Find(importPath, srcDir string) (filename, path string) {
cmd := exec.Command("go", "list", "-json", "-export", "--", importPath) cmd := exec.Command("go", "list", "-json", "-export", "--", importPath)
cmd.Dir = srcDir cmd.Dir = srcDir
out, err := cmd.CombinedOutput() out, err := cmd.Output()
if err != nil { if err != nil {
return "", "" return "", ""
} }

View file

@ -15,12 +15,15 @@ import (
// pkgConfig runs pkg-config with the specified arguments and returns the flags it prints. // pkgConfig runs pkg-config with the specified arguments and returns the flags it prints.
func pkgConfig(mode string, pkgs []string) (flags []string, err error) { func pkgConfig(mode string, pkgs []string) (flags []string, err error) {
cmd := exec.Command("pkg-config", append([]string{mode}, pkgs...)...) cmd := exec.Command("pkg-config", append([]string{mode}, pkgs...)...)
out, err := cmd.CombinedOutput() out, err := cmd.Output()
if err != nil { if err != nil {
s := fmt.Sprintf("%s failed: %v", strings.Join(cmd.Args, " "), err) s := fmt.Sprintf("%s failed: %v", strings.Join(cmd.Args, " "), err)
if len(out) > 0 { if len(out) > 0 {
s = fmt.Sprintf("%s: %s", s, out) s = fmt.Sprintf("%s: %s", s, out)
} }
if err, ok := err.(*exec.ExitError); ok && len(err.Stderr) > 0 {
s = fmt.Sprintf("%s\nstderr:\n%s", s, err.Stderr)
}
return nil, errors.New(s) return nil, errors.New(s)
} }
if len(out) > 0 { if len(out) > 0 {

View file

@ -15,22 +15,10 @@ Load passes most patterns directly to the underlying build tool.
The default build tool is the go command. The default build tool is the go command.
Its supported patterns are described at Its supported patterns are described at
https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns. https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.
Other build systems may be supported by providing a "driver";
see [The driver protocol].
Load may be used in Go projects that use alternative build systems, by All patterns with the prefix "query=", where query is a
installing an appropriate "driver" program for the build system and
specifying its location in the GOPACKAGESDRIVER environment variable.
For example,
https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
explains how to use the driver for Bazel.
The driver program is responsible for interpreting patterns in its
preferred notation and reporting information about the packages that
they identify.
(See driverRequest and driverResponse types for the JSON
schema used by the protocol.
Though the protocol is supported, these types are currently unexported;
see #64608 for a proposal to publish them.)
Regardless of driver, all patterns with the prefix "query=", where query is a
non-empty string of letters from [a-z], are reserved and may be non-empty string of letters from [a-z], are reserved and may be
interpreted as query operators. interpreted as query operators.
@ -86,7 +74,29 @@ for details.
Most tools should pass their command-line arguments (after any flags) Most tools should pass their command-line arguments (after any flags)
uninterpreted to [Load], so that it can interpret them uninterpreted to [Load], so that it can interpret them
according to the conventions of the underlying build system. according to the conventions of the underlying build system.
See the Example function for typical usage. See the Example function for typical usage.
# The driver protocol
[Load] may be used to load Go packages even in Go projects that use
alternative build systems, by installing an appropriate "driver"
program for the build system and specifying its location in the
GOPACKAGESDRIVER environment variable.
For example,
https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
explains how to use the driver for Bazel.
The driver program is responsible for interpreting patterns in its
preferred notation and reporting information about the packages that
those patterns identify. Drivers must also support the special "file="
and "pattern=" patterns described above.
The patterns are provided as positional command-line arguments. A
JSON-encoded [DriverRequest] message providing additional information
is written to the driver's standard input. The driver must write a
JSON-encoded [DriverResponse] message to its standard output. (This
message differs from the JSON schema produced by 'go list'.)
*/ */
package packages // import "golang.org/x/tools/go/packages" package packages // import "golang.org/x/tools/go/packages"

View file

@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This file enables an external tool to intercept package requests.
// If the tool is present then its results are used in preference to
// the go list command.
package packages package packages
// This file defines the protocol that enables an external "driver"
// tool to supply package metadata in place of 'go list'.
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
@ -17,31 +16,71 @@ import (
"strings" "strings"
) )
// The Driver Protocol // DriverRequest defines the schema of a request for package metadata
// from an external driver program. The JSON-encoded DriverRequest
// message is provided to the driver program's standard input. The
// query patterns are provided as command-line arguments.
// //
// The driver, given the inputs to a call to Load, returns metadata about the packages specified. // See the package documentation for an overview.
// This allows for different build systems to support go/packages by telling go/packages how the type DriverRequest struct {
// packages' source is organized.
// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in
// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package
// documentation in doc.go for the full description of the patterns that need to be supported.
// A driver receives as a JSON-serialized driverRequest struct in standard input and will
// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output.
// driverRequest is used to provide the portion of Load's Config that is needed by a driver.
type driverRequest struct {
Mode LoadMode `json:"mode"` Mode LoadMode `json:"mode"`
// Env specifies the environment the underlying build system should be run in. // Env specifies the environment the underlying build system should be run in.
Env []string `json:"env"` Env []string `json:"env"`
// BuildFlags are flags that should be passed to the underlying build system. // BuildFlags are flags that should be passed to the underlying build system.
BuildFlags []string `json:"build_flags"` BuildFlags []string `json:"build_flags"`
// Tests specifies whether the patterns should also return test packages. // Tests specifies whether the patterns should also return test packages.
Tests bool `json:"tests"` Tests bool `json:"tests"`
// Overlay maps file paths (relative to the driver's working directory) to the byte contents // Overlay maps file paths (relative to the driver's working directory) to the byte contents
// of overlay files. // of overlay files.
Overlay map[string][]byte `json:"overlay"` Overlay map[string][]byte `json:"overlay"`
} }
// DriverResponse defines the schema of a response from an external
// driver program, providing the results of a query for package
// metadata. The driver program must write a JSON-encoded
// DriverResponse message to its standard output.
//
// See the package documentation for an overview.
type DriverResponse struct {
// NotHandled is returned if the request can't be handled by the current
// driver. If an external driver returns a response with NotHandled, the
// rest of the DriverResponse is ignored, and go/packages will fallback
// to the next driver. If go/packages is extended in the future to support
// lists of multiple drivers, go/packages will fall back to the next driver.
NotHandled bool
// Compiler and Arch are the arguments pass of types.SizesFor
// to get a types.Sizes to use when type checking.
Compiler string
Arch string
// Roots is the set of package IDs that make up the root packages.
// We have to encode this separately because when we encode a single package
// we cannot know if it is one of the roots as that requires knowledge of the
// graph it is part of.
Roots []string `json:",omitempty"`
// Packages is the full set of packages in the graph.
// The packages are not connected into a graph.
// The Imports if populated will be stubs that only have their ID set.
// Imports will be connected and then type and syntax information added in a
// later pass (see refine).
Packages []*Package
// GoVersion is the minor version number used by the driver
// (e.g. the go command on the PATH) when selecting .go files.
// Zero means unknown.
GoVersion int
}
// driver is the type for functions that query the build system for the
// packages named by the patterns.
type driver func(cfg *Config, patterns ...string) (*DriverResponse, error)
// findExternalDriver returns the file path of a tool that supplies // findExternalDriver returns the file path of a tool that supplies
// the build system package structure, or "" if not found." // the build system package structure, or "" if not found."
// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
@ -64,8 +103,8 @@ func findExternalDriver(cfg *Config) driver {
return nil return nil
} }
} }
return func(cfg *Config, words ...string) (*driverResponse, error) { return func(cfg *Config, words ...string) (*DriverResponse, error) {
req, err := json.Marshal(driverRequest{ req, err := json.Marshal(DriverRequest{
Mode: cfg.Mode, Mode: cfg.Mode,
Env: cfg.Env, Env: cfg.Env,
BuildFlags: cfg.BuildFlags, BuildFlags: cfg.BuildFlags,
@ -92,7 +131,7 @@ func findExternalDriver(cfg *Config) driver {
fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr) fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
} }
var response driverResponse var response DriverResponse
if err := json.Unmarshal(buf.Bytes(), &response); err != nil { if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
return nil, err return nil, err
} }

View file

@ -35,23 +35,23 @@ type goTooOldError struct {
error error
} }
// responseDeduper wraps a driverResponse, deduplicating its contents. // responseDeduper wraps a DriverResponse, deduplicating its contents.
type responseDeduper struct { type responseDeduper struct {
seenRoots map[string]bool seenRoots map[string]bool
seenPackages map[string]*Package seenPackages map[string]*Package
dr *driverResponse dr *DriverResponse
} }
func newDeduper() *responseDeduper { func newDeduper() *responseDeduper {
return &responseDeduper{ return &responseDeduper{
dr: &driverResponse{}, dr: &DriverResponse{},
seenRoots: map[string]bool{}, seenRoots: map[string]bool{},
seenPackages: map[string]*Package{}, seenPackages: map[string]*Package{},
} }
} }
// addAll fills in r with a driverResponse. // addAll fills in r with a DriverResponse.
func (r *responseDeduper) addAll(dr *driverResponse) { func (r *responseDeduper) addAll(dr *DriverResponse) {
for _, pkg := range dr.Packages { for _, pkg := range dr.Packages {
r.addPackage(pkg) r.addPackage(pkg)
} }
@ -128,7 +128,7 @@ func (state *golistState) mustGetEnv() map[string]string {
// goListDriver uses the go list command to interpret the patterns and produce // goListDriver uses the go list command to interpret the patterns and produce
// the build system package structure. // the build system package structure.
// See driver for more details. // See driver for more details.
func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error) {
// Make sure that any asynchronous go commands are killed when we return. // Make sure that any asynchronous go commands are killed when we return.
parentCtx := cfg.Context parentCtx := cfg.Context
if parentCtx == nil { if parentCtx == nil {
@ -146,16 +146,18 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
} }
// Fill in response.Sizes asynchronously if necessary. // Fill in response.Sizes asynchronously if necessary.
var sizeserr error
var sizeswg sync.WaitGroup
if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 {
sizeswg.Add(1) errCh := make(chan error)
go func() { go func() {
compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner) compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner)
sizeserr = err
response.dr.Compiler = compiler response.dr.Compiler = compiler
response.dr.Arch = arch response.dr.Arch = arch
sizeswg.Done() errCh <- err
}()
defer func() {
if sizesErr := <-errCh; sizesErr != nil {
err = sizesErr
}
}() }()
} }
@ -208,10 +210,7 @@ extractQueries:
} }
} }
sizeswg.Wait() // (We may yet return an error due to defer.)
if sizeserr != nil {
return nil, sizeserr
}
return response.dr, nil return response.dr, nil
} }
@ -266,7 +265,7 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries
// adhocPackage attempts to load or construct an ad-hoc package for a given // adhocPackage attempts to load or construct an ad-hoc package for a given
// query, if the original call to the driver produced inadequate results. // query, if the original call to the driver produced inadequate results.
func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) { func (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) {
response, err := state.createDriverResponse(query) response, err := state.createDriverResponse(query)
if err != nil { if err != nil {
return nil, err return nil, err
@ -357,7 +356,7 @@ func otherFiles(p *jsonPackage) [][]string {
// createDriverResponse uses the "go list" command to expand the pattern // createDriverResponse uses the "go list" command to expand the pattern
// words and return a response for the specified packages. // words and return a response for the specified packages.
func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) { func (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) {
// go list uses the following identifiers in ImportPath and Imports: // go list uses the following identifiers in ImportPath and Imports:
// //
// "p" -- importable package or main (command) // "p" -- importable package or main (command)
@ -384,7 +383,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
pkgs := make(map[string]*Package) pkgs := make(map[string]*Package)
additionalErrors := make(map[string][]Error) additionalErrors := make(map[string][]Error)
// Decode the JSON and convert it to Package form. // Decode the JSON and convert it to Package form.
response := &driverResponse{ response := &DriverResponse{
GoVersion: goVersion, GoVersion: goVersion,
} }
for dec := json.NewDecoder(buf); dec.More(); { for dec := json.NewDecoder(buf); dec.More(); {

View file

@ -206,43 +206,6 @@ type Config struct {
Overlay map[string][]byte Overlay map[string][]byte
} }
// driver is the type for functions that query the build system for the
// packages named by the patterns.
type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
// driverResponse contains the results for a driver query.
type driverResponse struct {
// NotHandled is returned if the request can't be handled by the current
// driver. If an external driver returns a response with NotHandled, the
// rest of the driverResponse is ignored, and go/packages will fallback
// to the next driver. If go/packages is extended in the future to support
// lists of multiple drivers, go/packages will fall back to the next driver.
NotHandled bool
// Compiler and Arch are the arguments pass of types.SizesFor
// to get a types.Sizes to use when type checking.
Compiler string
Arch string
// Roots is the set of package IDs that make up the root packages.
// We have to encode this separately because when we encode a single package
// we cannot know if it is one of the roots as that requires knowledge of the
// graph it is part of.
Roots []string `json:",omitempty"`
// Packages is the full set of packages in the graph.
// The packages are not connected into a graph.
// The Imports if populated will be stubs that only have their ID set.
// Imports will be connected and then type and syntax information added in a
// later pass (see refine).
Packages []*Package
// GoVersion is the minor version number used by the driver
// (e.g. the go command on the PATH) when selecting .go files.
// Zero means unknown.
GoVersion int
}
// Load loads and returns the Go packages named by the given patterns. // Load loads and returns the Go packages named by the given patterns.
// //
// Config specifies loading options; // Config specifies loading options;
@ -291,7 +254,7 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) {
// no external driver, or the driver returns a response with NotHandled set, // no external driver, or the driver returns a response with NotHandled set,
// defaultDriver will fall back to the go list driver. // defaultDriver will fall back to the go list driver.
// The boolean result indicates that an external driver handled the request. // The boolean result indicates that an external driver handled the request.
func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, error) { func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {
if driver := findExternalDriver(cfg); driver != nil { if driver := findExternalDriver(cfg); driver != nil {
response, err := driver(cfg, patterns...) response, err := driver(cfg, patterns...)
if err != nil { if err != nil {
@ -303,7 +266,10 @@ func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, erro
} }
response, err := goListDriver(cfg, patterns...) response, err := goListDriver(cfg, patterns...)
return response, false, err if err != nil {
return nil, false, err
}
return response, false, nil
} }
// A Package describes a loaded Go package. // A Package describes a loaded Go package.
@ -648,7 +614,7 @@ func newLoader(cfg *Config) *loader {
// refine connects the supplied packages into a graph and then adds type // refine connects the supplied packages into a graph and then adds type
// and syntax information as requested by the LoadMode. // and syntax information as requested by the LoadMode.
func (ld *loader) refine(response *driverResponse) ([]*Package, error) { func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
roots := response.Roots roots := response.Roots
rootMap := make(map[string]int, len(roots)) rootMap := make(map[string]int, len(roots))
for i, root := range roots { for i, root := range roots {

View file

@ -29,9 +29,13 @@ import (
"strconv" "strconv"
"strings" "strings"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/typeparams"
"golang.org/x/tools/internal/typesinternal"
) )
// TODO(adonovan): think about generic aliases.
// A Path is an opaque name that identifies a types.Object // A Path is an opaque name that identifies a types.Object
// relative to its package. Conceptually, the name consists of a // relative to its package. Conceptually, the name consists of a
// sequence of destructuring operations applied to the package scope // sequence of destructuring operations applied to the package scope
@ -223,7 +227,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
// Reject obviously non-viable cases. // Reject obviously non-viable cases.
switch obj := obj.(type) { switch obj := obj.(type) {
case *types.TypeName: case *types.TypeName:
if _, ok := obj.Type().(*types.TypeParam); !ok { if _, ok := aliases.Unalias(obj.Type()).(*types.TypeParam); !ok {
// With the exception of type parameters, only package-level type names // With the exception of type parameters, only package-level type names
// have a path. // have a path.
return "", fmt.Errorf("no path for %v", obj) return "", fmt.Errorf("no path for %v", obj)
@ -310,7 +314,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
} }
// Inspect declared methods of defined types. // Inspect declared methods of defined types.
if T, ok := o.Type().(*types.Named); ok { if T, ok := aliases.Unalias(o.Type()).(*types.Named); ok {
path = append(path, opType) path = append(path, opType)
// The method index here is always with respect // The method index here is always with respect
// to the underlying go/types data structures, // to the underlying go/types data structures,
@ -395,13 +399,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
return "", false return "", false
} }
recvT := meth.Type().(*types.Signature).Recv().Type() _, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv())
if ptr, ok := recvT.(*types.Pointer); ok { if named == nil {
recvT = ptr.Elem()
}
named, ok := recvT.(*types.Named)
if !ok {
return "", false return "", false
} }
@ -444,6 +443,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
// nil, it will be allocated as necessary. // nil, it will be allocated as necessary.
func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte {
switch T := T.(type) { switch T := T.(type) {
case *aliases.Alias:
return find(obj, aliases.Unalias(T), path, seen)
case *types.Basic, *types.Named: case *types.Basic, *types.Named:
// Named types belonging to pkg were handled already, // Named types belonging to pkg were handled already,
// so T must belong to another package. No path. // so T must belong to another package. No path.
@ -616,6 +617,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
// Inv: t != nil, obj == nil // Inv: t != nil, obj == nil
t = aliases.Unalias(t)
switch code { switch code {
case opElem: case opElem:
hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map

28
vendor/golang.org/x/tools/internal/aliases/aliases.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
// Copyright 2024 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 aliases
import (
"go/token"
"go/types"
)
// Package aliases defines backward compatible shims
// for the types.Alias type representation added in 1.22.
// This defines placeholders for x/tools until 1.26.
// NewAlias creates a new TypeName in Package pkg that
// is an alias for the type rhs.
//
// When GoVersion>=1.22 and GODEBUG=gotypesalias=1,
// the Type() of the return value is a *types.Alias.
func NewAlias(pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName {
if enabled() {
tname := types.NewTypeName(pos, pkg, name, nil)
newAlias(tname, rhs)
return tname
}
return types.NewTypeName(pos, pkg, name, rhs)
}

View file

@ -0,0 +1,30 @@
// Copyright 2024 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.
//go:build !go1.22
// +build !go1.22
package aliases
import (
"go/types"
)
// Alias is a placeholder for a go/types.Alias for <=1.21.
// It will never be created by go/types.
type Alias struct{}
func (*Alias) String() string { panic("unreachable") }
func (*Alias) Underlying() types.Type { panic("unreachable") }
func (*Alias) Obj() *types.TypeName { panic("unreachable") }
// Unalias returns the type t for go <=1.21.
func Unalias(t types.Type) types.Type { return t }
// Always false for go <=1.21. Ignores GODEBUG.
func enabled() bool { return false }
func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") }

View file

@ -0,0 +1,72 @@
// Copyright 2024 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.
//go:build go1.22
// +build go1.22
package aliases
import (
"go/ast"
"go/parser"
"go/token"
"go/types"
"os"
"strings"
"sync"
)
// Alias is an alias of types.Alias.
type Alias = types.Alias
// Unalias is a wrapper of types.Unalias.
func Unalias(t types.Type) types.Type { return types.Unalias(t) }
// newAlias is an internal alias around types.NewAlias.
// Direct usage is discouraged as the moment.
// Try to use NewAlias instead.
func newAlias(tname *types.TypeName, rhs types.Type) *Alias {
a := types.NewAlias(tname, rhs)
// TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect.
Unalias(a)
return a
}
// enabled returns true when types.Aliases are enabled.
func enabled() bool {
// Use the gotypesalias value in GODEBUG if set.
godebug := os.Getenv("GODEBUG")
value := -1 // last set value.
for _, f := range strings.Split(godebug, ",") {
switch f {
case "gotypesalias=1":
value = 1
case "gotypesalias=0":
value = 0
}
}
switch value {
case 0:
return false
case 1:
return true
default:
return aliasesDefault()
}
}
// aliasesDefault reports if aliases are enabled by default.
func aliasesDefault() bool {
// Dynamically check if Aliases will be produced from go/types.
aliasesDefaultOnce.Do(func() {
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0)
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
_, gotypesaliasDefault = pkg.Scope().Lookup("A").Type().(*types.Alias)
})
return gotypesaliasDefault
}
var gotypesaliasDefault bool
var aliasesDefaultOnce sync.Once

View file

@ -259,13 +259,6 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
return return
} }
func deref(typ types.Type) types.Type {
if p, _ := typ.(*types.Pointer); p != nil {
return p.Elem()
}
return typ
}
type byPath []*types.Package type byPath []*types.Package
func (a byPath) Len() int { return len(a) } func (a byPath) Len() int { return len(a) }

View file

@ -23,6 +23,7 @@ import (
"strings" "strings"
"golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/go/types/objectpath"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/tokeninternal" "golang.org/x/tools/internal/tokeninternal"
) )
@ -506,13 +507,13 @@ func (p *iexporter) doDecl(obj types.Object) {
case *types.TypeName: case *types.TypeName:
t := obj.Type() t := obj.Type()
if tparam, ok := t.(*types.TypeParam); ok { if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok {
w.tag('P') w.tag('P')
w.pos(obj.Pos()) w.pos(obj.Pos())
constraint := tparam.Constraint() constraint := tparam.Constraint()
if p.version >= iexportVersionGo1_18 { if p.version >= iexportVersionGo1_18 {
implicit := false implicit := false
if iface, _ := constraint.(*types.Interface); iface != nil { if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil {
implicit = iface.IsImplicit() implicit = iface.IsImplicit()
} }
w.bool(implicit) w.bool(implicit)
@ -738,6 +739,8 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
}() }()
} }
switch t := t.(type) { switch t := t.(type) {
// TODO(adonovan): support types.Alias.
case *types.Named: case *types.Named:
if targs := t.TypeArgs(); targs.Len() > 0 { if targs := t.TypeArgs(); targs.Len() > 0 {
w.startType(instanceType) w.startType(instanceType)
@ -843,7 +846,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
ft := t.EmbeddedType(i) ft := t.EmbeddedType(i)
tPkg := pkg tPkg := pkg
if named, _ := ft.(*types.Named); named != nil { if named, _ := aliases.Unalias(ft).(*types.Named); named != nil {
w.pos(named.Obj().Pos()) w.pos(named.Obj().Pos())
} else { } else {
w.pos(token.NoPos) w.pos(token.NoPos)

View file

@ -22,6 +22,8 @@ import (
"strings" "strings"
"golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/go/types/objectpath"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/typesinternal"
) )
type intReader struct { type intReader struct {
@ -224,6 +226,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
// Gather the relevant packages from the manifest. // Gather the relevant packages from the manifest.
items := make([]GetPackagesItem, r.uint64()) items := make([]GetPackagesItem, r.uint64())
uniquePkgPaths := make(map[string]bool)
for i := range items { for i := range items {
pkgPathOff := r.uint64() pkgPathOff := r.uint64()
pkgPath := p.stringAt(pkgPathOff) pkgPath := p.stringAt(pkgPathOff)
@ -248,6 +251,12 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
} }
items[i].nameIndex = nameIndex items[i].nameIndex = nameIndex
uniquePkgPaths[pkgPath] = true
}
// Debugging #63822; hypothesis: there are duplicate PkgPaths.
if len(uniquePkgPaths) != len(items) {
reportf("found duplicate PkgPaths while reading export data manifest: %v", items)
} }
// Request packages all at once from the client, // Request packages all at once from the client,
@ -515,7 +524,7 @@ func canReuse(def *types.Named, rhs types.Type) bool {
if def == nil { if def == nil {
return true return true
} }
iface, _ := rhs.(*types.Interface) iface, _ := aliases.Unalias(rhs).(*types.Interface)
if iface == nil { if iface == nil {
return true return true
} }
@ -580,14 +589,13 @@ func (r *importReader) obj(name string) {
// If the receiver has any targs, set those as the // If the receiver has any targs, set those as the
// rparams of the method (since those are the // rparams of the method (since those are the
// typeparams being used in the method sig/body). // typeparams being used in the method sig/body).
base := baseType(recv.Type()) _, recvNamed := typesinternal.ReceiverNamed(recv)
assert(base != nil) targs := recvNamed.TypeArgs()
targs := base.TypeArgs()
var rparams []*types.TypeParam var rparams []*types.TypeParam
if targs.Len() > 0 { if targs.Len() > 0 {
rparams = make([]*types.TypeParam, targs.Len()) rparams = make([]*types.TypeParam, targs.Len())
for i := range rparams { for i := range rparams {
rparams[i] = targs.At(i).(*types.TypeParam) rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam)
} }
} }
msig := r.signature(recv, rparams, nil) msig := r.signature(recv, rparams, nil)
@ -617,7 +625,7 @@ func (r *importReader) obj(name string) {
} }
constraint := r.typ() constraint := r.typ()
if implicit { if implicit {
iface, _ := constraint.(*types.Interface) iface, _ := aliases.Unalias(constraint).(*types.Interface)
if iface == nil { if iface == nil {
errorf("non-interface constraint marked implicit") errorf("non-interface constraint marked implicit")
} }
@ -824,7 +832,7 @@ func (r *importReader) typ() types.Type {
} }
func isInterface(t types.Type) bool { func isInterface(t types.Type) bool {
_, ok := t.(*types.Interface) _, ok := aliases.Unalias(t).(*types.Interface)
return ok return ok
} }
@ -1023,7 +1031,7 @@ func (r *importReader) tparamList() []*types.TypeParam {
for i := range xs { for i := range xs {
// Note: the standard library importer is tolerant of nil types here, // Note: the standard library importer is tolerant of nil types here,
// though would panic in SetTypeParams. // though would panic in SetTypeParams.
xs[i] = r.typ().(*types.TypeParam) xs[i] = aliases.Unalias(r.typ()).(*types.TypeParam)
} }
return xs return xs
} }
@ -1070,13 +1078,3 @@ func (r *importReader) byte() byte {
} }
return x return x
} }
func baseType(typ types.Type) *types.Named {
// pointer receivers are never types.Named types
if p, _ := typ.(*types.Pointer); p != nil {
typ = p.Elem()
}
// receiver base types are always (possibly generic) types.Named types
n, _ := typ.(*types.Named)
return n
}

View file

@ -1,16 +0,0 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.18
// +build !go1.18
package gcimporter
import "go/types"
const iexportVersion = iexportVersionGo1_11
func additionalPredeclared() []types.Type {
return nil
}

View file

@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package gcimporter package gcimporter
import "go/types" import "go/types"

View file

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(go1.18 && goexperiment.unified) //go:build !goexperiment.unified
// +build !go1.18 !goexperiment.unified // +build !goexperiment.unified
package gcimporter package gcimporter

View file

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build go1.18 && goexperiment.unified //go:build goexperiment.unified
// +build go1.18,goexperiment.unified // +build goexperiment.unified
package gcimporter package gcimporter

View file

@ -1,19 +0,0 @@
// Copyright 2022 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.
//go:build !go1.18
// +build !go1.18
package gcimporter
import (
"fmt"
"go/token"
"go/types"
)
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
err = fmt.Errorf("go/tools compiled with a Go version earlier than 1.18 cannot read unified IR export data")
return
}

View file

@ -4,9 +4,6 @@
// Derived from go/internal/gcimporter/ureader.go // Derived from go/internal/gcimporter/ureader.go
//go:build go1.18
// +build go1.18
package gcimporter package gcimporter
import ( import (
@ -16,6 +13,7 @@ import (
"sort" "sort"
"strings" "strings"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/pkgbits" "golang.org/x/tools/internal/pkgbits"
) )
@ -553,7 +551,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
// If the underlying type is an interface, we need to // If the underlying type is an interface, we need to
// duplicate its methods so we can replace the receiver // duplicate its methods so we can replace the receiver
// parameter's type (#49906). // parameter's type (#49906).
if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { if iface, ok := aliases.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
methods := make([]*types.Func, iface.NumExplicitMethods()) methods := make([]*types.Func, iface.NumExplicitMethods())
for i := range methods { for i := range methods {
fn := iface.ExplicitMethod(i) fn := iface.ExplicitMethod(i)

View file

@ -9,11 +9,13 @@ package gopathwalk
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"io"
"io/fs" "io/fs"
"log"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"sync"
"time" "time"
) )
@ -21,8 +23,13 @@ import (
type Options struct { type Options struct {
// If Logf is non-nil, debug logging is enabled through this function. // If Logf is non-nil, debug logging is enabled through this function.
Logf func(format string, args ...interface{}) Logf func(format string, args ...interface{})
// Search module caches. Also disables legacy goimports ignore rules. // Search module caches. Also disables legacy goimports ignore rules.
ModulesEnabled bool ModulesEnabled bool
// Maximum number of concurrent calls to user-provided callbacks,
// or 0 for GOMAXPROCS.
Concurrency int
} }
// RootType indicates the type of a Root. // RootType indicates the type of a Root.
@ -43,19 +50,28 @@ type Root struct {
Type RootType Type RootType
} }
// Walk walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. // Walk concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to find packages.
//
// For each package found, add will be called with the absolute // For each package found, add will be called with the absolute
// paths of the containing source directory and the package directory. // paths of the containing source directory and the package directory.
//
// Unlike filepath.WalkDir, Walk follows symbolic links
// (while guarding against cycles).
func Walk(roots []Root, add func(root Root, dir string), opts Options) { func Walk(roots []Root, add func(root Root, dir string), opts Options) {
WalkSkip(roots, add, func(Root, string) bool { return false }, opts) WalkSkip(roots, add, func(Root, string) bool { return false }, opts)
} }
// WalkSkip walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. // WalkSkip concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to
// find packages.
//
// For each package found, add will be called with the absolute // For each package found, add will be called with the absolute
// paths of the containing source directory and the package directory. // paths of the containing source directory and the package directory.
// For each directory that will be scanned, skip will be called // For each directory that will be scanned, skip will be called
// with the absolute paths of the containing source directory and the directory. // with the absolute paths of the containing source directory and the directory.
// If skip returns false on a directory it will be processed. // If skip returns false on a directory it will be processed.
//
// Unlike filepath.WalkDir, WalkSkip follows symbolic links
// (while guarding against cycles).
func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root, dir string) bool, opts Options) { func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root, dir string) bool, opts Options) {
for _, root := range roots { for _, root := range roots {
walkDir(root, add, skip, opts) walkDir(root, add, skip, opts)
@ -64,45 +80,51 @@ func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root
// walkDir creates a walker and starts fastwalk with this walker. // walkDir creates a walker and starts fastwalk with this walker.
func walkDir(root Root, add func(Root, string), skip func(root Root, dir string) bool, opts Options) { func walkDir(root Root, add func(Root, string), skip func(root Root, dir string) bool, opts Options) {
if opts.Logf == nil {
opts.Logf = func(format string, args ...interface{}) {}
}
if _, err := os.Stat(root.Path); os.IsNotExist(err) { if _, err := os.Stat(root.Path); os.IsNotExist(err) {
if opts.Logf != nil { opts.Logf("skipping nonexistent directory: %v", root.Path)
opts.Logf("skipping nonexistent directory: %v", root.Path)
}
return return
} }
start := time.Now() start := time.Now()
if opts.Logf != nil { opts.Logf("scanning %s", root.Path)
opts.Logf("scanning %s", root.Path)
}
concurrency := opts.Concurrency
if concurrency == 0 {
// The walk be either CPU-bound or I/O-bound, depending on what the
// caller-supplied add function does and the details of the user's platform
// and machine. Rather than trying to fine-tune the concurrency level for a
// specific environment, we default to GOMAXPROCS: it is likely to be a good
// choice for a CPU-bound add function, and if it is instead I/O-bound, then
// dealing with I/O saturation is arguably the job of the kernel and/or
// runtime. (Oversaturating I/O seems unlikely to harm performance as badly
// as failing to saturate would.)
concurrency = runtime.GOMAXPROCS(0)
}
w := &walker{ w := &walker{
root: root, root: root,
add: add, add: add,
skip: skip, skip: skip,
opts: opts, opts: opts,
added: make(map[string]bool), sem: make(chan struct{}, concurrency),
} }
w.init() w.init()
// Add a trailing path separator to cause filepath.WalkDir to traverse symlinks. w.sem <- struct{}{}
path := root.Path path := root.Path
if len(path) == 0 { if path == "" {
path = "." + string(filepath.Separator) path = "."
} else if !os.IsPathSeparator(path[len(path)-1]) {
path = path + string(filepath.Separator)
} }
if fi, err := os.Lstat(path); err == nil {
w.walk(path, nil, fs.FileInfoToDirEntry(fi))
} else {
w.opts.Logf("scanning directory %v: %v", root.Path, err)
}
<-w.sem
w.walking.Wait()
if err := filepath.WalkDir(path, w.walk); err != nil { opts.Logf("scanned %s in %v", root.Path, time.Since(start))
logf := opts.Logf
if logf == nil {
logf = log.Printf
}
logf("scanning directory %v: %v", root.Path, err)
}
if opts.Logf != nil {
opts.Logf("scanned %s in %v", root.Path, time.Since(start))
}
} }
// walker is the callback for fastwalk.Walk. // walker is the callback for fastwalk.Walk.
@ -112,10 +134,18 @@ type walker struct {
skip func(Root, string) bool // The callback that will be invoked for every dir. dir is skipped if it returns true. skip func(Root, string) bool // The callback that will be invoked for every dir. dir is skipped if it returns true.
opts Options // Options passed to Walk by the user. opts Options // Options passed to Walk by the user.
pathSymlinks []os.FileInfo walking sync.WaitGroup
ignoredDirs []string sem chan struct{} // Channel of semaphore tokens; send to acquire, receive to release.
ignoredDirs []string
added map[string]bool added sync.Map // map[string]bool
}
// A symlinkList is a linked list of os.FileInfos for parent directories
// reached via symlinks.
type symlinkList struct {
info os.FileInfo
prev *symlinkList
} }
// init initializes the walker based on its Options // init initializes the walker based on its Options
@ -132,9 +162,7 @@ func (w *walker) init() {
for _, p := range ignoredPaths { for _, p := range ignoredPaths {
full := filepath.Join(w.root.Path, p) full := filepath.Join(w.root.Path, p)
w.ignoredDirs = append(w.ignoredDirs, full) w.ignoredDirs = append(w.ignoredDirs, full)
if w.opts.Logf != nil { w.opts.Logf("Directory added to ignore list: %s", full)
w.opts.Logf("Directory added to ignore list: %s", full)
}
} }
} }
@ -144,12 +172,10 @@ func (w *walker) init() {
func (w *walker) getIgnoredDirs(path string) []string { func (w *walker) getIgnoredDirs(path string) []string {
file := filepath.Join(path, ".goimportsignore") file := filepath.Join(path, ".goimportsignore")
slurp, err := os.ReadFile(file) slurp, err := os.ReadFile(file)
if w.opts.Logf != nil { if err != nil {
if err != nil { w.opts.Logf("%v", err)
w.opts.Logf("%v", err) } else {
} else { w.opts.Logf("Read %s", file)
w.opts.Logf("Read %s", file)
}
} }
if err != nil { if err != nil {
return nil return nil
@ -183,63 +209,22 @@ func (w *walker) shouldSkipDir(dir string) bool {
// walk walks through the given path. // walk walks through the given path.
// //
// Errors are logged if w.opts.Logf is non-nil, but otherwise ignored: // Errors are logged if w.opts.Logf is non-nil, but otherwise ignored.
// walk returns only nil or fs.SkipDir. func (w *walker) walk(path string, pathSymlinks *symlinkList, d fs.DirEntry) {
func (w *walker) walk(path string, d fs.DirEntry, err error) error {
if err != nil {
// We have no way to report errors back through Walk or WalkSkip,
// so just log and ignore them.
if w.opts.Logf != nil {
w.opts.Logf("%v", err)
}
if d == nil {
// Nothing more to do: the error prevents us from knowing
// what path even represents.
return nil
}
}
if d.Type().IsRegular() {
if !strings.HasSuffix(path, ".go") {
return nil
}
dir := filepath.Dir(path)
if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) {
// Doesn't make sense to have regular files
// directly in your $GOPATH/src or $GOROOT/src.
return nil
}
if !w.added[dir] {
w.add(w.root, dir)
w.added[dir] = true
}
return nil
}
if d.IsDir() {
base := filepath.Base(path)
if base == "" || base[0] == '.' || base[0] == '_' ||
base == "testdata" ||
(w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") ||
(!w.opts.ModulesEnabled && base == "node_modules") {
return fs.SkipDir
}
if w.shouldSkipDir(path) {
return fs.SkipDir
}
return nil
}
if d.Type()&os.ModeSymlink != 0 { if d.Type()&os.ModeSymlink != 0 {
// Walk the symlink's target rather than the symlink itself.
//
// (Note that os.Stat, unlike the lower-lever os.Readlink,
// follows arbitrarily many layers of symlinks, so it will eventually
// reach either a non-symlink or a nonexistent target.)
//
// TODO(bcmills): 'go list all' itself ignores symlinks within GOROOT/src // TODO(bcmills): 'go list all' itself ignores symlinks within GOROOT/src
// and GOPATH/src. Do we really need to traverse them here? If so, why? // and GOPATH/src. Do we really need to traverse them here? If so, why?
fi, err := os.Stat(path) fi, err := os.Stat(path)
if err != nil || !fi.IsDir() { if err != nil {
// Not a directory. Just walk the file (or broken link) and be done. w.opts.Logf("%v", err)
return w.walk(path, fs.FileInfoToDirEntry(fi), err) return
} }
// Avoid walking symlink cycles: if we have already followed a symlink to // Avoid walking symlink cycles: if we have already followed a symlink to
@ -249,83 +234,104 @@ func (w *walker) walk(path string, d fs.DirEntry, err error) error {
// the number of extra stat calls we make if we *don't* encounter a cycle. // the number of extra stat calls we make if we *don't* encounter a cycle.
// Since we don't actually expect to encounter symlink cycles in practice, // Since we don't actually expect to encounter symlink cycles in practice,
// this seems like the right tradeoff. // this seems like the right tradeoff.
for _, parent := range w.pathSymlinks { for parent := pathSymlinks; parent != nil; parent = parent.prev {
if os.SameFile(fi, parent) { if os.SameFile(fi, parent.info) {
return nil return
} }
} }
w.pathSymlinks = append(w.pathSymlinks, fi) pathSymlinks = &symlinkList{
defer func() { info: fi,
w.pathSymlinks = w.pathSymlinks[:len(w.pathSymlinks)-1] prev: pathSymlinks,
}() }
d = fs.FileInfoToDirEntry(fi)
}
// On some platforms the OS (or the Go os package) sometimes fails to if d.Type().IsRegular() {
// resolve directory symlinks before a trailing slash if !strings.HasSuffix(path, ".go") {
// (even though POSIX requires it to do so). return
//
// On macOS that failure may be caused by a known libc/kernel bug;
// see https://go.dev/issue/59586.
//
// On Windows before Go 1.21, it may be caused by a bug in
// os.Lstat (fixed in https://go.dev/cl/463177).
//
// Since we need to handle this explicitly on broken platforms anyway,
// it is simplest to just always do that and not rely on POSIX pathname
// resolution to walk the directory (such as by calling WalkDir with
// a trailing slash appended to the path).
//
// Instead, we make a sequence of walk calls — directly and through
// recursive calls to filepath.WalkDir — simulating what WalkDir would do
// if the symlink were a regular directory.
// First we call walk on the path as a directory
// (instead of a symlink).
err = w.walk(path, fs.FileInfoToDirEntry(fi), nil)
if err == fs.SkipDir {
return nil
} else if err != nil {
// This should be impossible, but handle it anyway in case
// walk is changed to return other errors.
return err
} }
// Now read the directory and walk its entries. dir := filepath.Dir(path)
ents, err := os.ReadDir(path) if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) {
// Doesn't make sense to have regular files
// directly in your $GOPATH/src or $GOROOT/src.
//
// TODO(bcmills): there are many levels of directory within
// RootModuleCache where this also wouldn't make sense,
// Can we generalize this to any directory without a corresponding
// import path?
return
}
if _, dup := w.added.LoadOrStore(dir, true); !dup {
w.add(w.root, dir)
}
}
if !d.IsDir() {
return
}
base := filepath.Base(path)
if base == "" || base[0] == '.' || base[0] == '_' ||
base == "testdata" ||
(w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") ||
(!w.opts.ModulesEnabled && base == "node_modules") ||
w.shouldSkipDir(path) {
return
}
// Read the directory and walk its entries.
f, err := os.Open(path)
if err != nil {
w.opts.Logf("%v", err)
return
}
defer f.Close()
for {
// We impose an arbitrary limit on the number of ReadDir results per
// directory to limit the amount of memory consumed for stale or upcoming
// directory entries. The limit trades off CPU (number of syscalls to read
// the whole directory) against RAM (reachable directory entries other than
// the one currently being processed).
//
// Since we process the directories recursively, we will end up maintaining
// a slice of entries for each level of the directory tree.
// (Compare https://go.dev/issue/36197.)
ents, err := f.ReadDir(1024)
if err != nil { if err != nil {
// Report the ReadDir error, as filepath.WalkDir would do. if err != io.EOF {
err = w.walk(path, fs.FileInfoToDirEntry(fi), err) w.opts.Logf("%v", err)
if err == fs.SkipDir {
return nil
} else if err != nil {
return err // Again, should be impossible.
} }
// Fall through and iterate over whatever entries we did manage to get. break
} }
for _, d := range ents { for _, d := range ents {
nextPath := filepath.Join(path, d.Name()) nextPath := filepath.Join(path, d.Name())
if d.IsDir() { if d.IsDir() {
// We want to walk the whole directory tree rooted at nextPath, select {
// not just the single entry for the directory. case w.sem <- struct{}{}:
err := filepath.WalkDir(nextPath, w.walk) // Got a new semaphore token, so we can traverse the directory concurrently.
if err != nil && w.opts.Logf != nil { d := d
w.opts.Logf("%v", err) w.walking.Add(1)
} go func() {
} else { defer func() {
err := w.walk(nextPath, d, nil) <-w.sem
if err == fs.SkipDir { w.walking.Done()
// Skip the rest of the entries in the parent directory of nextPath }()
// (that is, path itself). w.walk(nextPath, pathSymlinks, d)
break }()
} else if err != nil { continue
return err // Again, should be impossible.
default:
// No tokens available, so traverse serially.
} }
} }
}
return nil
}
// Not a file, regular directory, or symlink; skip. w.walk(nextPath, pathSymlinks, d)
return nil }
}
} }

View file

@ -13,6 +13,7 @@ import (
"go/build" "go/build"
"go/parser" "go/parser"
"go/token" "go/token"
"go/types"
"io/fs" "io/fs"
"io/ioutil" "io/ioutil"
"os" "os"
@ -700,20 +701,21 @@ func ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) (map
return result, nil return result, nil
} }
func PrimeCache(ctx context.Context, env *ProcessEnv) error { func PrimeCache(ctx context.Context, resolver Resolver) error {
// Fully scan the disk for directories, but don't actually read any Go files. // Fully scan the disk for directories, but don't actually read any Go files.
callback := &scanCallback{ callback := &scanCallback{
rootFound: func(gopathwalk.Root) bool { rootFound: func(root gopathwalk.Root) bool {
return true // See getCandidatePkgs: walking GOROOT is apparently expensive and
// unnecessary.
return root.Type != gopathwalk.RootGOROOT
}, },
dirFound: func(pkg *pkg) bool { dirFound: func(pkg *pkg) bool {
return false return false
}, },
packageNameLoaded: func(pkg *pkg) bool { // packageNameLoaded and exportsLoaded must never be called.
return false
},
} }
return getCandidatePkgs(ctx, callback, "", "", env)
return resolver.scan(ctx, callback)
} }
func candidateImportName(pkg *pkg) string { func candidateImportName(pkg *pkg) string {
@ -827,16 +829,45 @@ func GetPackageExports(ctx context.Context, wrapped func(PackageExport), searchP
return getCandidatePkgs(ctx, callback, filename, filePkg, env) return getCandidatePkgs(ctx, callback, filename, filePkg, env)
} }
var requiredGoEnvVars = []string{"GO111MODULE", "GOFLAGS", "GOINSECURE", "GOMOD", "GOMODCACHE", "GONOPROXY", "GONOSUMDB", "GOPATH", "GOPROXY", "GOROOT", "GOSUMDB", "GOWORK"} // TODO(rfindley): we should depend on GOOS and GOARCH, to provide accurate
// imports when doing cross-platform development.
var requiredGoEnvVars = []string{
"GO111MODULE",
"GOFLAGS",
"GOINSECURE",
"GOMOD",
"GOMODCACHE",
"GONOPROXY",
"GONOSUMDB",
"GOPATH",
"GOPROXY",
"GOROOT",
"GOSUMDB",
"GOWORK",
}
// ProcessEnv contains environment variables and settings that affect the use of // ProcessEnv contains environment variables and settings that affect the use of
// the go command, the go/build package, etc. // the go command, the go/build package, etc.
//
// ...a ProcessEnv *also* overwrites its Env along with derived state in the
// form of the resolver. And because it is lazily initialized, an env may just
// be broken and unusable, but there is no way for the caller to detect that:
// all queries will just fail.
//
// TODO(rfindley): refactor this package so that this type (perhaps renamed to
// just Env or Config) is an immutable configuration struct, to be exchanged
// for an initialized object via a constructor that returns an error. Perhaps
// the signature should be `func NewResolver(*Env) (*Resolver, error)`, where
// resolver is a concrete type used for resolving imports. Via this
// refactoring, we can avoid the need to call ProcessEnv.init and
// ProcessEnv.GoEnv everywhere, and implicitly fix all the places where this
// these are misused. Also, we'd delegate the caller the decision of how to
// handle a broken environment.
type ProcessEnv struct { type ProcessEnv struct {
GocmdRunner *gocommand.Runner GocmdRunner *gocommand.Runner
BuildFlags []string BuildFlags []string
ModFlag string ModFlag string
ModFile string
// SkipPathInScan returns true if the path should be skipped from scans of // SkipPathInScan returns true if the path should be skipped from scans of
// the RootCurrentModule root type. The function argument is a clean, // the RootCurrentModule root type. The function argument is a clean,
@ -846,7 +877,7 @@ type ProcessEnv struct {
// Env overrides the OS environment, and can be used to specify // Env overrides the OS environment, and can be used to specify
// GOPROXY, GO111MODULE, etc. PATH cannot be set here, because // GOPROXY, GO111MODULE, etc. PATH cannot be set here, because
// exec.Command will not honor it. // exec.Command will not honor it.
// Specifying all of RequiredGoEnvVars avoids a call to `go env`. // Specifying all of requiredGoEnvVars avoids a call to `go env`.
Env map[string]string Env map[string]string
WorkingDir string WorkingDir string
@ -854,9 +885,17 @@ type ProcessEnv struct {
// If Logf is non-nil, debug logging is enabled through this function. // If Logf is non-nil, debug logging is enabled through this function.
Logf func(format string, args ...interface{}) Logf func(format string, args ...interface{})
initialized bool // If set, ModCache holds a shared cache of directory info to use across
// multiple ProcessEnvs.
ModCache *DirInfoCache
resolver Resolver initialized bool // see TODO above
// resolver and resolverErr are lazily evaluated (see GetResolver).
// This is unclean, but see the big TODO in the docstring for ProcessEnv
// above: for now, we can't be sure that the ProcessEnv is fully initialized.
resolver Resolver
resolverErr error
} }
func (e *ProcessEnv) goEnv() (map[string]string, error) { func (e *ProcessEnv) goEnv() (map[string]string, error) {
@ -936,20 +975,31 @@ func (e *ProcessEnv) env() []string {
} }
func (e *ProcessEnv) GetResolver() (Resolver, error) { func (e *ProcessEnv) GetResolver() (Resolver, error) {
if e.resolver != nil {
return e.resolver, nil
}
if err := e.init(); err != nil { if err := e.init(); err != nil {
return nil, err return nil, err
} }
if len(e.Env["GOMOD"]) == 0 && len(e.Env["GOWORK"]) == 0 {
e.resolver = newGopathResolver(e) if e.resolver == nil && e.resolverErr == nil {
return e.resolver, nil // TODO(rfindley): we should only use a gopathResolver here if the working
// directory is actually *in* GOPATH. (I seem to recall an open gopls issue
// for this behavior, but I can't find it).
//
// For gopls, we can optionally explicitly choose a resolver type, since we
// already know the view type.
if len(e.Env["GOMOD"]) == 0 && len(e.Env["GOWORK"]) == 0 {
e.resolver = newGopathResolver(e)
} else {
e.resolver, e.resolverErr = newModuleResolver(e, e.ModCache)
}
} }
e.resolver = newModuleResolver(e)
return e.resolver, nil return e.resolver, e.resolverErr
} }
// buildContext returns the build.Context to use for matching files.
//
// TODO(rfindley): support dynamic GOOS, GOARCH here, when doing cross-platform
// development.
func (e *ProcessEnv) buildContext() (*build.Context, error) { func (e *ProcessEnv) buildContext() (*build.Context, error) {
ctx := build.Default ctx := build.Default
goenv, err := e.goEnv() goenv, err := e.goEnv()
@ -1029,15 +1079,23 @@ func addStdlibCandidates(pass *pass, refs references) error {
type Resolver interface { type Resolver interface {
// loadPackageNames loads the package names in importPaths. // loadPackageNames loads the package names in importPaths.
loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error)
// scan works with callback to search for packages. See scanCallback for details. // scan works with callback to search for packages. See scanCallback for details.
scan(ctx context.Context, callback *scanCallback) error scan(ctx context.Context, callback *scanCallback) error
// loadExports returns the set of exported symbols in the package at dir. // loadExports returns the set of exported symbols in the package at dir.
// loadExports may be called concurrently. // loadExports may be called concurrently.
loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error)
// scoreImportPath returns the relevance for an import path. // scoreImportPath returns the relevance for an import path.
scoreImportPath(ctx context.Context, path string) float64 scoreImportPath(ctx context.Context, path string) float64
ClearForNewScan() // ClearForNewScan returns a new Resolver based on the receiver that has
// cleared its internal caches of directory contents.
//
// The new resolver should be primed and then set via
// [ProcessEnv.UpdateResolver].
ClearForNewScan() Resolver
} }
// A scanCallback controls a call to scan and receives its results. // A scanCallback controls a call to scan and receives its results.
@ -1120,7 +1178,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil
go func(pkgName string, symbols map[string]bool) { go func(pkgName string, symbols map[string]bool) {
defer wg.Done() defer wg.Done()
found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols, filename) found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols)
if err != nil { if err != nil {
firstErrOnce.Do(func() { firstErrOnce.Do(func() {
@ -1151,6 +1209,17 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil
}() }()
for result := range results { for result := range results {
// Don't offer completions that would shadow predeclared
// names, such as github.com/coreos/etcd/error.
if types.Universe.Lookup(result.pkg.name) != nil { // predeclared
// Ideally we would skip this candidate only
// if the predeclared name is actually
// referenced by the file, but that's a lot
// trickier to compute and would still create
// an import that is likely to surprise the
// user before long.
continue
}
pass.addCandidate(result.imp, result.pkg) pass.addCandidate(result.imp, result.pkg)
} }
return firstErr return firstErr
@ -1193,31 +1262,22 @@ func ImportPathToAssumedName(importPath string) string {
type gopathResolver struct { type gopathResolver struct {
env *ProcessEnv env *ProcessEnv
walked bool walked bool
cache *dirInfoCache cache *DirInfoCache
scanSema chan struct{} // scanSema prevents concurrent scans. scanSema chan struct{} // scanSema prevents concurrent scans.
} }
func newGopathResolver(env *ProcessEnv) *gopathResolver { func newGopathResolver(env *ProcessEnv) *gopathResolver {
r := &gopathResolver{ r := &gopathResolver{
env: env, env: env,
cache: &dirInfoCache{ cache: NewDirInfoCache(),
dirs: map[string]*directoryPackageInfo{},
listeners: map[*int]cacheListener{},
},
scanSema: make(chan struct{}, 1), scanSema: make(chan struct{}, 1),
} }
r.scanSema <- struct{}{} r.scanSema <- struct{}{}
return r return r
} }
func (r *gopathResolver) ClearForNewScan() { func (r *gopathResolver) ClearForNewScan() Resolver {
<-r.scanSema return newGopathResolver(r.env)
r.cache = &dirInfoCache{
dirs: map[string]*directoryPackageInfo{},
listeners: map[*int]cacheListener{},
}
r.walked = false
r.scanSema <- struct{}{}
} }
func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
@ -1538,7 +1598,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl
// findImport searches for a package with the given symbols. // findImport searches for a package with the given symbols.
// If no package is found, findImport returns ("", false, nil) // If no package is found, findImport returns ("", false, nil)
func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool, filename string) (*pkg, error) { func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool) (*pkg, error) {
// Sort the candidates by their import package length, // Sort the candidates by their import package length,
// assuming that shorter package names are better than long // assuming that shorter package names are better than long
// ones. Note that this sorts by the de-vendored name, so // ones. Note that this sorts by the de-vendored name, so

View file

@ -236,7 +236,7 @@ func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast
src = src[:len(src)-len("}\n")] src = src[:len(src)-len("}\n")]
// Gofmt has also indented the function body one level. // Gofmt has also indented the function body one level.
// Remove that indent. // Remove that indent.
src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1) src = bytes.ReplaceAll(src, []byte("\n\t"), []byte("\n"))
return matchSpace(orig, src) return matchSpace(orig, src)
} }
return file, adjust, nil return file, adjust, nil

View file

@ -23,49 +23,88 @@ import (
"golang.org/x/tools/internal/gopathwalk" "golang.org/x/tools/internal/gopathwalk"
) )
// ModuleResolver implements resolver for modules using the go command as little // Notes(rfindley): ModuleResolver appears to be heavily optimized for scanning
// as feasible. // as fast as possible, which is desirable for a call to goimports from the
// command line, but it doesn't work as well for gopls, where it suffers from
// slow startup (golang/go#44863) and intermittent hanging (golang/go#59216),
// both caused by populating the cache, albeit in slightly different ways.
//
// A high level list of TODOs:
// - Optimize the scan itself, as there is some redundancy statting and
// reading go.mod files.
// - Invert the relationship between ProcessEnv and Resolver (see the
// docstring of ProcessEnv).
// - Make it easier to use an external resolver implementation.
//
// Smaller TODOs are annotated in the code below.
// ModuleResolver implements the Resolver interface for a workspace using
// modules.
//
// A goal of the ModuleResolver is to invoke the Go command as little as
// possible. To this end, it runs the Go command only for listing module
// information (i.e. `go list -m -e -json ...`). Package scanning, the process
// of loading package information for the modules, is implemented internally
// via the scan method.
//
// It has two types of state: the state derived from the go command, which
// is populated by init, and the state derived from scans, which is populated
// via scan. A root is considered scanned if it has been walked to discover
// directories. However, if the scan did not require additional information
// from the directory (such as package name or exports), the directory
// information itself may be partially populated. It will be lazily filled in
// as needed by scans, using the scanCallback.
type ModuleResolver struct { type ModuleResolver struct {
env *ProcessEnv env *ProcessEnv
moduleCacheDir string
dummyVendorMod *gocommand.ModuleJSON // If vendoring is enabled, the pseudo-module that represents the /vendor directory.
roots []gopathwalk.Root
scanSema chan struct{} // scanSema prevents concurrent scans and guards scannedRoots.
scannedRoots map[gopathwalk.Root]bool
initialized bool // Module state, populated during construction
mains []*gocommand.ModuleJSON dummyVendorMod *gocommand.ModuleJSON // if vendoring is enabled, a pseudo-module to represent the /vendor directory
mainByDir map[string]*gocommand.ModuleJSON moduleCacheDir string // GOMODCACHE, inferred from GOPATH if unset
modsByModPath []*gocommand.ModuleJSON // All modules, ordered by # of path components in module Path... roots []gopathwalk.Root // roots to scan, in approximate order of importance
modsByDir []*gocommand.ModuleJSON // ...or number of path components in their Dir. mains []*gocommand.ModuleJSON // main modules
mainByDir map[string]*gocommand.ModuleJSON // module information by dir, to join with roots
modsByModPath []*gocommand.ModuleJSON // all modules, ordered by # of path components in their module path
modsByDir []*gocommand.ModuleJSON // ...or by the number of path components in their Dir.
// moduleCacheCache stores information about the module cache. // Scanning state, populated by scan
moduleCacheCache *dirInfoCache
otherCache *dirInfoCache // scanSema prevents concurrent scans, and guards scannedRoots and the cache
// fields below (though the caches themselves are concurrency safe).
// Receive to acquire, send to release.
scanSema chan struct{}
scannedRoots map[gopathwalk.Root]bool // if true, root has been walked
// Caches of directory info, populated by scans and scan callbacks
//
// moduleCacheCache stores cached information about roots in the module
// cache, which are immutable and therefore do not need to be invalidated.
//
// otherCache stores information about all other roots (even GOROOT), which
// may change.
moduleCacheCache *DirInfoCache
otherCache *DirInfoCache
} }
func newModuleResolver(e *ProcessEnv) *ModuleResolver { // newModuleResolver returns a new module-aware goimports resolver.
//
// Note: use caution when modifying this constructor: changes must also be
// reflected in ModuleResolver.ClearForNewScan.
func newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleResolver, error) {
r := &ModuleResolver{ r := &ModuleResolver{
env: e, env: e,
scanSema: make(chan struct{}, 1), scanSema: make(chan struct{}, 1),
} }
r.scanSema <- struct{}{} r.scanSema <- struct{}{} // release
return r
}
func (r *ModuleResolver) init() error {
if r.initialized {
return nil
}
goenv, err := r.env.goEnv() goenv, err := r.env.goEnv()
if err != nil { if err != nil {
return err return nil, err
} }
// TODO(rfindley): can we refactor to share logic with r.env.invokeGo?
inv := gocommand.Invocation{ inv := gocommand.Invocation{
BuildFlags: r.env.BuildFlags, BuildFlags: r.env.BuildFlags,
ModFlag: r.env.ModFlag, ModFlag: r.env.ModFlag,
ModFile: r.env.ModFile,
Env: r.env.env(), Env: r.env.env(),
Logf: r.env.Logf, Logf: r.env.Logf,
WorkingDir: r.env.WorkingDir, WorkingDir: r.env.WorkingDir,
@ -77,9 +116,12 @@ func (r *ModuleResolver) init() error {
// Module vendor directories are ignored in workspace mode: // Module vendor directories are ignored in workspace mode:
// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md // https://go.googlesource.com/proposal/+/master/design/45713-workspace.md
if len(r.env.Env["GOWORK"]) == 0 { if len(r.env.Env["GOWORK"]) == 0 {
// TODO(rfindley): VendorEnabled runs the go command to get GOFLAGS, but
// they should be available from the ProcessEnv. Can we avoid the redundant
// invocation?
vendorEnabled, mainModVendor, err = gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner) vendorEnabled, mainModVendor, err = gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner)
if err != nil { if err != nil {
return err return nil, err
} }
} }
@ -100,19 +142,14 @@ func (r *ModuleResolver) init() error {
// GO111MODULE=on. Other errors are fatal. // GO111MODULE=on. Other errors are fatal.
if err != nil { if err != nil {
if errMsg := err.Error(); !strings.Contains(errMsg, "working directory is not part of a module") && !strings.Contains(errMsg, "go.mod file not found") { if errMsg := err.Error(); !strings.Contains(errMsg, "working directory is not part of a module") && !strings.Contains(errMsg, "go.mod file not found") {
return err return nil, err
} }
} }
} }
if gmc := r.env.Env["GOMODCACHE"]; gmc != "" { r.moduleCacheDir = gomodcacheForEnv(goenv)
r.moduleCacheDir = gmc if r.moduleCacheDir == "" {
} else { return nil, fmt.Errorf("cannot resolve GOMODCACHE")
gopaths := filepath.SplitList(goenv["GOPATH"])
if len(gopaths) == 0 {
return fmt.Errorf("empty GOPATH")
}
r.moduleCacheDir = filepath.Join(gopaths[0], "/pkg/mod")
} }
sort.Slice(r.modsByModPath, func(i, j int) bool { sort.Slice(r.modsByModPath, func(i, j int) bool {
@ -141,7 +178,11 @@ func (r *ModuleResolver) init() error {
} else { } else {
addDep := func(mod *gocommand.ModuleJSON) { addDep := func(mod *gocommand.ModuleJSON) {
if mod.Replace == nil { if mod.Replace == nil {
// This is redundant with the cache, but we'll skip it cheaply enough. // This is redundant with the cache, but we'll skip it cheaply enough
// when we encounter it in the module cache scan.
//
// Including it at a lower index in r.roots than the module cache dir
// helps prioritize matches from within existing dependencies.
r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootModuleCache}) r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootModuleCache})
} else { } else {
r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootOther}) r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootOther})
@ -158,24 +199,40 @@ func (r *ModuleResolver) init() error {
addDep(mod) addDep(mod)
} }
} }
// If provided, share the moduleCacheCache.
//
// TODO(rfindley): The module cache is immutable. However, the loaded
// exports do depend on GOOS and GOARCH. Fortunately, the
// ProcessEnv.buildContext does not adjust these from build.DefaultContext
// (even though it should). So for now, this is OK to share, but we need to
// add logic for handling GOOS/GOARCH.
r.moduleCacheCache = moduleCacheCache
r.roots = append(r.roots, gopathwalk.Root{Path: r.moduleCacheDir, Type: gopathwalk.RootModuleCache}) r.roots = append(r.roots, gopathwalk.Root{Path: r.moduleCacheDir, Type: gopathwalk.RootModuleCache})
} }
r.scannedRoots = map[gopathwalk.Root]bool{} r.scannedRoots = map[gopathwalk.Root]bool{}
if r.moduleCacheCache == nil { if r.moduleCacheCache == nil {
r.moduleCacheCache = &dirInfoCache{ r.moduleCacheCache = NewDirInfoCache()
dirs: map[string]*directoryPackageInfo{},
listeners: map[*int]cacheListener{},
}
} }
if r.otherCache == nil { r.otherCache = NewDirInfoCache()
r.otherCache = &dirInfoCache{ return r, nil
dirs: map[string]*directoryPackageInfo{}, }
listeners: map[*int]cacheListener{},
} // gomodcacheForEnv returns the GOMODCACHE value to use based on the given env
// map, which must have GOMODCACHE and GOPATH populated.
//
// TODO(rfindley): this is defensive refactoring.
// 1. Is this even relevant anymore? Can't we just read GOMODCACHE.
// 2. Use this to separate module cache scanning from other scanning.
func gomodcacheForEnv(goenv map[string]string) string {
if gmc := goenv["GOMODCACHE"]; gmc != "" {
return gmc
} }
r.initialized = true gopaths := filepath.SplitList(goenv["GOPATH"])
return nil if len(gopaths) == 0 {
return ""
}
return filepath.Join(gopaths[0], "/pkg/mod")
} }
func (r *ModuleResolver) initAllMods() error { func (r *ModuleResolver) initAllMods() error {
@ -206,30 +263,82 @@ func (r *ModuleResolver) initAllMods() error {
return nil return nil
} }
func (r *ModuleResolver) ClearForNewScan() { // ClearForNewScan invalidates the last scan.
<-r.scanSema //
r.scannedRoots = map[gopathwalk.Root]bool{} // It preserves the set of roots, but forgets about the set of directories.
r.otherCache = &dirInfoCache{ // Though it forgets the set of module cache directories, it remembers their
dirs: map[string]*directoryPackageInfo{}, // contents, since they are assumed to be immutable.
listeners: map[*int]cacheListener{}, func (r *ModuleResolver) ClearForNewScan() Resolver {
} <-r.scanSema // acquire r, to guard scannedRoots
r.scanSema <- struct{}{} r2 := &ModuleResolver{
} env: r.env,
dummyVendorMod: r.dummyVendorMod,
moduleCacheDir: r.moduleCacheDir,
roots: r.roots,
mains: r.mains,
mainByDir: r.mainByDir,
modsByModPath: r.modsByModPath,
func (r *ModuleResolver) ClearForNewMod() { scanSema: make(chan struct{}, 1),
<-r.scanSema scannedRoots: make(map[gopathwalk.Root]bool),
*r = ModuleResolver{ otherCache: NewDirInfoCache(),
env: r.env,
moduleCacheCache: r.moduleCacheCache, moduleCacheCache: r.moduleCacheCache,
otherCache: r.otherCache,
scanSema: r.scanSema,
} }
r.init() r2.scanSema <- struct{}{} // r2 must start released
r.scanSema <- struct{}{} // Invalidate root scans. We don't need to invalidate module cache roots,
// because they are immutable.
// (We don't support a use case where GOMODCACHE is cleaned in the middle of
// e.g. a gopls session: the user must restart gopls to get accurate
// imports.)
//
// Scanning for new directories in GOMODCACHE should be handled elsewhere,
// via a call to ScanModuleCache.
for _, root := range r.roots {
if root.Type == gopathwalk.RootModuleCache && r.scannedRoots[root] {
r2.scannedRoots[root] = true
}
}
r.scanSema <- struct{}{} // release r
return r2
} }
// findPackage returns the module and directory that contains the package at // ClearModuleInfo invalidates resolver state that depends on go.mod file
// the given import path, or returns nil, "" if no module is in scope. // contents (essentially, the output of go list -m -json ...).
//
// Notably, it does not forget directory contents, which are reset
// asynchronously via ClearForNewScan.
//
// If the ProcessEnv is a GOPATH environment, ClearModuleInfo is a no op.
//
// TODO(rfindley): move this to a new env.go, consolidating ProcessEnv methods.
func (e *ProcessEnv) ClearModuleInfo() {
if r, ok := e.resolver.(*ModuleResolver); ok {
resolver, resolverErr := newModuleResolver(e, e.ModCache)
if resolverErr == nil {
<-r.scanSema // acquire (guards caches)
resolver.moduleCacheCache = r.moduleCacheCache
resolver.otherCache = r.otherCache
r.scanSema <- struct{}{} // release
}
e.resolver = resolver
e.resolverErr = resolverErr
}
}
// UpdateResolver sets the resolver for the ProcessEnv to use in imports
// operations. Only for use with the result of [Resolver.ClearForNewScan].
//
// TODO(rfindley): this awkward API is a result of the (arguably) inverted
// relationship between configuration and state described in the doc comment
// for [ProcessEnv].
func (e *ProcessEnv) UpdateResolver(r Resolver) {
e.resolver = r
e.resolverErr = nil
}
// findPackage returns the module and directory from within the main modules
// and their dependencies that contains the package at the given import path,
// or returns nil, "" if no module is in scope.
func (r *ModuleResolver) findPackage(importPath string) (*gocommand.ModuleJSON, string) { func (r *ModuleResolver) findPackage(importPath string) (*gocommand.ModuleJSON, string) {
// This can't find packages in the stdlib, but that's harmless for all // This can't find packages in the stdlib, but that's harmless for all
// the existing code paths. // the existing code paths.
@ -295,10 +404,6 @@ func (r *ModuleResolver) cacheStore(info directoryPackageInfo) {
} }
} }
func (r *ModuleResolver) cacheKeys() []string {
return append(r.moduleCacheCache.Keys(), r.otherCache.Keys()...)
}
// cachePackageName caches the package name for a dir already in the cache. // cachePackageName caches the package name for a dir already in the cache.
func (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (string, error) { func (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (string, error) {
if info.rootType == gopathwalk.RootModuleCache { if info.rootType == gopathwalk.RootModuleCache {
@ -367,15 +472,15 @@ func (r *ModuleResolver) dirIsNestedModule(dir string, mod *gocommand.ModuleJSON
return modDir != mod.Dir return modDir != mod.Dir
} }
func (r *ModuleResolver) modInfo(dir string) (modDir string, modName string) { func readModName(modFile string) string {
readModName := func(modFile string) string { modBytes, err := os.ReadFile(modFile)
modBytes, err := os.ReadFile(modFile) if err != nil {
if err != nil { return ""
return ""
}
return modulePath(modBytes)
} }
return modulePath(modBytes)
}
func (r *ModuleResolver) modInfo(dir string) (modDir, modName string) {
if r.dirInModuleCache(dir) { if r.dirInModuleCache(dir) {
if matches := modCacheRegexp.FindStringSubmatch(dir); len(matches) == 3 { if matches := modCacheRegexp.FindStringSubmatch(dir); len(matches) == 3 {
index := strings.Index(dir, matches[1]+"@"+matches[2]) index := strings.Index(dir, matches[1]+"@"+matches[2])
@ -409,11 +514,9 @@ func (r *ModuleResolver) dirInModuleCache(dir string) bool {
} }
func (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { func (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
if err := r.init(); err != nil {
return nil, err
}
names := map[string]string{} names := map[string]string{}
for _, path := range importPaths { for _, path := range importPaths {
// TODO(rfindley): shouldn't this use the dirInfoCache?
_, packageDir := r.findPackage(path) _, packageDir := r.findPackage(path)
if packageDir == "" { if packageDir == "" {
continue continue
@ -431,10 +534,6 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error
ctx, done := event.Start(ctx, "imports.ModuleResolver.scan") ctx, done := event.Start(ctx, "imports.ModuleResolver.scan")
defer done() defer done()
if err := r.init(); err != nil {
return err
}
processDir := func(info directoryPackageInfo) { processDir := func(info directoryPackageInfo) {
// Skip this directory if we were not able to get the package information successfully. // Skip this directory if we were not able to get the package information successfully.
if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil { if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {
@ -444,18 +543,18 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error
if err != nil { if err != nil {
return return
} }
if !callback.dirFound(pkg) { if !callback.dirFound(pkg) {
return return
} }
pkg.packageName, err = r.cachePackageName(info) pkg.packageName, err = r.cachePackageName(info)
if err != nil { if err != nil {
return return
} }
if !callback.packageNameLoaded(pkg) { if !callback.packageNameLoaded(pkg) {
return return
} }
_, exports, err := r.loadExports(ctx, pkg, false) _, exports, err := r.loadExports(ctx, pkg, false)
if err != nil { if err != nil {
return return
@ -494,7 +593,6 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error
return packageScanned return packageScanned
} }
// Add anything new to the cache, and process it if we're still listening.
add := func(root gopathwalk.Root, dir string) { add := func(root gopathwalk.Root, dir string) {
r.cacheStore(r.scanDirForPackage(root, dir)) r.cacheStore(r.scanDirForPackage(root, dir))
} }
@ -509,9 +607,9 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
case <-r.scanSema: case <-r.scanSema: // acquire
} }
defer func() { r.scanSema <- struct{}{} }() defer func() { r.scanSema <- struct{}{} }() // release
// We have the lock on r.scannedRoots, and no other scans can run. // We have the lock on r.scannedRoots, and no other scans can run.
for _, root := range roots { for _, root := range roots {
if ctx.Err() != nil { if ctx.Err() != nil {
@ -613,9 +711,6 @@ func (r *ModuleResolver) canonicalize(info directoryPackageInfo) (*pkg, error) {
} }
func (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) { func (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) {
if err := r.init(); err != nil {
return "", nil, err
}
if info, ok := r.cacheLoad(pkg.dir); ok && !includeTest { if info, ok := r.cacheLoad(pkg.dir); ok && !includeTest {
return r.cacheExports(ctx, r.env, info) return r.cacheExports(ctx, r.env, info)
} }

View file

@ -7,8 +7,12 @@ package imports
import ( import (
"context" "context"
"fmt" "fmt"
"path"
"path/filepath"
"strings"
"sync" "sync"
"golang.org/x/mod/module"
"golang.org/x/tools/internal/gopathwalk" "golang.org/x/tools/internal/gopathwalk"
) )
@ -39,6 +43,8 @@ const (
exportsLoaded exportsLoaded
) )
// directoryPackageInfo holds (possibly incomplete) information about packages
// contained in a given directory.
type directoryPackageInfo struct { type directoryPackageInfo struct {
// status indicates the extent to which this struct has been filled in. // status indicates the extent to which this struct has been filled in.
status directoryPackageStatus status directoryPackageStatus
@ -63,7 +69,10 @@ type directoryPackageInfo struct {
packageName string // the package name, as declared in the source. packageName string // the package name, as declared in the source.
// Set when status >= exportsLoaded. // Set when status >= exportsLoaded.
// TODO(rfindley): it's hard to see this, but exports depend implicitly on
// the default build context GOOS and GOARCH.
//
// We can make this explicit, and key exports by GOOS, GOARCH.
exports []string exports []string
} }
@ -79,7 +88,7 @@ func (info *directoryPackageInfo) reachedStatus(target directoryPackageStatus) (
return true, nil return true, nil
} }
// dirInfoCache is a concurrency safe map for storing information about // DirInfoCache is a concurrency-safe map for storing information about
// directories that may contain packages. // directories that may contain packages.
// //
// The information in this cache is built incrementally. Entries are initialized in scan. // The information in this cache is built incrementally. Entries are initialized in scan.
@ -92,21 +101,26 @@ func (info *directoryPackageInfo) reachedStatus(target directoryPackageStatus) (
// The information in the cache is not expected to change for the cache's // The information in the cache is not expected to change for the cache's
// lifetime, so there is no protection against competing writes. Users should // lifetime, so there is no protection against competing writes. Users should
// take care not to hold the cache across changes to the underlying files. // take care not to hold the cache across changes to the underlying files.
// type DirInfoCache struct {
// TODO(suzmue): consider other concurrency strategies and data structures (RWLocks, sync.Map, etc)
type dirInfoCache struct {
mu sync.Mutex mu sync.Mutex
// dirs stores information about packages in directories, keyed by absolute path. // dirs stores information about packages in directories, keyed by absolute path.
dirs map[string]*directoryPackageInfo dirs map[string]*directoryPackageInfo
listeners map[*int]cacheListener listeners map[*int]cacheListener
} }
func NewDirInfoCache() *DirInfoCache {
return &DirInfoCache{
dirs: make(map[string]*directoryPackageInfo),
listeners: make(map[*int]cacheListener),
}
}
type cacheListener func(directoryPackageInfo) type cacheListener func(directoryPackageInfo)
// ScanAndListen calls listener on all the items in the cache, and on anything // ScanAndListen calls listener on all the items in the cache, and on anything
// newly added. The returned stop function waits for all in-flight callbacks to // newly added. The returned stop function waits for all in-flight callbacks to
// finish and blocks new ones. // finish and blocks new ones.
func (d *dirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() { func (d *DirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() {
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
// Flushing out all the callbacks is tricky without knowing how many there // Flushing out all the callbacks is tricky without knowing how many there
@ -162,8 +176,10 @@ func (d *dirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener
} }
// Store stores the package info for dir. // Store stores the package info for dir.
func (d *dirInfoCache) Store(dir string, info directoryPackageInfo) { func (d *DirInfoCache) Store(dir string, info directoryPackageInfo) {
d.mu.Lock() d.mu.Lock()
// TODO(rfindley, golang/go#59216): should we overwrite an existing entry?
// That seems incorrect as the cache should be idempotent.
_, old := d.dirs[dir] _, old := d.dirs[dir]
d.dirs[dir] = &info d.dirs[dir] = &info
var listeners []cacheListener var listeners []cacheListener
@ -180,7 +196,7 @@ func (d *dirInfoCache) Store(dir string, info directoryPackageInfo) {
} }
// Load returns a copy of the directoryPackageInfo for absolute directory dir. // Load returns a copy of the directoryPackageInfo for absolute directory dir.
func (d *dirInfoCache) Load(dir string) (directoryPackageInfo, bool) { func (d *DirInfoCache) Load(dir string) (directoryPackageInfo, bool) {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
info, ok := d.dirs[dir] info, ok := d.dirs[dir]
@ -191,7 +207,7 @@ func (d *dirInfoCache) Load(dir string) (directoryPackageInfo, bool) {
} }
// Keys returns the keys currently present in d. // Keys returns the keys currently present in d.
func (d *dirInfoCache) Keys() (keys []string) { func (d *DirInfoCache) Keys() (keys []string) {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
for key := range d.dirs { for key := range d.dirs {
@ -200,7 +216,7 @@ func (d *dirInfoCache) Keys() (keys []string) {
return keys return keys
} }
func (d *dirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) { func (d *DirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) {
if loaded, err := info.reachedStatus(nameLoaded); loaded { if loaded, err := info.reachedStatus(nameLoaded); loaded {
return info.packageName, err return info.packageName, err
} }
@ -213,7 +229,7 @@ func (d *dirInfoCache) CachePackageName(info directoryPackageInfo) (string, erro
return info.packageName, info.err return info.packageName, info.err
} }
func (d *dirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []string, error) { func (d *DirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []string, error) {
if reached, _ := info.reachedStatus(exportsLoaded); reached { if reached, _ := info.reachedStatus(exportsLoaded); reached {
return info.packageName, info.exports, info.err return info.packageName, info.exports, info.err
} }
@ -234,3 +250,81 @@ func (d *dirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info d
d.Store(info.dir, info) d.Store(info.dir, info)
return info.packageName, info.exports, info.err return info.packageName, info.exports, info.err
} }
// ScanModuleCache walks the given directory, which must be a GOMODCACHE value,
// for directory package information, storing the results in cache.
func ScanModuleCache(dir string, cache *DirInfoCache, logf func(string, ...any)) {
// Note(rfindley): it's hard to see, but this function attempts to implement
// just the side effects on cache of calling PrimeCache with a ProcessEnv
// that has the given dir as its GOMODCACHE.
//
// Teasing out the control flow, we see that we can avoid any handling of
// vendor/ and can infer module info entirely from the path, simplifying the
// logic here.
root := gopathwalk.Root{
Path: filepath.Clean(dir),
Type: gopathwalk.RootModuleCache,
}
directoryInfo := func(root gopathwalk.Root, dir string) directoryPackageInfo {
// This is a copy of ModuleResolver.scanDirForPackage, trimmed down to
// logic that applies to a module cache directory.
subdir := ""
if dir != root.Path {
subdir = dir[len(root.Path)+len("/"):]
}
matches := modCacheRegexp.FindStringSubmatch(subdir)
if len(matches) == 0 {
return directoryPackageInfo{
status: directoryScanned,
err: fmt.Errorf("invalid module cache path: %v", subdir),
}
}
modPath, err := module.UnescapePath(filepath.ToSlash(matches[1]))
if err != nil {
if logf != nil {
logf("decoding module cache path %q: %v", subdir, err)
}
return directoryPackageInfo{
status: directoryScanned,
err: fmt.Errorf("decoding module cache path %q: %v", subdir, err),
}
}
importPath := path.Join(modPath, filepath.ToSlash(matches[3]))
index := strings.Index(dir, matches[1]+"@"+matches[2])
modDir := filepath.Join(dir[:index], matches[1]+"@"+matches[2])
modName := readModName(filepath.Join(modDir, "go.mod"))
return directoryPackageInfo{
status: directoryScanned,
dir: dir,
rootType: root.Type,
nonCanonicalImportPath: importPath,
moduleDir: modDir,
moduleName: modName,
}
}
add := func(root gopathwalk.Root, dir string) {
info := directoryInfo(root, dir)
cache.Store(info.dir, info)
}
skip := func(_ gopathwalk.Root, dir string) bool {
// Skip directories that have already been scanned.
//
// Note that gopathwalk only adds "package" directories, which must contain
// a .go file, and all such package directories in the module cache are
// immutable. So if we can load a dir, it can be skipped.
info, ok := cache.Load(dir)
if !ok {
return false
}
packageScanned, _ := info.reachedStatus(directoryScanned)
return packageScanned
}
gopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Logf: logf, ModulesEnabled: true})
}

View file

@ -151,6 +151,7 @@ var stdlib = map[string][]string{
"cmp": { "cmp": {
"Compare", "Compare",
"Less", "Less",
"Or",
"Ordered", "Ordered",
}, },
"compress/bzip2": { "compress/bzip2": {
@ -632,6 +633,8 @@ var stdlib = map[string][]string{
"NameMismatch", "NameMismatch",
"NewCertPool", "NewCertPool",
"NotAuthorizedToSign", "NotAuthorizedToSign",
"OID",
"OIDFromInts",
"PEMCipher", "PEMCipher",
"PEMCipher3DES", "PEMCipher3DES",
"PEMCipherAES128", "PEMCipherAES128",
@ -706,6 +709,7 @@ var stdlib = map[string][]string{
"LevelWriteCommitted", "LevelWriteCommitted",
"Named", "Named",
"NamedArg", "NamedArg",
"Null",
"NullBool", "NullBool",
"NullByte", "NullByte",
"NullFloat64", "NullFloat64",
@ -1921,6 +1925,7 @@ var stdlib = map[string][]string{
"R_LARCH_32", "R_LARCH_32",
"R_LARCH_32_PCREL", "R_LARCH_32_PCREL",
"R_LARCH_64", "R_LARCH_64",
"R_LARCH_64_PCREL",
"R_LARCH_ABS64_HI12", "R_LARCH_ABS64_HI12",
"R_LARCH_ABS64_LO20", "R_LARCH_ABS64_LO20",
"R_LARCH_ABS_HI20", "R_LARCH_ABS_HI20",
@ -1928,12 +1933,17 @@ var stdlib = map[string][]string{
"R_LARCH_ADD16", "R_LARCH_ADD16",
"R_LARCH_ADD24", "R_LARCH_ADD24",
"R_LARCH_ADD32", "R_LARCH_ADD32",
"R_LARCH_ADD6",
"R_LARCH_ADD64", "R_LARCH_ADD64",
"R_LARCH_ADD8", "R_LARCH_ADD8",
"R_LARCH_ADD_ULEB128",
"R_LARCH_ALIGN",
"R_LARCH_B16", "R_LARCH_B16",
"R_LARCH_B21", "R_LARCH_B21",
"R_LARCH_B26", "R_LARCH_B26",
"R_LARCH_CFA",
"R_LARCH_COPY", "R_LARCH_COPY",
"R_LARCH_DELETE",
"R_LARCH_GNU_VTENTRY", "R_LARCH_GNU_VTENTRY",
"R_LARCH_GNU_VTINHERIT", "R_LARCH_GNU_VTINHERIT",
"R_LARCH_GOT64_HI12", "R_LARCH_GOT64_HI12",
@ -1953,6 +1963,7 @@ var stdlib = map[string][]string{
"R_LARCH_PCALA64_LO20", "R_LARCH_PCALA64_LO20",
"R_LARCH_PCALA_HI20", "R_LARCH_PCALA_HI20",
"R_LARCH_PCALA_LO12", "R_LARCH_PCALA_LO12",
"R_LARCH_PCREL20_S2",
"R_LARCH_RELATIVE", "R_LARCH_RELATIVE",
"R_LARCH_RELAX", "R_LARCH_RELAX",
"R_LARCH_SOP_ADD", "R_LARCH_SOP_ADD",
@ -1983,8 +1994,10 @@ var stdlib = map[string][]string{
"R_LARCH_SUB16", "R_LARCH_SUB16",
"R_LARCH_SUB24", "R_LARCH_SUB24",
"R_LARCH_SUB32", "R_LARCH_SUB32",
"R_LARCH_SUB6",
"R_LARCH_SUB64", "R_LARCH_SUB64",
"R_LARCH_SUB8", "R_LARCH_SUB8",
"R_LARCH_SUB_ULEB128",
"R_LARCH_TLS_DTPMOD32", "R_LARCH_TLS_DTPMOD32",
"R_LARCH_TLS_DTPMOD64", "R_LARCH_TLS_DTPMOD64",
"R_LARCH_TLS_DTPREL32", "R_LARCH_TLS_DTPREL32",
@ -2035,6 +2048,7 @@ var stdlib = map[string][]string{
"R_MIPS_LO16", "R_MIPS_LO16",
"R_MIPS_NONE", "R_MIPS_NONE",
"R_MIPS_PC16", "R_MIPS_PC16",
"R_MIPS_PC32",
"R_MIPS_PJUMP", "R_MIPS_PJUMP",
"R_MIPS_REL16", "R_MIPS_REL16",
"R_MIPS_REL32", "R_MIPS_REL32",
@ -2952,6 +2966,8 @@ var stdlib = map[string][]string{
"RegisterName", "RegisterName",
}, },
"encoding/hex": { "encoding/hex": {
"AppendDecode",
"AppendEncode",
"Decode", "Decode",
"DecodeString", "DecodeString",
"DecodedLen", "DecodedLen",
@ -3233,6 +3249,7 @@ var stdlib = map[string][]string{
"TypeSpec", "TypeSpec",
"TypeSwitchStmt", "TypeSwitchStmt",
"UnaryExpr", "UnaryExpr",
"Unparen",
"ValueSpec", "ValueSpec",
"Var", "Var",
"Visitor", "Visitor",
@ -3492,6 +3509,7 @@ var stdlib = map[string][]string{
"XOR_ASSIGN", "XOR_ASSIGN",
}, },
"go/types": { "go/types": {
"Alias",
"ArgumentError", "ArgumentError",
"Array", "Array",
"AssertableTo", "AssertableTo",
@ -3559,6 +3577,7 @@ var stdlib = map[string][]string{
"MethodVal", "MethodVal",
"MissingMethod", "MissingMethod",
"Named", "Named",
"NewAlias",
"NewArray", "NewArray",
"NewChan", "NewChan",
"NewChecker", "NewChecker",
@ -3627,6 +3646,7 @@ var stdlib = map[string][]string{
"Uint64", "Uint64",
"Uint8", "Uint8",
"Uintptr", "Uintptr",
"Unalias",
"Union", "Union",
"Universe", "Universe",
"Unsafe", "Unsafe",
@ -3643,6 +3663,11 @@ var stdlib = map[string][]string{
"WriteSignature", "WriteSignature",
"WriteType", "WriteType",
}, },
"go/version": {
"Compare",
"IsValid",
"Lang",
},
"hash": { "hash": {
"Hash", "Hash",
"Hash32", "Hash32",
@ -4078,6 +4103,7 @@ var stdlib = map[string][]string{
"NewTextHandler", "NewTextHandler",
"Record", "Record",
"SetDefault", "SetDefault",
"SetLogLoggerLevel",
"Source", "Source",
"SourceKey", "SourceKey",
"String", "String",
@ -4367,6 +4393,35 @@ var stdlib = map[string][]string{
"Uint64", "Uint64",
"Zipf", "Zipf",
}, },
"math/rand/v2": {
"ChaCha8",
"ExpFloat64",
"Float32",
"Float64",
"Int",
"Int32",
"Int32N",
"Int64",
"Int64N",
"IntN",
"N",
"New",
"NewChaCha8",
"NewPCG",
"NewZipf",
"NormFloat64",
"PCG",
"Perm",
"Rand",
"Shuffle",
"Source",
"Uint32",
"Uint32N",
"Uint64",
"Uint64N",
"UintN",
"Zipf",
},
"mime": { "mime": {
"AddExtensionType", "AddExtensionType",
"BEncoding", "BEncoding",
@ -4540,6 +4595,7 @@ var stdlib = map[string][]string{
"FS", "FS",
"File", "File",
"FileServer", "FileServer",
"FileServerFS",
"FileSystem", "FileSystem",
"Flusher", "Flusher",
"Get", "Get",
@ -4566,6 +4622,7 @@ var stdlib = map[string][]string{
"MethodPut", "MethodPut",
"MethodTrace", "MethodTrace",
"NewFileTransport", "NewFileTransport",
"NewFileTransportFS",
"NewRequest", "NewRequest",
"NewRequestWithContext", "NewRequestWithContext",
"NewResponseController", "NewResponseController",
@ -4599,6 +4656,7 @@ var stdlib = map[string][]string{
"Serve", "Serve",
"ServeContent", "ServeContent",
"ServeFile", "ServeFile",
"ServeFileFS",
"ServeMux", "ServeMux",
"ServeTLS", "ServeTLS",
"Server", "Server",
@ -5106,6 +5164,7 @@ var stdlib = map[string][]string{
"StructTag", "StructTag",
"Swapper", "Swapper",
"Type", "Type",
"TypeFor",
"TypeOf", "TypeOf",
"Uint", "Uint",
"Uint16", "Uint16",
@ -5342,6 +5401,7 @@ var stdlib = map[string][]string{
"CompactFunc", "CompactFunc",
"Compare", "Compare",
"CompareFunc", "CompareFunc",
"Concat",
"Contains", "Contains",
"ContainsFunc", "ContainsFunc",
"Delete", "Delete",
@ -10824,6 +10884,7 @@ var stdlib = map[string][]string{
"Value", "Value",
}, },
"testing/slogtest": { "testing/slogtest": {
"Run",
"TestHandler", "TestHandler",
}, },
"text/scanner": { "text/scanner": {

View file

@ -34,30 +34,16 @@ func GetLines(file *token.File) []int {
lines []int lines []int
_ []struct{} _ []struct{}
} }
type tokenFile118 struct {
_ *token.FileSet // deleted in go1.19
tokenFile119
}
type uP = unsafe.Pointer if unsafe.Sizeof(*file) != unsafe.Sizeof(tokenFile119{}) {
switch unsafe.Sizeof(*file) {
case unsafe.Sizeof(tokenFile118{}):
var ptr *tokenFile118
*(*uP)(uP(&ptr)) = uP(file)
ptr.mu.Lock()
defer ptr.mu.Unlock()
return ptr.lines
case unsafe.Sizeof(tokenFile119{}):
var ptr *tokenFile119
*(*uP)(uP(&ptr)) = uP(file)
ptr.mu.Lock()
defer ptr.mu.Unlock()
return ptr.lines
default:
panic("unexpected token.File size") panic("unexpected token.File size")
} }
var ptr *tokenFile119
type uP = unsafe.Pointer
*(*uP)(uP(&ptr)) = uP(file)
ptr.mu.Lock()
defer ptr.mu.Unlock()
return ptr.lines
} }
// AddExistingFiles adds the specified files to the FileSet if they // AddExistingFiles adds the specified files to the FileSet if they

View file

@ -2,20 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package typeparams contains common utilities for writing tools that interact // Package typeparams contains common utilities for writing tools that
// with generic Go code, as introduced with Go 1.18. // interact with generic Go code, as introduced with Go 1.18. It
// // supplements the standard library APIs. Notably, the StructuralTerms
// Many of the types and functions in this package are proxies for the new APIs // API computes a minimal representation of the structural
// introduced in the standard library with Go 1.18. For example, the
// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec
// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go
// versions older than 1.18 these helpers are implemented as stubs, allowing
// users of this package to write code that handles generic constructs inline,
// even if the Go version being used to compile does not support generics.
//
// Additionally, this package contains common utilities for working with the
// new generic constructs, to supplement the standard library APIs. Notably,
// the StructuralTerms API computes a minimal representation of the structural
// restrictions on a type parameter. // restrictions on a type parameter.
// //
// An external version of these APIs is available in the // An external version of these APIs is available in the
@ -27,6 +17,9 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"go/types" "go/types"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/typesinternal"
) )
// UnpackIndexExpr extracts data from AST nodes that represent index // UnpackIndexExpr extracts data from AST nodes that represent index
@ -72,9 +65,9 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke
} }
} }
// IsTypeParam reports whether t is a type parameter. // IsTypeParam reports whether t is a type parameter (or an alias of one).
func IsTypeParam(t types.Type) bool { func IsTypeParam(t types.Type) bool {
_, ok := t.(*types.TypeParam) _, ok := aliases.Unalias(t).(*types.TypeParam)
return ok return ok
} }
@ -90,13 +83,8 @@ func OriginMethod(fn *types.Func) *types.Func {
if recv == nil { if recv == nil {
return fn return fn
} }
base := recv.Type() _, named := typesinternal.ReceiverNamed(recv)
p, isPtr := base.(*types.Pointer) if named == nil {
if isPtr {
base = p.Elem()
}
named, isNamed := base.(*types.Named)
if !isNamed {
// Receiver is a *types.Interface. // Receiver is a *types.Interface.
return fn return fn
} }
@ -158,6 +146,9 @@ func OriginMethod(fn *types.Func) *types.Func {
// In this case, GenericAssignableTo reports that instantiations of Container // In this case, GenericAssignableTo reports that instantiations of Container
// are assignable to the corresponding instantiation of Interface. // are assignable to the corresponding instantiation of Interface.
func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool { func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool {
V = aliases.Unalias(V)
T = aliases.Unalias(T)
// If V and T are not both named, or do not have matching non-empty type // If V and T are not both named, or do not have matching non-empty type
// parameter lists, fall back on types.AssignableTo. // parameter lists, fall back on types.AssignableTo.

View file

@ -5,7 +5,10 @@
package typeparams package typeparams
import ( import (
"fmt"
"go/types" "go/types"
"golang.org/x/tools/internal/aliases"
) )
// CoreType returns the core type of T or nil if T does not have a core type. // CoreType returns the core type of T or nil if T does not have a core type.
@ -109,7 +112,7 @@ func CoreType(T types.Type) types.Type {
// _NormalTerms makes no guarantees about the order of terms, except that it // _NormalTerms makes no guarantees about the order of terms, except that it
// is deterministic. // is deterministic.
func _NormalTerms(typ types.Type) ([]*types.Term, error) { func _NormalTerms(typ types.Type) ([]*types.Term, error) {
switch typ := typ.(type) { switch typ := aliases.Unalias(typ).(type) {
case *types.TypeParam: case *types.TypeParam:
return StructuralTerms(typ) return StructuralTerms(typ)
case *types.Union: case *types.Union:
@ -120,3 +123,15 @@ func _NormalTerms(typ types.Type) ([]*types.Term, error) {
return []*types.Term{types.NewTerm(false, typ)}, nil return []*types.Term{types.NewTerm(false, typ)}, nil
} }
} }
// MustDeref returns the type of the variable pointed to by t.
// It panics if t's core type is not a pointer.
//
// TODO(adonovan): ideally this would live in typesinternal, but that
// creates an import cycle. Move there when we melt this package down.
func MustDeref(t types.Type) types.Type {
if ptr, ok := CoreType(t).(*types.Pointer); ok {
return ptr.Elem()
}
panic(fmt.Sprintf("%v is not a pointer", t))
}

View file

@ -0,0 +1,43 @@
// Copyright 2024 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 typesinternal
import (
"go/types"
"golang.org/x/tools/internal/aliases"
)
// ReceiverNamed returns the named type (if any) associated with the
// type of recv, which may be of the form N or *N, or aliases thereof.
// It also reports whether a Pointer was present.
func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
t := recv.Type()
if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
isPtr = true
t = ptr.Elem()
}
named, _ = aliases.Unalias(t).(*types.Named)
return
}
// Unpointer returns T given *T or an alias thereof.
// For all other types it is the identity function.
// It does not look at underlying types.
// The result may be an alias.
//
// Use this function to strip off the optional pointer on a receiver
// in a field or method selection, without losing the named type
// (which is needed to compute the method set).
//
// See also [typeparams.MustDeref], which removes one level of
// indirection from the type, regardless of named types (analogous to
// a LOAD instruction).
func Unpointer(t types.Type) types.Type {
if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
return ptr.Elem()
}
return t
}

View file

@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package typesinternal package typesinternal
import ( import (

View file

@ -0,0 +1,43 @@
// Copyright 2023 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 versions
// This file contains predicates for working with file versions to
// decide when a tool should consider a language feature enabled.
// GoVersions that features in x/tools can be gated to.
const (
Go1_18 = "go1.18"
Go1_19 = "go1.19"
Go1_20 = "go1.20"
Go1_21 = "go1.21"
Go1_22 = "go1.22"
)
// Future is an invalid unknown Go version sometime in the future.
// Do not use directly with Compare.
const Future = ""
// AtLeast reports whether the file version v comes after a Go release.
//
// Use this predicate to enable a behavior once a certain Go release
// has happened (and stays enabled in the future).
func AtLeast(v, release string) bool {
if v == Future {
return true // an unknown future version is always after y.
}
return Compare(Lang(v), Lang(release)) >= 0
}
// Before reports whether the file version v is strictly before a Go release.
//
// Use this predicate to disable a behavior once a certain Go release
// has happened (and stays enabled in the future).
func Before(v, release string) bool {
if v == Future {
return false // an unknown future version happens after y.
}
return Compare(Lang(v), Lang(release)) < 0
}

View file

@ -0,0 +1,14 @@
// Copyright 2024 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 versions
// toolchain is maximum version (<1.22) that the go toolchain used
// to build the current tool is known to support.
//
// When a tool is built with >=1.22, the value of toolchain is unused.
//
// x/tools does not support building with go <1.18. So we take this
// as the minimum possible maximum.
var toolchain string = Go1_18

View file

@ -0,0 +1,14 @@
// Copyright 2024 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.
//go:build go1.19
// +build go1.19
package versions
func init() {
if Compare(toolchain, Go1_19) < 0 {
toolchain = Go1_19
}
}

View file

@ -0,0 +1,14 @@
// Copyright 2024 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.
//go:build go1.20
// +build go1.20
package versions
func init() {
if Compare(toolchain, Go1_20) < 0 {
toolchain = Go1_20
}
}

View file

@ -0,0 +1,14 @@
// Copyright 2024 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.
//go:build go1.21
// +build go1.21
package versions
func init() {
if Compare(toolchain, Go1_21) < 0 {
toolchain = Go1_21
}
}

View file

@ -12,9 +12,19 @@ import (
"go/types" "go/types"
) )
// FileVersions always reports the a file's Go version as the // FileVersion returns a language version (<=1.21) derived from runtime.Version()
// zero version at this Go version. // or an unknown future version.
func FileVersions(info *types.Info, file *ast.File) string { return "" } func FileVersion(info *types.Info, file *ast.File) string {
// In x/tools built with Go <= 1.21, we do not have Info.FileVersions
// available. We use a go version derived from the toolchain used to
// compile the tool by default.
// This will be <= go1.21. We take this as the maximum version that
// this tool can support.
//
// There are no features currently in x/tools that need to tell fine grained
// differences for versions <1.22.
return toolchain
}
// InitFileVersions is a noop at this Go version. // InitFileVersions is a noop when compiled with this Go version.
func InitFileVersions(*types.Info) {} func InitFileVersions(*types.Info) {}

View file

@ -12,10 +12,27 @@ import (
"go/types" "go/types"
) )
// FileVersions maps a file to the file's semantic Go version. // FileVersions returns a file's Go version.
// The reported version is the zero version if a version cannot be determined. // The reported version is an unknown Future version if a
func FileVersions(info *types.Info, file *ast.File) string { // version cannot be determined.
return info.FileVersions[file] func FileVersion(info *types.Info, file *ast.File) string {
// In tools built with Go >= 1.22, the Go version of a file
// follow a cascades of sources:
// 1) types.Info.FileVersion, which follows the cascade:
// 1.a) file version (ast.File.GoVersion),
// 1.b) the package version (types.Config.GoVersion), or
// 2) is some unknown Future version.
//
// File versions require a valid package version to be provided to types
// in Config.GoVersion. Config.GoVersion is either from the package's module
// or the toolchain (go run). This value should be provided by go/packages
// or unitchecker.Config.GoVersion.
if v := info.FileVersions[file]; IsValid(v) {
return v
}
// Note: we could instead return runtime.Version() [if valid].
// This would act as a max version on what a tool can support.
return Future
} }
// InitFileVersions initializes info to record Go versions for Go files. // InitFileVersions initializes info to record Go versions for Go files.

View file

@ -4,6 +4,10 @@
package versions package versions
import (
"strings"
)
// Note: If we use build tags to use go/versions when go >=1.22, // Note: If we use build tags to use go/versions when go >=1.22,
// we run into go.dev/issue/53737. Under some operations users would see an // we run into go.dev/issue/53737. Under some operations users would see an
// import of "go/versions" even if they would not compile the file. // import of "go/versions" even if they would not compile the file.
@ -45,6 +49,7 @@ func IsValid(x string) bool { return isValid(stripGo(x)) }
// stripGo converts from a "go1.21" version to a "1.21" version. // stripGo converts from a "go1.21" version to a "1.21" version.
// If v does not start with "go", stripGo returns the empty string (a known invalid version). // If v does not start with "go", stripGo returns the empty string (a known invalid version).
func stripGo(v string) string { func stripGo(v string) string {
v, _, _ = strings.Cut(v, "-") // strip -bigcorp suffix.
if len(v) < 2 || v[:2] != "go" { if len(v) < 2 || v[:2] != "go" {
return "" return ""
} }

4
vendor/modernc.org/libc/.gitignore generated vendored Normal file
View file

@ -0,0 +1,4 @@
*.gz
*.zip
go.work
go.sum

1
vendor/modernc.org/libc/AUTHORS generated vendored
View file

@ -14,4 +14,5 @@ Jan Mercl <0xjnml@gmail.com>
Jason DeBettencourt <jasond17@gmail.com> Jason DeBettencourt <jasond17@gmail.com>
Koichi Shiraishi <zchee.io@gmail.com> Koichi Shiraishi <zchee.io@gmail.com>
Marius Orcsik <marius@federated.id> Marius Orcsik <marius@federated.id>
Scot C Bontrager <scot@indievisible.org>
Steffen Butzer <steffen(dot)butzer@outlook.com> Steffen Butzer <steffen(dot)butzer@outlook.com>

View file

@ -13,5 +13,6 @@ Jan Mercl <0xjnml@gmail.com>
Jason DeBettencourt <jasond17@gmail.com> Jason DeBettencourt <jasond17@gmail.com>
Koichi Shiraishi <zchee.io@gmail.com> Koichi Shiraishi <zchee.io@gmail.com>
Marius Orcsik <marius@federated.id> Marius Orcsik <marius@federated.id>
Scot C Bontrager <scot@indievisible.org>
Steffen Butzer <steffen(dot)butzer@outlook.com> Steffen Butzer <steffen(dot)butzer@outlook.com>
ZHU Zijia <piggynl@outlook.com> ZHU Zijia <piggynl@outlook.com>

193
vendor/modernc.org/libc/COPYRIGHT-MUSL generated vendored Normal file
View file

@ -0,0 +1,193 @@
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
Copyright © 2005-2020 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
Authors/contributors include:
A. Wilcox
Ada Worcester
Alex Dowad
Alex Suykov
Alexander Monakov
Andre McCurdy
Andrew Kelley
Anthony G. Basile
Aric Belsito
Arvid Picciani
Bartosz Brachaczek
Benjamin Peterson
Bobby Bingham
Boris Brezillon
Brent Cook
Chris Spiegel
Clément Vasseur
Daniel Micay
Daniel Sabogal
Daurnimator
David Carlier
David Edelsohn
Denys Vlasenko
Dmitry Ivanov
Dmitry V. Levin
Drew DeVault
Emil Renner Berthing
Fangrui Song
Felix Fietkau
Felix Janda
Gianluca Anzolin
Hauke Mehrtens
He X
Hiltjo Posthuma
Isaac Dunham
Jaydeep Patil
Jens Gustedt
Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
Julien Ramseier
Justin Cormack
Kaarle Ritvanen
Khem Raj
Kylie McClain
Leah Neukirchen
Luca Barbato
Luka Perkov
M Farkas-Dyck (Strake)
Mahesh Bodapati
Markus Wichmann
Masanori Ogino
Michael Clark
Michael Forney
Mikhail Kremnyov
Natanael Copa
Nicholas J. Kain
orc
Pascal Cuoq
Patrick Oppenlander
Petr Hosek
Petr Skocik
Pierre Carrier
Reini Urban
Rich Felker
Richard Pennington
Ryan Fairfax
Samuel Holland
Segev Finer
Shiz
sin
Solar Designer
Stefan Kristiansson
Stefan O'Rear
Szabolcs Nagy
Timo Teräs
Trutz Behn
Valentin Ochs
Will Dietz
William Haddon
William Pitcock
Portions of this software are derived from third-party works licensed
under terms compatible with the above MIT license:
The TRE regular expression implementation (src/regex/reg* and
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
under a 2-clause BSD license (license text in the source files). The
included version has been heavily modified by Rich Felker in 2012, in
the interests of size, simplicity, and namespace cleanliness.
Much of the math library code (src/math/* and src/complex/*) is
Copyright © 1993,2004 Sun Microsystems or
Copyright © 2003-2011 David Schultz or
Copyright © 2003-2009 Steven G. Kargl or
Copyright © 2003-2009 Bruce D. Evans or
Copyright © 2008 Stephen L. Moshier or
Copyright © 2017-2018 Arm Limited
and labelled as such in comments in the individual source files. All
have been licensed under extremely permissive terms.
The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008
The Android Open Source Project and is licensed under a two-clause BSD
license. It was taken from Bionic libc, used on Android.
The AArch64 memcpy and memset code (src/string/aarch64/*) are
Copyright © 1999-2019, Arm Limited.
The implementation of DES for crypt (src/crypt/crypt_des.c) is
Copyright © 1994 David Burren. It is licensed under a BSD license.
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
originally written by Solar Designer and placed into the public
domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
Valentin Ochs and is licensed under an MIT-style license.
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
The mips and microblaze ports were originally written by Richard
Pennington for use in the ellcc project. The original code was adapted
by Rich Felker for build system and code conventions during upstream
integration. It is licensed under the standard MIT terms.
The mips64 port was contributed by Imagination Technologies and is
licensed under the standard MIT terms.
The powerpc port was also originally written by Richard Pennington,
and later supplemented and integrated by John Spencer. It is licensed
under the standard MIT terms.
All other files which have no copyright comments are original works
produced specifically for use as part of this library, written either
by Rich Felker, the main author of the library, or by one or more
contibutors listed above. Details on authorship of individual files
can be found in the git version control history of the project. The
omission of copyright and license comments in each file is in the
interest of source tree size.
In addition, permission is hereby granted for all public header files
(include/* and arch/*/bits/*) and crt files intended to be linked into
applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
the copyright notice and permission notice otherwise required by the
license, and to use these files without any requirement of
attribution. These files include substantial contributions from:
Bobby Bingham
John Spencer
Nicholas J. Kain
Rich Felker
Richard Pennington
Stefan Kristiansson
Szabolcs Nagy
all of whom have explicitly granted such permission.
This file previously contained text expressing a belief that most of
the files covered by the above exception were sufficiently trivial not
to be subject to copyright, resulting in confusion over whether it
negated the permissions granted in the license. In the spirit of
permissive licensing, and of not having licensing issues being an
obstacle to adoption, that text has been removed.

3
vendor/modernc.org/libc/HACKING generated vendored
View file

@ -1,3 +0,0 @@
Install:
$ go get modernc.org/libc

265
vendor/modernc.org/libc/Makefile generated vendored
View file

@ -1,197 +1,116 @@
# Copyright 2019 The Libc Authors. All rights reserved. # Copyright 2024 The Libc Authors. All rights reserved.
# Use of this source code is governed by a BSD-style # Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file. # license that can be found in the LICENSE file.
.PHONY: all bench build_all_targets clean cover cpu editor internalError later mem nuke todo edit work devbench \ .PHONY: all build_all_targets check clean download edit editor generate dev membrk-test test work xtest short-test xlibc libc-test surface
darwin_amd64 \
darwin_arm64 \
linux_386 \
linux_amd64 \
linux_arm \
linux_arm64 \
strace \
SHELL=/bin/bash -o pipefail
grep=--include=*.go --include=*.l --include=*.y --include=*.yy --include=*.qbe --include=*.ssa DIR = /tmp/libc
ngrep='internalError\|TODOOK' TAR = musl-7ada6dde6f9dc6a2836c3d92c2f762d35fd229e0.tar.gz
log=log-$(shell go env GOOS)-$(shell go env GOARCH) URL = https://git.musl-libc.org/cgit/musl/snapshot/$(TAR)
all: all: editor
date golint 2>&1
go version 2>&1 | tee $(log) staticcheck 2>&1
go generate
gofmt -l -s -w *.go
go install -v ./...
go test
go test 2>&1 -timeout 1h | tee -a $(log)
# go vet -unsafeptr=false 2>&1 | grep -v $(ngrep) || true
# golint 2>&1 | grep -v $(ngrep) || true
# make todo
# misspell *.go
# staticcheck || true
grep -n 'FAIL\|PASS' $(log)
go version
date 2>&1 | tee -a $(log)
build_all_targets: build_all_targets:
./build_all_targets.sh ./build_all_targets.sh
echo done echo done
darwin_amd64:
@echo "Should be executed only on darwin/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
darwin_arm64:
@echo "Should be executed only on darwin/arm64."
go generate 2>&1 | tee log-generate
go build -v ./...
# only on freebsd/amd64
freebsd_amd64:
@echo "Should be executed only on freebsd/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
# only on freebsd/386
freebsd_386:
@echo "Should be executed only on freebsd/386."
go generate 2>&1 | tee log-generate
go build -v ./...
# only on freebsd/arm
freebsd_arm:
@echo "Should be executed only on freebsd/arm."
go generate 2>&1 | tee log-generate
go build -v ./...
freebsd_arm64:
go run addport.go freebsd_amd64 freebsd_arm64
go build -v ./...
# only on netbsd/amd64
netbsd_amd64:
@echo "Should be executed only on netbsd/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
# only on netbsd/arm
netbsd_arm:
@echo "Should be executed only on netbsd/arm."
go generate 2>&1 | tee log-generate
go build -v ./...
linux_amd64:
@echo "Should be executed only on linux/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
linux_386:
CCGO_CPP=i686-linux-gnu-cpp TARGET_GOOS=linux TARGET_GOARCH=386 go generate
GOOS=linux GOARCH=386 go build -v ./...
linux_arm:
CCGO_CPP=arm-linux-gnueabi-cpp TARGET_GOOS=linux TARGET_GOARCH=arm go generate
GOOS=linux GOARCH=arm go build -v ./...
linux_arm64:
CCGO_CPP=aarch64-linux-gnu-cpp TARGET_GOOS=linux TARGET_GOARCH=arm64 go generate
GOOS=linux GOARCH=arm64 go build -v ./...
linux_s390x:
CCGO_CPP=s390x-linux-gnu-cpp TARGET_GOOS=linux TARGET_GOARCH=s390x go generate
GOOS=linux GOARCH=s390x go build -v ./...
linux_ppc64le:
CCGO_CPP=powerpc64le-linux-gnu-cpp TARGET_GOOS=linux TARGET_GOARCH=ppc64le go generate
GOOS=linux GOARCH=ppc64le go build -v ./...
# only on openbsd/amd64
openbsd_amd64:
@echo "Should be executed only on openbsd/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
#
# only on openbsd/386
openbsd_386:
@echo "Should be executed only on openbsd/386."
go generate 2>&1 | tee log-generate
go build -v ./...
# only on openbsd/arm64
openbsd_arm64:
@echo "Should be executed only on openbsd/arm64."
go generate 2>&1 | tee log-generate
go build -v ./...
windows_amd64:
@echo "Should be executed only on windows/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
windows_arm64:
@echo "Should be executed only on windows/arm64."
go generate 2>&1 | tee log-generate
go build -v ./...
windows_386:
@echo "Should be executed only on linux/amd64."
CCGO_CPP=i686-w64-mingw32-cpp TARGET_GOOS=windows TARGET_GOARCH=386 go generate
GOOS=windows GOARCH=386 go build -v ./...
all_targets: linux_amd64 linux_386 linux_arm linux_arm64 linux_s390x # windows_amd64 windows_386
echo done
devbench:
date 2>&1 | tee log-devbench
go test -timeout 24h -dev -run @ -bench . 2>&1 | tee -a log-devbench
grep -n 'FAIL\|SKIP' log-devbench || true
bench:
date 2>&1 | tee log-bench
go test -timeout 24h -v -run '^[^E]' -bench . 2>&1 | tee -a log-bench
grep -n 'FAIL\|SKIP' log-bench || true
clean: clean:
rm -f log-* cpu.test mem.test *.out
git clean -fd
find testdata/nsz.repo.hu/ -name \*.go -delete
make -C testdata/nsz.repo.hu/libc-test/ cleanall
go clean go clean
rm -f *~ *.test *.out
cover: check:
t=$(shell mktemp) ; go test -coverprofile $$t && go tool cover -html $$t && unlink $$t staticcheck 2>&1 | grep -v U1000
cpu: clean download:
go test -run @ -bench . -cpuprofile cpu.out @if [ ! -f $(TAR) ]; then wget $(URL) ; fi
go tool pprof -lines *.test cpu.out
edit: edit:
@touch log @touch log
@if [ -f "Session.vim" ]; then novim -S & else novim -p Makefile libc.go & fi @if [ -f "Session.vim" ]; then novim -S & else novim -p Makefile all_musl_test.go generator.go libc.go libc_musl.go & fi
editor: editor:
# go generate 2>&1 | tee log gofmt -l -s -w *.go 2>&1 | tee log-editor
gofmt -l -s -w *.go go test -c -o /dev/null 2>&1 | tee -a log-editor
go test -short 2>&1 | tee -a log go install -v 2>&1 | tee -a log-editor
go install -v ./... go build -o /dev/null generator*.go
go build -o /dev/null generate.go
go build -o /dev/null strace.go
later: generate: download
@grep -n $(grep) LATER * || true mkdir -p $(DIR) || true
@grep -n $(grep) MAYBE * || true rm -rf $(DIR)/*
GO_GENERATE_DIR=$(DIR) go run generator*.go 2>&1 | tee log-generate
go build -v
# go install github.com/mdempsky/unconvert@latest
go build -v 2>&1 | tee -a log-generate
go test -v -short -count=1 ./... | tee -a log-generate
git status | tee -a log-generate
grep 'TRC\|TODO\|ERRORF\|FAIL' log-generate || true
mem: clean dev: download
go test -v -run ParserCS -memprofile mem.out -timeout 24h mkdir -p $(DIR) || true
go tool pprof -lines -web -alloc_space *.test mem.out rm -rf $(DIR)/*
echo -n > /tmp/ccgo.log
GO_GENERATE_DIR=$(DIR) GO_GENERATE_DEV=1 go run -tags=ccgo.dmesg,ccgo.assert generator*.go 2>&1 | tee log-generate
go build -v | tee -a log-generate
go test -v -short -count=1 ./... | tee -a log-generate
git status | tee -a log-generate
grep 'TRC\|TODO\|ERRORF\|FAIL' log-generate || true
grep 'TRC\|TODO\|ERRORF\|FAIL' /tmp/ccgo.log || true
nuke: clean membrk-test:
go clean -i echo -n > /tmp/ccgo.log
touch log-test
cp log-test log-test0
go test -v -timeout 24h -count=1 -tags=libc.membrk 2>&1 | tee log-test
grep -a 'TRC\|TODO\|ERRORF\|FAIL' log-test || true 2>&1 | tee -a log-test
todo: test:
@grep -nr $(grep) ^[[:space:]]*_[[:space:]]*=[[:space:]][[:alpha:]][[:alnum:]]* * | grep -v $(ngrep) || true echo -n > /tmp/ccgo.log
@grep -nr $(grep) 'TODO\|panic' * | grep -v $(ngrep) || true touch log-test
@grep -nr $(grep) BUG * | grep -v $(ngrep) || true cp log-test log-test0
@grep -nr $(grep) [^[:alpha:]]println * | grep -v $(ngrep) || true go test -v -timeout 24h -count=1 2>&1 | tee log-test
@grep -nir $(grep) 'work.*progress' || true
short-test:
echo -n > /tmp/ccgo.log
touch log-test
cp log-test log-test0
go test -v -timeout 24h -count=1 -short 2>&1 | tee log-test
grep -a 'TRC\|TODO\|ERRORF\|FAIL' log-test || true 2>&1 | tee -a log-test
xlibc:
echo -n > /tmp/ccgo.log
touch log-test
cp log-test log-test0
go test -v -timeout 24h -count=1 -tags=ccgo.dmesg,ccgo.assert 2>&1 -run TestLibc | tee log-test
grep -a 'TRC\|TODO\|ERRORF\|FAIL' log-test || true 2>&1 | tee -a log-test
xpthread:
echo -n > /tmp/ccgo.log
touch log-test
cp log-test log-test0
go test -v -timeout 24h -count=1 2>&1 -run TestLibc -re pthread | tee log-test
grep -a 'TRC\|TODO\|ERRORF\|FAIL' log-test || true 2>&1 | tee -a log-test
libc-test:
echo -n > /tmp/ccgo.log
touch log-test
cp log-test log-test0
go test -v -timeout 24h -count=1 2>&1 -run TestLibc | tee log-test
# grep -a 'TRC\|TODO\|ERRORF\|FAIL' log-test || true 2>&1 | tee -a log-test
grep -o 'undefined: \<.*\>' log-test | sort -u
xtest:
echo -n > /tmp/ccgo.log
touch log-test
cp log-test log-test0
go test -v -timeout 24h -count=1 -tags=ccgo.dmesg,ccgo.assert 2>&1 | tee log-test
grep -a 'TRC\|TODO\|ERRORF\|FAIL' log-test || true 2>&1 | tee -a log-test
work: work:
rm -f go.work* rm -f go.work*
@ -201,6 +120,6 @@ work:
go work use ../ccgo/v3 go work use ../ccgo/v3
go work use ../cc/v4 go work use ../cc/v4
strace: surface:
go run strace.go surface > surface.new
go build -v ./... surface surface.old surface.new > log-todo-surface || true

109
vendor/modernc.org/libc/aliases.go generated vendored Normal file
View file

@ -0,0 +1,109 @@
// Copyright 2024 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && (amd64 || loong64)
package libc // import "modernc.org/libc"
func X__vm_wait(tls *TLS) {}
// static volatile int *const dummy_lockptr = 0;
//
// weak_alias(dummy_lockptr, __atexit_lockptr);
// weak_alias(dummy_lockptr, __bump_lockptr);
// weak_alias(dummy_lockptr, __sem_open_lockptr);
var X__atexit_lockptr int32
var X__bump_lockptr int32
var X__sem_open_lockptr int32
// static int dummy(int fd)
//
// {
// return fd;
// }
//
// weak_alias(dummy, __aio_close);
func X__aio_close(tls *TLS, fd int32) int32 {
return fd
}
func Xtzset(tls *TLS) {
___tzset(tls)
}
type DIR = TDIR
const DT_DETACHED = _DT_DETACHED
const DT_EXITING = _DT_EXITING
const DT_JOINABLE = _DT_JOINABLE
type FILE = TFILE
type HEADER = THEADER
func Xfcntl64(tls *TLS, fd int32, cmd int32, va uintptr) (r int32) {
return Xfcntl(tls, fd, cmd, va)
}
func Xfopen64(tls *TLS, filename uintptr, mode uintptr) (r uintptr) {
return Xfopen(tls, filename, mode)
}
func Xfstat64(tls *TLS, fd int32, st uintptr) (r int32) {
return Xfstat(tls, fd, st)
}
func Xftruncate64(tls *TLS, fd int32, length Toff_t) (r int32) {
return Xftruncate(tls, fd, length)
}
func Xgetrlimit64(tls *TLS, resource int32, rlim uintptr) (r int32) {
return Xgetrlimit(tls, resource, rlim)
}
func Xlseek64(tls *TLS, fd int32, offset Toff_t, whence int32) (r Toff_t) {
return Xlseek(tls, fd, offset, whence)
}
func Xlstat64(tls *TLS, path uintptr, buf uintptr) (r int32) {
return Xlstat(tls, path, buf)
}
func Xmkstemp64(tls *TLS, template uintptr) (r int32) {
return Xmkstemp(tls, template)
}
func Xmkstemps64(tls *TLS, template uintptr, len1 int32) (r int32) {
return Xmkstemps(tls, template, len1)
}
func Xmmap64(tls *TLS, start uintptr, len1 Tsize_t, prot int32, flags int32, fd int32, off Toff_t) (r uintptr) {
return Xmmap(tls, start, len1, prot, flags, fd, off)
}
func Xopen64(tls *TLS, filename uintptr, flags int32, va uintptr) (r int32) {
return Xopen(tls, filename, flags, va)
}
func Xreaddir64(tls *TLS, dir uintptr) (r uintptr) {
return Xreaddir(tls, dir)
}
func Xsetrlimit64(tls *TLS, resource int32, rlim uintptr) (r int32) {
return Xsetrlimit(tls, resource, rlim)
}
func Xstat64(tls *TLS, path uintptr, buf uintptr) (r int32) {
return Xstat(tls, path, buf)
}
func Xpthread_setcancelstate(tls *TLS, new int32, old uintptr) int32 {
return _pthread_setcancelstate(tls, new, old)
}
func Xpthread_sigmask(tls *TLS, now int32, set, old uintptr) int32 {
return _pthread_sigmask(tls, now, set, old)
}

114
vendor/modernc.org/libc/atomic.go generated vendored Normal file
View file

@ -0,0 +1,114 @@
// Copyright 2024 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && (amd64 || loong64)
package libc // import "modernc.org/libc/v2"
import (
"math"
"math/bits"
"sync/atomic"
"unsafe"
)
func a_store_8(addr uintptr, val int8) int8 {
*(*int8)(unsafe.Pointer(addr)) = val
return val
}
func a_load_8(addr uintptr) (val int8) {
return *(*int8)(unsafe.Pointer(addr))
}
func a_load_16(addr uintptr) (val int16) {
if addr&1 != 0 {
panic("unaligned atomic access")
}
return *(*int16)(unsafe.Pointer(addr))
}
func a_store_16(addr uintptr, val uint16) {
if addr&1 != 0 {
panic("unaligned atomic access")
}
*(*uint16)(unsafe.Pointer(addr)) = val
}
// static inline int a_ctz_l(unsigned long x)
func _a_ctz_l(tls *TLS, x ulong) int32 {
if unsafe.Sizeof(x) == 8 {
return int32(bits.TrailingZeros64(x))
}
return int32(bits.TrailingZeros32(uint32(x)))
}
// static inline int a_ctz_64(uint64_t x)
func _a_ctz_64(tls *TLS, x uint64) int32 {
return int32(bits.TrailingZeros64(x))
}
func AtomicAddFloat32(addr *float32, delta float32) (new float32) {
v := AtomicLoadFloat32(addr) + delta
AtomicStoreFloat32(addr, v)
return v
}
func AtomicLoadFloat32(addr *float32) (val float32) {
return math.Float32frombits(atomic.LoadUint32((*uint32)(unsafe.Pointer(addr))))
}
func AtomicStoreFloat32(addr *float32, val float32) {
atomic.StoreUint32((*uint32)(unsafe.Pointer(addr)), math.Float32bits(val))
}
func AtomicAddFloat64(addr *float64, delta float64) (new float64) {
v := AtomicLoadFloat64(addr) + delta
AtomicStoreFloat64(addr, v)
return v
}
func AtomicLoadFloat64(addr *float64) (val float64) {
return math.Float64frombits(atomic.LoadUint64((*uint64)(unsafe.Pointer(addr))))
}
func AtomicStoreFloat64(addr *float64, val float64) {
atomic.StoreUint64((*uint64)(unsafe.Pointer(addr)), math.Float64bits(val))
}
func AtomicAddInt32(addr *int32, delta int32) (new int32) { return atomic.AddInt32(addr, delta) }
func AtomicAddInt64(addr *int64, delta int64) (new int64) { return atomic.AddInt64(addr, delta) }
func AtomicAddUint32(addr *uint32, delta uint32) (new uint32) { return atomic.AddUint32(addr, delta) }
func AtomicAddUint64(addr *uint64, delta uint64) (new uint64) { return atomic.AddUint64(addr, delta) }
func AtomicAddUintptr(addr *uintptr, delta uintptr) (new uintptr) {
return atomic.AddUintptr(addr, delta)
}
func AtomicLoadInt32(addr *int32) (val int32) { return atomic.LoadInt32(addr) }
func AtomicLoadInt64(addr *int64) (val int64) { return atomic.LoadInt64(addr) }
func AtomicLoadUint32(addr *uint32) (val uint32) { return atomic.LoadUint32(addr) }
func AtomicLoadUint64(addr *uint64) (val uint64) { return atomic.LoadUint64(addr) }
func AtomicLoadUintptr(addr *uintptr) (val uintptr) { return atomic.LoadUintptr(addr) }
func AtomicStoreInt32(addr *int32, val int32) { atomic.StoreInt32(addr, val) }
func AtomicStoreUint32(addr *uint32, val uint32) { atomic.StoreUint32(addr, val) }
func AtomicStoreUint64(addr *uint64, val uint64) { atomic.StoreUint64(addr, val) }
func AtomicStoreUintptr(addr *uintptr, val uintptr) { atomic.StoreUintptr(addr, val) }
func AtomicStoreInt64(addr *int64, val int64) { atomic.StoreInt64(addr, val) }

9
vendor/modernc.org/libc/builder.json generated vendored Normal file
View file

@ -0,0 +1,9 @@
{
"autogen": "linux/(amd64|loong64)",
"autoupdate": "",
"autotag": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/(386|amd64|arm64)|windows/(amd64|arm64)",
"download": [
{"re": "linux/(amd64|loong64)", "files": ["https://git.musl-libc.org/cgit/musl/snapshot/musl-7ada6dde6f9dc6a2836c3d92c2f762d35fd229e0.tar.gz"]}
],
"test": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/(386|amd64|arm64)|windows/(amd64|arm64)"
}

439
vendor/modernc.org/libc/builtin.go generated vendored Normal file
View file

@ -0,0 +1,439 @@
// Copyright 2024 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && (amd64 || loong64)
package libc // import "modernc.org/libc"
import (
"fmt"
"math"
mbits "math/bits"
"os"
"unsafe"
"modernc.org/mathutil"
)
func X__builtin_inff(tls *TLS) float32 {
return float32(math.Inf(1))
}
func X__builtin_nanf(tls *TLS, s uintptr) float32 {
return float32(math.NaN())
}
func X__builtin_printf(tls *TLS, fmt uintptr, va uintptr) (r int32) {
return Xprintf(tls, fmt, va)
}
func X__builtin_round(tls *TLS, x float64) (r float64) {
return Xround(tls, x)
}
func X__builtin_expect(t *TLS, exp, c long) long {
return exp
}
func X__builtin_bzero(t *TLS, s uintptr, n Tsize_t) {
Xbzero(t, s, n)
}
func X__builtin_abort(t *TLS) {
Xabort(t)
}
func X__builtin_abs(t *TLS, j int32) int32 {
return Xabs(t, j)
}
func X__builtin_ctz(t *TLS, n uint32) int32 {
return int32(mbits.TrailingZeros32(n))
}
func X__builtin_clz(t *TLS, n uint32) int32 {
return int32(mbits.LeadingZeros32(n))
}
func X__builtin_clzl(t *TLS, n ulong) int32 {
return int32(mbits.LeadingZeros64(n))
}
func X__builtin_clzll(t *TLS, n uint64) int32 {
return int32(mbits.LeadingZeros64(n))
}
func X__builtin_constant_p_impl() { panic(todo("internal error: should never be called")) }
func X__builtin_copysign(t *TLS, x, y float64) float64 {
return Xcopysign(t, x, y)
}
func X__builtin_copysignf(t *TLS, x, y float32) float32 {
return Xcopysignf(t, x, y)
}
func X__builtin_copysignl(t *TLS, x, y float64) float64 {
return Xcopysign(t, x, y)
}
func X__builtin_exit(t *TLS, status int32) {
Xexit(t, status)
}
func X__builtin_fabs(t *TLS, x float64) float64 {
return Xfabs(t, x)
}
func X__builtin_fabsf(t *TLS, x float32) float32 {
return Xfabsf(t, x)
}
func X__builtin_fabsl(t *TLS, x float64) float64 {
return Xfabsl(t, x)
}
func X__builtin_free(t *TLS, ptr uintptr) {
Xfree(t, ptr)
}
func X__builtin_getentropy(t *TLS, buf uintptr, n Tsize_t) int32 {
return Xgetentropy(t, buf, n)
}
func X__builtin_huge_val(t *TLS) float64 {
return math.Inf(1)
}
func X__builtin_huge_valf(t *TLS) float32 {
return float32(math.Inf(1))
}
func X__builtin_inf(t *TLS) float64 {
return math.Inf(1)
}
func X__builtin_infl(t *TLS) float64 {
return math.Inf(1)
}
func X__builtin_malloc(t *TLS, size Tsize_t) uintptr {
return Xmalloc(t, size)
}
func X__builtin_memcmp(t *TLS, s1, s2 uintptr, n Tsize_t) int32 {
return Xmemcmp(t, s1, s2, n)
}
func X__builtin_nan(t *TLS, s uintptr) float64 {
return math.NaN()
}
func X__builtin_nanl(t *TLS, s uintptr) float64 {
return math.NaN()
}
func X__builtin_prefetch(t *TLS, addr, args uintptr) {
}
func X__builtin_strchr(t *TLS, s uintptr, c int32) uintptr {
return Xstrchr(t, s, c)
}
func X__builtin_strcmp(t *TLS, s1, s2 uintptr) int32 {
return Xstrcmp(t, s1, s2)
}
func X__builtin_strcpy(t *TLS, dest, src uintptr) uintptr {
return Xstrcpy(t, dest, src)
}
func X__builtin_strlen(t *TLS, s uintptr) Tsize_t {
return Xstrlen(t, s)
}
func X__builtin_trap(t *TLS) {
Xabort(t)
}
func X__builtin_popcount(t *TLS, x uint32) int32 {
return int32(mbits.OnesCount32(x))
}
// int __builtin_popcountl (unsigned long x)
func X__builtin_popcountl(t *TLS, x ulong) int32 {
return int32(mbits.OnesCount64(x))
}
// char * __builtin___strcpy_chk (char *dest, const char *src, size_t os);
func X__builtin___strcpy_chk(t *TLS, dest, src uintptr, os Tsize_t) uintptr {
return Xstrcpy(t, dest, src)
}
func X__builtin_mmap(t *TLS, addr uintptr, length Tsize_t, prot, flags, fd int32, offset Toff_t) uintptr {
return Xmmap(t, addr, length, prot, flags, fd, offset)
}
// uint16_t __builtin_bswap16 (uint32_t x)
func X__builtin_bswap16(t *TLS, x uint16) uint16 {
return x<<8 |
x>>8
}
// uint32_t __builtin_bswap32 (uint32_t x)
func X__builtin_bswap32(t *TLS, x uint32) uint32 {
return x<<24 |
x&0xff00<<8 |
x&0xff0000>>8 |
x>>24
}
// uint64_t __builtin_bswap64 (uint64_t x)
func X__builtin_bswap64(t *TLS, x uint64) uint64 {
return x<<56 |
x&0xff00<<40 |
x&0xff0000<<24 |
x&0xff000000<<8 |
x&0xff00000000>>8 |
x&0xff0000000000>>24 |
x&0xff000000000000>>40 |
x>>56
}
// bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
func X__builtin_add_overflowInt64(t *TLS, a, b int64, res uintptr) int32 {
r, ovf := mathutil.AddOverflowInt64(a, b)
*(*int64)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
// bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
func X__builtin_add_overflowUint32(t *TLS, a, b uint32, res uintptr) int32 {
r := a + b
*(*uint32)(unsafe.Pointer(res)) = r
return Bool32(r < a)
}
// bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
func X__builtin_add_overflowUint64(t *TLS, a, b uint64, res uintptr) int32 {
r := a + b
*(*uint64)(unsafe.Pointer(res)) = r
return Bool32(r < a)
}
// bool __builtin_sub_overflow (type1 a, type2 b, type3 *res)
func X__builtin_sub_overflowInt64(t *TLS, a, b int64, res uintptr) int32 {
r, ovf := mathutil.SubOverflowInt64(a, b)
*(*int64)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
// bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
func X__builtin_mul_overflowInt64(t *TLS, a, b int64, res uintptr) int32 {
r, ovf := mathutil.MulOverflowInt64(a, b)
*(*int64)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
// bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
func X__builtin_mul_overflowUint64(t *TLS, a, b uint64, res uintptr) int32 {
hi, lo := mbits.Mul64(a, b)
*(*uint64)(unsafe.Pointer(res)) = lo
return Bool32(hi != 0)
}
// bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
func X__builtin_mul_overflowUint128(t *TLS, a, b Uint128, res uintptr) int32 {
r, ovf := a.mulOvf(b)
*(*Uint128)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
func X__builtin_unreachable(t *TLS) {
fmt.Fprintf(os.Stderr, "unrechable\n")
os.Stderr.Sync()
Xexit(t, 1)
}
func X__builtin_snprintf(t *TLS, str uintptr, size Tsize_t, format, args uintptr) int32 {
return Xsnprintf(t, str, size, format, args)
}
func X__builtin_sprintf(t *TLS, str, format, args uintptr) (r int32) {
return Xsprintf(t, str, format, args)
}
func X__builtin_memcpy(t *TLS, dest, src uintptr, n Tsize_t) (r uintptr) {
return Xmemcpy(t, dest, src, n)
}
// void * __builtin___memcpy_chk (void *dest, const void *src, size_t n, size_t os);
func X__builtin___memcpy_chk(t *TLS, dest, src uintptr, n, os Tsize_t) (r uintptr) {
if os != ^Tsize_t(0) && n < os {
Xabort(t)
}
return Xmemcpy(t, dest, src, n)
}
func X__builtin_memset(t *TLS, s uintptr, c int32, n Tsize_t) uintptr {
return Xmemset(t, s, c, n)
}
// void * __builtin___memset_chk (void *s, int c, size_t n, size_t os);
func X__builtin___memset_chk(t *TLS, s uintptr, c int32, n, os Tsize_t) uintptr {
if os < n {
Xabort(t)
}
return Xmemset(t, s, c, n)
}
// size_t __builtin_object_size (const void * ptr, int type)
func X__builtin_object_size(t *TLS, p uintptr, typ int32) Tsize_t {
return ^Tsize_t(0) //TODO frontend magic
}
// int __builtin___sprintf_chk (char *s, int flag, size_t os, const char *fmt, ...);
func X__builtin___sprintf_chk(t *TLS, s uintptr, flag int32, os Tsize_t, format, args uintptr) (r int32) {
return Xsprintf(t, s, format, args)
}
func X__builtin_vsnprintf(t *TLS, str uintptr, size Tsize_t, format, va uintptr) int32 {
return Xvsnprintf(t, str, size, format, va)
}
// int __builtin___snprintf_chk(char * str, size_t maxlen, int flag, size_t os, const char * format, ...);
func X__builtin___snprintf_chk(t *TLS, str uintptr, maxlen Tsize_t, flag int32, os Tsize_t, format, args uintptr) (r int32) {
if os != ^Tsize_t(0) && maxlen > os {
Xabort(t)
}
return Xsnprintf(t, str, maxlen, format, args)
}
// int __builtin___vsnprintf_chk (char *s, size_t maxlen, int flag, size_t os, const char *fmt, va_list ap);
func X__builtin___vsnprintf_chk(t *TLS, str uintptr, maxlen Tsize_t, flag int32, os Tsize_t, format, args uintptr) (r int32) {
if os != ^Tsize_t(0) && maxlen > os {
Xabort(t)
}
return Xsnprintf(t, str, maxlen, format, args)
}
func Xisnan(t *TLS, x float64) int32 {
return X__builtin_isnan(t, x)
}
func X__isnan(t *TLS, x float64) int32 {
return X__builtin_isnan(t, x)
}
func X__builtin_isnan(t *TLS, x float64) int32 {
return Bool32(math.IsNaN(x))
}
func Xisnanf(t *TLS, arg float32) int32 {
return X__builtin_isnanf(t, arg)
}
func X__isnanf(t *TLS, arg float32) int32 {
return X__builtin_isnanf(t, arg)
}
func X__builtin_isnanf(t *TLS, x float32) int32 {
return Bool32(math.IsNaN(float64(x)))
}
func Xisnanl(t *TLS, arg float64) int32 {
return X__builtin_isnanl(t, arg)
}
func X__isnanl(t *TLS, arg float64) int32 {
return X__builtin_isnanl(t, arg)
}
func X__builtin_isnanl(t *TLS, x float64) int32 {
return Bool32(math.IsNaN(x))
}
func X__builtin_llabs(tls *TLS, a int64) int64 {
return Xllabs(tls, a)
}
func X__builtin_log2(t *TLS, x float64) float64 {
return Xlog2(t, x)
}
func X__builtin___strncpy_chk(t *TLS, dest, src uintptr, n, os Tsize_t) (r uintptr) {
if n != ^Tsize_t(0) && os < n {
Xabort(t)
}
return Xstrncpy(t, dest, src, n)
}
func X__builtin___strcat_chk(t *TLS, dest, src uintptr, os Tsize_t) (r uintptr) {
return Xstrcat(t, dest, src)
}
func X__builtin___memmove_chk(t *TLS, dest, src uintptr, n, os Tsize_t) uintptr {
if os != ^Tsize_t(0) && os < n {
Xabort(t)
}
return Xmemmove(t, dest, src, n)
}
func X__builtin_isunordered(t *TLS, a, b float64) int32 {
return Bool32(math.IsNaN(a) || math.IsNaN(b))
}
func X__builtin_ffs(tls *TLS, i int32) (r int32) {
return Xffs(tls, i)
}
func X__builtin_rintf(tls *TLS, x float32) (r float32) {
return Xrintf(tls, x)
}
func X__builtin_lrintf(tls *TLS, x float32) (r long) {
return Xlrintf(tls, x)
}
func X__builtin_lrint(tls *TLS, x float64) (r long) {
return Xlrint(tls, x)
}
// double __builtin_fma(double x, double y, double z);
func X__builtin_fma(tls *TLS, x, y, z float64) (r float64) {
return math.FMA(x, y, z)
}
func X__builtin_alloca(tls *TLS, size Tsize_t) uintptr {
return Xalloca(tls, size)
}
func X__builtin_isprint(tls *TLS, c int32) (r int32) {
return Xisprint(tls, c)
}
func X__builtin_isblank(tls *TLS, c int32) (r int32) {
return Xisblank(tls, c)
}
func X__builtin_trunc(tls *TLS, x float64) (r float64) {
return Xtrunc(tls, x)
}
func X__builtin_hypot(tls *TLS, x float64, y float64) (r float64) {
return Xhypot(tls, x, y)
}
func X__builtin_fmax(tls *TLS, x float64, y float64) (r float64) {
return Xfmax(tls, x, y)
}
func X__builtin_fmin(tls *TLS, x float64, y float64) (r float64) {
return Xfmin(tls, x, y)
}

2
vendor/modernc.org/libc/ccgo.go generated vendored
View file

@ -1,5 +1,7 @@
// Code generated by 'go generate' - DO NOT EDIT. // Code generated by 'go generate' - DO NOT EDIT.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

154744
vendor/modernc.org/libc/ccgo_linux_amd64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

154052
vendor/modernc.org/libc/ccgo_linux_loong64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

19
vendor/modernc.org/libc/etc.go generated vendored
View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (
@ -170,6 +172,10 @@ func removeObject(t uintptr) {
} }
func (t *TLS) setErrno(err interface{}) { func (t *TLS) setErrno(err interface{}) {
if t == nil {
panic("nil TLS")
}
if memgrind { if memgrind {
if atomic.SwapInt32(&t.reentryGuard, 1) != 0 { if atomic.SwapInt32(&t.reentryGuard, 1) != 0 {
panic(todo("concurrent use of TLS instance %p", t)) panic(todo("concurrent use of TLS instance %p", t))
@ -566,6 +572,19 @@ func VaUintptr(app *uintptr) uintptr {
return v return v
} }
func getVaList(va uintptr) []string {
r := []string{}
for p := va; ; p += 8 {
st := *(*uintptr)(unsafe.Pointer(p))
if st == 0 {
return r
}
r = append(r, GoString(st))
}
return r
}
func roundup(n, to uintptr) uintptr { func roundup(n, to uintptr) uintptr {
if r := n % to; r != 0 { if r := n % to; r != 0 {
return n + to - r return n + to - r

69
vendor/modernc.org/libc/etc_musl.go generated vendored Normal file
View file

@ -0,0 +1,69 @@
// Copyright 2023 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && (amd64 || loong64)
package libc // import "modernc.org/libc"
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
)
// origin returns caller's short position, skipping skip frames.
func origin(skip int) string {
pc, fn, fl, _ := runtime.Caller(skip)
f := runtime.FuncForPC(pc)
var fns string
if f != nil {
fns = f.Name()
if x := strings.LastIndex(fns, "."); x > 0 {
fns = fns[x+1:]
}
if strings.HasPrefix(fns, "func") {
num := true
for _, c := range fns[len("func"):] {
if c < '0' || c > '9' {
num = false
break
}
}
if num {
return origin(skip + 2)
}
}
}
return fmt.Sprintf("%s:%d:%s", filepath.Base(fn), fl, fns)
}
// todo prints and return caller's position and an optional message tagged with TODO. Output goes to stderr.
func todo(s string, args ...interface{}) string {
switch {
case s == "":
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
default:
s = fmt.Sprintf(s, args...)
}
r := fmt.Sprintf("%s\n\tTODO %s", origin(2), s)
// fmt.Fprintf(os.Stderr, "%s\n", r)
// os.Stdout.Sync()
return r
}
// trc prints and return caller's position and an optional message tagged with TRC. Output goes to stderr.
func trc(s string, args ...interface{}) string {
switch {
case s == "":
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
default:
s = fmt.Sprintf(s, args...)
}
r := fmt.Sprintf("%s: TRC %s", origin(2), s)
fmt.Fprintf(os.Stderr, "%s\n", r)
os.Stderr.Sync()
return r
}

12
vendor/modernc.org/libc/int128.go generated vendored
View file

@ -49,7 +49,7 @@ func Int128FromFloat32(n float32) Int128 { return Int128(mathutil.NewInt128FromF
func Int128FromFloat64(n float64) Int128 { return Int128(mathutil.NewInt128FromFloat64(n)) } func Int128FromFloat64(n float64) Int128 { return Int128(mathutil.NewInt128FromFloat64(n)) }
func Int128FromInt16(n int16) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) } func Int128FromInt16(n int16) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
func Int128FromInt32(n int32) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) } func Int128FromInt32(n int32) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
func Int128FromInt64(n int64) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) } func Int128FromInt64(n int64) Int128 { return Int128(mathutil.NewInt128FromInt64(n)) }
func Int128FromInt8(n int8) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) } func Int128FromInt8(n int8) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
func Int128FromUint16(n uint16) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) } func Int128FromUint16(n uint16) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
func Int128FromUint32(n uint32) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) } func Int128FromUint32(n uint32) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
@ -65,7 +65,7 @@ func (n Int128) And(v Int128) Int128 { return Int128{n.Lo & v.Lo, n.Hi & v.Hi}
func (n Int128) Cmp(y Int128) int { return mathutil.Int128(n).Cmp(mathutil.Int128(y)) } func (n Int128) Cmp(y Int128) int { return mathutil.Int128(n).Cmp(mathutil.Int128(y)) }
func (n Int128) Int16() int16 { return int16(n.Lo) } func (n Int128) Int16() int16 { return int16(n.Lo) }
func (n Int128) Int32() int32 { return int32(n.Lo) } func (n Int128) Int32() int32 { return int32(n.Lo) }
func (n Int128) Int64() int64 { return int64(n.Lo) } func (n Int128) Int64() int64 { return n.Lo }
func (n Int128) Int8() int8 { return int8(n.Lo) } func (n Int128) Int8() int8 { return int8(n.Lo) }
func (n Int128) Or(v Int128) Int128 { return Int128{n.Lo | v.Lo, n.Hi | v.Hi} } func (n Int128) Or(v Int128) Int128 { return Int128{n.Lo | v.Lo, n.Hi | v.Hi} }
func (n Int128) Uint128() (r Uint128) { return Uint128{uint64(n.Lo), uint64(n.Hi)} } func (n Int128) Uint128() (r Uint128) { return Uint128{uint64(n.Lo), uint64(n.Hi)} }
@ -316,16 +316,16 @@ func (n Uint128) add64(m uint64) Uint128 {
func (n Uint128) Float32() float32 { func (n Uint128) Float32() float32 {
if n.Hi == 0 { if n.Hi == 0 {
return float32(uint64(n.Lo)) return float32(n.Lo)
} }
return float32(n.Hi)*(1<<64) + float32(uint64(n.Lo)) return float32(n.Hi)*(1<<64) + float32(n.Lo)
} }
func (n Uint128) Float64() float64 { func (n Uint128) Float64() float64 {
if n.Hi == 0 { if n.Hi == 0 {
return float64(uint64(n.Lo)) return float64(n.Lo)
} }
return float64(n.Hi)*(1<<64) + float64(uint64(n.Lo)) return float64(n.Hi)*(1<<64) + float64(n.Lo)
} }

View file

@ -6,6 +6,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

3
vendor/modernc.org/libc/libc.go generated vendored
View file

@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
//go.generate echo package libc > ccgo.go //go.generate echo package libc > ccgo.go
//go:generate go run generate.go
//go:generate go fmt ./... //go:generate go fmt ./...
// Package libc provides run time support for ccgo generated programs and // Package libc provides run time support for ccgo generated programs and

3
vendor/modernc.org/libc/libc64.go generated vendored
View file

@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build amd64 || arm64 || ppc64le || riscv64 || s390x || loong64 || mips64le //go:build ((amd64 || loong64) && !linux) || arm64 || ppc64le || riscv64 || s390x || mips64le
// +build amd64 arm64 ppc64le riscv64 s390x loong64 mips64le
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && amd64)
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && amd64)
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

View file

@ -1,779 +0,0 @@
// Copyright 2020 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package libc // import "modernc.org/libc"
import (
"os"
"strings"
"syscall"
gotime "time"
"unicode"
"unsafe"
"golang.org/x/sys/unix"
"modernc.org/libc/errno"
"modernc.org/libc/fcntl"
"modernc.org/libc/signal"
"modernc.org/libc/stdio"
"modernc.org/libc/sys/types"
"modernc.org/libc/time"
"modernc.org/libc/wctype"
)
var (
startTime = gotime.Now() // For clock(3)
)
// int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
func Xsigaction(t *TLS, signum int32, act, oldact uintptr) int32 {
if __ccgo_strace {
trc("t=%v signum=%v oldact=%v, (%v:)", t, signum, oldact, origin(2))
}
// musl/arch/x86_64/ksigaction.h
//
// struct k_sigaction {
// void (*handler)(int);
// unsigned long flags;
// void (*restorer)(void);
// unsigned mask[2];
// };
type k_sigaction struct {
handler uintptr
flags ulong
restorer uintptr
mask [2]uint32
}
var kact, koldact uintptr
if act != 0 {
sz := int(unsafe.Sizeof(k_sigaction{}))
kact = t.Alloc(sz)
defer t.Free(sz)
*(*k_sigaction)(unsafe.Pointer(kact)) = k_sigaction{
handler: (*signal.Sigaction)(unsafe.Pointer(act)).F__sigaction_handler.Fsa_handler,
flags: ulong((*signal.Sigaction)(unsafe.Pointer(act)).Fsa_flags),
restorer: (*signal.Sigaction)(unsafe.Pointer(act)).Fsa_restorer,
}
Xmemcpy(t, kact+unsafe.Offsetof(k_sigaction{}.mask), act+unsafe.Offsetof(signal.Sigaction{}.Fsa_mask), types.Size_t(unsafe.Sizeof(k_sigaction{}.mask)))
}
if oldact != 0 {
panic(todo(""))
}
if _, _, err := unix.Syscall6(unix.SYS_RT_SIGACTION, uintptr(signum), kact, koldact, unsafe.Sizeof(k_sigaction{}.mask), 0, 0); err != 0 {
t.setErrno(err)
return -1
}
if oldact != 0 {
panic(todo(""))
}
return 0
}
// int fcntl(int fd, int cmd, ... /* arg */ );
func Xfcntl64(t *TLS, fd, cmd int32, args uintptr) int32 {
if __ccgo_strace {
trc("t=%v cmd=%v args=%v, (%v:)", t, cmd, args, origin(2))
}
var arg uintptr
if args != 0 {
arg = *(*uintptr)(unsafe.Pointer(args))
}
if cmd == fcntl.F_SETFL {
arg |= unix.O_LARGEFILE
}
n, _, err := unix.Syscall(unix.SYS_FCNTL, uintptr(fd), uintptr(cmd), arg)
if err != 0 {
// if dmesgs {
// dmesg("%v: fd %v cmd %v", origin(1), fcntlCmdStr(fd), cmd)
// }
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: %d %s %#x: %d", origin(1), fd, fcntlCmdStr(cmd), arg, n)
// }
return int32(n)
}
// int lstat(const char *pathname, struct stat *statbuf);
func Xlstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := syscall.Lstat(GoString(pathname), (*syscall.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
// if dmesgs {
// dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
// }
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: %q: ok", origin(1), GoString(pathname))
// }
return 0
}
// int stat(const char *pathname, struct stat *statbuf);
func Xstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := syscall.Stat(GoString(pathname), (*syscall.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
// if dmesgs {
// dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
// }
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: %q: ok", origin(1), GoString(pathname))
// }
return 0
}
// int fstat(int fd, struct stat *statbuf);
func Xfstat64(t *TLS, fd int32, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v fd=%v statbuf=%v, (%v:)", t, fd, statbuf, origin(2))
}
if err := syscall.Fstat(int(fd), (*syscall.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
// if dmesgs {
// dmesg("%v: fd %d: %v", origin(1), fd, err)
// }
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: %d size %#x: ok\n%+v", origin(1), fd, (*stat.Stat)(unsafe.Pointer(statbuf)).Fst_size, (*stat.Stat)(unsafe.Pointer(statbuf)))
// }
return 0
}
func Xmmap(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
if __ccgo_strace {
trc("t=%v addr=%v length=%v fd=%v offset=%v, (%v:)", t, addr, length, fd, offset, origin(2))
}
return Xmmap64(t, addr, length, prot, flags, fd, offset)
}
// void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
func Xmmap64(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
if __ccgo_strace {
trc("t=%v addr=%v length=%v fd=%v offset=%v, (%v:)", t, addr, length, fd, offset, origin(2))
}
data, _, err := unix.Syscall6(unix.SYS_MMAP, addr, uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
if err != 0 {
// if dmesgs {
// dmesg("%v: %v", origin(1), err)
// }
t.setErrno(err)
return ^uintptr(0) // (void*)-1
}
// if dmesgs {
// dmesg("%v: %#x", origin(1), data)
// }
return data
}
// void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, ... /* void *new_address */);
func Xmremap(t *TLS, old_address uintptr, old_size, new_size types.Size_t, flags int32, args uintptr) uintptr {
if __ccgo_strace {
trc("t=%v old_address=%v new_size=%v flags=%v args=%v, (%v:)", t, old_address, new_size, flags, args, origin(2))
}
var arg uintptr
if args != 0 {
arg = *(*uintptr)(unsafe.Pointer(args))
}
data, _, err := unix.Syscall6(unix.SYS_MREMAP, old_address, uintptr(old_size), uintptr(new_size), uintptr(flags), arg, 0)
if err != 0 {
// if dmesgs {
// dmesg("%v: %v", origin(1), err)
// }
t.setErrno(err)
return ^uintptr(0) // (void*)-1
}
// if dmesgs {
// dmesg("%v: %#x", origin(1), data)
// }
return data
}
// int ftruncate(int fd, off_t length);
func Xftruncate64(t *TLS, fd int32, length types.Off_t) int32 {
if __ccgo_strace {
trc("t=%v fd=%v length=%v, (%v:)", t, fd, length, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0); err != 0 {
// if dmesgs {
// dmesg("%v: fd %d: %v", origin(1), fd, err)
// }
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: %d %#x: ok", origin(1), fd, length)
// }
return 0
}
// off64_t lseek64(int fd, off64_t offset, int whence);
func Xlseek64(t *TLS, fd int32, offset types.Off_t, whence int32) types.Off_t {
if __ccgo_strace {
trc("t=%v fd=%v offset=%v whence=%v, (%v:)", t, fd, offset, whence, origin(2))
}
n, _, err := unix.Syscall(unix.SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
if err != 0 {
// if dmesgs {
// dmesg("%v: fd %v, off %#x, whence %v: %v", origin(1), fd, offset, whenceStr(whence), err)
// }
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: fd %v, off %#x, whence %v: %#x", origin(1), fd, offset, whenceStr(whence), n)
// }
return types.Off_t(n)
}
// int utime(const char *filename, const struct utimbuf *times);
func Xutime(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_UTIME, filename, times, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// unsigned int alarm(unsigned int seconds);
func Xalarm(t *TLS, seconds uint32) uint32 {
if __ccgo_strace {
trc("t=%v seconds=%v, (%v:)", t, seconds, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_ALARM, uintptr(seconds), 0, 0)
// if err != 0 {
// panic(todo(""))
// }
// return uint32(n)
}
// time_t time(time_t *tloc);
func Xtime(t *TLS, tloc uintptr) types.Time_t {
if __ccgo_strace {
trc("t=%v tloc=%v, (%v:)", t, tloc, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_TIME, tloc, 0, 0)
// if err != 0 {
// t.setErrno(err)
// return types.Time_t(-1)
// }
// if tloc != 0 {
// *(*types.Time_t)(unsafe.Pointer(tloc)) = types.Time_t(n)
// }
// return types.Time_t(n)
}
// int getrlimit(int resource, struct rlimit *rlim);
func Xgetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
if __ccgo_strace {
trc("t=%v resource=%v rlim=%v, (%v:)", t, resource, rlim, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_GETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int mkdir(const char *path, mode_t mode);
func Xmkdir(t *TLS, path uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v path=%v mode=%v, (%v:)", t, path, mode, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_MKDIR, path, uintptr(mode), 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// // if dmesgs {
// // dmesg("%v: %q: ok", origin(1), GoString(path))
// // }
// return 0
}
// int symlink(const char *target, const char *linkpath);
func Xsymlink(t *TLS, target, linkpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v linkpath=%v, (%v:)", t, linkpath, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_SYMLINK, target, linkpath, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// // if dmesgs {
// // dmesg("%v: %q %q: ok", origin(1), GoString(target), GoString(linkpath))
// // }
// return 0
}
// int chmod(const char *pathname, mode_t mode)
func Xchmod(t *TLS, pathname uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_CHMOD, pathname, uintptr(mode), 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// // if dmesgs {
// // dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
// // }
// return 0
}
// int utimes(const char *filename, const struct timeval times[2]);
func Xutimes(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_UTIMES, filename, times, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// // if dmesgs {
// // dmesg("%v: %q: ok", origin(1), GoString(filename))
// // }
// return 0
}
// int unlink(const char *pathname);
func Xunlink(t *TLS, pathname uintptr) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v, (%v:)", t, pathname, origin(2))
}
if err := syscall.Unlink(GoString(pathname)); err != nil {
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: %q: ok", origin(1), GoString(pathname))
// }
return 0
}
// int access(const char *pathname, int mode);
func Xaccess(t *TLS, pathname uintptr, mode int32) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
if err := syscall.Access(GoString(pathname), uint32(mode)); err != nil {
t.setErrno(err)
return -1
}
// if dmesgs {
// dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
// }
return 0
}
// int rmdir(const char *pathname);
func Xrmdir(t *TLS, pathname uintptr) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v, (%v:)", t, pathname, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_RMDIR, pathname, 0, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// // if dmesgs {
// // dmesg("%v: %q: ok", origin(1), GoString(pathname))
// // }
// return 0
}
// int rename(const char *oldpath, const char *newpath);
func Xrename(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_RENAME, oldpath, newpath, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int mknod(const char *pathname, mode_t mode, dev_t dev);
func Xmknod(t *TLS, pathname uintptr, mode types.Mode_t, dev types.Dev_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v dev=%v, (%v:)", t, pathname, mode, dev, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_MKNOD, pathname, uintptr(mode), uintptr(dev)); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int chown(const char *pathname, uid_t owner, gid_t group);
func Xchown(t *TLS, pathname uintptr, owner types.Uid_t, group types.Gid_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v owner=%v group=%v, (%v:)", t, pathname, owner, group, origin(2))
}
panic(todo(""))
// // if _, _, err := unix.Syscall(unix.SYS_CHOWN, pathname, uintptr(owner), uintptr(group)); err != 0 {
// // t.setErrno(err)
// // return -1
// // }
// // return 0
}
// int link(const char *oldpath, const char *newpath);
func Xlink(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_LINK, oldpath, newpath, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int pipe(int pipefd[2]);
func Xpipe(t *TLS, pipefd uintptr) int32 {
if __ccgo_strace {
trc("t=%v pipefd=%v, (%v:)", t, pipefd, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_PIPE, pipefd, 0, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int dup2(int oldfd, int newfd);
func Xdup2(t *TLS, oldfd, newfd int32) int32 {
if __ccgo_strace {
trc("t=%v newfd=%v, (%v:)", t, newfd, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
// if err != 0 {
// t.setErrno(err)
// return -1
// }
// return int32(n)
}
// ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize);
func Xreadlink(t *TLS, path, buf uintptr, bufsize types.Size_t) types.Ssize_t {
if __ccgo_strace {
trc("t=%v buf=%v bufsize=%v, (%v:)", t, buf, bufsize, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_READLINK, path, buf, uintptr(bufsize))
// if err != 0 {
// t.setErrno(err)
// return -1
// }
// return types.Ssize_t(n)
}
// FILE *fopen64(const char *pathname, const char *mode);
func Xfopen64(t *TLS, pathname, mode uintptr) uintptr {
if __ccgo_strace {
trc("t=%v mode=%v, (%v:)", t, mode, origin(2))
}
m := strings.ReplaceAll(GoString(mode), "b", "")
var flags int
switch m {
case "r":
flags = os.O_RDONLY
case "r+":
flags = os.O_RDWR
case "w":
flags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC
case "w+":
flags = os.O_RDWR | os.O_CREATE | os.O_TRUNC
case "a":
flags = os.O_WRONLY | os.O_CREATE | os.O_APPEND
case "a+":
flags = os.O_RDWR | os.O_CREATE | os.O_APPEND
default:
panic(m)
}
fd, err := unix.Open(GoString(pathname), flags|unix.O_LARGEFILE, 0666)
if err != nil {
t.setErrno(err)
return 0
}
if p := newFile(t, int32(fd)); p != 0 {
return p
}
Xclose(t, int32(fd))
t.setErrno(errno.ENOMEM)
return 0
}
// int iswspace(wint_t wc);
func Xiswspace(t *TLS, wc wctype.Wint_t) int32 {
if __ccgo_strace {
trc("t=%v wc=%v, (%v:)", t, wc, origin(2))
}
return Bool32(unicode.IsSpace(rune(wc)))
}
// int iswalnum(wint_t wc);
func Xiswalnum(t *TLS, wc wctype.Wint_t) int32 {
if __ccgo_strace {
trc("t=%v wc=%v, (%v:)", t, wc, origin(2))
}
return Bool32(unicode.IsLetter(rune(wc)) || unicode.IsNumber(rune(wc)))
}
// int setrlimit(int resource, const struct rlimit *rlim);
func Xsetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
if __ccgo_strace {
trc("t=%v resource=%v rlim=%v, (%v:)", t, resource, rlim, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_SETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
func AtomicLoadPInt8(addr uintptr) (val int8) {
return int8(a_load_8(addr))
}
func AtomicLoadPInt16(addr uintptr) (val int16) {
return int16(a_load_16(addr))
}
func AtomicLoadPUint8(addr uintptr) byte {
return byte(a_load_8(addr))
}
func AtomicLoadPUint16(addr uintptr) uint16 {
return uint16(a_load_16(addr))
}
func AtomicLoadNUint8(ptr uintptr, memorder int32) uint8 {
return byte(a_load_8(ptr))
}
var _table1 = [384]int32{
129: int32(1),
130: int32(2),
131: int32(3),
132: int32(4),
133: int32(5),
134: int32(6),
135: int32(7),
136: int32(8),
137: int32(9),
138: int32(10),
139: int32(11),
140: int32(12),
141: int32(13),
142: int32(14),
143: int32(15),
144: int32(16),
145: int32(17),
146: int32(18),
147: int32(19),
148: int32(20),
149: int32(21),
150: int32(22),
151: int32(23),
152: int32(24),
153: int32(25),
154: int32(26),
155: int32(27),
156: int32(28),
157: int32(29),
158: int32(30),
159: int32(31),
160: int32(32),
161: int32(33),
162: int32(34),
163: int32(35),
164: int32(36),
165: int32(37),
166: int32(38),
167: int32(39),
168: int32(40),
169: int32(41),
170: int32(42),
171: int32(43),
172: int32(44),
173: int32(45),
174: int32(46),
175: int32(47),
176: int32(48),
177: int32(49),
178: int32(50),
179: int32(51),
180: int32(52),
181: int32(53),
182: int32(54),
183: int32(55),
184: int32(56),
185: int32(57),
186: int32(58),
187: int32(59),
188: int32(60),
189: int32(61),
190: int32(62),
191: int32(63),
192: int32(64),
193: int32('a'),
194: int32('b'),
195: int32('c'),
196: int32('d'),
197: int32('e'),
198: int32('f'),
199: int32('g'),
200: int32('h'),
201: int32('i'),
202: int32('j'),
203: int32('k'),
204: int32('l'),
205: int32('m'),
206: int32('n'),
207: int32('o'),
208: int32('p'),
209: int32('q'),
210: int32('r'),
211: int32('s'),
212: int32('t'),
213: int32('u'),
214: int32('v'),
215: int32('w'),
216: int32('x'),
217: int32('y'),
218: int32('z'),
219: int32(91),
220: int32(92),
221: int32(93),
222: int32(94),
223: int32(95),
224: int32(96),
225: int32('a'),
226: int32('b'),
227: int32('c'),
228: int32('d'),
229: int32('e'),
230: int32('f'),
231: int32('g'),
232: int32('h'),
233: int32('i'),
234: int32('j'),
235: int32('k'),
236: int32('l'),
237: int32('m'),
238: int32('n'),
239: int32('o'),
240: int32('p'),
241: int32('q'),
242: int32('r'),
243: int32('s'),
244: int32('t'),
245: int32('u'),
246: int32('v'),
247: int32('w'),
248: int32('x'),
249: int32('y'),
250: int32('z'),
251: int32(123),
252: int32(124),
253: int32(125),
254: int32(126),
255: int32(127),
}
var _ptable1 = uintptr(unsafe.Pointer(&_table1)) + uintptr(128)*4
func X__ctype_tolower_loc(tls *TLS) (r uintptr) {
if __ccgo_strace {
trc("tls=%v, (%v:)", tls, origin(2))
defer func() { trc("-> %v", r) }()
}
return uintptr(unsafe.Pointer(&_ptable1))
}
type Tin6_addr = struct {
F__in6_union struct {
F__s6_addr16 [0][8]uint16
F__s6_addr32 [0][4]uint32
F__s6_addr [16]uint8
}
}
var Xin6addr_any = Tin6_addr{}
func Xrewinddir(tls *TLS, f uintptr) {
if __ccgo_strace {
trc("tls=%v f=%v, (%v:)", tls, f, origin(2))
}
Xfseek(tls, f, 0, stdio.SEEK_SET)
}
// clock_t clock(void);
func Xclock(t *TLS) time.Clock_t {
if __ccgo_strace {
trc("t=%v, (%v:)", t, origin(2))
}
return time.Clock_t(gotime.Since(startTime) * gotime.Duration(time.CLOCKS_PER_SEC) / gotime.Second)
}

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && loong64)
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

1033
vendor/modernc.org/libc/libc_musl.go generated vendored Normal file

File diff suppressed because it is too large Load diff

31
vendor/modernc.org/libc/libc_musl_linux_amd64.go generated vendored Normal file
View file

@ -0,0 +1,31 @@
// Copyright 2023 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && amd64
package libc // import "modernc.org/libc
import (
"golang.org/x/sys/unix"
)
type long = int64
type ulong = uint64
// RawMem represents the biggest byte array the runtime can handle
type RawMem [1<<50 - 1]byte
// int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags);
func Xrenameat2(t *TLS, olddirfd int32, oldpath uintptr, newdirfd int32, newpath uintptr, flags int32) int32 {
if __ccgo_strace {
trc("t=%v olddirfd=%v oldpath=%v newdirfd=%v newpath=%v flags=%v, (%v:)", t, olddirfd, oldpath, newdirfd, newpath, flags, origin(2))
}
if _, _, err := unix.Syscall6(unix.SYS_RENAMEAT2, uintptr(olddirfd), oldpath, uintptr(newdirfd), newpath, uintptr(flags), 0); err != 0 {
t.setErrno(int32(err))
return -1
}
return 0
}

29
vendor/modernc.org/libc/libc_musl_linux_loong64.go generated vendored Normal file
View file

@ -0,0 +1,29 @@
// Copyright 2023 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package libc // import "modernc.org/libc
import (
"golang.org/x/sys/unix"
)
type long = int64
type ulong = uint64
// RawMem represents the biggest byte array the runtime can handle
type RawMem [1<<50 - 1]byte
// int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags);
func Xrenameat2(t *TLS, olddirfd int32, oldpath uintptr, newdirfd int32, newpath uintptr, flags int32) int32 {
if __ccgo_strace {
trc("t=%v olddirfd=%v oldpath=%v newdirfd=%v newpath=%v flags=%v, (%v:)", t, olddirfd, oldpath, newdirfd, newpath, flags, origin(2))
}
if _, _, err := unix.Syscall6(unix.SYS_RENAMEAT2, uintptr(olddirfd), oldpath, uintptr(newdirfd), newpath, uintptr(flags), 0); err != 0 {
t.setErrno(int32(err))
return -1
}
return 0
}

1000
vendor/modernc.org/libc/libc_openbsd.go generated vendored

File diff suppressed because it is too large Load diff

View file

@ -4,706 +4,7 @@
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import (
"strings"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
"modernc.org/libc/fcntl"
"modernc.org/libc/fts"
"modernc.org/libc/sys/types"
"modernc.org/libc/time"
"modernc.org/libc/utime"
)
type ( type (
long = int32 long = int32
ulong = uint32 ulong = uint32
) )
// int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
func Xsigaction(t *TLS, signum int32, act, oldact uintptr) int32 {
if __ccgo_strace {
trc("t=%v signum=%v oldact=%v, (%v:)", t, signum, oldact, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_SIGACTION, uintptr(signum), act, oldact); err != 0 {
t.setErrno(err)
return -1
}
return 0
}
// FILE *fopen64(const char *pathname, const char *mode);
func Xfopen64(t *TLS, pathname, mode uintptr) uintptr {
if __ccgo_strace {
trc("t=%v mode=%v, (%v:)", t, mode, origin(2))
}
m := strings.ReplaceAll(GoString(mode), "b", "")
var flags int
switch m {
case "r":
flags = fcntl.O_RDONLY
case "r+":
flags = fcntl.O_RDWR
case "w":
flags = fcntl.O_WRONLY | fcntl.O_CREAT | fcntl.O_TRUNC
case "w+":
flags = fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_TRUNC
case "a":
flags = fcntl.O_WRONLY | fcntl.O_CREAT | fcntl.O_APPEND
case "a+":
flags = fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_APPEND
default:
panic(m)
}
fd, err := unix.Open(GoString(pathname), int(flags), 0666)
if err != nil {
if dmesgs {
dmesg("%v: %q %q: %v FAIL", origin(1), GoString(pathname), GoString(mode), err)
}
t.setErrno(err)
return 0
}
if dmesgs {
dmesg("%v: %q %q: fd %v", origin(1), GoString(pathname), GoString(mode), fd)
}
if p := newFile(t, int32(fd)); p != 0 {
return p
}
panic("OOM")
}
// int lstat(const char *pathname, struct stat *statbuf);
func Xlstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := unix.Lstat(GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(pathname))
}
return 0
}
// int stat(const char *pathname, struct stat *statbuf);
func Xstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := unix.Stat(GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(pathname))
}
return 0
}
// int mkdir(const char *path, mode_t mode);
func Xmkdir(t *TLS, path uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v path=%v mode=%v, (%v:)", t, path, mode, origin(2))
}
if err := unix.Mkdir(GoString(path), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(path), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(path))
}
return 0
}
// int access(const char *pathname, int mode);
func Xaccess(t *TLS, pathname uintptr, mode int32) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
if err := unix.Access(GoString(pathname), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q %#o: %v FAIL", origin(1), GoString(pathname), mode, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
}
return 0
}
// int unlink(const char *pathname);
func Xunlink(t *TLS, pathname uintptr) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v, (%v:)", t, pathname, origin(2))
}
if err := unix.Unlink(GoString(pathname)); err != nil {
if dmesgs {
dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize);
func Xreadlink(t *TLS, path, buf uintptr, bufsize types.Size_t) types.Ssize_t {
if __ccgo_strace {
trc("t=%v buf=%v bufsize=%v, (%v:)", t, buf, bufsize, origin(2))
}
var n int
var err error
switch {
case buf == 0 || bufsize == 0:
n, err = unix.Readlink(GoString(path), nil)
default:
n, err = unix.Readlink(GoString(path), (*RawMem)(unsafe.Pointer(buf))[:bufsize:bufsize])
}
if err != nil {
if dmesgs {
dmesg("%v: %v FAIL", err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok")
}
return types.Ssize_t(n)
}
// int symlink(const char *target, const char *linkpath);
func Xsymlink(t *TLS, target, linkpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v linkpath=%v, (%v:)", t, linkpath, origin(2))
}
if err := unix.Symlink(GoString(target), GoString(linkpath)); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int chmod(const char *pathname, mode_t mode)
func Xchmod(t *TLS, pathname uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
if err := unix.Chmod(GoString(pathname), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q %#o: %v FAIL", origin(1), GoString(pathname), mode, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
}
return 0
}
// time_t time(time_t *tloc);
func Xtime(t *TLS, tloc uintptr) time.Time_t {
if __ccgo_strace {
trc("t=%v tloc=%v, (%v:)", t, tloc, origin(2))
}
panic(todo(""))
// n := time.Now().UTC().Unix()
// if tloc != 0 {
// *(*types.Time_t)(unsafe.Pointer(tloc)) = types.Time_t(n)
// }
// return types.Time_t(n)
}
// int utimes(const char *filename, const struct timeval times[2]);
func Xutimes(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
var a []unix.Timeval
if times != 0 {
a = make([]unix.Timeval, 2)
a[0] = *(*unix.Timeval)(unsafe.Pointer(times))
a[1] = *(*unix.Timeval)(unsafe.Pointer(times + unsafe.Sizeof(unix.Timeval{})))
}
if err := unix.Utimes(GoString(filename), a); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int fstat(int fd, struct stat *statbuf);
func Xfstat64(t *TLS, fd int32, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v fd=%v statbuf=%v, (%v:)", t, fd, statbuf, origin(2))
}
if err := unix.Fstat(int(fd), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: fd %d: %v FAIL", origin(1), fd, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: fd %d: ok", origin(1), fd)
}
return 0
}
// off64_t lseek64(int fd, off64_t offset, int whence);
func Xlseek64(t *TLS, fd int32, offset types.Off_t, whence int32) types.Off_t {
if __ccgo_strace {
trc("t=%v fd=%v offset=%v whence=%v, (%v:)", t, fd, offset, whence, origin(2))
}
n, err := unix.Seek(int(fd), int64(offset), int(whence))
if err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return types.Off_t(n)
}
func Xfcntl64(t *TLS, fd, cmd int32, args uintptr) int32 {
if __ccgo_strace {
trc("t=%v cmd=%v args=%v, (%v:)", t, cmd, args, origin(2))
}
var arg uintptr
if args != 0 {
arg = *(*uintptr)(unsafe.Pointer(args))
}
n, _, err := unix.Syscall(unix.SYS_FCNTL, uintptr(fd), uintptr(cmd), arg)
if err != 0 {
if dmesgs {
dmesg("%v: fd %v cmd %v", origin(1), fcntlCmdStr(fd), cmd)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %d %s %#x: %d", origin(1), fd, fcntlCmdStr(cmd), arg, n)
}
return int32(n)
}
// int rename(const char *oldpath, const char *newpath);
func Xrename(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
if err := unix.Rename(GoString(oldpath), GoString(newpath)); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int mknod(const char *pathname, mode_t mode, dev_t dev);
func Xmknod(t *TLS, pathname uintptr, mode types.Mode_t, dev types.Dev_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v dev=%v, (%v:)", t, pathname, mode, dev, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_MKNOD, pathname, uintptr(mode), uintptr(dev)); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int utime(const char *filename, const struct utimbuf *times);
func Xutime(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
var a []unix.Timeval
if times != 0 {
a = make([]unix.Timeval, 2)
a[0].Sec = int64((*utime.Utimbuf)(unsafe.Pointer(times)).Factime)
a[1].Sec = int64((*utime.Utimbuf)(unsafe.Pointer(times)).Fmodtime)
}
if err := unix.Utimes(GoString(filename), a); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int chown(const char *pathname, uid_t owner, gid_t group);
func Xchown(t *TLS, pathname uintptr, owner types.Uid_t, group types.Gid_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v owner=%v group=%v, (%v:)", t, pathname, owner, group, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_CHOWN, pathname, uintptr(owner), uintptr(group)); err != 0 {
t.setErrno(err)
return -1
}
return 0
}
// int link(const char *oldpath, const char *newpath);
func Xlink(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_LINK, oldpath, newpath, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int dup2(int oldfd, int newfd);
func Xdup2(t *TLS, oldfd, newfd int32) int32 {
if __ccgo_strace {
trc("t=%v newfd=%v, (%v:)", t, newfd, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
// if err != 0 {
// t.setErrno(err)
// return -1
// }
// return int32(n)
}
// unsigned int alarm(unsigned int seconds);
func Xalarm(t *TLS, seconds uint32) uint32 {
if __ccgo_strace {
trc("t=%v seconds=%v, (%v:)", t, seconds, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_ALARM, uintptr(seconds), 0, 0)
// if err != 0 {
// panic(todo(""))
// }
// return uint32(n)
}
func Xgetnameinfo(tls *TLS, sa1 uintptr, sl socklen_t, node uintptr, nodelen size_t, serv uintptr, servlen size_t, flags int32) int32 { /* getnameinfo.c:125:5: */
if __ccgo_strace {
trc("tls=%v sa1=%v sl=%v node=%v nodelen=%v serv=%v servlen=%v flags=%v, (%v:)", tls, sa1, sl, node, nodelen, serv, servlen, flags, origin(2))
}
panic(todo(""))
//TODO bp := tls.Alloc(347)
//TODO defer tls.Free(347)
//TODO // var ptr [78]int8 at bp, 78
//TODO // var buf [256]int8 at bp+78, 256
//TODO // var num [13]int8 at bp+334, 13
//TODO var af int32 = int32((*sockaddr)(unsafe.Pointer(sa1)).sa_family)
//TODO var a uintptr
//TODO var scopeid uint32
//TODO switch af {
//TODO case 2:
//TODO a = (sa1 + 4 /* &.sin_addr */)
//TODO if (uint64(sl) < uint64(unsafe.Sizeof(sockaddr_in{}))) {
//TODO return -6
//TODO }
//TODO mkptr4(tls, bp /* &ptr[0] */, a)
//TODO scopeid = uint32(0)
//TODO break
//TODO case 10:
//TODO a = (sa1 + 8 /* &.sin6_addr */)
//TODO if (uint64(sl) < uint64(unsafe.Sizeof(sockaddr_in6{}))) {
//TODO return -6
//TODO }
//TODO if Xmemcmp(tls, a, ts+88 /* "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" */, uint64(12)) != 0 {
//TODO mkptr6(tls, bp /* &ptr[0] */, a)
//TODO } else {
//TODO mkptr4(tls, bp /* &ptr[0] */, (a + uintptr(12)))
//TODO }
//TODO scopeid = (*sockaddr_in6)(unsafe.Pointer(sa1)).sin6_scope_id
//TODO break
//TODO default:
//TODO return -6
//TODO }
//TODO if (node != 0) && (nodelen != 0) {
//TODO *(*int8)(unsafe.Pointer(bp + 78 /* &buf[0] */)) = int8(0)
//TODO if !((flags & 0x01) != 0) {
//TODO reverse_hosts(tls, bp+78 /* &buf[0] */, a, scopeid, af)
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(bp + 78 /* buf */))) != 0) && !((flags & 0x01) != 0) {
//TODO Xabort(tls) //TODO-
//TODO // unsigned char query[18+PTR_MAX], reply[512];
//TODO // int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
//TODO // 0, 0, 0, query, sizeof query);
//TODO // query[3] = 0; /* don't need AD flag */
//TODO // int rlen = __res_send(query, qlen, reply, sizeof reply);
//TODO // buf[0] = 0;
//TODO // if (rlen > 0)
//TODO // __dns_parse(reply, rlen, dns_parse_callback, buf);
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(bp + 78 /* buf */))) != 0) {
//TODO if (flags & 0x08) != 0 {
//TODO return -2
//TODO }
//TODO Xinet_ntop(tls, af, a, bp+78 /* &buf[0] */, uint32(unsafe.Sizeof([256]int8{})))
//TODO if scopeid != 0 {
//TODO Xabort(tls) //TODO-
//TODO // char *p = 0, tmp[IF_NAMESIZE+1];
//TODO // if (!(flags & NI_NUMERICSCOPE) &&
//TODO // (IN6_IS_ADDR_LINKLOCAL(a) ||
//TODO // IN6_IS_ADDR_MC_LINKLOCAL(a)))
//TODO // p = if_indextoname(scopeid, tmp+1);
//TODO // if (!p)
//TODO // p = itoa(num, scopeid);
//TODO // *--p = '%';
//TODO // strcat(buf, p);
//TODO }
//TODO }
//TODO if Xstrlen(tls, bp+78 /* &buf[0] */) >= size_t(nodelen) {
//TODO return -12
//TODO }
//TODO Xstrcpy(tls, node, bp+78 /* &buf[0] */)
//TODO }
//TODO if (serv != 0) && (servlen != 0) {
//TODO var p uintptr = bp + 78 /* buf */
//TODO var port int32 = int32(Xntohs(tls, (*sockaddr_in)(unsafe.Pointer(sa1)).sin_port))
//TODO *(*int8)(unsafe.Pointer(bp + 78 /* &buf[0] */)) = int8(0)
//TODO if !((flags & 0x02) != 0) {
//TODO reverse_services(tls, bp+78 /* &buf[0] */, port, (flags & 0x10))
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(p))) != 0) {
//TODO p = itoa(tls, bp+334 /* &num[0] */, uint32(port))
//TODO }
//TODO if Xstrlen(tls, p) >= size_t(servlen) {
//TODO return -12
//TODO }
//TODO Xstrcpy(tls, serv, p)
//TODO }
//TODO return 0
}
func Xgethostbyaddr_r(tls *TLS, a uintptr, l socklen_t, af int32, h uintptr, buf uintptr, buflen size_t, res uintptr, err uintptr) int32 { /* gethostbyaddr_r.c:10:5: */
if __ccgo_strace {
trc("tls=%v a=%v l=%v af=%v h=%v buf=%v buflen=%v res=%v err=%v, (%v:)", tls, a, l, af, h, buf, buflen, res, err, origin(2))
}
panic(todo(""))
//TODO bp := tls.Alloc(28)
//TODO defer tls.Free(28)
//TODO //TODO union {
//TODO //TODO struct sockaddr_in sin;
//TODO //TODO struct sockaddr_in6 sin6;
//TODO //TODO } sa = { .sin.sin_family = af };
//TODO *(*struct {
//TODO sin sockaddr_in
//TODO _ [12]byte
//TODO })(unsafe.Pointer(bp /* sa1 */)) = struct {
//TODO sin sockaddr_in
//TODO _ [12]byte
//TODO }{} //TODO-
//TODO (*sockaddr_in)(unsafe.Pointer(bp /* &sa1 */)).sin_family = sa_family_t(af) //TODO-
//TODO var sl socklen_t
//TODO if af == 10 {
//TODO sl = uint32(unsafe.Sizeof(sockaddr_in6{}))
//TODO } else {
//TODO sl = uint32(unsafe.Sizeof(sockaddr_in{}))
//TODO }
//TODO var i int32
//TODO *(*uintptr)(unsafe.Pointer(res)) = uintptr(0)
//TODO // Load address argument into sockaddr structure
//TODO if (af == 10) && (l == socklen_t(16)) {
//TODO Xmemcpy(tls, (bp /* &sa1 */ /* &.sin6 */ + 8 /* &.sin6_addr */), a, uint64(16))
//TODO } else if (af == 2) && (l == socklen_t(4)) {
//TODO Xmemcpy(tls, (bp /* &sa1 */ /* &.sin */ + 4 /* &.sin_addr */), a, uint64(4))
//TODO } else {
//TODO *(*int32)(unsafe.Pointer(err)) = 3
//TODO return 22
//TODO }
//TODO // Align buffer and check for space for pointers and ip address
//TODO i = (int32(uintptr_t(buf) & (uint64(unsafe.Sizeof(uintptr(0))) - uint64(1))))
//TODO if !(i != 0) {
//TODO i = int32(unsafe.Sizeof(uintptr(0)))
//TODO }
//TODO if buflen <= (((uint64(5) * uint64(unsafe.Sizeof(uintptr(0)))) - uint64(i)) + uint64(l)) {
//TODO return 34
//TODO }
//TODO buf += (uintptr(uint64(unsafe.Sizeof(uintptr(0))) - uint64(i)))
//TODO buflen = buflen - (((uint64(5) * uint64(unsafe.Sizeof(uintptr(0)))) - uint64(i)) + uint64(l))
//TODO (*hostent)(unsafe.Pointer(h)).h_addr_list = buf
//TODO buf += (uintptr(uint64(2) * uint64(unsafe.Sizeof(uintptr(0)))))
//TODO (*hostent)(unsafe.Pointer(h)).h_aliases = buf
//TODO buf += (uintptr(uint64(2) * uint64(unsafe.Sizeof(uintptr(0)))))
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list)) = buf
//TODO Xmemcpy(tls, *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list)), a, uint64(l))
//TODO buf += uintptr(l)
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list + 1*8)) = uintptr(0)
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases)) = buf
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases + 1*8)) = uintptr(0)
//TODO switch Xgetnameinfo(tls, bp /* &sa1 */, sl, buf, uint32(buflen), uintptr(0), uint32(0), 0) {
//TODO case -3:
//TODO *(*int32)(unsafe.Pointer(err)) = 2
//TODO return 11
//TODO case -12:
//TODO return 34
//TODO default:
//TODO fallthrough
//TODO case -10:
//TODO fallthrough
//TODO case -11:
//TODO fallthrough
//TODO case -4:
//TODO *(*int32)(unsafe.Pointer(err)) = 3
//TODO return *(*int32)(unsafe.Pointer(X___errno_location(tls)))
//TODO case 0:
//TODO break
//TODO }
//TODO (*hostent)(unsafe.Pointer(h)).h_addrtype = af
//TODO (*hostent)(unsafe.Pointer(h)).h_length = int32(l)
//TODO (*hostent)(unsafe.Pointer(h)).h_name = *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases))
//TODO *(*uintptr)(unsafe.Pointer(res)) = h
//TODO return 0
}
// int getrlimit(int resource, struct rlimit *rlim);
func Xgetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
if __ccgo_strace {
trc("t=%v resource=%v rlim=%v, (%v:)", t, resource, rlim, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_GETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
t.setErrno(err)
return -1
}
return 0
}
func newFtsent(t *TLS, info int, path string, stat *unix.Stat_t, err syscall.Errno) (r *fts.FTSENT) {
var statp uintptr
if stat != nil {
statp = Xmalloc(t, types.Size_t(unsafe.Sizeof(unix.Stat_t{})))
if statp == 0 {
panic("OOM")
}
*(*unix.Stat_t)(unsafe.Pointer(statp)) = *stat
}
csp, errx := CString(path)
if errx != nil {
panic("OOM")
}
return &fts.FTSENT{
Ffts_info: uint16(info),
Ffts_path: csp,
Ffts_pathlen: uint32(len(path)),
Ffts_statp: statp,
Ffts_errno: int32(err),
}
}
// DIR *opendir(const char *name);
func Xopendir(t *TLS, name uintptr) uintptr {
if __ccgo_strace {
trc("t=%v name=%v, (%v:)", t, name, origin(2))
}
p := Xmalloc(t, uint32(unsafe.Sizeof(darwinDir{})))
if p == 0 {
panic("OOM")
}
fd := int(Xopen(t, name, fcntl.O_RDONLY|fcntl.O_DIRECTORY|fcntl.O_CLOEXEC, 0))
if fd < 0 {
if dmesgs {
dmesg("%v: FAIL %v", origin(1), (*darwinDir)(unsafe.Pointer(p)).fd)
}
Xfree(t, p)
return 0
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
(*darwinDir)(unsafe.Pointer(p)).fd = fd
(*darwinDir)(unsafe.Pointer(p)).h = 0
(*darwinDir)(unsafe.Pointer(p)).l = 0
(*darwinDir)(unsafe.Pointer(p)).eof = false
return p
}

View file

@ -4,729 +4,7 @@
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import (
"strings"
"syscall"
gotime "time"
"unsafe"
"golang.org/x/sys/unix"
"modernc.org/libc/fcntl"
"modernc.org/libc/fts"
"modernc.org/libc/stdio"
"modernc.org/libc/sys/types"
"modernc.org/libc/time"
"modernc.org/libc/utime"
)
type ( type (
long = int64 long = int64
ulong = uint64 ulong = uint64
) )
var (
startTime = gotime.Now() // For clock(3)
)
// int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
func Xsigaction(t *TLS, signum int32, act, oldact uintptr) int32 {
if __ccgo_strace {
trc("t=%v signum=%v oldact=%v, (%v:)", t, signum, oldact, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_SIGACTION, uintptr(signum), act, oldact); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// FILE *fopen64(const char *pathname, const char *mode);
func Xfopen64(t *TLS, pathname, mode uintptr) uintptr {
if __ccgo_strace {
trc("t=%v mode=%v, (%v:)", t, mode, origin(2))
}
m := strings.ReplaceAll(GoString(mode), "b", "")
var flags int
switch m {
case "r":
flags = fcntl.O_RDONLY
case "r+":
flags = fcntl.O_RDWR
case "w":
flags = fcntl.O_WRONLY | fcntl.O_CREAT | fcntl.O_TRUNC
case "w+":
flags = fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_TRUNC
case "a":
flags = fcntl.O_WRONLY | fcntl.O_CREAT | fcntl.O_APPEND
case "a+":
flags = fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_APPEND
default:
panic(m)
}
fd, err := unix.Open(GoString(pathname), int(flags), 0666)
if err != nil {
if dmesgs {
dmesg("%v: %q %q: %v FAIL", origin(1), GoString(pathname), GoString(mode), err)
}
t.setErrno(err)
return 0
}
if dmesgs {
dmesg("%v: %q %q: fd %v", origin(1), GoString(pathname), GoString(mode), fd)
}
if p := newFile(t, int32(fd)); p != 0 {
return p
}
panic("OOM")
}
// int lstat(const char *pathname, struct stat *statbuf);
func Xlstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := unix.Lstat(GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(pathname))
}
return 0
}
// int stat(const char *pathname, struct stat *statbuf);
func Xstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := unix.Stat(GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(pathname))
}
return 0
}
// int mkdir(const char *path, mode_t mode);
func Xmkdir(t *TLS, path uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v path=%v mode=%v, (%v:)", t, path, mode, origin(2))
}
if err := unix.Mkdir(GoString(path), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(path), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(path))
}
return 0
}
// int access(const char *pathname, int mode);
func Xaccess(t *TLS, pathname uintptr, mode int32) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
if err := unix.Access(GoString(pathname), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q %#o: %v FAIL", origin(1), GoString(pathname), mode, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
}
return 0
}
// int unlink(const char *pathname);
func Xunlink(t *TLS, pathname uintptr) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v, (%v:)", t, pathname, origin(2))
}
if err := unix.Unlink(GoString(pathname)); err != nil {
if dmesgs {
dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize);
func Xreadlink(t *TLS, path, buf uintptr, bufsize types.Size_t) types.Ssize_t {
if __ccgo_strace {
trc("t=%v buf=%v bufsize=%v, (%v:)", t, buf, bufsize, origin(2))
}
var n int
var err error
switch {
case buf == 0 || bufsize == 0:
n, err = unix.Readlink(GoString(path), nil)
default:
n, err = unix.Readlink(GoString(path), (*RawMem)(unsafe.Pointer(buf))[:bufsize:bufsize])
}
if err != nil {
if dmesgs {
dmesg("%v: %v FAIL", err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok")
}
return types.Ssize_t(n)
}
// int symlink(const char *target, const char *linkpath);
func Xsymlink(t *TLS, target, linkpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v linkpath=%v, (%v:)", t, linkpath, origin(2))
}
if err := unix.Symlink(GoString(target), GoString(linkpath)); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int chmod(const char *pathname, mode_t mode)
func Xchmod(t *TLS, pathname uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
if err := unix.Chmod(GoString(pathname), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q %#o: %v FAIL", origin(1), GoString(pathname), mode, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
}
return 0
}
// time_t time(time_t *tloc);
func Xtime(t *TLS, tloc uintptr) time.Time_t {
if __ccgo_strace {
trc("t=%v tloc=%v, (%v:)", t, tloc, origin(2))
}
panic(todo(""))
// n := time.Now().UTC().Unix()
// if tloc != 0 {
// *(*types.Time_t)(unsafe.Pointer(tloc)) = types.Time_t(n)
// }
// return types.Time_t(n)
}
// int utimes(const char *filename, const struct timeval times[2]);
func Xutimes(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
var a []unix.Timeval
if times != 0 {
a = make([]unix.Timeval, 2)
a[0] = *(*unix.Timeval)(unsafe.Pointer(times))
a[1] = *(*unix.Timeval)(unsafe.Pointer(times + unsafe.Sizeof(unix.Timeval{})))
}
if err := unix.Utimes(GoString(filename), a); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int fstat(int fd, struct stat *statbuf);
func Xfstat64(t *TLS, fd int32, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v fd=%v statbuf=%v, (%v:)", t, fd, statbuf, origin(2))
}
if err := unix.Fstat(int(fd), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: fd %d: %v FAIL", origin(1), fd, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: fd %d: ok", origin(1), fd)
}
return 0
}
// off64_t lseek64(int fd, off64_t offset, int whence);
func Xlseek64(t *TLS, fd int32, offset types.Off_t, whence int32) types.Off_t {
if __ccgo_strace {
trc("t=%v fd=%v offset=%v whence=%v, (%v:)", t, fd, offset, whence, origin(2))
}
n, err := unix.Seek(int(fd), int64(offset), int(whence))
if err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: fd %d, offset %#0x, whence %d, ok", origin(1), fd, offset, whence)
}
return types.Off_t(n)
}
func Xfcntl64(t *TLS, fd, cmd int32, args uintptr) int32 {
if __ccgo_strace {
trc("t=%v cmd=%v args=%v, (%v:)", t, cmd, args, origin(2))
}
var arg uintptr
if args != 0 {
arg = *(*uintptr)(unsafe.Pointer(args))
}
n, _, err := unix.Syscall(unix.SYS_FCNTL, uintptr(fd), uintptr(cmd), arg)
if err != 0 {
if dmesgs {
dmesg("%v: fd %v cmd %v", origin(1), fcntlCmdStr(fd), cmd)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %d %s %#x: %d", origin(1), fd, fcntlCmdStr(cmd), arg, n)
}
return int32(n)
}
// int rename(const char *oldpath, const char *newpath);
func Xrename(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
if err := unix.Rename(GoString(oldpath), GoString(newpath)); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int mknod(const char *pathname, mode_t mode, dev_t dev);
func Xmknod(t *TLS, pathname uintptr, mode types.Mode_t, dev types.Dev_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v dev=%v, (%v:)", t, pathname, mode, dev, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_MKNOD, pathname, uintptr(mode), uintptr(dev)); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int utime(const char *filename, const struct utimbuf *times);
func Xutime(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
var a []unix.Timeval
if times != 0 {
a = make([]unix.Timeval, 2)
a[0].Sec = (*utime.Utimbuf)(unsafe.Pointer(times)).Factime
a[1].Sec = (*utime.Utimbuf)(unsafe.Pointer(times)).Fmodtime
}
if err := unix.Utimes(GoString(filename), a); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int chown(const char *pathname, uid_t owner, gid_t group);
func Xchown(t *TLS, pathname uintptr, owner types.Uid_t, group types.Gid_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v owner=%v group=%v, (%v:)", t, pathname, owner, group, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_CHOWN, pathname, uintptr(owner), uintptr(group)); err != 0 {
t.setErrno(err)
return -1
}
return 0
}
// int link(const char *oldpath, const char *newpath);
func Xlink(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_LINK, oldpath, newpath, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int dup2(int oldfd, int newfd);
func Xdup2(t *TLS, oldfd, newfd int32) int32 {
if __ccgo_strace {
trc("t=%v newfd=%v, (%v:)", t, newfd, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
// if err != 0 {
// t.setErrno(err)
// return -1
// }
// return int32(n)
}
// unsigned int alarm(unsigned int seconds);
func Xalarm(t *TLS, seconds uint32) uint32 {
if __ccgo_strace {
trc("t=%v seconds=%v, (%v:)", t, seconds, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_ALARM, uintptr(seconds), 0, 0)
// if err != 0 {
// panic(todo(""))
// }
// return uint32(n)
}
// int getnameinfo(const struct sockaddr * restrict sa, socklen_t salen, char * restrict host, socklen_t hostlen, char * restrict serv, socklen_t servlen, int flags);
func Xgetnameinfo(tls *TLS, sa1 uintptr, sl socklen_t, node uintptr, nodelen size_t, serv uintptr, servlen size_t, flags int32) int32 { /* getnameinfo.c:125:5: */
if __ccgo_strace {
trc("tls=%v sa1=%v sl=%v node=%v nodelen=%v serv=%v servlen=%v flags=%v, (%v:)", tls, sa1, sl, node, nodelen, serv, servlen, flags, origin(2))
}
panic(todo(""))
//TODO bp := tls.Alloc(347)
//TODO defer tls.Free(347)
//TODO // var ptr [78]int8 at bp, 78
//TODO // var buf [256]int8 at bp+78, 256
//TODO // var num [13]int8 at bp+334, 13
//TODO var af int32 = int32((*sockaddr)(unsafe.Pointer(sa1)).sa_family)
//TODO var a uintptr
//TODO var scopeid uint32
//TODO switch af {
//TODO case 2:
//TODO a = (sa1 + 4 /* &.sin_addr */)
//TODO if (uint64(sl) < uint64(unsafe.Sizeof(sockaddr_in{}))) {
//TODO return -6
//TODO }
//TODO mkptr4(tls, bp /* &ptr[0] */, a)
//TODO scopeid = uint32(0)
//TODO break
//TODO case 10:
//TODO a = (sa1 + 8 /* &.sin6_addr */)
//TODO if (uint64(sl) < uint64(unsafe.Sizeof(sockaddr_in6{}))) {
//TODO return -6
//TODO }
//TODO if Xmemcmp(tls, a, ts+88 /* "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" */, uint64(12)) != 0 {
//TODO mkptr6(tls, bp /* &ptr[0] */, a)
//TODO } else {
//TODO mkptr4(tls, bp /* &ptr[0] */, (a + uintptr(12)))
//TODO }
//TODO scopeid = (*sockaddr_in6)(unsafe.Pointer(sa1)).sin6_scope_id
//TODO break
//TODO default:
//TODO return -6
//TODO }
//TODO if (node != 0) && (nodelen != 0) {
//TODO *(*int8)(unsafe.Pointer(bp + 78 /* &buf[0] */)) = int8(0)
//TODO if !((flags & 0x01) != 0) {
//TODO reverse_hosts(tls, bp+78 /* &buf[0] */, a, scopeid, af)
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(bp + 78 /* buf */))) != 0) && !((flags & 0x01) != 0) {
//TODO Xabort(tls) //TODO-
//TODO // unsigned char query[18+PTR_MAX], reply[512];
//TODO // int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
//TODO // 0, 0, 0, query, sizeof query);
//TODO // query[3] = 0; /* don't need AD flag */
//TODO // int rlen = __res_send(query, qlen, reply, sizeof reply);
//TODO // buf[0] = 0;
//TODO // if (rlen > 0)
//TODO // __dns_parse(reply, rlen, dns_parse_callback, buf);
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(bp + 78 /* buf */))) != 0) {
//TODO if (flags & 0x08) != 0 {
//TODO return -2
//TODO }
//TODO Xinet_ntop(tls, af, a, bp+78 /* &buf[0] */, uint32(unsafe.Sizeof([256]int8{})))
//TODO if scopeid != 0 {
//TODO Xabort(tls) //TODO-
//TODO // char *p = 0, tmp[IF_NAMESIZE+1];
//TODO // if (!(flags & NI_NUMERICSCOPE) &&
//TODO // (IN6_IS_ADDR_LINKLOCAL(a) ||
//TODO // IN6_IS_ADDR_MC_LINKLOCAL(a)))
//TODO // p = if_indextoname(scopeid, tmp+1);
//TODO // if (!p)
//TODO // p = itoa(num, scopeid);
//TODO // *--p = '%';
//TODO // strcat(buf, p);
//TODO }
//TODO }
//TODO if Xstrlen(tls, bp+78 /* &buf[0] */) >= size_t(nodelen) {
//TODO return -12
//TODO }
//TODO Xstrcpy(tls, node, bp+78 /* &buf[0] */)
//TODO }
//TODO if (serv != 0) && (servlen != 0) {
//TODO var p uintptr = bp + 78 /* buf */
//TODO var port int32 = int32(Xntohs(tls, (*sockaddr_in)(unsafe.Pointer(sa1)).sin_port))
//TODO *(*int8)(unsafe.Pointer(bp + 78 /* &buf[0] */)) = int8(0)
//TODO if !((flags & 0x02) != 0) {
//TODO reverse_services(tls, bp+78 /* &buf[0] */, port, (flags & 0x10))
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(p))) != 0) {
//TODO p = itoa(tls, bp+334 /* &num[0] */, uint32(port))
//TODO }
//TODO if Xstrlen(tls, p) >= size_t(servlen) {
//TODO return -12
//TODO }
//TODO Xstrcpy(tls, serv, p)
//TODO }
//TODO return 0
}
func Xgethostbyaddr_r(tls *TLS, a uintptr, l socklen_t, af int32, h uintptr, buf uintptr, buflen size_t, res uintptr, err uintptr) int32 { /* gethostbyaddr_r.c:10:5: */
if __ccgo_strace {
trc("tls=%v a=%v l=%v af=%v h=%v buf=%v buflen=%v res=%v err=%v, (%v:)", tls, a, l, af, h, buf, buflen, res, err, origin(2))
}
panic(todo(""))
//TODO bp := tls.Alloc(28)
//TODO defer tls.Free(28)
//TODO //TODO union {
//TODO //TODO struct sockaddr_in sin;
//TODO //TODO struct sockaddr_in6 sin6;
//TODO //TODO } sa = { .sin.sin_family = af };
//TODO *(*struct {
//TODO sin sockaddr_in
//TODO _ [12]byte
//TODO })(unsafe.Pointer(bp /* sa1 */)) = struct {
//TODO sin sockaddr_in
//TODO _ [12]byte
//TODO }{} //TODO-
//TODO (*sockaddr_in)(unsafe.Pointer(bp /* &sa1 */)).sin_family = sa_family_t(af) //TODO-
//TODO var sl socklen_t
//TODO if af == 10 {
//TODO sl = uint32(unsafe.Sizeof(sockaddr_in6{}))
//TODO } else {
//TODO sl = uint32(unsafe.Sizeof(sockaddr_in{}))
//TODO }
//TODO var i int32
//TODO *(*uintptr)(unsafe.Pointer(res)) = uintptr(0)
//TODO // Load address argument into sockaddr structure
//TODO if (af == 10) && (l == socklen_t(16)) {
//TODO Xmemcpy(tls, (bp /* &sa1 */ /* &.sin6 */ + 8 /* &.sin6_addr */), a, uint64(16))
//TODO } else if (af == 2) && (l == socklen_t(4)) {
//TODO Xmemcpy(tls, (bp /* &sa1 */ /* &.sin */ + 4 /* &.sin_addr */), a, uint64(4))
//TODO } else {
//TODO *(*int32)(unsafe.Pointer(err)) = 3
//TODO return 22
//TODO }
//TODO // Align buffer and check for space for pointers and ip address
//TODO i = (int32(uintptr_t(buf) & (uint64(unsafe.Sizeof(uintptr(0))) - uint64(1))))
//TODO if !(i != 0) {
//TODO i = int32(unsafe.Sizeof(uintptr(0)))
//TODO }
//TODO if buflen <= (((uint64(5) * uint64(unsafe.Sizeof(uintptr(0)))) - uint64(i)) + uint64(l)) {
//TODO return 34
//TODO }
//TODO buf += (uintptr(uint64(unsafe.Sizeof(uintptr(0))) - uint64(i)))
//TODO buflen = buflen - (((uint64(5) * uint64(unsafe.Sizeof(uintptr(0)))) - uint64(i)) + uint64(l))
//TODO (*hostent)(unsafe.Pointer(h)).h_addr_list = buf
//TODO buf += (uintptr(uint64(2) * uint64(unsafe.Sizeof(uintptr(0)))))
//TODO (*hostent)(unsafe.Pointer(h)).h_aliases = buf
//TODO buf += (uintptr(uint64(2) * uint64(unsafe.Sizeof(uintptr(0)))))
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list)) = buf
//TODO Xmemcpy(tls, *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list)), a, uint64(l))
//TODO buf += uintptr(l)
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list + 1*8)) = uintptr(0)
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases)) = buf
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases + 1*8)) = uintptr(0)
//TODO switch Xgetnameinfo(tls, bp /* &sa1 */, sl, buf, uint32(buflen), uintptr(0), uint32(0), 0) {
//TODO case -3:
//TODO *(*int32)(unsafe.Pointer(err)) = 2
//TODO return 11
//TODO case -12:
//TODO return 34
//TODO default:
//TODO fallthrough
//TODO case -10:
//TODO fallthrough
//TODO case -11:
//TODO fallthrough
//TODO case -4:
//TODO *(*int32)(unsafe.Pointer(err)) = 3
//TODO return *(*int32)(unsafe.Pointer(X___errno_location(tls)))
//TODO case 0:
//TODO break
//TODO }
//TODO (*hostent)(unsafe.Pointer(h)).h_addrtype = af
//TODO (*hostent)(unsafe.Pointer(h)).h_length = int32(l)
//TODO (*hostent)(unsafe.Pointer(h)).h_name = *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases))
//TODO *(*uintptr)(unsafe.Pointer(res)) = h
//TODO return 0
}
// int getrlimit(int resource, struct rlimit *rlim);
func Xgetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
if __ccgo_strace {
trc("t=%v resource=%v rlim=%v, (%v:)", t, resource, rlim, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_GETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
t.setErrno(err)
return -1
}
return 0
}
func newFtsent(t *TLS, info int, path string, stat *unix.Stat_t, err syscall.Errno) (r *fts.FTSENT) {
var statp uintptr
if stat != nil {
statp = Xmalloc(t, types.Size_t(unsafe.Sizeof(unix.Stat_t{})))
if statp == 0 {
panic("OOM")
}
*(*unix.Stat_t)(unsafe.Pointer(statp)) = *stat
}
csp, errx := CString(path)
if errx != nil {
panic("OOM")
}
return &fts.FTSENT{
Ffts_info: uint16(info),
Ffts_path: csp,
Ffts_pathlen: uint64(len(path)),
Ffts_statp: statp,
Ffts_errno: int32(err),
}
}
// DIR *opendir(const char *name);
func Xopendir(t *TLS, name uintptr) uintptr {
if __ccgo_strace {
trc("t=%v name=%v, (%v:)", t, name, origin(2))
}
p := Xmalloc(t, uint64(unsafe.Sizeof(darwinDir{})))
if p == 0 {
panic("OOM")
}
fd := int(Xopen(t, name, fcntl.O_RDONLY|fcntl.O_DIRECTORY|fcntl.O_CLOEXEC, 0))
if fd < 0 {
if dmesgs {
dmesg("%v: FAIL %v", origin(1), (*darwinDir)(unsafe.Pointer(p)).fd)
}
Xfree(t, p)
return 0
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
(*darwinDir)(unsafe.Pointer(p)).fd = fd
(*darwinDir)(unsafe.Pointer(p)).h = 0
(*darwinDir)(unsafe.Pointer(p)).l = 0
(*darwinDir)(unsafe.Pointer(p)).eof = false
return p
}
func Xrewinddir(tls *TLS, f uintptr) {
if __ccgo_strace {
trc("tls=%v f=%v, (%v:)", tls, f, origin(2))
}
Xfseek(tls, f, 0, stdio.SEEK_SET)
}
// clock_t clock(void);
func Xclock(t *TLS) time.Clock_t {
if __ccgo_strace {
trc("t=%v, (%v:)", t, origin(2))
}
return time.Clock_t(gotime.Since(startTime) * gotime.Duration(time.CLOCKS_PER_SEC) / gotime.Second)
}

View file

@ -4,721 +4,7 @@
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import (
"strings"
"syscall"
gotime "time"
"unsafe"
"golang.org/x/sys/unix"
"modernc.org/libc/fcntl"
"modernc.org/libc/fts"
"modernc.org/libc/sys/types"
"modernc.org/libc/time"
"modernc.org/libc/utime"
)
type ( type (
long = int64 long = int64
ulong = uint64 ulong = uint64
) )
var (
startTime = gotime.Now() // For clock(3)
)
// int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
func Xsigaction(t *TLS, signum int32, act, oldact uintptr) int32 {
if __ccgo_strace {
trc("t=%v signum=%v oldact=%v, (%v:)", t, signum, oldact, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_SIGACTION, uintptr(signum), act, oldact); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// FILE *fopen64(const char *pathname, const char *mode);
func Xfopen64(t *TLS, pathname, mode uintptr) uintptr {
if __ccgo_strace {
trc("t=%v mode=%v, (%v:)", t, mode, origin(2))
}
m := strings.ReplaceAll(GoString(mode), "b", "")
var flags int
switch m {
case "r":
flags = fcntl.O_RDONLY
case "r+":
flags = fcntl.O_RDWR
case "w":
flags = fcntl.O_WRONLY | fcntl.O_CREAT | fcntl.O_TRUNC
case "w+":
flags = fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_TRUNC
case "a":
flags = fcntl.O_WRONLY | fcntl.O_CREAT | fcntl.O_APPEND
case "a+":
flags = fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_APPEND
default:
panic(m)
}
fd, err := unix.Open(GoString(pathname), int(flags), 0666)
if err != nil {
if dmesgs {
dmesg("%v: %q %q: %v FAIL", origin(1), GoString(pathname), GoString(mode), err)
}
t.setErrno(err)
return 0
}
if dmesgs {
dmesg("%v: %q %q: fd %v", origin(1), GoString(pathname), GoString(mode), fd)
}
if p := newFile(t, int32(fd)); p != 0 {
return p
}
panic("OOM")
}
// int lstat(const char *pathname, struct stat *statbuf);
func Xlstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := unix.Lstat(GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(pathname))
}
return 0
}
// int stat(const char *pathname, struct stat *statbuf);
func Xstat64(t *TLS, pathname, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v statbuf=%v, (%v:)", t, statbuf, origin(2))
}
if err := unix.Stat(GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(pathname))
}
return 0
}
// int mkdir(const char *path, mode_t mode);
func Xmkdir(t *TLS, path uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v path=%v mode=%v, (%v:)", t, path, mode, origin(2))
}
if err := unix.Mkdir(GoString(path), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q: %v FAIL", origin(1), GoString(path), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q: ok", origin(1), GoString(path))
}
return 0
}
// int access(const char *pathname, int mode);
func Xaccess(t *TLS, pathname uintptr, mode int32) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
if err := unix.Access(GoString(pathname), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q %#o: %v FAIL", origin(1), GoString(pathname), mode, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
}
return 0
}
// int unlink(const char *pathname);
func Xunlink(t *TLS, pathname uintptr) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v, (%v:)", t, pathname, origin(2))
}
if err := unix.Unlink(GoString(pathname)); err != nil {
if dmesgs {
dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize);
func Xreadlink(t *TLS, path, buf uintptr, bufsize types.Size_t) types.Ssize_t {
if __ccgo_strace {
trc("t=%v buf=%v bufsize=%v, (%v:)", t, buf, bufsize, origin(2))
}
var n int
var err error
switch {
case buf == 0 || bufsize == 0:
n, err = unix.Readlink(GoString(path), nil)
default:
n, err = unix.Readlink(GoString(path), (*RawMem)(unsafe.Pointer(buf))[:bufsize:bufsize])
}
if err != nil {
if dmesgs {
dmesg("%v: %v FAIL", err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok")
}
return types.Ssize_t(n)
}
// int symlink(const char *target, const char *linkpath);
func Xsymlink(t *TLS, target, linkpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v linkpath=%v, (%v:)", t, linkpath, origin(2))
}
if err := unix.Symlink(GoString(target), GoString(linkpath)); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int chmod(const char *pathname, mode_t mode)
func Xchmod(t *TLS, pathname uintptr, mode types.Mode_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v, (%v:)", t, pathname, mode, origin(2))
}
if err := unix.Chmod(GoString(pathname), uint32(mode)); err != nil {
if dmesgs {
dmesg("%v: %q %#o: %v FAIL", origin(1), GoString(pathname), mode, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
}
return 0
}
// time_t time(time_t *tloc);
func Xtime(t *TLS, tloc uintptr) time.Time_t {
if __ccgo_strace {
trc("t=%v tloc=%v, (%v:)", t, tloc, origin(2))
}
panic(todo(""))
// n := time.Now().UTC().Unix()
// if tloc != 0 {
// *(*types.Time_t)(unsafe.Pointer(tloc)) = types.Time_t(n)
// }
// return types.Time_t(n)
}
// int utimes(const char *filename, const struct timeval times[2]);
func Xutimes(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
var a []unix.Timeval
if times != 0 {
a = make([]unix.Timeval, 2)
a[0] = *(*unix.Timeval)(unsafe.Pointer(times))
a[1] = *(*unix.Timeval)(unsafe.Pointer(times + unsafe.Sizeof(unix.Timeval{})))
}
if err := unix.Utimes(GoString(filename), a); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int fstat(int fd, struct stat *statbuf);
func Xfstat64(t *TLS, fd int32, statbuf uintptr) int32 {
if __ccgo_strace {
trc("t=%v fd=%v statbuf=%v, (%v:)", t, fd, statbuf, origin(2))
}
if err := unix.Fstat(int(fd), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
if dmesgs {
dmesg("%v: fd %d: %v FAIL", origin(1), fd, err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: fd %d: ok", origin(1), fd)
}
return 0
}
// off64_t lseek64(int fd, off64_t offset, int whence);
func Xlseek64(t *TLS, fd int32, offset types.Off_t, whence int32) types.Off_t {
if __ccgo_strace {
trc("t=%v fd=%v offset=%v whence=%v, (%v:)", t, fd, offset, whence, origin(2))
}
n, err := unix.Seek(int(fd), int64(offset), int(whence))
if err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return types.Off_t(n)
}
func Xfcntl64(t *TLS, fd, cmd int32, args uintptr) int32 {
if __ccgo_strace {
trc("t=%v cmd=%v args=%v, (%v:)", t, cmd, args, origin(2))
}
var arg uintptr
if args != 0 {
arg = *(*uintptr)(unsafe.Pointer(args))
}
n, _, err := unix.Syscall(unix.SYS_FCNTL, uintptr(fd), uintptr(cmd), arg)
if err != 0 {
if dmesgs {
dmesg("%v: fd %v cmd %v", origin(1), fcntlCmdStr(fd), cmd)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: %d %s %#x: %d", origin(1), fd, fcntlCmdStr(cmd), arg, n)
}
return int32(n)
}
// int rename(const char *oldpath, const char *newpath);
func Xrename(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
if err := unix.Rename(GoString(oldpath), GoString(newpath)); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int mknod(const char *pathname, mode_t mode, dev_t dev);
func Xmknod(t *TLS, pathname uintptr, mode types.Mode_t, dev types.Dev_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v mode=%v dev=%v, (%v:)", t, pathname, mode, dev, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_MKNOD, pathname, uintptr(mode), uintptr(dev)); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int utime(const char *filename, const struct utimbuf *times);
func Xutime(t *TLS, filename, times uintptr) int32 {
if __ccgo_strace {
trc("t=%v times=%v, (%v:)", t, times, origin(2))
}
var a []unix.Timeval
if times != 0 {
a = make([]unix.Timeval, 2)
a[0].Sec = (*utime.Utimbuf)(unsafe.Pointer(times)).Factime
a[1].Sec = (*utime.Utimbuf)(unsafe.Pointer(times)).Fmodtime
}
if err := unix.Utimes(GoString(filename), a); err != nil {
if dmesgs {
dmesg("%v: %v FAIL", origin(1), err)
}
t.setErrno(err)
return -1
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
return 0
}
// int chown(const char *pathname, uid_t owner, gid_t group);
func Xchown(t *TLS, pathname uintptr, owner types.Uid_t, group types.Gid_t) int32 {
if __ccgo_strace {
trc("t=%v pathname=%v owner=%v group=%v, (%v:)", t, pathname, owner, group, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_CHOWN, pathname, uintptr(owner), uintptr(group)); err != 0 {
t.setErrno(err)
return -1
}
return 0
}
// int link(const char *oldpath, const char *newpath);
func Xlink(t *TLS, oldpath, newpath uintptr) int32 {
if __ccgo_strace {
trc("t=%v newpath=%v, (%v:)", t, newpath, origin(2))
}
panic(todo(""))
// if _, _, err := unix.Syscall(unix.SYS_LINK, oldpath, newpath, 0); err != 0 {
// t.setErrno(err)
// return -1
// }
// return 0
}
// int dup2(int oldfd, int newfd);
func Xdup2(t *TLS, oldfd, newfd int32) int32 {
if __ccgo_strace {
trc("t=%v newfd=%v, (%v:)", t, newfd, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
// if err != 0 {
// t.setErrno(err)
// return -1
// }
// return int32(n)
}
// unsigned int alarm(unsigned int seconds);
func Xalarm(t *TLS, seconds uint32) uint32 {
if __ccgo_strace {
trc("t=%v seconds=%v, (%v:)", t, seconds, origin(2))
}
panic(todo(""))
// n, _, err := unix.Syscall(unix.SYS_ALARM, uintptr(seconds), 0, 0)
// if err != 0 {
// panic(todo(""))
// }
// return uint32(n)
}
// int getnameinfo(const struct sockaddr * restrict sa, socklen_t salen, char * restrict host, socklen_t hostlen, char * restrict serv, socklen_t servlen, int flags);
func Xgetnameinfo(tls *TLS, sa1 uintptr, sl socklen_t, node uintptr, nodelen size_t, serv uintptr, servlen size_t, flags int32) int32 { /* getnameinfo.c:125:5: */
if __ccgo_strace {
trc("tls=%v sa1=%v sl=%v node=%v nodelen=%v serv=%v servlen=%v flags=%v, (%v:)", tls, sa1, sl, node, nodelen, serv, servlen, flags, origin(2))
}
panic(todo(""))
//TODO bp := tls.Alloc(347)
//TODO defer tls.Free(347)
//TODO // var ptr [78]int8 at bp, 78
//TODO // var buf [256]int8 at bp+78, 256
//TODO // var num [13]int8 at bp+334, 13
//TODO var af int32 = int32((*sockaddr)(unsafe.Pointer(sa1)).sa_family)
//TODO var a uintptr
//TODO var scopeid uint32
//TODO switch af {
//TODO case 2:
//TODO a = (sa1 + 4 /* &.sin_addr */)
//TODO if (uint64(sl) < uint64(unsafe.Sizeof(sockaddr_in{}))) {
//TODO return -6
//TODO }
//TODO mkptr4(tls, bp /* &ptr[0] */, a)
//TODO scopeid = uint32(0)
//TODO break
//TODO case 10:
//TODO a = (sa1 + 8 /* &.sin6_addr */)
//TODO if (uint64(sl) < uint64(unsafe.Sizeof(sockaddr_in6{}))) {
//TODO return -6
//TODO }
//TODO if Xmemcmp(tls, a, ts+88 /* "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" */, uint64(12)) != 0 {
//TODO mkptr6(tls, bp /* &ptr[0] */, a)
//TODO } else {
//TODO mkptr4(tls, bp /* &ptr[0] */, (a + uintptr(12)))
//TODO }
//TODO scopeid = (*sockaddr_in6)(unsafe.Pointer(sa1)).sin6_scope_id
//TODO break
//TODO default:
//TODO return -6
//TODO }
//TODO if (node != 0) && (nodelen != 0) {
//TODO *(*int8)(unsafe.Pointer(bp + 78 /* &buf[0] */)) = int8(0)
//TODO if !((flags & 0x01) != 0) {
//TODO reverse_hosts(tls, bp+78 /* &buf[0] */, a, scopeid, af)
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(bp + 78 /* buf */))) != 0) && !((flags & 0x01) != 0) {
//TODO Xabort(tls) //TODO-
//TODO // unsigned char query[18+PTR_MAX], reply[512];
//TODO // int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
//TODO // 0, 0, 0, query, sizeof query);
//TODO // query[3] = 0; /* don't need AD flag */
//TODO // int rlen = __res_send(query, qlen, reply, sizeof reply);
//TODO // buf[0] = 0;
//TODO // if (rlen > 0)
//TODO // __dns_parse(reply, rlen, dns_parse_callback, buf);
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(bp + 78 /* buf */))) != 0) {
//TODO if (flags & 0x08) != 0 {
//TODO return -2
//TODO }
//TODO Xinet_ntop(tls, af, a, bp+78 /* &buf[0] */, uint32(unsafe.Sizeof([256]int8{})))
//TODO if scopeid != 0 {
//TODO Xabort(tls) //TODO-
//TODO // char *p = 0, tmp[IF_NAMESIZE+1];
//TODO // if (!(flags & NI_NUMERICSCOPE) &&
//TODO // (IN6_IS_ADDR_LINKLOCAL(a) ||
//TODO // IN6_IS_ADDR_MC_LINKLOCAL(a)))
//TODO // p = if_indextoname(scopeid, tmp+1);
//TODO // if (!p)
//TODO // p = itoa(num, scopeid);
//TODO // *--p = '%';
//TODO // strcat(buf, p);
//TODO }
//TODO }
//TODO if Xstrlen(tls, bp+78 /* &buf[0] */) >= size_t(nodelen) {
//TODO return -12
//TODO }
//TODO Xstrcpy(tls, node, bp+78 /* &buf[0] */)
//TODO }
//TODO if (serv != 0) && (servlen != 0) {
//TODO var p uintptr = bp + 78 /* buf */
//TODO var port int32 = int32(Xntohs(tls, (*sockaddr_in)(unsafe.Pointer(sa1)).sin_port))
//TODO *(*int8)(unsafe.Pointer(bp + 78 /* &buf[0] */)) = int8(0)
//TODO if !((flags & 0x02) != 0) {
//TODO reverse_services(tls, bp+78 /* &buf[0] */, port, (flags & 0x10))
//TODO }
//TODO if !(int32(*(*int8)(unsafe.Pointer(p))) != 0) {
//TODO p = itoa(tls, bp+334 /* &num[0] */, uint32(port))
//TODO }
//TODO if Xstrlen(tls, p) >= size_t(servlen) {
//TODO return -12
//TODO }
//TODO Xstrcpy(tls, serv, p)
//TODO }
//TODO return 0
}
func Xgethostbyaddr_r(tls *TLS, a uintptr, l socklen_t, af int32, h uintptr, buf uintptr, buflen size_t, res uintptr, err uintptr) int32 { /* gethostbyaddr_r.c:10:5: */
if __ccgo_strace {
trc("tls=%v a=%v l=%v af=%v h=%v buf=%v buflen=%v res=%v err=%v, (%v:)", tls, a, l, af, h, buf, buflen, res, err, origin(2))
}
panic(todo(""))
//TODO bp := tls.Alloc(28)
//TODO defer tls.Free(28)
//TODO //TODO union {
//TODO //TODO struct sockaddr_in sin;
//TODO //TODO struct sockaddr_in6 sin6;
//TODO //TODO } sa = { .sin.sin_family = af };
//TODO *(*struct {
//TODO sin sockaddr_in
//TODO _ [12]byte
//TODO })(unsafe.Pointer(bp /* sa1 */)) = struct {
//TODO sin sockaddr_in
//TODO _ [12]byte
//TODO }{} //TODO-
//TODO (*sockaddr_in)(unsafe.Pointer(bp /* &sa1 */)).sin_family = sa_family_t(af) //TODO-
//TODO var sl socklen_t
//TODO if af == 10 {
//TODO sl = uint32(unsafe.Sizeof(sockaddr_in6{}))
//TODO } else {
//TODO sl = uint32(unsafe.Sizeof(sockaddr_in{}))
//TODO }
//TODO var i int32
//TODO *(*uintptr)(unsafe.Pointer(res)) = uintptr(0)
//TODO // Load address argument into sockaddr structure
//TODO if (af == 10) && (l == socklen_t(16)) {
//TODO Xmemcpy(tls, (bp /* &sa1 */ /* &.sin6 */ + 8 /* &.sin6_addr */), a, uint64(16))
//TODO } else if (af == 2) && (l == socklen_t(4)) {
//TODO Xmemcpy(tls, (bp /* &sa1 */ /* &.sin */ + 4 /* &.sin_addr */), a, uint64(4))
//TODO } else {
//TODO *(*int32)(unsafe.Pointer(err)) = 3
//TODO return 22
//TODO }
//TODO // Align buffer and check for space for pointers and ip address
//TODO i = (int32(uintptr_t(buf) & (uint64(unsafe.Sizeof(uintptr(0))) - uint64(1))))
//TODO if !(i != 0) {
//TODO i = int32(unsafe.Sizeof(uintptr(0)))
//TODO }
//TODO if buflen <= (((uint64(5) * uint64(unsafe.Sizeof(uintptr(0)))) - uint64(i)) + uint64(l)) {
//TODO return 34
//TODO }
//TODO buf += (uintptr(uint64(unsafe.Sizeof(uintptr(0))) - uint64(i)))
//TODO buflen = buflen - (((uint64(5) * uint64(unsafe.Sizeof(uintptr(0)))) - uint64(i)) + uint64(l))
//TODO (*hostent)(unsafe.Pointer(h)).h_addr_list = buf
//TODO buf += (uintptr(uint64(2) * uint64(unsafe.Sizeof(uintptr(0)))))
//TODO (*hostent)(unsafe.Pointer(h)).h_aliases = buf
//TODO buf += (uintptr(uint64(2) * uint64(unsafe.Sizeof(uintptr(0)))))
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list)) = buf
//TODO Xmemcpy(tls, *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list)), a, uint64(l))
//TODO buf += uintptr(l)
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_addr_list + 1*8)) = uintptr(0)
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases)) = buf
//TODO *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases + 1*8)) = uintptr(0)
//TODO switch Xgetnameinfo(tls, bp /* &sa1 */, sl, buf, uint32(buflen), uintptr(0), uint32(0), 0) {
//TODO case -3:
//TODO *(*int32)(unsafe.Pointer(err)) = 2
//TODO return 11
//TODO case -12:
//TODO return 34
//TODO default:
//TODO fallthrough
//TODO case -10:
//TODO fallthrough
//TODO case -11:
//TODO fallthrough
//TODO case -4:
//TODO *(*int32)(unsafe.Pointer(err)) = 3
//TODO return *(*int32)(unsafe.Pointer(X___errno_location(tls)))
//TODO case 0:
//TODO break
//TODO }
//TODO (*hostent)(unsafe.Pointer(h)).h_addrtype = af
//TODO (*hostent)(unsafe.Pointer(h)).h_length = int32(l)
//TODO (*hostent)(unsafe.Pointer(h)).h_name = *(*uintptr)(unsafe.Pointer((*hostent)(unsafe.Pointer(h)).h_aliases))
//TODO *(*uintptr)(unsafe.Pointer(res)) = h
//TODO return 0
}
// int getrlimit(int resource, struct rlimit *rlim);
func Xgetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
if __ccgo_strace {
trc("t=%v resource=%v rlim=%v, (%v:)", t, resource, rlim, origin(2))
}
if _, _, err := unix.Syscall(unix.SYS_GETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
t.setErrno(err)
return -1
}
return 0
}
func newFtsent(t *TLS, info int, path string, stat *unix.Stat_t, err syscall.Errno) (r *fts.FTSENT) {
var statp uintptr
if stat != nil {
statp = Xmalloc(t, types.Size_t(unsafe.Sizeof(unix.Stat_t{})))
if statp == 0 {
panic("OOM")
}
*(*unix.Stat_t)(unsafe.Pointer(statp)) = *stat
}
csp, errx := CString(path)
if errx != nil {
panic("OOM")
}
return &fts.FTSENT{
Ffts_info: uint16(info),
Ffts_path: csp,
Ffts_pathlen: uint64(len(path)),
Ffts_statp: statp,
Ffts_errno: int32(err),
}
}
// DIR *opendir(const char *name);
func Xopendir(t *TLS, name uintptr) uintptr {
if __ccgo_strace {
trc("t=%v name=%v, (%v:)", t, name, origin(2))
}
p := Xmalloc(t, uint64(unsafe.Sizeof(darwinDir{})))
if p == 0 {
panic("OOM")
}
fd := int(Xopen(t, name, fcntl.O_RDONLY|fcntl.O_DIRECTORY|fcntl.O_CLOEXEC, 0))
if fd < 0 {
if dmesgs {
dmesg("%v: FAIL %v", origin(1), (*darwinDir)(unsafe.Pointer(p)).fd)
}
Xfree(t, p)
return 0
}
if dmesgs {
dmesg("%v: ok", origin(1))
}
(*darwinDir)(unsafe.Pointer(p)).fd = fd
(*darwinDir)(unsafe.Pointer(p)).h = 0
(*darwinDir)(unsafe.Pointer(p)).l = 0
(*darwinDir)(unsafe.Pointer(p)).eof = false
return p
}
// clock_t clock(void);
func Xclock(t *TLS) time.Clock_t {
if __ccgo_strace {
trc("t=%v, (%v:)", t, origin(2))
}
return time.Clock_t(gotime.Since(startTime) * gotime.Duration(time.CLOCKS_PER_SEC) / gotime.Second)
}

34
vendor/modernc.org/libc/libc_unix.go generated vendored
View file

@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build unix //go:build unix && !(linux && (amd64 || loong64))
// +build unix // +build unix
// +build !linux !amd64,!loong64
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (
"bufio" "bufio"
// "encoding/hex" // "encoding/hex"
"io/ioutil"
"math" "math"
"math/rand" "math/rand"
"os" "os"
@ -117,10 +117,6 @@ func Xgethostname(t *TLS, name uintptr, slen types.Size_t) int32 {
if __ccgo_strace { if __ccgo_strace {
trc("t=%v name=%v slen=%v, (%v:)", t, name, slen, origin(2)) trc("t=%v name=%v slen=%v, (%v:)", t, name, slen, origin(2))
} }
if slen < 0 {
t.setErrno(errno.EINVAL)
return -1
}
if slen == 0 { if slen == 0 {
return 0 return 0
@ -298,7 +294,7 @@ func Xtmpfile(t *TLS) uintptr {
if __ccgo_strace { if __ccgo_strace {
trc("t=%v, (%v:)", t, origin(2)) trc("t=%v, (%v:)", t, origin(2))
} }
f, err := ioutil.TempFile("", "tmpfile-") f, err := os.CreateTemp("", "tmpfile-")
if err != nil { if err != nil {
t.setErrno(err) t.setErrno(err)
return 0 return 0
@ -317,7 +313,7 @@ func Xtmpfile(t *TLS) uintptr {
// FILE *fdopen(int fd, const char *mode); // FILE *fdopen(int fd, const char *mode);
func Xfdopen(t *TLS, fd int32, mode uintptr) uintptr { func Xfdopen(t *TLS, fd int32, mode uintptr) uintptr {
if __ccgo_strace { if __ccgo_strace {
trc("t=%v fd=%v mode=%v, (%v:)", t, fd, mode, origin(2)) trc("t=%v fd=%v mode=%v, (%v:)", t, fd, GoString(mode), origin(2))
} }
m := strings.ReplaceAll(GoString(mode), "b", "") m := strings.ReplaceAll(GoString(mode), "b", "")
switch m { switch m {
@ -333,12 +329,12 @@ func Xfdopen(t *TLS, fd int32, mode uintptr) uintptr {
return 0 return 0
} }
if p := newFile(t, fd); p != 0 { p := newFile(t, fd)
return p if p == 0 {
t.setErrno(errno.EINVAL)
return 0
} }
return p
t.setErrno(errno.EINVAL)
return 0
} }
// struct passwd *getpwnam(const char *name); // struct passwd *getpwnam(const char *name);
@ -587,11 +583,7 @@ func initPasswd2(t *TLS, buf uintptr, buflen types.Size_t, p *pwd.Passwd, name,
} }
p.Fpw_shell, buf, buflen = bufString(buf, buflen, shell) p.Fpw_shell, buf, buflen = bufString(buf, buflen, shell)
if buf == 0 { return buf != 0
return false
}
return true
} }
func bufString(buf uintptr, buflen types.Size_t, s string) (uintptr, uintptr, types.Size_t) { func bufString(buf uintptr, buflen types.Size_t, s string) (uintptr, uintptr, types.Size_t) {
@ -971,14 +963,16 @@ func Xuuid_unparse(t *TLS, uu, out uintptr) {
*(*byte)(unsafe.Pointer(out + uintptr(len(s)))) = 0 *(*byte)(unsafe.Pointer(out + uintptr(len(s)))) = 0
} }
var staticRandomData = &rand.Rand{} // no longer used?
// var staticRandomData = &rand.Rand{}
// char *initstate(unsigned seed, char *state, size_t size); // char *initstate(unsigned seed, char *state, size_t size);
func Xinitstate(t *TLS, seed uint32, statebuf uintptr, statelen types.Size_t) uintptr { func Xinitstate(t *TLS, seed uint32, statebuf uintptr, statelen types.Size_t) uintptr {
if __ccgo_strace { if __ccgo_strace {
trc("t=%v seed=%v statebuf=%v statelen=%v, (%v:)", t, seed, statebuf, statelen, origin(2)) trc("t=%v seed=%v statebuf=%v statelen=%v, (%v:)", t, seed, statebuf, statelen, origin(2))
} }
staticRandomData = rand.New(rand.NewSource(int64(seed))) // staticRandomData = rand.New(rand.NewSource(int64(seed)))
_ = rand.New(rand.NewSource(int64(seed)))
return 0 return 0
} }

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build unix && !illumos //go:build unix && !illumos && !(linux && (amd64 || loong64)) && !openbsd
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"

6
vendor/modernc.org/libc/mem.go generated vendored
View file

@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !libc.membrk && !libc.memgrind //go:build !libc.membrk && !libc.memgrind && !(linux && (amd64 || loong64))
// +build !libc.membrk,!libc.memgrind // +build !libc.membrk
// +build !libc.memgrind
// +build !linux !amd64,!loong64
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"

6
vendor/modernc.org/libc/mem_brk.go generated vendored
View file

@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build libc.membrk && !libc.memgrind //go:build libc.membrk && !libc.memgrind && !(linux && (amd64 || loong64))
// +build libc.membrk,!libc.memgrind // +build libc.membrk
// +build !libc.memgrind
// +build !linux !amd64,!loong64
// This is a debug-only version of the memory handling functions. When a // This is a debug-only version of the memory handling functions. When a
// program is built with -tags=libc.membrk a simple but safe version of malloc // program is built with -tags=libc.membrk a simple but safe version of malloc

305
vendor/modernc.org/libc/mem_brk_musl.go generated vendored Normal file
View file

@ -0,0 +1,305 @@
// Copyright 2023 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build libc.membrk && !libc.memgrind && linux && (amd64 || loong64)
// This is a debug-only version of the memory handling functions. When a
// program is built with -tags=libc.membrk a simple but safe version of malloc
// and friends is used that works like sbrk(2). Additionally free becomes a
// nop.
// The fixed heap is initially filled with random bytes from a full cycle PRNG,
// program startup time is substantially prolonged.
package libc // import "modernc.org/libc/v2"
import (
"fmt"
"math"
"math/bits"
"runtime"
"strings"
"time"
"unsafe"
"modernc.org/mathutil"
)
const (
isMemBrk = true
heapSize = 1 << 30
)
var (
brkIndex uintptr
heap [heapSize]byte
heapP uintptr
heap0 uintptr
heapRecords []heapRecord
heapUsable = map[uintptr]Tsize_t{}
heapFree = map[uintptr]struct{}{}
rng *mathutil.FC32
)
type heapRecord struct {
p uintptr
pc uintptr
}
func (r *heapRecord) String() string {
return fmt.Sprintf("[p=%#0x usable=%v pc=%s]", r.p, Xmalloc_usable_size(nil, r.p), pc2origin(r.pc))
}
func init() {
if roundup(heapGuard, heapAlign) != heapGuard {
panic("internal error")
}
heap0 = uintptr(unsafe.Pointer(&heap[0]))
heapP = roundup(heap0, heapAlign)
var err error
if rng, err = mathutil.NewFC32(math.MinInt32, math.MaxInt32, true); err != nil {
panic(err)
}
rng.Seed(time.Now().UnixNano())
for i := range heap {
heap[i] = byte(rng.Next())
}
}
func pc2origin(pc uintptr) string {
f := runtime.FuncForPC(pc)
var fn, fns string
var fl int
if f != nil {
fn, fl = f.FileLine(pc)
fns = f.Name()
if x := strings.LastIndex(fns, "."); x > 0 {
fns = fns[x+1:]
}
}
return fmt.Sprintf("%s:%d:%s", fn, fl, fns)
}
func malloc0(tls *TLS, pc uintptr, n0 Tsize_t, zero bool) (r uintptr) {
usable := roundup(uintptr(n0), heapAlign)
rq := usable + 2*heapGuard
if brkIndex+rq > uintptr(len(heap)) {
tls.setErrno(ENOMEM)
return 0
}
r, brkIndex = heapP+brkIndex, brkIndex+rq
heapRecords = append(heapRecords, heapRecord{p: r, pc: pc})
r += heapGuard
heapUsable[r] = Tsize_t(usable)
if zero {
n := uintptr(n0)
for i := uintptr(0); i < n; i++ {
*(*byte)(unsafe.Pointer(r + i)) = 0
}
}
return r
}
func Xmalloc(tls *TLS, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v n=%v, (%v:)", tls, n, origin(2))
defer func() { trc("-> %v", r) }()
}
if n > math.MaxInt {
tls.setErrno(ENOMEM)
return 0
}
if n == 0 {
// malloc(0) should return unique pointers
// (often expected and gnulib replaces malloc if malloc(0) returns 0)
n = 1
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
pc, _, _, _ := runtime.Caller(1)
return malloc0(tls, pc, n, false)
}
func Xcalloc(tls *TLS, m Tsize_t, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v m=%v n=%v, (%v:)", tls, m, n, origin(2))
defer func() { trc("-> %v", r) }()
}
hi, rq := bits.Mul(uint(m), uint(n))
if hi != 0 || rq > math.MaxInt {
tls.setErrno(ENOMEM)
return 0
}
if rq == 0 {
rq = 1
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
pc, _, _, _ := runtime.Caller(1)
return malloc0(tls, pc, Tsize_t(rq), true)
}
func Xrealloc(tls *TLS, p uintptr, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v p=%v n=%v, (%v:)", tls, p, n, origin(2))
defer func() { trc("-> %v", r) }()
}
if n == 0 {
Xfree(tls, p)
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
pc, _, _, _ := runtime.Caller(1)
if p == 0 {
return malloc0(tls, pc, n, false)
}
usable := heapUsable[p]
if usable == 0 {
panic(todo("realloc of unallocated memory: %#0x", p))
}
if usable >= n { // in place
return p
}
// malloc
r = malloc0(tls, pc, n, false)
copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), usable), unsafe.Slice((*byte)(unsafe.Pointer(p)), usable))
Xfree(tls, p)
return r
}
func Xfree(tls *TLS, p uintptr) {
if __ccgo_strace {
trc("tls=%v p=%v, (%v:)", tls, p, origin(2))
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
if p == 0 {
return
}
if _, ok := heapUsable[p]; !ok {
panic(todo("free of unallocated memory: %#0x", p))
}
if _, ok := heapFree[p]; ok {
panic(todo("double free: %#0x", p))
}
heapFree[p] = struct{}{}
}
func Xmalloc_usable_size(tls *TLS, p uintptr) (r Tsize_t) {
if __ccgo_strace {
trc("tls=%v p=%v, (%v:)", tls, p, origin(2))
defer func() { trc("-> %v", r) }()
}
if p == 0 {
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
return heapUsable[p]
}
func MemAudit() (r []*MemAuditError) {
allocatorMu.Lock()
defer allocatorMu.Unlock()
a := heapRecords
auditP := heap0
rng.Seek(0)
for _, v := range a {
heapP := v.p
mallocP := heapP + heapGuard
usable := heapUsable[mallocP]
for ; auditP < mallocP; auditP++ {
if g, e := *(*byte)(unsafe.Pointer(auditP)), byte(rng.Next()); g != e {
r = append(r, &MemAuditError{Caller: pc2origin(v.pc), Message: fmt.Sprintf("guard area before %#0x, %v is corrupted at %#0x, got %#02x, expected %#02x", mallocP, usable, auditP, g, e)})
}
}
for i := 0; Tsize_t(i) < usable; i++ {
rng.Next()
}
auditP = mallocP + uintptr(usable)
z := roundup(auditP, heapAlign)
z += heapGuard
for ; auditP < z; auditP++ {
if g, e := *(*byte)(unsafe.Pointer(auditP)), byte(rng.Next()); g != e {
r = append(r, &MemAuditError{Caller: pc2origin(v.pc), Message: fmt.Sprintf("guard area after %#0x, %v is corrupted at %#0x, got %#02x, expected %#02x", mallocP, usable, auditP, g, e)})
}
}
}
z := heap0 + uintptr(len(heap))
for ; auditP < z; auditP++ {
if g, e := *(*byte)(unsafe.Pointer(auditP)), byte(rng.Next()); g != e {
r = append(r, &MemAuditError{Caller: "-", Message: fmt.Sprintf("guard area after used heap is corrupted at %#0x, got %#02x, expected %#02x", auditP, g, e)})
return r // Report only the first fail
}
}
return r
}
func UsableSize(p uintptr) Tsize_t {
if p == 0 {
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
return heapUsable[p]
}
// MemAuditStart locks the memory allocator, initializes and enables memory
// auditing. Finaly it unlocks the memory allocator.
//
// Some memory handling errors, like double free or freeing of unallocated
// memory, will panic when memory auditing is enabled.
//
// This memory auditing functionality has to be enabled using the libc.memgrind
// build tag.
//
// It is intended only for debug/test builds. It slows down memory allocation
// routines and it has additional memory costs.
func MemAuditStart() {}
// MemAuditReport locks the memory allocator, reports memory leaks, if any.
// Finally it disables memory auditing and unlocks the memory allocator.
//
// This memory auditing functionality has to be enabled using the libc.memgrind
// build tag.
//
// It is intended only for debug/test builds. It slows down memory allocation
// routines and it has additional memory costs.
func MemAuditReport() error { return nil }

151
vendor/modernc.org/libc/mem_musl.go generated vendored Normal file
View file

@ -0,0 +1,151 @@
// Copyright 2023 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !libc.membrk && !libc.memgrind && linux && (amd64 || loong64)
package libc // import "modernc.org/libc/v2"
import (
"math"
"math/bits"
"modernc.org/memory"
)
const (
isMemBrk = false
)
func Xmalloc(tls *TLS, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v n=%v, (%v:)", tls, n, origin(2))
defer func() { trc("-> %v", r) }()
}
if n > math.MaxInt {
tls.setErrno(ENOMEM)
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
if n == 0 {
// malloc(0) should return unique pointers
// (often expected and gnulib replaces malloc if malloc(0) returns 0)
n = 1
}
var err error
if r, err = allocator.UintptrMalloc(int(n)); err != nil {
r = 0
tls.setErrno(ENOMEM)
}
return r
}
func Xcalloc(tls *TLS, m Tsize_t, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v m=%v n=%v, (%v:)", tls, m, n, origin(2))
defer func() { trc("-> %v", r) }()
}
hi, rq := bits.Mul(uint(m), uint(n))
if hi != 0 || rq > math.MaxInt {
tls.setErrno(ENOMEM)
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
if rq == 0 {
rq = 1
}
var err error
if r, err = allocator.UintptrCalloc(int(rq)); err != nil {
r = 0
tls.setErrno(ENOMEM)
}
return r
}
func Xrealloc(tls *TLS, p uintptr, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v p=%v n=%v, (%v:)", tls, p, n, origin(2))
defer func() { trc("-> %v", r) }()
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
var err error
if r, err = allocator.UintptrRealloc(p, int(n)); err != nil {
r = 0
tls.setErrno(ENOMEM)
}
return r
}
func Xfree(tls *TLS, p uintptr) {
if __ccgo_strace {
trc("tls=%v p=%v, (%v:)", tls, p, origin(2))
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
allocator.UintptrFree(p)
}
func Xmalloc_usable_size(tls *TLS, p uintptr) (r Tsize_t) {
if __ccgo_strace {
trc("tls=%v p=%v, (%v:)", tls, p, origin(2))
defer func() { trc("-> %v", r) }()
}
if p == 0 {
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
return Tsize_t(memory.UintptrUsableSize(p))
}
func MemAudit() (r []*MemAuditError) {
return nil
}
func UsableSize(p uintptr) Tsize_t {
allocatorMu.Lock()
defer allocatorMu.Unlock()
return Tsize_t(memory.UintptrUsableSize(p))
}
// MemAuditStart locks the memory allocator, initializes and enables memory
// auditing. Finaly it unlocks the memory allocator.
//
// Some memory handling errors, like double free or freeing of unallocated
// memory, will panic when memory auditing is enabled.
//
// This memory auditing functionality has to be enabled using the libc.memgrind
// build tag.
//
// It is intended only for debug/test builds. It slows down memory allocation
// routines and it has additional memory costs.
func MemAuditStart() {}
// MemAuditReport locks the memory allocator, reports memory leaks, if any.
// Finally it disables memory auditing and unlocks the memory allocator.
//
// This memory auditing functionality has to be enabled using the libc.memgrind
// build tag.
//
// It is intended only for debug/test builds. It slows down memory allocation
// routines and it has additional memory costs.
func MemAuditReport() error { return nil }

View file

@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !libc.membrk && libc.memgrind //go:build !libc.membrk && libc.memgrind && !(linux && (amd64 || loong64))
// +build !libc.membrk,libc.memgrind // +build !libc.membrk
// +build libc.memgrind
// +build !linux !amd64,!loong64
// This is a debug-only version of the memory handling functions. When a // This is a debug-only version of the memory handling functions. When a
// program is built with -tags=libc.memgrind the functions MemAuditStart and // program is built with -tags=libc.memgrind the functions MemAuditStart and

339
vendor/modernc.org/libc/memgrind_musl.go generated vendored Normal file
View file

@ -0,0 +1,339 @@
// Copyright 2021 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !libc.membrk && libc.memgrind && linux && (amd64 || loong64)
// This is a debug-only version of the memory handling functions. When a
// program is built with -tags=libc.memgrind the functions MemAuditStart and
// MemAuditReport can be used to check for memory leaks.
package libc // import "modernc.org/libc"
import (
"fmt"
"runtime"
"sort"
"strings"
"unsafe"
"modernc.org/memory"
)
const (
isMemBrk = false
memgrind = true
)
type memReportItem struct {
p, pc uintptr
s string
}
func (it *memReportItem) String() string {
more := it.s
if more != "" {
a := strings.Split(more, "\n")
more = "\n\t\t" + strings.Join(a, "\n\t\t")
}
return fmt.Sprintf("\t%s: %#x%s", pc2origin(it.pc), it.p, more)
}
type memReport []memReportItem
func (r memReport) Error() string {
a := []string{"memory leaks"}
for _, v := range r {
a = append(a, v.String())
}
return strings.Join(a, "\n")
}
var (
allocs map[uintptr]uintptr // addr: caller
allocsMore map[uintptr]string
frees map[uintptr]uintptr // addr: caller
memAudit memReport
memAuditEnabled bool
)
func pc2origin(pc uintptr) string {
f := runtime.FuncForPC(pc)
var fn, fns string
var fl int
if f != nil {
fn, fl = f.FileLine(pc)
fns = f.Name()
if x := strings.LastIndex(fns, "."); x > 0 {
fns = fns[x+1:]
}
}
return fmt.Sprintf("%s:%d:%s", fn, fl, fns)
}
// void *malloc(size_t size);
func Xmalloc(t *TLS, size Tsize_t) uintptr {
if __ccgo_strace {
trc("t=%v size=%v, (%v:)", t, size, origin(2))
}
if size == 0 {
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
p, err := allocator.UintptrCalloc(int(size))
// if dmesgs {
// dmesg("%v: %v -> %#x, %v", origin(1), size, p, err)
// }
if err != nil {
t.setErrno(ENOMEM)
return 0
}
if memAuditEnabled {
pc, _, _, ok := runtime.Caller(1)
if !ok {
panic("cannot obtain caller's PC")
}
delete(frees, p)
if pc0, ok := allocs[p]; ok {
dmesg("%v: malloc returns same address twice, previous call at %v:", pc2origin(pc), pc2origin(pc0))
panic(fmt.Errorf("%v: malloc returns same address twice, previous call at %v:", pc2origin(pc), pc2origin(pc0)))
}
allocs[p] = pc
}
return p
}
// void *calloc(size_t nmemb, size_t size);
func Xcalloc(t *TLS, n, size Tsize_t) uintptr {
if __ccgo_strace {
trc("t=%v size=%v, (%v:)", t, size, origin(2))
}
rq := int(n * size)
if rq == 0 {
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
p, err := allocator.UintptrCalloc(int(n * size))
// if dmesgs {
// dmesg("%v: %v -> %#x, %v", origin(1), n*size, p, err)
// }
if err != nil {
t.setErrno(ENOMEM)
return 0
}
if memAuditEnabled {
pc, _, _, ok := runtime.Caller(1)
if !ok {
panic("cannot obtain caller's PC")
}
delete(frees, p)
if pc0, ok := allocs[p]; ok {
dmesg("%v: calloc returns same address twice, previous call at %v:", pc2origin(pc), pc2origin(pc0))
panic(fmt.Errorf("%v: calloc returns same address twice, previous call at %v:", pc2origin(pc), pc2origin(pc0)))
}
allocs[p] = pc
}
return p
}
// void *realloc(void *ptr, size_t size);
func Xrealloc(t *TLS, ptr uintptr, size Tsize_t) uintptr {
if __ccgo_strace {
trc("t=%v ptr=%v size=%v, (%v:)", t, ptr, size, origin(2))
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
var pc uintptr
if memAuditEnabled {
var ok bool
if pc, _, _, ok = runtime.Caller(1); !ok {
panic("cannot obtain caller's PC")
}
if ptr != 0 {
if pc0, ok := frees[ptr]; ok {
dmesg("%v: realloc: double free of %#x, previous call at %v:", pc2origin(pc), ptr, pc2origin(pc0))
panic(fmt.Errorf("%v: realloc: double free of %#x, previous call at %v:", pc2origin(pc), ptr, pc2origin(pc0)))
}
if _, ok := allocs[ptr]; !ok {
dmesg("%v: %v: realloc, free of unallocated memory: %#x", origin(1), pc2origin(pc), ptr)
panic(fmt.Errorf("%v: realloc, free of unallocated memory: %#x", pc2origin(pc), ptr))
}
delete(allocs, ptr)
delete(allocsMore, ptr)
frees[ptr] = pc
}
}
p, err := allocator.UintptrRealloc(ptr, int(size))
// if dmesgs {
// dmesg("%v: %#x, %v -> %#x, %v", origin(1), ptr, size, p, err)
// }
if err != nil {
t.setErrno(ENOMEM)
return 0
}
if memAuditEnabled && p != 0 {
delete(frees, p)
if pc0, ok := allocs[p]; ok {
dmesg("%v: realloc returns same address twice, previous call at %v:", pc2origin(pc), pc2origin(pc0))
panic(fmt.Errorf("%v: realloc returns same address twice, previous call at %v:", pc2origin(pc), pc2origin(pc0)))
}
allocs[p] = pc
}
return p
}
// void free(void *ptr);
func Xfree(t *TLS, p uintptr) {
if __ccgo_strace {
trc("t=%v p=%v, (%v:)", t, p, origin(2))
}
if p == 0 {
return
}
// if dmesgs {
// dmesg("%v: %#x", origin(1), p)
// }
allocatorMu.Lock()
defer allocatorMu.Unlock()
sz := memory.UintptrUsableSize(p)
if memAuditEnabled {
pc, _, _, ok := runtime.Caller(1)
if !ok {
panic("cannot obtain caller's PC")
}
if pc0, ok := frees[p]; ok {
dmesg("%v: double free of %#x, previous call at %v:", pc2origin(pc), p, pc2origin(pc0))
panic(fmt.Errorf("%v: double free of %#x, previous call at %v:", pc2origin(pc), p, pc2origin(pc0)))
}
if _, ok := allocs[p]; !ok {
dmesg("%v: free of unallocated memory: %#x", pc2origin(pc), p)
panic(fmt.Errorf("%v: free of unallocated memory: %#x", pc2origin(pc), p))
}
delete(allocs, p)
delete(allocsMore, p)
frees[p] = pc
}
for i := uintptr(0); i < uintptr(sz); i++ {
*(*byte)(unsafe.Pointer(p + i)) = 0
}
allocator.UintptrFree(p)
}
func UsableSize(p uintptr) Tsize_t {
allocatorMu.Lock()
defer allocatorMu.Unlock()
if memAuditEnabled {
pc, _, _, ok := runtime.Caller(1)
if !ok {
panic("cannot obtain caller's PC")
}
if _, ok := allocs[p]; !ok {
dmesg("%v: usable size of unallocated memory: %#x", pc2origin(pc), p)
panic(fmt.Errorf("%v: usable size of unallocated memory: %#x", pc2origin(pc), p))
}
}
return Tsize_t(memory.UintptrUsableSize(p))
}
func Xmalloc_usable_size(tls *TLS, p uintptr) (r Tsize_t) {
return UsableSize(p)
}
// MemAuditStart locks the memory allocator, initializes and enables memory
// auditing. Finally it unlocks the memory allocator.
//
// Some memory handling errors, like double free or freeing of unallocated
// memory, will panic when memory auditing is enabled.
//
// This memory auditing functionality has to be enabled using the libc.memgrind
// build tag.
//
// It is intended only for debug/test builds. It slows down memory allocation
// routines and it has additional memory costs.
func MemAuditStart() {
allocatorMu.Lock()
defer allocatorMu.Unlock()
allocs = map[uintptr]uintptr{} // addr: caller
allocsMore = map[uintptr]string{}
frees = map[uintptr]uintptr{} // addr: caller
memAuditEnabled = true
}
// MemAuditReport locks the memory allocator, reports memory leaks, if any.
// Finally it disables memory auditing and unlocks the memory allocator.
//
// This memory auditing functionality has to be enabled using the libc.memgrind
// build tag.
//
// It is intended only for debug/test builds. It slows down memory allocation
// routines and it has additional memory costs.
func MemAuditReport() (r error) {
allocatorMu.Lock()
defer func() {
allocs = nil
allocsMore = nil
frees = nil
memAuditEnabled = false
memAudit = nil
allocatorMu.Unlock()
}()
if len(allocs) != 0 {
for p, pc := range allocs {
memAudit = append(memAudit, memReportItem{p, pc, allocsMore[p]})
}
sort.Slice(memAudit, func(i, j int) bool {
return memAudit[i].String() < memAudit[j].String()
})
return memAudit
}
return nil
}
func MemAuditAnnotate(pc uintptr, s string) {
allocatorMu.Lock()
allocsMore[pc] = s
allocatorMu.Unlock()
}
func MemAudit() (r []*MemAuditError) {
return nil
}

View file

@ -1,5 +1,7 @@
// Code generated by 'ccgo -export-externs X -hide __syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6 -nostdinc -nostdlib -o ../musl_linux_amd64.go -pkgname libc -static-locals-prefix _s -Iarch/x86_64 -Iarch/generic -Iobj/src/internal -Isrc/include -Isrc/internal -Iobj/include -Iinclude copyright.c src/ctype/__ctype_b_loc.c src/ctype/isalnum.c src/ctype/isalpha.c src/ctype/isdigit.c src/ctype/islower.c src/ctype/isprint.c src/ctype/isupper.c src/ctype/isxdigit.c src/dirent/closedir.c src/dirent/opendir.c src/dirent/readdir.c src/internal/floatscan.c src/internal/intscan.c src/internal/shgetc.c src/locale/localeconv.c src/math/__fpclassify.c src/math/__fpclassifyf.c src/math/__fpclassifyl.c src/math/copysignl.c src/math/fabsl.c src/math/fmodl.c src/math/nanf.c src/math/rint.c src/math/scalbn.c src/math/scalbnl.c src/multibyte/internal.c src/multibyte/mbrtowc.c src/multibyte/mbsinit.c src/network/freeaddrinfo.c src/network/getaddrinfo.c src/network/gethostbyaddr.c src/network/gethostbyaddr_r.c src/network/gethostbyname.c src/network/gethostbyname2.c src/network/gethostbyname2_r.c src/network/gethostbyname_r.c src/network/getnameinfo.c src/network/h_errno.c src/network/inet_aton.c src/network/inet_ntop.c src/network/inet_pton.c src/network/lookup_ipliteral.c src/network/lookup_name.c src/network/lookup_serv.c src/prng/rand_r.c src/stdio/__lockfile.c src/stdio/__toread.c src/stdio/__uflow.c src/stdio/sscanf.c src/stdio/vfscanf.c src/stdio/vsscanf.c src/stdlib/bsearch.c src/stdlib/strtod.c src/stdlib/strtol.c src/string/strdup.c src/string/strlcat.c src/string/strlcpy.c src/string/strncasecmp.c src/string/strncat.c src/string/strnlen.c src/string/strspn.c src/string/strtok.c src/thread/pthread_attr_get.c src/thread/pthread_attr_setdetachstate.c src/thread/pthread_mutex_lock.c src/thread/pthread_mutexattr_destroy.c src/thread/pthread_mutexattr_init.c src/thread/pthread_mutexattr_settype.c', DO NOT EDIT. // Code generated by 'ccgo -export-externs X -hide __syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6 -nostdinc -nostdlib -o ../musl_linux_amd64.go -pkgname libc -static-locals-prefix _s -Iarch/x86_64 -Iarch/generic -Iobj/src/internal -Isrc/include -Isrc/internal -Iobj/include -Iinclude copyright.c src/ctype/__ctype_b_loc.c src/ctype/isalnum.c src/ctype/isalpha.c src/ctype/isdigit.c src/ctype/islower.c src/ctype/isprint.c src/ctype/isupper.c src/ctype/isxdigit.c src/dirent/closedir.c src/dirent/opendir.c src/dirent/readdir.c src/internal/floatscan.c src/internal/intscan.c src/internal/shgetc.c src/locale/localeconv.c src/math/__fpclassify.c src/math/__fpclassifyf.c src/math/__fpclassifyl.c src/math/copysignl.c src/math/fabsl.c src/math/fmodl.c src/math/nanf.c src/math/rint.c src/math/scalbn.c src/math/scalbnl.c src/multibyte/internal.c src/multibyte/mbrtowc.c src/multibyte/mbsinit.c src/network/freeaddrinfo.c src/network/getaddrinfo.c src/network/gethostbyaddr.c src/network/gethostbyaddr_r.c src/network/gethostbyname.c src/network/gethostbyname2.c src/network/gethostbyname2_r.c src/network/gethostbyname_r.c src/network/getnameinfo.c src/network/h_errno.c src/network/inet_aton.c src/network/inet_ntop.c src/network/inet_pton.c src/network/lookup_ipliteral.c src/network/lookup_name.c src/network/lookup_serv.c src/prng/rand_r.c src/stdio/__lockfile.c src/stdio/__toread.c src/stdio/__uflow.c src/stdio/sscanf.c src/stdio/vfscanf.c src/stdio/vsscanf.c src/stdlib/bsearch.c src/stdlib/strtod.c src/stdlib/strtol.c src/string/strdup.c src/string/strlcat.c src/string/strlcpy.c src/string/strncasecmp.c src/string/strncat.c src/string/strnlen.c src/string/strspn.c src/string/strtok.c src/thread/pthread_attr_get.c src/thread/pthread_attr_setdetachstate.c src/thread/pthread_mutex_lock.c src/thread/pthread_mutexattr_destroy.c src/thread/pthread_mutexattr_init.c src/thread/pthread_mutexattr_settype.c', DO NOT EDIT.
//go:build !(linux && amd64)
package libc package libc
import ( import (

File diff suppressed because it is too large Load diff

2
vendor/modernc.org/libc/printf.go generated vendored
View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

27
vendor/modernc.org/libc/pthread.go generated vendored
View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (
@ -37,6 +39,7 @@ type TLS struct {
errnop uintptr errnop uintptr
allocaStack [][]uintptr allocaStack [][]uintptr
allocas []uintptr allocas []uintptr
jumpBuffers []uintptr
pthreadData pthreadData
stack stackHeader stack stackHeader
@ -82,6 +85,29 @@ func (t *TLS) FreeAlloca() func() {
} }
} }
func (tls *TLS) PushJumpBuffer(jb uintptr) {
tls.jumpBuffers = append(tls.jumpBuffers, jb)
}
type LongjmpRetval int32
func (tls *TLS) PopJumpBuffer(jb uintptr) {
n := len(tls.jumpBuffers)
if n == 0 || tls.jumpBuffers[n-1] != jb {
panic(todo("unsupported setjmp/longjmp usage"))
}
tls.jumpBuffers = tls.jumpBuffers[:n-1]
}
func (tls *TLS) Longjmp(jb uintptr, val int32) {
tls.PopJumpBuffer(jb)
if val == 0 {
val = 1
}
panic(LongjmpRetval(val))
}
func Xalloca(tls *TLS, size size_t) uintptr { func Xalloca(tls *TLS, size size_t) uintptr {
if __ccgo_strace { if __ccgo_strace {
trc("tls=%v size=%v, (%v:)", tls, size, origin(2)) trc("tls=%v size=%v, (%v:)", tls, size, origin(2))
@ -420,6 +446,7 @@ func (m *mutex) lock(id int32) int32 {
m.Unlock() m.Unlock()
m.wait.Lock() m.wait.Lock()
// intentional empty section - wake up other waiters
m.wait.Unlock() m.wait.Unlock()
} }
default: default:

View file

@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !freebsd && !openbsd //go:build !freebsd && !openbsd && !(linux && (amd64 || loong64))
// +build !freebsd,!openbsd // +build !freebsd
// +build !openbsd
// +build !linux !amd64,!loong64
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"

508
vendor/modernc.org/libc/pthread_musl.go generated vendored Normal file
View file

@ -0,0 +1,508 @@
// Copyright 2024 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && (amd64 || loong64)
package libc // import "modernc.org/libc"
import (
"runtime"
"slices"
"sync"
"sync/atomic"
"time"
"unsafe"
)
type pthreadAttr struct {
detachState int32
}
type pthreadCleanupItem struct {
routine, arg uintptr
}
// C version is 40 bytes.
type pthreadMutex struct {
sync.Mutex // 0 8
count int32 // 8 4
mType uint32 // 12 4
outer sync.Mutex // 16 8
owner int32 // 20 4
// 24
}
type pthreadConds struct {
sync.Mutex
conds map[uintptr][]chan struct{}
}
var (
// Ensure there's enough space for unsafe type conversions.
_ [unsafe.Sizeof(sync.Mutex{}) - __CCGO_SIZEOF_GO_MUTEX]byte
_ [unsafe.Sizeof(Tpthread_mutex_t{}) - unsafe.Sizeof(pthreadMutex{})]byte
_ [unsafe.Sizeof(Tpthread_attr_t{}) - unsafe.Sizeof(pthreadAttr{})]byte
pthreadKeysMutex sync.Mutex
pthreadKeyDestructors []uintptr
pthreadKeysFree []Tpthread_key_t
conds = pthreadConds{conds: map[uintptr][]chan struct{}{}}
)
func _pthread_setcancelstate(tls *TLS, new int32, old uintptr) int32 {
//TODO actually respect cancel state
if uint32(new) > 2 {
return EINVAL
}
p := tls.pthread + unsafe.Offsetof(t__pthread{}.Fcanceldisable)
if old != 0 {
r := *(*int32)(unsafe.Pointer(p))
*(*int32)(unsafe.Pointer(old)) = int32(byte(r))
}
*(*int32)(unsafe.Pointer(p)) = new
return 0
}
func Xpthread_getspecific(tls *TLS, k Tpthread_key_t) uintptr {
return tls.pthreadKeyValues[k]
}
func Xpthread_setspecific(tls *TLS, k Tpthread_key_t, x uintptr) int32 {
if tls.pthreadKeyValues == nil {
tls.pthreadKeyValues = map[Tpthread_key_t]uintptr{}
}
tls.pthreadKeyValues[k] = x
return 0
}
func Xpthread_key_create(tls *TLS, k uintptr, dtor uintptr) int32 {
pthreadKeysMutex.Lock()
defer pthreadKeysMutex.Unlock()
var key Tpthread_key_t
switch l := Tpthread_key_t(len(pthreadKeysFree)); {
case l == 0:
key = Tpthread_key_t(len(pthreadKeyDestructors))
pthreadKeyDestructors = append(pthreadKeyDestructors, dtor)
default:
key = pthreadKeysFree[l-1]
pthreadKeysFree = pthreadKeysFree[:l-1]
pthreadKeyDestructors[key] = dtor
}
*(*Tpthread_key_t)(unsafe.Pointer(k)) = key
return 0
}
func Xpthread_key_delete(tls *TLS, k Tpthread_key_t) int32 {
pthreadKeysMutex.Lock()
defer pthreadKeysMutex.Unlock()
pthreadKeysFree = append(pthreadKeysFree, k)
return 0
}
func Xpthread_create(tls *TLS, res, attrp, entry, arg uintptr) int32 {
var attr pthreadAttr
if attrp != 0 {
attr = *(*pthreadAttr)(unsafe.Pointer(attrp))
}
detachState := int32(_DT_JOINABLE)
if attr.detachState != 0 {
detachState = _DT_DETACHED
}
tls2 := NewTLS()
tls2.ownsPthread = false
*(*Tpthread_t)(unsafe.Pointer(res)) = tls2.pthread
(*t__pthread)(unsafe.Pointer(tls2.pthread)).Fdetach_state = detachState
if detachState == _DT_JOINABLE {
(*sync.Mutex)(unsafe.Pointer(tls2.pthread + unsafe.Offsetof(t__pthread{}.F__ccgo_join_mutex))).Lock()
}
go func() {
Xpthread_exit(tls2, (*(*func(*TLS, uintptr) uintptr)(unsafe.Pointer(&struct{ uintptr }{entry})))(tls2, arg))
}()
return 0
}
func Xpthread_exit(tls *TLS, result uintptr) {
state := atomic.LoadInt32((*int32)(unsafe.Pointer(tls.pthread + unsafe.Offsetof(t__pthread{}.Fdetach_state))))
(*t__pthread)(unsafe.Pointer(tls.pthread)).Fresult = result
switch state {
case _DT_JOINABLE, _DT_DETACHED:
// ok
default:
panic(todo("", state))
}
for len(tls.pthreadCleanupItems) != 0 {
Xpthread_cleanup_pop(tls, 1)
}
for {
done := true
for k, v := range tls.pthreadKeyValues {
if v != 0 {
delete(tls.pthreadKeyValues, k)
pthreadKeysMutex.Lock()
d := pthreadKeyDestructors[k]
pthreadKeysMutex.Unlock()
if d != 0 {
done = false
(*(*func(*TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{d})))(tls, v)
}
}
}
if done {
break
}
}
if state == _DT_JOINABLE {
(*sync.Mutex)(unsafe.Pointer(tls.pthread + unsafe.Offsetof(t__pthread{}.F__ccgo_join_mutex))).Unlock()
}
atomic.StoreInt32((*int32)(unsafe.Pointer(tls.pthread+unsafe.Offsetof(t__pthread{}.Fdetach_state))), _DT_EXITED)
tls.Close()
runtime.Goexit()
}
func Xpthread_join(tls *TLS, t Tpthread_t, res uintptr) (r int32) {
if (*t__pthread)(unsafe.Pointer(t)).Fdetach_state > _DT_JOINABLE {
return EINVAL
}
(*sync.Mutex)(unsafe.Pointer(t + unsafe.Offsetof(t__pthread{}.F__ccgo_join_mutex))).Lock()
if res != 0 {
*(*uintptr)(unsafe.Pointer(res)) = (*t__pthread)(unsafe.Pointer(tls.pthread)).Fresult
}
return 0
}
func Xpthread_cleanup_push(tls *TLS, f, x uintptr) {
X_pthread_cleanup_push(tls, 0, f, x)
}
func __pthread_cleanup_push(tls *TLS, _, f, x uintptr) {
tls.pthreadCleanupItems = append(tls.pthreadCleanupItems, pthreadCleanupItem{f, x})
}
func X_pthread_cleanup_push(tls *TLS, _, f, x uintptr) {
tls.pthreadCleanupItems = append(tls.pthreadCleanupItems, pthreadCleanupItem{f, x})
}
func Xpthread_cleanup_pop(tls *TLS, run int32) {
X_pthread_cleanup_pop(tls, 0, run)
}
func __pthread_cleanup_pop(tls *TLS, _ uintptr, run int32) {
X_pthread_cleanup_pop(tls, 0, run)
}
func X_pthread_cleanup_pop(tls *TLS, _ uintptr, run int32) {
l := len(tls.pthreadCleanupItems)
item := tls.pthreadCleanupItems[l-1]
tls.pthreadCleanupItems = tls.pthreadCleanupItems[:l-1]
if run != 0 {
(*(*func(*TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{item.routine})))(tls, item.arg)
}
}
func Xpthread_attr_init(tls *TLS, a uintptr) int32 {
*(*Tpthread_attr_t)(unsafe.Pointer(a)) = Tpthread_attr_t{}
return 0
}
func Xpthread_attr_setscope(tls *TLS, a uintptr, scope int32) int32 {
switch scope {
case PTHREAD_SCOPE_SYSTEM:
return 0
case PTHREAD_SCOPE_PROCESS:
return ENOTSUP
default:
return EINVAL
}
}
func Xpthread_attr_setstacksize(tls *TLS, a uintptr, stacksite Tsize_t) int32 {
return 0
}
func Xpthread_attr_setdetachstate(tls *TLS, a uintptr, state int32) (r int32) {
if uint32(state) > 1 {
return EINVAL
}
(*pthreadAttr)(unsafe.Pointer(a)).detachState = state
return 0
}
func Xpthread_attr_getdetachstate(tls *TLS, a uintptr, state uintptr) int32 {
*(*int32)(unsafe.Pointer(state)) = (*pthreadAttr)(unsafe.Pointer(a)).detachState
return 0
}
func Xpthread_attr_destroy(tls *TLS, a uintptr) int32 {
return 0
}
func Xpthread_self(tls *TLS) uintptr {
return tls.pthread
}
func Xpthread_mutex_init(tls *TLS, m, a uintptr) int32 {
*(*Tpthread_mutex_t)(unsafe.Pointer(m)) = Tpthread_mutex_t{}
if a != 0 {
(*pthreadMutex)(unsafe.Pointer(m)).mType = (*Tpthread_mutexattr_t)(unsafe.Pointer(a)).F__attr
}
return 0
}
func Xpthread_mutex_destroy(tls *TLS, mutex uintptr) int32 {
return 0
}
func Xpthread_mutex_lock(tls *TLS, m uintptr) int32 {
(*pthreadMutex)(unsafe.Pointer(m)).outer.Lock()
owner := (*pthreadMutex)(unsafe.Pointer(m)).owner
typ := (*pthreadMutex)(unsafe.Pointer(m)).mType
switch typ {
case PTHREAD_MUTEX_NORMAL:
(*pthreadMutex)(unsafe.Pointer(m)).owner = tls.ID
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
(*pthreadMutex)(unsafe.Pointer(m)).Lock()
case PTHREAD_MUTEX_RECURSIVE:
switch owner {
case 0:
(*pthreadMutex)(unsafe.Pointer(m)).count = 1
(*pthreadMutex)(unsafe.Pointer(m)).owner = tls.ID
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
(*pthreadMutex)(unsafe.Pointer(m)).Lock()
return 0
case tls.ID:
(*pthreadMutex)(unsafe.Pointer(m)).count++
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
return 0
default:
wait:
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
(*pthreadMutex)(unsafe.Pointer(m)).Lock()
(*pthreadMutex)(unsafe.Pointer(m)).outer.Lock()
if (*pthreadMutex)(unsafe.Pointer(m)).owner != 0 {
goto wait
}
(*pthreadMutex)(unsafe.Pointer(m)).count = 1
(*pthreadMutex)(unsafe.Pointer(m)).owner = tls.ID
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
return 0
}
default:
panic(todo("typ=%v", typ))
}
return 0
}
func Xpthread_mutex_trylock(tls *TLS, m uintptr) int32 {
(*pthreadMutex)(unsafe.Pointer(m)).outer.Lock()
owner := (*pthreadMutex)(unsafe.Pointer(m)).owner
typ := (*pthreadMutex)(unsafe.Pointer(m)).mType
switch typ {
case PTHREAD_MUTEX_NORMAL:
if owner != 0 {
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
return EBUSY
}
(*pthreadMutex)(unsafe.Pointer(m)).owner = tls.ID
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
(*pthreadMutex)(unsafe.Pointer(m)).Lock()
return 0
default:
panic(todo("typ=%v", typ))
}
}
func Xpthread_mutex_unlock(tls *TLS, m uintptr) int32 {
(*pthreadMutex)(unsafe.Pointer(m)).outer.Lock()
count := (*pthreadMutex)(unsafe.Pointer(m)).count
owner := (*pthreadMutex)(unsafe.Pointer(m)).owner
typ := (*pthreadMutex)(unsafe.Pointer(m)).mType
switch typ {
case PTHREAD_MUTEX_NORMAL:
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
(*pthreadMutex)(unsafe.Pointer(m)).Unlock()
return 0
case PTHREAD_MUTEX_RECURSIVE:
switch owner {
case tls.ID:
switch count {
case 1:
(*pthreadMutex)(unsafe.Pointer(m)).owner = 0
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
(*pthreadMutex)(unsafe.Pointer(m)).Unlock()
return 0
default:
(*pthreadMutex)(unsafe.Pointer(m)).count--
(*pthreadMutex)(unsafe.Pointer(m)).outer.Unlock()
return 0
}
default:
panic(todo("", owner, tls.ID))
}
default:
panic(todo("", typ))
}
}
func Xpthread_cond_init(tls *TLS, c, a uintptr) int32 {
*(*Tpthread_cond_t)(unsafe.Pointer(c)) = Tpthread_cond_t{}
if a != 0 {
panic(todo(""))
}
conds.Lock()
delete(conds.conds, c)
conds.Unlock()
return 0
}
func Xpthread_cond_timedwait(tls *TLS, c, m, ts uintptr) (r int32) {
var to <-chan time.Time
if ts != 0 {
deadlineSecs := (*Ttimespec)(unsafe.Pointer(ts)).Ftv_sec
deadlineNsecs := (*Ttimespec)(unsafe.Pointer(ts)).Ftv_nsec
deadline := time.Unix(deadlineSecs, deadlineNsecs)
d := deadline.Sub(time.Now())
if d <= 0 {
return ETIMEDOUT
}
to = time.After(d)
}
conds.Lock()
waiters := conds.conds[c]
ch := make(chan struct{}, 1)
waiters = append(waiters, ch)
conds.conds[c] = waiters
conds.Unlock()
defer func() {
conds.Lock()
defer conds.Unlock()
waiters = conds.conds[c]
for i, v := range waiters {
if v == ch {
conds.conds[c] = slices.Delete(waiters, i, i+1)
return
}
}
}()
switch typ := (*pthreadMutex)(unsafe.Pointer(m)).mType; typ {
case PTHREAD_MUTEX_NORMAL:
(*pthreadMutex)(unsafe.Pointer(m)).owner = 0
(*pthreadMutex)(unsafe.Pointer(m)).Unlock()
select {
case <-ch:
// ok
case <-to:
r = ETIMEDOUT
}
(*pthreadMutex)(unsafe.Pointer(m)).owner = tls.ID
(*pthreadMutex)(unsafe.Pointer(m)).Lock()
return r
default:
panic(todo("", typ))
}
}
func Xpthread_cond_wait(tls *TLS, c, m uintptr) int32 {
return Xpthread_cond_timedwait(tls, c, m, 0)
}
func Xpthread_cond_signal(tls *TLS, c uintptr) int32 {
return pthreadSignalN(tls, c, false)
}
func pthreadSignalN(tls *TLS, c uintptr, all bool) int32 {
conds.Lock()
waiters := conds.conds[c]
handle := waiters
if len(waiters) != 0 {
switch {
case all:
delete(conds.conds, c)
default:
handle = handle[:1]
conds.conds[c] = waiters[1:]
}
}
conds.Unlock()
for _, v := range handle {
close(v)
}
return 0
}
func Xpthread_cond_broadcast(tls *TLS, c uintptr) int32 {
return pthreadSignalN(tls, c, true)
}
func Xpthread_cond_destroy(tls *TLS, c uintptr) int32 {
return Xpthread_cond_broadcast(tls, c)
}
func Xpthread_atfork(tls *TLS, prepare, parent, child uintptr) int32 {
// fork(2) not supported.
return 0
}
func Xpthread_mutexattr_init(tls *TLS, a uintptr) int32 {
*(*Tpthread_mutexattr_t)(unsafe.Pointer(a)) = Tpthread_mutexattr_t{}
return 0
}
func Xpthread_mutexattr_destroy(tls *TLS, a uintptr) int32 {
return 0
}
func Xpthread_mutexattr_settype(tls *TLS, a uintptr, typ int32) int32 {
if uint32(typ) > 2 {
return EINVAL
}
(*Tpthread_mutexattr_t)(unsafe.Pointer(a)).F__attr = uint32(typ) & 3
return 0
}
func Xpthread_detach(tls *TLS, t uintptr) int32 {
state := atomic.SwapInt32((*int32)(unsafe.Pointer(tls.pthread+unsafe.Offsetof(t__pthread{}.Fdetach_state))), _DT_DETACHED)
switch state {
case _DT_EXITED, _DT_DETACHED:
return 0
default:
panic(todo("", tls.ID, state))
}
}
// int pthread_equal(pthread_t, pthread_t);
func Xpthread_equal(tls *TLS, t, u uintptr) int32 {
return Bool32(t == u)
}
// int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict old)
func _pthread_sigmask(tls *TLS, now int32, set, old uintptr) int32 {
// ignored
return 0
}
// 202402251838 all_test.go:589: files=36 buildFails=30 execFails=2 pass=4
// 202402262246 all_test.go:589: files=36 buildFails=26 execFails=2 pass=8
// 202403041858 all_musl_test.go:640: files=36 buildFails=22 execFails=4 pass=10

2200
vendor/modernc.org/libc/rtl.go generated vendored Normal file

File diff suppressed because it is too large Load diff

2
vendor/modernc.org/libc/scanf.go generated vendored
View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

9305
vendor/modernc.org/libc/surface.new generated vendored Normal file

File diff suppressed because it is too large Load diff

9184
vendor/modernc.org/libc/surface.old generated vendored Normal file

File diff suppressed because it is too large Load diff

2
vendor/modernc.org/libc/sync.go generated vendored
View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(linux && (amd64 || loong64))
package libc // import "modernc.org/libc" package libc // import "modernc.org/libc"
import ( import (

90
vendor/modernc.org/libc/syscall_musl.go generated vendored Normal file
View file

@ -0,0 +1,90 @@
// Copyright 2024 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && (amd64 || loong64)
package libc // import "modernc.org/libc"
import (
"runtime"
"syscall"
)
func ___syscall_cp(tls *TLS, n, a, b, c, d, e, f long) long {
r1, _, err := (syscall.Syscall6(uintptr(n), uintptr(a), uintptr(b), uintptr(c), uintptr(d), uintptr(e), uintptr(f)))
if err != 0 {
return long(-err)
}
return long(r1)
}
func X__syscall0(tls *TLS, n long) long {
switch n {
case __NR_sched_yield:
runtime.Gosched()
return 0
default:
r1, _, err := syscall.Syscall(uintptr(n), 0, 0, 0)
if err != 0 {
return long(-err)
}
return long(r1)
}
}
func X__syscall1(tls *TLS, n, a1 long) long {
r1, _, err := syscall.Syscall(uintptr(n), uintptr(a1), 0, 0)
if err != 0 {
return long(-err)
}
return long(r1)
}
func X__syscall2(tls *TLS, n, a1, a2 long) long {
r1, _, err := syscall.Syscall(uintptr(n), uintptr(a1), uintptr(a2), 0)
if err != 0 {
return long(-err)
}
return long(r1)
}
func X__syscall3(tls *TLS, n, a1, a2, a3 long) long {
r1, _, err := syscall.Syscall(uintptr(n), uintptr(a1), uintptr(a2), uintptr(a3))
if err != 0 {
return long(-err)
}
return long(r1)
}
func X__syscall4(tls *TLS, n, a1, a2, a3, a4 long) long {
r1, _, err := syscall.Syscall6(uintptr(n), uintptr(a1), uintptr(a2), uintptr(a3), uintptr(a4), 0, 0)
if err != 0 {
return long(-err)
}
return long(r1)
}
func X__syscall5(tls *TLS, n, a1, a2, a3, a4, a5 long) long {
r1, _, err := syscall.Syscall6(uintptr(n), uintptr(a1), uintptr(a2), uintptr(a3), uintptr(a4), uintptr(a5), 0)
if err != 0 {
return long(-err)
}
return long(r1)
}
func X__syscall6(tls *TLS, n, a1, a2, a3, a4, a5, a6 long) long {
r1, _, err := syscall.Syscall6(uintptr(n), uintptr(a1), uintptr(a2), uintptr(a3), uintptr(a4), uintptr(a5), uintptr(a6))
if err != 0 {
return long(-err)
}
return long(r1)
}

5
vendor/modernc.org/libc/unconvert.sh generated vendored Normal file
View file

@ -0,0 +1,5 @@
set -evx
until unconvert -fastmath ./...
do
unconvert -fastmath -apply ./...
done

5
vendor/modernc.org/memory/AUTHORS generated vendored
View file

@ -8,6 +8,7 @@
# #
# Please keep the list sorted. # Please keep the list sorted.
Jan Mercl <0xjnml@gmail.com>
Steffen Butzer <steffen(dot)butzer@outlook.com>
Gleb Sakhnov <gleb.sakhnov@gmail.com> Gleb Sakhnov <gleb.sakhnov@gmail.com>
Jan Mercl <0xjnml@gmail.com>
Scot C Bontrager <scot@indievisible.org>
Steffen Butzer <steffen(dot)butzer@outlook.com>

View file

@ -7,7 +7,8 @@
# Please keep the list sorted. # Please keep the list sorted.
Anup Kodlekere <anup.kodlekere@ibm.com> Anup Kodlekere <anup.kodlekere@ibm.com>
Gleb Sakhnov <gleb.sakhnov@gmail.com>
Jan Mercl <0xjnml@gmail.com> Jan Mercl <0xjnml@gmail.com>
Scot C Bontrager <scot@indievisible.org>
Steffen Butzer <steffen(dot)butzer@outlook.com> Steffen Butzer <steffen(dot)butzer@outlook.com>
ZHU Zijia <piggynl@outlook.com> ZHU Zijia <piggynl@outlook.com>
Gleb Sakhnov <gleb.sakhnov@gmail.com>

6
vendor/modernc.org/memory/builder.json generated vendored Normal file
View file

@ -0,0 +1,6 @@
{
"autogen": "none",
"autotag": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/amd64|windows/(amd64|arm64)",
"autoupdate": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/amd64|windows/(amd64|arm64)",
"test": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/amd64|windows/(amd64|arm64)"
}

View file

@ -1,19 +1,97 @@
// Copyright 2017 The Memory Authors. All rights reserved. // Copyright 2011 Evan Shaw. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE-MMAP-GO file.
// Modifications (c) 2024 The Memory Authors.
// Copyright 2024 The Memory Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build 386 || amd64 || arm64 //go:build openbsd && (386 || amd64 || arm64)
// +build 386 amd64 arm64
package memory package memory
import ( import (
_ "unsafe" "fmt"
"os"
"sync"
"unsafe"
"golang.org/x/sys/unix"
) )
// Function syscall.mmap for darwin and openbsd calls internal/abi.FuncPCABI0, // track what can be unmapped
// which is implemented as a compile intrinsic so the code cannot be reused. var allocmap map[uintptr][]byte
// Using go:linkname directive to link mmapSyscall to syscall.mmap var m sync.Mutex
//go:linkname mmapSyscall syscall.mmap const pageSizeLog = 20
func mmapSyscall(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
var (
osPageMask = osPageSize - 1
osPageSize = os.Getpagesize()
)
func init() {
allocmap = make(map[uintptr][]byte)
}
func unmap(addr uintptr, size int) error {
if trace {
fmt.Fprintf(os.Stderr, "unmap %#x\n", addr)
}
a, ok := allocmap[addr]
if !ok {
if trace {
fmt.Fprintf(os.Stderr, "unmap %#x: not found\n", addr)
}
// panic("unmap called on unknown mapping")
return nil
}
if err := unix.Munmap(a); err != nil {
if trace {
fmt.Fprintf(os.Stderr, "unmap: %s\n", err.Error())
}
// panic(err.Error())
return err
}
m.Lock()
delete(allocmap, addr)
m.Unlock()
return nil
}
func mmap(size int) (uintptr, int, error) {
roundsize := roundup(size, osPageSize) + pageSize
b, err := unix.Mmap(-1, 0, roundsize, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANON)
if err != nil {
return 0, 0, err
}
p := uintptr(unsafe.Pointer(&b[0]))
if trace {
fmt.Fprintf(os.Stderr, "mmap actual @%#x size: %#x\n", p, roundsize)
}
// waste all the space until the next page
r := (p + uintptr(pageSize)) &^ uintptr(pageMask)
nsize := (roundsize) - int((r - p))
if nsize < size {
panic("didn't allocate enough to meet initial request!")
}
if trace {
fmt.Fprintf(os.Stderr, "mmap page-rounded @%#x size: %#x\n", r, nsize)
}
m.Lock()
allocmap[r] = b
m.Unlock()
return r, nsize, nil
}

View file

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE-MMAP-GO file. // license that can be found in the LICENSE-MMAP-GO file.
//go:build darwin || dragonfly || freebsd || linux || openbsd || (solaris && !illumos) || netbsd //go:build darwin || dragonfly || freebsd || linux || (solaris && !illumos) || netbsd
// +build darwin dragonfly freebsd linux openbsd solaris,!illumos netbsd // +build darwin dragonfly freebsd linux solaris,!illumos netbsd
// Modifications (c) 2017 The Memory Authors. // Modifications (c) 2017 The Memory Authors.
@ -33,6 +33,7 @@ func unmap(addr uintptr, size int) error {
// pageSize aligned. // pageSize aligned.
func mmap(size int) (uintptr, int, error) { func mmap(size int) (uintptr, int, error) {
size = roundup(size, osPageSize) size = roundup(size, osPageSize)
// The actual mmap syscall varies by architecture. mmapSyscall provides same // The actual mmap syscall varies by architecture. mmapSyscall provides same
// functionality as the unexported funtion syscall.mmap and is declared in // functionality as the unexported funtion syscall.mmap and is declared in
// mmap_*_*.go and mmap_fallback.go. To add support for a new architecture, // mmap_*_*.go and mmap_fallback.go. To add support for a new architecture,

View file

@ -23,6 +23,7 @@ Josh Bleecher Snyder <josharian@gmail.com>
Josh Klein <josh.klein@outlook.com> Josh Klein <josh.klein@outlook.com>
Kim <grufwub@gmail.com> Kim <grufwub@gmail.com>
Logan Snow <logansnow@protonmail.com> Logan Snow <logansnow@protonmail.com>
Mario Salgado <mariozalgo@gmail.com>
Mark Summerfield <mark@qtrac.eu> Mark Summerfield <mark@qtrac.eu>
Matthew Gabeler-Lee <fastcat@gmail.com> Matthew Gabeler-Lee <fastcat@gmail.com>
Michael Hoffmann <mhoffm@posteo.de> Michael Hoffmann <mhoffm@posteo.de>

6
vendor/modernc.org/sqlite/Makefile generated vendored
View file

@ -29,6 +29,8 @@ build_all_targets:
GOOS=linux GOARCH=arm go build -v ./... GOOS=linux GOARCH=arm go build -v ./...
GOOS=linux GOARCH=arm64 go test -c -o /dev/null GOOS=linux GOARCH=arm64 go test -c -o /dev/null
GOOS=linux GOARCH=arm64 go build -v ./... GOOS=linux GOARCH=arm64 go build -v ./...
GOOS=linux GOARCH=loong64 go test -c -o /dev/null
GOOS=linux GOARCH=loong64 go build -v ./...
GOOS=linux GOARCH=ppc64le go test -c -o /dev/null GOOS=linux GOARCH=ppc64le go test -c -o /dev/null
GOOS=linux GOARCH=ppc64le go build -v ./... GOOS=linux GOARCH=ppc64le go build -v ./...
GOOS=linux GOARCH=riscv64 go test -c -o /dev/null GOOS=linux GOARCH=riscv64 go test -c -o /dev/null
@ -55,7 +57,7 @@ clean:
edit: edit:
@touch log @touch log
@if [ -f "Session.vim" ]; then novim -S & else novim -p Makefile go.mod builder.json all_test.go generator.go & fi @if [ -f "Session.vim" ]; then novim -S & else novim -p Makefile go.mod builder.json all_test.go vendor_libsqlite3.go & fi
editor: editor:
gofmt -l -s -w . 2>&1 | tee log-editor gofmt -l -s -w . 2>&1 | tee log-editor
@ -64,7 +66,7 @@ editor:
go build -o /dev/null vendor_libsqlite3.go go build -o /dev/null vendor_libsqlite3.go
test: test:
go test -v -timeout 24h 2>&1 | tee log-test go test -v -timeout 24h . ./functest 2>&1 | tee log-test
vendor: vendor:
go run vendor_libsqlite3.go && make build_all_targets go run vendor_libsqlite3.go && make build_all_targets

Some files were not shown because too many files have changed in this diff Show more