fix auth; update deps
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2020 Gabriel Vasile
|
||||
Copyright (c) 2018 Gabriel Vasile
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
-3
@@ -16,9 +16,6 @@
|
||||
<a href="https://goreportcard.com/report/github.com/gabriel-vasile/mimetype">
|
||||
<img alt="Go report card" src="https://goreportcard.com/badge/github.com/gabriel-vasile/mimetype">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/gabriel-vasile/mimetype">
|
||||
<img alt="Code coverage" src="https://codecov.io/gh/gabriel-vasile/mimetype/branch/master/graph/badge.svg?token=qcfJF1kkl2"/>
|
||||
</a>
|
||||
<a href="LICENSE">
|
||||
<img alt="License" src="https://img.shields.io/badge/License-MIT-green.svg">
|
||||
</a>
|
||||
|
||||
+74
-37
@@ -3,6 +3,7 @@ package magic
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -74,51 +75,87 @@ func CRX(raw []byte, limit uint32) bool {
|
||||
}
|
||||
|
||||
// Tar matches a (t)ape (ar)chive file.
|
||||
// Tar files are divided into 512 bytes records. First record contains a 257
|
||||
// bytes header padded with NUL.
|
||||
func Tar(raw []byte, _ uint32) bool {
|
||||
// The "magic" header field for files in in UStar (POSIX IEEE P1003.1) archives
|
||||
// has the prefix "ustar". The values of the remaining bytes in this field vary
|
||||
// by archiver implementation.
|
||||
if len(raw) >= 512 && bytes.HasPrefix(raw[257:], []byte{0x75, 0x73, 0x74, 0x61, 0x72}) {
|
||||
return true
|
||||
}
|
||||
const sizeRecord = 512
|
||||
|
||||
if len(raw) < 256 {
|
||||
// The structure of a tar header:
|
||||
// type TarHeader struct {
|
||||
// Name [100]byte
|
||||
// Mode [8]byte
|
||||
// Uid [8]byte
|
||||
// Gid [8]byte
|
||||
// Size [12]byte
|
||||
// Mtime [12]byte
|
||||
// Chksum [8]byte
|
||||
// Linkflag byte
|
||||
// Linkname [100]byte
|
||||
// Magic [8]byte
|
||||
// Uname [32]byte
|
||||
// Gname [32]byte
|
||||
// Devmajor [8]byte
|
||||
// Devminor [8]byte
|
||||
// }
|
||||
|
||||
if len(raw) < sizeRecord {
|
||||
return false
|
||||
}
|
||||
raw = raw[:sizeRecord]
|
||||
|
||||
// First 100 bytes of the header represent the file name.
|
||||
// Check if file looks like Gentoo GLEP binary package.
|
||||
if bytes.Contains(raw[:100], []byte("/gpkg-1\x00")) {
|
||||
return false
|
||||
}
|
||||
|
||||
// The older v7 format has no "magic" field, and therefore must be identified
|
||||
// with heuristics based on legal ranges of values for other header fields:
|
||||
// https://www.nationalarchives.gov.uk/PRONOM/Format/proFormatSearch.aspx?status=detailReport&id=385&strPageToDisplay=signatures
|
||||
rules := []struct {
|
||||
min, max uint8
|
||||
i int
|
||||
}{
|
||||
{0x21, 0xEF, 0},
|
||||
{0x30, 0x37, 105},
|
||||
{0x20, 0x37, 106},
|
||||
{0x00, 0x00, 107},
|
||||
{0x30, 0x37, 113},
|
||||
{0x20, 0x37, 114},
|
||||
{0x00, 0x00, 115},
|
||||
{0x30, 0x37, 121},
|
||||
{0x20, 0x37, 122},
|
||||
{0x00, 0x00, 123},
|
||||
{0x30, 0x37, 134},
|
||||
{0x30, 0x37, 146},
|
||||
{0x30, 0x37, 153},
|
||||
{0x00, 0x37, 154},
|
||||
// Get the checksum recorded into the file.
|
||||
recsum, err := tarParseOctal(raw[148:156])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, r := range rules {
|
||||
if raw[r.i] < r.min || raw[r.i] > r.max {
|
||||
return false
|
||||
}
|
||||
sum1, sum2 := tarChksum(raw)
|
||||
return recsum == sum1 || recsum == sum2
|
||||
}
|
||||
|
||||
// tarParseOctal converts octal string to decimal int.
|
||||
func tarParseOctal(b []byte) (int64, error) {
|
||||
// Because unused fields are filled with NULs, we need to skip leading NULs.
|
||||
// Fields may also be padded with spaces or NULs.
|
||||
// So we remove leading and trailing NULs and spaces to be sure.
|
||||
b = bytes.Trim(b, " \x00")
|
||||
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
x, err := strconv.ParseUint(tarParseString(b), 8, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(x), nil
|
||||
}
|
||||
|
||||
// tarParseString converts a NUL ended bytes slice to a string.
|
||||
func tarParseString(b []byte) string {
|
||||
if i := bytes.IndexByte(b, 0); i >= 0 {
|
||||
return string(b[:i])
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
for _, i := range []uint8{135, 147, 155} {
|
||||
if raw[i] != 0x00 && raw[i] != 0x20 {
|
||||
return false
|
||||
// tarChksum computes the checksum for the header block b.
|
||||
// The actual checksum is written to same b block after it has been calculated.
|
||||
// Before calculation the bytes from b reserved for checksum have placeholder
|
||||
// value of ASCII space 0x20.
|
||||
// POSIX specifies a sum of the unsigned byte values, but the Sun tar used
|
||||
// signed byte values. We compute and return both.
|
||||
func tarChksum(b []byte) (unsigned, signed int64) {
|
||||
for i, c := range b {
|
||||
if 148 <= i && i < 156 {
|
||||
c = ' ' // Treat the checksum field itself as all spaces.
|
||||
}
|
||||
unsigned += int64(c)
|
||||
signed += int64(int8(c))
|
||||
}
|
||||
|
||||
return true
|
||||
return unsigned, signed
|
||||
}
|
||||
|
||||
+4
-1
@@ -153,8 +153,11 @@ func ftyp(sigs ...[]byte) Detector {
|
||||
if len(raw) < 12 {
|
||||
return false
|
||||
}
|
||||
if !bytes.Equal(raw[4:8], []byte("ftyp")) {
|
||||
return false
|
||||
}
|
||||
for _, s := range sigs {
|
||||
if bytes.Equal(raw[4:12], append([]byte("ftyp"), s...)) {
|
||||
if bytes.Equal(raw[8:12], s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
+25
-19
@@ -1,7 +1,6 @@
|
||||
package magic
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -234,9 +233,10 @@ func GeoJSON(raw []byte, limit uint32) bool {
|
||||
// types.
|
||||
func NdJSON(raw []byte, limit uint32) bool {
|
||||
lCount, hasObjOrArr := 0, false
|
||||
sc := bufio.NewScanner(dropLastLine(raw, limit))
|
||||
for sc.Scan() {
|
||||
l := sc.Bytes()
|
||||
raw = dropLastLine(raw, limit)
|
||||
var l []byte
|
||||
for len(raw) != 0 {
|
||||
l, raw = scanLine(raw)
|
||||
// Empty lines are allowed in NDJSON.
|
||||
if l = trimRWS(trimLWS(l)); len(l) == 0 {
|
||||
continue
|
||||
@@ -301,20 +301,15 @@ func Svg(raw []byte, limit uint32) bool {
|
||||
}
|
||||
|
||||
// Srt matches a SubRip file.
|
||||
func Srt(in []byte, _ uint32) bool {
|
||||
s := bufio.NewScanner(bytes.NewReader(in))
|
||||
if !s.Scan() {
|
||||
return false
|
||||
}
|
||||
// First line must be 1.
|
||||
if s.Text() != "1" {
|
||||
return false
|
||||
}
|
||||
func Srt(raw []byte, _ uint32) bool {
|
||||
line, raw := scanLine(raw)
|
||||
|
||||
if !s.Scan() {
|
||||
// First line must be 1.
|
||||
if string(line) != "1" {
|
||||
return false
|
||||
}
|
||||
secondLine := s.Text()
|
||||
line, raw = scanLine(raw)
|
||||
secondLine := string(line)
|
||||
// Timestamp format (e.g: 00:02:16,612 --> 00:02:19,376) limits secondLine
|
||||
// length to exactly 29 characters.
|
||||
if len(secondLine) != 29 {
|
||||
@@ -325,14 +320,12 @@ func Srt(in []byte, _ uint32) bool {
|
||||
if strings.Contains(secondLine, ".") {
|
||||
return false
|
||||
}
|
||||
// For Go <1.17, comma is not recognised as a decimal separator by `time.Parse`.
|
||||
secondLine = strings.ReplaceAll(secondLine, ",", ".")
|
||||
// Second line must be a time range.
|
||||
ts := strings.Split(secondLine, " --> ")
|
||||
if len(ts) != 2 {
|
||||
return false
|
||||
}
|
||||
const layout = "15:04:05.000"
|
||||
const layout = "15:04:05,000"
|
||||
t0, err := time.Parse(layout, ts[0])
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -345,8 +338,9 @@ func Srt(in []byte, _ uint32) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
line, _ = scanLine(raw)
|
||||
// A third line must exist and not be empty. This is the actual subtitle text.
|
||||
return s.Scan() && len(s.Bytes()) != 0
|
||||
return len(line) != 0
|
||||
}
|
||||
|
||||
// Vtt matches a Web Video Text Tracks (WebVTT) file. See
|
||||
@@ -373,3 +367,15 @@ func Vtt(raw []byte, limit uint32) bool {
|
||||
return bytes.Equal(raw, []byte{0xEF, 0xBB, 0xBF, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54}) || // UTF-8 BOM and "WEBVTT"
|
||||
bytes.Equal(raw, []byte{0x57, 0x45, 0x42, 0x56, 0x54, 0x54}) // "WEBVTT"
|
||||
}
|
||||
|
||||
// dropCR drops a terminal \r from the data.
|
||||
func dropCR(data []byte) []byte {
|
||||
if len(data) > 0 && data[len(data)-1] == '\r' {
|
||||
return data[0 : len(data)-1]
|
||||
}
|
||||
return data
|
||||
}
|
||||
func scanLine(b []byte) (line, remainder []byte) {
|
||||
line, remainder, _ = bytes.Cut(b, []byte("\n"))
|
||||
return dropCR(line), remainder
|
||||
}
|
||||
|
||||
+8
-14
@@ -18,7 +18,7 @@ func Tsv(raw []byte, limit uint32) bool {
|
||||
}
|
||||
|
||||
func sv(in []byte, comma rune, limit uint32) bool {
|
||||
r := csv.NewReader(dropLastLine(in, limit))
|
||||
r := csv.NewReader(bytes.NewReader(dropLastLine(in, limit)))
|
||||
r.Comma = comma
|
||||
r.ReuseRecord = true
|
||||
r.LazyQuotes = true
|
||||
@@ -44,20 +44,14 @@ func sv(in []byte, comma rune, limit uint32) bool {
|
||||
// mimetype limits itself to ReadLimit bytes when performing a detection.
|
||||
// This means, for file formats like CSV for NDJSON, the last line of the input
|
||||
// can be an incomplete line.
|
||||
func dropLastLine(b []byte, cutAt uint32) io.Reader {
|
||||
if cutAt == 0 {
|
||||
return bytes.NewReader(b)
|
||||
func dropLastLine(b []byte, readLimit uint32) []byte {
|
||||
if readLimit == 0 || uint32(len(b)) < readLimit {
|
||||
return b
|
||||
}
|
||||
if uint32(len(b)) >= cutAt {
|
||||
for i := cutAt - 1; i > 0; i-- {
|
||||
if b[i] == '\n' {
|
||||
return bytes.NewReader(b[:i])
|
||||
}
|
||||
for i := len(b) - 1; i > 0; i-- {
|
||||
if b[i] == '\n' {
|
||||
return b[:i]
|
||||
}
|
||||
|
||||
// No newline was found between the 0 index and cutAt.
|
||||
return bytes.NewReader(b[:cutAt])
|
||||
}
|
||||
|
||||
return bytes.NewReader(b)
|
||||
return b
|
||||
}
|
||||
|
||||
+5
-3
@@ -7,14 +7,15 @@ package mimetype
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var defaultLimit uint32 = 3072
|
||||
|
||||
// readLimit is the maximum number of bytes from the input used when detecting.
|
||||
var readLimit uint32 = 3072
|
||||
var readLimit uint32 = defaultLimit
|
||||
|
||||
// Detect returns the MIME type found from the provided byte slice.
|
||||
//
|
||||
@@ -48,7 +49,7 @@ func DetectReader(r io.Reader) (*MIME, error) {
|
||||
// Using atomic because readLimit can be written at the same time in other goroutine.
|
||||
l := atomic.LoadUint32(&readLimit)
|
||||
if l == 0 {
|
||||
in, err = ioutil.ReadAll(r)
|
||||
in, err = io.ReadAll(r)
|
||||
if err != nil {
|
||||
return errMIME, err
|
||||
}
|
||||
@@ -103,6 +104,7 @@ func EqualsAny(s string, mimes ...string) bool {
|
||||
// SetLimit sets the maximum number of bytes read from input when detecting the MIME type.
|
||||
// Increasing the limit provides better detection for file formats which store
|
||||
// their magical numbers towards the end of the file: docx, pptx, xlsx, etc.
|
||||
// During detection data is read in a single block of size limit, i.e. it is not buffered.
|
||||
// A limit of 0 means the whole input file will be used.
|
||||
func SetLimit(limit uint32) {
|
||||
// Using atomic because readLimit can be read at the same time in other goroutine.
|
||||
|
||||
+29
@@ -1,5 +1,34 @@
|
||||
# Changelog
|
||||
|
||||
## 0.28.1
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.28.1.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Implement `http.ResponseWriter` to hook into various parts of the response process ([#837](https://github.com/getsentry/sentry-go/pull/837))
|
||||
|
||||
## 0.28.0
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.28.0.
|
||||
|
||||
### Features
|
||||
|
||||
- Add a `Fiber` performance tracing & error reporting integration ([#795](https://github.com/getsentry/sentry-go/pull/795))
|
||||
- Add performance tracing to the `Echo` integration ([#722](https://github.com/getsentry/sentry-go/pull/722))
|
||||
- Add performance tracing to the `FastHTTP` integration ([#732](https://github.com/getsentry/sentry-go/pull/723))
|
||||
- Add performance tracing to the `Iris` integration ([#809](https://github.com/getsentry/sentry-go/pull/809))
|
||||
- Add performance tracing to the `Negroni` integration ([#808](https://github.com/getsentry/sentry-go/pull/808))
|
||||
- Add `FailureIssueThreshold` & `RecoveryThreshold` to `MonitorConfig` ([#775](https://github.com/getsentry/sentry-go/pull/775))
|
||||
- Use `errors.Unwrap()` to create exception groups ([#792](https://github.com/getsentry/sentry-go/pull/792))
|
||||
- Add support for matching on strings for `ClientOptions.IgnoreErrors` & `ClientOptions.IgnoreTransactions` ([#819](https://github.com/getsentry/sentry-go/pull/819))
|
||||
- Add `http.request.method` attribute for performance span data ([#786](https://github.com/getsentry/sentry-go/pull/786))
|
||||
- Accept `interface{}` for span data values ([#784](https://github.com/getsentry/sentry-go/pull/784))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix missing stack trace for parsing error in `logrusentry` ([#689](https://github.com/getsentry/sentry-go/pull/689))
|
||||
|
||||
## 0.27.0
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.27.0.
|
||||
|
||||
-2
@@ -13,7 +13,6 @@
|
||||
[](https://github.com/getsentry/sentry-go/actions?query=workflow%3Ago-workflow)
|
||||
[](https://goreportcard.com/report/github.com/getsentry/sentry-go)
|
||||
[](https://discord.gg/Ww9hbqr)
|
||||
[](https://godoc.org/github.com/getsentry/sentry-go)
|
||||
[](https://pkg.go.dev/github.com/getsentry/sentry-go)
|
||||
|
||||
`sentry-go` provides a Sentry client implementation for the Go programming
|
||||
@@ -85,7 +84,6 @@ checkout the official documentation:
|
||||
|
||||
- [Bug Tracker](https://github.com/getsentry/sentry-go/issues)
|
||||
- [GitHub Project](https://github.com/getsentry/sentry-go)
|
||||
- [](https://godoc.org/github.com/getsentry/sentry-go)
|
||||
- [](https://pkg.go.dev/github.com/getsentry/sentry-go)
|
||||
- [](https://docs.sentry.io/platforms/go/)
|
||||
- [](https://github.com/getsentry/sentry-go/discussions)
|
||||
|
||||
+4
@@ -87,6 +87,10 @@ type MonitorConfig struct { //nolint: maligned // prefer readability over optima
|
||||
// A tz database string representing the timezone which the monitor's execution schedule is in.
|
||||
// See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
Timezone string `json:"timezone,omitempty"`
|
||||
// The number of consecutive failed check-ins it takes before an issue is created.
|
||||
FailureIssueThreshold int64 `json:"failure_issue_threshold,omitempty"`
|
||||
// The number of consecutive OK check-ins it takes before an issue is resolved.
|
||||
RecoveryThreshold int64 `json:"recovery_threshold,omitempty"`
|
||||
}
|
||||
|
||||
type CheckIn struct { //nolint: maligned // prefer readability over optimal memory layout
|
||||
|
||||
+1
-2
@@ -90,11 +90,10 @@ func NewDsn(rawURL string) (*Dsn, error) {
|
||||
// Port
|
||||
var port int
|
||||
if parsedURL.Port() != "" {
|
||||
parsedPort, err := strconv.Atoi(parsedURL.Port())
|
||||
port, err = strconv.Atoi(parsedURL.Port())
|
||||
if err != nil {
|
||||
return nil, &DsnParseError{"invalid port"}
|
||||
}
|
||||
port = parsedPort
|
||||
} else {
|
||||
port = scheme.defaultPort()
|
||||
}
|
||||
|
||||
+2
-2
@@ -140,7 +140,7 @@ func (iei *ignoreErrorsIntegration) processor(event *Event, _ *EventHint) *Event
|
||||
|
||||
for _, suspect := range suspects {
|
||||
for _, pattern := range iei.ignoreErrors {
|
||||
if pattern.Match([]byte(suspect)) {
|
||||
if pattern.Match([]byte(suspect)) || strings.Contains(suspect, pattern.String()) {
|
||||
Logger.Printf("Event dropped due to being matched by `IgnoreErrors` option."+
|
||||
"| Value matched: %s | Filter used: %s", suspect, pattern)
|
||||
return nil
|
||||
@@ -202,7 +202,7 @@ func (iei *ignoreTransactionsIntegration) processor(event *Event, _ *EventHint)
|
||||
}
|
||||
|
||||
for _, pattern := range iei.ignoreTransactions {
|
||||
if pattern.Match([]byte(suspect)) {
|
||||
if pattern.Match([]byte(suspect)) || strings.Contains(suspect, pattern.String()) {
|
||||
Logger.Printf("Transaction dropped due to being matched by `IgnoreTransactions` option."+
|
||||
"| Value matched: %s | Filter used: %s", suspect, pattern)
|
||||
return nil
|
||||
|
||||
+64
-28
@@ -3,6 +3,7 @@ package sentry
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -24,6 +25,9 @@ const profileType = "profile"
|
||||
// checkInType is the type of a check in event.
|
||||
const checkInType = "check_in"
|
||||
|
||||
// metricType is the type of a metric event.
|
||||
const metricType = "statsd"
|
||||
|
||||
// Level marks the severity of the event.
|
||||
type Level string
|
||||
|
||||
@@ -36,15 +40,6 @@ const (
|
||||
LevelFatal Level = "fatal"
|
||||
)
|
||||
|
||||
func getSensitiveHeaders() map[string]bool {
|
||||
return map[string]bool{
|
||||
"Authorization": true,
|
||||
"Cookie": true,
|
||||
"X-Forwarded-For": true,
|
||||
"X-Real-Ip": true,
|
||||
}
|
||||
}
|
||||
|
||||
// SdkInfo contains all metadata about about the SDK being used.
|
||||
type SdkInfo struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
@@ -170,6 +165,13 @@ type Request struct {
|
||||
Env map[string]string `json:"env,omitempty"`
|
||||
}
|
||||
|
||||
var sensitiveHeaders = map[string]struct{}{
|
||||
"Authorization": {},
|
||||
"Cookie": {},
|
||||
"X-Forwarded-For": {},
|
||||
"X-Real-Ip": {},
|
||||
}
|
||||
|
||||
// NewRequest returns a new Sentry Request from the given http.Request.
|
||||
//
|
||||
// NewRequest avoids operations that depend on network access. In particular, it
|
||||
@@ -200,7 +202,6 @@ func NewRequest(r *http.Request) *Request {
|
||||
env = map[string]string{"REMOTE_ADDR": addr, "REMOTE_PORT": port}
|
||||
}
|
||||
} else {
|
||||
sensitiveHeaders := getSensitiveHeaders()
|
||||
for k, v := range r.Header {
|
||||
if _, ok := sensitiveHeaders[k]; !ok {
|
||||
headers[k] = strings.Join(v, ",")
|
||||
@@ -222,11 +223,15 @@ func NewRequest(r *http.Request) *Request {
|
||||
|
||||
// Mechanism is the mechanism by which an exception was generated and handled.
|
||||
type Mechanism struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
HelpLink string `json:"help_link,omitempty"`
|
||||
Handled *bool `json:"handled,omitempty"`
|
||||
Data map[string]interface{} `json:"data,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
HelpLink string `json:"help_link,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Handled *bool `json:"handled,omitempty"`
|
||||
ParentID *int `json:"parent_id,omitempty"`
|
||||
ExceptionID int `json:"exception_id"`
|
||||
IsExceptionGroup bool `json:"is_exception_group,omitempty"`
|
||||
Data map[string]any `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// SetUnhandled indicates that the exception is an unhandled exception, i.e.
|
||||
@@ -318,6 +323,7 @@ type Event struct {
|
||||
Exception []Exception `json:"exception,omitempty"`
|
||||
DebugMeta *DebugMeta `json:"debug_meta,omitempty"`
|
||||
Attachments []*Attachment `json:"-"`
|
||||
Metrics []Metric `json:"-"`
|
||||
|
||||
// The fields below are only relevant for transactions.
|
||||
|
||||
@@ -339,27 +345,43 @@ type Event struct {
|
||||
// SetException appends the unwrapped errors to the event's exception list.
|
||||
//
|
||||
// maxErrorDepth is the maximum depth of the error chain we will look
|
||||
// into while unwrapping the errors.
|
||||
// into while unwrapping the errors. If maxErrorDepth is -1, we will
|
||||
// unwrap all errors in the chain.
|
||||
func (e *Event) SetException(exception error, maxErrorDepth int) {
|
||||
err := exception
|
||||
if err == nil {
|
||||
if exception == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < maxErrorDepth && err != nil; i++ {
|
||||
err := exception
|
||||
|
||||
for i := 0; err != nil && (i < maxErrorDepth || maxErrorDepth == -1); i++ {
|
||||
// Add the current error to the exception slice with its details
|
||||
e.Exception = append(e.Exception, Exception{
|
||||
Value: err.Error(),
|
||||
Type: reflect.TypeOf(err).String(),
|
||||
Stacktrace: ExtractStacktrace(err),
|
||||
})
|
||||
switch previous := err.(type) {
|
||||
case interface{ Unwrap() error }:
|
||||
err = previous.Unwrap()
|
||||
case interface{ Cause() error }:
|
||||
err = previous.Cause()
|
||||
default:
|
||||
err = nil
|
||||
|
||||
// Attempt to unwrap the error using the standard library's Unwrap method.
|
||||
// If errors.Unwrap returns nil, it means either there is no error to unwrap,
|
||||
// or the error does not implement the Unwrap method.
|
||||
unwrappedErr := errors.Unwrap(err)
|
||||
|
||||
if unwrappedErr != nil {
|
||||
// The error was successfully unwrapped using the standard library's Unwrap method.
|
||||
err = unwrappedErr
|
||||
continue
|
||||
}
|
||||
|
||||
cause, ok := err.(interface{ Cause() error })
|
||||
if !ok {
|
||||
// We cannot unwrap the error further.
|
||||
break
|
||||
}
|
||||
|
||||
// The error implements the Cause method, indicating it may have been wrapped
|
||||
// using the github.com/pkg/errors package.
|
||||
err = cause.Cause()
|
||||
}
|
||||
|
||||
// Add a trace of the current stack to the most recent error in a chain if
|
||||
@@ -370,8 +392,23 @@ func (e *Event) SetException(exception error, maxErrorDepth int) {
|
||||
e.Exception[0].Stacktrace = NewStacktrace()
|
||||
}
|
||||
|
||||
if len(e.Exception) <= 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// event.Exception should be sorted such that the most recent error is last.
|
||||
reverse(e.Exception)
|
||||
|
||||
for i := range e.Exception {
|
||||
e.Exception[i].Mechanism = &Mechanism{
|
||||
IsExceptionGroup: true,
|
||||
ExceptionID: i,
|
||||
}
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
e.Exception[i].Mechanism.ParentID = Pointer(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Event.Contexts map[string]interface{} => map[string]EventContext,
|
||||
@@ -492,13 +529,12 @@ func (e *Event) checkInMarshalJSON() ([]byte, error) {
|
||||
|
||||
// NewEvent creates a new Event.
|
||||
func NewEvent() *Event {
|
||||
event := Event{
|
||||
return &Event{
|
||||
Contexts: make(map[string]Context),
|
||||
Extra: make(map[string]interface{}),
|
||||
Tags: make(map[string]string),
|
||||
Modules: make(map[string]string),
|
||||
}
|
||||
return &event
|
||||
}
|
||||
|
||||
// Thread specifies threads that were running at the time of an event.
|
||||
|
||||
+8
-9
@@ -32,15 +32,14 @@ var knownCategories = map[Category]struct{}{
|
||||
|
||||
// String returns the category formatted for debugging.
|
||||
func (c Category) String() string {
|
||||
switch c {
|
||||
case "":
|
||||
if c == "" {
|
||||
return "CategoryAll"
|
||||
default:
|
||||
caser := cases.Title(language.English)
|
||||
rv := "Category"
|
||||
for _, w := range strings.Fields(string(c)) {
|
||||
rv += caser.String(w)
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
caser := cases.Title(language.English)
|
||||
rv := "Category"
|
||||
for _, w := range strings.Fields(string(c)) {
|
||||
rv += caser.String(w)
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
+427
@@ -0,0 +1,427 @@
|
||||
package sentry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"math"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
NumberOrString interface {
|
||||
int | string
|
||||
}
|
||||
|
||||
void struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
member void
|
||||
keyRegex = regexp.MustCompile(`[^a-zA-Z0-9_/.-]+`)
|
||||
valueRegex = regexp.MustCompile(`[^\w\d\s_:/@\.{}\[\]$-]+`)
|
||||
unitRegex = regexp.MustCompile(`[^a-z]+`)
|
||||
)
|
||||
|
||||
type MetricUnit struct {
|
||||
unit string
|
||||
}
|
||||
|
||||
func (m MetricUnit) toString() string {
|
||||
return m.unit
|
||||
}
|
||||
|
||||
func NanoSecond() MetricUnit {
|
||||
return MetricUnit{
|
||||
"nanosecond",
|
||||
}
|
||||
}
|
||||
|
||||
func MicroSecond() MetricUnit {
|
||||
return MetricUnit{
|
||||
"microsecond",
|
||||
}
|
||||
}
|
||||
|
||||
func MilliSecond() MetricUnit {
|
||||
return MetricUnit{
|
||||
"millisecond",
|
||||
}
|
||||
}
|
||||
|
||||
func Second() MetricUnit {
|
||||
return MetricUnit{
|
||||
"second",
|
||||
}
|
||||
}
|
||||
|
||||
func Minute() MetricUnit {
|
||||
return MetricUnit{
|
||||
"minute",
|
||||
}
|
||||
}
|
||||
|
||||
func Hour() MetricUnit {
|
||||
return MetricUnit{
|
||||
"hour",
|
||||
}
|
||||
}
|
||||
|
||||
func Day() MetricUnit {
|
||||
return MetricUnit{
|
||||
"day",
|
||||
}
|
||||
}
|
||||
|
||||
func Week() MetricUnit {
|
||||
return MetricUnit{
|
||||
"week",
|
||||
}
|
||||
}
|
||||
|
||||
func Bit() MetricUnit {
|
||||
return MetricUnit{
|
||||
"bit",
|
||||
}
|
||||
}
|
||||
|
||||
func Byte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"byte",
|
||||
}
|
||||
}
|
||||
|
||||
func KiloByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"kilobyte",
|
||||
}
|
||||
}
|
||||
|
||||
func KibiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"kibibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func MegaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"megabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func MebiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"mebibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func GigaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"gigabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func GibiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"gibibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func TeraByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"terabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func TebiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"tebibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func PetaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"petabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func PebiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"pebibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func ExaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"exabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func ExbiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"exbibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func Ratio() MetricUnit {
|
||||
return MetricUnit{
|
||||
"ratio",
|
||||
}
|
||||
}
|
||||
|
||||
func Percent() MetricUnit {
|
||||
return MetricUnit{
|
||||
"percent",
|
||||
}
|
||||
}
|
||||
|
||||
func CustomUnit(unit string) MetricUnit {
|
||||
return MetricUnit{
|
||||
unitRegex.ReplaceAllString(unit, ""),
|
||||
}
|
||||
}
|
||||
|
||||
type Metric interface {
|
||||
GetType() string
|
||||
GetTags() map[string]string
|
||||
GetKey() string
|
||||
GetUnit() string
|
||||
GetTimestamp() int64
|
||||
SerializeValue() string
|
||||
SerializeTags() string
|
||||
}
|
||||
|
||||
type abstractMetric struct {
|
||||
key string
|
||||
unit MetricUnit
|
||||
tags map[string]string
|
||||
// A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
timestamp int64
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetTags() map[string]string {
|
||||
return am.tags
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetKey() string {
|
||||
return am.key
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetUnit() string {
|
||||
return am.unit.toString()
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetTimestamp() int64 {
|
||||
return am.timestamp
|
||||
}
|
||||
|
||||
func (am abstractMetric) SerializeTags() string {
|
||||
var sb strings.Builder
|
||||
|
||||
values := make([]string, 0, len(am.tags))
|
||||
for k := range am.tags {
|
||||
values = append(values, k)
|
||||
}
|
||||
sortSlice(values)
|
||||
|
||||
for _, key := range values {
|
||||
val := sanitizeValue(am.tags[key])
|
||||
key = sanitizeKey(key)
|
||||
sb.WriteString(fmt.Sprintf("%s:%s,", key, val))
|
||||
}
|
||||
s := sb.String()
|
||||
if len(s) > 0 {
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Counter Metric.
|
||||
type CounterMetric struct {
|
||||
value float64
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (c *CounterMetric) Add(value float64) {
|
||||
c.value += value
|
||||
}
|
||||
|
||||
func (c CounterMetric) GetType() string {
|
||||
return "c"
|
||||
}
|
||||
|
||||
func (c CounterMetric) SerializeValue() string {
|
||||
return fmt.Sprintf(":%v", c.value)
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewCounterMetric(key string, unit MetricUnit, tags map[string]string, timestamp int64, value float64) CounterMetric {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return CounterMetric{
|
||||
value,
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
// Distribution Metric.
|
||||
type DistributionMetric struct {
|
||||
values []float64
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (d *DistributionMetric) Add(value float64) {
|
||||
d.values = append(d.values, value)
|
||||
}
|
||||
|
||||
func (d DistributionMetric) GetType() string {
|
||||
return "d"
|
||||
}
|
||||
|
||||
func (d DistributionMetric) SerializeValue() string {
|
||||
var sb strings.Builder
|
||||
for _, el := range d.values {
|
||||
sb.WriteString(fmt.Sprintf(":%v", el))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewDistributionMetric(key string, unit MetricUnit, tags map[string]string, timestamp int64, value float64) DistributionMetric {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return DistributionMetric{
|
||||
[]float64{value},
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
// Gauge Metric.
|
||||
type GaugeMetric struct {
|
||||
last float64
|
||||
min float64
|
||||
max float64
|
||||
sum float64
|
||||
count float64
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (g *GaugeMetric) Add(value float64) {
|
||||
g.last = value
|
||||
g.min = math.Min(g.min, value)
|
||||
g.max = math.Max(g.max, value)
|
||||
g.sum += value
|
||||
g.count++
|
||||
}
|
||||
|
||||
func (g GaugeMetric) GetType() string {
|
||||
return "g"
|
||||
}
|
||||
|
||||
func (g GaugeMetric) SerializeValue() string {
|
||||
return fmt.Sprintf(":%v:%v:%v:%v:%v", g.last, g.min, g.max, g.sum, g.count)
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewGaugeMetric(key string, unit MetricUnit, tags map[string]string, timestamp int64, value float64) GaugeMetric {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return GaugeMetric{
|
||||
value, // last
|
||||
value, // min
|
||||
value, // max
|
||||
value, // sum
|
||||
value, // count
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
// Set Metric.
|
||||
type SetMetric[T NumberOrString] struct {
|
||||
values map[T]void
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (s *SetMetric[T]) Add(value T) {
|
||||
s.values[value] = member
|
||||
}
|
||||
|
||||
func (s SetMetric[T]) GetType() string {
|
||||
return "s"
|
||||
}
|
||||
|
||||
func (s SetMetric[T]) SerializeValue() string {
|
||||
_hash := func(s string) uint32 {
|
||||
return crc32.ChecksumIEEE([]byte(s))
|
||||
}
|
||||
|
||||
values := make([]T, 0, len(s.values))
|
||||
for k := range s.values {
|
||||
values = append(values, k)
|
||||
}
|
||||
sortSlice(values)
|
||||
|
||||
var sb strings.Builder
|
||||
for _, el := range values {
|
||||
switch any(el).(type) {
|
||||
case int:
|
||||
sb.WriteString(fmt.Sprintf(":%v", el))
|
||||
case string:
|
||||
s := fmt.Sprintf("%v", el)
|
||||
sb.WriteString(fmt.Sprintf(":%d", _hash(s)))
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewSetMetric[T NumberOrString](key string, unit MetricUnit, tags map[string]string, timestamp int64, value T) SetMetric[T] {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return SetMetric[T]{
|
||||
map[T]void{
|
||||
value: member,
|
||||
},
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
func sanitizeKey(s string) string {
|
||||
return keyRegex.ReplaceAllString(s, "_")
|
||||
}
|
||||
|
||||
func sanitizeValue(s string) string {
|
||||
return valueRegex.ReplaceAllString(s, "")
|
||||
}
|
||||
|
||||
type Ordered interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~string
|
||||
}
|
||||
|
||||
func sortSlice[T Ordered](s []T) {
|
||||
sort.Slice(s, func(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
})
|
||||
}
|
||||
+11
-12
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
// The version of the SDK.
|
||||
const SDKVersion = "0.27.0"
|
||||
const SDKVersion = "0.28.1"
|
||||
|
||||
// apiVersion is the minimum version of the Sentry API compatible with the
|
||||
// sentry-go SDK.
|
||||
@@ -72,18 +72,17 @@ func Recover() *EventID {
|
||||
|
||||
// RecoverWithContext captures a panic and passes relevant context object.
|
||||
func RecoverWithContext(ctx context.Context) *EventID {
|
||||
if err := recover(); err != nil {
|
||||
var hub *Hub
|
||||
|
||||
if HasHubOnContext(ctx) {
|
||||
hub = GetHubFromContext(ctx)
|
||||
} else {
|
||||
hub = CurrentHub()
|
||||
}
|
||||
|
||||
return hub.RecoverWithContext(ctx, err)
|
||||
err := recover()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
|
||||
hub := GetHubFromContext(ctx)
|
||||
if hub == nil {
|
||||
hub = CurrentHub()
|
||||
}
|
||||
|
||||
return hub.RecoverWithContext(ctx, err)
|
||||
}
|
||||
|
||||
// WithScope is a shorthand for CurrentHub().WithScope.
|
||||
|
||||
+20
-15
@@ -7,8 +7,8 @@ import (
|
||||
|
||||
// Checks whether the transaction should be profiled (according to ProfilesSampleRate)
|
||||
// and starts a profiler if so.
|
||||
func (span *Span) sampleTransactionProfile() {
|
||||
var sampleRate = span.clientOptions().ProfilesSampleRate
|
||||
func (s *Span) sampleTransactionProfile() {
|
||||
var sampleRate = s.clientOptions().ProfilesSampleRate
|
||||
switch {
|
||||
case sampleRate < 0.0 || sampleRate > 1.0:
|
||||
Logger.Printf("Skipping transaction profiling: ProfilesSampleRate out of range [0.0, 1.0]: %f\n", sampleRate)
|
||||
@@ -19,7 +19,7 @@ func (span *Span) sampleTransactionProfile() {
|
||||
if globalProfiler == nil {
|
||||
Logger.Println("Skipping transaction profiling: the profiler couldn't be started")
|
||||
} else {
|
||||
span.collectProfile = collectTransactionProfile
|
||||
s.collectProfile = collectTransactionProfile
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,22 +69,27 @@ func (info *profileInfo) UpdateFromEvent(event *Event) {
|
||||
info.Dist = event.Dist
|
||||
info.Transaction.ID = event.EventID
|
||||
|
||||
getStringFromContext := func(context map[string]interface{}, originalValue, key string) string {
|
||||
v, ok := context[key]
|
||||
if !ok {
|
||||
return originalValue
|
||||
}
|
||||
|
||||
if s, ok := v.(string); ok {
|
||||
return s
|
||||
}
|
||||
|
||||
return originalValue
|
||||
}
|
||||
|
||||
if runtimeContext, ok := event.Contexts["runtime"]; ok {
|
||||
if value, ok := runtimeContext["name"]; !ok {
|
||||
info.Runtime.Name = value.(string)
|
||||
}
|
||||
if value, ok := runtimeContext["version"]; !ok {
|
||||
info.Runtime.Version = value.(string)
|
||||
}
|
||||
info.Runtime.Name = getStringFromContext(runtimeContext, info.Runtime.Name, "name")
|
||||
info.Runtime.Version = getStringFromContext(runtimeContext, info.Runtime.Version, "version")
|
||||
}
|
||||
if osContext, ok := event.Contexts["os"]; ok {
|
||||
if value, ok := osContext["name"]; !ok {
|
||||
info.OS.Name = value.(string)
|
||||
}
|
||||
info.OS.Name = getStringFromContext(osContext, info.OS.Name, "name")
|
||||
}
|
||||
if deviceContext, ok := event.Contexts["device"]; ok {
|
||||
if value, ok := deviceContext["arch"]; !ok {
|
||||
info.Device.Architecture = value.(string)
|
||||
}
|
||||
info.Device.Architecture = getStringFromContext(deviceContext, info.Device.Architecture, "arch")
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -169,11 +169,11 @@ func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Sp
|
||||
|
||||
span.Sampled = span.sample()
|
||||
|
||||
span.recorder = &spanRecorder{}
|
||||
if hasParent {
|
||||
span.recorder = parent.spanRecorder()
|
||||
} else {
|
||||
span.recorder = &spanRecorder{}
|
||||
}
|
||||
|
||||
span.recorder.record(&span)
|
||||
|
||||
hub := hubFromContext(ctx)
|
||||
@@ -226,7 +226,11 @@ func (s *Span) SetTag(name, value string) {
|
||||
// SetData sets a data on the span. It is recommended to use SetData instead of
|
||||
// accessing the data map directly as SetData takes care of initializing the map
|
||||
// when necessary.
|
||||
func (s *Span) SetData(name, value string) {
|
||||
func (s *Span) SetData(name string, value interface{}) {
|
||||
if value == nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
|
||||
+98
-10
@@ -2,6 +2,7 @@ package sentry
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -94,6 +95,55 @@ func getRequestBodyFromEvent(event *Event) []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func marshalMetrics(metrics []Metric) []byte {
|
||||
var b bytes.Buffer
|
||||
for i, metric := range metrics {
|
||||
b.WriteString(metric.GetKey())
|
||||
if unit := metric.GetUnit(); unit != "" {
|
||||
b.WriteString(fmt.Sprintf("@%s", unit))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("%s|%s", metric.SerializeValue(), metric.GetType()))
|
||||
if serializedTags := metric.SerializeTags(); serializedTags != "" {
|
||||
b.WriteString(fmt.Sprintf("|#%s", serializedTags))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("|T%d", metric.GetTimestamp()))
|
||||
|
||||
if i < len(metrics)-1 {
|
||||
b.WriteString("\n")
|
||||
}
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func encodeMetric(enc *json.Encoder, b io.Writer, metrics []Metric) error {
|
||||
body := marshalMetrics(metrics)
|
||||
// Item header
|
||||
err := enc.Encode(struct {
|
||||
Type string `json:"type"`
|
||||
Length int `json:"length"`
|
||||
}{
|
||||
Type: metricType,
|
||||
Length: len(body),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// metric payload
|
||||
if _, err = b.Write(body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// "Envelopes should be terminated with a trailing newline."
|
||||
//
|
||||
// [1]: https://develop.sentry.dev/sdk/envelopes/#envelopes
|
||||
if _, err := b.Write([]byte("\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeAttachment(enc *json.Encoder, b io.Writer, attachment *Attachment) error {
|
||||
// Attachment header
|
||||
err := enc.Encode(struct {
|
||||
@@ -175,11 +225,15 @@ func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMes
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if event.Type == transactionType || event.Type == checkInType {
|
||||
switch event.Type {
|
||||
case transactionType, checkInType:
|
||||
err = encodeEnvelopeItem(enc, event.Type, body)
|
||||
} else {
|
||||
case metricType:
|
||||
err = encodeMetric(enc, &b, event.Metrics)
|
||||
default:
|
||||
err = encodeEnvelopeItem(enc, eventType, body)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -206,7 +260,7 @@ func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMes
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
func getRequestFromEvent(event *Event, dsn *Dsn) (r *http.Request, err error) {
|
||||
func getRequestFromEvent(ctx context.Context, event *Event, dsn *Dsn) (r *http.Request, err error) {
|
||||
defer func() {
|
||||
if r != nil {
|
||||
r.Header.Set("User-Agent", fmt.Sprintf("%s/%s", event.Sdk.Name, event.Sdk.Version))
|
||||
@@ -233,7 +287,13 @@ func getRequestFromEvent(event *Event, dsn *Dsn) (r *http.Request, err error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return http.NewRequest(
|
||||
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
return http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
dsn.GetAPIURL().String(),
|
||||
envelope,
|
||||
@@ -344,8 +404,13 @@ func (t *HTTPTransport) Configure(options ClientOptions) {
|
||||
})
|
||||
}
|
||||
|
||||
// SendEvent assembles a new packet out of Event and sends it to remote server.
|
||||
// SendEvent assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPTransport) SendEvent(event *Event) {
|
||||
t.SendEventWithContext(context.Background(), event)
|
||||
}
|
||||
|
||||
// SendEventWithContext assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPTransport) SendEventWithContext(ctx context.Context, event *Event) {
|
||||
if t.dsn == nil {
|
||||
return
|
||||
}
|
||||
@@ -356,7 +421,7 @@ func (t *HTTPTransport) SendEvent(event *Event) {
|
||||
return
|
||||
}
|
||||
|
||||
request, err := getRequestFromEvent(event, t.dsn)
|
||||
request, err := getRequestFromEvent(ctx, event, t.dsn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -478,6 +543,13 @@ func (t *HTTPTransport) worker() {
|
||||
Logger.Printf("There was an issue with sending an event: %v", err)
|
||||
continue
|
||||
}
|
||||
if response.StatusCode >= 400 && response.StatusCode <= 599 {
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
Logger.Printf("Error while reading response code: %v", err)
|
||||
}
|
||||
Logger.Printf("Sending %s failed with the following error: %s", eventType, string(b))
|
||||
}
|
||||
t.mu.Lock()
|
||||
t.limits.Merge(ratelimit.FromResponse(response))
|
||||
t.mu.Unlock()
|
||||
@@ -567,8 +639,13 @@ func (t *HTTPSyncTransport) Configure(options ClientOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
// SendEvent assembles a new packet out of Event and sends it to remote server.
|
||||
// SendEvent assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPSyncTransport) SendEvent(event *Event) {
|
||||
t.SendEventWithContext(context.Background(), event)
|
||||
}
|
||||
|
||||
// SendEventWithContext assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPSyncTransport) SendEventWithContext(ctx context.Context, event *Event) {
|
||||
if t.dsn == nil {
|
||||
return
|
||||
}
|
||||
@@ -577,15 +654,18 @@ func (t *HTTPSyncTransport) SendEvent(event *Event) {
|
||||
return
|
||||
}
|
||||
|
||||
request, err := getRequestFromEvent(event, t.dsn)
|
||||
request, err := getRequestFromEvent(ctx, event, t.dsn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var eventType string
|
||||
if event.Type == transactionType {
|
||||
switch {
|
||||
case event.Type == transactionType:
|
||||
eventType = "transaction"
|
||||
} else {
|
||||
case event.Type == metricType:
|
||||
eventType = metricType
|
||||
default:
|
||||
eventType = fmt.Sprintf("%s event", event.Level)
|
||||
}
|
||||
Logger.Printf(
|
||||
@@ -601,6 +681,14 @@ func (t *HTTPSyncTransport) SendEvent(event *Event) {
|
||||
Logger.Printf("There was an issue with sending an event: %v", err)
|
||||
return
|
||||
}
|
||||
if response.StatusCode >= 400 && response.StatusCode <= 599 {
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
Logger.Printf("Error while reading response code: %v", err)
|
||||
}
|
||||
Logger.Printf("Sending %s failed with the following error: %s", eventType, string(b))
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
t.limits.Merge(ratelimit.FromResponse(response))
|
||||
t.mu.Unlock()
|
||||
|
||||
+4
@@ -112,3 +112,7 @@ func revisionFromBuildInfo(info *debug.BuildInfo) string {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func Pointer[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
+7
-11
@@ -60,7 +60,7 @@ func main() {
|
||||
// Output: {"time":1516134303,"level":"debug","message":"hello world"}
|
||||
```
|
||||
> Note: By default log writes to `os.Stderr`
|
||||
> Note: The default log level for `log.Print` is *debug*
|
||||
> Note: The default log level for `log.Print` is *trace*
|
||||
|
||||
### Contextual Logging
|
||||
|
||||
@@ -412,15 +412,7 @@ Equivalent of `Lshortfile`:
|
||||
|
||||
```go
|
||||
zerolog.CallerMarshalFunc = func(pc uintptr, file string, line int) string {
|
||||
short := file
|
||||
for i := len(file) - 1; i > 0; i-- {
|
||||
if file[i] == '/' {
|
||||
short = file[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
file = short
|
||||
return file + ":" + strconv.Itoa(line)
|
||||
return filepath.Base(file) + ":" + strconv.Itoa(line)
|
||||
}
|
||||
log.Logger = log.With().Caller().Logger()
|
||||
log.Info().Msg("hello world")
|
||||
@@ -646,10 +638,14 @@ Some settings can be changed and will be applied to all loggers:
|
||||
* `zerolog.LevelFieldName`: Can be set to customize level field name.
|
||||
* `zerolog.MessageFieldName`: Can be set to customize message field name.
|
||||
* `zerolog.ErrorFieldName`: Can be set to customize `Err` field name.
|
||||
* `zerolog.TimeFieldFormat`: Can be set to customize `Time` field value formatting. If set with `zerolog.TimeFormatUnix`, `zerolog.TimeFormatUnixMs` or `zerolog.TimeFormatUnixMicro`, times are formated as UNIX timestamp.
|
||||
* `zerolog.TimeFieldFormat`: Can be set to customize `Time` field value formatting. If set with `zerolog.TimeFormatUnix`, `zerolog.TimeFormatUnixMs` or `zerolog.TimeFormatUnixMicro`, times are formatted as UNIX timestamp.
|
||||
* `zerolog.DurationFieldUnit`: Can be set to customize the unit for time.Duration type fields added by `Dur` (default: `time.Millisecond`).
|
||||
* `zerolog.DurationFieldInteger`: If set to `true`, `Dur` fields are formatted as integers instead of floats (default: `false`).
|
||||
* `zerolog.ErrorHandler`: Called whenever zerolog fails to write an event on its output. If not set, an error is printed on the stderr. This handler must be thread safe and non-blocking.
|
||||
* `zerolog.FloatingPointPrecision`: If set to a value other than -1, controls the number
|
||||
of digits when formatting float numbers in JSON. See
|
||||
[strconv.FormatFloat](https://pkg.go.dev/strconv#FormatFloat)
|
||||
for more details.
|
||||
|
||||
## Field Types
|
||||
|
||||
|
||||
+3
-3
@@ -183,13 +183,13 @@ func (a *Array) Uint64(i uint64) *Array {
|
||||
|
||||
// Float32 appends f as a float32 to the array.
|
||||
func (a *Array) Float32(f float32) *Array {
|
||||
a.buf = enc.AppendFloat32(enc.AppendArrayDelim(a.buf), f)
|
||||
a.buf = enc.AppendFloat32(enc.AppendArrayDelim(a.buf), f, FloatingPointPrecision)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float64 appends f as a float64 to the array.
|
||||
func (a *Array) Float64(f float64) *Array {
|
||||
a.buf = enc.AppendFloat64(enc.AppendArrayDelim(a.buf), f)
|
||||
a.buf = enc.AppendFloat64(enc.AppendArrayDelim(a.buf), f, FloatingPointPrecision)
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ func (a *Array) Time(t time.Time) *Array {
|
||||
|
||||
// Dur appends d to the array.
|
||||
func (a *Array) Dur(d time.Duration) *Array {
|
||||
a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger)
|
||||
a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
return a
|
||||
}
|
||||
|
||||
|
||||
+71
-20
@@ -28,6 +28,8 @@ const (
|
||||
|
||||
colorBold = 1
|
||||
colorDarkGray = 90
|
||||
|
||||
unknownLevel = "???"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -57,12 +59,21 @@ type ConsoleWriter struct {
|
||||
// TimeFormat specifies the format for timestamp in output.
|
||||
TimeFormat string
|
||||
|
||||
// TimeLocation tells ConsoleWriter’s default FormatTimestamp
|
||||
// how to localize the time.
|
||||
TimeLocation *time.Location
|
||||
|
||||
// PartsOrder defines the order of parts in output.
|
||||
PartsOrder []string
|
||||
|
||||
// PartsExclude defines parts to not display in output.
|
||||
PartsExclude []string
|
||||
|
||||
// FieldsOrder defines the order of contextual fields in output.
|
||||
FieldsOrder []string
|
||||
|
||||
fieldIsOrdered map[string]int
|
||||
|
||||
// FieldsExclude defines contextual fields to not display in output.
|
||||
FieldsExclude []string
|
||||
|
||||
@@ -83,9 +94,9 @@ type ConsoleWriter struct {
|
||||
// NewConsoleWriter creates and initializes a new ConsoleWriter.
|
||||
func NewConsoleWriter(options ...func(w *ConsoleWriter)) ConsoleWriter {
|
||||
w := ConsoleWriter{
|
||||
Out: os.Stdout,
|
||||
TimeFormat: consoleDefaultTimeFormat,
|
||||
PartsOrder: consoleDefaultPartsOrder(),
|
||||
Out: os.Stdout,
|
||||
TimeFormat: consoleDefaultTimeFormat,
|
||||
PartsOrder: consoleDefaultPartsOrder(),
|
||||
}
|
||||
|
||||
for _, opt := range options {
|
||||
@@ -185,7 +196,12 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
|
||||
}
|
||||
fields = append(fields, field)
|
||||
}
|
||||
sort.Strings(fields)
|
||||
|
||||
if len(w.FieldsOrder) > 0 {
|
||||
w.orderFields(fields)
|
||||
} else {
|
||||
sort.Strings(fields)
|
||||
}
|
||||
|
||||
// Write space only if something has already been written to the buffer, and if there are fields.
|
||||
if buf.Len() > 0 && len(fields) > 0 {
|
||||
@@ -284,7 +300,7 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
|
||||
}
|
||||
case TimestampFieldName:
|
||||
if w.FormatTimestamp == nil {
|
||||
f = consoleDefaultFormatTimestamp(w.TimeFormat, w.NoColor)
|
||||
f = consoleDefaultFormatTimestamp(w.TimeFormat, w.TimeLocation, w.NoColor)
|
||||
} else {
|
||||
f = w.FormatTimestamp
|
||||
}
|
||||
@@ -318,6 +334,32 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
|
||||
}
|
||||
}
|
||||
|
||||
// orderFields takes an array of field names and an array representing field order
|
||||
// and returns an array with any ordered fields at the beginning, in order,
|
||||
// and the remaining fields after in their original order.
|
||||
func (w ConsoleWriter) orderFields(fields []string) {
|
||||
if w.fieldIsOrdered == nil {
|
||||
w.fieldIsOrdered = make(map[string]int)
|
||||
for i, fieldName := range w.FieldsOrder {
|
||||
w.fieldIsOrdered[fieldName] = i
|
||||
}
|
||||
}
|
||||
sort.Slice(fields, func(i, j int) bool {
|
||||
ii, iOrdered := w.fieldIsOrdered[fields[i]]
|
||||
jj, jOrdered := w.fieldIsOrdered[fields[j]]
|
||||
if iOrdered && jOrdered {
|
||||
return ii < jj
|
||||
}
|
||||
if iOrdered {
|
||||
return true
|
||||
}
|
||||
if jOrdered {
|
||||
return false
|
||||
}
|
||||
return fields[i] < fields[j]
|
||||
})
|
||||
}
|
||||
|
||||
// needsQuote returns true when the string s should be quoted in output.
|
||||
func needsQuote(s string) bool {
|
||||
for i := range s {
|
||||
@@ -352,19 +394,23 @@ func consoleDefaultPartsOrder() []string {
|
||||
}
|
||||
}
|
||||
|
||||
func consoleDefaultFormatTimestamp(timeFormat string, noColor bool) Formatter {
|
||||
func consoleDefaultFormatTimestamp(timeFormat string, location *time.Location, noColor bool) Formatter {
|
||||
if timeFormat == "" {
|
||||
timeFormat = consoleDefaultTimeFormat
|
||||
}
|
||||
if location == nil {
|
||||
location = time.Local
|
||||
}
|
||||
|
||||
return func(i interface{}) string {
|
||||
t := "<nil>"
|
||||
switch tt := i.(type) {
|
||||
case string:
|
||||
ts, err := time.ParseInLocation(TimeFieldFormat, tt, time.Local)
|
||||
ts, err := time.ParseInLocation(TimeFieldFormat, tt, location)
|
||||
if err != nil {
|
||||
t = tt
|
||||
} else {
|
||||
t = ts.Local().Format(timeFormat)
|
||||
t = ts.In(location).Format(timeFormat)
|
||||
}
|
||||
case json.Number:
|
||||
i, err := tt.Int64()
|
||||
@@ -385,32 +431,37 @@ func consoleDefaultFormatTimestamp(timeFormat string, noColor bool) Formatter {
|
||||
}
|
||||
|
||||
ts := time.Unix(sec, nsec)
|
||||
t = ts.Format(timeFormat)
|
||||
t = ts.In(location).Format(timeFormat)
|
||||
}
|
||||
}
|
||||
return colorize(t, colorDarkGray, noColor)
|
||||
}
|
||||
}
|
||||
|
||||
func stripLevel(ll string) string {
|
||||
if len(ll) == 0 {
|
||||
return unknownLevel
|
||||
}
|
||||
if len(ll) > 3 {
|
||||
ll = ll[:3]
|
||||
}
|
||||
return strings.ToUpper(ll)
|
||||
}
|
||||
|
||||
func consoleDefaultFormatLevel(noColor bool) Formatter {
|
||||
return func(i interface{}) string {
|
||||
var l string
|
||||
if ll, ok := i.(string); ok {
|
||||
level, _ := ParseLevel(ll)
|
||||
fl, ok := FormattedLevels[level]
|
||||
if ok {
|
||||
l = colorize(fl, LevelColors[level], noColor)
|
||||
} else {
|
||||
l = strings.ToUpper(ll)[0:3]
|
||||
}
|
||||
} else {
|
||||
if i == nil {
|
||||
l = "???"
|
||||
} else {
|
||||
l = strings.ToUpper(fmt.Sprintf("%s", i))[0:3]
|
||||
return colorize(fl, LevelColors[level], noColor)
|
||||
}
|
||||
return stripLevel(ll)
|
||||
}
|
||||
return l
|
||||
if i == nil {
|
||||
return unknownLevel
|
||||
}
|
||||
return stripLevel(fmt.Sprintf("%s", i))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-8
@@ -325,25 +325,25 @@ func (c Context) Uints64(key string, i []uint64) Context {
|
||||
|
||||
// Float32 adds the field key with f as a float32 to the logger context.
|
||||
func (c Context) Float32(key string, f float32) Context {
|
||||
c.l.context = enc.AppendFloat32(enc.AppendKey(c.l.context, key), f)
|
||||
c.l.context = enc.AppendFloat32(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
// Floats32 adds the field key with f as a []float32 to the logger context.
|
||||
func (c Context) Floats32(key string, f []float32) Context {
|
||||
c.l.context = enc.AppendFloats32(enc.AppendKey(c.l.context, key), f)
|
||||
c.l.context = enc.AppendFloats32(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
// Float64 adds the field key with f as a float64 to the logger context.
|
||||
func (c Context) Float64(key string, f float64) Context {
|
||||
c.l.context = enc.AppendFloat64(enc.AppendKey(c.l.context, key), f)
|
||||
c.l.context = enc.AppendFloat64(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
// Floats64 adds the field key with f as a []float64 to the logger context.
|
||||
func (c Context) Floats64(key string, f []float64) Context {
|
||||
c.l.context = enc.AppendFloats64(enc.AppendKey(c.l.context, key), f)
|
||||
c.l.context = enc.AppendFloats64(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -365,13 +365,13 @@ func (c Context) Timestamp() Context {
|
||||
return c
|
||||
}
|
||||
|
||||
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
// Time adds the field key with t formatted as string using zerolog.TimeFieldFormat.
|
||||
func (c Context) Time(key string, t time.Time) Context {
|
||||
c.l.context = enc.AppendTime(enc.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
}
|
||||
|
||||
// Times adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
// Times adds the field key with t formatted as string using zerolog.TimeFieldFormat.
|
||||
func (c Context) Times(key string, t []time.Time) Context {
|
||||
c.l.context = enc.AppendTimes(enc.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
@@ -379,13 +379,13 @@ func (c Context) Times(key string, t []time.Time) Context {
|
||||
|
||||
// Dur adds the fields key with d divided by unit and stored as a float.
|
||||
func (c Context) Dur(key string, d time.Duration) Context {
|
||||
c.l.context = enc.AppendDuration(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
c.l.context = enc.AppendDuration(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
// Durs adds the fields key with d divided by unit and stored as a float.
|
||||
func (c Context) Durs(key string, d []time.Duration) Context {
|
||||
c.l.context = enc.AppendDurations(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
c.l.context = enc.AppendDurations(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -409,6 +409,12 @@ func (c Context) Any(key string, i interface{}) Context {
|
||||
return c.Interface(key, i)
|
||||
}
|
||||
|
||||
// Reset removes all the context fields.
|
||||
func (c Context) Reset() Context {
|
||||
c.l.context = enc.AppendBeginMarker(make([]byte, 0, 500))
|
||||
return c
|
||||
}
|
||||
|
||||
type callerHook struct {
|
||||
callerSkipFrameCount int
|
||||
}
|
||||
|
||||
+6
-6
@@ -13,13 +13,13 @@ type encoder interface {
|
||||
AppendBool(dst []byte, val bool) []byte
|
||||
AppendBools(dst []byte, vals []bool) []byte
|
||||
AppendBytes(dst, s []byte) []byte
|
||||
AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte
|
||||
AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte
|
||||
AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, precision int) []byte
|
||||
AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, precision int) []byte
|
||||
AppendEndMarker(dst []byte) []byte
|
||||
AppendFloat32(dst []byte, val float32) []byte
|
||||
AppendFloat64(dst []byte, val float64) []byte
|
||||
AppendFloats32(dst []byte, vals []float32) []byte
|
||||
AppendFloats64(dst []byte, vals []float64) []byte
|
||||
AppendFloat32(dst []byte, val float32, precision int) []byte
|
||||
AppendFloat64(dst []byte, val float64, precision int) []byte
|
||||
AppendFloats32(dst []byte, vals []float32, precision int) []byte
|
||||
AppendFloats64(dst []byte, vals []float64, precision int) []byte
|
||||
AppendHex(dst, s []byte) []byte
|
||||
AppendIPAddr(dst []byte, ip net.IP) []byte
|
||||
AppendIPPrefix(dst []byte, pfx net.IPNet) []byte
|
||||
|
||||
+7
-7
@@ -644,7 +644,7 @@ func (e *Event) Float32(key string, f float32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendFloat32(enc.AppendKey(e.buf, key), f)
|
||||
e.buf = enc.AppendFloat32(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -653,7 +653,7 @@ func (e *Event) Floats32(key string, f []float32) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendFloats32(enc.AppendKey(e.buf, key), f)
|
||||
e.buf = enc.AppendFloats32(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -662,7 +662,7 @@ func (e *Event) Float64(key string, f float64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendFloat64(enc.AppendKey(e.buf, key), f)
|
||||
e.buf = enc.AppendFloat64(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ func (e *Event) Floats64(key string, f []float64) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendFloats64(enc.AppendKey(e.buf, key), f)
|
||||
e.buf = enc.AppendFloats64(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -713,7 +713,7 @@ func (e *Event) Dur(key string, d time.Duration) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@ func (e *Event) Durs(key string, d []time.Duration) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendDurations(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = enc.AppendDurations(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -739,7 +739,7 @@ func (e *Event) TimeDiff(key string, t time.Time, start time.Time) *Event {
|
||||
if t.After(start) {
|
||||
d = t.Sub(start)
|
||||
}
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -139,13 +139,13 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
|
||||
case uint64:
|
||||
dst = enc.AppendUint64(dst, val)
|
||||
case float32:
|
||||
dst = enc.AppendFloat32(dst, val)
|
||||
dst = enc.AppendFloat32(dst, val, FloatingPointPrecision)
|
||||
case float64:
|
||||
dst = enc.AppendFloat64(dst, val)
|
||||
dst = enc.AppendFloat64(dst, val, FloatingPointPrecision)
|
||||
case time.Time:
|
||||
dst = enc.AppendTime(dst, val, TimeFieldFormat)
|
||||
case time.Duration:
|
||||
dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
case *string:
|
||||
if val != nil {
|
||||
dst = enc.AppendString(dst, *val)
|
||||
@@ -220,13 +220,13 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
|
||||
}
|
||||
case *float32:
|
||||
if val != nil {
|
||||
dst = enc.AppendFloat32(dst, *val)
|
||||
dst = enc.AppendFloat32(dst, *val, FloatingPointPrecision)
|
||||
} else {
|
||||
dst = enc.AppendNil(dst)
|
||||
}
|
||||
case *float64:
|
||||
if val != nil {
|
||||
dst = enc.AppendFloat64(dst, *val)
|
||||
dst = enc.AppendFloat64(dst, *val, FloatingPointPrecision)
|
||||
} else {
|
||||
dst = enc.AppendNil(dst)
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
|
||||
}
|
||||
case *time.Duration:
|
||||
if val != nil {
|
||||
dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
} else {
|
||||
dst = enc.AppendNil(dst)
|
||||
}
|
||||
@@ -267,13 +267,13 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
|
||||
case []uint64:
|
||||
dst = enc.AppendUints64(dst, val)
|
||||
case []float32:
|
||||
dst = enc.AppendFloats32(dst, val)
|
||||
dst = enc.AppendFloats32(dst, val, FloatingPointPrecision)
|
||||
case []float64:
|
||||
dst = enc.AppendFloats64(dst, val)
|
||||
dst = enc.AppendFloats64(dst, val, FloatingPointPrecision)
|
||||
case []time.Time:
|
||||
dst = enc.AppendTimes(dst, val, TimeFieldFormat)
|
||||
case []time.Duration:
|
||||
dst = enc.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = enc.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
case nil:
|
||||
dst = enc.AppendNil(dst)
|
||||
case net.IP:
|
||||
|
||||
+22
-2
@@ -1,6 +1,7 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
@@ -81,8 +82,22 @@ var (
|
||||
}
|
||||
|
||||
// InterfaceMarshalFunc allows customization of interface marshaling.
|
||||
// Default: "encoding/json.Marshal"
|
||||
InterfaceMarshalFunc = json.Marshal
|
||||
// Default: "encoding/json.Marshal" with disabled HTML escaping
|
||||
InterfaceMarshalFunc = func(v interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
encoder := json.NewEncoder(&buf)
|
||||
encoder.SetEscapeHTML(false)
|
||||
err := encoder.Encode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := buf.Bytes()
|
||||
if len(b) > 0 {
|
||||
// Remove trailing \n which is added by Encode.
|
||||
return b[:len(b)-1], nil
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// TimeFieldFormat defines the time format of the Time field type. If set to
|
||||
// TimeFormatUnix, TimeFormatUnixMs, TimeFormatUnixMicro or TimeFormatUnixNano, the time is formatted as a UNIX
|
||||
@@ -136,6 +151,11 @@ var (
|
||||
// TriggerLevelWriterBufferReuseLimit is a limit in bytes that a buffer is dropped
|
||||
// from the TriggerLevelWriter buffer pool if the buffer grows above the limit.
|
||||
TriggerLevelWriterBufferReuseLimit = 64 * 1024
|
||||
|
||||
// FloatingPointPrecision, if set to a value other than -1, controls the number
|
||||
// of digits when formatting float numbers in JSON. See strconv.FormatFloat for
|
||||
// more details.
|
||||
FloatingPointPrecision = -1
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ func decodeFloat(src *bufio.Reader) (float64, int) {
|
||||
|
||||
switch minor {
|
||||
case additionalTypeFloat16:
|
||||
panic(fmt.Errorf("float16 is not suppported in decodeFloat"))
|
||||
panic(fmt.Errorf("float16 is not supported in decodeFloat"))
|
||||
|
||||
case additionalTypeFloat32:
|
||||
pb := readNBytes(src, 4)
|
||||
|
||||
+5
-5
@@ -29,7 +29,7 @@ func (e Encoder) appendFloatTimestamp(dst []byte, t time.Time) []byte {
|
||||
nanos := t.Nanosecond()
|
||||
var val float64
|
||||
val = float64(secs)*1.0 + float64(nanos)*1e-9
|
||||
return e.AppendFloat64(dst, val)
|
||||
return e.AppendFloat64(dst, val, -1)
|
||||
}
|
||||
|
||||
// AppendTime encodes and adds a timestamp to the dst byte array.
|
||||
@@ -64,17 +64,17 @@ func (e Encoder) AppendTimes(dst []byte, vals []time.Time, unused string) []byte
|
||||
// AppendDuration encodes and adds a duration to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, unused int) []byte {
|
||||
if useInt {
|
||||
return e.AppendInt64(dst, int64(d/unit))
|
||||
}
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit))
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit), unused)
|
||||
}
|
||||
|
||||
// AppendDurations encodes and adds an array of durations to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, unused int) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
@@ -87,7 +87,7 @@ func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Dur
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, d := range vals {
|
||||
dst = e.AppendDuration(dst, d, unit, useInt)
|
||||
dst = e.AppendDuration(dst, d, unit, useInt, unused)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
+6
-6
@@ -352,7 +352,7 @@ func (e Encoder) AppendUints64(dst []byte, vals []uint64) []byte {
|
||||
}
|
||||
|
||||
// AppendFloat32 encodes and inserts a single precision float value into the dst byte array.
|
||||
func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
|
||||
func (Encoder) AppendFloat32(dst []byte, val float32, unused int) []byte {
|
||||
switch {
|
||||
case math.IsNaN(float64(val)):
|
||||
return append(dst, "\xfa\x7f\xc0\x00\x00"...)
|
||||
@@ -372,7 +372,7 @@ func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
|
||||
}
|
||||
|
||||
// AppendFloats32 encodes and inserts an array of single precision float value into the dst byte array.
|
||||
func (e Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
|
||||
func (e Encoder) AppendFloats32(dst []byte, vals []float32, unused int) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
@@ -385,13 +385,13 @@ func (e Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = e.AppendFloat32(dst, v)
|
||||
dst = e.AppendFloat32(dst, v, unused)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat64 encodes and inserts a double precision float value into the dst byte array.
|
||||
func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
|
||||
func (Encoder) AppendFloat64(dst []byte, val float64, unused int) []byte {
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
return append(dst, "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"...)
|
||||
@@ -412,7 +412,7 @@ func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
|
||||
}
|
||||
|
||||
// AppendFloats64 encodes and inserts an array of double precision float values into the dst byte array.
|
||||
func (e Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
|
||||
func (e Encoder) AppendFloats64(dst []byte, vals []float64, unused int) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
@@ -425,7 +425,7 @@ func (e Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = e.AppendFloat64(dst, v)
|
||||
dst = e.AppendFloat64(dst, v, unused)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
+5
-5
@@ -88,24 +88,24 @@ func appendUnixNanoTimes(dst []byte, vals []time.Time, div int64) []byte {
|
||||
|
||||
// AppendDuration formats the input duration with the given unit & format
|
||||
// and appends the encoded string to the input byte slice.
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, precision int) []byte {
|
||||
if useInt {
|
||||
return strconv.AppendInt(dst, int64(d/unit), 10)
|
||||
}
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit))
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit), precision)
|
||||
}
|
||||
|
||||
// AppendDurations formats the input durations with the given unit & format
|
||||
// and appends the encoded string list to the input byte slice.
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, precision int) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = e.AppendDuration(dst, vals[0], unit, useInt)
|
||||
dst = e.AppendDuration(dst, vals[0], unit, useInt, precision)
|
||||
if len(vals) > 1 {
|
||||
for _, d := range vals[1:] {
|
||||
dst = e.AppendDuration(append(dst, ','), d, unit, useInt)
|
||||
dst = e.AppendDuration(append(dst, ','), d, unit, useInt, precision)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
|
||||
+33
-12
@@ -299,7 +299,7 @@ func (Encoder) AppendUints64(dst []byte, vals []uint64) []byte {
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendFloat(dst []byte, val float64, bitSize int) []byte {
|
||||
func appendFloat(dst []byte, val float64, bitSize, precision int) []byte {
|
||||
// JSON does not permit NaN or Infinity. A typical JSON encoder would fail
|
||||
// with an error, but a logging library wants the data to get through so we
|
||||
// make a tradeoff and store those types as string.
|
||||
@@ -311,26 +311,47 @@ func appendFloat(dst []byte, val float64, bitSize int) []byte {
|
||||
case math.IsInf(val, -1):
|
||||
return append(dst, `"-Inf"`...)
|
||||
}
|
||||
return strconv.AppendFloat(dst, val, 'f', -1, bitSize)
|
||||
// convert as if by es6 number to string conversion
|
||||
// see also https://cs.opensource.google/go/go/+/refs/tags/go1.20.3:src/encoding/json/encode.go;l=573
|
||||
strFmt := byte('f')
|
||||
// If precision is set to a value other than -1, we always just format the float using that precision.
|
||||
if precision == -1 {
|
||||
// Use float32 comparisons for underlying float32 value to get precise cutoffs right.
|
||||
if abs := math.Abs(val); abs != 0 {
|
||||
if bitSize == 64 && (abs < 1e-6 || abs >= 1e21) || bitSize == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
|
||||
strFmt = 'e'
|
||||
}
|
||||
}
|
||||
}
|
||||
dst = strconv.AppendFloat(dst, val, strFmt, precision, bitSize)
|
||||
if strFmt == 'e' {
|
||||
// Clean up e-09 to e-9
|
||||
n := len(dst)
|
||||
if n >= 4 && dst[n-4] == 'e' && dst[n-3] == '-' && dst[n-2] == '0' {
|
||||
dst[n-2] = dst[n-1]
|
||||
dst = dst[:n-1]
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat32 converts the input float32 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
|
||||
return appendFloat(dst, float64(val), 32)
|
||||
func (Encoder) AppendFloat32(dst []byte, val float32, precision int) []byte {
|
||||
return appendFloat(dst, float64(val), 32, precision)
|
||||
}
|
||||
|
||||
// AppendFloats32 encodes the input float32s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func (Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
|
||||
func (Encoder) AppendFloats32(dst []byte, vals []float32, precision int) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = appendFloat(dst, float64(vals[0]), 32)
|
||||
dst = appendFloat(dst, float64(vals[0]), 32, precision)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = appendFloat(append(dst, ','), float64(val), 32)
|
||||
dst = appendFloat(append(dst, ','), float64(val), 32, precision)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
@@ -339,21 +360,21 @@ func (Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
|
||||
|
||||
// AppendFloat64 converts the input float64 to a string and
|
||||
// appends the encoded string to the input byte slice.
|
||||
func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
|
||||
return appendFloat(dst, val, 64)
|
||||
func (Encoder) AppendFloat64(dst []byte, val float64, precision int) []byte {
|
||||
return appendFloat(dst, val, 64, precision)
|
||||
}
|
||||
|
||||
// AppendFloats64 encodes the input float64s to json and
|
||||
// appends the encoded string list to the input byte slice.
|
||||
func (Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
|
||||
func (Encoder) AppendFloats64(dst []byte, vals []float64, precision int) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = appendFloat(dst, vals[0], 64)
|
||||
dst = appendFloat(dst, vals[0], 64, precision)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = appendFloat(append(dst, ','), val, 64)
|
||||
dst = appendFloat(append(dst, ','), val, 64, precision)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
//
|
||||
// Sub-loggers let you chain loggers with additional context:
|
||||
//
|
||||
// sublogger := log.With().Str("component": "foo").Logger()
|
||||
// sublogger := log.With().Str("component", "foo").Logger()
|
||||
// sublogger.Info().Msg("hello world")
|
||||
// // Output: {"time":1494567715,"level":"info","message":"hello world","component":"foo"}
|
||||
//
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ func (s *BurstSampler) Sample(lvl Level) bool {
|
||||
}
|
||||
|
||||
func (s *BurstSampler) inc() uint32 {
|
||||
now := time.Now().UnixNano()
|
||||
now := TimestampFunc().UnixNano()
|
||||
resetAt := atomic.LoadInt64(&s.resetAt)
|
||||
var c uint32
|
||||
if now > resetAt {
|
||||
|
||||
+3
-2
@@ -46,10 +46,11 @@ func (s *strikethroughParser) Trigger() []byte {
|
||||
func (s *strikethroughParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
|
||||
before := block.PrecendingCharacter()
|
||||
line, segment := block.PeekLine()
|
||||
node := parser.ScanDelimiter(line, before, 2, defaultStrikethroughDelimiterProcessor)
|
||||
if node == nil {
|
||||
node := parser.ScanDelimiter(line, before, 1, defaultStrikethroughDelimiterProcessor)
|
||||
if node == nil || node.OriginalLength > 2 || before == '~' {
|
||||
return nil
|
||||
}
|
||||
|
||||
node.Segment = segment.WithStop(segment.Start + node.OriginalLength)
|
||||
block.Advance(node.OriginalLength)
|
||||
pc.PushDelimiter(node)
|
||||
|
||||
+3
-3
@@ -492,7 +492,7 @@ func (r *TableHTMLRenderer) renderTableCell(
|
||||
tag = "th"
|
||||
}
|
||||
if entering {
|
||||
fmt.Fprintf(w, "<%s", tag)
|
||||
_, _ = fmt.Fprintf(w, "<%s", tag)
|
||||
if n.Alignment != ast.AlignNone {
|
||||
amethod := r.TableConfig.TableCellAlignMethod
|
||||
if amethod == TableCellAlignDefault {
|
||||
@@ -505,7 +505,7 @@ func (r *TableHTMLRenderer) renderTableCell(
|
||||
switch amethod {
|
||||
case TableCellAlignAttribute:
|
||||
if _, ok := n.AttributeString("align"); !ok { // Skip align render if overridden
|
||||
fmt.Fprintf(w, ` align="%s"`, n.Alignment.String())
|
||||
_, _ = fmt.Fprintf(w, ` align="%s"`, n.Alignment.String())
|
||||
}
|
||||
case TableCellAlignStyle:
|
||||
v, ok := n.AttributeString("style")
|
||||
@@ -528,7 +528,7 @@ func (r *TableHTMLRenderer) renderTableCell(
|
||||
}
|
||||
_ = w.WriteByte('>')
|
||||
} else {
|
||||
fmt.Fprintf(w, "</%s>\n", tag)
|
||||
_, _ = fmt.Fprintf(w, "</%s>\n", tag)
|
||||
}
|
||||
return gast.WalkContinue, nil
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,12 +2,13 @@
|
||||
package goldmark
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/renderer"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/text"
|
||||
"github.com/yuin/goldmark/util"
|
||||
"io"
|
||||
)
|
||||
|
||||
// DefaultParser returns a new Parser that is configured by default values.
|
||||
|
||||
+46
-7
@@ -126,13 +126,13 @@ func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.N
|
||||
if line[0] == '!' {
|
||||
if len(line) > 1 && line[1] == '[' {
|
||||
block.Advance(1)
|
||||
pc.Set(linkBottom, pc.LastDelimiter())
|
||||
pushLinkBottom(pc)
|
||||
return processLinkLabelOpen(block, segment.Start+1, true, pc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if line[0] == '[' {
|
||||
pc.Set(linkBottom, pc.LastDelimiter())
|
||||
pushLinkBottom(pc)
|
||||
return processLinkLabelOpen(block, segment.Start, false, pc)
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.N
|
||||
}
|
||||
last := tlist.(*linkLabelState).Last
|
||||
if last == nil {
|
||||
_ = popLinkBottom(pc)
|
||||
return nil
|
||||
}
|
||||
block.Advance(1)
|
||||
@@ -151,11 +152,13 @@ func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.N
|
||||
// > A link label can have at most 999 characters inside the square brackets.
|
||||
if linkLabelStateLength(tlist.(*linkLabelState)) > 998 {
|
||||
ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
|
||||
_ = popLinkBottom(pc)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !last.IsImage && s.containsLink(last) { // a link in a link text is not allowed
|
||||
ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
|
||||
_ = popLinkBottom(pc)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -169,6 +172,7 @@ func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.N
|
||||
link, hasValue = s.parseReferenceLink(parent, last, block, pc)
|
||||
if link == nil && hasValue {
|
||||
ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
|
||||
_ = popLinkBottom(pc)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -182,12 +186,14 @@ func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.N
|
||||
// > A link label can have at most 999 characters inside the square brackets.
|
||||
if len(maybeReference) > 999 {
|
||||
ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
|
||||
_ = popLinkBottom(pc)
|
||||
return nil
|
||||
}
|
||||
|
||||
ref, ok := pc.Reference(util.ToLinkReference(maybeReference))
|
||||
if !ok {
|
||||
ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
|
||||
_ = popLinkBottom(pc)
|
||||
return nil
|
||||
}
|
||||
link = ast.NewLink()
|
||||
@@ -230,11 +236,7 @@ func processLinkLabelOpen(block text.Reader, pos int, isImage bool, pc Context)
|
||||
}
|
||||
|
||||
func (s *linkParser) processLinkLabel(parent ast.Node, link *ast.Link, last *linkLabelState, pc Context) {
|
||||
var bottom ast.Node
|
||||
if v := pc.Get(linkBottom); v != nil {
|
||||
bottom = v.(ast.Node)
|
||||
}
|
||||
pc.Set(linkBottom, nil)
|
||||
bottom := popLinkBottom(pc)
|
||||
ProcessDelimiters(bottom, pc)
|
||||
for c := last.NextSibling(); c != nil; {
|
||||
next := c.NextSibling()
|
||||
@@ -395,6 +397,43 @@ func parseLinkTitle(block text.Reader) ([]byte, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func pushLinkBottom(pc Context) {
|
||||
bottoms := pc.Get(linkBottom)
|
||||
b := pc.LastDelimiter()
|
||||
if bottoms == nil {
|
||||
pc.Set(linkBottom, b)
|
||||
return
|
||||
}
|
||||
if s, ok := bottoms.([]ast.Node); ok {
|
||||
pc.Set(linkBottom, append(s, b))
|
||||
return
|
||||
}
|
||||
pc.Set(linkBottom, []ast.Node{bottoms.(ast.Node), b})
|
||||
}
|
||||
|
||||
func popLinkBottom(pc Context) ast.Node {
|
||||
bottoms := pc.Get(linkBottom)
|
||||
if bottoms == nil {
|
||||
return nil
|
||||
}
|
||||
if v, ok := bottoms.(ast.Node); ok {
|
||||
pc.Set(linkBottom, nil)
|
||||
return v
|
||||
}
|
||||
s := bottoms.([]ast.Node)
|
||||
v := s[len(s)-1]
|
||||
n := s[0 : len(s)-1]
|
||||
switch len(n) {
|
||||
case 0:
|
||||
pc.Set(linkBottom, nil)
|
||||
case 1:
|
||||
pc.Set(linkBottom, n[0])
|
||||
default:
|
||||
pc.Set(linkBottom, s[0:len(s)-1])
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (s *linkParser) CloseBlock(parent ast.Node, block text.Reader, pc Context) {
|
||||
pc.Set(linkBottom, nil)
|
||||
tlist := pc.Get(linkLabelStateKey)
|
||||
|
||||
+19
-19
@@ -445,7 +445,7 @@ func (r *Renderer) renderList(w util.BufWriter, source []byte, node ast.Node, en
|
||||
_ = w.WriteByte('<')
|
||||
_, _ = w.WriteString(tag)
|
||||
if n.IsOrdered() && n.Start != 1 {
|
||||
fmt.Fprintf(w, " start=\"%d\"", n.Start)
|
||||
_, _ = fmt.Fprintf(w, " start=\"%d\"", n.Start)
|
||||
}
|
||||
if n.Attributes() != nil {
|
||||
RenderAttributes(w, n, ListAttributeFilter)
|
||||
@@ -680,7 +680,7 @@ func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, e
|
||||
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
|
||||
}
|
||||
_, _ = w.WriteString(`" alt="`)
|
||||
_, _ = w.Write(nodeToHTMLText(n, source))
|
||||
r.renderAttribute(w, source, n)
|
||||
_ = w.WriteByte('"')
|
||||
if n.Title != nil {
|
||||
_, _ = w.WriteString(` title="`)
|
||||
@@ -770,6 +770,23 @@ func (r *Renderer) renderString(w util.BufWriter, source []byte, node ast.Node,
|
||||
return ast.WalkContinue, nil
|
||||
}
|
||||
|
||||
func (r *Renderer) renderAttribute(w util.BufWriter, source []byte, n ast.Node) {
|
||||
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if s, ok := c.(*ast.String); ok {
|
||||
_, _ = r.renderString(w, source, s, true)
|
||||
} else if t, ok := c.(*ast.String); ok {
|
||||
_, _ = r.renderText(w, source, t, true)
|
||||
} else if !c.HasChildren() {
|
||||
r.Writer.Write(w, c.Text(source))
|
||||
if t, ok := c.(*ast.Text); ok && t.SoftLineBreak() {
|
||||
_ = w.WriteByte('\n')
|
||||
}
|
||||
} else {
|
||||
r.renderAttribute(w, source, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dataPrefix = []byte("data-")
|
||||
|
||||
// RenderAttributes renders given node's attributes.
|
||||
@@ -1007,20 +1024,3 @@ func IsDangerousURL(url []byte) bool {
|
||||
return hasPrefix(url, bJs) || hasPrefix(url, bVb) ||
|
||||
hasPrefix(url, bFile) || hasPrefix(url, bData)
|
||||
}
|
||||
|
||||
func nodeToHTMLText(n ast.Node, source []byte) []byte {
|
||||
var buf bytes.Buffer
|
||||
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if s, ok := c.(*ast.String); ok && s.IsCode() {
|
||||
buf.Write(s.Text(source))
|
||||
} else if !c.HasChildren() {
|
||||
buf.Write(util.EscapeHTML(c.Text(source)))
|
||||
if t, ok := c.(*ast.Text); ok && t.SoftLineBreak() {
|
||||
buf.WriteByte('\n')
|
||||
}
|
||||
} else {
|
||||
buf.Write(nodeToHTMLText(c, source))
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
+13
-9
@@ -1,11 +1,15 @@
|
||||
lint:
|
||||
image: registry.gitlab.com/etke.cc/base
|
||||
script:
|
||||
- golangci-lint run ./...
|
||||
stages:
|
||||
- test
|
||||
- release
|
||||
default:
|
||||
image: registry.gitlab.com/etke.cc/base/build
|
||||
|
||||
unit:
|
||||
image: registry.gitlab.com/etke.cc/base
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- go test -coverprofile=cover.out ./...
|
||||
- go tool cover -func=cover.out
|
||||
- rm -f cover.out
|
||||
- just lint
|
||||
- just test
|
||||
cache:
|
||||
key: ${CI_COMMIT_REF_SLUG}
|
||||
paths:
|
||||
- /root/cache/
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
run:
|
||||
concurrency: 4
|
||||
timeout: 30m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
build-tags: []
|
||||
skip-dirs-use-default: true
|
||||
skip-files: []
|
||||
modules-download-mode: readonly
|
||||
|
||||
output:
|
||||
formats:
|
||||
- format: colored-line-number
|
||||
print-issued-lines: true
|
||||
print-linter-name: true
|
||||
sort-results: true
|
||||
|
||||
linters-settings:
|
||||
decorder:
|
||||
dec-order:
|
||||
- const
|
||||
- var
|
||||
- type
|
||||
- func
|
||||
dogsled:
|
||||
max-blank-identifiers: 3
|
||||
errcheck:
|
||||
check-type-assertions: true
|
||||
check-blank: true
|
||||
errchkjson:
|
||||
report-no-exported: true
|
||||
exhaustive:
|
||||
check:
|
||||
- switch
|
||||
- map
|
||||
default-signifies-exhaustive: true
|
||||
gocognit:
|
||||
min-complexity: 15
|
||||
nestif:
|
||||
min-complexity: 5
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- style
|
||||
- performance
|
||||
gofmt:
|
||||
simplify: true
|
||||
rewrite-rules:
|
||||
- pattern: 'interface{}'
|
||||
replacement: 'any'
|
||||
- pattern: 'a[b:len(a)]'
|
||||
replacement: 'a[b:]'
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
grouper:
|
||||
const-require-single-const: true
|
||||
import-require-single-import: true
|
||||
var-require-single-var: true
|
||||
misspell:
|
||||
locale: US
|
||||
usestdlibvars:
|
||||
time-month: true
|
||||
time-layout: true
|
||||
crypto-hash: true
|
||||
default-rpc-path: true
|
||||
sql-isolation-level: true
|
||||
tls-signature-scheme: true
|
||||
constant-kind: true
|
||||
unparam:
|
||||
check-exported: true
|
||||
linters:
|
||||
disable-all: false
|
||||
enable:
|
||||
- asasalint
|
||||
- asciicheck
|
||||
- bidichk
|
||||
- bodyclose
|
||||
- containedctx
|
||||
- decorder
|
||||
- dogsled
|
||||
- dupl
|
||||
- dupword
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- forcetypeassert
|
||||
- gocognit
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gosec
|
||||
- gosimple
|
||||
- gosmopolitan
|
||||
- govet
|
||||
- ineffassign
|
||||
- makezero
|
||||
- mirror
|
||||
- misspell
|
||||
- nestif
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- predeclared
|
||||
- revive
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- usestdlibvars
|
||||
- wastedassign
|
||||
fast: false
|
||||
|
||||
|
||||
issues:
|
||||
exclude-dirs:
|
||||
- mocks
|
||||
exclude-files:
|
||||
- dotenv/parser.go
|
||||
exclude-rules:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocyclo
|
||||
- gocognit
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "SA9003:"
|
||||
- linters:
|
||||
- lll
|
||||
source: "^//go:generate "
|
||||
- linters:
|
||||
- revive
|
||||
text: "returns unexported type"
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
new: false
|
||||
+5
@@ -2,12 +2,17 @@
|
||||
|
||||
Simple go environment variables reader, for env-based configs
|
||||
|
||||
Automatically loads .env file if exists
|
||||
|
||||
```go
|
||||
env.SetPrefix("app") // all env vars should start with APP_
|
||||
login := env.String("matrix.login", "none") // export APP_MATRIX_LOGIN=buscarron
|
||||
enabled := env.Bool("form.enabled") // export APP_FORM_ENABLED=1
|
||||
size := env.Int("cache.size", 1000) // export APP_CACHE_SIZE=500
|
||||
slice := env.Slice("form.fields") // export APP_FORM_FIELDS="one two three"
|
||||
|
||||
// need to load custom env file?
|
||||
dotenv.Load(".env.dev", ".env.local")
|
||||
```
|
||||
|
||||
see more in godoc
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package dotenv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
// EnvFile is the default file to load
|
||||
const EnvFile = ".env"
|
||||
|
||||
// Load loads the EnvFile and additional files
|
||||
func Load(additionalFiles ...string) {
|
||||
files := []string{EnvFile}
|
||||
if len(additionalFiles) > 0 {
|
||||
files = append(files, additionalFiles...)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
loadFile(file) //nolint:errcheck // ignore error
|
||||
}
|
||||
}
|
||||
|
||||
func loadFile(file string) error {
|
||||
if _, err := os.Stat(".env"); errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
|
||||
contents, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
contentsMap := make(map[string]string)
|
||||
if err := parseBytes(contents, contentsMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for key, value := range contentsMap {
|
||||
os.Setenv(key, value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
package dotenv
|
||||
|
||||
// This file is modified version of github.com/joho/godotenv/parser.go
|
||||
// The original file is licensed under MIT License
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
charComment = '#'
|
||||
prefixSingleQuote = '\''
|
||||
prefixDoubleQuote = '"'
|
||||
|
||||
exportPrefix = "export"
|
||||
)
|
||||
|
||||
func parseBytes(src []byte, out map[string]string) error {
|
||||
src = bytes.ReplaceAll(src, []byte("\r\n"), []byte("\n"))
|
||||
cutset := src
|
||||
for {
|
||||
cutset = getStatementStart(cutset)
|
||||
if cutset == nil {
|
||||
// reached end of file
|
||||
break
|
||||
}
|
||||
|
||||
key, left, err := locateKeyName(cutset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value, left, err := extractVarValue(left, out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out[key] = value
|
||||
cutset = left
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getStatementPosition returns position of statement begin.
|
||||
//
|
||||
// It skips any comment line or non-whitespace character.
|
||||
func getStatementStart(src []byte) []byte {
|
||||
pos := indexOfNonSpaceChar(src)
|
||||
if pos == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
src = src[pos:]
|
||||
if src[0] != charComment {
|
||||
return src
|
||||
}
|
||||
|
||||
// skip comment section
|
||||
pos = bytes.IndexFunc(src, isCharFunc('\n'))
|
||||
if pos == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return getStatementStart(src[pos:])
|
||||
}
|
||||
|
||||
// locateKeyName locates and parses key name and returns rest of slice
|
||||
func locateKeyName(src []byte) (key string, cutset []byte, err error) {
|
||||
// trim "export" and space at beginning
|
||||
src = bytes.TrimLeftFunc(src, isSpace)
|
||||
if bytes.HasPrefix(src, []byte(exportPrefix)) {
|
||||
trimmed := bytes.TrimPrefix(src, []byte(exportPrefix))
|
||||
if bytes.IndexFunc(trimmed, isSpace) == 0 {
|
||||
src = bytes.TrimLeftFunc(trimmed, isSpace)
|
||||
}
|
||||
}
|
||||
|
||||
// locate key name end and validate it in single loop
|
||||
offset := 0
|
||||
loop:
|
||||
for i, char := range src {
|
||||
rchar := rune(char)
|
||||
if isSpace(rchar) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch char {
|
||||
case '=', ':':
|
||||
// library also supports yaml-style value declaration
|
||||
key = string(src[0:i])
|
||||
offset = i + 1
|
||||
break loop
|
||||
case '_':
|
||||
default:
|
||||
// variable name should match [A-Za-z0-9_.]
|
||||
if unicode.IsLetter(rchar) || unicode.IsNumber(rchar) || rchar == '.' {
|
||||
continue
|
||||
}
|
||||
|
||||
return "", nil, fmt.Errorf(
|
||||
`unexpected character %q in variable name near %q`,
|
||||
string(char), string(src))
|
||||
}
|
||||
}
|
||||
|
||||
if len(src) == 0 {
|
||||
return "", nil, errors.New("zero length string")
|
||||
}
|
||||
|
||||
// trim whitespace
|
||||
key = strings.TrimRightFunc(key, unicode.IsSpace)
|
||||
cutset = bytes.TrimLeftFunc(src[offset:], isSpace)
|
||||
return key, cutset, nil
|
||||
}
|
||||
|
||||
// extractVarValue extracts variable value and returns rest of slice
|
||||
func extractVarValue(src []byte, vars map[string]string) (value string, rest []byte, err error) {
|
||||
quote, hasPrefix := hasQuotePrefix(src)
|
||||
if !hasPrefix {
|
||||
// unquoted value - read until end of line
|
||||
endOfLine := bytes.IndexFunc(src, isLineEnd)
|
||||
|
||||
// Hit EOF without a trailing newline
|
||||
if endOfLine == -1 {
|
||||
endOfLine = len(src)
|
||||
|
||||
if endOfLine == 0 {
|
||||
return "", nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Convert line to rune away to do accurate countback of runes
|
||||
line := []rune(string(src[0:endOfLine]))
|
||||
|
||||
// Assume end of line is end of var
|
||||
endOfVar := len(line)
|
||||
if endOfVar == 0 {
|
||||
return "", src[endOfLine:], nil
|
||||
}
|
||||
|
||||
// Work backwards to check if the line ends in whitespace then
|
||||
// a comment (ie asdasd # some comment)
|
||||
for i := endOfVar - 1; i >= 0; i-- {
|
||||
if line[i] == charComment && i > 0 {
|
||||
if isSpace(line[i-1]) {
|
||||
endOfVar = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trimmed := strings.TrimFunc(string(line[0:endOfVar]), isSpace)
|
||||
|
||||
return expandVariables(trimmed, vars), src[endOfLine:], nil
|
||||
}
|
||||
|
||||
// lookup quoted string terminator
|
||||
for i := 1; i < len(src); i++ {
|
||||
if char := src[i]; char != quote {
|
||||
continue
|
||||
}
|
||||
|
||||
// skip escaped quote symbol (\" or \', depends on quote)
|
||||
if prevChar := src[i-1]; prevChar == '\\' {
|
||||
continue
|
||||
}
|
||||
|
||||
// trim quotes
|
||||
trimFunc := isCharFunc(rune(quote))
|
||||
value = string(bytes.TrimLeftFunc(bytes.TrimRightFunc(src[0:i], trimFunc), trimFunc))
|
||||
if quote == prefixDoubleQuote {
|
||||
// unescape newlines for double quote (this is compat feature)
|
||||
// and expand environment variables
|
||||
value = expandVariables(expandEscapes(value), vars)
|
||||
}
|
||||
|
||||
return value, src[i+1:], nil
|
||||
}
|
||||
|
||||
// return formatted error if quoted string is not terminated
|
||||
valEndIndex := bytes.IndexFunc(src, isCharFunc('\n'))
|
||||
if valEndIndex == -1 {
|
||||
valEndIndex = len(src)
|
||||
}
|
||||
|
||||
return "", nil, fmt.Errorf("unterminated quoted value %s", src[:valEndIndex])
|
||||
}
|
||||
|
||||
func expandEscapes(str string) string {
|
||||
out := escapeRegex.ReplaceAllStringFunc(str, func(match string) string {
|
||||
c := strings.TrimPrefix(match, `\`)
|
||||
switch c {
|
||||
case "n":
|
||||
return "\n"
|
||||
case "r":
|
||||
return "\r"
|
||||
default:
|
||||
return match
|
||||
}
|
||||
})
|
||||
return unescapeCharsRegex.ReplaceAllString(out, "$1")
|
||||
}
|
||||
|
||||
func indexOfNonSpaceChar(src []byte) int {
|
||||
return bytes.IndexFunc(src, func(r rune) bool {
|
||||
return !unicode.IsSpace(r)
|
||||
})
|
||||
}
|
||||
|
||||
// hasQuotePrefix reports whether charset starts with single or double quote and returns quote character
|
||||
func hasQuotePrefix(src []byte) (prefix byte, isQuored bool) {
|
||||
if len(src) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
switch prefix := src[0]; prefix {
|
||||
case prefixDoubleQuote, prefixSingleQuote:
|
||||
return prefix, true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
func isCharFunc(char rune) func(rune) bool {
|
||||
return func(v rune) bool {
|
||||
return v == char
|
||||
}
|
||||
}
|
||||
|
||||
// isSpace reports whether the rune is a space character but not line break character
|
||||
//
|
||||
// this differs from unicode.IsSpace, which also applies line break as space
|
||||
func isSpace(r rune) bool {
|
||||
switch r {
|
||||
case '\t', '\v', '\f', '\r', ' ', 0x85, 0xA0:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isLineEnd(r rune) bool {
|
||||
if r == '\n' || r == '\r' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
escapeRegex = regexp.MustCompile(`\\.`)
|
||||
expandVarRegex = regexp.MustCompile(`(\\)?(\$)(\()?\{?([A-Z0-9_]+)?\}?`)
|
||||
unescapeCharsRegex = regexp.MustCompile(`\\([^$])`)
|
||||
)
|
||||
|
||||
func expandVariables(v string, m map[string]string) string {
|
||||
return expandVarRegex.ReplaceAllStringFunc(v, func(s string) string {
|
||||
submatch := expandVarRegex.FindStringSubmatch(s)
|
||||
|
||||
if submatch == nil {
|
||||
return s
|
||||
}
|
||||
if submatch[1] == "\\" || submatch[2] == "(" {
|
||||
return submatch[0][1:]
|
||||
} else if submatch[4] != "" {
|
||||
return m[submatch[4]]
|
||||
}
|
||||
return s
|
||||
})
|
||||
}
|
||||
+6
@@ -4,10 +4,16 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitlab.com/etke.cc/go/env/dotenv"
|
||||
)
|
||||
|
||||
var envprefix string
|
||||
|
||||
func init() {
|
||||
dotenv.Load()
|
||||
}
|
||||
|
||||
// SetPrefix sets prefix for all env vars
|
||||
func SetPrefix(prefix string) {
|
||||
envprefix = prefix
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
# show help by default
|
||||
default:
|
||||
@just --list --justfile {{ justfile() }}
|
||||
|
||||
# update go deps
|
||||
update *flags:
|
||||
go get {{flags}} .
|
||||
go mod tidy
|
||||
|
||||
# run linter
|
||||
lint:
|
||||
golangci-lint run ./...
|
||||
|
||||
# automatically fix liter issues
|
||||
lintfix:
|
||||
golangci-lint run --fix ./...
|
||||
|
||||
# run unit tests
|
||||
test:
|
||||
@go test -cover -coverprofile=cover.out -coverpkg=./... -covermode=set ./...
|
||||
@go tool cover -func=cover.out
|
||||
-@rm -f cover.out
|
||||
+6
@@ -104,6 +104,8 @@ type Database struct {
|
||||
Dialect Dialect
|
||||
UpgradeTable UpgradeTable
|
||||
|
||||
txnCtxKey contextKey
|
||||
|
||||
IgnoreForeignTables bool
|
||||
IgnoreUnsupportedDatabase bool
|
||||
}
|
||||
@@ -132,6 +134,8 @@ func (db *Database) Child(versionTable string, upgradeTable UpgradeTable, log Da
|
||||
Log: log,
|
||||
Dialect: db.Dialect,
|
||||
|
||||
txnCtxKey: db.txnCtxKey,
|
||||
|
||||
IgnoreForeignTables: true,
|
||||
IgnoreUnsupportedDatabase: db.IgnoreUnsupportedDatabase,
|
||||
}
|
||||
@@ -149,6 +153,8 @@ func NewWithDB(db *sql.DB, rawDialect string) (*Database, error) {
|
||||
|
||||
IgnoreForeignTables: true,
|
||||
VersionTable: "version",
|
||||
|
||||
txnCtxKey: contextKey(nextContextKeyDatabaseTransaction.Add(1)),
|
||||
}
|
||||
wrappedDB.LoggingDB.UnderlyingExecable = db
|
||||
wrappedDB.LoggingDB.db = wrappedDB
|
||||
|
||||
Vendored
+2
-1
@@ -4,6 +4,7 @@ import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// JSON is a utility type for using arbitrary JSON data as values in database Exec and Scan calls.
|
||||
@@ -29,7 +30,7 @@ func (j JSON) Value() (driver.Value, error) {
|
||||
return nil, nil
|
||||
}
|
||||
v, err := json.Marshal(j.Data)
|
||||
return string(v), err
|
||||
return unsafe.String(unsafe.SliceData(v), len(v)), err
|
||||
}
|
||||
|
||||
// JSONPtr is a convenience function for wrapping a pointer to a value in the JSON utility, but removing typed nils
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
CREATE TABLE foo (
|
||||
-- only: postgres
|
||||
key BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
||||
-- only: sqlite
|
||||
key INTEGER PRIMARY KEY,
|
||||
-- only: sqlite (line commented)
|
||||
-- key INTEGER PRIMARY KEY,
|
||||
|
||||
data JSONB NOT NULL
|
||||
);
|
||||
|
||||
@@ -8,4 +8,3 @@ CREATE FUNCTION delete_data() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN
|
||||
DELETE FROM test WHERE key <= NEW.data->>'index';
|
||||
RETURN NEW;
|
||||
END $$;
|
||||
-- end only postgres
|
||||
|
||||
@@ -7,4 +7,3 @@ CREATE TABLE foo (
|
||||
CREATE TRIGGER test AFTER INSERT ON foo WHEN NEW.data->>'action' = 'delete' BEGIN
|
||||
DELETE FROM test WHERE key <= NEW.data->>'index';
|
||||
END;
|
||||
-- end only sqlite
|
||||
|
||||
+13
-7
@@ -12,6 +12,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
@@ -26,13 +27,18 @@ var (
|
||||
ErrTxnCommit = fmt.Errorf("%w: commit", ErrTxn)
|
||||
)
|
||||
|
||||
type contextKey int
|
||||
type contextKey int64
|
||||
|
||||
const (
|
||||
ContextKeyDatabaseTransaction contextKey = iota
|
||||
ContextKeyDoTxnCallerSkip
|
||||
ContextKeyDoTxnCallerSkip contextKey = 1
|
||||
)
|
||||
|
||||
var nextContextKeyDatabaseTransaction atomic.Uint64
|
||||
|
||||
func init() {
|
||||
nextContextKeyDatabaseTransaction.Store(1 << 61)
|
||||
}
|
||||
|
||||
func (db *Database) Exec(ctx context.Context, query string, args ...any) (sql.Result, error) {
|
||||
return db.Conn(ctx).ExecContext(ctx, query, args...)
|
||||
}
|
||||
@@ -56,7 +62,7 @@ func (db *Database) DoTxn(ctx context.Context, opts *sql.TxOptions, fn func(ctx
|
||||
if ctx == nil {
|
||||
panic("DoTxn() called with nil ctx")
|
||||
}
|
||||
if ctx.Value(ContextKeyDatabaseTransaction) != nil {
|
||||
if ctx.Value(db.txnCtxKey) != nil {
|
||||
zerolog.Ctx(ctx).Trace().Msg("Already in a transaction, not creating a new one")
|
||||
return fn(ctx)
|
||||
}
|
||||
@@ -82,7 +88,7 @@ func (db *Database) DoTxn(ctx context.Context, opts *sql.TxOptions, fn func(ctx
|
||||
select {
|
||||
case <-ticker.C:
|
||||
slowLog.Warn().
|
||||
Dur("duration_seconds", time.Since(start)).
|
||||
Float64("duration_seconds", time.Since(start).Seconds()).
|
||||
Msg("Transaction still running")
|
||||
case <-deadlockCh:
|
||||
return
|
||||
@@ -106,7 +112,7 @@ func (db *Database) DoTxn(ctx context.Context, opts *sql.TxOptions, fn func(ctx
|
||||
log.Trace().Msg("Transaction started")
|
||||
tx.noTotalLog = true
|
||||
ctx = log.WithContext(ctx)
|
||||
ctx = context.WithValue(ctx, ContextKeyDatabaseTransaction, tx)
|
||||
ctx = context.WithValue(ctx, db.txnCtxKey, tx)
|
||||
err = fn(ctx)
|
||||
if err != nil {
|
||||
log.Trace().Err(err).Msg("Database transaction failed, rolling back")
|
||||
@@ -131,7 +137,7 @@ func (db *Database) Conn(ctx context.Context) Execable {
|
||||
if ctx == nil {
|
||||
panic("Conn() called with nil ctx")
|
||||
}
|
||||
txn, ok := ctx.Value(ContextKeyDatabaseTransaction).(Transaction)
|
||||
txn, ok := ctx.Value(db.txnCtxKey).(Transaction)
|
||||
if ok {
|
||||
return txn
|
||||
}
|
||||
|
||||
+48
-29
@@ -121,40 +121,38 @@ func parseFileHeader(file []byte) (from, to, compat int, message string, txn boo
|
||||
// -- only: sqlite for next 123 lines
|
||||
//
|
||||
// If the single-line limit is on the second line of the file, the whole file is limited to that dialect.
|
||||
var dialectLineFilter = regexp.MustCompile(`^\s*-- only: (postgres|sqlite)(?: for next (\d+) lines| until "(end) only")?`)
|
||||
//
|
||||
// If the filter ends with `(lines commented)`, then ALL lines chosen by the filter will be uncommented.
|
||||
var dialectLineFilter = regexp.MustCompile(`^\s*-- only: (postgres|sqlite)(?: for next (\d+) lines| until "(end) only")?(?: \(lines? (commented)\))?`)
|
||||
|
||||
// Constants used to make parseDialectFilter clearer
|
||||
const (
|
||||
skipUntilEndTag = -1
|
||||
skipNothing = 0
|
||||
skipCurrentLine = 1
|
||||
skipNextLine = 2
|
||||
skipNextLine = 1
|
||||
)
|
||||
|
||||
func (db *Database) parseDialectFilter(line []byte) (int, error) {
|
||||
func (db *Database) parseDialectFilter(line []byte) (dialect Dialect, lineCount int, uncomment bool, err error) {
|
||||
match := dialectLineFilter.FindSubmatch(line)
|
||||
if match == nil {
|
||||
return skipNothing, nil
|
||||
return
|
||||
}
|
||||
dialect, err := ParseDialect(string(match[1]))
|
||||
dialect, err = ParseDialect(string(match[1]))
|
||||
if err != nil {
|
||||
return skipNothing, err
|
||||
} else if dialect == db.Dialect {
|
||||
// Skip the dialect filter line
|
||||
return skipCurrentLine, nil
|
||||
} else if bytes.Equal(match[3], []byte("end")) {
|
||||
return skipUntilEndTag, nil
|
||||
} else if len(match[2]) == 0 {
|
||||
// Skip the dialect filter and the next line
|
||||
return skipNextLine, nil
|
||||
} else {
|
||||
// Parse number of lines to skip, add 1 for current line
|
||||
lineCount, err := strconv.Atoi(string(match[2]))
|
||||
if err != nil {
|
||||
return skipNothing, fmt.Errorf("invalid line count '%s': %w", match[2], err)
|
||||
}
|
||||
return skipCurrentLine + lineCount, nil
|
||||
return
|
||||
}
|
||||
uncomment = bytes.Equal(match[4], []byte("commented"))
|
||||
if bytes.Equal(match[3], []byte("end")) {
|
||||
lineCount = skipUntilEndTag
|
||||
} else if len(match[2]) == 0 {
|
||||
lineCount = skipNextLine
|
||||
} else {
|
||||
lineCount, err = strconv.Atoi(string(match[2]))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid line count %q: %w", match[2], err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var endLineFilter = regexp.MustCompile(`^\s*-- end only (postgres|sqlite)$`)
|
||||
@@ -162,15 +160,16 @@ var endLineFilter = regexp.MustCompile(`^\s*-- end only (postgres|sqlite)$`)
|
||||
func (db *Database) filterSQLUpgrade(lines [][]byte) (string, error) {
|
||||
output := make([][]byte, 0, len(lines))
|
||||
for i := 0; i < len(lines); i++ {
|
||||
skipLines, err := db.parseDialectFilter(lines[i])
|
||||
dialect, lineCount, uncomment, err := db.parseDialectFilter(lines[i])
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if skipLines > 0 {
|
||||
// Current line is implicitly skipped, so reduce one here
|
||||
i += skipLines - 1
|
||||
} else if skipLines == skipUntilEndTag {
|
||||
} else if lineCount == skipNothing {
|
||||
output = append(output, lines[i])
|
||||
} else if lineCount == skipUntilEndTag {
|
||||
startedAt := i
|
||||
startedAtMatch := dialectLineFilter.FindSubmatch(lines[startedAt])
|
||||
// Skip filter start line
|
||||
i++
|
||||
for ; i < len(lines); i++ {
|
||||
if match := endLineFilter.FindSubmatch(lines[i]); match != nil {
|
||||
if !bytes.Equal(match[1], startedAtMatch[1]) {
|
||||
@@ -178,12 +177,32 @@ func (db *Database) filterSQLUpgrade(lines [][]byte) (string, error) {
|
||||
}
|
||||
break
|
||||
}
|
||||
if dialect == db.Dialect {
|
||||
if uncomment {
|
||||
output = append(output, bytes.TrimPrefix(lines[i], []byte("--")))
|
||||
} else {
|
||||
output = append(output, lines[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if i == len(lines) {
|
||||
return "", fmt.Errorf(`didn't get end tag matching start %q at line %d`, string(startedAtMatch[1]), startedAt)
|
||||
}
|
||||
} else if dialect != db.Dialect {
|
||||
i += lineCount
|
||||
} else {
|
||||
output = append(output, lines[i])
|
||||
// Skip current line, uncomment the specified number of lines
|
||||
i++
|
||||
targetI := i + lineCount
|
||||
for ; i < targetI; i++ {
|
||||
if uncomment {
|
||||
output = append(output, bytes.TrimPrefix(lines[i], []byte("--")))
|
||||
} else {
|
||||
output = append(output, lines[i])
|
||||
}
|
||||
}
|
||||
// Decrement counter to avoid skipping the next line
|
||||
i--
|
||||
}
|
||||
}
|
||||
return string(bytes.Join(output, []byte("\n"))), nil
|
||||
@@ -191,7 +210,7 @@ func (db *Database) filterSQLUpgrade(lines [][]byte) (string, error) {
|
||||
|
||||
func sqlUpgradeFunc(fileName string, lines [][]byte) upgradeFunc {
|
||||
return func(ctx context.Context, db *Database) error {
|
||||
if skip, err := db.parseDialectFilter(lines[0]); err == nil && skip == skipNextLine {
|
||||
if dialect, skip, _, err := db.parseDialectFilter(lines[0]); err == nil && skip == skipNextLine && dialect != db.Dialect {
|
||||
return nil
|
||||
} else if upgradeSQL, err := db.filterSQLUpgrade(lines); err != nil {
|
||||
panic(fmt.Errorf("failed to parse upgrade %s: %w", fileName, err))
|
||||
|
||||
+8
@@ -904,6 +904,10 @@ func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
|
||||
return errors.New("ssh: signature did not verify")
|
||||
}
|
||||
|
||||
func (k *skECDSAPublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||
return &k.PublicKey
|
||||
}
|
||||
|
||||
type skEd25519PublicKey struct {
|
||||
// application is a URL-like string, typically "ssh:" for SSH.
|
||||
// see openssh/PROTOCOL.u2f for details.
|
||||
@@ -1000,6 +1004,10 @@ func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *skEd25519PublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||
return k.PublicKey
|
||||
}
|
||||
|
||||
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
|
||||
// *ecdsa.PrivateKey or any other crypto.Signer and returns a
|
||||
// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
|
||||
|
||||
+30
@@ -462,6 +462,24 @@ func (p *PartialSuccessError) Error() string {
|
||||
// It is returned in ServerAuthError.Errors from NewServerConn.
|
||||
var ErrNoAuth = errors.New("ssh: no auth passed yet")
|
||||
|
||||
// BannerError is an error that can be returned by authentication handlers in
|
||||
// ServerConfig to send a banner message to the client.
|
||||
type BannerError struct {
|
||||
Err error
|
||||
Message string
|
||||
}
|
||||
|
||||
func (b *BannerError) Unwrap() error {
|
||||
return b.Err
|
||||
}
|
||||
|
||||
func (b *BannerError) Error() string {
|
||||
if b.Err == nil {
|
||||
return b.Message
|
||||
}
|
||||
return b.Err.Error()
|
||||
}
|
||||
|
||||
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
|
||||
sessionID := s.transport.getSessionID()
|
||||
var cache pubKeyCache
|
||||
@@ -734,6 +752,18 @@ userAuthLoop:
|
||||
config.AuthLogCallback(s, userAuthReq.Method, authErr)
|
||||
}
|
||||
|
||||
var bannerErr *BannerError
|
||||
if errors.As(authErr, &bannerErr) {
|
||||
if bannerErr.Message != "" {
|
||||
bannerMsg := &userAuthBannerMsg{
|
||||
Message: bannerErr.Message,
|
||||
}
|
||||
if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if authErr == nil {
|
||||
break userAuthLoop
|
||||
}
|
||||
|
||||
+3
-1
@@ -22,10 +22,12 @@ func Sort[S ~[]E, E constraints.Ordered](x S) {
|
||||
// SortFunc sorts the slice x in ascending order as determined by the cmp
|
||||
// function. This sort is not guaranteed to be stable.
|
||||
// cmp(a, b) should return a negative number when a < b, a positive number when
|
||||
// a > b and zero when a == b.
|
||||
// a > b and zero when a == b or when a is not comparable to b in the sense
|
||||
// of the formal definition of Strict Weak Ordering.
|
||||
//
|
||||
// SortFunc requires that cmp is a strict weak ordering.
|
||||
// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
|
||||
// To indicate 'uncomparable', return 0 from the function.
|
||||
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
|
||||
n := len(x)
|
||||
pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)
|
||||
|
||||
+2
@@ -263,6 +263,7 @@ struct ltchars {
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/sock_diag.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/taskstats.h>
|
||||
#include <linux/tipc.h>
|
||||
@@ -549,6 +550,7 @@ ccflags="$@"
|
||||
$2 !~ "NLA_TYPE_MASK" &&
|
||||
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
|
||||
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
|
||||
$2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ ||
|
||||
$2 ~ /^FIORDCHK$/ ||
|
||||
$2 ~ /^SIOC/ ||
|
||||
$2 ~ /^TIOC/ ||
|
||||
|
||||
+18
-2
@@ -502,6 +502,7 @@ const (
|
||||
BPF_IMM = 0x0
|
||||
BPF_IND = 0x40
|
||||
BPF_JA = 0x0
|
||||
BPF_JCOND = 0xe0
|
||||
BPF_JEQ = 0x10
|
||||
BPF_JGE = 0x30
|
||||
BPF_JGT = 0x20
|
||||
@@ -657,6 +658,9 @@ const (
|
||||
CAN_NPROTO = 0x8
|
||||
CAN_RAW = 0x1
|
||||
CAN_RAW_FILTER_MAX = 0x200
|
||||
CAN_RAW_XL_VCID_RX_FILTER = 0x4
|
||||
CAN_RAW_XL_VCID_TX_PASS = 0x2
|
||||
CAN_RAW_XL_VCID_TX_SET = 0x1
|
||||
CAN_RTR_FLAG = 0x40000000
|
||||
CAN_SFF_ID_BITS = 0xb
|
||||
CAN_SFF_MASK = 0x7ff
|
||||
@@ -1339,6 +1343,7 @@ const (
|
||||
F_OFD_SETLK = 0x25
|
||||
F_OFD_SETLKW = 0x26
|
||||
F_OK = 0x0
|
||||
F_SEAL_EXEC = 0x20
|
||||
F_SEAL_FUTURE_WRITE = 0x10
|
||||
F_SEAL_GROW = 0x4
|
||||
F_SEAL_SEAL = 0x1
|
||||
@@ -1627,6 +1632,7 @@ const (
|
||||
IP_FREEBIND = 0xf
|
||||
IP_HDRINCL = 0x3
|
||||
IP_IPSEC_POLICY = 0x10
|
||||
IP_LOCAL_PORT_RANGE = 0x33
|
||||
IP_MAXPACKET = 0xffff
|
||||
IP_MAX_MEMBERSHIPS = 0x14
|
||||
IP_MF = 0x2000
|
||||
@@ -1653,6 +1659,7 @@ const (
|
||||
IP_PMTUDISC_OMIT = 0x5
|
||||
IP_PMTUDISC_PROBE = 0x3
|
||||
IP_PMTUDISC_WANT = 0x1
|
||||
IP_PROTOCOL = 0x34
|
||||
IP_RECVERR = 0xb
|
||||
IP_RECVERR_RFC4884 = 0x1a
|
||||
IP_RECVFRAGSIZE = 0x19
|
||||
@@ -2169,7 +2176,7 @@ const (
|
||||
NFT_SECMARK_CTX_MAXLEN = 0x100
|
||||
NFT_SET_MAXNAMELEN = 0x100
|
||||
NFT_SOCKET_MAX = 0x3
|
||||
NFT_TABLE_F_MASK = 0x3
|
||||
NFT_TABLE_F_MASK = 0x7
|
||||
NFT_TABLE_MAXNAMELEN = 0x100
|
||||
NFT_TRACETYPE_MAX = 0x3
|
||||
NFT_TUNNEL_F_MASK = 0x7
|
||||
@@ -2403,6 +2410,7 @@ const (
|
||||
PERF_RECORD_MISC_USER = 0x2
|
||||
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
|
||||
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
|
||||
PID_FS_MAGIC = 0x50494446
|
||||
PIPEFS_MAGIC = 0x50495045
|
||||
PPPIOCGNPMODE = 0xc008744c
|
||||
PPPIOCNEWUNIT = 0xc004743e
|
||||
@@ -2896,8 +2904,9 @@ const (
|
||||
RWF_APPEND = 0x10
|
||||
RWF_DSYNC = 0x2
|
||||
RWF_HIPRI = 0x1
|
||||
RWF_NOAPPEND = 0x20
|
||||
RWF_NOWAIT = 0x8
|
||||
RWF_SUPPORTED = 0x1f
|
||||
RWF_SUPPORTED = 0x3f
|
||||
RWF_SYNC = 0x4
|
||||
RWF_WRITE_LIFE_NOT_SET = 0x0
|
||||
SCHED_BATCH = 0x3
|
||||
@@ -2918,7 +2927,9 @@ const (
|
||||
SCHED_RESET_ON_FORK = 0x40000000
|
||||
SCHED_RR = 0x2
|
||||
SCM_CREDENTIALS = 0x2
|
||||
SCM_PIDFD = 0x4
|
||||
SCM_RIGHTS = 0x1
|
||||
SCM_SECURITY = 0x3
|
||||
SCM_TIMESTAMP = 0x1d
|
||||
SC_LOG_FLUSH = 0x100000
|
||||
SECCOMP_ADDFD_FLAG_SEND = 0x2
|
||||
@@ -3051,6 +3062,8 @@ const (
|
||||
SIOCSMIIREG = 0x8949
|
||||
SIOCSRARP = 0x8962
|
||||
SIOCWANDEV = 0x894a
|
||||
SK_DIAG_BPF_STORAGE_MAX = 0x3
|
||||
SK_DIAG_BPF_STORAGE_REQ_MAX = 0x1
|
||||
SMACK_MAGIC = 0x43415d53
|
||||
SMART_AUTOSAVE = 0xd2
|
||||
SMART_AUTO_OFFLINE = 0xdb
|
||||
@@ -3071,6 +3084,8 @@ const (
|
||||
SOCKFS_MAGIC = 0x534f434b
|
||||
SOCK_BUF_LOCK_MASK = 0x3
|
||||
SOCK_DCCP = 0x6
|
||||
SOCK_DESTROY = 0x15
|
||||
SOCK_DIAG_BY_FAMILY = 0x14
|
||||
SOCK_IOC_TYPE = 0x89
|
||||
SOCK_PACKET = 0xa
|
||||
SOCK_RAW = 0x3
|
||||
@@ -3260,6 +3275,7 @@ const (
|
||||
TCP_MAX_WINSHIFT = 0xe
|
||||
TCP_MD5SIG = 0xe
|
||||
TCP_MD5SIG_EXT = 0x20
|
||||
TCP_MD5SIG_FLAG_IFINDEX = 0x2
|
||||
TCP_MD5SIG_FLAG_PREFIX = 0x1
|
||||
TCP_MD5SIG_MAXKEYLEN = 0x50
|
||||
TCP_MSS = 0x200
|
||||
|
||||
+1
@@ -118,6 +118,7 @@ const (
|
||||
IXOFF = 0x1000
|
||||
IXON = 0x400
|
||||
MAP_32BIT = 0x40
|
||||
MAP_ABOVE4G = 0x80
|
||||
MAP_ANON = 0x20
|
||||
MAP_ANONYMOUS = 0x20
|
||||
MAP_DENYWRITE = 0x800
|
||||
|
||||
+1
@@ -118,6 +118,7 @@ const (
|
||||
IXOFF = 0x1000
|
||||
IXON = 0x400
|
||||
MAP_32BIT = 0x40
|
||||
MAP_ABOVE4G = 0x80
|
||||
MAP_ANON = 0x20
|
||||
MAP_ANONYMOUS = 0x20
|
||||
MAP_DENYWRITE = 0x800
|
||||
|
||||
+1
@@ -87,6 +87,7 @@ const (
|
||||
FICLONE = 0x40049409
|
||||
FICLONERANGE = 0x4020940d
|
||||
FLUSHO = 0x1000
|
||||
FPMR_MAGIC = 0x46504d52
|
||||
FPSIMD_MAGIC = 0x46508001
|
||||
FS_IOC_ENABLE_VERITY = 0x40806685
|
||||
FS_IOC_GETFLAGS = 0x80086601
|
||||
|
||||
+34
-3
@@ -4605,7 +4605,7 @@ const (
|
||||
NL80211_ATTR_MAC_HINT = 0xc8
|
||||
NL80211_ATTR_MAC_MASK = 0xd7
|
||||
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
|
||||
NL80211_ATTR_MAX = 0x149
|
||||
NL80211_ATTR_MAX = 0x14a
|
||||
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
|
||||
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
|
||||
NL80211_ATTR_MAX_MATCH_SETS = 0x85
|
||||
@@ -5209,7 +5209,7 @@ const (
|
||||
NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf
|
||||
NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe
|
||||
NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf
|
||||
NL80211_FREQUENCY_ATTR_MAX = 0x1f
|
||||
NL80211_FREQUENCY_ATTR_MAX = 0x20
|
||||
NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6
|
||||
NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11
|
||||
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
|
||||
@@ -5703,7 +5703,7 @@ const (
|
||||
NL80211_STA_FLAG_ASSOCIATED = 0x7
|
||||
NL80211_STA_FLAG_AUTHENTICATED = 0x5
|
||||
NL80211_STA_FLAG_AUTHORIZED = 0x1
|
||||
NL80211_STA_FLAG_MAX = 0x7
|
||||
NL80211_STA_FLAG_MAX = 0x8
|
||||
NL80211_STA_FLAG_MAX_OLD_API = 0x6
|
||||
NL80211_STA_FLAG_MFP = 0x4
|
||||
NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2
|
||||
@@ -6001,3 +6001,34 @@ type CachestatRange struct {
|
||||
Off uint64
|
||||
Len uint64
|
||||
}
|
||||
|
||||
const (
|
||||
SK_MEMINFO_RMEM_ALLOC = 0x0
|
||||
SK_MEMINFO_RCVBUF = 0x1
|
||||
SK_MEMINFO_WMEM_ALLOC = 0x2
|
||||
SK_MEMINFO_SNDBUF = 0x3
|
||||
SK_MEMINFO_FWD_ALLOC = 0x4
|
||||
SK_MEMINFO_WMEM_QUEUED = 0x5
|
||||
SK_MEMINFO_OPTMEM = 0x6
|
||||
SK_MEMINFO_BACKLOG = 0x7
|
||||
SK_MEMINFO_DROPS = 0x8
|
||||
SK_MEMINFO_VARS = 0x9
|
||||
SKNLGRP_NONE = 0x0
|
||||
SKNLGRP_INET_TCP_DESTROY = 0x1
|
||||
SKNLGRP_INET_UDP_DESTROY = 0x2
|
||||
SKNLGRP_INET6_TCP_DESTROY = 0x3
|
||||
SKNLGRP_INET6_UDP_DESTROY = 0x4
|
||||
SK_DIAG_BPF_STORAGE_REQ_NONE = 0x0
|
||||
SK_DIAG_BPF_STORAGE_REQ_MAP_FD = 0x1
|
||||
SK_DIAG_BPF_STORAGE_REP_NONE = 0x0
|
||||
SK_DIAG_BPF_STORAGE = 0x1
|
||||
SK_DIAG_BPF_STORAGE_NONE = 0x0
|
||||
SK_DIAG_BPF_STORAGE_PAD = 0x1
|
||||
SK_DIAG_BPF_STORAGE_MAP_ID = 0x2
|
||||
SK_DIAG_BPF_STORAGE_MAP_VALUE = 0x3
|
||||
)
|
||||
|
||||
type SockDiagReq struct {
|
||||
Family uint8
|
||||
Protocol uint8
|
||||
}
|
||||
|
||||
+1
@@ -68,6 +68,7 @@ type UserInfo10 struct {
|
||||
//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
|
||||
//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
|
||||
//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
|
||||
//sys NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) = netapi32.NetUserEnum
|
||||
|
||||
const (
|
||||
// do not reorder
|
||||
|
||||
+9
@@ -401,6 +401,7 @@ var (
|
||||
procTransmitFile = modmswsock.NewProc("TransmitFile")
|
||||
procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree")
|
||||
procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation")
|
||||
procNetUserEnum = modnetapi32.NewProc("NetUserEnum")
|
||||
procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo")
|
||||
procNtCreateFile = modntdll.NewProc("NtCreateFile")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
@@ -3486,6 +3487,14 @@ func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (nete
|
||||
return
|
||||
}
|
||||
|
||||
func NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) {
|
||||
r0, _, _ := syscall.Syscall9(procNetUserEnum.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), uintptr(unsafe.Pointer(resumeHandle)), 0)
|
||||
if r0 != 0 {
|
||||
neterr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) {
|
||||
r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0)
|
||||
if r0 != 0 {
|
||||
|
||||
+1
@@ -15,5 +15,6 @@ Jan Mercl <0xjnml@gmail.com>
|
||||
Jason DeBettencourt <jasond17@gmail.com>
|
||||
Koichi Shiraishi <zchee.io@gmail.com>
|
||||
Marius Orcsik <marius@federated.id>
|
||||
Patricio Whittingslow <graded.sp@gmail.com>
|
||||
Scot C Bontrager <scot@indievisible.org>
|
||||
Steffen Butzer <steffen(dot)butzer@outlook.com>
|
||||
|
||||
+3
@@ -8,12 +8,15 @@
|
||||
|
||||
Dan Kortschak <dan@kortschak.io>
|
||||
Dan Peterson <danp@danp.net>
|
||||
Bjørn Wiegell <bj.wiegell@gmail.com>
|
||||
Fabrice Colliot <f.colliot@gmail.com>
|
||||
Jaap Aarts <jaap.aarts1@gmail.com>
|
||||
Jan Mercl <0xjnml@gmail.com>
|
||||
Jason DeBettencourt <jasond17@gmail.com>
|
||||
Koichi Shiraishi <zchee.io@gmail.com>
|
||||
Marius Orcsik <marius@federated.id>
|
||||
Patricio Whittingslow <graded.sp@gmail.com>
|
||||
Scot C Bontrager <scot@indievisible.org>
|
||||
Steffen Butzer <steffen(dot)butzer@outlook.com>
|
||||
W. Michael Petullo <mike@flyn.org>
|
||||
ZHU Zijia <piggynl@outlook.com>
|
||||
|
||||
+564
-1
@@ -9,6 +9,9 @@ SHELL=/bin/bash -o pipefail
|
||||
DIR = /tmp/libc
|
||||
TAR = musl-7ada6dde6f9dc6a2836c3d92c2f762d35fd229e0.tar.gz
|
||||
URL = https://git.musl-libc.org/cgit/musl/snapshot/$(TAR)
|
||||
UCRT_386 = libc_windows_386.go
|
||||
UCRT_AMD64 = libc_windows_amd64.go
|
||||
UCRT_ARM64 = libc_windows_arm64.go
|
||||
|
||||
all: editor
|
||||
golint 2>&1
|
||||
@@ -33,7 +36,7 @@ download:
|
||||
|
||||
edit:
|
||||
@touch log
|
||||
@if [ -f "Session.vim" ]; then novim -S & else novim -p Makefile all_musl_test.go generator.go libc.go libc_musl.go & fi
|
||||
@if [ -f "Session.vim" ]; then novim -S & else novim -p Makefile all_windows_test.go generator.go libc.go libc_windows*.go & fi
|
||||
|
||||
editor:
|
||||
gofmt -l -s -w *.go 2>&1 | tee log-editor
|
||||
@@ -41,6 +44,566 @@ editor:
|
||||
go install -v 2>&1 | tee -a log-editor
|
||||
go build -o /dev/null generator*.go
|
||||
|
||||
ucrt:
|
||||
make ucrt_amd64 ucrt_arm64 ucrt_386
|
||||
go build -v ./... 2>&1 | tee -a log-generate
|
||||
GOOS=darwin go build -v ./... 2>&1 | tee -a log-generate
|
||||
git status
|
||||
|
||||
ucrt_amd64:
|
||||
echo -n > log-generate
|
||||
( ccgo -v4 \
|
||||
--cpp=$(shell which x86_64-w64-mingw32-gcc) \
|
||||
--goos=windows \
|
||||
--goarch=amd64 \
|
||||
--package-name libc \
|
||||
--prefix-external=X \
|
||||
--prefix-field=F \
|
||||
--prefix-static-internal=_ \
|
||||
--prefix-static-none=_ \
|
||||
--prefix-tagged-struct=T \
|
||||
--prefix-tagged-union=T \
|
||||
--prefix-typename=T \
|
||||
--winapi-test panic \
|
||||
--winapi=ctype.h \
|
||||
--winapi=float.h \
|
||||
--winapi=io.h \
|
||||
--winapi=libucrt.c \
|
||||
--winapi=locale.h \
|
||||
--winapi=malloc.h \
|
||||
--winapi=math.h \
|
||||
--winapi=process.h \
|
||||
--winapi=types.h \
|
||||
--winapi=stat.h \
|
||||
--winapi=stdio.h \
|
||||
--winapi=stdlib.h \
|
||||
--winapi=string.h \
|
||||
--winapi=time.h \
|
||||
--winapi=timeb.h \
|
||||
--winapi=wchar.h \
|
||||
--winapi=winbase.h \
|
||||
-build-lines=" " \
|
||||
-eval-all-macros \
|
||||
-hide __acrt_iob_func \
|
||||
-hide __create_locale \
|
||||
-hide __free_locale \
|
||||
-hide __get_current_locale \
|
||||
-hide __iob_func \
|
||||
-hide __lock_fhandle \
|
||||
-hide __sep__ \
|
||||
-hide __updatetlocinfo \
|
||||
-hide __updatetmbcinfo \
|
||||
-hide _beginthread \
|
||||
-hide _beginthreadex \
|
||||
-hide _endthreadex \
|
||||
-hide _errno \
|
||||
-hide _filbuf \
|
||||
-hide _flsbuf \
|
||||
-hide _get_amblksiz \
|
||||
-hide _get_osplatform \
|
||||
-hide _get_osver \
|
||||
-hide _get_output_format \
|
||||
-hide _get_sbh_threshold \
|
||||
-hide _get_winmajor \
|
||||
-hide _get_winminor \
|
||||
-hide _get_winver \
|
||||
-hide _heapadd \
|
||||
-hide _heapset \
|
||||
-hide _heapused \
|
||||
-hide _matherr \
|
||||
-hide _onexit \
|
||||
-hide _set_amblksiz \
|
||||
-hide _set_malloc_crt_max_wait \
|
||||
-hide _set_output_format \
|
||||
-hide _set_sbh_threshold \
|
||||
-hide _strcmpi \
|
||||
-hide _strnset_l \
|
||||
-hide _strset_l \
|
||||
-hide _unlock_fhandle \
|
||||
-hide _wcsncpy_l \
|
||||
-hide _wctime \
|
||||
-hide _wctime_s \
|
||||
-hide _wgetdcwd_nolock \
|
||||
-hide _wgetenv \
|
||||
-hide _wputenv \
|
||||
-hide access \
|
||||
-hide at_quick_exit \
|
||||
-hide atexit \
|
||||
-hide chdir \
|
||||
-hide exit \
|
||||
-hide lldiv \
|
||||
-hide qsort \
|
||||
-hide chmod \
|
||||
-hide chsize \
|
||||
-hide close \
|
||||
-hide creat \
|
||||
-hide cwait \
|
||||
-hide dup \
|
||||
-hide dup2 \
|
||||
-hide eof \
|
||||
-hide execv \
|
||||
-hide execve \
|
||||
-hide execvp \
|
||||
-hide execvpe \
|
||||
-hide fcloseall \
|
||||
-hide fdopen \
|
||||
-hide fgetchar \
|
||||
-hide fgetpos64 \
|
||||
-hide filelength \
|
||||
-hide fileno \
|
||||
-hide flushall \
|
||||
-hide fopen64 \
|
||||
-hide fpreset \
|
||||
-hide fputchar \
|
||||
-hide fsetpos64 \
|
||||
-hide ftime \
|
||||
-hide fwide \
|
||||
-hide getcwd \
|
||||
-hide getpid \
|
||||
-hide getw \
|
||||
-hide isatty \
|
||||
-hide itoa \
|
||||
-hide lltoa \
|
||||
-hide lltow \
|
||||
-hide locking \
|
||||
-hide lseek \
|
||||
-hide lseek64 \
|
||||
-hide ltoa \
|
||||
-hide memccpy \
|
||||
-hide memicmp \
|
||||
-hide mempcpy \
|
||||
-hide mkdir \
|
||||
-hide mkstemp \
|
||||
-hide mktemp \
|
||||
-hide onexit \
|
||||
-hide putenv \
|
||||
-hide putw \
|
||||
-hide read \
|
||||
-hide rmdir \
|
||||
-hide rmtmp \
|
||||
-hide setmode \
|
||||
-hide spawnv \
|
||||
-hide spawnve \
|
||||
-hide spawnvp \
|
||||
-hide spawnvpe \
|
||||
-hide strcasecmp \
|
||||
-hide strcmpi \
|
||||
-hide strdup \
|
||||
-hide stricmp \
|
||||
-hide strlwr \
|
||||
-hide strlwr_l \
|
||||
-hide strncasecmp \
|
||||
-hide strnicmp \
|
||||
-hide strnset \
|
||||
-hide strrev \
|
||||
-hide strset \
|
||||
-hide strtok_r \
|
||||
-hide strupr \
|
||||
-hide swab \
|
||||
-hide tell \
|
||||
-hide tempnam \
|
||||
-hide tzset \
|
||||
-hide ulltoa \
|
||||
-hide ulltow \
|
||||
-hide ultoa \
|
||||
-hide umask \
|
||||
-hide unlink \
|
||||
-hide wcsdup \
|
||||
-hide wcsicmp \
|
||||
-hide wcsicoll \
|
||||
-hide wcslwr \
|
||||
-hide wcsnicmp \
|
||||
-hide wcsnset \
|
||||
-hide wcsrev \
|
||||
-hide wcsset \
|
||||
-hide wcsupr \
|
||||
-hide wmemchr \
|
||||
-hide wmemcmp \
|
||||
-hide wmemcpy \
|
||||
-hide wmemmove \
|
||||
-hide wmempcpy \
|
||||
-hide wmemset \
|
||||
-hide write \
|
||||
-hide wtoll \
|
||||
-ignore-link-errors \
|
||||
-import syscall \
|
||||
-keep-strings \
|
||||
-o $(UCRT_AMD64) \
|
||||
libucrt.c \
|
||||
|| true ) 2>&1 | tee -a log-generate
|
||||
sed -i '/"modernc.org\/libc"/d' $(UCRT_AMD64)
|
||||
sed -i 's/\<libc\>\.//g' $(UCRT_AMD64)
|
||||
GOOS=windows GOARCH=amd64 go build -v ./... 2>&1 | tee -a log-generate
|
||||
|
||||
ucrt_arm64:
|
||||
echo -n > log-generate
|
||||
( ccgo -v4 \
|
||||
--cpp=$(shell which x86_64-w64-mingw32-gcc) \
|
||||
--goos=windows \
|
||||
--goarch=amd64 \
|
||||
--package-name libc \
|
||||
--prefix-external=X \
|
||||
--prefix-field=F \
|
||||
--prefix-static-internal=_ \
|
||||
--prefix-static-none=_ \
|
||||
--prefix-tagged-struct=T \
|
||||
--prefix-tagged-union=T \
|
||||
--prefix-typename=T \
|
||||
--winapi-test panic \
|
||||
--winapi=ctype.h \
|
||||
--winapi=float.h \
|
||||
--winapi=io.h \
|
||||
--winapi=libucrt.c \
|
||||
--winapi=locale.h \
|
||||
--winapi=malloc.h \
|
||||
--winapi=math.h \
|
||||
--winapi=process.h \
|
||||
--winapi=types.h \
|
||||
--winapi=stat.h \
|
||||
--winapi=stdio.h \
|
||||
--winapi=stdlib.h \
|
||||
--winapi=string.h \
|
||||
--winapi=time.h \
|
||||
--winapi=timeb.h \
|
||||
--winapi=wchar.h \
|
||||
--winapi=winbase.h \
|
||||
-build-lines=" " \
|
||||
-eval-all-macros \
|
||||
-hide __acrt_iob_func \
|
||||
-hide _errno \
|
||||
-hide _wgetenv \
|
||||
-hide _wputenv \
|
||||
-hide exit \
|
||||
-hide lldiv \
|
||||
-hide qsort \
|
||||
-hide __sep__ \
|
||||
-hide __create_locale \
|
||||
-hide __free_locale \
|
||||
-hide __get_current_locale \
|
||||
-hide __iob_func \
|
||||
-hide __lock_fhandle \
|
||||
-hide __updatetlocinfo \
|
||||
-hide __updatetmbcinfo \
|
||||
-hide _beginthread \
|
||||
-hide _beginthreadex \
|
||||
-hide _endthreadex \
|
||||
-hide _filbuf \
|
||||
-hide _flsbuf \
|
||||
-hide _get_amblksiz \
|
||||
-hide _get_osplatform \
|
||||
-hide _get_osver \
|
||||
-hide _get_output_format \
|
||||
-hide _get_sbh_threshold \
|
||||
-hide _get_winmajor \
|
||||
-hide _get_winminor \
|
||||
-hide _get_winver \
|
||||
-hide _heapadd \
|
||||
-hide _heapset \
|
||||
-hide _heapused \
|
||||
-hide _matherr \
|
||||
-hide _onexit \
|
||||
-hide _set_amblksiz \
|
||||
-hide _set_malloc_crt_max_wait \
|
||||
-hide _set_output_format \
|
||||
-hide _set_sbh_threshold \
|
||||
-hide _strcmpi \
|
||||
-hide _strnset_l \
|
||||
-hide _strset_l \
|
||||
-hide _unlock_fhandle \
|
||||
-hide _wcsncpy_l \
|
||||
-hide _wctime \
|
||||
-hide _wctime_s \
|
||||
-hide _wgetdcwd_nolock \
|
||||
-hide access \
|
||||
-hide at_quick_exit \
|
||||
-hide atexit \
|
||||
-hide chdir \
|
||||
-hide chmod \
|
||||
-hide chsize \
|
||||
-hide close \
|
||||
-hide creat \
|
||||
-hide cwait \
|
||||
-hide dup \
|
||||
-hide dup2 \
|
||||
-hide eof \
|
||||
-hide execv \
|
||||
-hide execve \
|
||||
-hide execvp \
|
||||
-hide execvpe \
|
||||
-hide fcloseall \
|
||||
-hide fdopen \
|
||||
-hide fgetchar \
|
||||
-hide fgetpos64 \
|
||||
-hide filelength \
|
||||
-hide fileno \
|
||||
-hide flushall \
|
||||
-hide fopen64 \
|
||||
-hide fpreset \
|
||||
-hide fputchar \
|
||||
-hide fsetpos64 \
|
||||
-hide ftime \
|
||||
-hide fwide \
|
||||
-hide getcwd \
|
||||
-hide getpid \
|
||||
-hide getw \
|
||||
-hide isatty \
|
||||
-hide itoa \
|
||||
-hide lltoa \
|
||||
-hide lltow \
|
||||
-hide locking \
|
||||
-hide lseek \
|
||||
-hide lseek64 \
|
||||
-hide ltoa \
|
||||
-hide memccpy \
|
||||
-hide memicmp \
|
||||
-hide mempcpy \
|
||||
-hide mkdir \
|
||||
-hide mkstemp \
|
||||
-hide mktemp \
|
||||
-hide onexit \
|
||||
-hide putenv \
|
||||
-hide putw \
|
||||
-hide read \
|
||||
-hide rmdir \
|
||||
-hide rmtmp \
|
||||
-hide setmode \
|
||||
-hide spawnv \
|
||||
-hide spawnve \
|
||||
-hide spawnvp \
|
||||
-hide spawnvpe \
|
||||
-hide strcasecmp \
|
||||
-hide strcmpi \
|
||||
-hide strdup \
|
||||
-hide stricmp \
|
||||
-hide strlwr \
|
||||
-hide strlwr_l \
|
||||
-hide strncasecmp \
|
||||
-hide strnicmp \
|
||||
-hide strnset \
|
||||
-hide strrev \
|
||||
-hide strset \
|
||||
-hide strtok_r \
|
||||
-hide strupr \
|
||||
-hide swab \
|
||||
-hide tell \
|
||||
-hide tempnam \
|
||||
-hide tzset \
|
||||
-hide ulltoa \
|
||||
-hide ulltow \
|
||||
-hide ultoa \
|
||||
-hide umask \
|
||||
-hide unlink \
|
||||
-hide wcsdup \
|
||||
-hide wcsicmp \
|
||||
-hide wcsicoll \
|
||||
-hide wcslwr \
|
||||
-hide wcsnicmp \
|
||||
-hide wcsnset \
|
||||
-hide wcsrev \
|
||||
-hide wcsset \
|
||||
-hide wcsupr \
|
||||
-hide wmemchr \
|
||||
-hide wmemcmp \
|
||||
-hide wmemcpy \
|
||||
-hide wmemmove \
|
||||
-hide wmempcpy \
|
||||
-hide wmemset \
|
||||
-hide write \
|
||||
-hide wtoll \
|
||||
-ignore-link-errors \
|
||||
-import syscall \
|
||||
-keep-strings \
|
||||
-o $(UCRT_ARM64) \
|
||||
libucrt.c \
|
||||
|| true ) 2>&1 | tee -a log-generate
|
||||
sed -i '/"modernc.org\/libc"/d' $(UCRT_ARM64)
|
||||
sed -i 's/\<libc\>\.//g' $(UCRT_ARM64)
|
||||
GOOS=windows GOARCH=arm64 go build -v ./... 2>&1 | tee -a log-generate
|
||||
|
||||
ucrt_386:
|
||||
echo -n > log-generate
|
||||
( ccgo -v4 \
|
||||
--cpp=$(shell which i686-w64-mingw32-gcc) \
|
||||
--goos=windows \
|
||||
--goarch=386 \
|
||||
--package-name libc \
|
||||
--prefix-external=X \
|
||||
--prefix-field=F \
|
||||
--prefix-static-internal=_ \
|
||||
--prefix-static-none=_ \
|
||||
--prefix-tagged-struct=T \
|
||||
--prefix-tagged-union=T \
|
||||
--prefix-typename=T \
|
||||
--winapi-test panic \
|
||||
--winapi=ctype.h \
|
||||
--winapi=float.h \
|
||||
--winapi=io.h \
|
||||
--winapi=libucrt.c \
|
||||
--winapi=locale.h \
|
||||
--winapi=malloc.h \
|
||||
--winapi=math.h \
|
||||
--winapi=process.h \
|
||||
--winapi=types.h \
|
||||
--winapi=stat.h \
|
||||
--winapi=stdio.h \
|
||||
--winapi=stdlib.h \
|
||||
--winapi=string.h \
|
||||
--winapi=time.h \
|
||||
--winapi=timeb.h \
|
||||
--winapi=wchar.h \
|
||||
--winapi=winbase.h \
|
||||
-build-lines=" " \
|
||||
-eval-all-macros \
|
||||
-hide __acrt_iob_func \
|
||||
-hide _errno \
|
||||
-hide _wgetenv \
|
||||
-hide _wputenv \
|
||||
-hide exit \
|
||||
-hide lldiv \
|
||||
-hide qsort \
|
||||
-hide __sep__ \
|
||||
-hide __create_locale \
|
||||
-hide __free_locale \
|
||||
-hide __get_current_locale \
|
||||
-hide __lock_fhandle \
|
||||
-hide __updatetlocinfo \
|
||||
-hide __updatetmbcinfo \
|
||||
-hide _beginthread \
|
||||
-hide _beginthreadex \
|
||||
-hide _endthreadex \
|
||||
-hide _filbuf \
|
||||
-hide _flsbuf \
|
||||
-hide _get_amblksiz \
|
||||
-hide _get_osplatform \
|
||||
-hide _get_osver \
|
||||
-hide _get_output_format \
|
||||
-hide _get_sbh_threshold \
|
||||
-hide _get_winmajor \
|
||||
-hide _get_winminor \
|
||||
-hide _get_winver \
|
||||
-hide _heapadd \
|
||||
-hide _heapset \
|
||||
-hide _heapused \
|
||||
-hide _matherr \
|
||||
-hide _onexit \
|
||||
-hide _set_amblksiz \
|
||||
-hide _set_malloc_crt_max_wait \
|
||||
-hide _set_output_format \
|
||||
-hide _set_sbh_threshold \
|
||||
-hide _strcmpi \
|
||||
-hide _strnset_l \
|
||||
-hide _strset_l \
|
||||
-hide _unlock_fhandle \
|
||||
-hide _wcsncpy_l \
|
||||
-hide _wctime \
|
||||
-hide _wctime_s \
|
||||
-hide _wgetdcwd_nolock \
|
||||
-hide access \
|
||||
-hide at_quick_exit \
|
||||
-hide atexit \
|
||||
-hide chdir \
|
||||
-hide chmod \
|
||||
-hide chsize \
|
||||
-hide close \
|
||||
-hide creat \
|
||||
-hide cwait \
|
||||
-hide dup \
|
||||
-hide dup2 \
|
||||
-hide eof \
|
||||
-hide execv \
|
||||
-hide execve \
|
||||
-hide execvp \
|
||||
-hide execvpe \
|
||||
-hide fcloseall \
|
||||
-hide fdopen \
|
||||
-hide fgetchar \
|
||||
-hide fgetpos64 \
|
||||
-hide filelength \
|
||||
-hide fileno \
|
||||
-hide flushall \
|
||||
-hide fopen64 \
|
||||
-hide fpreset \
|
||||
-hide fputchar \
|
||||
-hide fsetpos64 \
|
||||
-hide ftime \
|
||||
-hide fwide \
|
||||
-hide getcwd \
|
||||
-hide getpid \
|
||||
-hide getw \
|
||||
-hide isatty \
|
||||
-hide itoa \
|
||||
-hide lltoa \
|
||||
-hide lltow \
|
||||
-hide locking \
|
||||
-hide lseek \
|
||||
-hide lseek64 \
|
||||
-hide ltoa \
|
||||
-hide memccpy \
|
||||
-hide memicmp \
|
||||
-hide mempcpy \
|
||||
-hide mkdir \
|
||||
-hide mkstemp \
|
||||
-hide mktemp \
|
||||
-hide onexit \
|
||||
-hide putenv \
|
||||
-hide putw \
|
||||
-hide read \
|
||||
-hide rmdir \
|
||||
-hide rmtmp \
|
||||
-hide setmode \
|
||||
-hide spawnv \
|
||||
-hide spawnve \
|
||||
-hide spawnvp \
|
||||
-hide spawnvpe \
|
||||
-hide strcasecmp \
|
||||
-hide strcmpi \
|
||||
-hide strdup \
|
||||
-hide stricmp \
|
||||
-hide strlwr \
|
||||
-hide strlwr_l \
|
||||
-hide strncasecmp \
|
||||
-hide strnicmp \
|
||||
-hide strnset \
|
||||
-hide strrev \
|
||||
-hide strset \
|
||||
-hide strtok_r \
|
||||
-hide strupr \
|
||||
-hide swab \
|
||||
-hide tell \
|
||||
-hide tempnam \
|
||||
-hide tzset \
|
||||
-hide ulltoa \
|
||||
-hide ulltow \
|
||||
-hide ultoa \
|
||||
-hide umask \
|
||||
-hide unlink \
|
||||
-hide wcsdup \
|
||||
-hide wcsicmp \
|
||||
-hide wcsicoll \
|
||||
-hide wcslwr \
|
||||
-hide wcsnicmp \
|
||||
-hide wcsnset \
|
||||
-hide wcsrev \
|
||||
-hide wcsset \
|
||||
-hide wcsupr \
|
||||
-hide wmemchr \
|
||||
-hide wmemcmp \
|
||||
-hide wmemcpy \
|
||||
-hide wmemmove \
|
||||
-hide wmempcpy \
|
||||
-hide wmemset \
|
||||
-hide write \
|
||||
-hide wtoll \
|
||||
-ignore-link-errors \
|
||||
-import syscall \
|
||||
-keep-strings \
|
||||
-o $(UCRT_386) \
|
||||
libucrt.c \
|
||||
|| true ) 2>&1 | tee -a log-generate
|
||||
sed -i '/"modernc.org\/libc"/d' $(UCRT_386)
|
||||
sed -i 's/\<libc\>\.//g' $(UCRT_386)
|
||||
GOOS=windows GOARCH=386 go build -v ./... 2>&1 | tee -a log-generate
|
||||
|
||||
generate: download
|
||||
mkdir -p $(DIR) || true
|
||||
rm -rf $(DIR)/*
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// 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)
|
||||
//go:build linux && (amd64 || arm64 || loong64)
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
// Copyright 202 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
heapAlign = 16
|
||||
heapGuard = 16
|
||||
)
|
||||
|
||||
const FALSE = 0
|
||||
const TRUE = 1
|
||||
|
||||
var (
|
||||
pid = fmt.Sprintf("[%v %v] ", os.Getpid(), filepath.Base(os.Args[0]))
|
||||
)
|
||||
|
||||
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:]
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s:%d:%s", filepath.Base(fn), fl, fns)
|
||||
}
|
||||
|
||||
func trc(s string, args ...interface{}) string { //TODO-
|
||||
switch {
|
||||
case s == "":
|
||||
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
|
||||
default:
|
||||
s = fmt.Sprintf(s, args...)
|
||||
}
|
||||
r := fmt.Sprintf("%s: TRC %s (%v:)", origin(2), s, origin(3))
|
||||
fmt.Fprintf(os.Stdout, "%s %s\n", pid, r)
|
||||
os.Stdout.Sync()
|
||||
return r
|
||||
}
|
||||
|
||||
func todo(s string, args ...interface{}) string { //TODO-
|
||||
switch {
|
||||
case s == "":
|
||||
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
|
||||
default:
|
||||
s = fmt.Sprintf(s, args...)
|
||||
}
|
||||
r := fmt.Sprintf("%s %s: TODOTODO %s (%v:)", pid, origin(2), s, origin(3)) //TODOOK
|
||||
if dmesgs {
|
||||
dmesg("%s", r)
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s\n", r)
|
||||
fmt.Fprintf(os.Stdout, "%s\n", debug.Stack()) //TODO-
|
||||
os.Stdout.Sync()
|
||||
os.Exit(1)
|
||||
panic("unrechable")
|
||||
}
|
||||
|
||||
type sorter struct {
|
||||
len int
|
||||
base uintptr
|
||||
sz uintptr
|
||||
f func(*TLS, uintptr, uintptr) int32
|
||||
t *TLS
|
||||
}
|
||||
|
||||
func (s *sorter) Len() int { return s.len }
|
||||
|
||||
func (s *sorter) Less(i, j int) bool {
|
||||
return s.f(s.t, s.base+uintptr(i)*s.sz, s.base+uintptr(j)*s.sz) < 0
|
||||
}
|
||||
|
||||
func (s *sorter) Swap(i, j int) {
|
||||
p := s.base + uintptr(i)*s.sz
|
||||
q := s.base + uintptr(j)*s.sz
|
||||
for i := 0; i < int(s.sz); i++ {
|
||||
*(*byte)(unsafe.Pointer(p)), *(*byte)(unsafe.Pointer(q)) = *(*byte)(unsafe.Pointer(q)), *(*byte)(unsafe.Pointer(p))
|
||||
p++
|
||||
q++
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -2,13 +2,13 @@
|
||||
// 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)
|
||||
//go:build linux && (amd64 || arm64 || loong64)
|
||||
|
||||
package libc // import "modernc.org/libc/v2"
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/bits"
|
||||
mbits "math/bits"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -41,15 +41,15 @@ func a_store_16(addr uintptr, val uint16) {
|
||||
// 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(mbits.TrailingZeros64(x))
|
||||
}
|
||||
|
||||
return int32(bits.TrailingZeros32(uint32(x)))
|
||||
return int32(mbits.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))
|
||||
return int32(mbits.TrailingZeros64(x))
|
||||
}
|
||||
|
||||
func AtomicAddFloat32(addr *float32, delta float32) (new float32) {
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"autogen": "linux/(amd64|loong64)",
|
||||
"autogen": "linux/(amd64|arm64|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)",
|
||||
"autotag": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/(386|amd64|arm64)|windows/(amd64|arm64|386)",
|
||||
"download": [
|
||||
{"re": "linux/(amd64|loong64)", "files": ["https://git.musl-libc.org/cgit/musl/snapshot/musl-7ada6dde6f9dc6a2836c3d92c2f762d35fd229e0.tar.gz"]}
|
||||
{"re": "linux/(amd64|arm64|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)"
|
||||
"test": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/(386|amd64|arm64)|windows/(amd64|arm64|386)"
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// 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)
|
||||
//go:build linux && (amd64 || arm64 || loong64)
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// Code generated by 'go generate' - DO NOT EDIT.
|
||||
|
||||
//go:build !(linux && (amd64 || loong64))
|
||||
//go:build !(linux && (amd64 || arm64 || loong64))
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+1212
-1213
File diff suppressed because one or more lines are too long
+154129
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+7
-3
@@ -10,7 +10,6 @@ package libc // import "modernc.org/libc"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -18,7 +17,6 @@ import (
|
||||
const dmesgs = true
|
||||
|
||||
var (
|
||||
pid = fmt.Sprintf("[%v %v] ", os.Getpid(), filepath.Base(os.Args[0]))
|
||||
logf *os.File
|
||||
)
|
||||
|
||||
@@ -28,7 +26,7 @@ func init() {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
dmesg("%v", time.Now())
|
||||
dmesg("==== dmesg init() %v", time.Now())
|
||||
}
|
||||
|
||||
func dmesg(s string, args ...interface{}) {
|
||||
@@ -43,3 +41,9 @@ func dmesg(s string, args ...interface{}) {
|
||||
fmt.Fprintln(logf, s)
|
||||
}
|
||||
}
|
||||
|
||||
func dmesgFinish() {
|
||||
dmesg("==== dmesgFinish() %v", time.Now())
|
||||
logf.Sync()
|
||||
logf.Close()
|
||||
}
|
||||
|
||||
+1
-161
@@ -2,7 +2,7 @@
|
||||
// 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))
|
||||
//go:build !((linux && (amd64 || arm64 || loong64)) || windows)
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -62,50 +61,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
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:]
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s:%d:%s", filepath.Base(fn), fl, fns)
|
||||
}
|
||||
|
||||
func trc(s string, args ...interface{}) string { //TODO-
|
||||
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.Stdout, "%s\n", r)
|
||||
os.Stdout.Sync()
|
||||
return r
|
||||
}
|
||||
|
||||
func todo(s string, args ...interface{}) string { //TODO-
|
||||
switch {
|
||||
case s == "":
|
||||
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
|
||||
default:
|
||||
s = fmt.Sprintf(s, args...)
|
||||
}
|
||||
r := fmt.Sprintf("%s: TODOTODO %s", origin(2), s) //TODOOK
|
||||
if dmesgs {
|
||||
dmesg("%s", r)
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s\n", r)
|
||||
fmt.Fprintf(os.Stdout, "%s\n", debug.Stack()) //TODO-
|
||||
os.Stdout.Sync()
|
||||
os.Exit(1)
|
||||
panic("unrechable")
|
||||
}
|
||||
|
||||
var coverPCs [1]uintptr //TODO not concurrent safe
|
||||
|
||||
func Cover() {
|
||||
@@ -481,97 +436,6 @@ func VaOther(app *uintptr, sz uint64) (r uintptr) {
|
||||
return r
|
||||
}
|
||||
|
||||
func VaInt32(app *uintptr) int32 {
|
||||
ap := *(*uintptr)(unsafe.Pointer(app))
|
||||
if ap == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ap = roundup(ap, 8)
|
||||
v := int32(*(*int64)(unsafe.Pointer(ap)))
|
||||
ap += 8
|
||||
*(*uintptr)(unsafe.Pointer(app)) = ap
|
||||
return v
|
||||
}
|
||||
|
||||
func VaUint32(app *uintptr) uint32 {
|
||||
ap := *(*uintptr)(unsafe.Pointer(app))
|
||||
if ap == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ap = roundup(ap, 8)
|
||||
v := uint32(*(*uint64)(unsafe.Pointer(ap)))
|
||||
ap += 8
|
||||
*(*uintptr)(unsafe.Pointer(app)) = ap
|
||||
return v
|
||||
}
|
||||
|
||||
func VaInt64(app *uintptr) int64 {
|
||||
ap := *(*uintptr)(unsafe.Pointer(app))
|
||||
if ap == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ap = roundup(ap, 8)
|
||||
v := *(*int64)(unsafe.Pointer(ap))
|
||||
ap += 8
|
||||
*(*uintptr)(unsafe.Pointer(app)) = ap
|
||||
return v
|
||||
}
|
||||
|
||||
func VaUint64(app *uintptr) uint64 {
|
||||
ap := *(*uintptr)(unsafe.Pointer(app))
|
||||
if ap == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ap = roundup(ap, 8)
|
||||
v := *(*uint64)(unsafe.Pointer(ap))
|
||||
ap += 8
|
||||
*(*uintptr)(unsafe.Pointer(app)) = ap
|
||||
return v
|
||||
}
|
||||
|
||||
func VaFloat32(app *uintptr) float32 {
|
||||
ap := *(*uintptr)(unsafe.Pointer(app))
|
||||
if ap == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ap = roundup(ap, 8)
|
||||
v := *(*float64)(unsafe.Pointer(ap))
|
||||
ap += 8
|
||||
*(*uintptr)(unsafe.Pointer(app)) = ap
|
||||
return float32(v)
|
||||
}
|
||||
|
||||
func VaFloat64(app *uintptr) float64 {
|
||||
ap := *(*uintptr)(unsafe.Pointer(app))
|
||||
if ap == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ap = roundup(ap, 8)
|
||||
v := *(*float64)(unsafe.Pointer(ap))
|
||||
ap += 8
|
||||
*(*uintptr)(unsafe.Pointer(app)) = ap
|
||||
return v
|
||||
}
|
||||
|
||||
func VaUintptr(app *uintptr) uintptr {
|
||||
ap := *(*uintptr)(unsafe.Pointer(app))
|
||||
if ap == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ap = roundup(ap, 8)
|
||||
v := *(*uintptr)(unsafe.Pointer(ap))
|
||||
ap += 8
|
||||
*(*uintptr)(unsafe.Pointer(app)) = ap
|
||||
return v
|
||||
}
|
||||
|
||||
func getVaList(va uintptr) []string {
|
||||
r := []string{}
|
||||
|
||||
@@ -637,30 +501,6 @@ func Bool64(b bool) int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type sorter struct {
|
||||
len int
|
||||
base uintptr
|
||||
sz uintptr
|
||||
f func(*TLS, uintptr, uintptr) int32
|
||||
t *TLS
|
||||
}
|
||||
|
||||
func (s *sorter) Len() int { return s.len }
|
||||
|
||||
func (s *sorter) Less(i, j int) bool {
|
||||
return s.f(s.t, s.base+uintptr(i)*s.sz, s.base+uintptr(j)*s.sz) < 0
|
||||
}
|
||||
|
||||
func (s *sorter) Swap(i, j int) {
|
||||
p := uintptr(s.base + uintptr(i)*s.sz)
|
||||
q := uintptr(s.base + uintptr(j)*s.sz)
|
||||
for i := 0; i < int(s.sz); i++ {
|
||||
*(*byte)(unsafe.Pointer(p)), *(*byte)(unsafe.Pointer(q)) = *(*byte)(unsafe.Pointer(q)), *(*byte)(unsafe.Pointer(p))
|
||||
p++
|
||||
q++
|
||||
}
|
||||
}
|
||||
|
||||
func CString(s string) (uintptr, error) {
|
||||
n := len(s)
|
||||
p := Xmalloc(nil, types.Size_t(n)+1)
|
||||
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
// 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
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
// 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))
|
||||
//go:build !(linux && (amd64 || arm64 || loong64))
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+11
-377
@@ -2,7 +2,7 @@
|
||||
// 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))
|
||||
//go:build !((linux && (amd64 || arm64 || loong64)) || windows)
|
||||
|
||||
//go.generate echo package libc > ccgo.go
|
||||
//go:generate go fmt ./...
|
||||
@@ -51,7 +51,7 @@ type (
|
||||
)
|
||||
|
||||
var (
|
||||
allocMu sync.Mutex
|
||||
allocatorMu sync.Mutex
|
||||
environInitialized bool
|
||||
isWindows bool
|
||||
ungetcMu sync.Mutex
|
||||
@@ -174,6 +174,7 @@ func exit(t *TLS, status int32, audit bool) {
|
||||
func X_exit(_ *TLS, status int32) {
|
||||
if dmesgs {
|
||||
dmesg("%v: EXIT %v", origin(1), status)
|
||||
dmesgFinish()
|
||||
}
|
||||
os.Exit(int(status))
|
||||
}
|
||||
@@ -510,13 +511,6 @@ func X__isnanl(t *TLS, arg float64) int32 {
|
||||
return Xisnanl(t, arg)
|
||||
}
|
||||
|
||||
func Xvfprintf(t *TLS, stream, format, ap uintptr) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v ap=%v, (%v:)", t, ap, origin(2))
|
||||
}
|
||||
return Xfprintf(t, stream, format, ap)
|
||||
}
|
||||
|
||||
// int __builtin_popcount (unsigned int x)
|
||||
func X__builtin_popcount(t *TLS, x uint32) int32 {
|
||||
if __ccgo_strace {
|
||||
@@ -735,19 +729,6 @@ func AtomicStoreNUint16(ptr uintptr, val uint16, memorder int32) {
|
||||
a_store_16(ptr, val)
|
||||
}
|
||||
|
||||
// int sprintf(char *str, const char *format, ...);
|
||||
func Xsprintf(t *TLS, str, format, args uintptr) (r int32) {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v args=%v, (%v:)", t, args, origin(2))
|
||||
defer func() { trc("-> %v", r) }()
|
||||
}
|
||||
b := printf(format, args)
|
||||
r = int32(len(b))
|
||||
copy((*RawMem)(unsafe.Pointer(str))[:r:r], b)
|
||||
*(*byte)(unsafe.Pointer(str + uintptr(r))) = 0
|
||||
return int32(len(b))
|
||||
}
|
||||
|
||||
// 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 types.Size_t, format, args uintptr) (r int32) {
|
||||
if __ccgo_strace {
|
||||
@@ -795,14 +776,6 @@ func Xvprintf(t *TLS, s, ap uintptr) int32 {
|
||||
return Xprintf(t, s, ap)
|
||||
}
|
||||
|
||||
// int vsprintf(char *str, const char *format, va_list ap);
|
||||
func Xvsprintf(t *TLS, str, format, va uintptr) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v va=%v, (%v:)", t, va, origin(2))
|
||||
}
|
||||
return Xsprintf(t, str, format, va)
|
||||
}
|
||||
|
||||
// int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
func Xvsnprintf(t *TLS, str uintptr, size types.Size_t, format, va uintptr) int32 {
|
||||
if __ccgo_strace {
|
||||
@@ -886,15 +859,6 @@ func Xstrcspn(t *TLS, s, reject uintptr) (r types.Size_t) {
|
||||
}
|
||||
}
|
||||
|
||||
// int printf(const char *format, ...);
|
||||
func Xprintf(t *TLS, format, args uintptr) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v args=%v, (%v:)", t, args, origin(2))
|
||||
}
|
||||
n, _ := write(printf(format, args))
|
||||
return int32(n)
|
||||
}
|
||||
|
||||
// int snprintf(char *str, size_t size, const char *format, ...);
|
||||
func Xsnprintf(t *TLS, str uintptr, size types.Size_t, format, args uintptr) (r int32) {
|
||||
if __ccgo_strace {
|
||||
@@ -995,206 +959,14 @@ func X__builtin_llabs(tls *TLS, a int64) int64 {
|
||||
return Xllabs(tls, a)
|
||||
}
|
||||
|
||||
func Xacos(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Acos(x)
|
||||
}
|
||||
|
||||
func Xacosh(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Acosh(x)
|
||||
}
|
||||
|
||||
func Xasin(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Asin(x)
|
||||
}
|
||||
|
||||
func Xasinh(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Asinh(x)
|
||||
}
|
||||
|
||||
func Xatan(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Atan(x)
|
||||
}
|
||||
|
||||
func Xatan2(t *TLS, x, y float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v y=%v, (%v:)", t, y, origin(2))
|
||||
}
|
||||
return math.Atan2(x, y)
|
||||
}
|
||||
|
||||
func Xatanh(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Atanh(x)
|
||||
}
|
||||
|
||||
func Xceil(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Ceil(x)
|
||||
}
|
||||
|
||||
func Xceilf(t *TLS, x float32) float32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return float32(math.Ceil(float64(x)))
|
||||
}
|
||||
|
||||
func Xcopysign(t *TLS, x, y float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v y=%v, (%v:)", t, y, origin(2))
|
||||
}
|
||||
return math.Copysign(x, y)
|
||||
}
|
||||
|
||||
func Xcopysignf(t *TLS, x, y float32) float32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v y=%v, (%v:)", t, y, origin(2))
|
||||
}
|
||||
return float32(math.Copysign(float64(x), float64(y)))
|
||||
}
|
||||
|
||||
func Xcos(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Cos(x)
|
||||
}
|
||||
|
||||
func Xcosf(t *TLS, x float32) float32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return float32(math.Cos(float64(x)))
|
||||
}
|
||||
|
||||
func Xcosh(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Cosh(x)
|
||||
}
|
||||
|
||||
func Xexp(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Exp(x)
|
||||
}
|
||||
|
||||
func Xfabs(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Abs(x)
|
||||
}
|
||||
|
||||
func Xfabsf(t *TLS, x float32) float32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return float32(math.Abs(float64(x)))
|
||||
}
|
||||
|
||||
func Xfloor(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Floor(x)
|
||||
}
|
||||
|
||||
func Xfmod(t *TLS, x, y float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v y=%v, (%v:)", t, y, origin(2))
|
||||
}
|
||||
return math.Mod(x, y)
|
||||
}
|
||||
|
||||
func Xhypot(t *TLS, x, y float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v y=%v, (%v:)", t, y, origin(2))
|
||||
}
|
||||
return math.Hypot(x, y)
|
||||
}
|
||||
|
||||
func Xisnan(t *TLS, x float64) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return X__builtin_isnan(t, x)
|
||||
}
|
||||
|
||||
func Xisnanf(t *TLS, x float32) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return Bool32(math.IsNaN(float64(x)))
|
||||
}
|
||||
|
||||
func Xisnanl(t *TLS, x float64) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return Bool32(math.IsNaN(x))
|
||||
} // ccgo has to handle long double as double as Go does not support long double.
|
||||
|
||||
func Xldexp(t *TLS, x float64, exp int32) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v exp=%v, (%v:)", t, x, exp, origin(2))
|
||||
}
|
||||
return math.Ldexp(x, int(exp))
|
||||
}
|
||||
|
||||
func Xlog(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Log(x)
|
||||
}
|
||||
|
||||
func Xlog10(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Log10(x)
|
||||
func X__builtin_hypot(t *TLS, x float64, y float64) (r float64) {
|
||||
return Xhypot(t, x, y)
|
||||
}
|
||||
|
||||
func X__builtin_log2(t *TLS, x float64) float64 {
|
||||
return Xlog2(t, x)
|
||||
}
|
||||
|
||||
func Xlog2(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Log2(x)
|
||||
}
|
||||
|
||||
func Xround(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Round(x)
|
||||
}
|
||||
|
||||
func X__builtin_round(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
@@ -1202,13 +974,6 @@ func X__builtin_round(t *TLS, x float64) float64 {
|
||||
return math.Round(x)
|
||||
}
|
||||
|
||||
func Xroundf(t *TLS, x float32) float32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return float32(math.Round(float64(x)))
|
||||
}
|
||||
|
||||
func X__builtin_roundf(t *TLS, x float32) float32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
@@ -1216,55 +981,6 @@ func X__builtin_roundf(t *TLS, x float32) float32 {
|
||||
return float32(math.Round(float64(x)))
|
||||
}
|
||||
|
||||
func Xsin(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Sin(x)
|
||||
}
|
||||
|
||||
func Xsinf(t *TLS, x float32) float32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return float32(math.Sin(float64(x)))
|
||||
}
|
||||
|
||||
func Xsinh(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Sinh(x)
|
||||
}
|
||||
|
||||
func Xsqrt(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Sqrt(x)
|
||||
}
|
||||
|
||||
func Xtan(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Tan(x)
|
||||
}
|
||||
|
||||
func Xtanh(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Tanh(x)
|
||||
}
|
||||
|
||||
func Xtrunc(t *TLS, x float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v, (%v:)", t, x, origin(2))
|
||||
}
|
||||
return math.Trunc(x)
|
||||
}
|
||||
|
||||
var nextRand = uint64(1)
|
||||
|
||||
// int rand(void);
|
||||
@@ -1276,35 +992,6 @@ func Xrand(t *TLS) int32 {
|
||||
return int32(uint32(nextRand / (math.MaxUint32 + 1) % math.MaxInt32))
|
||||
}
|
||||
|
||||
func Xpow(t *TLS, x, y float64) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v y=%v, (%v:)", t, y, origin(2))
|
||||
}
|
||||
r := math.Pow(x, y)
|
||||
if x > 0 && r == 1 && y >= -1.0000000000000000715e-18 && y < -1e-30 {
|
||||
r = 0.9999999999999999
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func Xfrexp(t *TLS, x float64, exp uintptr) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v exp=%v, (%v:)", t, x, exp, origin(2))
|
||||
}
|
||||
f, e := math.Frexp(x)
|
||||
*(*int32)(unsafe.Pointer(exp)) = int32(e)
|
||||
return f
|
||||
}
|
||||
|
||||
func Xmodf(t *TLS, x float64, iptr uintptr) float64 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v x=%v iptr=%v, (%v:)", t, x, iptr, origin(2))
|
||||
}
|
||||
i, f := math.Modf(x)
|
||||
*(*float64)(unsafe.Pointer(iptr)) = i
|
||||
return f
|
||||
}
|
||||
|
||||
// char *strncpy(char *dest, const char *src, size_t n)
|
||||
func Xstrncpy(t *TLS, dest, src uintptr, n types.Size_t) (r uintptr) {
|
||||
if __ccgo_strace {
|
||||
@@ -2403,76 +2090,23 @@ func Xffs(tls *TLS, i int32) (r int32) {
|
||||
return int32(mbits.TrailingZeros32(uint32(i))) + 1
|
||||
}
|
||||
|
||||
var _toint5 = Float32FromInt32(1) / Float32FromFloat32(1.1920928955078125e-07)
|
||||
|
||||
func X__builtin_rintf(tls *TLS, x float32) (r float32) {
|
||||
return Xrintf(tls, x)
|
||||
}
|
||||
|
||||
func Xrintf(tls *TLS, x float32) (r float32) {
|
||||
if __ccgo_strace {
|
||||
trc("tls=%v x=%v, (%v:)", tls, x, origin(2))
|
||||
defer func() { trc("-> %v", r) }()
|
||||
}
|
||||
bp := tls.Alloc(16)
|
||||
defer tls.Free(16)
|
||||
var e, s int32
|
||||
var y float32
|
||||
var v1 float32
|
||||
var _ /* u at bp+0 */ struct {
|
||||
Fi [0]uint32
|
||||
Ff float32
|
||||
}
|
||||
_, _, _, _ = e, s, y, v1
|
||||
*(*struct {
|
||||
Fi [0]uint32
|
||||
Ff float32
|
||||
})(unsafe.Pointer(bp)) = struct {
|
||||
Fi [0]uint32
|
||||
Ff float32
|
||||
}{}
|
||||
*(*float32)(unsafe.Pointer(bp)) = x
|
||||
e = int32(*(*uint32)(unsafe.Pointer(bp)) >> int32(23) & uint32(0xff))
|
||||
s = int32(*(*uint32)(unsafe.Pointer(bp)) >> int32(31))
|
||||
if e >= Int32FromInt32(0x7f)+Int32FromInt32(23) {
|
||||
return x
|
||||
}
|
||||
if s != 0 {
|
||||
y = x - _toint5 + _toint5
|
||||
} else {
|
||||
y = x + _toint5 - _toint5
|
||||
}
|
||||
if y == Float32FromInt32(0) {
|
||||
if s != 0 {
|
||||
v1 = -Float32FromFloat32(0)
|
||||
} else {
|
||||
v1 = Float32FromFloat32(0)
|
||||
}
|
||||
return v1
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func X__builtin_lrintf(tls *TLS, x float32) (r long) {
|
||||
return Xlrintf(tls, x)
|
||||
}
|
||||
|
||||
func Xlrintf(tls *TLS, x float32) (r long) {
|
||||
if __ccgo_strace {
|
||||
trc("tls=%v x=%v, (%v:)", tls, x, origin(2))
|
||||
defer func() { trc("-> %v", r) }()
|
||||
}
|
||||
return long(Xrintf(tls, x))
|
||||
}
|
||||
|
||||
func X__builtin_lrint(tls *TLS, x float64) (r long) {
|
||||
return Xlrint(tls, x)
|
||||
}
|
||||
|
||||
func Xlrint(tls *TLS, x float64) (r long) {
|
||||
if __ccgo_strace {
|
||||
trc("tls=%v x=%v, (%v:)", tls, x, origin(2))
|
||||
defer func() { trc("-> %v", r) }()
|
||||
func Xprintf(t *TLS, format, va uintptr) int32 {
|
||||
n, err := os.Stdout.Write(printf(format, va))
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return long(Xrint(tls, x))
|
||||
|
||||
return int32(n)
|
||||
}
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build 386 || arm
|
||||
// +build 386 arm
|
||||
//go:build !windows && (386 || arm)
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ((amd64 || loong64) && !linux) || arm64 || ppc64le || riscv64 || s390x || mips64le
|
||||
//go:build !windows && (((amd64 || arm64 || loong64) && !linux) || ppc64le || riscv64 || s390x || mips64le)
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+2
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !(linux && arm64)
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
import (
|
||||
|
||||
+14
-2
@@ -55,6 +55,10 @@ type (
|
||||
ulong = types.User_ulong_t
|
||||
)
|
||||
|
||||
type pthreadAttr struct {
|
||||
detachState int32
|
||||
}
|
||||
|
||||
// // Keep these outside of the var block otherwise go generate will miss them.
|
||||
var X__stderrp = Xstdout
|
||||
var X__stdinp = Xstdin
|
||||
@@ -452,9 +456,11 @@ func Xsysconf(t *TLS, name int32) long {
|
||||
return long(unix.Getpagesize())
|
||||
case unistd.X_SC_NPROCESSORS_ONLN:
|
||||
return long(runtime.NumCPU())
|
||||
case unistd.X_SC_GETPW_R_SIZE_MAX:
|
||||
return 128
|
||||
}
|
||||
|
||||
panic(todo(""))
|
||||
panic(todo("", name))
|
||||
}
|
||||
|
||||
// int close(int fd);
|
||||
@@ -2158,7 +2164,7 @@ func X__ccgo_pthreadAttrGetDetachState(tls *TLS, a uintptr) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("tls=%v a=%v, (%v:)", tls, a, origin(2))
|
||||
}
|
||||
panic(todo(""))
|
||||
return (*pthreadAttr)(unsafe.Pointer(a)).detachState
|
||||
}
|
||||
|
||||
func Xpthread_attr_getdetachstate(tls *TLS, a uintptr, state uintptr) int32 {
|
||||
@@ -2498,3 +2504,9 @@ func Xsetrlimit(t *TLS, resource int32, rlim uintptr) int32 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func X__fpclassifyd(tls *TLS, x float64) (r int32) {
|
||||
return X__fpclassify(tls, x)
|
||||
}
|
||||
|
||||
var Xin6addr_any = in6_addr{}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// 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))
|
||||
//go:build !(linux && (amd64 || arm64 || loong64))
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
-729
@@ -1,729 +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"
|
||||
gotime "time"
|
||||
"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/stat"
|
||||
"modernc.org/libc/sys/types"
|
||||
"modernc.org/libc/time"
|
||||
)
|
||||
|
||||
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/src/internal/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 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", 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.Fstatat(unix.AT_FDCWD, GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf)), 0); 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 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.Unlinkat(unix.AT_FDCWD, GoString(pathname), 0); 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 := unix.Faccessat(unix.AT_FDCWD, GoString(pathname), uint32(mode), 0); err != nil {
|
||||
if dmesgs {
|
||||
dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
|
||||
}
|
||||
t.setErrno(err)
|
||||
return -1
|
||||
}
|
||||
|
||||
if dmesgs {
|
||||
dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
|
||||
}
|
||||
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 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.Syscall(unix.SYS_FSTAT, uintptr(fd), statbuf, 0); err != 0 {
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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 rmdir(const char *pathname);
|
||||
func Xrmdir(t *TLS, pathname uintptr) int32 {
|
||||
if __ccgo_strace {
|
||||
trc("t=%v pathname=%v, (%v:)", t, pathname, origin(2))
|
||||
}
|
||||
if err := unix.Rmdir(GoString(pathname)); err != nil {
|
||||
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))
|
||||
}
|
||||
if err := unix.Rename(GoString(oldpath), GoString(newpath)); err != nil {
|
||||
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(""))
|
||||
}
|
||||
|
||||
// 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.Chown(GoString(pathname), int(owner), int(group)); err != nil {
|
||||
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(""))
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
if _, _, err := unix.Syscall(unix.SYS_PIPE2, 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(""))
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
n, err := unix.Readlink(GoString(path), GoBytes(buf, int(bufsize)))
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
//TODO- flags |= fcntl.O_LARGEFILE
|
||||
fd, err := unix.Openat(unix.AT_FDCWD, GoString(pathname), flags, 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 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 {
|
||||
t.setErrno(err)
|
||||
return -1
|
||||
}
|
||||
|
||||
if dmesgs {
|
||||
dmesg("%v: %q: ok", origin(1), GoString(path))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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))
|
||||
}
|
||||
if err := unix.Chmod(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
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
n := gotime.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 tv []unix.Timeval
|
||||
if times != 0 {
|
||||
tv = make([]unix.Timeval, 2)
|
||||
*(*[2]unix.Timeval)(unsafe.Pointer(&tv[0])) = *(*[2]unix.Timeval)(unsafe.Pointer(times))
|
||||
}
|
||||
if err := unix.Utimes(GoString(filename), tv); err != nil {
|
||||
t.setErrno(err)
|
||||
return -1
|
||||
}
|
||||
|
||||
if times != 0 {
|
||||
*(*[2]unix.Timeval)(unsafe.Pointer(times)) = *(*[2]unix.Timeval)(unsafe.Pointer(&tv[0]))
|
||||
}
|
||||
if dmesgs {
|
||||
dmesg("%v: %q: ok", origin(1), GoString(filename))
|
||||
}
|
||||
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))
|
||||
}
|
||||
if times == 0 {
|
||||
return Xutimes(t, filename, 0)
|
||||
}
|
||||
|
||||
if err := unix.Utime(GoString(filename), (*unix.Utimbuf)(unsafe.Pointer(times))); err != nil {
|
||||
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(""))
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
if _, _, err := unix.Syscall(unix.SYS_SETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
|
||||
t.setErrno(err)
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
const __NFDBITS = 64
|
||||
|
||||
func X__fdelt_chk(tls *TLS, d int64) (r int64) {
|
||||
if __ccgo_strace {
|
||||
trc("tls=%v d=%v, (%v:)", tls, d, origin(2))
|
||||
defer func() { trc("-> %v", r) }()
|
||||
}
|
||||
|
||||
return d / __NFDBITS
|
||||
}
|
||||
+48
-13
@@ -2,7 +2,7 @@
|
||||
// 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)
|
||||
//go:build linux && (amd64 || arm64 || loong64)
|
||||
|
||||
//go:generate go run generator.go
|
||||
|
||||
@@ -128,11 +128,6 @@ import (
|
||||
"modernc.org/memory"
|
||||
)
|
||||
|
||||
const (
|
||||
heapAlign = 16
|
||||
heapGuard = 16
|
||||
)
|
||||
|
||||
var (
|
||||
_ error = (*MemAuditError)(nil)
|
||||
|
||||
@@ -278,15 +273,18 @@ type TLS struct {
|
||||
allocaStack []int
|
||||
allocas []uintptr
|
||||
jumpBuffers []uintptr
|
||||
pendingSignals chan os.Signal
|
||||
pthread uintptr // *t__pthread
|
||||
pthreadCleanupItems []pthreadCleanupItem
|
||||
pthreadKeyValues map[Tpthread_key_t]uintptr
|
||||
sigHandlers map[int32]uintptr
|
||||
sp int
|
||||
stack []tlsStackSlot
|
||||
|
||||
ID int32
|
||||
|
||||
ownsPthread bool
|
||||
checkSignals bool
|
||||
ownsPthread bool
|
||||
}
|
||||
|
||||
var __ccgo_environOnce sync.Once
|
||||
@@ -311,6 +309,7 @@ func NewTLS() (r *TLS) {
|
||||
ID: id,
|
||||
ownsPthread: true,
|
||||
pthread: pthread,
|
||||
sigHandlers: map[int32]uintptr{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,6 +403,29 @@ func (tls *TLS) Alloc(n0 int) (r uintptr) {
|
||||
func (tls *TLS) Free(n int) {
|
||||
//TODO shrink stacks if possible. Tcl is currently against.
|
||||
tls.sp--
|
||||
if !tls.checkSignals {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case sig := <-tls.pendingSignals:
|
||||
signum := int32(sig.(syscall.Signal))
|
||||
h, ok := tls.sigHandlers[signum]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
switch h {
|
||||
case SIG_DFL:
|
||||
// nop
|
||||
case SIG_IGN:
|
||||
// nop
|
||||
default:
|
||||
(*(*func(*TLS, int32))(unsafe.Pointer(&struct{ uintptr }{h})))(tls, signum)
|
||||
}
|
||||
default:
|
||||
// nop
|
||||
}
|
||||
}
|
||||
|
||||
func (tls *TLS) alloca(n Tsize_t) (r uintptr) {
|
||||
@@ -475,6 +497,10 @@ func Xexit(tls *TLS, code int32) {
|
||||
for _, v := range atExit {
|
||||
v()
|
||||
}
|
||||
atExitHandlersMu.Lock()
|
||||
for _, v := range atExitHandlers {
|
||||
(*(*func(*TLS))(unsafe.Pointer(&struct{ uintptr }{v})))(tls)
|
||||
}
|
||||
os.Exit(int(code))
|
||||
}
|
||||
|
||||
@@ -647,24 +673,33 @@ func Xfork(t *TLS) int32 {
|
||||
const SIG_DFL = 0
|
||||
const SIG_IGN = 1
|
||||
|
||||
var sigHandlers = map[int32]uintptr{}
|
||||
|
||||
func Xsignal(tls *TLS, signum int32, handler uintptr) (r uintptr) {
|
||||
r, sigHandlers[signum] = sigHandlers[signum], handler
|
||||
sigHandlers[signum] = handler
|
||||
r, tls.sigHandlers[signum] = tls.sigHandlers[signum], handler
|
||||
switch handler {
|
||||
case SIG_DFL:
|
||||
gosignal.Reset(syscall.Signal(signum))
|
||||
case SIG_IGN:
|
||||
gosignal.Ignore(syscall.Signal(signum))
|
||||
default:
|
||||
panic(todo(""))
|
||||
if tls.pendingSignals == nil {
|
||||
tls.pendingSignals = make(chan os.Signal, 3)
|
||||
tls.checkSignals = true
|
||||
}
|
||||
gosignal.Notify(tls.pendingSignals, syscall.Signal(signum))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
var (
|
||||
atExitHandlersMu sync.Mutex
|
||||
atExitHandlers []uintptr
|
||||
)
|
||||
|
||||
func Xatexit(tls *TLS, func_ uintptr) (r int32) {
|
||||
return -1
|
||||
atExitHandlersMu.Lock()
|
||||
atExitHandlers = append(atExitHandlers, func_)
|
||||
atExitHandlersMu.Unlock()
|
||||
return 0
|
||||
}
|
||||
|
||||
var __sync_synchronize_dummy int32
|
||||
|
||||
+1
-3
@@ -2,9 +2,7 @@
|
||||
// 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
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
+29
@@ -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
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// 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
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
+1
-3
@@ -2,9 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build unix && !(linux && (amd64 || loong64))
|
||||
// +build unix
|
||||
// +build !linux !amd64,!loong64
|
||||
//go:build unix && !(linux && (amd64 || arm64 || loong64))
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build unix && !illumos && !(linux && (amd64 || loong64)) && !openbsd
|
||||
//go:build unix && !illumos && !(linux && (amd64 || arm64 || loong64)) && !openbsd
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
|
||||
+1423
-7242
File diff suppressed because it is too large
Load Diff
+12165
-697
File diff suppressed because it is too large
Load Diff
+12086
-594
File diff suppressed because it is too large
Load Diff
+12086
-594
File diff suppressed because it is too large
Load Diff
+25
@@ -0,0 +1,25 @@
|
||||
//go:build ignore
|
||||
|
||||
#define _UCRT
|
||||
#define __CRT__NO_INLINE
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#include <float.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <locale.h>
|
||||
#include <malloc.h>
|
||||
|
||||
int __cdecl _mkdir(const char *_Path);
|
||||
|
||||
int __cdecl _fstat64(int _FileDes,struct _stat64 *_Stat);
|
||||
int __cdecl _stat64(const char *_Name,struct _stat64 *_Stat);
|
||||
int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat);
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
// 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 || arm64 || loong64))
|
||||
|
||||
package libc // import "modernc.org/libc"
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func Xsin(t *TLS, x float64) float64 {
|
||||
return math.Sin(x)
|
||||
}
|
||||
|
||||
func Xsinf(t *TLS, x float32) float32 {
|
||||
return float32(math.Sin(float64(x)))
|
||||
}
|
||||
|
||||
func Xsinh(t *TLS, x float64) float64 {
|
||||
return math.Sinh(x)
|
||||
}
|
||||
|
||||
func Xsinhf(t *TLS, x float32) float32 {
|
||||
return float32(math.Sinh(float64(x)))
|
||||
}
|
||||
|
||||
func Xcos(t *TLS, x float64) float64 {
|
||||
return math.Cos(x)
|
||||
}
|
||||
|
||||
func Xcosf(t *TLS, x float32) float32 {
|
||||
return float32(math.Cos(float64(x)))
|
||||
}
|
||||
|
||||
func Xcosh(t *TLS, x float64) float64 {
|
||||
return math.Cosh(x)
|
||||
}
|
||||
|
||||
func Xcoshf(t *TLS, x float32) float32 {
|
||||
return float32(math.Cosh(float64(x)))
|
||||
}
|
||||
|
||||
func Xtan(t *TLS, x float64) float64 {
|
||||
return math.Tan(x)
|
||||
}
|
||||
|
||||
func Xtanf(t *TLS, x float32) float32 {
|
||||
return float32(math.Tan(float64(x)))
|
||||
}
|
||||
|
||||
func Xtanh(t *TLS, x float64) float64 {
|
||||
return math.Tanh(x)
|
||||
}
|
||||
|
||||
func Xtanhf(t *TLS, x float32) float32 {
|
||||
return float32(math.Tanh(float64(x)))
|
||||
}
|
||||
|
||||
func Xasin(t *TLS, x float64) float64 {
|
||||
return math.Asin(x)
|
||||
}
|
||||
|
||||
func Xasinf(t *TLS, x float32) float32 {
|
||||
return float32(math.Asin(float64(x)))
|
||||
}
|
||||
|
||||
func Xasinh(t *TLS, x float64) float64 {
|
||||
return math.Asinh(x)
|
||||
}
|
||||
|
||||
func Xasinhf(t *TLS, x float32) float32 {
|
||||
return float32(math.Asinh(float64(x)))
|
||||
}
|
||||
|
||||
func Xacos(t *TLS, x float64) float64 {
|
||||
return math.Acos(x)
|
||||
}
|
||||
|
||||
func Xacosf(t *TLS, x float32) float32 {
|
||||
return float32(math.Acos(float64(x)))
|
||||
}
|
||||
|
||||
func Xacosh(t *TLS, x float64) float64 {
|
||||
return math.Acosh(x)
|
||||
}
|
||||
|
||||
func Xacoshf(t *TLS, x float32) float32 {
|
||||
return float32(math.Acosh(float64(x)))
|
||||
}
|
||||
|
||||
func Xatan(t *TLS, x float64) float64 {
|
||||
return math.Atan(x)
|
||||
}
|
||||
|
||||
func Xatanf(t *TLS, x float32) float32 {
|
||||
return float32(math.Atan(float64(x)))
|
||||
}
|
||||
|
||||
func Xatan2(t *TLS, x, y float64) float64 {
|
||||
return math.Atan2(x, y)
|
||||
}
|
||||
|
||||
func Xatan2f(t *TLS, x, y float32) float32 {
|
||||
return float32(math.Atan2(float64(x), float64(y)))
|
||||
}
|
||||
|
||||
func Xatanh(t *TLS, x float64) float64 {
|
||||
return math.Atanh(x)
|
||||
}
|
||||
|
||||
func Xatanhf(t *TLS, x float32) float32 {
|
||||
return float32(math.Atanh(float64(x)))
|
||||
}
|
||||
|
||||
func Xexp(t *TLS, x float64) float64 {
|
||||
return math.Exp(x)
|
||||
}
|
||||
|
||||
func Xexpf(t *TLS, x float32) float32 {
|
||||
return float32(math.Exp(float64(x)))
|
||||
}
|
||||
|
||||
func Xfabs(t *TLS, x float64) float64 {
|
||||
return math.Abs(x)
|
||||
}
|
||||
|
||||
func Xfabsf(t *TLS, x float32) float32 {
|
||||
return float32(math.Abs(float64(x)))
|
||||
}
|
||||
|
||||
func Xlog(t *TLS, x float64) float64 {
|
||||
return math.Log(x)
|
||||
}
|
||||
|
||||
func Xlogf(t *TLS, x float32) float32 {
|
||||
return float32(math.Log(float64(x)))
|
||||
}
|
||||
|
||||
func Xlog10(t *TLS, x float64) float64 {
|
||||
return math.Log10(x)
|
||||
}
|
||||
|
||||
func Xlog10f(t *TLS, x float32) float32 {
|
||||
return float32(math.Log10(float64(x)))
|
||||
}
|
||||
|
||||
func Xlog2(t *TLS, x float64) float64 {
|
||||
return math.Log2(x)
|
||||
}
|
||||
|
||||
func Xlog2f(t *TLS, x float32) float32 {
|
||||
return float32(math.Log2(float64(x)))
|
||||
}
|
||||
|
||||
func Xpow(t *TLS, x, y float64) float64 {
|
||||
r := math.Pow(x, y)
|
||||
if x > 0 && r == 1 && y >= -1.0000000000000000715e-18 && y < -1e-30 {
|
||||
r = 0.9999999999999999
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func Xpowf(t *TLS, x, y float32) float32 {
|
||||
return float32(math.Pow(float64(x), float64(y)))
|
||||
}
|
||||
|
||||
func Xsqrt(t *TLS, x float64) float64 {
|
||||
return math.Sqrt(x)
|
||||
}
|
||||
|
||||
func Xsqrtf(t *TLS, x float32) float32 {
|
||||
return float32(math.Sqrt(float64(x)))
|
||||
}
|
||||
|
||||
func Xround(t *TLS, x float64) float64 {
|
||||
return math.Round(x)
|
||||
}
|
||||
|
||||
func Xroundf(t *TLS, x float32) float32 {
|
||||
return float32(math.Round(float64(x)))
|
||||
}
|
||||
|
||||
func Xceil(t *TLS, x float64) float64 {
|
||||
return math.Ceil(x)
|
||||
}
|
||||
|
||||
func Xceilf(t *TLS, x float32) float32 {
|
||||
return float32(math.Ceil(float64(x)))
|
||||
}
|
||||
|
||||
func Xfloor(t *TLS, x float64) float64 {
|
||||
return math.Floor(x)
|
||||
}
|
||||
|
||||
func Xfloorf(t *TLS, x float32) float32 {
|
||||
return float32(math.Floor(float64(x)))
|
||||
}
|
||||
|
||||
func Xcopysign(t *TLS, x, y float64) float64 {
|
||||
return math.Copysign(x, y)
|
||||
}
|
||||
|
||||
func Xcopysignf(t *TLS, x, y float32) float32 {
|
||||
return float32(math.Copysign(float64(x), float64(y)))
|
||||
}
|
||||
|
||||
func Xfmod(t *TLS, x, y float64) float64 {
|
||||
return math.Mod(x, y)
|
||||
}
|
||||
|
||||
func Xfmodf(t *TLS, x, y float32) float32 {
|
||||
return float32(math.Mod(float64(x), float64(y)))
|
||||
}
|
||||
|
||||
func Xhypot(t *TLS, x, y float64) float64 {
|
||||
return math.Hypot(x, y)
|
||||
}
|
||||
|
||||
func Xhypotf(t *TLS, x, y float32) float32 {
|
||||
return float32(math.Hypot(float64(x), float64(y)))
|
||||
}
|
||||
|
||||
func Xisnan(t *TLS, x float64) int32 {
|
||||
return Bool32(math.IsNaN(x))
|
||||
}
|
||||
|
||||
func Xisnanf(t *TLS, x float32) int32 {
|
||||
return Bool32(math.IsNaN(float64(x)))
|
||||
}
|
||||
|
||||
func Xisnanl(t *TLS, x float64) int32 {
|
||||
return Bool32(math.IsNaN(x))
|
||||
}
|
||||
|
||||
func Xldexp(t *TLS, x float64, exp int32) float64 {
|
||||
return math.Ldexp(x, int(exp))
|
||||
}
|
||||
|
||||
func Xtrunc(t *TLS, x float64) float64 {
|
||||
return math.Trunc(x)
|
||||
}
|
||||
|
||||
func Xtruncf(t *TLS, x float32) float32 {
|
||||
return float32(math.Trunc(float64(x)))
|
||||
}
|
||||
|
||||
func Xfrexp(t *TLS, x float64, exp uintptr) float64 {
|
||||
f, e := math.Frexp(x)
|
||||
*(*int32)(unsafe.Pointer(exp)) = int32(e)
|
||||
return f
|
||||
}
|
||||
|
||||
func Xfrexpf(t *TLS, x float32, exp uintptr) float32 {
|
||||
f, e := math.Frexp(float64(x))
|
||||
*(*int32)(unsafe.Pointer(exp)) = int32(e)
|
||||
return float32(f)
|
||||
}
|
||||
|
||||
func Xmodf(t *TLS, x float64, iptr uintptr) float64 {
|
||||
i, f := math.Modf(x)
|
||||
*(*float64)(unsafe.Pointer(iptr)) = i
|
||||
return f
|
||||
}
|
||||
|
||||
func Xmodff(t *TLS, x float32, iptr uintptr) float32 {
|
||||
i, f := math.Modf(float64(x))
|
||||
*(*float32)(unsafe.Pointer(iptr)) = float32(i)
|
||||
return float32(f)
|
||||
}
|
||||
|
||||
var _toint5 = Float32FromInt32(1) / Float32FromFloat32(1.1920928955078125e-07)
|
||||
|
||||
func Xrintf(tls *TLS, x float32) (r float32) {
|
||||
bp := tls.Alloc(16)
|
||||
defer tls.Free(16)
|
||||
var e, s int32
|
||||
var y float32
|
||||
var v1 float32
|
||||
var _ /* u at bp+0 */ struct {
|
||||
Fi [0]uint32
|
||||
Ff float32
|
||||
}
|
||||
_, _, _, _ = e, s, y, v1
|
||||
*(*struct {
|
||||
Fi [0]uint32
|
||||
Ff float32
|
||||
})(unsafe.Pointer(bp)) = struct {
|
||||
Fi [0]uint32
|
||||
Ff float32
|
||||
}{}
|
||||
*(*float32)(unsafe.Pointer(bp)) = x
|
||||
e = int32(*(*uint32)(unsafe.Pointer(bp)) >> int32(23) & uint32(0xff))
|
||||
s = int32(*(*uint32)(unsafe.Pointer(bp)) >> int32(31))
|
||||
if e >= Int32FromInt32(0x7f)+Int32FromInt32(23) {
|
||||
return x
|
||||
}
|
||||
if s != 0 {
|
||||
y = x - _toint5 + _toint5
|
||||
} else {
|
||||
y = x + _toint5 - _toint5
|
||||
}
|
||||
if y == Float32FromInt32(0) {
|
||||
if s != 0 {
|
||||
v1 = -Float32FromFloat32(0)
|
||||
} else {
|
||||
v1 = Float32FromFloat32(0)
|
||||
}
|
||||
return v1
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func Xlrintf(tls *TLS, x float32) (r long) {
|
||||
return long(Xrintf(tls, x))
|
||||
}
|
||||
|
||||
func Xlrint(tls *TLS, x float64) (r long) {
|
||||
return long(Xrint(tls, x))
|
||||
}
|
||||
|
||||
func Xrint(tls *TLS, x float64) float64 {
|
||||
switch {
|
||||
case x == 0: // also +0 and -0
|
||||
return 0
|
||||
case math.IsInf(x, 0), math.IsNaN(x):
|
||||
return x
|
||||
case x >= math.MinInt64 && x <= math.MaxInt64 && float64(int64(x)) == x:
|
||||
return x
|
||||
case x >= 0:
|
||||
return math.Floor(x + 0.5)
|
||||
default:
|
||||
return math.Ceil(x - 0.5)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user