├── internal └── crt │ ├── README.md │ ├── ptrace_enabled_linux.go │ ├── ptrace_disabled_linux.go │ ├── atoi_linux.go │ ├── resource_linux.go │ ├── CONTRIBUTORS │ ├── crt64_windows.go │ ├── sys_ioctl_linux.go │ ├── errno_linux.go │ ├── builtin_linux.go │ ├── strace_disabled_linux.go │ ├── crt32_linux.go │ ├── crt32_windows.go │ ├── crt64_linux.go │ ├── AUTHORS │ ├── assert_linux.go │ ├── sys_stat_linux.go │ ├── signal_linux.go │ ├── ctype_linux.go │ ├── dlfcn_linux.go │ ├── sys_time_linux.go │ ├── strings_linux.go │ ├── fcntl_linux.go │ ├── fcntl_linux_386.go │ ├── fcntl_linux_amd64.go │ ├── sys_mman_linux.go │ ├── pwd_linux.go │ ├── sys_stat_linux_amd64.go │ ├── sys_stat_linux_386.go │ ├── all_test.go │ ├── LICENSE │ ├── time_linux.go │ ├── strace_enabled_linux.go │ ├── Makefile │ ├── stdarg_linux.go │ ├── math_linux.go │ ├── stdlib_linux.go │ ├── string_linux.go │ ├── crt_linux.go │ ├── unistd_linux.go │ ├── pthread_linux.go │ └── stdio_linux.go ├── README.md ├── LICENSE ├── appveyor.yml └── doc.go /internal/crt/README.md: -------------------------------------------------------------------------------- 1 | # crt 2 | 3 | Package crt provides C-runtime services. (Work In Progress) 4 | 5 | Installation 6 | 7 | $ go get github.com/cznic/crt 8 | 9 | Documentation: [godoc.org/github.com/cznic/crt](http://godoc.org/github.com/cznic/crt) 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | `github.com/cznic/sqlite3shell` has moved to [`modernc.org/sqlite3shell`](https://godoc.org/modernc.org/sqlite3shell) ([vcs](https://gitlab.com/cznic/sqlite3shell)). 2 | 3 | Please update your import paths to `modernc.org/sqlite3shell`. 4 | 5 | This repo is now archived. 6 | -------------------------------------------------------------------------------- /internal/crt/ptrace_enabled_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build crt.ptrace 6 | 7 | package crt 8 | 9 | const ptrace = true 10 | -------------------------------------------------------------------------------- /internal/crt/ptrace_disabled_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !crt.ptrace 6 | 7 | package crt 8 | 9 | const ptrace = false 10 | -------------------------------------------------------------------------------- /internal/crt/atoi_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2005-2014 Rich Felker, et al. All rights reserved. 2 | // Use of this source code is governed by a MIT 3 | // license that can be found in the LICENSE-MUSL file. 4 | 5 | package crt 6 | 7 | // int atoi(const char *nptr); 8 | func Xatoi(tls *TLS, _s uintptr) int32 { 9 | panic("TODO atoi") 10 | } 11 | -------------------------------------------------------------------------------- /internal/crt/resource_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | // int getrusage(int who, struct rusage *usage); 8 | func Xgetrusage(tls *TLS, who int32, usage uintptr) int32 { 9 | panic("TODO getrusage") 10 | } 11 | -------------------------------------------------------------------------------- /internal/crt/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This file lists people who contributed code to this repository. The AUTHORS 2 | # file lists the copyright holders; this file lists people. 3 | # 4 | # Names should be added to this file like so: 5 | # Name 6 | # 7 | # Please keep the list sorted. 8 | 9 | Jan Mercl <0xjnml@gmail.com> 10 | Steffen Butzer 11 | -------------------------------------------------------------------------------- /internal/crt/crt64_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64 6 | 7 | package crt 8 | 9 | type ( 10 | long_t = int32 11 | rawmem [1<<50 - 1]byte 12 | size_t = uint64 13 | ssize_t = int64 14 | ulong_t = uint32 15 | ) 16 | -------------------------------------------------------------------------------- /internal/crt/sys_ioctl_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | // int ioctl(int fd, unsigned long request, ...); 8 | func Xioctl(tls *TLS, fd int32, request ulong_t, va ...interface{}) int32 { 9 | panic("TODO ioctl") 10 | } 11 | -------------------------------------------------------------------------------- /internal/crt/errno_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "unsafe" 9 | ) 10 | 11 | // extern int *__errno_location(void); 12 | func X__errno_location(tls *TLS) uintptr { return uintptr(unsafe.Pointer(&tls.errno)) } 13 | -------------------------------------------------------------------------------- /internal/crt/builtin_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "math/bits" 9 | ) 10 | 11 | // uint64_t __builtin_bswap64 (uint64_t x) 12 | func X__builtin_bswap64(tls *TLS, x uint64) uint64 { return bits.ReverseBytes64(x) } 13 | -------------------------------------------------------------------------------- /internal/crt/strace_disabled_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !crt.strace 6 | 7 | package crt 8 | 9 | const strace = false 10 | 11 | func cmdString(flag int32) string { return "" } 12 | func modeString(flag int32) string { return "" } 13 | -------------------------------------------------------------------------------- /internal/crt/crt32_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build 386 6 | 7 | package crt 8 | 9 | type ( 10 | long_t = int32 11 | pthread_t = uint32 12 | rawmem [1<<31 - 1]byte 13 | size_t = uint32 14 | ssize_t = int32 15 | ulong_t = uint32 16 | ) 17 | -------------------------------------------------------------------------------- /internal/crt/crt32_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build 386 6 | 7 | package crt 8 | 9 | type ( 10 | long_t = int32 11 | pthread_t = uint32 12 | rawmem [1<<31 - 1]byte 13 | size_t = uint32 14 | ssize_t = int32 15 | ulong_t = uint32 16 | ) 17 | -------------------------------------------------------------------------------- /internal/crt/crt64_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64 6 | 7 | package crt 8 | 9 | type ( 10 | long_t = int64 11 | pthread_t = uint64 12 | rawmem [1<<50 - 1]byte 13 | size_t = uint64 14 | ssize_t = int64 15 | ulong_t = uint64 16 | ) 17 | -------------------------------------------------------------------------------- /internal/crt/AUTHORS: -------------------------------------------------------------------------------- 1 | # This file lists authors for copyright purposes. This file is distinct from 2 | # the CONTRIBUTORS files. See the latter for an explanation. 3 | # 4 | # Names should be added to this file as: 5 | # Name or Organization 6 | # 7 | # The email address is not required for organizations. 8 | # 9 | # Please keep the list sorted. 10 | 11 | Jan Mercl <0xjnml@gmail.com> 12 | Steffen Butzer 13 | -------------------------------------------------------------------------------- /internal/crt/assert_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | func X__builtin_assert_fail(tls *TLS, file uintptr, line int32, fn, msg uintptr) { 12 | panic(fmt.Errorf("%s.%s:%d: assertion failure: %s", GoString(file), GoString(fn), line, GoString(msg))) 13 | } 14 | -------------------------------------------------------------------------------- /internal/crt/sys_stat_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | // int fchmod(int fd, mode_t mode); 8 | func Xfchmod(tls *TLS, fd int32, mode uint32) int32 { 9 | panic("TODO fchmod") 10 | } 11 | 12 | // int mkdir(const char *pathname, mode_t mode); 13 | func Xmkdir(tls *TLS, pathname uintptr, mode uint32) int32 { 14 | panic("TODO mkdir") 15 | } 16 | -------------------------------------------------------------------------------- /internal/crt/signal_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | "unsafe" 12 | ) 13 | 14 | // sighandler_t sysv_signal(int signum, sighandler_t handler); 15 | func X__sysv_signal(tls *TLS, signum int32, handler uintptr) { 16 | ch := make(chan os.Signal) 17 | go func() { 18 | <-ch 19 | (*(*func(*TLS, int32))(unsafe.Pointer(&handler)))(tls, signum) 20 | }() 21 | signal.Notify(ch, syscall.Signal(signum)) 22 | } 23 | -------------------------------------------------------------------------------- /internal/crt/ctype_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | // int tolower(int c); 8 | func Xtolower(tls *TLS, c int32) int32 { 9 | if c >= 'A' && c <= 'Z' { 10 | c |= ' ' 11 | } 12 | return c 13 | } 14 | 15 | // int isprint(int c); 16 | func X__builtin_isprint(tls *TLS, c int32) int32 { 17 | if c >= ' ' && c <= '~' { 18 | return 1 19 | } 20 | 21 | return 0 22 | } 23 | 24 | // int isprint(int c); 25 | func Xisprint(tls *TLS, c int32) int32 { return X__builtin_isprint(tls, c) } 26 | -------------------------------------------------------------------------------- /internal/crt/dlfcn_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | // void *dlopen(const char *filename, int flags); 8 | func Xdlopen(tls *TLS, filename uintptr, flags int32) uintptr { 9 | panic("TODO dlopen") 10 | } 11 | 12 | // char *dlerror(void); 13 | func Xdlerror(tls *TLS) uintptr { 14 | panic("TODO dlerror") 15 | } 16 | 17 | // int dlclose(void *handle); 18 | func Xdlclose(tls *TLS, handle uintptr) int32 { 19 | panic("TODO dlclose") 20 | } 21 | 22 | // void *dlsym(void *handle, const char *symbol); 23 | func Xdlsym(tls *TLS, handle, symbol uintptr) uintptr { 24 | panic("TODO dlsym") 25 | } 26 | -------------------------------------------------------------------------------- /internal/crt/sys_time_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "syscall" 11 | ) 12 | 13 | // int gettimeofday(struct timeval *restrict tp, void *restrict tzp); 14 | func Xgettimeofday(tls *TLS, tp, tzp uintptr) int32 { 15 | r, _, err := syscall.Syscall(syscall.SYS_GETTIMEOFDAY, tp, tzp, 0) 16 | if strace { 17 | fmt.Fprintf(os.Stderr, "gettimeofday(%#x, %#x) %v %v\n", tp, tzp, r, err) 18 | } 19 | return int32(r) 20 | } 21 | 22 | // int utimes(const char *filename, const struct timeval times[2]); 23 | func Xutimes(tls *TLS, filename, times uintptr) int32 { 24 | panic("TODO utimes") 25 | } 26 | -------------------------------------------------------------------------------- /internal/crt/strings_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | // int ffs(int i); 8 | func X__builtin_ffs(tls *TLS, i int32) int32 { 9 | if i == 0 { 10 | return 0 11 | } 12 | 13 | var r int32 14 | for ; r < 32 && i&(1<&1 | grep -v $(ngrep) || true 12 | golint 2>&1 | grep -v $(ngrep) || true 13 | make todo 14 | unused . || true 15 | misspell *.go 16 | gosimple || true 17 | maligned || true 18 | #unconvert -apply 19 | 20 | clean: 21 | go clean 22 | rm -f *~ *.test *.out 23 | 24 | cover: 25 | t=$(shell tempfile) ; go test -coverprofile $$t && go tool cover -html $$t && unlink $$t 26 | 27 | cpu: clean 28 | go test -run @ -bench . -cpuprofile cpu.out 29 | go tool pprof -lines *.test cpu.out 30 | 31 | edit: 32 | @ 1>/dev/null 2>/dev/null gvim -p Makefile all_test.go builtin.go crt*.go 33 | 34 | editor: 35 | gofmt -l -s -w *.go 36 | GOOS=linux GOARCH=386 go build 37 | GOOS=linux GOARCH=amd64 go build 38 | #TODO GOOS=windows GOARCH=386 go build 39 | #TODO GOOS=windows GOARCH=amd64 go build 40 | go test -i 41 | go test 2>&1 | tee log 42 | go install 43 | 44 | internalError: 45 | egrep -ho '"internal error.*"' *.go | sort | cat -n 46 | 47 | later: 48 | @grep -n $(grep) LATER * || true 49 | @grep -n $(grep) MAYBE * || true 50 | 51 | mem: clean 52 | go test -run @ -bench . -memprofile mem.out -memprofilerate 1 -timeout 24h 53 | go tool pprof -lines -web -alloc_space *.test mem.out 54 | 55 | nuke: clean 56 | go clean -i 57 | 58 | todo: 59 | @grep -nr $(grep) ^[[:space:]]*_[[:space:]]*=[[:space:]][[:alpha:]][[:alnum:]]* * | grep -v $(ngrep) || true 60 | @grep -nr $(grep) TODO * | grep -v $(ngrep) || true 61 | @grep -nr $(grep) BUG * | grep -v $(ngrep) || true 62 | @grep -nr $(grep) [^[:alpha:]]println * | grep -v $(ngrep) || true 63 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Steffen Butzer 2 | # 3 | # If licensing should apply to this file, 4 | # this is free and unencumbered software released into the public domain. 5 | # Anyone is free to copy, modify, publish, use, compile, sell, or 6 | # distribute this file, for any purpose, commercial or non-commercial, and by any 7 | # means. 8 | # In jurisdictions that recognize copyright laws, the author or authors 9 | # of this software dedicate any and all copyright interest in the 10 | # software to the public domain. We make this dedication for the benefit 11 | # of the public at large and to the detriment of our heirs and 12 | # successors. We intend this dedication to be an overt act of 13 | # relinquishment in perpetuity of all present and future rights to this 14 | # software under copyright law. 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | # For more information, please refer to 23 | 24 | environment: 25 | PROJ_NAME: sqlite3shell 26 | PROJ_PATH: src/github.com/cznic 27 | 28 | matrix: 29 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 30 | GOPATH: C:\gopath 31 | GOARCH: 386 32 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 33 | GOPATH: C:\gopath 34 | GOARCH: amd64 35 | - APPVEYOR_BUILD_WORKER_IMAGE: ubuntu 36 | GOPATH: /home/appveyor/gopath 37 | GOARCH: 386 38 | - APPVEYOR_BUILD_WORKER_IMAGE: ubuntu 39 | GOPATH: /home/appveyor/gopath 40 | GOARCH: amd64 41 | 42 | stack: go 1.10 43 | 44 | install: 45 | - cd .. 46 | - ps: $env:PROJ_PATH = $env:GOPATH + "/" + $env:PROJ_PATH 47 | - ps: $env:PROJ_FULL_PATH = $env:PROJ_PATH + "/" + $env:PROJ_NAME 48 | - ps: New-Item $env:PROJ_PATH -ItemType Directory 49 | - ps: Move-Item $env:APPVEYOR_BUILD_FOLDER $env:PROJ_FULL_PATH 50 | - ps: Set-Location -Path $env:PROJ_FULL_PATH 51 | - go get -d ./... 52 | 53 | build: off 54 | 55 | test_script: 56 | - go test -timeout 999m -v 57 | -------------------------------------------------------------------------------- /internal/crt/stdarg_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | func VAuintptr(ap *[]interface{}) (r uintptr) { 12 | s := *ap 13 | switch x := s[0].(type) { 14 | case uintptr: 15 | r = x 16 | default: 17 | panic(fmt.Errorf("crt.VAuintptr %T", x)) 18 | } 19 | *ap = s[1:] 20 | return r 21 | } 22 | 23 | func VAfloat64(ap *[]interface{}) float64 { 24 | s := *ap 25 | v := s[0].(float64) 26 | *ap = s[1:] 27 | return v 28 | } 29 | 30 | func VAint32(ap *[]interface{}) (v int32) { 31 | s := *ap 32 | switch x := s[0].(type) { 33 | case int32: 34 | v = x 35 | case uint32: 36 | v = int32(x) 37 | case int64: 38 | v = int32(x) 39 | case uint64: 40 | v = int32(x) 41 | case uintptr: 42 | v = int32(x) 43 | default: 44 | panic(fmt.Errorf("crt.VAint32 %T", x)) 45 | } 46 | *ap = s[1:] 47 | return v 48 | } 49 | 50 | func VAuint32(ap *[]interface{}) (v uint32) { 51 | s := *ap 52 | switch x := s[0].(type) { 53 | case int32: 54 | v = uint32(x) 55 | case uint32: 56 | v = x 57 | case int64: 58 | v = uint32(x) 59 | case uint64: 60 | v = uint32(x) 61 | case uintptr: 62 | v = uint32(x) 63 | default: 64 | panic(fmt.Errorf("crt.VAuint32 %T", x)) 65 | } 66 | *ap = s[1:] 67 | return v 68 | } 69 | 70 | func VAint64(ap *[]interface{}) (v int64) { 71 | s := *ap 72 | switch x := s[0].(type) { 73 | case int32: 74 | v = int64(x) 75 | case uint32: 76 | v = int64(x) 77 | case int64: 78 | v = x 79 | case uint64: 80 | v = int64(x) 81 | case uintptr: 82 | v = int64(x) 83 | default: 84 | panic(fmt.Errorf("crt.VAint64 %T", x)) 85 | } 86 | *ap = s[1:] 87 | return v 88 | } 89 | 90 | func VAuint64(ap *[]interface{}) (v uint64) { 91 | s := *ap 92 | switch x := s[0].(type) { 93 | case int32: 94 | v = uint64(x) 95 | case uint32: 96 | v = uint64(x) 97 | case int64: 98 | v = uint64(x) 99 | case uint64: 100 | v = x 101 | case uintptr: 102 | v = uint64(x) 103 | default: 104 | panic(fmt.Errorf("crt.VAuint64 %T", x)) 105 | } 106 | *ap = s[1:] 107 | return v 108 | } 109 | 110 | func vaLong(ap *[]interface{}) int64 { return VAint64(ap) } 111 | func vaULong(ap *[]interface{}) uint64 { return VAuint64(ap) } 112 | -------------------------------------------------------------------------------- /internal/crt/math_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "math" 9 | ) 10 | 11 | func Xacos(tls *TLS, x float64) float64 { return math.Acos(x) } 12 | func Xasin(tls *TLS, x float64) float64 { return math.Asin(x) } 13 | func Xatan(tls *TLS, x float64) float64 { return math.Atan(x) } 14 | func Xatan2(tls *TLS, y, x float64) float64 { return math.Atan2(y, x) } 15 | func Xceil(tls *TLS, x float64) float64 { return math.Ceil(x) } 16 | func Xcopysign(tls *TLS, x, y float64) float64 { return X__builtin_copysign(tls, x, y) } 17 | func Xcos(tls *TLS, x float64) float64 { return math.Cos(x) } 18 | func Xcosh(tls *TLS, x float64) float64 { return math.Cosh(x) } 19 | func Xexp(tls *TLS, x float64) float64 { return math.Exp(x) } 20 | func Xfabs(tls *TLS, x float64) float64 { return math.Abs(x) } 21 | func Xfabsf(tls *TLS, x float32) float32 { return float32(math.Abs(float64(x))) } 22 | func Xfloor(tls *TLS, x float64) float64 { return math.Floor(x) } 23 | func Xfmod(tls *TLS, x, y float64) float64 { return math.Mod(x, y) } 24 | func Xhypot(tls *TLS, x, y float64) float64 { return math.Hypot(x, y) } 25 | func Xlog(tls *TLS, x float64) float64 { return math.Log(x) } 26 | func Xlog10(tls *TLS, x float64) float64 { return math.Log10(x) } 27 | func Xpow(tls *TLS, x, y float64) float64 { return math.Pow(x, y) } 28 | func Xsin(tls *TLS, x float64) float64 { return math.Sin(x) } 29 | func Xsinh(tls *TLS, x float64) float64 { return math.Sinh(x) } 30 | func Xsqrt(tls *TLS, x float64) float64 { return math.Sqrt(x) } 31 | func Xtan(tls *TLS, x float64) float64 { return math.Tan(x) } 32 | func Xtanh(tls *TLS, x float64) float64 { return math.Tanh(x) } 33 | 34 | // double round(double x); 35 | func Xround(tls *TLS, x float64) float64 { 36 | switch { 37 | case x < 0: 38 | return math.Ceil(x - 0.5) 39 | case x > 0: 40 | return math.Floor(x + 0.5) 41 | } 42 | return x 43 | } 44 | 45 | // int __signbit(double x); 46 | func X__signbit(tls *TLS, x float64) int32 { 47 | if math.Signbit(x) { 48 | return 1 49 | } 50 | 51 | return 0 52 | } 53 | 54 | // int __signbitf(float x); 55 | func X__signbitf(tls *TLS, x float32) int32 { 56 | if math.Signbit(float64(x)) { 57 | return 1 58 | } 59 | 60 | return 0 61 | } 62 | 63 | func X__builtin_copysign(tls *TLS, x, y float64) float64 { return math.Copysign(x, y) } 64 | 65 | // int isnan(x); 66 | func Xisnan(tls *TLS, x float64) int32 { 67 | if math.IsNaN(x) { 68 | return 1 69 | } 70 | 71 | return 0 72 | } 73 | -------------------------------------------------------------------------------- /internal/crt/stdlib_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "os/exec" 11 | "sort" 12 | "syscall" 13 | "unsafe" 14 | 15 | "github.com/cznic/mathutil" 16 | ) 17 | 18 | // void exit(int); 19 | func Xexit(tls *TLS, n int32) { X__builtin_exit(tls, n) } 20 | 21 | // // void exit(int); 22 | // func X__builtin_exit(tls *TLS, n int32) { 23 | // os.Exit(int(n)) 24 | // } 25 | 26 | // void free(void *ptr); 27 | func Xfree(tls *TLS, ptr uintptr) { 28 | free(tls, ptr) 29 | if strace { 30 | fmt.Fprintf(os.Stderr, "free(%#x)\n", ptr) 31 | } 32 | } 33 | 34 | // void abort(); 35 | func Xabort(tls *TLS) { X__builtin_abort(tls) } 36 | 37 | // void __builtin_trap(); 38 | func X__builtin_trap(tls *TLS) { os.Exit(1) } 39 | 40 | // void abort(); 41 | func X__builtin_abort(tls *TLS) { X__builtin_trap(tls) } 42 | 43 | // char *getenv(const char *name); 44 | func Xgetenv(tls *TLS, name uintptr) uintptr { 45 | nm := GoString(name) 46 | v := os.Getenv(nm) 47 | var p uintptr 48 | if v != "" { 49 | p = CString(v) 50 | } 51 | return p 52 | } 53 | 54 | // int abs(int j); 55 | func X__builtin_abs(tls *TLS, j int32) int32 { 56 | if j < 0 { 57 | return -j 58 | } 59 | 60 | return j 61 | } 62 | 63 | // int abs(int j); 64 | func Xabs(tls *TLS, j int32) int32 { return X__builtin_abs(tls, j) } 65 | 66 | type sorter struct { 67 | base uintptr 68 | compar func(tls *TLS, a, b uintptr) int32 69 | nmemb int 70 | size uintptr 71 | tls *TLS 72 | buf []byte 73 | } 74 | 75 | func (s *sorter) Len() int { return s.nmemb } 76 | 77 | func (s *sorter) Less(i, j int) bool { 78 | return s.compar(s.tls, s.base+uintptr(i)*s.size, s.base+uintptr(j)*s.size) < 0 79 | } 80 | 81 | func (s *sorter) Swap(i, j int) { 82 | p := s.base + uintptr(i)*s.size 83 | q := s.base + uintptr(j)*s.size 84 | switch s.size { 85 | case 1: 86 | *(*int8)(unsafe.Pointer(p)), *(*int8)(unsafe.Pointer(q)) = *(*int8)(unsafe.Pointer(q)), *(*int8)(unsafe.Pointer(p)) 87 | case 2: 88 | *(*int16)(unsafe.Pointer(p)), *(*int16)(unsafe.Pointer(q)) = *(*int16)(unsafe.Pointer(q)), *(*int16)(unsafe.Pointer(p)) 89 | case 4: 90 | *(*int32)(unsafe.Pointer(p)), *(*int32)(unsafe.Pointer(q)) = *(*int32)(unsafe.Pointer(q)), *(*int32)(unsafe.Pointer(p)) 91 | case 8: 92 | *(*int64)(unsafe.Pointer(p)), *(*int64)(unsafe.Pointer(q)) = *(*int64)(unsafe.Pointer(q)), *(*int64)(unsafe.Pointer(p)) 93 | default: 94 | size := int(s.size) 95 | if s.buf == nil { 96 | s.buf = make([]byte, size) 97 | } 98 | Copy(uintptr(unsafe.Pointer(&s.buf[0])), p, size) 99 | Copy(p, q, size) 100 | Copy(q, uintptr(unsafe.Pointer(&s.buf[0])), size) 101 | } 102 | } 103 | 104 | // void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 105 | func qsort(tls *TLS, base uintptr, nmemb, size size_t, compar uintptr) { 106 | if size > mathutil.MaxInt { 107 | panic("size overflow") 108 | } 109 | 110 | if nmemb > mathutil.MaxInt { 111 | panic("nmemb overflow") 112 | } 113 | 114 | s := sorter{base, *(*func(*TLS, uintptr, uintptr) int32)(unsafe.Pointer(&compar)), int(nmemb), uintptr(size), tls, nil} 115 | sort.Sort(&s) 116 | } 117 | 118 | // int system(const char *command); 119 | func Xsystem(tls *TLS, command uintptr) int32 { 120 | if command == 0 || *(*int8)(unsafe.Pointer(command)) == 0 { 121 | return 1 122 | } 123 | 124 | cmd := exec.Command("sh", "-c", GoString(command)) 125 | if err := cmd.Run(); err != nil { 126 | return int32(cmd.ProcessState.Sys().(syscall.WaitStatus)) 127 | } 128 | 129 | return 0 130 | } 131 | 132 | // void *calloc(size_t nmemb, size_t size); 133 | func Xcalloc(tls *TLS, nmemb, size size_t) (p uintptr) { 134 | hi, lo := mathutil.MulUint128_64(uint64(nmemb), uint64(size)) 135 | if hi == 0 && lo <= mathutil.MaxInt { 136 | p = calloc(tls, int(lo)) 137 | } 138 | if strace { 139 | fmt.Fprintf(os.Stderr, "calloc(%#x) %#x\n", size, p) 140 | } 141 | return p 142 | } 143 | 144 | // void *malloc(size_t size); 145 | func X__builtin_malloc(tls *TLS, size size_t) (p uintptr) { 146 | if size < mathutil.MaxInt { 147 | p = malloc(tls, int(size)) 148 | } 149 | if strace { 150 | fmt.Fprintf(os.Stderr, "malloc(%#x) %#x\n", size, p) 151 | } 152 | return p 153 | } 154 | 155 | // void *malloc(size_t size); 156 | func Xmalloc(tls *TLS, size size_t) uintptr { return X__builtin_malloc(tls, size) } 157 | 158 | // void *realloc(void *ptr, size_t size); 159 | func Xrealloc(tls *TLS, ptr uintptr, size size_t) (p uintptr) { 160 | if size < mathutil.MaxInt { 161 | p = realloc(tls, ptr, int(size)) 162 | } 163 | if strace { 164 | fmt.Fprintf(os.Stderr, "realloc(%#x, %#x) %#x\n", ptr, size, p) 165 | } 166 | return p 167 | } 168 | 169 | // size_t malloc_usable_size (void *ptr); 170 | // func Xmalloc_usable_size(tls *TLS, ptr uintptr) size_t { return size_t(memory.UintptrUsableSize(ptr)) } 171 | 172 | // void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 173 | func Xqsort(tls *TLS, base uintptr, nmemb, size size_t, compar uintptr) { 174 | qsort(tls, base, nmemb, size, compar) 175 | } 176 | 177 | // long int strtol(const char *nptr, char **endptr, int base); 178 | func Xstrtol(tls *TLS, nptr, endptr uintptr, base int32) int64 { 179 | panic("TODO strtol") 180 | } 181 | -------------------------------------------------------------------------------- /internal/crt/string_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "unsafe" 9 | ) 10 | 11 | // char *strcat(char *dest, const char *src) 12 | func Xstrcat(tls *TLS, dest, src uintptr) uintptr { 13 | ret := dest 14 | for *(*int8)(unsafe.Pointer(dest)) != 0 { 15 | dest++ 16 | } 17 | for { 18 | c := *(*int8)(unsafe.Pointer(src)) 19 | src++ 20 | *(*int8)(unsafe.Pointer(dest)) = c 21 | dest++ 22 | if c == 0 { 23 | return ret 24 | } 25 | } 26 | } 27 | 28 | // char *index(const char *s, int c) 29 | func Xindex(tls *TLS, s uintptr, c int32) uintptr { return Xstrchr(tls, s, c) } 30 | 31 | // char *strchr(const char *s, int c) 32 | func Xstrchr(tls *TLS, s uintptr, c int32) uintptr { 33 | for { 34 | ch2 := *(*byte)(unsafe.Pointer(s)) 35 | if ch2 == byte(c) { 36 | return s 37 | } 38 | 39 | if ch2 == 0 { 40 | return 0 41 | } 42 | 43 | s++ 44 | } 45 | } 46 | 47 | // char *strchrnul(const char *s, int c); 48 | func Xstrchrnul(tls *TLS, s uintptr, c int32) uintptr { 49 | for { 50 | ch2 := *(*byte)(unsafe.Pointer(s)) 51 | if ch2 == 0 || ch2 == byte(c) { 52 | return s 53 | } 54 | 55 | s++ 56 | } 57 | } 58 | 59 | // int strcmp(const char *s1, const char *s2) 60 | func X__builtin_strcmp(tls *TLS, s1, s2 uintptr) int32 { 61 | for { 62 | ch1 := *(*byte)(unsafe.Pointer(s1)) 63 | s1++ 64 | ch2 := *(*byte)(unsafe.Pointer(s2)) 65 | s2++ 66 | if ch1 != ch2 || ch1 == 0 || ch2 == 0 { 67 | return int32(ch1) - int32(ch2) 68 | } 69 | } 70 | } 71 | 72 | // int strcmp(const char *s1, const char *s2) 73 | func Xstrcmp(tls *TLS, s1, s2 uintptr) int32 { return X__builtin_strcmp(tls, s1, s2) } 74 | 75 | // char *strcpy(char *dest, const char *src) 76 | func X__builtin_strcpy(tls *TLS, dest, src uintptr) uintptr { 77 | r := dest 78 | for { 79 | c := *(*int8)(unsafe.Pointer(src)) 80 | src++ 81 | *(*int8)(unsafe.Pointer(dest)) = c 82 | dest++ 83 | if c == 0 { 84 | return r 85 | } 86 | } 87 | } 88 | 89 | // char *strcpy(char *dest, const char *src) 90 | func Xstrcpy(tls *TLS, dest, src uintptr) uintptr { return X__builtin_strcpy(tls, dest, src) } 91 | 92 | // char *rindex(const char *s, int c) 93 | func Xrindex(tls *TLS, s uintptr, c int32) uintptr { return Xstrrchr(tls, s, c) } 94 | 95 | // char *strrchr(const char *s, int c) 96 | func Xstrrchr(tls *TLS, s uintptr, c int32) uintptr { 97 | var ret uintptr 98 | for { 99 | ch2 := *(*byte)(unsafe.Pointer(s)) 100 | if ch2 == 0 { 101 | return ret 102 | } 103 | 104 | if ch2 == byte(c) { 105 | ret = s 106 | } 107 | s++ 108 | } 109 | } 110 | 111 | // char *strstr(const char *haystack, const char *needle); 112 | func Xstrstr(tls *TLS, haystack, needle uintptr) uintptr { 113 | panic("TODO strstr") 114 | } 115 | 116 | // char *strncpy(char *dest, const char *src, size_t n) 117 | func Xstrncpy(tls *TLS, dest, src uintptr, n size_t) uintptr { 118 | ret := dest 119 | for c := *(*int8)(unsafe.Pointer(src)); c != 0 && n > 0; n-- { 120 | *(*int8)(unsafe.Pointer(dest)) = c 121 | dest++ 122 | src++ 123 | c = *(*int8)(unsafe.Pointer(src)) 124 | } 125 | for ; n > 0; n-- { 126 | *(*int8)(unsafe.Pointer(dest)) = 0 127 | dest++ 128 | } 129 | return ret 130 | } 131 | 132 | // size_t strlen(const char *s) 133 | func X__builtin_strlen(tls *TLS, s uintptr) size_t { 134 | var n size_t 135 | for ; *(*int8)(unsafe.Pointer(s)) != 0; s++ { 136 | n++ 137 | } 138 | return n 139 | } 140 | 141 | // size_t strlen(const char *s) 142 | func Xstrlen(tls *TLS, s uintptr) size_t { return X__builtin_strlen(tls, s) } 143 | 144 | // int strncmp(const char *s1, const char *s2, size_t n) 145 | func Xstrncmp(tls *TLS, s1, s2 uintptr, n size_t) int32 { 146 | var ch1, ch2 byte 147 | for n != 0 { 148 | ch1 = *(*byte)(unsafe.Pointer(s1)) 149 | s1++ 150 | ch2 = *(*byte)(unsafe.Pointer(s2)) 151 | s2++ 152 | n-- 153 | if ch1 != ch2 || ch1 == 0 || ch2 == 0 { 154 | break 155 | } 156 | } 157 | if n != 0 { 158 | return int32(ch1) - int32(ch2) 159 | } 160 | 161 | return 0 162 | } 163 | 164 | // void *memset(void *s, int c, size_t n) 165 | func Xmemset(tls *TLS, s uintptr, c int32, n size_t) uintptr { 166 | return X__builtin_memset(tls, s, c, n) 167 | } 168 | 169 | // void *memset(void *s, int c, size_t n) 170 | func X__builtin_memset(tls *TLS, s uintptr, c int32, n size_t) uintptr { 171 | for d := s; n > 0; n-- { 172 | *(*int8)(unsafe.Pointer(d)) = int8(c) 173 | d++ 174 | } 175 | return s 176 | } 177 | 178 | // void *memcpy(void *dest, const void *src, size_t n) 179 | func X__builtin_memcpy(tls *TLS, dest, src uintptr, n size_t) uintptr { 180 | Copy(dest, src, int(n)) 181 | return dest 182 | } 183 | 184 | // void *memcpy(void *dest, const void *src, size_t n) 185 | func Xmemcpy(tls *TLS, dest, src uintptr, n size_t) uintptr { 186 | return X__builtin_memcpy(tls, dest, src, n) 187 | } 188 | 189 | // int memcmp(const void *s1, const void *s2, size_t n) 190 | func X__builtin_memcmp(tls *TLS, s1, s2 uintptr, n size_t) int32 { 191 | var ch1, ch2 byte 192 | for n != 0 { 193 | ch1 = *(*byte)(unsafe.Pointer(s1)) 194 | s1++ 195 | ch2 = *(*byte)(unsafe.Pointer(s2)) 196 | s2++ 197 | if ch1 != ch2 { 198 | break 199 | } 200 | 201 | n-- 202 | } 203 | if n != 0 { 204 | return int32(ch1) - int32(ch2) 205 | } 206 | 207 | return 0 208 | } 209 | 210 | // int memcmp(const void *s1, const void *s2, size_t n) 211 | func Xmemcmp(tls *TLS, s1, s2 uintptr, n size_t) int32 { 212 | return X__builtin_memcmp(tls, s1, s2, n) 213 | } 214 | 215 | // void *memmove(void *dest, const void *src, size_t n); 216 | func Xmemmove(tls *TLS, dest, src uintptr, n size_t) uintptr { 217 | Copy(dest, src, int(n)) 218 | return dest 219 | } 220 | 221 | // void *mempcpy(void *dest, const void *src, size_t n); 222 | func Xmempcpy(tls *TLS, dest, src uintptr, n size_t) uintptr { 223 | return dest + uintptr(Copy(dest, src, int(n))) 224 | } 225 | -------------------------------------------------------------------------------- /internal/crt/crt_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package crt provides C-runtime services. (Work In Progress) 6 | // 7 | // Installation 8 | // 9 | // $ go get github.com/cznic/crt 10 | // 11 | // Documentation: http://godoc.org/github.com/cznic/crt 12 | package crt 13 | 14 | import ( 15 | "fmt" 16 | "io" 17 | "os" 18 | "reflect" 19 | "sync" 20 | "sync/atomic" 21 | "syscall" 22 | "unsafe" 23 | 24 | "github.com/cznic/ccir/libc/errno" 25 | "github.com/cznic/internal/buffer" 26 | "github.com/cznic/mathutil" 27 | "github.com/cznic/memory" 28 | ) 29 | 30 | const ( 31 | ptrSize = mathutil.UintPtrBits / 8 32 | ) 33 | 34 | var ( 35 | _ io.Writer = (*memWriter)(nil) 36 | 37 | allocMu sync.Mutex 38 | allocator memory.Allocator 39 | threadID uintptr 40 | ) 41 | 42 | type ( 43 | T__uid_t = uint32 44 | T__gid_t = uint32 45 | ) 46 | 47 | // TLS represents the C-thread local storage. 48 | type TLS struct { 49 | threadID uintptr 50 | errno int32 51 | } 52 | 53 | func (t *TLS) setErrno(err interface{}) { 54 | switch x := err.(type) { 55 | case int: 56 | t.errno = int32(x) 57 | case *os.PathError: 58 | t.setErrno(x.Err) 59 | case syscall.Errno: 60 | t.errno = int32(x) 61 | default: 62 | panic(fmt.Errorf("crt.setErrno %T(%#v)", x, x)) 63 | } 64 | } 65 | 66 | // NewTLS returns a newly created TLS, allocated outside of the Go runtime 67 | // heap. To free the TLS use Free(uintptr(unsafe.Pointer(tls))). 68 | func NewTLS() *TLS { 69 | tls := (*TLS)(unsafe.Pointer(MustCalloc(int(unsafe.Sizeof(TLS{}))))) 70 | tls.threadID = atomic.AddUintptr(&threadID, 1) 71 | return tls 72 | } 73 | 74 | // void __register_stdfiles(void *, void *, void *); 75 | func X__register_stdfiles(tls *TLS, in, out, err uintptr) { 76 | stdin = in 77 | stdout = out 78 | stderr = err 79 | } 80 | 81 | // void exit(int); 82 | func X__builtin_exit(tls *TLS, n int32) { os.Exit(int(n)) } 83 | 84 | // BSS allocates the the bss segment of a package/command. 85 | func BSS(init *byte) uintptr { 86 | r := uintptr(unsafe.Pointer(init)) 87 | if r%unsafe.Sizeof(uintptr(0)) != 0 { 88 | panic("internal error") 89 | } 90 | 91 | return r 92 | } 93 | 94 | // DS allocates the the data segment of a package/command. 95 | func DS(init []byte) uintptr { 96 | r := (*reflect.SliceHeader)(unsafe.Pointer(&init)).Data 97 | if r%unsafe.Sizeof(uintptr(0)) != 0 { 98 | panic("internal error") 99 | } 100 | 101 | return r 102 | } 103 | 104 | // TS allocates the R/O text segment of a package/command. 105 | func TS(init string) uintptr { return (*reflect.StringHeader)(unsafe.Pointer(&init)).Data } 106 | 107 | // Free frees memory allocated by Calloc, Malloc or Realloc. 108 | func Free(p uintptr) error { 109 | allocMu.Lock() 110 | err := allocator.UintptrFree(p) 111 | allocMu.Unlock() 112 | return err 113 | } 114 | 115 | // Calloc allocates zeroed memory. 116 | func Calloc(size int) (uintptr, error) { 117 | allocMu.Lock() 118 | p, err := allocator.UintptrCalloc(size) 119 | allocMu.Unlock() 120 | return p, err 121 | } 122 | 123 | // Malloc allocates memory. 124 | func Malloc(size int) (uintptr, error) { 125 | allocMu.Lock() 126 | p, err := allocator.UintptrMalloc(size) 127 | allocMu.Unlock() 128 | return p, err 129 | } 130 | 131 | // MustCalloc is like Calloc but panics if the allocation cannot be made. 132 | func MustCalloc(size int) uintptr { 133 | p, err := Calloc(size) 134 | if err != nil { 135 | panic(fmt.Errorf("out of memory: %v", err)) 136 | } 137 | 138 | return p 139 | } 140 | 141 | // MustMalloc is like Malloc but panics if the allocation cannot be made. 142 | func MustMalloc(size int) uintptr { 143 | p, err := Malloc(size) 144 | if err != nil { 145 | panic(fmt.Errorf("out of memory: %v", err)) 146 | } 147 | 148 | return p 149 | } 150 | 151 | // Realloc reallocates memory. 152 | func Realloc(p uintptr, size int) (uintptr, error) { 153 | allocMu.Lock() 154 | p, err := allocator.UintptrRealloc(p, size) 155 | allocMu.Unlock() 156 | return p, err 157 | } 158 | 159 | type memWriter uintptr 160 | 161 | func (m *memWriter) Write(b []byte) (int, error) { 162 | if len(b) == 0 { 163 | return 0, nil 164 | } 165 | 166 | Copy(uintptr(*m), uintptr(unsafe.Pointer(&b[0])), len(b)) 167 | *m += memWriter(len(b)) 168 | return len(b), nil 169 | } 170 | 171 | func (m *memWriter) WriteByte(b byte) error { 172 | *(*byte)(unsafe.Pointer(*m)) = b 173 | *m++ 174 | return nil 175 | } 176 | 177 | // Copy copies n bytes form src to dest and returns n. 178 | func Copy(dst, src uintptr, n int) int { 179 | return copy((*rawmem)(unsafe.Pointer(dst))[:n], (*rawmem)(unsafe.Pointer(src))[:n]) 180 | } 181 | 182 | // CString allocates a C string initialized from s. 183 | func CString(s string) uintptr { 184 | n := len(s) 185 | var tls TLS 186 | p := malloc(&tls, n+1) 187 | if p == 0 { 188 | return 0 189 | } 190 | 191 | copy((*rawmem)(unsafe.Pointer(p))[:n], s) 192 | (*rawmem)(unsafe.Pointer(p))[n] = 0 193 | return p 194 | } 195 | 196 | // GoString returns a string from a C char* null terminated string s. 197 | func GoString(s uintptr) string { 198 | if s == 0 { 199 | return "" 200 | } 201 | 202 | var b buffer.Bytes 203 | for { 204 | ch := *(*byte)(unsafe.Pointer(s)) 205 | if ch == 0 { 206 | r := string(b.Bytes()) 207 | b.Close() 208 | return r 209 | } 210 | 211 | b.WriteByte(ch) 212 | s++ 213 | } 214 | } 215 | 216 | func calloc(tls *TLS, size int) uintptr { 217 | p, err := Calloc(size) 218 | if err != nil { 219 | tls.setErrno(errno.XENOMEM) 220 | return 0 221 | } 222 | 223 | return p 224 | } 225 | 226 | func free(tls *TLS, p uintptr) { Free(p) } 227 | 228 | func malloc(tls *TLS, size int) uintptr { 229 | p, err := Malloc(size) 230 | if err != nil { 231 | tls.setErrno(errno.XENOMEM) 232 | return 0 233 | } 234 | 235 | return p 236 | } 237 | 238 | func realloc(tls *TLS, p uintptr, size int) uintptr { 239 | p, err := Realloc(p, size) 240 | if err != nil { 241 | tls.setErrno(errno.XENOMEM) 242 | return 0 243 | } 244 | 245 | return p 246 | } 247 | -------------------------------------------------------------------------------- /internal/crt/unistd_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "syscall" 11 | "time" 12 | "unsafe" 13 | 14 | "github.com/cznic/ccir/libc/errno" 15 | "github.com/cznic/ccir/libc/unistd" 16 | "golang.org/x/crypto/ssh/terminal" 17 | ) 18 | 19 | // int close(int fd); 20 | func Xclose(tls *TLS, fd int32) int32 { 21 | r, _, err := syscall.Syscall(syscall.SYS_CLOSE, uintptr(fd), 0, 0) 22 | if strace { 23 | fmt.Fprintf(os.Stderr, "close(%v) %v %v\n", fd, r, err) 24 | } 25 | if err != 0 { 26 | tls.setErrno(err) 27 | } 28 | return int32(r) 29 | } 30 | 31 | // int access(const char *path, int amode); 32 | func Xaccess(tls *TLS, path uintptr, amode int32) int32 { 33 | r, _, err := syscall.Syscall(syscall.SYS_ACCESS, path, uintptr(amode), 0) 34 | if strace { 35 | fmt.Fprintf(os.Stderr, "access(%q) %v %v\n", GoString(path), r, err) 36 | } 37 | if err != 0 { 38 | tls.setErrno(err) 39 | } 40 | return int32(r) 41 | } 42 | 43 | // int unlink(const char *path); 44 | func Xunlink(tls *TLS, path uintptr) int32 { 45 | r, _, err := syscall.Syscall(syscall.SYS_UNLINK, path, 0, 0) 46 | if strace { 47 | fmt.Fprintf(os.Stderr, "unlink(%q) %v %v\n", GoString(path), r, err) 48 | } 49 | if err != 0 { 50 | tls.setErrno(err) 51 | } 52 | return int32(r) 53 | } 54 | 55 | // int rmdir(const char *pathname); 56 | func Xrmdir(tls *TLS, pathname uintptr) int32 { 57 | panic("TODO rmdir") 58 | } 59 | 60 | // int fchown(int fd, uid_t owner, gid_t group); 61 | func Xfchown(tls *TLS, fd int32, owner, group uint32) int32 { 62 | panic("TODO fchown") 63 | } 64 | 65 | // uid_t getuid(void); 66 | func Xgetuid(tls *TLS) uint32 { 67 | r, _, _ := syscall.RawSyscall(syscall.SYS_GETUID, 0, 0, 0) 68 | if strace { 69 | fmt.Fprintf(os.Stderr, "getuid() %v\n", r) 70 | } 71 | return uint32(r) 72 | } 73 | 74 | // uid_t geteuid(void); 75 | func Xgeteuid(tls *TLS) uint32 { 76 | r, _, _ := syscall.RawSyscall(syscall.SYS_GETEUID, 0, 0, 0) 77 | if strace { 78 | fmt.Fprintf(os.Stderr, "geteuid() %v\n", r) 79 | } 80 | return uint32(r) 81 | } 82 | 83 | // int fsync(int fildes); 84 | func Xfsync(tls *TLS, fildes int32) int32 { 85 | r, _, err := syscall.Syscall(syscall.SYS_FSYNC, uintptr(fildes), 0, 0) 86 | if strace { 87 | fmt.Fprintf(os.Stderr, "fsync(%v) %v %v\n", fildes, r, err) 88 | } 89 | if err != 0 { 90 | tls.setErrno(err) 91 | } 92 | return int32(r) 93 | } 94 | 95 | // int fdatasync(int fd); 96 | func Xfdatasync(tls *TLS, fildes int32) int32 { 97 | r, _, err := syscall.Syscall(syscall.SYS_FDATASYNC, uintptr(fildes), 0, 0) 98 | if strace { 99 | fmt.Fprintf(os.Stderr, "fdatasync(%v) %v %v\n", fildes, r, err) 100 | } 101 | if err != 0 { 102 | tls.setErrno(err) 103 | } 104 | return int32(r) 105 | } 106 | 107 | // pid_t getpid(void); 108 | func Xgetpid(tls *TLS) int32 { 109 | r, _, _ := syscall.RawSyscall(syscall.SYS_GETPID, 0, 0, 0) 110 | if strace { 111 | fmt.Fprintf(os.Stderr, "getpid() %v\n", r) 112 | } 113 | return int32(r) 114 | } 115 | 116 | // unsigned sleep(unsigned seconds); 117 | func Xsleep(tls *TLS, seconds uint32) uint32 { 118 | time.Sleep(time.Duration(seconds) * time.Second) 119 | if strace { 120 | fmt.Fprintf(os.Stderr, "sleep(%#x)", seconds) 121 | } 122 | return 0 123 | } 124 | 125 | // off_t lseek64(int fildes, off_t offset, int whence); 126 | func Xlseek64(tls *TLS, fildes int32, offset int64, whence int32) int64 { 127 | r, _, err := syscall.Syscall(syscall.SYS_LSEEK, uintptr(fildes), uintptr(offset), uintptr(whence)) 128 | if strace { 129 | fmt.Fprintf(os.Stderr, "lseek(%v, %v, %v) %v %v\n", fildes, offset, whence, r, err) 130 | } 131 | if err != 0 { 132 | tls.setErrno(err) 133 | } 134 | return int64(r) 135 | } 136 | 137 | // int ftruncate(int fildes, off_t length); 138 | func Xftruncate64(tls *TLS, fildes int32, length int64) int32 { 139 | r, _, err := syscall.Syscall(syscall.SYS_FTRUNCATE, uintptr(fildes), uintptr(length), 0) 140 | if strace { 141 | fmt.Fprintf(os.Stderr, "ftruncate(%#x, %#x) %v, %v\n", fildes, length, r, err) 142 | } 143 | if err != 0 { 144 | tls.setErrno(err) 145 | } 146 | return int32(r) 147 | } 148 | 149 | // int usleep(useconds_t usec); 150 | func Xusleep(tls *TLS, usec uint32) int32 { 151 | time.Sleep(time.Duration(usec) * time.Microsecond) 152 | if strace { 153 | fmt.Fprintf(os.Stderr, "usleep(%#x)", usec) 154 | } 155 | return 0 156 | } 157 | 158 | // int chdir(const char *path); 159 | func Xchdir(tls *TLS, path uintptr) int32 { 160 | panic("TODO chdir") 161 | } 162 | 163 | // ssize_t read(int fd, void *buf, size_t count); 164 | func Xread(tls *TLS, fd int32, buf uintptr, count size_t) ssize_t { //TODO stdin 165 | r, _, err := syscall.Syscall(syscall.SYS_READ, uintptr(fd), buf, uintptr(count)) 166 | if strace { 167 | fmt.Fprintf(os.Stderr, "read(%v, %#x, %v) %v %v\n", fd, buf, count, r, err) 168 | } 169 | if err != 0 { 170 | tls.setErrno(err) 171 | } 172 | return ssize_t(r) 173 | } 174 | 175 | // char *getcwd(char *buf, size_t size); 176 | func Xgetcwd(tls *TLS, buf uintptr, size size_t) uintptr { 177 | r, _, err := syscall.Syscall(syscall.SYS_GETCWD, buf, uintptr(size), 0) 178 | if strace { 179 | fmt.Fprintf(os.Stderr, "getcwd(%#x, %#x) %v %v %q\n", buf, size, r, err, GoString(buf)) 180 | } 181 | if err != 0 { 182 | tls.setErrno(err) 183 | } 184 | return r 185 | } 186 | 187 | // ssize_t write(int fd, const void *buf, size_t count); 188 | func Xwrite(tls *TLS, fd int32, buf uintptr, count size_t) ssize_t { 189 | switch fd { 190 | case unistd.XSTDOUT_FILENO: 191 | n, err := os.Stdout.Write((*rawmem)(unsafe.Pointer(buf))[:count]) 192 | if err != nil { 193 | tls.setErrno(err) 194 | } 195 | return ssize_t(n) 196 | case unistd.XSTDERR_FILENO: 197 | n, err := os.Stderr.Write((*rawmem)(unsafe.Pointer(buf))[:count]) 198 | if err != nil { 199 | tls.setErrno(err) 200 | } 201 | return ssize_t(n) 202 | } 203 | r, _, err := syscall.Syscall(syscall.SYS_WRITE, uintptr(fd), buf, uintptr(count)) 204 | if strace { 205 | fmt.Fprintf(os.Stderr, "write(%v, %#x, %v) %v %v\n", fd, buf, count, r, err) 206 | } 207 | if err != 0 { 208 | tls.setErrno(err) 209 | } 210 | return ssize_t(r) 211 | } 212 | 213 | // ssize_t readlink(const char *pathname, char *buf, size_t bufsiz); 214 | func Xreadlink(tls *TLS, pathname, buf uintptr, bufsiz size_t) ssize_t { 215 | panic("TODO readlink") 216 | } 217 | 218 | // long sysconf(int name); 219 | func Xsysconf(tls *TLS, name int32) int64 { 220 | switch name { 221 | case unistd.X_SC_PAGESIZE: 222 | return int64(os.Getpagesize()) 223 | default: 224 | panic(fmt.Errorf("%v(%#x)", name, name)) 225 | } 226 | } 227 | 228 | // int isatty(int fd); 229 | func Xisatty(tls *TLS, fd int32) int32 { 230 | if terminal.IsTerminal(int(fd)) { 231 | return 1 232 | } 233 | 234 | tls.setErrno(errno.XENOTTY) 235 | return 0 236 | } 237 | -------------------------------------------------------------------------------- /internal/crt/pthread_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "sync" 11 | "unsafe" 12 | 13 | "github.com/cznic/ccir/libc/errno" 14 | "github.com/cznic/ccir/libc/pthread" 15 | ) 16 | 17 | type mu struct { 18 | *sync.Cond 19 | attr int32 20 | count int 21 | owner uintptr 22 | sync.Mutex 23 | } 24 | 25 | type mutexMap struct { 26 | m map[uintptr]*mu 27 | sync.Mutex 28 | } 29 | 30 | func (m *mutexMap) mu(p uintptr) *mu { 31 | m.Lock() 32 | r := m.m[p] 33 | if r == nil { 34 | r = &mu{} 35 | r.Cond = sync.NewCond(&r.Mutex) 36 | m.m[p] = r 37 | } 38 | m.Unlock() 39 | return r 40 | } 41 | 42 | type threadState struct { 43 | c chan struct{} 44 | detached bool 45 | retval uintptr 46 | } 47 | 48 | type threadMap struct { 49 | m map[uintptr]*threadState 50 | sync.Mutex 51 | } 52 | 53 | var ( 54 | mutexes = &mutexMap{m: map[uintptr]*mu{}} 55 | threads = &threadMap{m: map[uintptr]*threadState{}} 56 | ) 57 | 58 | // extern int pthread_mutexattr_init(pthread_mutexattr_t * __attr); 59 | func Xpthread_mutexattr_init(tls *TLS, attr uintptr) int32 { 60 | var r int32 61 | if ptrace { 62 | fmt.Fprintf(os.Stderr, "pthread_mutexattr_init(%#x) %v\n", attr, r) 63 | } 64 | return r 65 | } 66 | 67 | // extern int pthread_mutexattr_settype(pthread_mutexattr_t * __attr, int __kind); 68 | func Xpthread_mutexattr_settype(tls *TLS, attr uintptr, kind int32) int32 { 69 | *(*int32)(unsafe.Pointer(attr)) = kind 70 | var r int32 71 | if ptrace { 72 | fmt.Fprintf(os.Stderr, "pthread_mutexattr_settype(%#x, %v) %v\n", attr, kind, r) 73 | } 74 | return r 75 | } 76 | 77 | // extern int pthread_mutex_init(pthread_mutex_t * __mutex, pthread_mutexattr_t * __mutexattr); 78 | func Xpthread_mutex_init(tls *TLS, mutex, mutexattr uintptr) int32 { 79 | attr := int32(pthread.XPTHREAD_MUTEX_NORMAL) 80 | if mutexattr != 0 { 81 | attr = *(*int32)(unsafe.Pointer(mutexattr)) 82 | } 83 | mutexes.mu(mutex).attr = attr 84 | var r int32 85 | if ptrace { 86 | fmt.Fprintf(os.Stderr, "pthread_mutex_init(%#x, %#x) %v\n", mutex, mutexattr, r) 87 | } 88 | return r 89 | } 90 | 91 | // extern int pthread_mutexattr_destroy(pthread_mutexattr_t * __attr); 92 | func Xpthread_mutexattr_destroy(tls *TLS, attr uintptr) int32 { 93 | *(*int32)(unsafe.Pointer(attr)) = -1 94 | var r int32 95 | if ptrace { 96 | fmt.Fprintf(os.Stderr, "pthread_mutexattr_destroy(%#x) %v\n", attr, r) 97 | } 98 | return r 99 | } 100 | 101 | // extern int pthread_mutex_destroy(pthread_mutex_t * __mutex); 102 | func Xpthread_mutex_destroy(tls *TLS, mutex uintptr) int32 { 103 | mutexes.Lock() 104 | delete(mutexes.m, mutex) 105 | mutexes.Unlock() 106 | var r int32 107 | if ptrace { 108 | fmt.Fprintf(os.Stderr, "pthread_mutex_destroy(%#x) %v\n", mutex, r) 109 | } 110 | return r 111 | } 112 | 113 | // extern int pthread_mutex_lock(pthread_mutex_t * __mutex); 114 | func Xpthread_mutex_lock(tls *TLS, mutex uintptr) int32 { 115 | threadID := tls.threadID 116 | mu := mutexes.mu(mutex) 117 | var r int32 118 | mu.Lock() 119 | switch mu.attr { 120 | case pthread.XPTHREAD_MUTEX_NORMAL: 121 | if mu.count == 0 { 122 | mu.owner = threadID 123 | mu.count = 1 124 | break 125 | } 126 | 127 | for mu.count != 0 { 128 | mu.Cond.Wait() 129 | } 130 | mu.owner = threadID 131 | mu.count = 1 132 | case pthread.XPTHREAD_MUTEX_RECURSIVE: 133 | if mu.count == 0 { 134 | mu.owner = threadID 135 | mu.count = 1 136 | break 137 | } 138 | 139 | if mu.owner == threadID { 140 | mu.count++ 141 | break 142 | } 143 | 144 | panic("TODO") 145 | default: 146 | panic(fmt.Errorf("attr %#x", mu.attr)) 147 | } 148 | if ptrace { 149 | fmt.Fprintf(os.Stderr, "pthread_mutex_lock(%#x: %+v [thread id %v]) %v\n", mutex, mu, threadID, r) 150 | } 151 | mu.Unlock() 152 | return r 153 | } 154 | 155 | // int pthread_mutex_trylock(pthread_mutex_t *mutex); 156 | func Xpthread_mutex_trylock(tls *TLS, mutex uintptr) int32 { 157 | threadID := tls.threadID 158 | mu := mutexes.mu(mutex) 159 | var r int32 160 | mu.Lock() 161 | switch mu.attr { 162 | case pthread.XPTHREAD_MUTEX_NORMAL: 163 | if mu.count == 0 { 164 | mu.count = 1 165 | mu.owner = threadID 166 | break 167 | } 168 | 169 | r = errno.XEBUSY 170 | default: 171 | panic(fmt.Errorf("attr %#x", mu.attr)) 172 | } 173 | if ptrace { 174 | fmt.Fprintf(os.Stderr, "pthread_mutex_trylock(%#x: %+v [thread id %v]) %v\n", mutex, mu, threadID, r) 175 | } 176 | mu.Unlock() 177 | return r 178 | } 179 | 180 | // extern int pthread_mutex_unlock(pthread_mutex_t * __mutex); 181 | func Xpthread_mutex_unlock(tls *TLS, mutex uintptr) int32 { 182 | threadID := tls.threadID 183 | mu := mutexes.mu(mutex) 184 | var r int32 185 | mu.Lock() 186 | switch mu.attr { 187 | case pthread.XPTHREAD_MUTEX_NORMAL: 188 | if mu.count == 0 { 189 | panic("TODO") 190 | } 191 | 192 | mu.owner = 0 193 | mu.count = 0 194 | mu.Cond.Broadcast() 195 | case pthread.XPTHREAD_MUTEX_RECURSIVE: 196 | if mu.count == 0 { 197 | panic("TODO") 198 | } 199 | 200 | if mu.owner == threadID { 201 | mu.count-- 202 | if mu.count != 0 { 203 | break 204 | } 205 | 206 | mu.owner = 0 207 | mu.Cond.Broadcast() 208 | break 209 | } 210 | 211 | panic("TODO") 212 | default: 213 | panic(fmt.Errorf("TODO %#x", mu.attr)) 214 | } 215 | if ptrace { 216 | fmt.Fprintf(os.Stderr, "pthread_mutex_unlock(%#x: %+v [thread id %v]) %v\n", mutex, mu, threadID, r) 217 | } 218 | mu.Unlock() 219 | return r 220 | } 221 | 222 | // pthread_t pthread_self(void); 223 | func Xpthread_self(tls *TLS) pthread_t { 224 | threadID := tls.threadID 225 | if ptrace { 226 | fmt.Fprintf(os.Stderr, "pthread_self() %v\n", threadID) 227 | } 228 | return pthread_t(threadID) 229 | } 230 | 231 | // extern int pthread_equal(pthread_t __thread1, pthread_t __thread2); 232 | func Xpthread_equal(tls *TLS, thread1, thread2 pthread_t) int32 { 233 | if thread1 == thread2 { 234 | return 1 235 | } 236 | 237 | var r int32 238 | if ptrace { 239 | fmt.Fprintf(os.Stderr, "pthread_equal(%v, %v) %v\n", thread1, thread2, r) 240 | } 241 | return r 242 | } 243 | 244 | // int pthread_join(pthread_t thread, void **value_ptr); 245 | func Xpthread_join(tls *TLS, thread pthread_t, value_ptr uintptr) int32 { 246 | panic("TODO pthread_join") 247 | threads.Lock() 248 | t := threads.m[uintptr(thread)] 249 | threads.Unlock() 250 | if t != nil { 251 | <-t.c 252 | if value_ptr != 0 { 253 | *(*uintptr)(unsafe.Pointer(value_ptr)) = t.retval 254 | } 255 | threads.Lock() 256 | delete(threads.m, uintptr(thread)) 257 | threads.Unlock() 258 | } 259 | var r int32 260 | if ptrace { 261 | fmt.Fprintf(os.Stderr, "pthread_join(%v, %#x) %v\n", thread, value_ptr, r) 262 | } 263 | return r 264 | } 265 | 266 | // int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void*), void *restrict arg); 267 | func Xpthread_create(tls *TLS, thread, attr, start_routine, arg uintptr) int32 { 268 | panic("TODO pthread_create") 269 | if attr != 0 { 270 | panic("TODO") 271 | } 272 | 273 | new := NewTLS() 274 | *(*uint64)(unsafe.Pointer(thread)) = uint64(new.threadID) 275 | threads.Lock() 276 | t := &threadState{c: make(chan struct{})} 277 | threads.m[new.threadID] = t 278 | threads.Unlock() 279 | ch := make(chan struct{}) 280 | go func() { 281 | close(ch) 282 | t.retval = (*(*func(*TLS, uintptr) uintptr)(unsafe.Pointer(&start_routine)))(new, arg) 283 | if ptrace { 284 | fmt.Fprintf(os.Stderr, "thread #%#x finished: %#x\n", new.threadID, t.retval) 285 | } 286 | close(t.c) 287 | if t.detached { 288 | threads.Lock() 289 | delete(threads.m, new.threadID) 290 | threads.Unlock() 291 | if ptrace { 292 | fmt.Fprintf(os.Stderr, "thread #%#x was detached", new.threadID) 293 | } 294 | } 295 | }() 296 | var r int32 297 | if ptrace { 298 | fmt.Fprintf(os.Stderr, "pthread_create(%#x, %#x, fn, %#x) #%#x %v\n", thread, attr, arg, new.threadID, r) 299 | } 300 | <-ch 301 | return r 302 | } 303 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | //go:generate sqlite2go -shell -o "main_${GOOS}_${GOARCH}.go" 2 | //go:generate gofmt -l -s -w . 3 | 4 | // Command sqlite3shell is a mechanically produced Go port of shell.c, part of 5 | // the SQLite project. 6 | // 7 | // Installation 8 | // 9 | // To install and/or update perform 10 | // 11 | // $ go get [-u] github.com/cznic/sqlite3shell 12 | // 13 | // Changelog 14 | // 15 | // 2018-03-06: Initial release. 16 | // 17 | // Status 18 | // 19 | // This is an early technology preview of sqlite2go - a support-sqlite-only 20 | // version of CCGO[0]. DO NOT USE IN PRODUCTION. Please help the development by 21 | // reporting any issues found at [1]. 22 | // 23 | // Supported platforms and operating systems 24 | // 25 | // In GOOS_GOARCH form 26 | // 27 | // linux_386 28 | // linux_amd64 29 | // 30 | // Windows port is planned and expected to be the next port. Contributors of 31 | // other OS/platforms are welcome. 32 | // 33 | // [0] http://github.com/cznic/ccgo 34 | // [1] http://github.com/cznic/sqlite3shell/issues 35 | // 36 | // Getting help 37 | // 38 | // Usage hints can be obtained via the -help command flag or the .help shell 39 | // command. 40 | // 41 | // $ sqlite3shell -help 42 | // Usage: ./sqlite3shell [OPTIONS] FILENAME [SQL] 43 | // FILENAME is the name of an SQLite database. A new database is created 44 | // if the file does not previously exist. 45 | // OPTIONS include: 46 | // -ascii set output mode to 'ascii' 47 | // -bail stop after hitting an error 48 | // -batch force batch I/O 49 | // -column set output mode to 'column' 50 | // -cmd COMMAND run "COMMAND" before reading stdin 51 | // -csv set output mode to 'csv' 52 | // -echo print commands before execution 53 | // -init FILENAME read/process named file 54 | // -[no]header turn headers on or off 55 | // -help show this message 56 | // -html set output mode to HTML 57 | // -interactive force interactive I/O 58 | // -line set output mode to 'line' 59 | // -list set output mode to 'list' 60 | // -lookaside SIZE N use N entries of SZ bytes for lookaside memory 61 | // -mmap N default mmap size set to N 62 | // -newline SEP set output row separator. Default: '\n' 63 | // -nullvalue TEXT set text string for NULL values. Default '' 64 | // -pagecache SIZE N use N slots of SZ bytes each for page cache memory 65 | // -quote set output mode to 'quote' 66 | // -separator SEP set output column separator. Default: '|' 67 | // -stats print memory stats before each finalize 68 | // -version show SQLite version 69 | // -vfs NAME use NAME as the default VFS 70 | // $ sqlite3shell db 71 | // SQLite version 3.21.0 2017-10-24 18:55:49 72 | // Enter ".help" for usage hints. 73 | // sqlite> .help 74 | // .auth ON|OFF Show authorizer callbacks 75 | // .backup ?DB? FILE Backup DB (default "main") to FILE 76 | // .bail on|off Stop after hitting an error. Default OFF 77 | // .binary on|off Turn binary output on or off. Default OFF 78 | // .cd DIRECTORY Change the working directory to DIRECTORY 79 | // .changes on|off Show number of rows changed by SQL 80 | // .check GLOB Fail if output since .testcase does not match 81 | // .clone NEWDB Clone data into NEWDB from the existing database 82 | // .databases List names and files of attached databases 83 | // .dbinfo ?DB? Show status information about the database 84 | // .dump ?TABLE? ... Dump the database in an SQL text format 85 | // If TABLE specified, only dump tables matching 86 | // LIKE pattern TABLE. 87 | // .echo on|off Turn command echo on or off 88 | // .eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN 89 | // .exit Exit this program 90 | // .fullschema ?--indent? Show schema and the content of sqlite_stat tables 91 | // .headers on|off Turn display of headers on or off 92 | // .help Show this message 93 | // .import FILE TABLE Import data from FILE into TABLE 94 | // .imposter INDEX TABLE Create imposter table TABLE on index INDEX 95 | // .indexes ?TABLE? Show names of all indexes 96 | // If TABLE specified, only show indexes for tables 97 | // matching LIKE pattern TABLE. 98 | // .limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT 99 | // .lint OPTIONS Report potential schema issues. Options: 100 | // fkey-indexes Find missing foreign key indexes 101 | // .load FILE ?ENTRY? Load an extension library 102 | // .log FILE|off Turn logging on or off. FILE can be stderr/stdout 103 | // .mode MODE ?TABLE? Set output mode where MODE is one of: 104 | // ascii Columns/rows delimited by 0x1F and 0x1E 105 | // csv Comma-separated values 106 | // column Left-aligned columns. (See .width) 107 | // html HTML code 108 | // insert SQL insert statements for TABLE 109 | // line One value per line 110 | // list Values delimited by "|" 111 | // quote Escape answers as for SQL 112 | // tabs Tab-separated values 113 | // tcl TCL list elements 114 | // .nullvalue STRING Use STRING in place of NULL values 115 | // .once FILENAME Output for the next SQL command only to FILENAME 116 | // .open ?OPTIONS? ?FILE? Close existing database and reopen FILE 117 | // The --new option starts with an empty file 118 | // .output ?FILENAME? Send output to FILENAME or stdout 119 | // .print STRING... Print literal STRING 120 | // .prompt MAIN CONTINUE Replace the standard prompts 121 | // .quit Exit this program 122 | // .read FILENAME Execute SQL in FILENAME 123 | // .restore ?DB? FILE Restore content of DB (default "main") from FILE 124 | // .save FILE Write in-memory database into FILE 125 | // .scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off 126 | // .schema ?PATTERN? Show the CREATE statements matching PATTERN 127 | // Add --indent for pretty-printing 128 | // .selftest ?--init? Run tests defined in the SELFTEST table 129 | // .separator COL ?ROW? Change the column separator and optionally the row 130 | // separator for both the output mode and .import 131 | // .sha3sum ?OPTIONS...? Compute a SHA3 hash of database content 132 | // .shell CMD ARGS... Run CMD ARGS... in a system shell 133 | // .show Show the current values for various settings 134 | // .stats ?on|off? Show stats or turn stats on or off 135 | // .system CMD ARGS... Run CMD ARGS... in a system shell 136 | // .tables ?TABLE? List names of tables 137 | // If TABLE specified, only list tables matching 138 | // LIKE pattern TABLE. 139 | // .testcase NAME Begin redirecting output to 'testcase-out.txt' 140 | // .timeout MS Try opening locked tables for MS milliseconds 141 | // .timer on|off Turn SQL timer on or off 142 | // .trace FILE|off Output each SQL statement as it is run 143 | // .vfsinfo ?AUX? Information about the top-level VFS 144 | // .vfslist List all available VFSes 145 | // .vfsname ?AUX? Print the name of the VFS stack 146 | // .width NUM1 NUM2 ... Set column widths for "column" mode 147 | // Negative values right-justify 148 | // sqlite> 149 | package main 150 | -------------------------------------------------------------------------------- /internal/crt/stdio_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The CRT Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crt 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | "os" 13 | "sync" 14 | "unsafe" 15 | 16 | "github.com/cznic/ccir/libc/errno" 17 | "github.com/cznic/ccir/libc/stdio" 18 | "github.com/cznic/internal/buffer" 19 | "github.com/cznic/mathutil" 20 | ) 21 | 22 | var ( 23 | stdin, stdout, stderr uintptr 24 | 25 | files = &fmap{ 26 | m: map[uintptr]*os.File{}, 27 | } 28 | nullReader = bytes.NewBuffer(nil) 29 | ) 30 | 31 | type fmap struct { 32 | m map[uintptr]*os.File 33 | mu sync.Mutex 34 | } 35 | 36 | func (m *fmap) add(f *os.File, u uintptr) { 37 | m.mu.Lock() 38 | m.m[u] = f 39 | m.mu.Unlock() 40 | } 41 | 42 | func (m *fmap) reader(u uintptr) io.Reader { 43 | switch u { 44 | case stdin: 45 | return os.Stdin 46 | case stdout, stderr: 47 | return nullReader 48 | } 49 | 50 | m.mu.Lock() 51 | f := m.m[u] 52 | m.mu.Unlock() 53 | return f 54 | } 55 | 56 | func (m *fmap) file(u uintptr) *os.File { 57 | switch u { 58 | case stdin: 59 | return os.Stdin 60 | case stdout: 61 | return os.Stdout 62 | case stderr: 63 | return os.Stderr 64 | } 65 | 66 | m.mu.Lock() 67 | f := m.m[u] 68 | m.mu.Unlock() 69 | return f 70 | } 71 | 72 | func (m *fmap) writer(u uintptr) io.Writer { 73 | switch u { 74 | case stdin: 75 | return ioutil.Discard 76 | case stdout: 77 | return os.Stdout 78 | case stderr: 79 | return os.Stderr 80 | } 81 | 82 | m.mu.Lock() 83 | f := m.m[u] 84 | m.mu.Unlock() 85 | return f 86 | } 87 | 88 | func (m *fmap) extract(u uintptr) *os.File { 89 | m.mu.Lock() 90 | f := m.m[u] 91 | delete(m.m, u) 92 | m.mu.Unlock() 93 | return f 94 | } 95 | 96 | // int printf(const char *format, ...); 97 | func Xprintf(tls *TLS, format uintptr /* *int8 */, args ...interface{}) int32 { 98 | return X__builtin_printf(tls, format, args...) 99 | } 100 | 101 | // int printf(const char *format, ...); 102 | func X__builtin_printf(tls *TLS, format uintptr /* *int8 */, args ...interface{}) int32 { 103 | return goFprintf(os.Stdout, format, args...) 104 | } 105 | 106 | func goFprintf(w io.Writer, format uintptr /* *int8 */, ap ...interface{}) int32 { 107 | var b buffer.Bytes 108 | written := 0 109 | for { 110 | c := *(*int8)(unsafe.Pointer(format)) 111 | format++ 112 | switch c { 113 | case 0: 114 | _, err := b.WriteTo(w) 115 | b.Close() 116 | if err != nil { 117 | return -1 118 | } 119 | 120 | return int32(written) 121 | case '%': 122 | modifiers := "" 123 | long := 0 124 | short := 0 125 | hash := false 126 | var w []interface{} 127 | more: 128 | c := *(*int8)(unsafe.Pointer(format)) 129 | format++ 130 | switch c { 131 | case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '-': 132 | modifiers += string(c) 133 | goto more 134 | case '#': 135 | hash = true 136 | goto more 137 | case '*': 138 | w = append(w, VAint32(&ap)) 139 | modifiers += string(c) 140 | goto more 141 | case 'c': 142 | arg := VAint32(&ap) 143 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sc", modifiers), append(w, arg)...) 144 | written += n 145 | case 'd', 'i': 146 | var arg interface{} 147 | switch long { 148 | case 0: 149 | arg = VAint32(&ap) 150 | case 1: 151 | arg = vaLong(&ap) 152 | default: 153 | arg = VAint64(&ap) 154 | } 155 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sd", modifiers), append(w, arg)...) 156 | written += n 157 | case 'l': 158 | long++ 159 | goto more 160 | case 'f': 161 | if hash { 162 | panic(fmt.Errorf("TODO #f")) 163 | } 164 | 165 | arg := VAfloat64(&ap) 166 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sf", modifiers), append(w, arg)...) 167 | written += n 168 | case 'h': 169 | short++ 170 | goto more 171 | case 'o': 172 | nz := false 173 | var arg interface{} 174 | switch long { 175 | case 0: 176 | v := VAuint32(&ap) 177 | nz = v != 0 178 | arg = v 179 | case 1: 180 | v := vaULong(&ap) 181 | nz = v != 0 182 | arg = v 183 | default: 184 | v := VAuint64(&ap) 185 | nz = v != 0 186 | arg = v 187 | } 188 | if hash && nz { 189 | b.WriteByte('0') 190 | written++ 191 | } 192 | 193 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%so", modifiers), append(w, arg)...) 194 | written += n 195 | case 'p': 196 | arg := VAuintptr(&ap) 197 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sp", modifiers), append(w, arg)...) 198 | written += n 199 | case 'g': 200 | if hash { 201 | panic(fmt.Errorf("TODO #g")) 202 | } 203 | 204 | arg := VAfloat64(&ap) 205 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sg", modifiers), append(w, arg)...) 206 | written += n 207 | case 's': 208 | arg := VAuintptr(&ap) 209 | if arg == 0 { 210 | break 211 | } 212 | 213 | var b2 buffer.Bytes 214 | for { 215 | c := *(*int8)(unsafe.Pointer(arg)) 216 | arg++ 217 | if c == 0 { 218 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%ss", modifiers), append(w, b2.Bytes())...) 219 | b2.Close() 220 | written += n 221 | break 222 | } 223 | 224 | b2.WriteByte(byte(c)) 225 | } 226 | case 'u': 227 | var arg interface{} 228 | switch long { 229 | case 0: 230 | arg = VAuint32(&ap) 231 | case 1: 232 | arg = vaULong(&ap) 233 | default: 234 | arg = VAuint64(&ap) 235 | } 236 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sd", modifiers), append(w, arg)...) 237 | written += n 238 | case 'x': 239 | nz := false 240 | var arg interface{} 241 | switch long { 242 | case 0: 243 | v := VAuint32(&ap) 244 | nz = v != 0 245 | arg = v 246 | case 1: 247 | v := vaULong(&ap) 248 | nz = v != 0 249 | arg = v 250 | default: 251 | v := VAuint64(&ap) 252 | nz = v != 0 253 | arg = v 254 | } 255 | if hash && nz { 256 | b.WriteString("0x") 257 | written += 2 258 | } 259 | 260 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sx", modifiers), append(w, arg)...) 261 | written += n 262 | case 'X': 263 | nz := false 264 | var arg interface{} 265 | switch long { 266 | case 0: 267 | v := VAuint32(&ap) 268 | nz = v != 0 269 | arg = v 270 | case 1: 271 | v := vaULong(&ap) 272 | nz = v != 0 273 | arg = v 274 | default: 275 | v := VAuint64(&ap) 276 | nz = v != 0 277 | arg = v 278 | } 279 | if hash && nz { 280 | b.WriteString("0X") 281 | written += 2 282 | } 283 | 284 | n, _ := fmt.Fprintf(&b, fmt.Sprintf("%%%sX", modifiers), append(w, arg)...) 285 | written += n 286 | default: 287 | panic(fmt.Errorf("TODO %q", "%"+string(c))) 288 | } 289 | default: 290 | b.WriteByte(byte(c)) 291 | written++ 292 | if c == '\n' { 293 | if _, err := b.WriteTo(w); err != nil { 294 | b.Close() 295 | return -1 296 | } 297 | b.Reset() 298 | } 299 | } 300 | } 301 | } 302 | 303 | // int sprintf(char *str, const char *format, ...); 304 | func X__builtin_sprintf(tls *TLS, str, format uintptr, args ...interface{}) int32 { 305 | w := memWriter(str) 306 | n := goFprintf(&w, format, args...) 307 | w.WriteByte(0) 308 | return n 309 | } 310 | 311 | // int sprintf(char *str, const char *format, ...); 312 | func Xsprintf(tls *TLS, str, format uintptr, args ...interface{}) int32 { 313 | return X__builtin_sprintf(tls, str, format, args...) 314 | } 315 | 316 | // int fputc(int c, FILE *stream); 317 | func Xfputc(tls *TLS, c int32, stream uintptr) int32 { 318 | w := files.writer(stream) 319 | if _, err := w.Write([]byte{byte(c)}); err != nil { 320 | return stdio.XEOF 321 | } 322 | 323 | return int32(byte(c)) 324 | } 325 | 326 | // int putc(int c, FILE *stream); 327 | func Xputc(tls *TLS, c int32, stream uintptr) int32 { 328 | panic("TODO putc") 329 | } 330 | 331 | // int putc(int c, FILE *stream); 332 | func X_IO_putc(tls *TLS, c int32, stream uintptr) int32 { return Xputc(tls, c, stream) } 333 | 334 | // FILE *fopen64(const char *path, const char *mode); 335 | func Xfopen64(tls *TLS, path, mode uintptr) uintptr { 336 | p := GoString(path) 337 | var u uintptr 338 | switch p { 339 | case os.Stderr.Name(): 340 | u = stderr 341 | case os.Stdin.Name(): 342 | u = stdin 343 | case os.Stdout.Name(): 344 | u = stdout 345 | default: 346 | var f *os.File 347 | var err error 348 | switch mode := GoString(mode); mode { 349 | case "a": 350 | if f, err = os.OpenFile(p, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666); err != nil { 351 | switch { 352 | case os.IsPermission(err): 353 | tls.setErrno(errno.XEPERM) 354 | default: 355 | tls.setErrno(errno.XEACCES) 356 | } 357 | } 358 | case "r", "rb": 359 | if f, err = os.OpenFile(p, os.O_RDONLY, 0666); err != nil { 360 | switch { 361 | case os.IsNotExist(err): 362 | tls.setErrno(errno.XENOENT) 363 | case os.IsPermission(err): 364 | tls.setErrno(errno.XEPERM) 365 | default: 366 | tls.setErrno(errno.XEACCES) 367 | } 368 | } 369 | case "w": 370 | if f, err = os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666); err != nil { 371 | switch { 372 | case os.IsPermission(err): 373 | tls.setErrno(errno.XEPERM) 374 | default: 375 | tls.setErrno(errno.XEACCES) 376 | } 377 | } 378 | default: 379 | panic(mode) 380 | } 381 | if f != nil { 382 | u = Xmalloc(tls, ptrSize) 383 | files.add(f, u) 384 | } 385 | } 386 | return u 387 | } 388 | 389 | // size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 390 | func fwrite(tls *TLS, ptr uintptr, size, nmemb size_t, stream uintptr) size_t { 391 | hi, lo := mathutil.MulUint128_64(uint64(size), uint64(nmemb)) 392 | if hi != 0 || lo > uint64(len(rawmem{})) { 393 | tls.setErrno(errno.XE2BIG) 394 | return 0 395 | } 396 | 397 | n, err := files.writer(stream).Write((*rawmem)(unsafe.Pointer(ptr))[:lo]) 398 | if err != nil { 399 | tls.setErrno(errno.XEIO) 400 | } 401 | return size_t(n) / size 402 | } 403 | 404 | // int fclose(FILE *stream); 405 | func Xfclose(tls *TLS, stream uintptr) int32 { 406 | switch stream { 407 | case stdin, stdout, stderr: 408 | tls.setErrno(errno.XEIO) 409 | return stdio.XEOF 410 | } 411 | 412 | f := files.extract(stream) 413 | if f == nil { 414 | tls.setErrno(errno.XEBADF) 415 | return stdio.XEOF 416 | } 417 | 418 | Xfree(tls, stream) 419 | if err := f.Close(); err != nil { 420 | tls.setErrno(errno.XEIO) 421 | return stdio.XEOF 422 | } 423 | 424 | return 0 425 | } 426 | 427 | // size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 428 | func fread(tls *TLS, ptr uintptr, size, nmemb size_t, stream uintptr) size_t { 429 | hi, lo := mathutil.MulUint128_64(uint64(size), uint64(nmemb)) 430 | if hi != 0 || lo > uint64(len(rawmem{})) { 431 | tls.setErrno(errno.XE2BIG) 432 | return 0 433 | } 434 | 435 | n, err := files.reader(stream).Read((*rawmem)(unsafe.Pointer(ptr))[:lo]) 436 | if err != nil { 437 | tls.setErrno(errno.XEIO) 438 | } 439 | return size_t(n) / size 440 | } 441 | 442 | func fseek(tls *TLS, stream uintptr, offset long_t, whence int32) int32 { 443 | f := files.file(stream) 444 | if f == nil { 445 | tls.setErrno(errno.XEBADF) 446 | return -1 447 | } 448 | 449 | if _, err := f.Seek(int64(offset), int(whence)); err != nil { 450 | tls.setErrno(errno.XEINVAL) 451 | return -1 452 | } 453 | 454 | return 0 455 | } 456 | 457 | func ftell(tls *TLS, stream uintptr) long_t { 458 | f := files.file(stream) 459 | if f == nil { 460 | tls.setErrno(errno.XEBADF) 461 | return -1 462 | } 463 | 464 | n, err := f.Seek(0, os.SEEK_CUR) 465 | if err != nil { 466 | tls.setErrno(errno.XEBADF) 467 | return -1 468 | } 469 | 470 | return long_t(n) 471 | } 472 | 473 | // int fgetc(FILE *stream); 474 | func Xfgetc(tls *TLS, stream uintptr) int32 { 475 | p := buffer.Get(1) 476 | if _, err := files.reader(stream).Read(*p); err != nil { 477 | buffer.Put(p) 478 | return stdio.XEOF 479 | } 480 | 481 | r := int32((*p)[0]) 482 | buffer.Put(p) 483 | return r 484 | } 485 | 486 | // char *fgets(char *s, int size, FILE *stream); 487 | func Xfgets(tls *TLS, s uintptr, size int32, stream uintptr) uintptr { 488 | f := files.reader(stream) 489 | p := buffer.Get(1) 490 | b := *p 491 | w := memWriter(s) 492 | ok := false 493 | for i := int(size) - 1; i > 0; i-- { 494 | _, err := f.Read(b) 495 | if err != nil { 496 | if !ok { 497 | buffer.Put(p) 498 | return 0 499 | } 500 | 501 | break 502 | } 503 | 504 | ok = true 505 | w.WriteByte(b[0]) 506 | if b[0] == '\n' { 507 | break 508 | } 509 | } 510 | w.WriteByte(0) 511 | buffer.Put(p) 512 | return s 513 | 514 | } 515 | 516 | // int __builtin_fprintf(void* stream, const char *format, ...); 517 | func X__builtin_fprintf(tls *TLS, stream, format uintptr, args ...interface{}) int32 { 518 | return goFprintf(files.writer(stream), format, args...) 519 | } 520 | 521 | // int fprintf(FILE * stream, const char *format, ...); 522 | func Xfprintf(tls *TLS, stream, format uintptr, args ...interface{}) int32 { 523 | return X__builtin_fprintf(tls, stream, format, args...) 524 | } 525 | 526 | // int fflush(FILE *stream); 527 | func Xfflush(tls *TLS, stream uintptr) int32 { 528 | f := files.file(stream) 529 | if f == nil { 530 | tls.setErrno(stdio.XEOF) 531 | return -1 532 | } 533 | 534 | if err := f.Sync(); err != nil { 535 | tls.setErrno(err) 536 | return -1 537 | } 538 | 539 | return 0 540 | } 541 | 542 | // int vprintf(const char *format, va_list ap); 543 | func Xvprintf(tls *TLS, format uintptr, ap []interface{}) int32 { 544 | return goFprintf(os.Stdout, format, ap...) 545 | } 546 | 547 | // int vfprintf(FILE *stream, const char *format, va_list ap); 548 | func Xvfprintf(tls *TLS, stream, format uintptr, ap []interface{}) int32 { 549 | return goFprintf(files.writer(stream), format, ap...) 550 | } 551 | 552 | // void rewind(FILE *stream); 553 | func Xrewind(tls *TLS, stream uintptr) { fseek(tls, stream, 0, int32(os.SEEK_SET)) } 554 | 555 | // FILE *popen(const char *command, const char *type); 556 | func Xpopen(tls *TLS, command, typ uintptr) uintptr { 557 | panic("TODO popen") 558 | } 559 | 560 | // int pclose(FILE *stream); 561 | func Xpclose(tls *TLS, stream uintptr) int32 { 562 | panic("TODO pclose") 563 | } 564 | 565 | // size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 566 | func Xfwrite(tls *TLS, ptr uintptr, size, nmemb size_t, stream uintptr) size_t { 567 | return fwrite(tls, ptr, size, nmemb, stream) 568 | } 569 | 570 | // size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 571 | func Xfread(tls *TLS, ptr uintptr, size, nmemb size_t, stream uintptr) size_t { 572 | return fread(tls, ptr, size, nmemb, stream) 573 | } 574 | 575 | // int fseek(FILE *stream, long offset, int whence); 576 | func Xfseek(tls *TLS, stream uintptr, offset long_t, whence int32) int32 { 577 | return fseek(tls, stream, offset, whence) 578 | } 579 | 580 | // long ftell(FILE *stream); 581 | func Xftell(tls *TLS, stream uintptr) long_t { return ftell(tls, stream) } 582 | 583 | // int setvbuf(FILE *stream, char *buf, int mode, size_t size); 584 | func Xsetvbuf(tls *TLS, stream, buf uintptr, mode int32, size size_t) int32 { 585 | return 0 //TODO setvbuf 586 | } 587 | --------------------------------------------------------------------------------