Compare commits
75 Commits
d093db1a2b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72c9d79dd2 | ||
|
|
96703721e3 | ||
|
|
7ac5c15ff8 | ||
|
|
d743b6dbd0 | ||
|
|
ca365ad39c | ||
|
|
86b8e62862 | ||
|
|
7262f5f69b | ||
|
|
b2954c0461 | ||
|
|
03b9a6d1f1 | ||
|
|
fa7bafa241 | ||
|
|
502e47d0bc | ||
|
|
0eb0abf4a8 | ||
|
|
49b7bd2f85 | ||
|
|
045ab30dfa | ||
|
|
b1cf639f39 | ||
|
|
cc546d9b2d | ||
|
|
0066a267a6 | ||
|
|
f58053ebe9 | ||
|
|
b30b1811ea | ||
|
|
3fb1ee4ea3 | ||
|
|
7a790fa31e | ||
|
|
774de58bf7 | ||
|
|
6aa549cb02 | ||
|
|
fe7c3a9682 | ||
|
|
36dcf70dbe | ||
|
|
989bc3c2ff | ||
|
|
f22d7d958b | ||
|
|
6a4e10ee2b | ||
|
|
09da985455 | ||
|
|
f52832ee82 | ||
|
|
0cafba0571 | ||
|
|
1a397dbf45 | ||
|
|
b10283d752 | ||
|
|
284613b5bc | ||
|
|
929d15c5b7 | ||
|
|
5e61378d63 | ||
|
|
c948a32458 | ||
|
|
35e2e40ce6 | ||
|
|
847cd736b6 | ||
|
|
9cf8cb0736 | ||
|
|
4997264f4c | ||
|
|
f69a850bd8 | ||
|
|
5a3d5e5610 | ||
|
|
c38e8529af | ||
|
|
7a946b7604 | ||
|
|
e0fa44eef7 | ||
|
|
6440b07d14 | ||
|
|
bae33f8c60 | ||
|
|
daa446cc02 | ||
|
|
daac3907f4 | ||
|
|
83305227db | ||
|
|
f5d82fc6aa | ||
|
|
e581b7835c | ||
|
|
19f4b614d3 | ||
|
|
58462fb5a4 | ||
|
|
2f8dba4e23 | ||
|
|
0d91cd63db | ||
|
|
9681050a46 | ||
|
|
0b4d78796e | ||
|
|
1805a087e0 | ||
|
|
fabd26e8e9 | ||
|
|
9646356d7f | ||
|
|
84bbda1031 | ||
|
|
9b4accafe3 | ||
|
|
9352ca82de | ||
|
|
058874b566 | ||
|
|
8ade122378 | ||
|
|
fe98fa67f3 | ||
|
|
5cc9b141b9 | ||
|
|
266af7353a | ||
|
|
dd20f066a3 | ||
|
|
697fc16b52 | ||
|
|
8621619433 | ||
|
|
768ce8e92e | ||
|
|
757afa603e |
@@ -6,6 +6,8 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'cmd/**'
|
- 'cmd/**'
|
||||||
- 'src/**'
|
- 'src/**'
|
||||||
|
- 'build/**'
|
||||||
|
- '.gitea/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.21.3-alpine3.18 as builder
|
FROM golang:1.23.9-alpine3.21 as builder
|
||||||
|
|
||||||
COPY ./ /go/src/ana-ledger
|
COPY ./ /go/src/ana-ledger
|
||||||
WORKDIR /go/src/ana-ledger
|
WORKDIR /go/src/ana-ledger
|
||||||
|
|||||||
1
cmd/cli/bpi.dat
Symbolic link
1
cmd/cli/bpi.dat
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../../../../../Sync/Core/ledger/bpi.dat
|
||||||
@@ -3,13 +3,20 @@ package cli
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Files FileList
|
Files FileList
|
||||||
BPI string
|
BPI string
|
||||||
|
CPI string
|
||||||
|
CPIYear int
|
||||||
Query struct {
|
Query struct {
|
||||||
Period Period
|
Period Period
|
||||||
Sort string
|
Sort string
|
||||||
NoRounding bool
|
NoRounding bool
|
||||||
Depth int
|
Depth int
|
||||||
Reverse bool
|
With string
|
||||||
NoExchanging bool
|
NoExchanging bool
|
||||||
Normalize bool
|
Normalize bool
|
||||||
|
USDOnly bool
|
||||||
}
|
}
|
||||||
|
Compact bool
|
||||||
|
GroupDate string
|
||||||
|
NoPercent bool
|
||||||
|
CSV string
|
||||||
}
|
}
|
||||||
|
|||||||
1
cmd/cli/cpi.dat
Symbolic link
1
cmd/cli/cpi.dat
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../../../../../Sync/Core/ledger/cpi.dat
|
||||||
@@ -3,6 +3,8 @@ package cli
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -49,20 +51,96 @@ func (period *Period) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (period *Period) Set(s string) error {
|
func (period *Period) Set(s string) error {
|
||||||
if result, err := time.Parse("2006", s); err == nil {
|
ss := strings.Split(s, "..")
|
||||||
period.Start = result
|
if err := period.setStartStop(ss[0]); err != nil {
|
||||||
period.Stop = result.AddDate(1, 0, 0).Add(-1 * time.Minute)
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ss) != 2 {
|
||||||
|
} else if err := period.setStop(ss[1]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (period *Period) setStartStop(s string) error {
|
||||||
|
stop, err := period.setT(time.Now(), s, &period.Start)
|
||||||
|
period.Stop = stop
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (period *Period) setStop(s string) error {
|
||||||
|
_, err := period.setT(time.Now(), s, &period.Stop)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Period) setT(now time.Time, s string, t *time.Time) (time.Time, error) {
|
||||||
|
if s == "" {
|
||||||
|
*t = time.Unix(0, 0)
|
||||||
|
return time.Now().AddDate(100, 0, 0), nil
|
||||||
|
}
|
||||||
|
if submatches := regexp.MustCompile(`[+-]?(?P<years>[0-9]+y)?(?P<months>[0-9]+mo)?(?P<weeks>[0-9]+w)?(?P<days>[0-9]+d)?([0-9]+[a-z])?`).FindStringSubmatch(s); len(submatches) > 0 {
|
||||||
|
s2 := s
|
||||||
|
result := now
|
||||||
|
scalar := time.Duration(1)
|
||||||
|
if strings.HasPrefix(s2, "-") {
|
||||||
|
scalar = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, submatch := range submatches[1 : len(submatches)-1] {
|
||||||
|
if len(submatch) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
unit := submatch[len(submatch)-1]
|
||||||
|
if submatch[len(submatch)-1] == 'o' { // mo
|
||||||
|
submatch = submatch[:len(submatch)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := strconv.Atoi(submatch[:len(submatch)-1])
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
switch unit {
|
||||||
|
case 'y':
|
||||||
|
result = result.AddDate(int(scalar*1), 0, 0)
|
||||||
|
case 'o':
|
||||||
|
result = result.AddDate(0, int(scalar*1), 0)
|
||||||
|
case 'w':
|
||||||
|
result = result.AddDate(0, 0, int(scalar*7))
|
||||||
|
case 'd':
|
||||||
|
result = result.AddDate(0, 0, int(scalar*1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s2 = strings.ReplaceAll(s2, submatches[i+1], "")
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdDuration := strings.TrimLeft(s2, "+-"); stdDuration != "" {
|
||||||
|
if d, err := time.ParseDuration(stdDuration); err == nil {
|
||||||
|
result = result.Add(scalar * d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if result != now {
|
||||||
|
*t = result
|
||||||
|
return result.AddDate(100, 0, 0), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if result, err := time.Parse("2006", s); err == nil {
|
||||||
|
*t = result
|
||||||
|
return result.AddDate(1, 0, 0).Add(-1 * time.Minute), nil
|
||||||
|
}
|
||||||
if result, err := time.Parse("2006-01", s); err == nil {
|
if result, err := time.Parse("2006-01", s); err == nil {
|
||||||
period.Start = result
|
*t = result
|
||||||
period.Stop = result.AddDate(0, 1, 0).Add(-1 * time.Minute)
|
return result.AddDate(0, 1, 0).Add(-1 * time.Minute), nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
if result, err := time.Parse("2006-01-02", s); err == nil {
|
if result, err := time.Parse("2006-01-02", s); err == nil {
|
||||||
period.Start = result
|
*t = result
|
||||||
period.Stop = result.AddDate(0, 0, 1).Add(-1 * time.Minute)
|
return result.AddDate(0, 0, 1).Add(-1 * time.Minute), nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unimplemented format: %s", s)
|
return time.Time{}, fmt.Errorf("unimplemented format: %s", s)
|
||||||
}
|
}
|
||||||
|
|||||||
41
cmd/cli/flag_test.go
Normal file
41
cmd/cli/flag_test.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPeriodSetT(t *testing.T) {
|
||||||
|
now := time.Date(2010, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
cases := map[string]time.Time{
|
||||||
|
"2001-02-03": time.Date(2001, 2, 3, 0, 0, 0, 0, time.UTC),
|
||||||
|
"2001-02": time.Date(2001, 2, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
"2001": time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
"": time.Unix(0, 0),
|
||||||
|
"1m": now.Add(1 * time.Minute),
|
||||||
|
"+1m": now.Add(1 * time.Minute),
|
||||||
|
"-1m": now.Add(-1 * time.Minute),
|
||||||
|
"1h1m": now.Add(1*time.Hour + 1*time.Minute),
|
||||||
|
"1d": now.Add(24 * time.Hour),
|
||||||
|
"+1d": now.Add(24 * time.Hour),
|
||||||
|
"-1d": now.Add(-24 * time.Hour),
|
||||||
|
"1d1m": now.Add(24*time.Hour + 1*time.Minute),
|
||||||
|
"+1d1m": now.Add(24*time.Hour + 1*time.Minute),
|
||||||
|
"-1d1m": now.Add(-1*24*time.Hour + -1*1*time.Minute),
|
||||||
|
"1y1mo1w1d1h": now.AddDate(1, 1, 7+1).Add(1 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
for input, expect := range cases {
|
||||||
|
input, expect := input, expect
|
||||||
|
t.Run(input, func(t *testing.T) {
|
||||||
|
p := &Period{}
|
||||||
|
var got time.Time
|
||||||
|
if _, err := p.setT(now, input, &got); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got.Unix() != expect.Unix() {
|
||||||
|
t.Errorf("expected %s but got %s", expect.String(), got.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
549
cmd/cli/main.go
549
cmd/cli/main.go
@@ -1,15 +1,31 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"encoding/csv"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
|
"maps"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gogs.inhome.blapointe.com/ana-ledger/src/ana"
|
"gogs.inhome.blapointe.com/ana-ledger/src/ana"
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank"
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank/cache"
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank/teller"
|
||||||
"gogs.inhome.blapointe.com/ana-ledger/src/ledger"
|
"gogs.inhome.blapointe.com/ana-ledger/src/ledger"
|
||||||
|
|
||||||
|
"github.com/guptarohit/asciigraph"
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Main() {
|
func Main() {
|
||||||
@@ -17,41 +33,48 @@ func Main() {
|
|||||||
|
|
||||||
fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||||
fs.Var(&config.Files, "f", "paths to files")
|
fs.Var(&config.Files, "f", "paths to files")
|
||||||
fs.Var(&config.Query.Period, "period", "period")
|
fs.Var(&config.Query.Period, "period", "period can be YYYY, YYYY-mm, YYYY-mm-dd, x..y")
|
||||||
fs.StringVar(&config.Query.Sort, "S", "", "sort ie date")
|
fs.StringVar(&config.Query.Sort, "S", "", "sort ie date")
|
||||||
fs.BoolVar(&config.Query.NoRounding, "no-rounding", false, "no rounding")
|
fs.BoolVar(&config.Query.NoRounding, "no-rounding", false, "no rounding")
|
||||||
|
fs.BoolVar(&config.Compact, "c", false, "reg entries oneline")
|
||||||
|
fs.StringVar(&config.Query.With, "w", "", "regexp for transactions")
|
||||||
|
fs.StringVar(&config.CSV, "csv", "", "if csv then the csv")
|
||||||
fs.IntVar(&config.Query.Depth, "depth", 0, "depth grouping")
|
fs.IntVar(&config.Query.Depth, "depth", 0, "depth grouping")
|
||||||
fs.BoolVar(&config.Query.Reverse, "r", false, "reverse printed accounts")
|
|
||||||
fs.BoolVar(&config.Query.Normalize, "n", false, "normalize with default normalizer")
|
fs.BoolVar(&config.Query.Normalize, "n", false, "normalize with default normalizer")
|
||||||
|
fs.BoolVar(&config.Query.USDOnly, "usd", false, "filter to usd")
|
||||||
fs.BoolVar(&config.Query.NoExchanging, "no-exchanging", true, "omit currency exchanges")
|
fs.BoolVar(&config.Query.NoExchanging, "no-exchanging", true, "omit currency exchanges")
|
||||||
fs.StringVar(&config.BPI, "bpi", "", "path to bpi")
|
fs.StringVar(&config.BPI, "bpi", "", "path to bpi")
|
||||||
|
fs.StringVar(&config.CPI, "cpi", "", "path to cpi")
|
||||||
|
fs.StringVar(&config.GroupDate, "group-date", "^....-..-..", "date grouping")
|
||||||
|
fs.IntVar(&config.CPIYear, "cpiy", 0, "use cpi to convert usd to this year's value")
|
||||||
|
fs.BoolVar(&config.NoPercent, "no-percent", false, "compute percent")
|
||||||
if err := fs.Parse(os.Args[1:]); err != nil {
|
if err := fs.Parse(os.Args[1:]); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
files := config.Files.Strings()
|
files := config.Files.Strings()
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
panic("must specify at least one file")
|
log.Fatalf("must specify at least one file")
|
||||||
}
|
}
|
||||||
ledgerFiles, err := ledger.NewFiles(files[0], files[1:]...)
|
ledgerFiles, err := ledger.NewFiles(files[0], files[1:]...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
positional := fs.Args()
|
positional := fs.Args()
|
||||||
if len(positional) == 0 || len(positional[0]) < 3 {
|
if len(positional) == 0 || len(positional[0]) < 3 {
|
||||||
panic("positional arguments required, ie bal|reg PATTERN MATCHING")
|
log.Fatalf("positional arguments required, ie bal|reg PATTERN MATCHING")
|
||||||
}
|
}
|
||||||
cmd := positional[0]
|
cmd := positional[0]
|
||||||
|
|
||||||
q, err := BuildQuery(positional[1:])
|
q, err := BuildQuery(config, positional[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
deltas, err := ledgerFiles.Deltas()
|
deltas, err := ledgerFiles.Deltas()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if period := config.Query.Period; !period.Empty() {
|
if period := config.Query.Period; !period.Empty() {
|
||||||
@@ -65,11 +88,13 @@ func Main() {
|
|||||||
|
|
||||||
pattern := ".*"
|
pattern := ".*"
|
||||||
if depth := config.Query.Depth; depth > 0 {
|
if depth := config.Query.Depth; depth > 0 {
|
||||||
|
patterns := []string{}
|
||||||
pattern = ""
|
pattern = ""
|
||||||
for i := 0; i < depth; i++ {
|
for i := 0; i < depth; i++ {
|
||||||
pattern += "[^:]*:"
|
pattern += "[^:]*:"
|
||||||
|
patterns = append([]string{strings.Trim(pattern, ":")}, patterns...)
|
||||||
}
|
}
|
||||||
pattern = strings.Trim(pattern, ":")
|
pattern = strings.Join(patterns, "|")
|
||||||
}
|
}
|
||||||
group := ledger.GroupName(pattern)
|
group := ledger.GroupName(pattern)
|
||||||
|
|
||||||
@@ -77,27 +102,235 @@ func Main() {
|
|||||||
if config.BPI != "" {
|
if config.BPI != "" {
|
||||||
b, err := ledger.NewBPIs(config.BPI)
|
b, err := ledger.NewBPIs(config.BPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
bpis = b
|
bpis = b
|
||||||
|
if period := config.Query.Period; !period.Empty() {
|
||||||
|
before := period.Stop.Format("2006-01-02")
|
||||||
|
for _, timeToValue := range bpis {
|
||||||
|
maps.DeleteFunc(timeToValue, func(k string, _ float64) bool {
|
||||||
|
return k > before
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cpiNormalizer := ana.NewNormalizer()
|
||||||
|
if config.CPI != "" && config.CPIYear > 0 {
|
||||||
|
c, err := ledger.NewBPIs(config.CPI)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
cpi := c["CPI"]
|
||||||
|
cpiy := cpi.Lookup(fmt.Sprintf("%d-06-01", config.CPIYear))
|
||||||
|
if cpiy == nil {
|
||||||
|
log.Fatalf("no cpi for year %d", config.CPIYear)
|
||||||
|
}
|
||||||
|
|
||||||
|
for date, value := range cpi {
|
||||||
|
cpiNormalizer = cpiNormalizer.With(".*", date, value/(*cpiy))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Query.Normalize {
|
if config.Query.Normalize {
|
||||||
deltas = ana.NewDefaultNormalizer().Normalize(deltas)
|
deltas = ana.NewDefaultNormalizer().Normalize(deltas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Query.With != "" {
|
||||||
|
deltas = deltas.Like(ledger.LikeWith(config.Query.With))
|
||||||
|
}
|
||||||
|
|
||||||
|
w := bufio.NewWriter(os.Stdout)
|
||||||
|
defer w.Flush()
|
||||||
|
|
||||||
|
maxAccW := 0
|
||||||
|
for _, delta := range deltas.Like(q).Group(group) {
|
||||||
|
if accW := len(delta.Name); accW > maxAccW {
|
||||||
|
maxAccW = accW
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch cmd[:3] {
|
switch cmd[:3] {
|
||||||
case "bal":
|
case "bal": // balances
|
||||||
balances := deltas.Balances().
|
balances := deltas.Group(ledger.GroupDate(config.GroupDate)).Balances().
|
||||||
WithBPIs(bpis).
|
WithBPIs(bpis).
|
||||||
KindaLike(q).
|
KindaLike(q).
|
||||||
KindaGroup(group)
|
KindaGroup(group).
|
||||||
FPrintBalances(os.Stdout, "", balances, nil)
|
Nonzero().
|
||||||
case "reg":
|
Normalize(cpiNormalizer, "9")
|
||||||
transactions := deltas.Transactions()
|
|
||||||
|
|
||||||
|
cumulatives := make(ledger.Balances)
|
||||||
|
cumulativesFormat := "%s%.2f"
|
||||||
|
if !config.NoPercent {
|
||||||
|
var sum float64
|
||||||
|
for key := range balances {
|
||||||
|
if _, ok := cumulatives[key]; !ok {
|
||||||
|
cumulatives[key] = make(ledger.Balance)
|
||||||
|
}
|
||||||
|
for currency, val := range balances[key] {
|
||||||
|
if currency == ledger.USD {
|
||||||
|
cumulatives[key][currency] = val
|
||||||
|
sum += val
|
||||||
|
} else {
|
||||||
|
cumulatives[key][currency] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for key := range cumulatives {
|
||||||
|
cumulatives[key][ledger.USD] = 100 * cumulatives[key][ledger.USD] / sum
|
||||||
|
}
|
||||||
|
cumulativesFormat = "%.0f%%"
|
||||||
|
}
|
||||||
|
|
||||||
|
FPrintBalances(w, "", balances, cumulatives, config.Query.USDOnly, config.Query.Normalize, time.Now().Format("2006-01-02"), false, maxAccW, cumulativesFormat)
|
||||||
|
case "gra": // graph
|
||||||
|
dateGrouping := "^[0-9]{4}-[0-9]{2}"
|
||||||
|
if period := config.Query.Period; !period.Empty() {
|
||||||
|
day := time.Hour * 24
|
||||||
|
year := day * 365
|
||||||
|
r := period.Stop.Sub(period.Start)
|
||||||
|
if r > 10*year {
|
||||||
|
dateGrouping = "^[0-9]{4}"
|
||||||
|
} else if r > 5*year {
|
||||||
|
} else if r > year {
|
||||||
|
dateGrouping = "^[0-9]{4}-[0-9]{2}-[0-9]"
|
||||||
|
} else {
|
||||||
|
dateGrouping = "^[0-9]{4}-[0-9]{2}-[0-9]{2}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deltas = deltas.Group(ledger.GroupDate(dateGrouping))
|
||||||
|
|
||||||
|
transactions := deltas.Transactions()
|
||||||
|
cumulative := make(ledger.Balances)
|
||||||
|
data := map[string][]float64{}
|
||||||
|
pushData := func() {
|
||||||
|
soFar := 0
|
||||||
|
for _, v := range data {
|
||||||
|
soFar = len(v)
|
||||||
|
}
|
||||||
|
for k, balance := range cumulative {
|
||||||
|
for curr, v := range balance {
|
||||||
|
if curr != ledger.USD {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := data[k]; !ok {
|
||||||
|
data[k] = make([]float64, soFar)
|
||||||
|
}
|
||||||
|
data[k] = append(data[k], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for i, transaction := range transactions {
|
for i, transaction := range transactions {
|
||||||
balances := ledger.Deltas(transaction).Like(q).Group(group).Balances().WithBPIs(bpis)
|
if i > 0 && transactions[i-1][0].Date != transaction[0].Date {
|
||||||
|
pushData()
|
||||||
|
}
|
||||||
|
balances := ledger.Deltas(transaction).
|
||||||
|
Like(q).
|
||||||
|
Group(group).
|
||||||
|
Balances().
|
||||||
|
WithBPIsAt(bpis, transaction[0].Date).
|
||||||
|
Nonzero().
|
||||||
|
Normalize(cpiNormalizer, transaction[0].Date)
|
||||||
|
cumulative.PushAll(balances)
|
||||||
|
}
|
||||||
|
pushData()
|
||||||
|
|
||||||
|
labels := []string{}
|
||||||
|
for k := range data {
|
||||||
|
labels = append(labels, k)
|
||||||
|
}
|
||||||
|
slices.Sort(labels)
|
||||||
|
|
||||||
|
points := [][]float64{}
|
||||||
|
for _, k := range labels {
|
||||||
|
points = append(points, data[k])
|
||||||
|
}
|
||||||
|
for i := range points {
|
||||||
|
for j := range points[i] {
|
||||||
|
points[i][j] /= 1000.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options := []asciigraph.Option{asciigraph.Precision(0)}
|
||||||
|
if _, h, err := terminal.GetSize(0); err == nil && h > 4 {
|
||||||
|
options = append(options, asciigraph.Height(h-4))
|
||||||
|
}
|
||||||
|
if len(labels) < 256 {
|
||||||
|
seriesColors := make([]asciigraph.AnsiColor, len(labels))
|
||||||
|
for i := range seriesColors {
|
||||||
|
seriesColors[i] = asciigraph.AnsiColor(i)
|
||||||
|
}
|
||||||
|
options = append(options, asciigraph.SeriesLegends(labels...))
|
||||||
|
options = append(options, asciigraph.SeriesColors(seriesColors...))
|
||||||
|
}
|
||||||
|
fmt.Println(asciigraph.PlotMany(points, options...))
|
||||||
|
case "rec": // reconcile via teller // DEAD
|
||||||
|
log.Fatalf("dead and bad")
|
||||||
|
byDate := map[string]ledger.Deltas{}
|
||||||
|
for _, delta := range deltas {
|
||||||
|
delta := delta
|
||||||
|
byDate[delta.Date] = append(byDate[delta.Date], delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, can := signal.NotifyContext(context.Background(), syscall.SIGINT)
|
||||||
|
defer can()
|
||||||
|
|
||||||
|
teller, err := teller.New()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
client := cache.New(teller)
|
||||||
|
|
||||||
|
accounts, err := client.Accounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
inDay := func(date string, transaction bank.Transaction) bool {
|
||||||
|
return slices.ContainsFunc(byDate[date], func(d ledger.Delta) bool {
|
||||||
|
v := fmt.Sprintf("%.2f", d.Value)
|
||||||
|
nv := fmt.Sprintf("%.2f", -1.0*d.Value)
|
||||||
|
a := fmt.Sprintf("%.2f", transaction.Amount)
|
||||||
|
return v == a || nv == a
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, acc := range accounts {
|
||||||
|
transactions, err := client.Transactions(ctx, acc)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, transaction := range transactions {
|
||||||
|
if inDay(transaction.Date, transaction) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := "missing"
|
||||||
|
|
||||||
|
ts, err := time.ParseInLocation("2006-01-02", transaction.Date, time.Local)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
dayBefore := ts.Add(-24 * time.Hour).Format("2006-01-02")
|
||||||
|
dayAfter := ts.Add(24 * time.Hour).Format("2006-01-02")
|
||||||
|
if inDay(dayBefore, transaction) || inDay(dayAfter, transaction) {
|
||||||
|
msg = "1dayoff"
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := " "
|
||||||
|
if transaction.Status != "posted" {
|
||||||
|
prefix = "! "
|
||||||
|
}
|
||||||
|
fmt.Printf("[%s] %s $%7.2f %s%s (%s)\n", msg, transaction.Date, transaction.Amount, prefix, transaction.Details.CounterParty.Name, transaction.Description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "reg": // reg
|
||||||
|
deltas = deltas.Group(ledger.GroupDate(config.GroupDate))
|
||||||
|
transactions := deltas.Transactions()
|
||||||
|
cumulative := make(ledger.Balances)
|
||||||
|
for _, transaction := range transactions {
|
||||||
|
balances := ledger.Deltas(transaction).Like(q).Group(group).Balances().WithBPIsAt(bpis, transaction[0].Date).Nonzero().Normalize(cpiNormalizer, transaction[0].Date)
|
||||||
shouldPrint := false
|
shouldPrint := false
|
||||||
shouldPrint = shouldPrint || len(balances) > 2
|
shouldPrint = shouldPrint || len(balances) > 2
|
||||||
if config.Query.NoExchanging {
|
if config.Query.NoExchanging {
|
||||||
@@ -109,31 +342,251 @@ func Main() {
|
|||||||
shouldPrint = shouldPrint || len(balances) > 0
|
shouldPrint = shouldPrint || len(balances) > 0
|
||||||
}
|
}
|
||||||
if shouldPrint {
|
if shouldPrint {
|
||||||
fmt.Printf("%s\t%s\n", transaction[0].Date, transaction[0].Description)
|
cumulative.PushAll(balances)
|
||||||
FPrintBalances(os.Stdout, "\t\t", balances, transactions[:i+1].Deltas().Like(q).Group(group).Balances())
|
cumulative = cumulative.Nonzero()
|
||||||
|
FPrintBalancesFor(transaction[0].Description, w, "\t\t", balances, cumulative, config.Query.USDOnly, config.Query.Normalize, transaction[0].Date, config.Compact, maxAccW, "%s%.2f")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "csv": // reconcile with given csv
|
||||||
|
deltas := deltas.Group(group)
|
||||||
|
|
||||||
|
if config.CSV == "" {
|
||||||
|
log.Fatalf("missing required -csv")
|
||||||
|
}
|
||||||
|
f, err := os.Open(config.CSV)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("cannot open csv %q: %v", config.CSV, err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
reader := csv.NewReader(f)
|
||||||
|
fields, err := reader.Read()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dateIdxs := []int{}
|
||||||
|
for i := range fields {
|
||||||
|
if strings.Contains(strings.ToLower(fields[i]), "date") {
|
||||||
|
dateIdxs = append(dateIdxs, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
descIdx := slices.IndexFunc(fields, func(field string) bool {
|
||||||
|
return strings.Contains(strings.ToLower(field), "desc")
|
||||||
|
})
|
||||||
|
|
||||||
|
amountIdx := slices.IndexFunc(fields, func(field string) bool {
|
||||||
|
return strings.Contains(strings.ToLower(field), "amount")
|
||||||
|
})
|
||||||
|
|
||||||
|
csvDeltas := make(ledger.Deltas, 0)
|
||||||
|
for {
|
||||||
|
line, err := reader.Read()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to read csv line: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dates := []string{}
|
||||||
|
for _, dateIdx := range dateIdxs {
|
||||||
|
dates = append(dates, normalizeDate(line[dateIdx]))
|
||||||
|
}
|
||||||
|
dates = slices.Compact(dates)
|
||||||
|
desc := line[descIdx]
|
||||||
|
amount := line[amountIdx]
|
||||||
|
|
||||||
|
amountF, err := strconv.ParseFloat(amount, 32)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("non-float amount %q: %v", amount, err)
|
||||||
|
}
|
||||||
|
csvDeltas = append(csvDeltas, ledger.Delta{
|
||||||
|
Date: dates[0],
|
||||||
|
OtherDates: dates[1:],
|
||||||
|
Name: desc,
|
||||||
|
Value: amountF,
|
||||||
|
Currency: ledger.USD,
|
||||||
|
Description: desc,
|
||||||
|
Payee: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
matched := map[string]struct{}{}
|
||||||
|
matchies := func(deltas ledger.Deltas, delta ledger.Delta) (ledger.Deltas, []string) {
|
||||||
|
deltas = slices.Clone(deltas)
|
||||||
|
dates := append([]string{delta.Date}, delta.OtherDates...)
|
||||||
|
matches := deltas.Like(func(delta ledger.Delta) bool {
|
||||||
|
return delta.Date >= slices.Min(dates)
|
||||||
|
})
|
||||||
|
matches = matches.Like(func(delta ledger.Delta) bool {
|
||||||
|
return delta.Date <= slices.Max(dates)
|
||||||
|
})
|
||||||
|
matches = matches.Like(func(delta ledger.Delta) bool {
|
||||||
|
return delta.Currency == ledger.USD
|
||||||
|
})
|
||||||
|
matches = matches.Like(func(d2 ledger.Delta) bool {
|
||||||
|
return fmt.Sprintf("%.2f", d2.Value) == fmt.Sprintf("%.2f", delta.Value)
|
||||||
|
})
|
||||||
|
for _, match := range matches {
|
||||||
|
if _, ok := matched[match.ID()]; !ok {
|
||||||
|
matched[match.ID()] = struct{}{}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches, dates
|
||||||
|
}
|
||||||
|
|
||||||
|
datesMatched := []string{}
|
||||||
|
namesMatched := []string{}
|
||||||
|
nonAssetNamesMatched := []string{}
|
||||||
|
for _, csvDelta := range csvDeltas {
|
||||||
|
matches, dates := matchies(deltas, csvDelta)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
fmt.Printf("unique to csv | %s %s %.2f\n", strings.Join(dates, "="), csvDelta.Name, csvDelta.Value)
|
||||||
|
}
|
||||||
|
for _, match := range matches {
|
||||||
|
datesMatched = append(datesMatched, match.Date)
|
||||||
|
datesMatched = append(datesMatched, match.OtherDates...)
|
||||||
|
namesMatched = append(namesMatched, match.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nonAssetNamesMatched = slices.DeleteFunc(slices.Clone(namesMatched), func(name string) bool {
|
||||||
|
return strings.Contains(name, "Asset")
|
||||||
|
})
|
||||||
|
datesMatched = slices.DeleteFunc(datesMatched, func(a string) bool { return strings.TrimSpace(a) == "" })
|
||||||
|
datesMatched = slices.Compact(datesMatched)
|
||||||
|
namesMatched = slices.Compact(namesMatched)
|
||||||
|
|
||||||
|
transactions := deltas.Transactions()
|
||||||
|
deltas = deltas.Like(func(delta ledger.Delta) bool {
|
||||||
|
return delta.Date >= slices.Min(datesMatched)
|
||||||
|
})
|
||||||
|
deltas = deltas.Like(func(delta ledger.Delta) bool {
|
||||||
|
return delta.Date <= slices.Max(datesMatched)
|
||||||
|
})
|
||||||
|
deltas = deltas.Like(func(delta ledger.Delta) bool {
|
||||||
|
return slices.Contains(namesMatched, delta.Name)
|
||||||
|
})
|
||||||
|
deltas = deltas.Like(func(delta ledger.Delta) bool {
|
||||||
|
xaction := transactions.Lookup(delta)
|
||||||
|
if noXactionFound := len(xaction) == 0; noXactionFound {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
names := []string{}
|
||||||
|
for _, delta := range xaction.Deltas() {
|
||||||
|
names = append(names, delta.Name)
|
||||||
|
}
|
||||||
|
slices.Sort(names)
|
||||||
|
_ = names
|
||||||
|
|
||||||
|
allTheSame := true
|
||||||
|
for i := range xaction {
|
||||||
|
for j := i + 1; j < len(xaction); j++ {
|
||||||
|
allTheSame = allTheSame && (xaction[i].Name == xaction[j].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if allTheSame {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if anyNameNotRelevant := slices.ContainsFunc(xaction.Deltas(), func(some ledger.Delta) bool {
|
||||||
|
return !slices.Contains(namesMatched, delta.Name)
|
||||||
|
}); anyNameNotRelevant {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasNonAssetNameMatch := slices.ContainsFunc(xaction.Deltas(), func(some ledger.Delta) bool {
|
||||||
|
return slices.Contains(nonAssetNamesMatched, delta.Name)
|
||||||
|
}); !hasNonAssetNameMatch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
deltasSum := deltas.Group(ledger.GroupDate(""), ledger.GroupName("")).Balances()[""][ledger.USD]
|
||||||
|
csvSum := csvDeltas.Group(ledger.GroupDate(""), ledger.GroupName("")).Balances()[""][ledger.USD]
|
||||||
|
if deltasSum != csvSum {
|
||||||
|
log.Printf("csv sum %.2f but deltas sum %.2f", csvSum, deltasSum)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, delta := range deltas {
|
||||||
|
matches, dates := matchies(csvDeltas, delta)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
fmt.Printf("unique to ledger | %s %s %.2f\n", strings.Join(dates, "="), delta.Description, delta.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, delta := range deltas {
|
||||||
|
if _, ok := matched[delta.ID()]; !ok {
|
||||||
|
fmt.Printf("unmatched ledger | %s %s %.2f\n", delta.Date, delta.Description, delta.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, delta := range csvDeltas {
|
||||||
|
if _, ok := matched[delta.ID()]; !ok {
|
||||||
|
fmt.Printf("unmatched csv | %s %s %.2f\n", delta.Date, delta.Description, delta.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic("unknown command " + positional[0])
|
log.Fatalf("unknown command %q", positional[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func FPrintBalances(w io.Writer, linePrefix string, balances, cumulatives ledger.Balances) {
|
func FPrintBalancesFor(description string, w io.Writer, linePrefix string, balances, cumulatives ledger.Balances, usdOnly, normalized bool, date string, compact bool, keyW int, cumulativeFormat string) {
|
||||||
|
if compact {
|
||||||
|
FPrintBalances(w, date+"\t", balances, cumulatives, usdOnly, normalized, date, compact, keyW, cumulativeFormat)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "%s\t%s\n", date, description)
|
||||||
|
FPrintBalances(w, linePrefix, balances, cumulatives, usdOnly, normalized, date, compact, keyW, cumulativeFormat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FPrintBalances(w io.Writer, linePrefix string, balances, cumulatives ledger.Balances, usdOnly, normalized bool, date string, fullKey bool, max int, cumulativeFormat string) {
|
||||||
|
maxes := map[ledger.Currency]float64{}
|
||||||
keys := []string{}
|
keys := []string{}
|
||||||
for k := range balances {
|
for k, v := range balances {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
|
for k2, v2 := range v {
|
||||||
|
if math.Abs(v2) > math.Abs(maxes[k2]) {
|
||||||
|
maxes[k2] = math.Abs(v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
slices.Sort(keys)
|
slices.Sort(keys)
|
||||||
|
|
||||||
max := 0
|
normalizer := ana.NewDefaultNormalizer()
|
||||||
for _, k := range keys {
|
|
||||||
if n := len(k); n > max {
|
cumulativeFormat = strings.ReplaceAll(cumulativeFormat, "%", "%%")
|
||||||
max = n
|
format := fmt.Sprintf("%s%%-%ds\t%%s%%.2f ("+cumulativeFormat+")\n", linePrefix, max)
|
||||||
|
if normalized {
|
||||||
|
format = fmt.Sprintf("%s%%-%ds\t%%s%%.2f (%%s%%.2f (%%.2f @%%.2f ("+cumulativeFormat+")))\n", linePrefix, max)
|
||||||
}
|
}
|
||||||
|
for i, key := range keys {
|
||||||
|
printableKey := key
|
||||||
|
if fullKey {
|
||||||
|
} else if i == 0 {
|
||||||
|
} else {
|
||||||
|
commonPrefixLen := func() int {
|
||||||
|
j := 0
|
||||||
|
n := len(keys[i])
|
||||||
|
if n2 := len(keys[i-1]); n2 < n {
|
||||||
|
n = n2
|
||||||
|
}
|
||||||
|
for j = 0; j < n; j++ {
|
||||||
|
if keys[i-1][j] != keys[i][j] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for keys[i][j] != ':' && j > 0 {
|
||||||
|
j -= 1
|
||||||
|
}
|
||||||
|
return j
|
||||||
|
}()
|
||||||
|
printableKey = strings.Repeat(" ", commonPrefixLen) + keys[i][commonPrefixLen:]
|
||||||
}
|
}
|
||||||
|
|
||||||
format := fmt.Sprintf("%s%%-%ds\t%%s%%.2f (%%s%%.2f)\n", linePrefix, max)
|
|
||||||
for _, key := range keys {
|
|
||||||
currencies := []ledger.Currency{}
|
currencies := []ledger.Currency{}
|
||||||
for currency := range balances[key] {
|
for currency := range balances[key] {
|
||||||
currencies = append(currencies, currency)
|
currencies = append(currencies, currency)
|
||||||
@@ -142,8 +595,13 @@ func FPrintBalances(w io.Writer, linePrefix string, balances, cumulatives ledger
|
|||||||
|
|
||||||
for _, currency := range currencies {
|
for _, currency := range currencies {
|
||||||
printableCurrency := currency
|
printableCurrency := currency
|
||||||
|
format := format
|
||||||
if printableCurrency != "$" {
|
if printableCurrency != "$" {
|
||||||
printableCurrency += " "
|
printableCurrency += " "
|
||||||
|
format = strings.ReplaceAll(format, "%.2f", "%.3f")
|
||||||
|
}
|
||||||
|
if usdOnly && printableCurrency != "$" {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cumulative := balances[key][currency]
|
cumulative := balances[key][currency]
|
||||||
@@ -153,7 +611,40 @@ func FPrintBalances(w io.Writer, linePrefix string, balances, cumulatives ledger
|
|||||||
cumulative = value
|
cumulative = value
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, format, key, printableCurrency, balances[key][currency], printableCurrency, cumulative)
|
printingPercents := strings.Contains(cumulativeFormat, "%%%%")
|
||||||
|
if !printingPercents {
|
||||||
|
if !normalized {
|
||||||
|
fmt.Fprintf(w, format,
|
||||||
|
printableKey,
|
||||||
|
printableCurrency, balances[key][currency],
|
||||||
|
printableCurrency, cumulative,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
factor := normalizer.NormalizeFactor(key, date)
|
||||||
|
trailingMax := maxes[currency] - math.Abs(balances[key][currency])
|
||||||
|
fmt.Fprintf(w, format, printableKey, printableCurrency, balances[key][currency], printableCurrency, cumulative, cumulative*factor, factor, printableCurrency, factor*trailingMax)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !normalized {
|
||||||
|
fmt.Fprintf(w, format, printableKey, printableCurrency, balances[key][currency], cumulative)
|
||||||
|
} else {
|
||||||
|
factor := normalizer.NormalizeFactor(key, date)
|
||||||
|
trailingMax := maxes[currency] - math.Abs(balances[key][currency])
|
||||||
|
fmt.Fprintf(w, format, printableKey, printableCurrency, balances[key][currency], printableCurrency, cumulative, cumulative*factor, factor, factor*trailingMax)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeDate(date string) string {
|
||||||
|
for _, layout := range []string{
|
||||||
|
"01/02/2006",
|
||||||
|
} {
|
||||||
|
if t, err := time.Parse(layout, date); err == nil {
|
||||||
|
return t.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Fatalf("cannot normalize date %q", date)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type Query struct{}
|
type Query struct{}
|
||||||
|
|
||||||
func BuildQuery(args args) (ledger.Like, error) {
|
func BuildQuery(config Config, args args) (ledger.Like, error) {
|
||||||
var result ledger.Like
|
var result ledger.Like
|
||||||
var err error
|
var err error
|
||||||
func() {
|
func() {
|
||||||
@@ -18,12 +18,12 @@ func BuildQuery(args args) (ledger.Like, error) {
|
|||||||
err = fmt.Errorf("panicked: %v", err)
|
err = fmt.Errorf("panicked: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
result, err = buildQuery(args)
|
result, err = buildQuery(config, args)
|
||||||
}()
|
}()
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildQuery(args args) (ledger.Like, error) {
|
func buildQuery(config Config, args args) (ledger.Like, error) {
|
||||||
likeName := func(s string) ledger.Like {
|
likeName := func(s string) ledger.Like {
|
||||||
return ledger.LikeName(s)
|
return ledger.LikeName(s)
|
||||||
}
|
}
|
||||||
@@ -46,17 +46,17 @@ func buildQuery(args args) (ledger.Like, error) {
|
|||||||
switch args.peek() {
|
switch args.peek() {
|
||||||
case "and":
|
case "and":
|
||||||
args.pop()
|
args.pop()
|
||||||
var like ledger.Like
|
var and ledger.Like
|
||||||
switch args.peek() {
|
switch args.peek() {
|
||||||
case "not":
|
case "not":
|
||||||
args.pop()
|
args.pop()
|
||||||
log.Println("and not", args.peek())
|
log.Println("and not", args.peek())
|
||||||
like = notLike(likeName(args.pop()))
|
and = notLike(likeName(args.pop()))
|
||||||
default:
|
default:
|
||||||
log.Println("and ", args.peek())
|
log.Println("and ", args.peek())
|
||||||
like = likeName(args.pop())
|
and = likeName(args.pop())
|
||||||
}
|
}
|
||||||
like = andLike(like, like)
|
like = andLike(like, and)
|
||||||
case "not":
|
case "not":
|
||||||
args.pop()
|
args.pop()
|
||||||
log.Println("or not ", args.peek())
|
log.Println("or not ", args.peek())
|
||||||
|
|||||||
12
cmd/cli/run.sh
Normal file
12
cmd/cli/run.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
cmd="bal"
|
||||||
|
case "$1" in
|
||||||
|
bal|reg|gra|graph|rec )
|
||||||
|
cmd="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
cd "$(dirname "$(realpath "$BASH_SOURCE")")"
|
||||||
|
go run ../ cli "$@" $(printf " -f %s" $HOME/Sync/Core/ledger/eras/2022-/*.txt) "$cmd" :AssetAccount:
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
<span>
|
<span>
|
||||||
<label for="likeName">likeName</label>
|
<label for="likeName">likeName</label>
|
||||||
<input name="likeName" type="text" value="AssetAccount"/>
|
<input name="likeName" type="text" value="Bel:AssetAccount"/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
|
|
||||||
<span>
|
<span>
|
||||||
<label for="prediction">prediction</label>
|
<label for="prediction">prediction</label>
|
||||||
<input name="prediction" type="text" value="interest=AssetAccount:Cash \$ 0.02&prediction=contributions=AssetAccount:Bonds $ 1875&prediction=interest=AssetAccount:Monthly \$ 0.03&prediction=contributions=AssetAccount:Monthly $ 2500"/>
|
<input name="prediction" type="text" value="interest=Bel:AssetAccount:Cash \$ 0.02&prediction=contributions=Bel:AssetAccount:Bonds $ 1916&prediction=interest=Bel:AssetAccount:Monthly \$ 0.03&prediction=contributions=Bel:AssetAccount:Monthly $ 3500"/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
|
|
||||||
<span>
|
<span>
|
||||||
<label for="whatIf">whatIf</label>
|
<label for="whatIf">whatIf</label>
|
||||||
<input name="whatIf" type="text" value="AssetAccount:Cash $ -.10000"/>
|
<input name="whatIf" type="text" value="Bel:AssetAccount:Cash $ -.10000"/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<li><a href="/api/trends">Where does the house money go?</a></li>
|
<li><a href="/api/trends">Where does the house money go?</a></li>
|
||||||
<li><a href="/explore.html">Explore Bel's Money</a></li>
|
<li><a href="/explore.html">Explore Bel's Money</a></li>
|
||||||
<li><a href="/api/bal?x=y&mode=bal&likeName=AssetAccount&chart=stack&predictionMonths=120&bpi=true&zoomStart=YYYY-MM&prediction=interest=AssetAccount:Cash%20\$%200.02&prediction=contributions=AssetAccount:Bonds%20$%201875&prediction=interest=AssetAccount:Monthly%20\$%200.03&prediction=contributions=AssetAccount:Monthly%20$%202500&predictFixedGrowth=VBTLX=0.02&predictFixedGrowth=GLD=0.02&predictFixedGrowth=FXAIX=0.03&predictFixedGrowth=FSPSX=0.03&whatIf=AssetAccount:Cash%20$%20-.10000&=">Project Bel's Net Worth</a></li>
|
<li><a href="/api/bal?x=y&mode=bal&likeName=AssetAccount&chart=stack&predictionMonths=120&bpi=true&zoomStart=YYYY-MM&prediction=interest=AssetAccount:Cash%20\$%200.02&prediction=contributions=AssetAccount:Bonds%20$%201875&prediction=interest=AssetAccount:Monthly%20\$%200.03&prediction=contributions=AssetAccount:Monthly%20$%202500&predictFixedGrowth=VBTLX=0.02&predictFixedGrowth=GLD=0.02&predictFixedGrowth=FXAIX=0.03&predictFixedGrowth=FSPSX=0.03&whatIf=AssetAccount:Cash%20$%20-.10000&=">Project Bel's Net Worth</a></li>
|
||||||
<li><a href="/api/reg?x=y&mode=reg&likeName=Withdrawal:&chart=stack&predictionMonths=3&bpi=false&zoomStart=YYYY-MM&prediction=autoContributions=&predictFixedGrowth=VBTLX=0&whatIf=AssetAccount:Cash%20$%20-.10000&=">Expect Bel's Expenses</a></li>
|
<!--<li><a href="/api/reg?x=y&mode=reg&likeName=Bel:Withdrawal:&chart=stack&predictionMonths=3&bpi=false&zoomStart=YYYY-MM&prediction=autoContributions=&predictFixedGrowth=VBTLX=0&whatIf=AssetAccount:Cash%20$%20-.10000&=">Expect Bel's Expenses</a></li>-->
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
<footer>
|
<footer>
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (router Router) APITransactions(w http.ResponseWriter, r *http.Request) {
|
|||||||
v := normalized[k]
|
v := normalized[k]
|
||||||
if v := math.Abs(v["$"]); v < biggest {
|
if v := math.Abs(v["$"]); v < biggest {
|
||||||
normalizedDelta := biggest - v
|
normalizedDelta := biggest - v
|
||||||
normalizedFactor := normalizer.NormalizeFactor(ledger.Delta{Name: k, Date: time.Now().Format("2006-01-02")})
|
normalizedFactor := normalizer.NormalizeFactor(k, time.Now().Format("2006-01-02"))
|
||||||
normalized[fmt.Sprintf(`(%s trailing $)`, k)] = ledger.Balance{"$": normalizedDelta * normalizedFactor}
|
normalized[fmt.Sprintf(`(%s trailing $)`, k)] = ledger.Balance{"$": normalizedDelta * normalizedFactor}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,6 +297,11 @@ func (router Router) APIReg(w http.ResponseWriter, r *http.Request) {
|
|||||||
register := deltas.Register()
|
register := deltas.Register()
|
||||||
predicted := make(ledger.Register)
|
predicted := make(ledger.Register)
|
||||||
|
|
||||||
|
bpis, err := router.bpis()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
if predictionMonths, err := strconv.ParseInt(r.URL.Query().Get("predictionMonths"), 10, 16); err == nil && predictionMonths > 0 {
|
if predictionMonths, err := strconv.ParseInt(r.URL.Query().Get("predictionMonths"), 10, 16); err == nil && predictionMonths > 0 {
|
||||||
window := time.Hour * 24.0 * 365.0 / 12.0 * time.Duration(predictionMonths)
|
window := time.Hour * 24.0 * 365.0 / 12.0 * time.Duration(predictionMonths)
|
||||||
// TODO whatif
|
// TODO whatif
|
||||||
@@ -334,10 +339,6 @@ func (router Router) APIReg(w http.ResponseWriter, r *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
bpis, err := router.bpis()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
bpis, err = ana.BPIsWithFixedGrowthPrediction(bpis, window, currency, rate)
|
bpis, err = ana.BPIsWithFixedGrowthPrediction(bpis, window, currency, rate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -346,10 +347,6 @@ func (router Router) APIReg(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r.URL.Query().Get("bpi") == "true" {
|
if r.URL.Query().Get("bpi") == "true" {
|
||||||
bpis, err := router.bpis()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
register = register.WithBPIs(bpis)
|
register = register.WithBPIs(bpis)
|
||||||
predicted = predicted.WithBPIs(bpis)
|
predicted = predicted.WithBPIs(bpis)
|
||||||
}
|
}
|
||||||
|
|||||||
3
cmd/install.sh
Normal file
3
cmd/install.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
cd "$(dirname "$(realpath "$BASH_SOURCE")")"
|
||||||
|
go build -o $GOPATH/bin/ana-ledger
|
||||||
1
cmd/install_scratch.sh
Normal file
1
cmd/install_scratch.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CGO_ENABLED=1 CC=x86_64-linux-musl-gcc go build -ldflags="-linkmode external -extldflags -static" -o $HOME/Go/bin/ana-ledger
|
||||||
38
cmd/main.go
38
cmd/main.go
@@ -1,19 +1,57 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"gogs.inhome.blapointe.com/ana-ledger/cmd/cli"
|
"gogs.inhome.blapointe.com/ana-ledger/cmd/cli"
|
||||||
"gogs.inhome.blapointe.com/ana-ledger/cmd/http"
|
"gogs.inhome.blapointe.com/ana-ledger/cmd/http"
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank/teller"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
|
case "tel":
|
||||||
|
ctx, can := signal.NotifyContext(context.Background(), syscall.SIGINT)
|
||||||
|
defer can()
|
||||||
|
|
||||||
|
if c, err := teller.New(); err != nil {
|
||||||
|
} else if _, err := c.Accounts(ctx); err != nil {
|
||||||
|
} else {
|
||||||
|
log.Println("teller already init")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := teller.Init(ctx); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
case "http":
|
case "http":
|
||||||
os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
|
os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
|
||||||
http.Main()
|
http.Main()
|
||||||
case "cli":
|
case "cli":
|
||||||
os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
|
os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
|
||||||
cli.Main()
|
cli.Main()
|
||||||
|
case "shared":
|
||||||
|
files := os.Args[2:]
|
||||||
|
os.Args = []string{os.Args[0], "cli"}
|
||||||
|
for _, f := range files {
|
||||||
|
if strings.HasPrefix(f, "-") {
|
||||||
|
os.Args = append(os.Args, f)
|
||||||
|
} else {
|
||||||
|
os.Args = append(os.Args, "-f", f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Args = append(os.Args,
|
||||||
|
"-w=^Housey",
|
||||||
|
"--depth=1",
|
||||||
|
"--usd",
|
||||||
|
"-n",
|
||||||
|
"--no-percent",
|
||||||
|
"bal", "^Bel", "^Zach",
|
||||||
|
)
|
||||||
|
main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
go.mod
16
go.mod
@@ -1,5 +1,17 @@
|
|||||||
module gogs.inhome.blapointe.com/ana-ledger
|
module gogs.inhome.blapointe.com/ana-ledger
|
||||||
|
|
||||||
go 1.21.1
|
go 1.23.0
|
||||||
|
|
||||||
require github.com/go-echarts/go-echarts/v2 v2.3.1
|
toolchain go1.24.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-echarts/go-echarts/v2 v2.3.1
|
||||||
|
github.com/guptarohit/asciigraph v0.7.3
|
||||||
|
golang.org/x/crypto v0.38.0
|
||||||
|
golang.org/x/time v0.11.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
|
golang.org/x/term v0.32.0 // indirect
|
||||||
|
)
|
||||||
|
|||||||
10
go.sum
10
go.sum
@@ -2,9 +2,19 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-echarts/go-echarts/v2 v2.3.1 h1:Yw0HVjVTxpYm48l974dMjRzx8ni2ql0kKi/kawSgxFE=
|
github.com/go-echarts/go-echarts/v2 v2.3.1 h1:Yw0HVjVTxpYm48l974dMjRzx8ni2ql0kKi/kawSgxFE=
|
||||||
github.com/go-echarts/go-echarts/v2 v2.3.1/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI=
|
github.com/go-echarts/go-echarts/v2 v2.3.1/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI=
|
||||||
|
github.com/guptarohit/asciigraph v0.7.3 h1:p05XDDn7cBTWiBqWb30mrwxd6oU0claAjqeytllnsPY=
|
||||||
|
github.com/guptarohit/asciigraph v0.7.3/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
|
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
|
||||||
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||||
|
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||||
|
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||||
|
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
|
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
|
||||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -19,19 +19,23 @@ type normalize struct {
|
|||||||
|
|
||||||
func NewDefaultNormalizer() Normalizer {
|
func NewDefaultNormalizer() Normalizer {
|
||||||
return NewNormalizer().
|
return NewNormalizer().
|
||||||
With("^Zach:", "2023-10-05", 139). // to turtle
|
With("^Zach", "2026-01-01", 156). // turtle up again!
|
||||||
With("^Zach:", "2021-12-30", 135). // at pluralsight
|
With("^Zach", "2025-09-01", 151). // turtle up
|
||||||
With("^Zach:", "2020-07-30", 120). // to pluralsight
|
With("^Zach", "2023-10-05", 139). // to turtle
|
||||||
With("^Zach:", "2019-07-16", 77). // at fedex
|
With("^Zach", "2021-12-30", 135). // at pluralsight
|
||||||
With("^Zach:", "2017-02-16", 49). // to fedex
|
With("^Zach", "2020-07-30", 120). // to pluralsight
|
||||||
With("^Bel:", "2023-12-05", 190). // to render
|
With("^Zach", "2019-07-16", 77). // at fedex
|
||||||
With("^Bel:", "2022-12-31", 154). // at q
|
With("^Zach", "2017-02-16", 49). // to fedex
|
||||||
With("^Bel:", "2022-06-30", 148). // at q
|
With("^Bel", "2025-10-01", 225). // render up
|
||||||
With("^Bel:", "2021-12-31", 122). // at q
|
With("^Bel", "2025-04-01", 214). // lc4 at render
|
||||||
With("^Bel:", "2020-12-31", 118). // at q
|
With("^Bel", "2023-12-05", 190). // to render
|
||||||
With("^Bel:", "2019-12-31", 111). // at q
|
With("^Bel", "2022-12-31", 154). // at q
|
||||||
With("^Bel:", "2018-12-31", 92). // at q
|
With("^Bel", "2022-06-30", 148). // at q
|
||||||
With("^Bel:", "2018-02-16", 86) // to q
|
With("^Bel", "2021-12-31", 122). // at q
|
||||||
|
With("^Bel", "2020-12-31", 118). // at q
|
||||||
|
With("^Bel", "2019-12-31", 111). // at q
|
||||||
|
With("^Bel", "2018-12-31", 92). // at q
|
||||||
|
With("^Bel", "2018-02-16", 86) // to q
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNormalizer() Normalizer {
|
func NewNormalizer() Normalizer {
|
||||||
@@ -68,15 +72,15 @@ func (n Normalizer) Normalize(deltas ledger.Deltas) ledger.Deltas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n Normalizer) NormalizeDelta(delta ledger.Delta) ledger.Delta {
|
func (n Normalizer) NormalizeDelta(delta ledger.Delta) ledger.Delta {
|
||||||
delta.Value /= n.NormalizeFactor(delta)
|
delta.Value /= n.NormalizeFactor(delta.Name, delta.Date)
|
||||||
return delta
|
return delta
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n Normalizer) NormalizeFactor(delta ledger.Delta) float64 {
|
func (n Normalizer) NormalizeFactor(name, date string) float64 {
|
||||||
for pattern := range n.m {
|
for pattern := range n.m {
|
||||||
if regexp.MustCompile(pattern).MatchString(delta.Name) {
|
if regexp.MustCompile(pattern).MatchString(name) {
|
||||||
for _, normalize := range n.m[pattern] {
|
for _, normalize := range n.m[pattern] {
|
||||||
if normalize.startDate < delta.Date {
|
if normalize.startDate < date {
|
||||||
return normalize.factor
|
return normalize.factor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/bank/cache/cache.go
vendored
Normal file
107
src/bank/cache/cache.go
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
Client bank.Agg
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ bank.Agg = Client{}
|
||||||
|
|
||||||
|
func New(client bank.Agg) Client {
|
||||||
|
return Client{Client: client}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) Accounts(ctx context.Context) ([]bank.Account, error) {
|
||||||
|
k := "accounts"
|
||||||
|
result := []bank.Account{}
|
||||||
|
if err := fromCache(k, &result); err != nil {
|
||||||
|
log.Printf("%q not in cache: %v", k, err)
|
||||||
|
} else {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := c.Client.Accounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
toCache(k, result)
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) Transactions(ctx context.Context, a bank.Account) ([]bank.Transaction, error) {
|
||||||
|
k := path.Join("accounts.d", a.Account)
|
||||||
|
result := []bank.Transaction{}
|
||||||
|
if err := fromCache(k, &result); err != nil {
|
||||||
|
log.Printf("%q not in cache: %v", k, err)
|
||||||
|
} else {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := c.Client.Transactions(ctx, a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
toCache(k, result)
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
d = path.Join("/tmp/ana_ledger_bank_cache.d")
|
||||||
|
)
|
||||||
|
|
||||||
|
func toCache(k string, v interface{}) {
|
||||||
|
if err := _toCache(k, v); err != nil {
|
||||||
|
log.Printf("failed to cache %s: %v", k, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _toCache(k string, v interface{}) error {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p := path.Join(d, k)
|
||||||
|
os.MkdirAll(path.Dir(p), os.ModePerm)
|
||||||
|
if err := os.WriteFile(p, b, os.ModePerm); err != nil {
|
||||||
|
os.Remove(p)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromCache(k string, ptr interface{}) error {
|
||||||
|
p := path.Join(d, k)
|
||||||
|
if stat, err := os.Stat(p); err != nil {
|
||||||
|
return err
|
||||||
|
} else if time.Since(stat.ModTime()) > 24*time.Hour {
|
||||||
|
return fmt.Errorf("stale")
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := os.ReadFile(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(b, ptr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
50
src/bank/cache/cache_integration_test.go
vendored
Normal file
50
src/bank/cache/cache_integration_test.go
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package cache_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank/cache"
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank/teller"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
tellerC, err := teller.New()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
client := cache.New(tellerC)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
i := i
|
||||||
|
client := client
|
||||||
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
|
accounts, err := client.Accounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, account := range accounts {
|
||||||
|
account := account
|
||||||
|
t.Run(account.Account, func(t *testing.T) {
|
||||||
|
transactions, err := client.Transactions(ctx, account)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tr := range transactions {
|
||||||
|
t.Logf("[%d] %+v", i, tr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
client.Client = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/bank/teller/application_id.txt
Normal file
1
src/bank/teller/application_id.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
app_pdvv33dtmta4fema66000
|
||||||
29
src/bank/teller/certificate.pem
Normal file
29
src/bank/teller/certificate.pem
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIExjCCAq6gAwIBAgIIGEJSCPAVjIYwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UE
|
||||||
|
BhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxDzANBgNVBAcMBkxvbmRvbjEPMA0GA1UE
|
||||||
|
CgwGVGVsbGVyMR4wHAYDVQQLDBVUZWxsZXIgQXBwbGljYXRpb24gQ0EwHhcNMjUw
|
||||||
|
NTI0MDEyMzIzWhcNMjgwNTIzMDEyMzIzWjAkMSIwIAYDVQQDDBlhcHBfcGR2djMz
|
||||||
|
ZHRtdGE0ZmVtYTY2MDAwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||||
|
tWbYAc2wQBBvKJhTlo5YPLqkM5GgaYaWUqJJ5bFht+U2PL0rJHbS7oRG9fXtgb12
|
||||||
|
jEzD3CUUPpCxj7oRgYdji2SH5NKmo3M85/Cry1y5pmotmqGlqrt01zStj2A+FuzR
|
||||||
|
BqdmVb1CIE2iJmttGn3C3f9OCbV5kMKreu4DhVdPW7eafpo+yIMaoJxx2CAMqw5Y
|
||||||
|
GK2NNpehMHzpL4Z0032yEQJaBblYeUT4zgMCxoupXQ7hCsyjn/ws7ocpMHXY9r08
|
||||||
|
6PjaY1j6wYwX9OUJDXz0zgoeShr2vcfkjBc1QavRLVQQUWgYJevS/8rCfo32B7ub
|
||||||
|
Ym1CmWz2cY3+4UV3uihJgQIDAQABo4G+MIG7MA4GA1UdDwEB/wQEAwIF4DATBgNV
|
||||||
|
HSUEDDAKBggrBgEFBQcDAjCBkwYDVR0jBIGLMIGIgBSEq++simSLxXkuNSUKjel6
|
||||||
|
pmhxmqFlpGMwYTELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxDzANBgNV
|
||||||
|
BAcMBkxvbmRvbjEPMA0GA1UECgwGVGVsbGVyMR4wHAYDVQQLDBVUZWxsZXIgQXBw
|
||||||
|
bGljYXRpb24gQ0GCCQDiNWG/vm85CTANBgkqhkiG9w0BAQsFAAOCAgEARv/Kjwcu
|
||||||
|
ppXbTf9pvsesEgo6O+OM1qW73SkmQeB5ZfF6KEOn57SujTjVQRlBGhVs//+Ezlav
|
||||||
|
GKKm4Xw0eCKUfISIgz+nY7lSlVvW2REZAdpuiY6owsqtiL/Fe/RBvkUmNSWnu8vc
|
||||||
|
OIfnpqP6flKL7KjXwQXoI/Xt9Zw6D56dHQi5hYgYtP0HqtEZn6vdtroHM3mbIL6D
|
||||||
|
Dnfdhb3ywwVZTiQE5ceQk+StDYuzTz7PNQL6IWxcH4j73dQlvFzMLSDm9yA2NguK
|
||||||
|
SEiRi4gYmluQxSiTN3gYqfOMeVv/buklHknkRHCInOTOiDWX8ku0FWwApiwsmvLS
|
||||||
|
3z/9WK4QEMLQfxBbp7UJePWx0Tq6KE61gcTgMbjqz+Xi9n2KM6RenDdMg2rQXWX4
|
||||||
|
xqC0sOOuSS19WFCGYDBRjI2JOQqfeEymq8pQsrGm+XyzCPMi+eFyLZqkRiT85MCr
|
||||||
|
IZuUWpMTcqILGP3Ar5Z0ppDI1ppVDhWMoq5EYx0iuJjNQZEtHlbu1j+cw6uVAoqJ
|
||||||
|
T/E5/qKcLRkkDKV68B+CP2z+iOXH5M1dcYFu6yEkKxVbEuTJNyN5gHhBATyIoMQ0
|
||||||
|
RdohL8F9hdOHvTLo89xrFEHiLExIT0NISjlT0M/mTqq4rbr5kp5W/ee9h5uSVUJ8
|
||||||
|
3nCv0NH3CX0Ygjzd7Czd9hWRahQz+vv55u4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
64
src/bank/teller/init.go
Normal file
64
src/bank/teller/init.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package teller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"slices"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed application_id.txt
|
||||||
|
applicationId string
|
||||||
|
//go:embed init.html
|
||||||
|
initHTML string
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(ctx context.Context) error {
|
||||||
|
environment := "development"
|
||||||
|
if sandbox := !slices.Contains(os.Args, "forreal"); sandbox {
|
||||||
|
environment = "sandbox"
|
||||||
|
}
|
||||||
|
fmt.Printf("environment=%q\n", environment)
|
||||||
|
|
||||||
|
newTokens := make(chan string)
|
||||||
|
defer close(newTokens)
|
||||||
|
s := &http.Server{
|
||||||
|
Addr: ":20000",
|
||||||
|
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
b, _ := io.ReadAll(r.Body)
|
||||||
|
newTokens <- string(b)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := template.New("initHTML").Parse(initHTML)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.Execute(w, map[string]string{
|
||||||
|
"applicationId": applicationId,
|
||||||
|
"environment": environment,
|
||||||
|
}); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
defer s.Close()
|
||||||
|
go s.ListenAndServe()
|
||||||
|
|
||||||
|
fmt.Println("Open http://localhost:20000")
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case newToken := <-newTokens:
|
||||||
|
return fmt.Errorf("not impl: %q >> token.txt", newToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
58
src/bank/teller/init.html
Normal file
58
src/bank/teller/init.html
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<button id="teller-connect">Connect to your bank</button>
|
||||||
|
|
||||||
|
<h3 id="log">
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<script src="https://cdn.teller.io/connect/connect.js"></script>
|
||||||
|
<script>
|
||||||
|
function logme(msg) {
|
||||||
|
document.getElementById("log").innerHTML += `<br>* ${msg}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function http(method, remote, callback, body) {
|
||||||
|
var xmlhttp = new XMLHttpRequest();
|
||||||
|
xmlhttp.onreadystatechange = function() {
|
||||||
|
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||||
|
callback(xmlhttp.responseText, xmlhttp.status)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xmlhttp.open(method, remote, true);
|
||||||
|
if (typeof body == "undefined") {
|
||||||
|
body = null
|
||||||
|
}
|
||||||
|
xmlhttp.send(body);
|
||||||
|
}
|
||||||
|
function callback(responseBody, responseStatus) {
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
var tellerConnect = TellerConnect.setup({
|
||||||
|
applicationId: "{{.applicationId}}",
|
||||||
|
environment: "{{.environment}}",
|
||||||
|
products: ["verify", "balance", "transactions"],
|
||||||
|
onInit: function() {
|
||||||
|
logme("Teller Connect has initialized")
|
||||||
|
},
|
||||||
|
onSuccess: function(enrollment) {
|
||||||
|
logme(`User enrolled successfully: ${enrollment.accessToken}`)
|
||||||
|
http("post", "/", callback, enrollment.accessToken)
|
||||||
|
},
|
||||||
|
onExit: function() {
|
||||||
|
logme("User closed Teller Connect")
|
||||||
|
},
|
||||||
|
onFailure: function(failure) {
|
||||||
|
logme(`Failed: type=${failure.type} code=${failure.code} message=${failure.message}`)
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var el = document.getElementById("teller-connect");
|
||||||
|
el.addEventListener("click", function() {
|
||||||
|
tellerConnect.open();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
28
src/bank/teller/private_key.pem
Normal file
28
src/bank/teller/private_key.pem
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1ZtgBzbBAEG8o
|
||||||
|
mFOWjlg8uqQzkaBphpZSoknlsWG35TY8vSskdtLuhEb19e2BvXaMTMPcJRQ+kLGP
|
||||||
|
uhGBh2OLZIfk0qajczzn8KvLXLmmai2aoaWqu3TXNK2PYD4W7NEGp2ZVvUIgTaIm
|
||||||
|
a20afcLd/04JtXmQwqt67gOFV09bt5p+mj7IgxqgnHHYIAyrDlgYrY02l6EwfOkv
|
||||||
|
hnTTfbIRAloFuVh5RPjOAwLGi6ldDuEKzKOf/Czuhykwddj2vTzo+NpjWPrBjBf0
|
||||||
|
5QkNfPTOCh5KGva9x+SMFzVBq9EtVBBRaBgl69L/ysJ+jfYHu5tibUKZbPZxjf7h
|
||||||
|
RXe6KEmBAgMBAAECggEAExDEEyxzIciYZkPcRS6gx4E2UNU1buHeWsED00hZZOKK
|
||||||
|
WMfpCOQUN01fx+oZFFG9a/GFhFXBUvISN3Du9hYsuDHQtpQNP5CVDiuVYsJUINF4
|
||||||
|
CZCDwPYCybuXokITRIWPUou1jb1efdaq/C6+QNKG8J4srYiNRlGvhDQP2qvag2ET
|
||||||
|
YtY+6OuQPF9QSeoKLBCJJi8bP/wy3OfOQkTqvlpyEGVOUc5utGuziITShL2mLtQw
|
||||||
|
1O22r4BIFtkvnhM4kGimbSDMYwtAgMrBrktR4Xp7JICV6eZn6fJgjpYOix/4ILxS
|
||||||
|
Ri69qPLso4qF+ML/vsTHlxQj7FwZDZozT4hm3DK3gQKBgQDdnEAdQYuKIvwrHflk
|
||||||
|
Pxb9q7MjrMJMGiA9GvSVTimeWu68kH2y/dUUQyBtr8SRCScNUmhRCfaZCBakSYR0
|
||||||
|
0v+6FLXleI28dD93Qzn70G0N6kVdKLdM3Rt0r+fojPhP+8pHn74UzvcoGUDOzoax
|
||||||
|
VPvHLe19wqrbRFIU4IAE6qjmNQKBgQDRjUFjRJIh4wgrB6rROeoTtYRRyS9RLliw
|
||||||
|
dpH78Vz7OYTx7qnvtVOl8led82Ott7hEXcK9Ihobz8uPCewW/x+sPYty13shT46K
|
||||||
|
8zEj9FoP9XhAS3MOqLDNx7h5jv7nvua8aRQEPkF30SmPqb+X4nN5+JjuJiTqWgJ+
|
||||||
|
5nfnyX4PnQKBgQCE87brVmV27GJJI+R5JfiPG7GPl5fBvHLW9hMCeDAz1u4fprgi
|
||||||
|
6HIrg9IyvB67vLf3IBeBdu7BBL9AtPKIfAX8B2zRTLAL/doNnQFud67ViFUw/Lpr
|
||||||
|
nMNaECabt+dJZRAIRGfvZ/OT1QKyj+jy/r9G0eEHcAC9J5HvAHkNehL2eQKBgAU+
|
||||||
|
a6x4Qs/mRoYNIxEpSdpEaJNDXZPCfSWtUenkGFeREOqc9lOxTe6RKfAh7xShzFKp
|
||||||
|
pf3lpJGdmZJyxR2uNLSytZKiIcqrmv2PKGOl8bsEgYXaXX64afQ8Uzl3gpl6BXwh
|
||||||
|
hQa2KB0/drLJpKnAWPNsbSdIfRQAPJ/AVK/QMv9hAoGAMtmCDJK1KVZcpFJbFSMk
|
||||||
|
pPJjcp1XRWKsiBOPfUKlwbBSFDBUnhyPcsfL9ooAwzBnBcpNf6S5I+I22AdDuk8E
|
||||||
|
S3uOBBlNhoecWN1tqVlcbTR1p5kXV0WVAcQ09hGPqja5ghrTTpWbC7SviSVNa0fx
|
||||||
|
LXKvqDx5qTleSmrPwPs5TW4=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
95
src/bank/teller/teller.go
Normal file
95
src/bank/teller/teller.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package teller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
_ "embed"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank"
|
||||||
|
|
||||||
|
"golang.org/x/time/rate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
cert tls.Certificate
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ bank.Agg = Client{}
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed certificate.pem
|
||||||
|
certificate []byte
|
||||||
|
//go:embed private_key.pem
|
||||||
|
privateKey []byte
|
||||||
|
//go:embed token.txt
|
||||||
|
Tokens string
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() (Client, error) {
|
||||||
|
cert, err := tls.X509KeyPair(certificate, privateKey)
|
||||||
|
return Client{cert: cert}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) Accounts(ctx context.Context) ([]bank.Account, error) {
|
||||||
|
var result []bank.Account
|
||||||
|
for _, token := range strings.Fields(Tokens) {
|
||||||
|
var more []bank.Account
|
||||||
|
if err := c.get(ctx, "https://api.teller.io/accounts", token, &more); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i := range more {
|
||||||
|
more[i].Token = token
|
||||||
|
}
|
||||||
|
result = append(result, more...)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) Transactions(ctx context.Context, a bank.Account) ([]bank.Transaction, error) {
|
||||||
|
var result []bank.Transaction
|
||||||
|
err := c.get(ctx, "https://api.teller.io/accounts/"+a.Account+"/transactions", a.Token, &result)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var limiter = rate.NewLimiter(0.1, 1)
|
||||||
|
|
||||||
|
func (c Client) get(ctx context.Context, url, token string, ptr interface{}) error {
|
||||||
|
if err := limiter.Wait(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Teller.Get(%s, %s)", url, token)
|
||||||
|
httpc := &http.Client{
|
||||||
|
Timeout: time.Second,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
TLSClientConfig: &tls.Config{Certificates: []tls.Certificate{c.cert}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.SetBasicAuth(token, "")
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
|
resp, err := httpc.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
b, _ := io.ReadAll(resp.Body)
|
||||||
|
if err := json.Unmarshal(b, &ptr); err != nil {
|
||||||
|
return fmt.Errorf("cannot unmarshal: %w: %s", err, b)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
41
src/bank/teller/teller_integration_test.go
Normal file
41
src/bank/teller/teller_integration_test.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package teller_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank/teller"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
teller.Tokens = "test_token_bfu2cyvq3il6o"
|
||||||
|
|
||||||
|
c, err := teller.New()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
accounts, err := c.Accounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, account := range accounts {
|
||||||
|
account := account
|
||||||
|
t.Run(account.Account, func(t *testing.T) {
|
||||||
|
transactions, err := c.Transactions(ctx, account)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tr := range transactions {
|
||||||
|
t.Logf("[%d] %+v", i, tr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
59
src/bank/teller/teller_manual_test.go
Normal file
59
src/bank/teller/teller_manual_test.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
//go:build manual
|
||||||
|
|
||||||
|
package teller_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gogs.inhome.blapointe.com/ana-ledger/src/bank/teller"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntegration(t *testing.T) {
|
||||||
|
teller.Tokens = "test_token_bfu2cyvq3il6o"
|
||||||
|
|
||||||
|
//curl --cert certificate.pem --cert-key private_key.pem --auth test_token_bfu2cyvq3il6o: https://api.teller.io/accounts
|
||||||
|
cert, err := tls.LoadX509KeyPair("./certificate.pem", "./private_key.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &http.Client{
|
||||||
|
Timeout: time.Second,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
TLSClientConfig: &tls.Config{Certificates: []tls.Certificate{cert}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
//curl --cert certificate.pem --cert-key private_key.pem --auth test_token_bfu2cyvq3il6o: https://api.teller.io/accounts
|
||||||
|
|
||||||
|
for _, url := range []string{
|
||||||
|
"https://api.teller.io/accounts",
|
||||||
|
"https://api.teller.io/accounts/acc_pdvv4810fi9hmrcn6g000/transactions",
|
||||||
|
} {
|
||||||
|
url := url
|
||||||
|
t.Run(url, func(t *testing.T) {
|
||||||
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
req.SetBasicAuth("test_token_bfu2cyvq3il6o", "")
|
||||||
|
|
||||||
|
resp, err := c.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
if code := resp.StatusCode; code >= 300 {
|
||||||
|
t.Fatalf("(%d) %s", code, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("(%d) %s", resp.StatusCode, body)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
2
src/bank/teller/token.txt
Normal file
2
src/bank/teller/token.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
token_2utqstwpn3pxwgvyno56hqdehq
|
||||||
|
token_vr6dnzvfv7c24wuxtmnnzyiqbm
|
||||||
31
src/bank/types.go
Normal file
31
src/bank/types.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package bank
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
type Agg interface {
|
||||||
|
Accounts(context.Context) ([]Account, error)
|
||||||
|
Transactions(context.Context, Account) ([]Transaction, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Account struct {
|
||||||
|
Institution struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"institution"`
|
||||||
|
Name string `json:"last_four"`
|
||||||
|
Account string `json:"id"`
|
||||||
|
Token string `json:"__token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Transaction struct {
|
||||||
|
Amount float64 `json:"amount,string"`
|
||||||
|
Details struct {
|
||||||
|
ProcessingStatus string `json:"processing_status"`
|
||||||
|
CounterParty struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"counterparty"`
|
||||||
|
} `json:"details"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Date string `json:"date"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
@@ -9,6 +9,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Normalizer interface {
|
||||||
|
NormalizeFactor(string, string) float64
|
||||||
|
}
|
||||||
|
|
||||||
type Balances map[string]Balance
|
type Balances map[string]Balance
|
||||||
|
|
||||||
type Balance map[Currency]float64
|
type Balance map[Currency]float64
|
||||||
@@ -157,7 +161,7 @@ func (balances Balances) WithBPIsAt(bpis BPIs, date string) Balances {
|
|||||||
if k2 == USD {
|
if k2 == USD {
|
||||||
result[k][USD] = result[k][USD] + v2
|
result[k][USD] = result[k][USD] + v2
|
||||||
} else if scalar := bpis[k2].Lookup(date); scalar != nil {
|
} else if scalar := bpis[k2].Lookup(date); scalar != nil {
|
||||||
result[k][USD] = result[k][USD] + *scalar*v2
|
result[k][USD] = result[k][USD] + v2*(*scalar)
|
||||||
} else {
|
} else {
|
||||||
result[k][k2] = result[k][k2] + v2
|
result[k][k2] = result[k][k2] + v2
|
||||||
}
|
}
|
||||||
@@ -246,3 +250,14 @@ func (balance Balance) Debug() string {
|
|||||||
}
|
}
|
||||||
return strings.Join(result, " + ")
|
return strings.Join(result, " + ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (balances Balances) Normalize(n Normalizer, date string) Balances {
|
||||||
|
result := make(Balances)
|
||||||
|
for name, balance := range balances {
|
||||||
|
result[name] = make(Balance)
|
||||||
|
for currency, value := range balance {
|
||||||
|
result[name][currency] = value / n.NormalizeFactor(name, date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const (
|
|||||||
|
|
||||||
type Delta struct {
|
type Delta struct {
|
||||||
Date string
|
Date string
|
||||||
|
OtherDates []string
|
||||||
Name string
|
Name string
|
||||||
Value float64
|
Value float64
|
||||||
Currency Currency
|
Currency Currency
|
||||||
@@ -20,11 +21,13 @@ type Delta struct {
|
|||||||
isSet bool
|
isSet bool
|
||||||
fileName string
|
fileName string
|
||||||
lineNo int
|
lineNo int
|
||||||
|
with []Delta
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDelta(transaction string, payee bool, d, desc, name string, v float64, c string, isSet bool, fileName string, lineNo int) Delta {
|
func newDelta(transaction string, payee bool, d, desc, name string, v float64, c string, isSet bool, fileName string, lineNo int, otherDates []string) Delta {
|
||||||
return Delta{
|
return Delta{
|
||||||
Date: d,
|
Date: d,
|
||||||
|
OtherDates: otherDates,
|
||||||
Name: name,
|
Name: name,
|
||||||
Value: v,
|
Value: v,
|
||||||
Currency: Currency(c),
|
Currency: Currency(c),
|
||||||
@@ -38,12 +41,24 @@ func newDelta(transaction string, payee bool, d, desc, name string, v float64, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (delta Delta) ID() string {
|
||||||
|
return fmt.Sprintf("%.2f", delta.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (delta Delta) withWith(other Delta) Delta {
|
||||||
|
other.with = nil
|
||||||
|
delta.with = append(delta.with, other)
|
||||||
|
return delta
|
||||||
|
}
|
||||||
|
|
||||||
func (delta Delta) equivalent(other Delta) bool {
|
func (delta Delta) equivalent(other Delta) bool {
|
||||||
delta.fileName = ""
|
delta.fileName = ""
|
||||||
delta.lineNo = 0
|
delta.lineNo = 0
|
||||||
|
delta.with = nil
|
||||||
other.fileName = ""
|
other.fileName = ""
|
||||||
other.lineNo = 0
|
other.lineNo = 0
|
||||||
return delta == other
|
other.with = nil
|
||||||
|
return fmt.Sprintf("%+v", delta) == fmt.Sprintf("%+v", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (delta Delta) Debug() string {
|
func (delta Delta) Debug() string {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
func TestDelta(t *testing.T) {
|
func TestDelta(t *testing.T) {
|
||||||
d := "2099-08-07"
|
d := "2099-08-07"
|
||||||
delta := newDelta("x", true, d, "", "name", 34.56, "$", false, "", 0)
|
delta := newDelta("x", true, d, "", "name", 34.56, "$", false, "", 0, []string{"d2"})
|
||||||
|
|
||||||
if delta.Transaction != "x" {
|
if delta.Transaction != "x" {
|
||||||
t.Error(delta.Transaction)
|
t.Error(delta.Transaction)
|
||||||
@@ -17,6 +17,9 @@ func TestDelta(t *testing.T) {
|
|||||||
if delta.Date != d {
|
if delta.Date != d {
|
||||||
t.Error(delta.Date)
|
t.Error(delta.Date)
|
||||||
}
|
}
|
||||||
|
if delta.OtherDates[0] != "d2" {
|
||||||
|
t.Error(delta.OtherDates)
|
||||||
|
}
|
||||||
if delta.Name != "name" {
|
if delta.Name != "name" {
|
||||||
t.Error(delta.Name)
|
t.Error(delta.Name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,10 +57,7 @@ func (deltas Deltas) Balances() Balances {
|
|||||||
}
|
}
|
||||||
result[delta.Name][delta.Currency] += delta.Value
|
result[delta.Name][delta.Currency] += delta.Value
|
||||||
if result[delta.Name][delta.Currency] < 0.000000001 && result[delta.Name][delta.Currency] > -0.000000001 {
|
if result[delta.Name][delta.Currency] < 0.000000001 && result[delta.Name][delta.Currency] > -0.000000001 {
|
||||||
delete(result[delta.Name], delta.Currency)
|
result[delta.Name][delta.Currency] = 0
|
||||||
if len(result[delta.Name]) == 0 {
|
|
||||||
delete(result, delta.Name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -38,9 +38,12 @@ func TestDeltas(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
balances := deltas.Balances()
|
balances := deltas.Balances()
|
||||||
if len(balances) != 1 {
|
if len(balances) != 2 {
|
||||||
t.Error(len(balances), balances)
|
t.Error(len(balances), balances)
|
||||||
}
|
}
|
||||||
|
if balances["a"][""] != 0 {
|
||||||
|
t.Error(balances["a"])
|
||||||
|
}
|
||||||
if balances["b"][""] != 1.3 {
|
if balances["b"][""] != 1.3 {
|
||||||
t.Error(balances["b"])
|
t.Error(balances["b"])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,8 +99,12 @@ func (files Files) add(payee string, delta Delta) error {
|
|||||||
if delta.Currency != USD {
|
if delta.Currency != USD {
|
||||||
currencyValue = fmt.Sprintf("%.2f %s", delta.Value, delta.Currency)
|
currencyValue = fmt.Sprintf("%.2f %s", delta.Value, delta.Currency)
|
||||||
}
|
}
|
||||||
|
date := delta.Date
|
||||||
|
for _, otherDate := range delta.OtherDates {
|
||||||
|
date += "=" + otherDate
|
||||||
|
}
|
||||||
return files.append(fmt.Sprintf("%s %s\n%s%s%s%s\n%s%s",
|
return files.append(fmt.Sprintf("%s %s\n%s%s%s%s\n%s%s",
|
||||||
delta.Date, delta.Description,
|
date, delta.Description,
|
||||||
filesAppendDelim, delta.Name, filesAppendDelim+filesAppendDelim+filesAppendDelim, currencyValue,
|
filesAppendDelim, delta.Name, filesAppendDelim+filesAppendDelim+filesAppendDelim, currencyValue,
|
||||||
filesAppendDelim, payee,
|
filesAppendDelim, payee,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -73,12 +73,13 @@ func TestFileAmend(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"payee": {
|
"payee": {
|
||||||
from: `
|
from: `
|
||||||
2006-01-02 description
|
2006-01-02=2006-01-03 description
|
||||||
recipient $3.45
|
recipient $3.45
|
||||||
payee
|
payee
|
||||||
`,
|
`,
|
||||||
old: Delta{
|
old: Delta{
|
||||||
Date: "2006-01-02",
|
Date: "2006-01-02",
|
||||||
|
OtherDates: []string{"2006-01-03"},
|
||||||
Name: "payee",
|
Name: "payee",
|
||||||
Value: -3.45,
|
Value: -3.45,
|
||||||
Currency: "$",
|
Currency: "$",
|
||||||
@@ -86,16 +87,17 @@ func TestFileAmend(t *testing.T) {
|
|||||||
},
|
},
|
||||||
now: Delta{
|
now: Delta{
|
||||||
Date: "2106-11-12",
|
Date: "2106-11-12",
|
||||||
|
OtherDates: []string{"2006-01-03"},
|
||||||
Name: "1payee",
|
Name: "1payee",
|
||||||
Value: -13.45,
|
Value: -13.45,
|
||||||
Currency: "T",
|
Currency: "T",
|
||||||
Description: "1description",
|
Description: "1description",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
2006-01-02 description
|
2006-01-02=2006-01-03 description
|
||||||
payee $3.45
|
payee $3.45
|
||||||
recipient
|
recipient
|
||||||
2106-11-12 1description
|
2106-11-12=2006-01-03 1description
|
||||||
1payee -13.45 T
|
1payee -13.45 T
|
||||||
recipient`,
|
recipient`,
|
||||||
},
|
},
|
||||||
@@ -443,7 +445,7 @@ func TestFileDeltas(t *testing.T) {
|
|||||||
t.Error(deltas[i].Transaction)
|
t.Error(deltas[i].Transaction)
|
||||||
}
|
}
|
||||||
deltas[i].Transaction = ""
|
deltas[i].Transaction = ""
|
||||||
if want[i] != deltas[i] {
|
if !want[i].equivalent(deltas[i]) {
|
||||||
t.Errorf("[%d] \n\twant=%s, \n\t got=%s", i, want[i].Debug(), deltas[i].Debug())
|
t.Errorf("[%d] \n\twant=%s, \n\t got=%s", i, want[i].Debug(), deltas[i].Debug())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package ledger
|
package ledger
|
||||||
|
|
||||||
import "regexp"
|
import (
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
type Group func(Delta) Delta
|
type Group func(Delta) Delta
|
||||||
|
|
||||||
@@ -17,6 +19,9 @@ func GroupDate(pattern string) Group {
|
|||||||
p := regexp.MustCompile(pattern)
|
p := regexp.MustCompile(pattern)
|
||||||
return func(d Delta) Delta {
|
return func(d Delta) Delta {
|
||||||
d.Date = p.FindString(d.Date)
|
d.Date = p.FindString(d.Date)
|
||||||
|
for i := range d.with {
|
||||||
|
d.with[i].Date = p.FindString(d.with[i].Date)
|
||||||
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,6 +30,9 @@ func GroupName(pattern string) Group {
|
|||||||
p := regexp.MustCompile(pattern)
|
p := regexp.MustCompile(pattern)
|
||||||
return func(d Delta) Delta {
|
return func(d Delta) Delta {
|
||||||
d.Name = p.FindString(d.Name)
|
d.Name = p.FindString(d.Name)
|
||||||
|
for i := range d.with {
|
||||||
|
d.with[i].Name = p.FindString(d.with[i].Name)
|
||||||
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,21 @@ type Like func(Delta) bool
|
|||||||
|
|
||||||
type Likes []Like
|
type Likes []Like
|
||||||
|
|
||||||
|
func LikeWith(pattern string) Like {
|
||||||
|
l := LikeName(pattern)
|
||||||
|
return func(d Delta) bool {
|
||||||
|
if l(d) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, d := range d.with {
|
||||||
|
if l(d) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func LikeTransactions(deltas ...Delta) Like {
|
func LikeTransactions(deltas ...Delta) Like {
|
||||||
return func(d Delta) bool {
|
return func(d Delta) bool {
|
||||||
for i := range deltas {
|
for i := range deltas {
|
||||||
|
|||||||
@@ -36,3 +36,20 @@ func TestLikesAll(t *testing.T) {
|
|||||||
t.Error(likes.All(delta))
|
t.Error(likes.All(delta))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLikeWith(t *testing.T) {
|
||||||
|
delta := Delta{
|
||||||
|
Name: "x",
|
||||||
|
with: []Delta{
|
||||||
|
Delta{Name: "y"},
|
||||||
|
Delta{Name: "z"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !LikeWith("x")(delta) {
|
||||||
|
t.Error("like with self not caught")
|
||||||
|
}
|
||||||
|
if !LikeWith("z")(delta) {
|
||||||
|
t.Error("like with reverse not caught")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,8 +16,21 @@ import (
|
|||||||
|
|
||||||
type Transaction Deltas
|
type Transaction Deltas
|
||||||
|
|
||||||
|
func (t Transaction) Deltas() Deltas {
|
||||||
|
return Deltas(slices.Clone(t))
|
||||||
|
}
|
||||||
|
|
||||||
type Transactions []Transaction
|
type Transactions []Transaction
|
||||||
|
|
||||||
|
func (transactions Transactions) Lookup(delta Delta) Transaction {
|
||||||
|
for i := range transactions {
|
||||||
|
if transactions[i][0].Transaction == delta.Transaction {
|
||||||
|
return slices.Clone(transactions[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (transactions Transactions) Deltas() Deltas {
|
func (transactions Transactions) Deltas() Deltas {
|
||||||
result := make(Deltas, 0, len(transactions))
|
result := make(Deltas, 0, len(transactions))
|
||||||
for _, transaction := range transactions {
|
for _, transaction := range transactions {
|
||||||
@@ -106,6 +119,7 @@ func (transaction Transaction) Payee() string {
|
|||||||
|
|
||||||
type transaction struct {
|
type transaction struct {
|
||||||
date string
|
date string
|
||||||
|
otherDates []string
|
||||||
description string
|
description string
|
||||||
payee string
|
payee string
|
||||||
recipients []transactionRecipient
|
recipients []transactionRecipient
|
||||||
@@ -142,6 +156,7 @@ func (t transaction) deltas() Deltas {
|
|||||||
recipient.isSet,
|
recipient.isSet,
|
||||||
t.fileName,
|
t.fileName,
|
||||||
t.lineNo+i,
|
t.lineNo+i,
|
||||||
|
t.otherDates,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
for currency, value := range sums {
|
for currency, value := range sums {
|
||||||
@@ -162,9 +177,19 @@ func (t transaction) deltas() Deltas {
|
|||||||
false,
|
false,
|
||||||
t.fileName,
|
t.fileName,
|
||||||
t.lineNo,
|
t.lineNo,
|
||||||
|
t.otherDates,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := range result {
|
||||||
|
for j := range result {
|
||||||
|
if i != j {
|
||||||
|
result[i] = result[i].withWith(result[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,16 +303,17 @@ func _readTransaction(name string, r *bufio.Reader) (transaction, error) {
|
|||||||
return transaction{}, err
|
return transaction{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dateDescriptionPattern := regexp.MustCompile(`^([0-9]+-[0-9]+-[0-9]+)\s+(.*)$`)
|
dateDescriptionPattern := regexp.MustCompile(`^([0-9]+-[0-9]+-[0-9]+)((=[0-9]+-[0-9]+-[0-9]+)*)\s+(.*)$`)
|
||||||
dateDescriptionMatches := dateDescriptionPattern.FindAllSubmatch(firstLine, 4)
|
dateDescriptionMatches := dateDescriptionPattern.FindAllStringSubmatch(string(firstLine), 4)
|
||||||
if len(dateDescriptionMatches) != 1 {
|
if len(dateDescriptionMatches) != 1 {
|
||||||
return transaction{}, fmt.Errorf("bad first line: %v matches: %q", len(dateDescriptionMatches), firstLine)
|
return transaction{}, fmt.Errorf("bad first line: %v matches: %q", len(dateDescriptionMatches), firstLine)
|
||||||
} else if len(dateDescriptionMatches[0]) != 3 {
|
} else if len(dateDescriptionMatches[0]) != 5 {
|
||||||
return transaction{}, fmt.Errorf("bad first line: %v submatches: %q", len(dateDescriptionMatches[0]), firstLine)
|
return transaction{}, fmt.Errorf("bad first line: %v submatches: %q", len(dateDescriptionMatches[0]), firstLine)
|
||||||
}
|
}
|
||||||
result := transaction{
|
result := transaction{
|
||||||
date: string(dateDescriptionMatches[0][1]),
|
date: dateDescriptionMatches[0][1],
|
||||||
description: string(dateDescriptionMatches[0][2]),
|
otherDates: strings.Split(strings.Trim(dateDescriptionMatches[0][2], "="), "="),
|
||||||
|
description: dateDescriptionMatches[0][4],
|
||||||
name: name,
|
name: name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,12 +58,13 @@ func TestReadTransaction(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"verbose": {
|
"verbose": {
|
||||||
input: `
|
input: `
|
||||||
2003-04-05 Reasoning here
|
2003-04-05=2003-04-06=2003-04-07 Reasoning here
|
||||||
A:B $1.00
|
A:B $1.00
|
||||||
C:D $-1.00
|
C:D $-1.00
|
||||||
`,
|
`,
|
||||||
want: transaction{
|
want: transaction{
|
||||||
date: "2003-04-05",
|
date: "2003-04-05",
|
||||||
|
otherDates: []string{"2003-04-06", "2003-04-07"},
|
||||||
description: "Reasoning here",
|
description: "Reasoning here",
|
||||||
payee: "A:B",
|
payee: "A:B",
|
||||||
recipients: []transactionRecipient{
|
recipients: []transactionRecipient{
|
||||||
|
|||||||
18
vendor/github.com/guptarohit/asciigraph/.gitignore
generated
vendored
Normal file
18
vendor/github.com/guptarohit/asciigraph/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# ide
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# build dirs
|
||||||
|
*dist*
|
||||||
74
vendor/github.com/guptarohit/asciigraph/.goreleaser.yml
generated
vendored
Normal file
74
vendor/github.com/guptarohit/asciigraph/.goreleaser.yml
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Build customization
|
||||||
|
builds:
|
||||||
|
- env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
main: ./cmd/asciigraph/main.go
|
||||||
|
ldflags: '-s -w'
|
||||||
|
# GOOS list to build in.
|
||||||
|
# For more info refer to https://golang.org/doc/install/source#environment
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- darwin
|
||||||
|
- windows
|
||||||
|
# GOARCH to build in.
|
||||||
|
# For more info refer to https://golang.org/doc/install/source#environment
|
||||||
|
goarch:
|
||||||
|
- 386
|
||||||
|
- amd64
|
||||||
|
- arm
|
||||||
|
- arm64
|
||||||
|
ignore:
|
||||||
|
- goos: darwin
|
||||||
|
goarch: 386
|
||||||
|
checksum:
|
||||||
|
name_template: '{{ .ProjectName }}_{{ .Version }}_sha512-checksums.txt'
|
||||||
|
algorithm: sha512
|
||||||
|
# Archive customization
|
||||||
|
archives:
|
||||||
|
- id: tar
|
||||||
|
format: tar.gz
|
||||||
|
files:
|
||||||
|
- LICENSE
|
||||||
|
- README.md
|
||||||
|
name_template: >-
|
||||||
|
{{- .ProjectName }}_
|
||||||
|
{{- .Version }}_
|
||||||
|
{{- title .Os }}_
|
||||||
|
{{- if eq .Arch "amd64" }}x86_64
|
||||||
|
{{- else if eq .Arch "386" }}i386
|
||||||
|
{{- else }}{{ .Arch }}{{ end }}
|
||||||
|
{{- if .Arm }}v{{ .Arm }}{{ end -}}
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
format: zip
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- '^docs:'
|
||||||
|
- '^test:'
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: guptarohit
|
||||||
|
name: asciigraph
|
||||||
|
# If set to true, will not auto-publish the release.
|
||||||
|
# Default is false.
|
||||||
|
draft: true
|
||||||
|
dockers:
|
||||||
|
- image_templates:
|
||||||
|
- 'ghcr.io/guptarohit/asciigraph:{{ .Version }}'
|
||||||
|
- 'ghcr.io/guptarohit/asciigraph:{{ .Tag }}'
|
||||||
|
- 'ghcr.io/guptarohit/asciigraph:v{{ .Major }}'
|
||||||
|
- 'ghcr.io/guptarohit/asciigraph:v{{ .Major }}.{{ .Minor }}'
|
||||||
|
- 'ghcr.io/guptarohit/asciigraph:latest'
|
||||||
|
dockerfile: goreleaser.dockerfile
|
||||||
|
build_flag_templates:
|
||||||
|
- '--label=org.opencontainers.image.title={{ .ProjectName }}'
|
||||||
|
- '--label=org.opencontainers.image.name={{ .ProjectName }}'
|
||||||
|
- '--label=org.opencontainers.image.description=Go package to make lightweight line graphs ╭┈╯ in CLI'
|
||||||
|
- '--label=org.opencontainers.image.url=https://github.com/guptarohit/asciigraph'
|
||||||
|
- '--label=org.opencontainers.image.source=https://github.com/guptarohit/asciigraph'
|
||||||
|
- '--label=org.opencontainers.image.version={{ .Version }}'
|
||||||
|
- '--label=org.opencontainers.image.created={{ .Date }}'
|
||||||
|
- '--label=org.opencontainers.image.revision={{ .FullCommit }}'
|
||||||
|
- '--label=org.opencontainers.image.licenses=BSD-3-Clause'
|
||||||
113
vendor/github.com/guptarohit/asciigraph/CHANGELOG.md
generated
vendored
Normal file
113
vendor/github.com/guptarohit/asciigraph/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [0.7.3] - 2024-10-26
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Incorrect plot height calculation for small value ranges (#59)
|
||||||
|
|
||||||
|
## [0.7.2] - 2024-08-12
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Unintended modification of input data (#55)
|
||||||
|
|
||||||
|
## [0.7.1] - 2024-03-30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- CLI: Option to specify legends for series (`sl`)
|
||||||
|
|
||||||
|
## [0.7.0] - 2024-03-30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- CLI: Options to specify delimiter (`d`) and number of series (`sn`)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- CLI: Option (`sc`) to specify series colors
|
||||||
|
|
||||||
|
## [0.6.0] - 2024-03-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Option to add legends for colored graphs
|
||||||
|
|
||||||
|
## [0.5.6] - 2023-06-24
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Options to set upper & lower bound of graph
|
||||||
|
|
||||||
|
## [0.5.5] - 2022-05-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Ansi colors support for graphs
|
||||||
|
|
||||||
|
## [0.5.4] - 2022-05-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Option to plot multiple series together (#34)
|
||||||
|
- Dockerfile file support (#33)
|
||||||
|
|
||||||
|
## [0.5.3] - 2022-02-20
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Handled NaN first value (#32)
|
||||||
|
- Fixed incorrect y-axis start value tick (#31)
|
||||||
|
|
||||||
|
## [0.5.2] - 2021-03-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- added support to set custom precision of data point labels along the y-axis
|
||||||
|
- added go module support
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- updated README to markdown format
|
||||||
|
|
||||||
|
## [0.5.1] - 2020-09-14
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- added support for NaN values in series
|
||||||
|
- added option to control fps of plot rendering via cli for real-time data
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- removed use of append() method
|
||||||
|
- make caption centered
|
||||||
|
- removed trailing spaces from plot
|
||||||
|
|
||||||
|
## [0.5.0] - 2020-06-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- added support for the realtime plot of data points (from stdin) for CLI.
|
||||||
|
|
||||||
|
## [0.4.2] - 2020-06-07
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Prevent panics when data is flat. (#8)
|
||||||
|
- Prevent BADPREC issue when maximum and minimum values in a series are 0. (#10)
|
||||||
|
|
||||||
|
[0.7.2]: https://github.com/guptarohit/asciigraph/releases/tag/v0.7.2
|
||||||
|
[0.7.1]: https://github.com/guptarohit/asciigraph/releases/tag/v0.7.1
|
||||||
|
[0.7.0]: https://github.com/guptarohit/asciigraph/releases/tag/v0.7.0
|
||||||
|
[0.6.0]: https://github.com/guptarohit/asciigraph/releases/tag/v0.6.0
|
||||||
|
[0.5.6]: https://github.com/guptarohit/asciigraph/releases/tag/v0.5.6
|
||||||
|
[0.5.5]: https://github.com/guptarohit/asciigraph/releases/tag/v0.5.5
|
||||||
|
[0.5.4]: https://github.com/guptarohit/asciigraph/releases/tag/v0.5.4
|
||||||
|
[0.5.3]: https://github.com/guptarohit/asciigraph/releases/tag/v0.5.3
|
||||||
|
[0.5.2]: https://github.com/guptarohit/asciigraph/releases/tag/v0.5.2
|
||||||
|
[0.5.1]: https://github.com/guptarohit/asciigraph/releases/tag/v0.5.1
|
||||||
|
[0.5.0]: https://github.com/guptarohit/asciigraph/releases/tag/v0.5.0
|
||||||
|
[0.4.2]: https://github.com/guptarohit/asciigraph/releases/tag/v0.4.2
|
||||||
133
vendor/github.com/guptarohit/asciigraph/CODE_OF_CONDUCT.md
generated
vendored
Normal file
133
vendor/github.com/guptarohit/asciigraph/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||||
|
identity and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the overall
|
||||||
|
community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||||
|
any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email address,
|
||||||
|
without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
https://github.com/guptarohit.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series of
|
||||||
|
actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or permanent
|
||||||
|
ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||||
|
community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.1, available at
|
||||||
|
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by
|
||||||
|
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||||
|
[https://www.contributor-covenant.org/translations][translations].
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||||
|
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||||
|
[FAQ]: https://www.contributor-covenant.org/faq
|
||||||
|
[translations]: https://www.contributor-covenant.org/translations
|
||||||
10
vendor/github.com/guptarohit/asciigraph/Dockerfile
generated
vendored
Normal file
10
vendor/github.com/guptarohit/asciigraph/Dockerfile
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
FROM golang:1.23-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY cmd ./cmd
|
||||||
|
COPY go.mod ./
|
||||||
|
COPY *.go ./
|
||||||
|
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /app/asciigraph ./cmd/asciigraph/main.go
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=builder /app/asciigraph /asciigraph
|
||||||
|
ENTRYPOINT ["/asciigraph"]
|
||||||
29
vendor/github.com/guptarohit/asciigraph/LICENSE
generated
vendored
Normal file
29
vendor/github.com/guptarohit/asciigraph/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2018, Rohit Gupta
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
292
vendor/github.com/guptarohit/asciigraph/README.md
generated
vendored
Normal file
292
vendor/github.com/guptarohit/asciigraph/README.md
generated
vendored
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
# asciigraph
|
||||||
|
|
||||||
|
[![Build status][]][1] [![Go Report Card][]][2] [![Coverage Status][]][3] [![GoDoc][]][4] [![License][]][5] [![Mentioned in Awesome Go][]][6]
|
||||||
|
|
||||||
|
Go package to make lightweight ASCII line graphs ╭┈╯.
|
||||||
|
|
||||||
|
![image][]
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
```bash
|
||||||
|
go get -u github.com/guptarohit/asciigraph@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic graph
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/guptarohit/asciigraph"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := []float64{3, 4, 9, 6, 2, 4, 5, 8, 5, 10, 2, 7, 2, 5, 6}
|
||||||
|
graph := asciigraph.Plot(data)
|
||||||
|
|
||||||
|
fmt.Println(graph)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Running this example would render the following graph:
|
||||||
|
```bash
|
||||||
|
10.00 ┤ ╭╮
|
||||||
|
9.00 ┤ ╭╮ ││
|
||||||
|
8.00 ┤ ││ ╭╮││
|
||||||
|
7.00 ┤ ││ ││││╭╮
|
||||||
|
6.00 ┤ │╰╮ ││││││ ╭
|
||||||
|
5.00 ┤ │ │ ╭╯╰╯│││╭╯
|
||||||
|
4.00 ┤╭╯ │╭╯ ││││
|
||||||
|
3.00 ┼╯ ││ ││││
|
||||||
|
2.00 ┤ ╰╯ ╰╯╰╯
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Series
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/guptarohit/asciigraph"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := [][]float64{{0, 1, 2, 3, 3, 3, 2, 0}, {5, 4, 2, 1, 4, 6, 6}}
|
||||||
|
graph := asciigraph.PlotMany(data)
|
||||||
|
|
||||||
|
fmt.Println(graph)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Running this example would render the following graph:
|
||||||
|
```bash
|
||||||
|
6.00 ┤ ╭─
|
||||||
|
5.00 ┼╮ │
|
||||||
|
4.00 ┤╰╮ ╭╯
|
||||||
|
3.00 ┤ │╭│─╮
|
||||||
|
2.00 ┤ ╰╮│ ╰╮
|
||||||
|
1.00 ┤╭╯╰╯ │
|
||||||
|
0.00 ┼╯ ╰
|
||||||
|
```
|
||||||
|
|
||||||
|
### Colored graphs
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/guptarohit/asciigraph"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := make([][]float64, 4)
|
||||||
|
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
for x := -20; x <= 20; x++ {
|
||||||
|
v := math.NaN()
|
||||||
|
if r := 20 - i; x >= -r && x <= r {
|
||||||
|
v = math.Sqrt(math.Pow(float64(r), 2)-math.Pow(float64(x), 2)) / 2
|
||||||
|
}
|
||||||
|
data[i] = append(data[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graph := asciigraph.PlotMany(data, asciigraph.Precision(0), asciigraph.SeriesColors(
|
||||||
|
asciigraph.Red,
|
||||||
|
asciigraph.Yellow,
|
||||||
|
asciigraph.Green,
|
||||||
|
asciigraph.Blue,
|
||||||
|
))
|
||||||
|
|
||||||
|
fmt.Println(graph)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Running this example would render the following graph:
|
||||||
|
|
||||||
|
![colored_graph_image][]
|
||||||
|
|
||||||
|
### Legends for colored graphs
|
||||||
|
|
||||||
|
The graph can include legends for each series, making it easier to interpret.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/guptarohit/asciigraph"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := make([][]float64, 3)
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
for x := -12; x <= 12; x++ {
|
||||||
|
v := math.NaN()
|
||||||
|
if r := 12 - i; x >= -r && x <= r {
|
||||||
|
v = math.Sqrt(math.Pow(float64(r), 2)-math.Pow(float64(x), 2)) / 2
|
||||||
|
}
|
||||||
|
data[i] = append(data[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graph := asciigraph.PlotMany(data,
|
||||||
|
asciigraph.Precision(0),
|
||||||
|
asciigraph.SeriesColors(asciigraph.Red, asciigraph.Green, asciigraph.Blue),
|
||||||
|
asciigraph.SeriesLegends("Red", "Green", "Blue"),
|
||||||
|
asciigraph.Caption("Series with legends"))
|
||||||
|
fmt.Println(graph)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Running this example would render the following graph:
|
||||||
|
|
||||||
|
![graph_with_legends_image][]
|
||||||
|
|
||||||
|
|
||||||
|
## CLI Installation
|
||||||
|
|
||||||
|
This package also brings a small utility for command line usage.
|
||||||
|
|
||||||
|
Assuming `$GOPATH/bin` is in your `$PATH`, install CLI with following command:
|
||||||
|
```bash
|
||||||
|
go install github.com/guptarohit/asciigraph/cmd/asciigraph@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
or pull Docker image:
|
||||||
|
```bash
|
||||||
|
docker pull ghcr.io/guptarohit/asciigraph:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
or download binaries from the [releases][] page.
|
||||||
|
|
||||||
|
|
||||||
|
## CLI Usage
|
||||||
|
|
||||||
|
```bash ✘ 0|125 16:19:23
|
||||||
|
> asciigraph --help
|
||||||
|
Usage of asciigraph:
|
||||||
|
asciigraph [options]
|
||||||
|
Options:
|
||||||
|
-ac axis color
|
||||||
|
y-axis color of the plot
|
||||||
|
-b buffer
|
||||||
|
data points buffer when realtime graph enabled, default equal to `width`
|
||||||
|
-c caption
|
||||||
|
caption for the graph
|
||||||
|
-cc caption color
|
||||||
|
caption color of the plot
|
||||||
|
-d delimiter
|
||||||
|
data delimiter for splitting data points in the input stream (default ",")
|
||||||
|
-f fps
|
||||||
|
set fps to control how frequently graph to be rendered when realtime graph enabled (default 24)
|
||||||
|
-h height
|
||||||
|
height in text rows, 0 for auto-scaling
|
||||||
|
-lb lower bound
|
||||||
|
lower bound set the minimum value for the vertical axis (ignored if series contains lower values) (default +Inf)
|
||||||
|
-lc label color
|
||||||
|
y-axis label color of the plot
|
||||||
|
-o offset
|
||||||
|
offset in columns, for the label (default 3)
|
||||||
|
-p precision
|
||||||
|
precision of data point labels along the y-axis (default 2)
|
||||||
|
-r realtime
|
||||||
|
enables realtime graph for data stream
|
||||||
|
-sc series colors
|
||||||
|
comma-separated series colors corresponding to each series
|
||||||
|
-sl series legends
|
||||||
|
comma-separated series legends corresponding to each series
|
||||||
|
-sn number of series
|
||||||
|
number of series (columns) in the input data (default 1)
|
||||||
|
-ub upper bound
|
||||||
|
upper bound set the maximum value for the vertical axis (ignored if series contains larger values) (default -Inf)
|
||||||
|
-w width
|
||||||
|
width in columns, 0 for auto-scaling
|
||||||
|
asciigraph expects data points from stdin. Invalid values are logged to stderr.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Feed it data points via stdin:
|
||||||
|
```bash
|
||||||
|
seq 1 72 | asciigraph -h 10 -c "plot data from stdin"
|
||||||
|
```
|
||||||
|
|
||||||
|
or use Docker image:
|
||||||
|
```bash
|
||||||
|
seq 1 72 | docker run -i --rm ghcr.io/guptarohit/asciigraph -h 10 -c "plot data from stdin"
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
72.00 ┤ ╭────
|
||||||
|
64.90 ┤ ╭──────╯
|
||||||
|
57.80 ┤ ╭──────╯
|
||||||
|
50.70 ┤ ╭──────╯
|
||||||
|
43.60 ┤ ╭──────╯
|
||||||
|
36.50 ┤ ╭───────╯
|
||||||
|
29.40 ┤ ╭──────╯
|
||||||
|
22.30 ┤ ╭──────╯
|
||||||
|
15.20 ┤ ╭──────╯
|
||||||
|
8.10 ┤ ╭──────╯
|
||||||
|
1.00 ┼──╯
|
||||||
|
plot data from stdin
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Example of **real-time graph** for data points stream via stdin:
|
||||||
|
|
||||||
|
<a href="https://asciinema.org/a/382383" target="_blank"><img width="500" alt="Realtime graph for data points via stdin (google ping) using asciigraph" src="https://asciinema.org/a/382383.svg" /></a>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>command for above graph</summary>
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ping -i.2 google.com | grep -oP '(?<=time=).*(?=ms)' --line-buffered | asciigraph -r -h 10 -w 40 -c "realtime plot data (google ping in ms) from stdin"
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
Example of **multi-series real-time graph** for data points stream via stdin:
|
||||||
|
|
||||||
|
<a href="https://asciinema.org/a/649906" target="_blank"><img width="500" alt="Ping latency comparison: Google (Blue) vs. DuckDuckGo (Red) with asciigraph" src="https://asciinema.org/a/649906.svg" /></a>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>command for above graph</summary>
|
||||||
|
|
||||||
|
```sh
|
||||||
|
{unbuffer paste -d, <(ping -i 0.4 google.com | sed -u -n -E 's/.*time=(.*)ms.*/\1/p') <(ping -i 0.4 duckduckgo.com | sed -u -n -E 's/.*time=(.*)ms.*/\1/p') } | asciigraph -r -h 15 -w 60 -sn 2 -sc "blue,red" -c "Ping Latency Comparison" -sl "Google, DuckDuckGo"
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
## Acknowledgement
|
||||||
|
|
||||||
|
This package started as golang port of [asciichart][].
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Feel free to make a pull request! :octocat:
|
||||||
|
|
||||||
|
|
||||||
|
[Build status]: https://github.com/guptarohit/asciigraph/actions/workflows/test.yml/badge.svg
|
||||||
|
[1]: https://github.com/guptarohit/asciigraph/actions/workflows/test.yml
|
||||||
|
[Go Report Card]: https://goreportcard.com/badge/github.com/guptarohit/asciigraph
|
||||||
|
[2]: https://goreportcard.com/report/github.com/guptarohit/asciigraph
|
||||||
|
[Coverage Status]: https://coveralls.io/repos/github/guptarohit/asciigraph/badge.svg?branch=master
|
||||||
|
[3]: https://coveralls.io/github/guptarohit/asciigraph?branch=master
|
||||||
|
[GoDoc]: https://godoc.org/github.com/guptarohit/asciigraph?status.svg
|
||||||
|
[4]: https://godoc.org/github.com/guptarohit/asciigraph
|
||||||
|
[License]: https://img.shields.io/badge/licence-BSD-blue.svg
|
||||||
|
[5]: https://github.com/guptarohit/asciigraph/blob/master/LICENSE
|
||||||
|
[Mentioned in Awesome Go]: https://awesome.re/mentioned-badge-flat.svg
|
||||||
|
[6]: https://github.com/avelino/awesome-go#advanced-console-uis
|
||||||
|
[image]: https://user-images.githubusercontent.com/7895001/41509956-b1b2b3d0-7279-11e8-9d19-d7dea17d5e44.png
|
||||||
|
[colored_graph_image]: https://user-images.githubusercontent.com/7895001/166443444-40ad8113-2c0f-46d7-9c75-1cf08435ce15.png
|
||||||
|
[releases]: https://github.com/guptarohit/asciigraph/releases
|
||||||
|
[asciichart]: https://github.com/kroitor/asciichart
|
||||||
|
[graph_with_legends_image]: https://github.com/guptarohit/asciigraph/assets/7895001/4066ee95-55ca-42a4-8a03-e73ce20df5d3
|
||||||
265
vendor/github.com/guptarohit/asciigraph/asciigraph.go
generated
vendored
Normal file
265
vendor/github.com/guptarohit/asciigraph/asciigraph.go
generated
vendored
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
package asciigraph
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Plot returns ascii graph for a series.
|
||||||
|
func Plot(series []float64, options ...Option) string {
|
||||||
|
return PlotMany([][]float64{series}, options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlotMany returns ascii graph for multiple series.
|
||||||
|
func PlotMany(data [][]float64, options ...Option) string {
|
||||||
|
var logMaximum float64
|
||||||
|
config := configure(config{
|
||||||
|
Offset: 3,
|
||||||
|
Precision: 2,
|
||||||
|
}, options)
|
||||||
|
|
||||||
|
// Create a deep copy of the input data
|
||||||
|
dataCopy := make([][]float64, len(data))
|
||||||
|
for i, series := range data {
|
||||||
|
dataCopy[i] = make([]float64, len(series))
|
||||||
|
copy(dataCopy[i], series)
|
||||||
|
}
|
||||||
|
data = dataCopy
|
||||||
|
|
||||||
|
lenMax := 0
|
||||||
|
for i := range data {
|
||||||
|
if l := len(data[i]); l > lenMax {
|
||||||
|
lenMax = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Width > 0 {
|
||||||
|
for i := range data {
|
||||||
|
for j := len(data[i]); j < lenMax; j++ {
|
||||||
|
data[i] = append(data[i], math.NaN())
|
||||||
|
}
|
||||||
|
data[i] = interpolateArray(data[i], config.Width)
|
||||||
|
}
|
||||||
|
|
||||||
|
lenMax = config.Width
|
||||||
|
}
|
||||||
|
|
||||||
|
minimum, maximum := math.Inf(1), math.Inf(-1)
|
||||||
|
for i := range data {
|
||||||
|
minVal, maxVal := minMaxFloat64Slice(data[i])
|
||||||
|
if minVal < minimum {
|
||||||
|
minimum = minVal
|
||||||
|
}
|
||||||
|
if maxVal > maximum {
|
||||||
|
maximum = maxVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if config.LowerBound != nil && *config.LowerBound < minimum {
|
||||||
|
minimum = *config.LowerBound
|
||||||
|
}
|
||||||
|
if config.UpperBound != nil && *config.UpperBound > maximum {
|
||||||
|
maximum = *config.UpperBound
|
||||||
|
}
|
||||||
|
interval := math.Abs(maximum - minimum)
|
||||||
|
|
||||||
|
if config.Height <= 0 {
|
||||||
|
config.Height = calculateHeight(interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Offset <= 0 {
|
||||||
|
config.Offset = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
var ratio float64
|
||||||
|
if interval != 0 {
|
||||||
|
ratio = float64(config.Height) / interval
|
||||||
|
} else {
|
||||||
|
ratio = 1
|
||||||
|
}
|
||||||
|
min2 := round(minimum * ratio)
|
||||||
|
max2 := round(maximum * ratio)
|
||||||
|
|
||||||
|
intmin2 := int(min2)
|
||||||
|
intmax2 := int(max2)
|
||||||
|
|
||||||
|
rows := int(math.Abs(float64(intmax2 - intmin2)))
|
||||||
|
width := lenMax + config.Offset
|
||||||
|
|
||||||
|
type cell struct {
|
||||||
|
Text string
|
||||||
|
Color AnsiColor
|
||||||
|
}
|
||||||
|
plot := make([][]cell, rows+1)
|
||||||
|
|
||||||
|
// initialise empty 2D grid
|
||||||
|
for i := 0; i < rows+1; i++ {
|
||||||
|
line := make([]cell, width)
|
||||||
|
for j := 0; j < width; j++ {
|
||||||
|
line[j].Text = " "
|
||||||
|
line[j].Color = Default
|
||||||
|
}
|
||||||
|
plot[i] = line
|
||||||
|
}
|
||||||
|
|
||||||
|
precision := config.Precision
|
||||||
|
logMaximum = math.Log10(math.Max(math.Abs(maximum), math.Abs(minimum))) //to find number of zeros after decimal
|
||||||
|
if minimum == float64(0) && maximum == float64(0) {
|
||||||
|
logMaximum = float64(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if logMaximum < 0 {
|
||||||
|
// negative log
|
||||||
|
if math.Mod(logMaximum, 1) != 0 {
|
||||||
|
// non-zero digits after decimal
|
||||||
|
precision += uint(math.Abs(logMaximum))
|
||||||
|
} else {
|
||||||
|
precision += uint(math.Abs(logMaximum) - 1.0)
|
||||||
|
}
|
||||||
|
} else if logMaximum > 2 {
|
||||||
|
precision = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
maxNumLength := len(fmt.Sprintf("%0.*f", precision, maximum))
|
||||||
|
minNumLength := len(fmt.Sprintf("%0.*f", precision, minimum))
|
||||||
|
maxWidth := int(math.Max(float64(maxNumLength), float64(minNumLength)))
|
||||||
|
|
||||||
|
// axis and labels
|
||||||
|
for y := intmin2; y < intmax2+1; y++ {
|
||||||
|
var magnitude float64
|
||||||
|
if rows > 0 {
|
||||||
|
magnitude = maximum - (float64(y-intmin2) * interval / float64(rows))
|
||||||
|
} else {
|
||||||
|
magnitude = float64(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
label := fmt.Sprintf("%*.*f", maxWidth+1, precision, magnitude)
|
||||||
|
w := y - intmin2
|
||||||
|
h := int(math.Max(float64(config.Offset)-float64(len(label)), 0))
|
||||||
|
|
||||||
|
plot[w][h].Text = label
|
||||||
|
plot[w][h].Color = config.LabelColor
|
||||||
|
plot[w][config.Offset-1].Text = "┤"
|
||||||
|
plot[w][config.Offset-1].Color = config.AxisColor
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range data {
|
||||||
|
series := data[i]
|
||||||
|
|
||||||
|
color := Default
|
||||||
|
if i < len(config.SeriesColors) {
|
||||||
|
color = config.SeriesColors[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
var y0, y1 int
|
||||||
|
|
||||||
|
if !math.IsNaN(series[0]) {
|
||||||
|
y0 = int(round(series[0]*ratio) - min2)
|
||||||
|
plot[rows-y0][config.Offset-1].Text = "┼" // first value
|
||||||
|
plot[rows-y0][config.Offset-1].Color = config.AxisColor
|
||||||
|
}
|
||||||
|
|
||||||
|
for x := 0; x < len(series)-1; x++ { // plot the line
|
||||||
|
d0 := series[x]
|
||||||
|
d1 := series[x+1]
|
||||||
|
|
||||||
|
if math.IsNaN(d0) && math.IsNaN(d1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if math.IsNaN(d1) && !math.IsNaN(d0) {
|
||||||
|
y0 = int(round(d0*ratio) - float64(intmin2))
|
||||||
|
plot[rows-y0][x+config.Offset].Text = "╴"
|
||||||
|
plot[rows-y0][x+config.Offset].Color = color
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if math.IsNaN(d0) && !math.IsNaN(d1) {
|
||||||
|
y1 = int(round(d1*ratio) - float64(intmin2))
|
||||||
|
plot[rows-y1][x+config.Offset].Text = "╶"
|
||||||
|
plot[rows-y1][x+config.Offset].Color = color
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
y0 = int(round(d0*ratio) - float64(intmin2))
|
||||||
|
y1 = int(round(d1*ratio) - float64(intmin2))
|
||||||
|
|
||||||
|
if y0 == y1 {
|
||||||
|
plot[rows-y0][x+config.Offset].Text = "─"
|
||||||
|
} else {
|
||||||
|
if y0 > y1 {
|
||||||
|
plot[rows-y1][x+config.Offset].Text = "╰"
|
||||||
|
plot[rows-y0][x+config.Offset].Text = "╮"
|
||||||
|
} else {
|
||||||
|
plot[rows-y1][x+config.Offset].Text = "╭"
|
||||||
|
plot[rows-y0][x+config.Offset].Text = "╯"
|
||||||
|
}
|
||||||
|
|
||||||
|
start := int(math.Min(float64(y0), float64(y1))) + 1
|
||||||
|
end := int(math.Max(float64(y0), float64(y1)))
|
||||||
|
for y := start; y < end; y++ {
|
||||||
|
plot[rows-y][x+config.Offset].Text = "│"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start := int(math.Min(float64(y0), float64(y1)))
|
||||||
|
end := int(math.Max(float64(y0), float64(y1)))
|
||||||
|
for y := start; y <= end; y++ {
|
||||||
|
plot[rows-y][x+config.Offset].Color = color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// join columns
|
||||||
|
var lines bytes.Buffer
|
||||||
|
for h, horizontal := range plot {
|
||||||
|
if h != 0 {
|
||||||
|
lines.WriteRune('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove trailing spaces
|
||||||
|
lastCharIndex := 0
|
||||||
|
for i := width - 1; i >= 0; i-- {
|
||||||
|
if horizontal[i].Text != " " {
|
||||||
|
lastCharIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c := Default
|
||||||
|
for _, v := range horizontal[:lastCharIndex+1] {
|
||||||
|
if v.Color != c {
|
||||||
|
c = v.Color
|
||||||
|
lines.WriteString(c.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.WriteString(v.Text)
|
||||||
|
}
|
||||||
|
if c != Default {
|
||||||
|
lines.WriteString(Default.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add caption if not empty
|
||||||
|
if config.Caption != "" {
|
||||||
|
lines.WriteRune('\n')
|
||||||
|
lines.WriteString(strings.Repeat(" ", config.Offset+maxWidth))
|
||||||
|
if len(config.Caption) < lenMax {
|
||||||
|
lines.WriteString(strings.Repeat(" ", (lenMax-len(config.Caption))/2))
|
||||||
|
}
|
||||||
|
if config.CaptionColor != Default {
|
||||||
|
lines.WriteString(config.CaptionColor.String())
|
||||||
|
}
|
||||||
|
lines.WriteString(config.Caption)
|
||||||
|
if config.CaptionColor != Default {
|
||||||
|
lines.WriteString(Default.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.SeriesLegends) > 0 {
|
||||||
|
addLegends(&lines, config, lenMax, config.Offset+maxWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.String()
|
||||||
|
}
|
||||||
312
vendor/github.com/guptarohit/asciigraph/color.go
generated
vendored
Normal file
312
vendor/github.com/guptarohit/asciigraph/color.go
generated
vendored
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
package asciigraph
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type AnsiColor byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
Default AnsiColor = 0
|
||||||
|
AliceBlue AnsiColor = 255
|
||||||
|
AntiqueWhite AnsiColor = 255
|
||||||
|
Aqua AnsiColor = 14
|
||||||
|
Aquamarine AnsiColor = 122
|
||||||
|
Azure AnsiColor = 15
|
||||||
|
Beige AnsiColor = 230
|
||||||
|
Bisque AnsiColor = 224
|
||||||
|
Black AnsiColor = 188 // dummy value
|
||||||
|
BlanchedAlmond AnsiColor = 230
|
||||||
|
Blue AnsiColor = 12
|
||||||
|
BlueViolet AnsiColor = 92
|
||||||
|
Brown AnsiColor = 88
|
||||||
|
BurlyWood AnsiColor = 180
|
||||||
|
CadetBlue AnsiColor = 73
|
||||||
|
Chartreuse AnsiColor = 118
|
||||||
|
Chocolate AnsiColor = 166
|
||||||
|
Coral AnsiColor = 209
|
||||||
|
CornflowerBlue AnsiColor = 68
|
||||||
|
Cornsilk AnsiColor = 230
|
||||||
|
Crimson AnsiColor = 161
|
||||||
|
Cyan AnsiColor = 14
|
||||||
|
DarkBlue AnsiColor = 18
|
||||||
|
DarkCyan AnsiColor = 30
|
||||||
|
DarkGoldenrod AnsiColor = 136
|
||||||
|
DarkGray AnsiColor = 248
|
||||||
|
DarkGreen AnsiColor = 22
|
||||||
|
DarkKhaki AnsiColor = 143
|
||||||
|
DarkMagenta AnsiColor = 90
|
||||||
|
DarkOliveGreen AnsiColor = 59
|
||||||
|
DarkOrange AnsiColor = 208
|
||||||
|
DarkOrchid AnsiColor = 134
|
||||||
|
DarkRed AnsiColor = 88
|
||||||
|
DarkSalmon AnsiColor = 173
|
||||||
|
DarkSeaGreen AnsiColor = 108
|
||||||
|
DarkSlateBlue AnsiColor = 60
|
||||||
|
DarkSlateGray AnsiColor = 238
|
||||||
|
DarkTurquoise AnsiColor = 44
|
||||||
|
DarkViolet AnsiColor = 92
|
||||||
|
DeepPink AnsiColor = 198
|
||||||
|
DeepSkyBlue AnsiColor = 39
|
||||||
|
DimGray AnsiColor = 242
|
||||||
|
DodgerBlue AnsiColor = 33
|
||||||
|
Firebrick AnsiColor = 124
|
||||||
|
FloralWhite AnsiColor = 15
|
||||||
|
ForestGreen AnsiColor = 28
|
||||||
|
Fuchsia AnsiColor = 13
|
||||||
|
Gainsboro AnsiColor = 253
|
||||||
|
GhostWhite AnsiColor = 15
|
||||||
|
Gold AnsiColor = 220
|
||||||
|
Goldenrod AnsiColor = 178
|
||||||
|
Gray AnsiColor = 8
|
||||||
|
Green AnsiColor = 2
|
||||||
|
GreenYellow AnsiColor = 155
|
||||||
|
Honeydew AnsiColor = 15
|
||||||
|
HotPink AnsiColor = 205
|
||||||
|
IndianRed AnsiColor = 167
|
||||||
|
Indigo AnsiColor = 54
|
||||||
|
Ivory AnsiColor = 15
|
||||||
|
Khaki AnsiColor = 222
|
||||||
|
Lavender AnsiColor = 254
|
||||||
|
LavenderBlush AnsiColor = 255
|
||||||
|
LawnGreen AnsiColor = 118
|
||||||
|
LemonChiffon AnsiColor = 230
|
||||||
|
LightBlue AnsiColor = 152
|
||||||
|
LightCoral AnsiColor = 210
|
||||||
|
LightCyan AnsiColor = 195
|
||||||
|
LightGoldenrodYellow AnsiColor = 230
|
||||||
|
LightGray AnsiColor = 252
|
||||||
|
LightGreen AnsiColor = 120
|
||||||
|
LightPink AnsiColor = 217
|
||||||
|
LightSalmon AnsiColor = 216
|
||||||
|
LightSeaGreen AnsiColor = 37
|
||||||
|
LightSkyBlue AnsiColor = 117
|
||||||
|
LightSlateGray AnsiColor = 103
|
||||||
|
LightSteelBlue AnsiColor = 152
|
||||||
|
LightYellow AnsiColor = 230
|
||||||
|
Lime AnsiColor = 10
|
||||||
|
LimeGreen AnsiColor = 77
|
||||||
|
Linen AnsiColor = 255
|
||||||
|
Magenta AnsiColor = 13
|
||||||
|
Maroon AnsiColor = 1
|
||||||
|
MediumAquamarine AnsiColor = 79
|
||||||
|
MediumBlue AnsiColor = 20
|
||||||
|
MediumOrchid AnsiColor = 134
|
||||||
|
MediumPurple AnsiColor = 98
|
||||||
|
MediumSeaGreen AnsiColor = 72
|
||||||
|
MediumSlateBlue AnsiColor = 99
|
||||||
|
MediumSpringGreen AnsiColor = 48
|
||||||
|
MediumTurquoise AnsiColor = 80
|
||||||
|
MediumVioletRed AnsiColor = 162
|
||||||
|
MidnightBlue AnsiColor = 17
|
||||||
|
MintCream AnsiColor = 15
|
||||||
|
MistyRose AnsiColor = 224
|
||||||
|
Moccasin AnsiColor = 223
|
||||||
|
NavajoWhite AnsiColor = 223
|
||||||
|
Navy AnsiColor = 4
|
||||||
|
OldLace AnsiColor = 230
|
||||||
|
Olive AnsiColor = 3
|
||||||
|
OliveDrab AnsiColor = 64
|
||||||
|
Orange AnsiColor = 214
|
||||||
|
OrangeRed AnsiColor = 202
|
||||||
|
Orchid AnsiColor = 170
|
||||||
|
PaleGoldenrod AnsiColor = 223
|
||||||
|
PaleGreen AnsiColor = 120
|
||||||
|
PaleTurquoise AnsiColor = 159
|
||||||
|
PaleVioletRed AnsiColor = 168
|
||||||
|
PapayaWhip AnsiColor = 230
|
||||||
|
PeachPuff AnsiColor = 223
|
||||||
|
Peru AnsiColor = 173
|
||||||
|
Pink AnsiColor = 218
|
||||||
|
Plum AnsiColor = 182
|
||||||
|
PowderBlue AnsiColor = 152
|
||||||
|
Purple AnsiColor = 5
|
||||||
|
Red AnsiColor = 9
|
||||||
|
RosyBrown AnsiColor = 138
|
||||||
|
RoyalBlue AnsiColor = 63
|
||||||
|
SaddleBrown AnsiColor = 94
|
||||||
|
Salmon AnsiColor = 210
|
||||||
|
SandyBrown AnsiColor = 215
|
||||||
|
SeaGreen AnsiColor = 29
|
||||||
|
SeaShell AnsiColor = 15
|
||||||
|
Sienna AnsiColor = 131
|
||||||
|
Silver AnsiColor = 7
|
||||||
|
SkyBlue AnsiColor = 117
|
||||||
|
SlateBlue AnsiColor = 62
|
||||||
|
SlateGray AnsiColor = 66
|
||||||
|
Snow AnsiColor = 15
|
||||||
|
SpringGreen AnsiColor = 48
|
||||||
|
SteelBlue AnsiColor = 67
|
||||||
|
Tan AnsiColor = 180
|
||||||
|
Teal AnsiColor = 6
|
||||||
|
Thistle AnsiColor = 182
|
||||||
|
Tomato AnsiColor = 203
|
||||||
|
Turquoise AnsiColor = 80
|
||||||
|
Violet AnsiColor = 213
|
||||||
|
Wheat AnsiColor = 223
|
||||||
|
White AnsiColor = 15
|
||||||
|
WhiteSmoke AnsiColor = 255
|
||||||
|
Yellow AnsiColor = 11
|
||||||
|
YellowGreen AnsiColor = 149
|
||||||
|
)
|
||||||
|
|
||||||
|
var ColorNames = map[string]AnsiColor{
|
||||||
|
"default": Default,
|
||||||
|
"aliceblue": AliceBlue,
|
||||||
|
"antiquewhite": AntiqueWhite,
|
||||||
|
"aqua": Aqua,
|
||||||
|
"aquamarine": Aquamarine,
|
||||||
|
"azure": Azure,
|
||||||
|
"beige": Beige,
|
||||||
|
"bisque": Bisque,
|
||||||
|
"black": Black,
|
||||||
|
"blanchedalmond": BlanchedAlmond,
|
||||||
|
"blue": Blue,
|
||||||
|
"blueviolet": BlueViolet,
|
||||||
|
"brown": Brown,
|
||||||
|
"burlywood": BurlyWood,
|
||||||
|
"cadetblue": CadetBlue,
|
||||||
|
"chartreuse": Chartreuse,
|
||||||
|
"chocolate": Chocolate,
|
||||||
|
"coral": Coral,
|
||||||
|
"cornflowerblue": CornflowerBlue,
|
||||||
|
"cornsilk": Cornsilk,
|
||||||
|
"crimson": Crimson,
|
||||||
|
"cyan": Cyan,
|
||||||
|
"darkblue": DarkBlue,
|
||||||
|
"darkcyan": DarkCyan,
|
||||||
|
"darkgoldenrod": DarkGoldenrod,
|
||||||
|
"darkgray": DarkGray,
|
||||||
|
"darkgreen": DarkGreen,
|
||||||
|
"darkkhaki": DarkKhaki,
|
||||||
|
"darkmagenta": DarkMagenta,
|
||||||
|
"darkolivegreen": DarkOliveGreen,
|
||||||
|
"darkorange": DarkOrange,
|
||||||
|
"darkorchid": DarkOrchid,
|
||||||
|
"darkred": DarkRed,
|
||||||
|
"darksalmon": DarkSalmon,
|
||||||
|
"darkseagreen": DarkSeaGreen,
|
||||||
|
"darkslateblue": DarkSlateBlue,
|
||||||
|
"darkslategray": DarkSlateGray,
|
||||||
|
"darkturquoise": DarkTurquoise,
|
||||||
|
"darkviolet": DarkViolet,
|
||||||
|
"deeppink": DeepPink,
|
||||||
|
"deepskyblue": DeepSkyBlue,
|
||||||
|
"dimgray": DimGray,
|
||||||
|
"dodgerblue": DodgerBlue,
|
||||||
|
"firebrick": Firebrick,
|
||||||
|
"floralwhite": FloralWhite,
|
||||||
|
"forestgreen": ForestGreen,
|
||||||
|
"fuchsia": Fuchsia,
|
||||||
|
"gainsboro": Gainsboro,
|
||||||
|
"ghostwhite": GhostWhite,
|
||||||
|
"gold": Gold,
|
||||||
|
"goldenrod": Goldenrod,
|
||||||
|
"gray": Gray,
|
||||||
|
"green": Green,
|
||||||
|
"greenyellow": GreenYellow,
|
||||||
|
"honeydew": Honeydew,
|
||||||
|
"hotpink": HotPink,
|
||||||
|
"indianred": IndianRed,
|
||||||
|
"indigo": Indigo,
|
||||||
|
"ivory": Ivory,
|
||||||
|
"khaki": Khaki,
|
||||||
|
"lavender": Lavender,
|
||||||
|
"lavenderblush": LavenderBlush,
|
||||||
|
"lawngreen": LawnGreen,
|
||||||
|
"lemonchiffon": LemonChiffon,
|
||||||
|
"lightblue": LightBlue,
|
||||||
|
"lightcoral": LightCoral,
|
||||||
|
"lightcyan": LightCyan,
|
||||||
|
"lightgoldenrodyellow": LightGoldenrodYellow,
|
||||||
|
"lightgray": LightGray,
|
||||||
|
"lightgreen": LightGreen,
|
||||||
|
"lightpink": LightPink,
|
||||||
|
"lightsalmon": LightSalmon,
|
||||||
|
"lightseagreen": LightSeaGreen,
|
||||||
|
"lightskyblue": LightSkyBlue,
|
||||||
|
"lightslategray": LightSlateGray,
|
||||||
|
"lightsteelblue": LightSteelBlue,
|
||||||
|
"lightyellow": LightYellow,
|
||||||
|
"lime": Lime,
|
||||||
|
"limegreen": LimeGreen,
|
||||||
|
"linen": Linen,
|
||||||
|
"magenta": Magenta,
|
||||||
|
"maroon": Maroon,
|
||||||
|
"mediumaquamarine": MediumAquamarine,
|
||||||
|
"mediumblue": MediumBlue,
|
||||||
|
"mediumorchid": MediumOrchid,
|
||||||
|
"mediumpurple": MediumPurple,
|
||||||
|
"mediumseagreen": MediumSeaGreen,
|
||||||
|
"mediumslateblue": MediumSlateBlue,
|
||||||
|
"mediumspringgreen": MediumSpringGreen,
|
||||||
|
"mediumturquoise": MediumTurquoise,
|
||||||
|
"mediumvioletred": MediumVioletRed,
|
||||||
|
"midnightblue": MidnightBlue,
|
||||||
|
"mintcream": MintCream,
|
||||||
|
"mistyrose": MistyRose,
|
||||||
|
"moccasin": Moccasin,
|
||||||
|
"navajowhite": NavajoWhite,
|
||||||
|
"navy": Navy,
|
||||||
|
"oldlace": OldLace,
|
||||||
|
"olive": Olive,
|
||||||
|
"olivedrab": OliveDrab,
|
||||||
|
"orange": Orange,
|
||||||
|
"orangered": OrangeRed,
|
||||||
|
"orchid": Orchid,
|
||||||
|
"palegoldenrod": PaleGoldenrod,
|
||||||
|
"palegreen": PaleGreen,
|
||||||
|
"paleturquoise": PaleTurquoise,
|
||||||
|
"palevioletred": PaleVioletRed,
|
||||||
|
"papayawhip": PapayaWhip,
|
||||||
|
"peachpuff": PeachPuff,
|
||||||
|
"peru": Peru,
|
||||||
|
"pink": Pink,
|
||||||
|
"plum": Plum,
|
||||||
|
"powderblue": PowderBlue,
|
||||||
|
"purple": Purple,
|
||||||
|
"red": Red,
|
||||||
|
"rosybrown": RosyBrown,
|
||||||
|
"royalblue": RoyalBlue,
|
||||||
|
"saddlebrown": SaddleBrown,
|
||||||
|
"salmon": Salmon,
|
||||||
|
"sandybrown": SandyBrown,
|
||||||
|
"seagreen": SeaGreen,
|
||||||
|
"seashell": SeaShell,
|
||||||
|
"sienna": Sienna,
|
||||||
|
"silver": Silver,
|
||||||
|
"skyblue": SkyBlue,
|
||||||
|
"slateblue": SlateBlue,
|
||||||
|
"slategray": SlateGray,
|
||||||
|
"snow": Snow,
|
||||||
|
"springgreen": SpringGreen,
|
||||||
|
"steelblue": SteelBlue,
|
||||||
|
"tan": Tan,
|
||||||
|
"teal": Teal,
|
||||||
|
"thistle": Thistle,
|
||||||
|
"tomato": Tomato,
|
||||||
|
"turquoise": Turquoise,
|
||||||
|
"violet": Violet,
|
||||||
|
"wheat": Wheat,
|
||||||
|
"white": White,
|
||||||
|
"whitesmoke": WhiteSmoke,
|
||||||
|
"yellow": Yellow,
|
||||||
|
"yellowgreen": YellowGreen,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c AnsiColor) String() string {
|
||||||
|
if c == Default {
|
||||||
|
return "\x1b[0m"
|
||||||
|
}
|
||||||
|
if c == Black {
|
||||||
|
c = 0
|
||||||
|
}
|
||||||
|
if c <= Silver {
|
||||||
|
// 3-bit color
|
||||||
|
return fmt.Sprintf("\x1b[%dm", 30+byte(c))
|
||||||
|
}
|
||||||
|
if c <= White {
|
||||||
|
// 4-bit color
|
||||||
|
return fmt.Sprintf("\x1b[%dm", 82+byte(c))
|
||||||
|
}
|
||||||
|
// 8-bit color
|
||||||
|
return fmt.Sprintf("\x1b[38;5;%dm", byte(c))
|
||||||
|
}
|
||||||
3
vendor/github.com/guptarohit/asciigraph/goreleaser.dockerfile
generated
vendored
Normal file
3
vendor/github.com/guptarohit/asciigraph/goreleaser.dockerfile
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
FROM scratch
|
||||||
|
COPY asciigraph /asciigraph
|
||||||
|
ENTRYPOINT ["/asciigraph"]
|
||||||
45
vendor/github.com/guptarohit/asciigraph/legend.go
generated
vendored
Normal file
45
vendor/github.com/guptarohit/asciigraph/legend.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package asciigraph
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create legend item as a colored box and text
|
||||||
|
func createLegendItem(text string, color AnsiColor) (string, int) {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"%s■%s %s",
|
||||||
|
color.String(),
|
||||||
|
Default.String(),
|
||||||
|
text,
|
||||||
|
),
|
||||||
|
// Can't use len() because of AnsiColor, add 2 for box and space
|
||||||
|
utf8.RuneCountInString(text) + 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add legend for each series added to the graph
|
||||||
|
func addLegends(lines *bytes.Buffer, config *config, lenMax int, leftPad int) {
|
||||||
|
lines.WriteString("\n\n")
|
||||||
|
lines.WriteString(strings.Repeat(" ", leftPad))
|
||||||
|
|
||||||
|
var legendsText string
|
||||||
|
var legendsTextLen int
|
||||||
|
rightPad := 3
|
||||||
|
for i, text := range config.SeriesLegends {
|
||||||
|
item, itemLen := createLegendItem(text, config.SeriesColors[i])
|
||||||
|
legendsText += item
|
||||||
|
legendsTextLen += itemLen
|
||||||
|
|
||||||
|
if i < len(config.SeriesLegends)-1 {
|
||||||
|
legendsText += strings.Repeat(" ", rightPad)
|
||||||
|
legendsTextLen += rightPad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if legendsTextLen < lenMax {
|
||||||
|
lines.WriteString(strings.Repeat(" ", (lenMax-legendsTextLen)/2))
|
||||||
|
}
|
||||||
|
lines.WriteString(legendsText)
|
||||||
|
}
|
||||||
126
vendor/github.com/guptarohit/asciigraph/options.go
generated
vendored
Normal file
126
vendor/github.com/guptarohit/asciigraph/options.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package asciigraph
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option represents a configuration setting.
|
||||||
|
type Option interface {
|
||||||
|
apply(c *config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// config holds various graph options
|
||||||
|
type config struct {
|
||||||
|
Width, Height int
|
||||||
|
LowerBound, UpperBound *float64
|
||||||
|
Offset int
|
||||||
|
Caption string
|
||||||
|
Precision uint
|
||||||
|
CaptionColor AnsiColor
|
||||||
|
AxisColor AnsiColor
|
||||||
|
LabelColor AnsiColor
|
||||||
|
SeriesColors []AnsiColor
|
||||||
|
SeriesLegends []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optionFunc applies an option.
|
||||||
|
type optionFunc func(*config)
|
||||||
|
|
||||||
|
// apply implements the Option interface.
|
||||||
|
func (of optionFunc) apply(c *config) { of(c) }
|
||||||
|
|
||||||
|
func configure(defaults config, options []Option) *config {
|
||||||
|
for _, o := range options {
|
||||||
|
o.apply(&defaults)
|
||||||
|
}
|
||||||
|
return &defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width sets the graphs width. By default, the width of the graph is
|
||||||
|
// determined by the number of data points. If the value given is a
|
||||||
|
// positive number, the data points are interpolated on the x axis.
|
||||||
|
// Values <= 0 reset the width to the default value.
|
||||||
|
func Width(w int) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
if w > 0 {
|
||||||
|
c.Width = w
|
||||||
|
} else {
|
||||||
|
c.Width = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Height sets the graphs height.
|
||||||
|
func Height(h int) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
if h > 0 {
|
||||||
|
c.Height = h
|
||||||
|
} else {
|
||||||
|
c.Height = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// LowerBound sets the graph's minimum value for the vertical axis. It will be ignored
|
||||||
|
// if the series contains a lower value.
|
||||||
|
func LowerBound(min float64) Option {
|
||||||
|
return optionFunc(func(c *config) { c.LowerBound = &min })
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpperBound sets the graph's maximum value for the vertical axis. It will be ignored
|
||||||
|
// if the series contains a bigger value.
|
||||||
|
func UpperBound(max float64) Option {
|
||||||
|
return optionFunc(func(c *config) { c.UpperBound = &max })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset sets the graphs offset.
|
||||||
|
func Offset(o int) Option {
|
||||||
|
return optionFunc(func(c *config) { c.Offset = o })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precision sets the graphs precision.
|
||||||
|
func Precision(p uint) Option {
|
||||||
|
return optionFunc(func(c *config) { c.Precision = p })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caption sets the graphs caption.
|
||||||
|
func Caption(caption string) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
c.Caption = strings.TrimSpace(caption)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptionColor sets the caption color.
|
||||||
|
func CaptionColor(ac AnsiColor) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
c.CaptionColor = ac
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AxisColor sets the axis color.
|
||||||
|
func AxisColor(ac AnsiColor) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
c.AxisColor = ac
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabelColor sets the axis label color.
|
||||||
|
func LabelColor(ac AnsiColor) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
c.LabelColor = ac
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SeriesColors sets the series colors.
|
||||||
|
func SeriesColors(ac ...AnsiColor) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
c.SeriesColors = ac
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SeriesLegends sets the legend text for the corresponding series.
|
||||||
|
func SeriesLegends(text ...string) Option {
|
||||||
|
return optionFunc(func(c *config) {
|
||||||
|
c.SeriesLegends = text
|
||||||
|
})
|
||||||
|
}
|
||||||
105
vendor/github.com/guptarohit/asciigraph/utils.go
generated
vendored
Normal file
105
vendor/github.com/guptarohit/asciigraph/utils.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package asciigraph
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func minMaxFloat64Slice(v []float64) (min, max float64) {
|
||||||
|
min = math.Inf(1)
|
||||||
|
max = math.Inf(-1)
|
||||||
|
|
||||||
|
if len(v) == 0 {
|
||||||
|
panic("Empty slice")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range v {
|
||||||
|
if e < min {
|
||||||
|
min = e
|
||||||
|
}
|
||||||
|
if e > max {
|
||||||
|
max = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func round(input float64) float64 {
|
||||||
|
if math.IsNaN(input) {
|
||||||
|
return math.NaN()
|
||||||
|
}
|
||||||
|
sign := 1.0
|
||||||
|
if input < 0 {
|
||||||
|
sign = -1
|
||||||
|
input *= -1
|
||||||
|
}
|
||||||
|
_, decimal := math.Modf(input)
|
||||||
|
var rounded float64
|
||||||
|
if decimal >= 0.5 {
|
||||||
|
rounded = math.Ceil(input)
|
||||||
|
} else {
|
||||||
|
rounded = math.Floor(input)
|
||||||
|
}
|
||||||
|
return rounded * sign
|
||||||
|
}
|
||||||
|
|
||||||
|
func linearInterpolate(before, after, atPoint float64) float64 {
|
||||||
|
return before + (after-before)*atPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func interpolateArray(data []float64, fitCount int) []float64 {
|
||||||
|
|
||||||
|
var interpolatedData []float64
|
||||||
|
|
||||||
|
springFactor := float64(len(data)-1) / float64(fitCount-1)
|
||||||
|
interpolatedData = append(interpolatedData, data[0])
|
||||||
|
|
||||||
|
for i := 1; i < fitCount-1; i++ {
|
||||||
|
spring := float64(i) * springFactor
|
||||||
|
before := math.Floor(spring)
|
||||||
|
after := math.Ceil(spring)
|
||||||
|
atPoint := spring - before
|
||||||
|
interpolatedData = append(interpolatedData, linearInterpolate(data[int(before)], data[int(after)], atPoint))
|
||||||
|
}
|
||||||
|
interpolatedData = append(interpolatedData, data[len(data)-1])
|
||||||
|
return interpolatedData
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear terminal screen
|
||||||
|
var Clear func()
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
platform := runtime.GOOS
|
||||||
|
|
||||||
|
if platform == "windows" {
|
||||||
|
Clear = func() {
|
||||||
|
cmd := exec.Command("cmd", "/c", "cls")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Clear = func() {
|
||||||
|
fmt.Print("\033[2J\033[H")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateHeight(interval float64) int {
|
||||||
|
if interval >= 1 {
|
||||||
|
return int(interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
scaleFactor := math.Pow(10, math.Floor(math.Log10(interval)))
|
||||||
|
scaledDelta := interval / scaleFactor
|
||||||
|
|
||||||
|
if scaledDelta < 2 {
|
||||||
|
return int(math.Ceil(scaledDelta))
|
||||||
|
}
|
||||||
|
return int(math.Floor(scaledDelta))
|
||||||
|
}
|
||||||
27
vendor/golang.org/x/crypto/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/crypto/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Copyright 2009 The Go Authors.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google LLC nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
22
vendor/golang.org/x/crypto/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/crypto/PATENTS
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
||||||
76
vendor/golang.org/x/crypto/ssh/terminal/terminal.go
generated
vendored
Normal file
76
vendor/golang.org/x/crypto/ssh/terminal/terminal.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package terminal provides support functions for dealing with terminals, as
|
||||||
|
// commonly found on UNIX systems.
|
||||||
|
//
|
||||||
|
// Deprecated: this package moved to golang.org/x/term.
|
||||||
|
package terminal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"golang.org/x/term"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EscapeCodes contains escape sequences that can be written to the terminal in
|
||||||
|
// order to achieve different styles of text.
|
||||||
|
type EscapeCodes = term.EscapeCodes
|
||||||
|
|
||||||
|
// Terminal contains the state for running a VT100 terminal that is capable of
|
||||||
|
// reading lines of input.
|
||||||
|
type Terminal = term.Terminal
|
||||||
|
|
||||||
|
// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
|
||||||
|
// a local terminal, that terminal must first have been put into raw mode.
|
||||||
|
// prompt is a string that is written at the start of each input line (i.e.
|
||||||
|
// "> ").
|
||||||
|
func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
|
||||||
|
return term.NewTerminal(c, prompt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrPasteIndicator may be returned from ReadLine as the error, in addition
|
||||||
|
// to valid line data. It indicates that bracketed paste mode is enabled and
|
||||||
|
// that the returned line consists only of pasted data. Programs may wish to
|
||||||
|
// interpret pasted data more literally than typed data.
|
||||||
|
var ErrPasteIndicator = term.ErrPasteIndicator
|
||||||
|
|
||||||
|
// State contains the state of a terminal.
|
||||||
|
type State = term.State
|
||||||
|
|
||||||
|
// IsTerminal returns whether the given file descriptor is a terminal.
|
||||||
|
func IsTerminal(fd int) bool {
|
||||||
|
return term.IsTerminal(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||||
|
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||||
|
// returned does not include the \n.
|
||||||
|
func ReadPassword(fd int) ([]byte, error) {
|
||||||
|
return term.ReadPassword(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeRaw puts the terminal connected to the given file descriptor into raw
|
||||||
|
// mode and returns the previous state of the terminal so that it can be
|
||||||
|
// restored.
|
||||||
|
func MakeRaw(fd int) (*State, error) {
|
||||||
|
return term.MakeRaw(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore restores the terminal connected to the given file descriptor to a
|
||||||
|
// previous state.
|
||||||
|
func Restore(fd int, oldState *State) error {
|
||||||
|
return term.Restore(fd, oldState)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetState returns the current state of a terminal which may be useful to
|
||||||
|
// restore the terminal after a signal.
|
||||||
|
func GetState(fd int) (*State, error) {
|
||||||
|
return term.GetState(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSize returns the dimensions of the given terminal.
|
||||||
|
func GetSize(fd int) (width, height int, err error) {
|
||||||
|
return term.GetSize(fd)
|
||||||
|
}
|
||||||
27
vendor/golang.org/x/sys/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/sys/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Copyright 2009 The Go Authors.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google LLC nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
22
vendor/golang.org/x/sys/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/sys/PATENTS
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
||||||
8
vendor/golang.org/x/sys/plan9/asm.s
generated
vendored
Normal file
8
vendor/golang.org/x/sys/plan9/asm.s
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
TEXT ·use(SB),NOSPLIT,$0
|
||||||
|
RET
|
||||||
30
vendor/golang.org/x/sys/plan9/asm_plan9_386.s
generated
vendored
Normal file
30
vendor/golang.org/x/sys/plan9/asm_plan9_386.s
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for 386, Plan 9
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-32
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-44
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-36
|
||||||
|
JMP syscall·seek(SB)
|
||||||
|
|
||||||
|
TEXT ·exit(SB),NOSPLIT,$4-4
|
||||||
|
JMP syscall·exit(SB)
|
||||||
30
vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s
generated
vendored
Normal file
30
vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for amd64, Plan 9
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-64
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·seek(SB)
|
||||||
|
|
||||||
|
TEXT ·exit(SB),NOSPLIT,$8-8
|
||||||
|
JMP syscall·exit(SB)
|
||||||
25
vendor/golang.org/x/sys/plan9/asm_plan9_arm.s
generated
vendored
Normal file
25
vendor/golang.org/x/sys/plan9/asm_plan9_arm.s
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for plan9 on arm
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-32
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-44
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-36
|
||||||
|
JMP syscall·exit(SB)
|
||||||
70
vendor/golang.org/x/sys/plan9/const_plan9.go
generated
vendored
Normal file
70
vendor/golang.org/x/sys/plan9/const_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package plan9
|
||||||
|
|
||||||
|
// Plan 9 Constants
|
||||||
|
|
||||||
|
// Open modes
|
||||||
|
const (
|
||||||
|
O_RDONLY = 0
|
||||||
|
O_WRONLY = 1
|
||||||
|
O_RDWR = 2
|
||||||
|
O_TRUNC = 16
|
||||||
|
O_CLOEXEC = 32
|
||||||
|
O_EXCL = 0x1000
|
||||||
|
)
|
||||||
|
|
||||||
|
// Rfork flags
|
||||||
|
const (
|
||||||
|
RFNAMEG = 1 << 0
|
||||||
|
RFENVG = 1 << 1
|
||||||
|
RFFDG = 1 << 2
|
||||||
|
RFNOTEG = 1 << 3
|
||||||
|
RFPROC = 1 << 4
|
||||||
|
RFMEM = 1 << 5
|
||||||
|
RFNOWAIT = 1 << 6
|
||||||
|
RFCNAMEG = 1 << 10
|
||||||
|
RFCENVG = 1 << 11
|
||||||
|
RFCFDG = 1 << 12
|
||||||
|
RFREND = 1 << 13
|
||||||
|
RFNOMNT = 1 << 14
|
||||||
|
)
|
||||||
|
|
||||||
|
// Qid.Type bits
|
||||||
|
const (
|
||||||
|
QTDIR = 0x80
|
||||||
|
QTAPPEND = 0x40
|
||||||
|
QTEXCL = 0x20
|
||||||
|
QTMOUNT = 0x10
|
||||||
|
QTAUTH = 0x08
|
||||||
|
QTTMP = 0x04
|
||||||
|
QTFILE = 0x00
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dir.Mode bits
|
||||||
|
const (
|
||||||
|
DMDIR = 0x80000000
|
||||||
|
DMAPPEND = 0x40000000
|
||||||
|
DMEXCL = 0x20000000
|
||||||
|
DMMOUNT = 0x10000000
|
||||||
|
DMAUTH = 0x08000000
|
||||||
|
DMTMP = 0x04000000
|
||||||
|
DMREAD = 0x4
|
||||||
|
DMWRITE = 0x2
|
||||||
|
DMEXEC = 0x1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
STATMAX = 65535
|
||||||
|
ERRMAX = 128
|
||||||
|
STATFIXLEN = 49
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mount and bind flags
|
||||||
|
const (
|
||||||
|
MREPL = 0x0000
|
||||||
|
MBEFORE = 0x0001
|
||||||
|
MAFTER = 0x0002
|
||||||
|
MORDER = 0x0003
|
||||||
|
MCREATE = 0x0004
|
||||||
|
MCACHE = 0x0010
|
||||||
|
MMASK = 0x0017
|
||||||
|
)
|
||||||
212
vendor/golang.org/x/sys/plan9/dir_plan9.go
generated
vendored
Normal file
212
vendor/golang.org/x/sys/plan9/dir_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Plan 9 directory marshalling. See intro(5).
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrShortStat = errors.New("stat buffer too short")
|
||||||
|
ErrBadStat = errors.New("malformed stat buffer")
|
||||||
|
ErrBadName = errors.New("bad character in file name")
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Qid represents a 9P server's unique identification for a file.
|
||||||
|
type Qid struct {
|
||||||
|
Path uint64 // the file server's unique identification for the file
|
||||||
|
Vers uint32 // version number for given Path
|
||||||
|
Type uint8 // the type of the file (plan9.QTDIR for example)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Dir contains the metadata for a file.
|
||||||
|
type Dir struct {
|
||||||
|
// system-modified data
|
||||||
|
Type uint16 // server type
|
||||||
|
Dev uint32 // server subtype
|
||||||
|
|
||||||
|
// file data
|
||||||
|
Qid Qid // unique id from server
|
||||||
|
Mode uint32 // permissions
|
||||||
|
Atime uint32 // last read time
|
||||||
|
Mtime uint32 // last write time
|
||||||
|
Length int64 // file length
|
||||||
|
Name string // last element of path
|
||||||
|
Uid string // owner name
|
||||||
|
Gid string // group name
|
||||||
|
Muid string // last modifier name
|
||||||
|
}
|
||||||
|
|
||||||
|
var nullDir = Dir{
|
||||||
|
Type: ^uint16(0),
|
||||||
|
Dev: ^uint32(0),
|
||||||
|
Qid: Qid{
|
||||||
|
Path: ^uint64(0),
|
||||||
|
Vers: ^uint32(0),
|
||||||
|
Type: ^uint8(0),
|
||||||
|
},
|
||||||
|
Mode: ^uint32(0),
|
||||||
|
Atime: ^uint32(0),
|
||||||
|
Mtime: ^uint32(0),
|
||||||
|
Length: ^int64(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null assigns special "don't touch" values to members of d to
|
||||||
|
// avoid modifying them during plan9.Wstat.
|
||||||
|
func (d *Dir) Null() { *d = nullDir }
|
||||||
|
|
||||||
|
// Marshal encodes a 9P stat message corresponding to d into b
|
||||||
|
//
|
||||||
|
// If there isn't enough space in b for a stat message, ErrShortStat is returned.
|
||||||
|
func (d *Dir) Marshal(b []byte) (n int, err error) {
|
||||||
|
n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
|
||||||
|
if n > len(b) {
|
||||||
|
return n, ErrShortStat
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range d.Name {
|
||||||
|
if c == '/' {
|
||||||
|
return n, ErrBadName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b = pbit16(b, uint16(n)-2)
|
||||||
|
b = pbit16(b, d.Type)
|
||||||
|
b = pbit32(b, d.Dev)
|
||||||
|
b = pbit8(b, d.Qid.Type)
|
||||||
|
b = pbit32(b, d.Qid.Vers)
|
||||||
|
b = pbit64(b, d.Qid.Path)
|
||||||
|
b = pbit32(b, d.Mode)
|
||||||
|
b = pbit32(b, d.Atime)
|
||||||
|
b = pbit32(b, d.Mtime)
|
||||||
|
b = pbit64(b, uint64(d.Length))
|
||||||
|
b = pstring(b, d.Name)
|
||||||
|
b = pstring(b, d.Uid)
|
||||||
|
b = pstring(b, d.Gid)
|
||||||
|
b = pstring(b, d.Muid)
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
|
||||||
|
//
|
||||||
|
// If b is too small to hold a valid stat message, ErrShortStat is returned.
|
||||||
|
//
|
||||||
|
// If the stat message itself is invalid, ErrBadStat is returned.
|
||||||
|
func UnmarshalDir(b []byte) (*Dir, error) {
|
||||||
|
if len(b) < STATFIXLEN {
|
||||||
|
return nil, ErrShortStat
|
||||||
|
}
|
||||||
|
size, buf := gbit16(b)
|
||||||
|
if len(b) != int(size)+2 {
|
||||||
|
return nil, ErrBadStat
|
||||||
|
}
|
||||||
|
b = buf
|
||||||
|
|
||||||
|
var d Dir
|
||||||
|
d.Type, b = gbit16(b)
|
||||||
|
d.Dev, b = gbit32(b)
|
||||||
|
d.Qid.Type, b = gbit8(b)
|
||||||
|
d.Qid.Vers, b = gbit32(b)
|
||||||
|
d.Qid.Path, b = gbit64(b)
|
||||||
|
d.Mode, b = gbit32(b)
|
||||||
|
d.Atime, b = gbit32(b)
|
||||||
|
d.Mtime, b = gbit32(b)
|
||||||
|
|
||||||
|
n, b := gbit64(b)
|
||||||
|
d.Length = int64(n)
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
if d.Name, b, ok = gstring(b); !ok {
|
||||||
|
return nil, ErrBadStat
|
||||||
|
}
|
||||||
|
if d.Uid, b, ok = gstring(b); !ok {
|
||||||
|
return nil, ErrBadStat
|
||||||
|
}
|
||||||
|
if d.Gid, b, ok = gstring(b); !ok {
|
||||||
|
return nil, ErrBadStat
|
||||||
|
}
|
||||||
|
if d.Muid, b, ok = gstring(b); !ok {
|
||||||
|
return nil, ErrBadStat
|
||||||
|
}
|
||||||
|
|
||||||
|
return &d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
|
||||||
|
func pbit8(b []byte, v uint8) []byte {
|
||||||
|
b[0] = byte(v)
|
||||||
|
return b[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
|
||||||
|
func pbit16(b []byte, v uint16) []byte {
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
return b[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
|
||||||
|
func pbit32(b []byte, v uint32) []byte {
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
b[2] = byte(v >> 16)
|
||||||
|
b[3] = byte(v >> 24)
|
||||||
|
return b[4:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
|
||||||
|
func pbit64(b []byte, v uint64) []byte {
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
b[2] = byte(v >> 16)
|
||||||
|
b[3] = byte(v >> 24)
|
||||||
|
b[4] = byte(v >> 32)
|
||||||
|
b[5] = byte(v >> 40)
|
||||||
|
b[6] = byte(v >> 48)
|
||||||
|
b[7] = byte(v >> 56)
|
||||||
|
return b[8:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
|
||||||
|
// returning the remaining slice of b..
|
||||||
|
func pstring(b []byte, s string) []byte {
|
||||||
|
b = pbit16(b, uint16(len(s)))
|
||||||
|
n := copy(b, s)
|
||||||
|
return b[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
|
||||||
|
func gbit8(b []byte) (uint8, []byte) {
|
||||||
|
return uint8(b[0]), b[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
|
||||||
|
func gbit16(b []byte) (uint16, []byte) {
|
||||||
|
return uint16(b[0]) | uint16(b[1])<<8, b[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
|
||||||
|
func gbit32(b []byte) (uint32, []byte) {
|
||||||
|
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
|
||||||
|
func gbit64(b []byte) (uint64, []byte) {
|
||||||
|
lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||||
|
hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
|
||||||
|
return uint64(lo) | uint64(hi)<<32, b[8:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
|
||||||
|
// It returns the string with the remaining slice of b and a boolean. If the length is
|
||||||
|
// greater than the number of bytes in b, the boolean will be false.
|
||||||
|
func gstring(b []byte) (string, []byte, bool) {
|
||||||
|
n, b := gbit16(b)
|
||||||
|
if int(n) > len(b) {
|
||||||
|
return "", b, false
|
||||||
|
}
|
||||||
|
return string(b[:n]), b[n:], true
|
||||||
|
}
|
||||||
31
vendor/golang.org/x/sys/plan9/env_plan9.go
generated
vendored
Normal file
31
vendor/golang.org/x/sys/plan9/env_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Plan 9 environment variables.
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Getenv(key string) (value string, found bool) {
|
||||||
|
return syscall.Getenv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Setenv(key, value string) error {
|
||||||
|
return syscall.Setenv(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clearenv() {
|
||||||
|
syscall.Clearenv()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Environ() []string {
|
||||||
|
return syscall.Environ()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
return syscall.Unsetenv(key)
|
||||||
|
}
|
||||||
50
vendor/golang.org/x/sys/plan9/errors_plan9.go
generated
vendored
Normal file
50
vendor/golang.org/x/sys/plan9/errors_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const (
|
||||||
|
// Invented values to support what package os expects.
|
||||||
|
O_CREAT = 0x02000
|
||||||
|
O_APPEND = 0x00400
|
||||||
|
O_NOCTTY = 0x00000
|
||||||
|
O_NONBLOCK = 0x00000
|
||||||
|
O_SYNC = 0x00000
|
||||||
|
O_ASYNC = 0x00000
|
||||||
|
|
||||||
|
S_IFMT = 0x1f000
|
||||||
|
S_IFIFO = 0x1000
|
||||||
|
S_IFCHR = 0x2000
|
||||||
|
S_IFDIR = 0x4000
|
||||||
|
S_IFBLK = 0x6000
|
||||||
|
S_IFREG = 0x8000
|
||||||
|
S_IFLNK = 0xa000
|
||||||
|
S_IFSOCK = 0xc000
|
||||||
|
)
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
var (
|
||||||
|
EINVAL = syscall.NewError("bad arg in system call")
|
||||||
|
ENOTDIR = syscall.NewError("not a directory")
|
||||||
|
EISDIR = syscall.NewError("file is a directory")
|
||||||
|
ENOENT = syscall.NewError("file does not exist")
|
||||||
|
EEXIST = syscall.NewError("file already exists")
|
||||||
|
EMFILE = syscall.NewError("no free file descriptors")
|
||||||
|
EIO = syscall.NewError("i/o error")
|
||||||
|
ENAMETOOLONG = syscall.NewError("file name too long")
|
||||||
|
EINTR = syscall.NewError("interrupted")
|
||||||
|
EPERM = syscall.NewError("permission denied")
|
||||||
|
EBUSY = syscall.NewError("no free devices")
|
||||||
|
ETIMEDOUT = syscall.NewError("connection timed out")
|
||||||
|
EPLAN9 = syscall.NewError("not supported by plan 9")
|
||||||
|
|
||||||
|
// The following errors do not correspond to any
|
||||||
|
// Plan 9 system messages. Invented to support
|
||||||
|
// what package os and others expect.
|
||||||
|
EACCES = syscall.NewError("access permission denied")
|
||||||
|
EAFNOSUPPORT = syscall.NewError("address family not supported by protocol")
|
||||||
|
)
|
||||||
150
vendor/golang.org/x/sys/plan9/mkall.sh
generated
vendored
Normal file
150
vendor/golang.org/x/sys/plan9/mkall.sh
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# The plan9 package provides access to the raw system call
|
||||||
|
# interface of the underlying operating system. Porting Go to
|
||||||
|
# a new architecture/operating system combination requires
|
||||||
|
# some manual effort, though there are tools that automate
|
||||||
|
# much of the process. The auto-generated files have names
|
||||||
|
# beginning with z.
|
||||||
|
#
|
||||||
|
# This script runs or (given -n) prints suggested commands to generate z files
|
||||||
|
# for the current system. Running those commands is not automatic.
|
||||||
|
# This script is documentation more than anything else.
|
||||||
|
#
|
||||||
|
# * asm_${GOOS}_${GOARCH}.s
|
||||||
|
#
|
||||||
|
# This hand-written assembly file implements system call dispatch.
|
||||||
|
# There are three entry points:
|
||||||
|
#
|
||||||
|
# func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
|
||||||
|
# func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
|
||||||
|
# func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
|
||||||
|
#
|
||||||
|
# The first and second are the standard ones; they differ only in
|
||||||
|
# how many arguments can be passed to the kernel.
|
||||||
|
# The third is for low-level use by the ForkExec wrapper;
|
||||||
|
# unlike the first two, it does not call into the scheduler to
|
||||||
|
# let it know that a system call is running.
|
||||||
|
#
|
||||||
|
# * syscall_${GOOS}.go
|
||||||
|
#
|
||||||
|
# This hand-written Go file implements system calls that need
|
||||||
|
# special handling and lists "//sys" comments giving prototypes
|
||||||
|
# for ones that can be auto-generated. Mksyscall reads those
|
||||||
|
# comments to generate the stubs.
|
||||||
|
#
|
||||||
|
# * syscall_${GOOS}_${GOARCH}.go
|
||||||
|
#
|
||||||
|
# Same as syscall_${GOOS}.go except that it contains code specific
|
||||||
|
# to ${GOOS} on one particular architecture.
|
||||||
|
#
|
||||||
|
# * types_${GOOS}.c
|
||||||
|
#
|
||||||
|
# This hand-written C file includes standard C headers and then
|
||||||
|
# creates typedef or enum names beginning with a dollar sign
|
||||||
|
# (use of $ in variable names is a gcc extension). The hardest
|
||||||
|
# part about preparing this file is figuring out which headers to
|
||||||
|
# include and which symbols need to be #defined to get the
|
||||||
|
# actual data structures that pass through to the kernel system calls.
|
||||||
|
# Some C libraries present alternate versions for binary compatibility
|
||||||
|
# and translate them on the way in and out of system calls, but
|
||||||
|
# there is almost always a #define that can get the real ones.
|
||||||
|
# See types_darwin.c and types_linux.c for examples.
|
||||||
|
#
|
||||||
|
# * zerror_${GOOS}_${GOARCH}.go
|
||||||
|
#
|
||||||
|
# This machine-generated file defines the system's error numbers,
|
||||||
|
# error strings, and signal numbers. The generator is "mkerrors.sh".
|
||||||
|
# Usually no arguments are needed, but mkerrors.sh will pass its
|
||||||
|
# arguments on to godefs.
|
||||||
|
#
|
||||||
|
# * zsyscall_${GOOS}_${GOARCH}.go
|
||||||
|
#
|
||||||
|
# Generated by mksyscall.pl; see syscall_${GOOS}.go above.
|
||||||
|
#
|
||||||
|
# * zsysnum_${GOOS}_${GOARCH}.go
|
||||||
|
#
|
||||||
|
# Generated by mksysnum_${GOOS}.
|
||||||
|
#
|
||||||
|
# * ztypes_${GOOS}_${GOARCH}.go
|
||||||
|
#
|
||||||
|
# Generated by godefs; see types_${GOOS}.c above.
|
||||||
|
|
||||||
|
GOOSARCH="${GOOS}_${GOARCH}"
|
||||||
|
|
||||||
|
# defaults
|
||||||
|
mksyscall="go run mksyscall.go"
|
||||||
|
mkerrors="./mkerrors.sh"
|
||||||
|
zerrors="zerrors_$GOOSARCH.go"
|
||||||
|
mksysctl=""
|
||||||
|
zsysctl="zsysctl_$GOOSARCH.go"
|
||||||
|
mksysnum=
|
||||||
|
mktypes=
|
||||||
|
run="sh"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
-syscalls)
|
||||||
|
for i in zsyscall*go
|
||||||
|
do
|
||||||
|
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
|
||||||
|
rm _$i
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-n)
|
||||||
|
run="cat"
|
||||||
|
shift
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$#" in
|
||||||
|
0)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo 'usage: mkall.sh [-n]' 1>&2
|
||||||
|
exit 2
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$GOOSARCH" in
|
||||||
|
_* | *_ | _)
|
||||||
|
echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
plan9_386)
|
||||||
|
mkerrors=
|
||||||
|
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,386"
|
||||||
|
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
|
||||||
|
mktypes="XXX"
|
||||||
|
;;
|
||||||
|
plan9_amd64)
|
||||||
|
mkerrors=
|
||||||
|
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,amd64"
|
||||||
|
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
|
||||||
|
mktypes="XXX"
|
||||||
|
;;
|
||||||
|
plan9_arm)
|
||||||
|
mkerrors=
|
||||||
|
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,arm"
|
||||||
|
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
|
||||||
|
mktypes="XXX"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
(
|
||||||
|
if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
|
||||||
|
case "$GOOS" in
|
||||||
|
plan9)
|
||||||
|
syscall_goos="syscall_$GOOS.go"
|
||||||
|
if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos |gofmt >zsyscall_$GOOSARCH.go"; fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
||||||
|
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
|
||||||
|
if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi
|
||||||
|
) | $run
|
||||||
246
vendor/golang.org/x/sys/plan9/mkerrors.sh
generated
vendored
Normal file
246
vendor/golang.org/x/sys/plan9/mkerrors.sh
generated
vendored
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# Generate Go code listing errors and other #defined constant
|
||||||
|
# values (ENAMETOOLONG etc.), by asking the preprocessor
|
||||||
|
# about the definitions.
|
||||||
|
|
||||||
|
unset LANG
|
||||||
|
export LC_ALL=C
|
||||||
|
export LC_CTYPE=C
|
||||||
|
|
||||||
|
CC=${CC:-gcc}
|
||||||
|
|
||||||
|
uname=$(uname)
|
||||||
|
|
||||||
|
includes='
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
'
|
||||||
|
|
||||||
|
ccflags="$@"
|
||||||
|
|
||||||
|
# Write go tool cgo -godefs input.
|
||||||
|
(
|
||||||
|
echo package plan9
|
||||||
|
echo
|
||||||
|
echo '/*'
|
||||||
|
indirect="includes_$(uname)"
|
||||||
|
echo "${!indirect} $includes"
|
||||||
|
echo '*/'
|
||||||
|
echo 'import "C"'
|
||||||
|
echo
|
||||||
|
echo 'const ('
|
||||||
|
|
||||||
|
# The gcc command line prints all the #defines
|
||||||
|
# it encounters while processing the input
|
||||||
|
echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '
|
||||||
|
$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
|
||||||
|
|
||||||
|
$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
|
||||||
|
$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
|
||||||
|
$2 ~ /^(SCM_SRCRT)$/ {next}
|
||||||
|
$2 ~ /^(MAP_FAILED)$/ {next}
|
||||||
|
|
||||||
|
$2 !~ /^ETH_/ &&
|
||||||
|
$2 !~ /^EPROC_/ &&
|
||||||
|
$2 !~ /^EQUIV_/ &&
|
||||||
|
$2 !~ /^EXPR_/ &&
|
||||||
|
$2 ~ /^E[A-Z0-9_]+$/ ||
|
||||||
|
$2 ~ /^B[0-9_]+$/ ||
|
||||||
|
$2 ~ /^V[A-Z0-9]+$/ ||
|
||||||
|
$2 ~ /^CS[A-Z0-9]/ ||
|
||||||
|
$2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
|
||||||
|
$2 ~ /^IGN/ ||
|
||||||
|
$2 ~ /^IX(ON|ANY|OFF)$/ ||
|
||||||
|
$2 ~ /^IN(LCR|PCK)$/ ||
|
||||||
|
$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
|
||||||
|
$2 ~ /^C(LOCAL|READ)$/ ||
|
||||||
|
$2 == "BRKINT" ||
|
||||||
|
$2 == "HUPCL" ||
|
||||||
|
$2 == "PENDIN" ||
|
||||||
|
$2 == "TOSTOP" ||
|
||||||
|
$2 ~ /^PAR/ ||
|
||||||
|
$2 ~ /^SIG[^_]/ ||
|
||||||
|
$2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ ||
|
||||||
|
$2 ~ /^IN_/ ||
|
||||||
|
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||||
|
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
|
||||||
|
$2 == "ICMPV6_FILTER" ||
|
||||||
|
$2 == "SOMAXCONN" ||
|
||||||
|
$2 == "NAME_MAX" ||
|
||||||
|
$2 == "IFNAMSIZ" ||
|
||||||
|
$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
|
||||||
|
$2 ~ /^SYSCTL_VERS/ ||
|
||||||
|
$2 ~ /^(MS|MNT)_/ ||
|
||||||
|
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||||
|
$2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ ||
|
||||||
|
$2 ~ /^LINUX_REBOOT_CMD_/ ||
|
||||||
|
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
|
||||||
|
$2 !~ "NLA_TYPE_MASK" &&
|
||||||
|
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
|
||||||
|
$2 ~ /^SIOC/ ||
|
||||||
|
$2 ~ /^TIOC/ ||
|
||||||
|
$2 !~ "RTF_BITS" &&
|
||||||
|
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
|
||||||
|
$2 ~ /^BIOC/ ||
|
||||||
|
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
|
||||||
|
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
|
||||||
|
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
||||||
|
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||||
|
$2 !~ /^(BPF_TIMEVAL)$/ &&
|
||||||
|
$2 ~ /^(BPF|DLT)_/ ||
|
||||||
|
$2 !~ "WMESGLEN" &&
|
||||||
|
$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
|
||||||
|
$2 ~ /^__WCOREFLAG$/ {next}
|
||||||
|
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
|
||||||
|
|
||||||
|
{next}
|
||||||
|
' | sort
|
||||||
|
|
||||||
|
echo ')'
|
||||||
|
) >_const.go
|
||||||
|
|
||||||
|
# Pull out the error names for later.
|
||||||
|
errors=$(
|
||||||
|
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
|
||||||
|
sort
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull out the signal names for later.
|
||||||
|
signals=$(
|
||||||
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
||||||
|
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
|
||||||
|
sort
|
||||||
|
)
|
||||||
|
|
||||||
|
# Again, writing regexps to a file.
|
||||||
|
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||||
|
sort >_error.grep
|
||||||
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||||
|
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
|
||||||
|
sort >_signal.grep
|
||||||
|
|
||||||
|
echo '// mkerrors.sh' "$@"
|
||||||
|
echo '// Code generated by the command above; DO NOT EDIT.'
|
||||||
|
echo
|
||||||
|
go tool cgo -godefs -- "$@" _const.go >_error.out
|
||||||
|
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
||||||
|
echo
|
||||||
|
echo '// Errors'
|
||||||
|
echo 'const ('
|
||||||
|
cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/'
|
||||||
|
echo ')'
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo '// Signals'
|
||||||
|
echo 'const ('
|
||||||
|
cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/'
|
||||||
|
echo ')'
|
||||||
|
|
||||||
|
# Run C program to print error and syscall strings.
|
||||||
|
(
|
||||||
|
echo -E "
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
|
||||||
|
|
||||||
|
int errors[] = {
|
||||||
|
"
|
||||||
|
for i in $errors
|
||||||
|
do
|
||||||
|
echo -E ' '$i,
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -E "
|
||||||
|
};
|
||||||
|
|
||||||
|
int signals[] = {
|
||||||
|
"
|
||||||
|
for i in $signals
|
||||||
|
do
|
||||||
|
echo -E ' '$i,
|
||||||
|
done
|
||||||
|
|
||||||
|
# Use -E because on some systems bash builtin interprets \n itself.
|
||||||
|
echo -E '
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
intcmp(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return *(int*)a - *(int*)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
int i, j, e;
|
||||||
|
char buf[1024], *p;
|
||||||
|
|
||||||
|
printf("\n\n// Error table\n");
|
||||||
|
printf("var errors = [...]string {\n");
|
||||||
|
qsort(errors, nelem(errors), sizeof errors[0], intcmp);
|
||||||
|
for(i=0; i<nelem(errors); i++) {
|
||||||
|
e = errors[i];
|
||||||
|
if(i > 0 && errors[i-1] == e)
|
||||||
|
continue;
|
||||||
|
strcpy(buf, strerror(e));
|
||||||
|
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
|
||||||
|
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
|
||||||
|
buf[0] += a - A;
|
||||||
|
printf("\t%d: \"%s\",\n", e, buf);
|
||||||
|
}
|
||||||
|
printf("}\n\n");
|
||||||
|
|
||||||
|
printf("\n\n// Signal table\n");
|
||||||
|
printf("var signals = [...]string {\n");
|
||||||
|
qsort(signals, nelem(signals), sizeof signals[0], intcmp);
|
||||||
|
for(i=0; i<nelem(signals); i++) {
|
||||||
|
e = signals[i];
|
||||||
|
if(i > 0 && signals[i-1] == e)
|
||||||
|
continue;
|
||||||
|
strcpy(buf, strsignal(e));
|
||||||
|
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
|
||||||
|
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
|
||||||
|
buf[0] += a - A;
|
||||||
|
// cut trailing : number.
|
||||||
|
p = strrchr(buf, ":"[0]);
|
||||||
|
if(p)
|
||||||
|
*p = '\0';
|
||||||
|
printf("\t%d: \"%s\",\n", e, buf);
|
||||||
|
}
|
||||||
|
printf("}\n\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
'
|
||||||
|
) >_errors.c
|
||||||
|
|
||||||
|
$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out
|
||||||
23
vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh
generated
vendored
Normal file
23
vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
COMMAND="mksysnum_plan9.sh $@"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
// $COMMAND
|
||||||
|
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
const(
|
||||||
|
EOF
|
||||||
|
|
||||||
|
SP='[ ]' # space or tab
|
||||||
|
sed "s/^#define${SP}\\([A-Z0-9_][A-Z0-9_]*\\)${SP}${SP}*\\([0-9][0-9]*\\)/SYS_\\1=\\2/g" \
|
||||||
|
< $1 | grep -v SYS__
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
)
|
||||||
|
EOF
|
||||||
21
vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go
generated
vendored
Normal file
21
vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build go1.5
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func fixwd() {
|
||||||
|
syscall.Fixwd()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getwd() (wd string, err error) {
|
||||||
|
return syscall.Getwd()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chdir(path string) error {
|
||||||
|
return syscall.Chdir(path)
|
||||||
|
}
|
||||||
23
vendor/golang.org/x/sys/plan9/pwd_plan9.go
generated
vendored
Normal file
23
vendor/golang.org/x/sys/plan9/pwd_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !go1.5
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
func fixwd() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getwd() (wd string, err error) {
|
||||||
|
fd, err := open(".", O_RDONLY)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer Close(fd)
|
||||||
|
return Fd2path(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chdir(path string) error {
|
||||||
|
return chdir(path)
|
||||||
|
}
|
||||||
30
vendor/golang.org/x/sys/plan9/race.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/plan9/race.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build plan9 && race
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const raceenabled = true
|
||||||
|
|
||||||
|
func raceAcquire(addr unsafe.Pointer) {
|
||||||
|
runtime.RaceAcquire(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||||
|
runtime.RaceReleaseMerge(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||||
|
runtime.RaceReadRange(addr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||||
|
runtime.RaceWriteRange(addr, len)
|
||||||
|
}
|
||||||
25
vendor/golang.org/x/sys/plan9/race0.go
generated
vendored
Normal file
25
vendor/golang.org/x/sys/plan9/race0.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build plan9 && !race
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const raceenabled = false
|
||||||
|
|
||||||
|
func raceAcquire(addr unsafe.Pointer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||||
|
}
|
||||||
22
vendor/golang.org/x/sys/plan9/str.go
generated
vendored
Normal file
22
vendor/golang.org/x/sys/plan9/str.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build plan9
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
|
||||||
|
if val < 0 {
|
||||||
|
return "-" + itoa(-val)
|
||||||
|
}
|
||||||
|
var buf [32]byte // big enough for int64
|
||||||
|
i := len(buf) - 1
|
||||||
|
for val >= 10 {
|
||||||
|
buf[i] = byte(val%10 + '0')
|
||||||
|
i--
|
||||||
|
val /= 10
|
||||||
|
}
|
||||||
|
buf[i] = byte(val + '0')
|
||||||
|
return string(buf[i:])
|
||||||
|
}
|
||||||
109
vendor/golang.org/x/sys/plan9/syscall.go
generated
vendored
Normal file
109
vendor/golang.org/x/sys/plan9/syscall.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build plan9
|
||||||
|
|
||||||
|
// Package plan9 contains an interface to the low-level operating system
|
||||||
|
// primitives. OS details vary depending on the underlying system, and
|
||||||
|
// by default, godoc will display the OS-specific documentation for the current
|
||||||
|
// system. If you want godoc to display documentation for another
|
||||||
|
// system, set $GOOS and $GOARCH to the desired system. For example, if
|
||||||
|
// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
|
||||||
|
// to freebsd and $GOARCH to arm.
|
||||||
|
//
|
||||||
|
// The primary use of this package is inside other packages that provide a more
|
||||||
|
// portable interface to the system, such as "os", "time" and "net". Use
|
||||||
|
// those packages rather than this one if you can.
|
||||||
|
//
|
||||||
|
// For details of the functions and data types in this package consult
|
||||||
|
// the manuals for the appropriate operating system.
|
||||||
|
//
|
||||||
|
// These calls return err == nil to indicate success; otherwise
|
||||||
|
// err represents an operating system error describing the failure and
|
||||||
|
// holds a value of type syscall.ErrorString.
|
||||||
|
package plan9 // import "golang.org/x/sys/plan9"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||||
|
// containing the text of s. If s contains a NUL byte at any
|
||||||
|
// location, it returns (nil, EINVAL).
|
||||||
|
func ByteSliceFromString(s string) ([]byte, error) {
|
||||||
|
if strings.IndexByte(s, 0) != -1 {
|
||||||
|
return nil, EINVAL
|
||||||
|
}
|
||||||
|
a := make([]byte, len(s)+1)
|
||||||
|
copy(a, s)
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytePtrFromString returns a pointer to a NUL-terminated array of
|
||||||
|
// bytes containing the text of s. If s contains a NUL byte at any
|
||||||
|
// location, it returns (nil, EINVAL).
|
||||||
|
func BytePtrFromString(s string) (*byte, error) {
|
||||||
|
a, err := ByteSliceFromString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &a[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any
|
||||||
|
// bytes after the NUL removed.
|
||||||
|
func ByteSliceToString(s []byte) string {
|
||||||
|
if i := bytes.IndexByte(s, 0); i != -1 {
|
||||||
|
s = s[:i]
|
||||||
|
}
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string.
|
||||||
|
// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated
|
||||||
|
// at a zero byte; if the zero byte is not present, the program may crash.
|
||||||
|
func BytePtrToString(p *byte) string {
|
||||||
|
if p == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if *p == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find NUL terminator.
|
||||||
|
n := 0
|
||||||
|
for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ {
|
||||||
|
ptr = unsafe.Pointer(uintptr(ptr) + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(unsafe.Slice(p, n))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||||
|
// See mksyscall.pl.
|
||||||
|
var _zero uintptr
|
||||||
|
|
||||||
|
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
||||||
|
return int64(ts.Sec), int64(ts.Nsec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tv *Timeval) Unix() (sec int64, nsec int64) {
|
||||||
|
return int64(tv.Sec), int64(tv.Usec) * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *Timespec) Nano() int64 {
|
||||||
|
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tv *Timeval) Nano() int64 {
|
||||||
|
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
|
||||||
|
}
|
||||||
|
|
||||||
|
// use is a no-op, but the compiler cannot see that it is.
|
||||||
|
// Calling use(p) ensures that p is kept live until that point.
|
||||||
|
//
|
||||||
|
//go:noescape
|
||||||
|
func use(p unsafe.Pointer)
|
||||||
361
vendor/golang.org/x/sys/plan9/syscall_plan9.go
generated
vendored
Normal file
361
vendor/golang.org/x/sys/plan9/syscall_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Plan 9 system calls.
|
||||||
|
// This file is compiled as ordinary Go code,
|
||||||
|
// but it is also input to mksyscall,
|
||||||
|
// which parses the //sys lines and generates system call stubs.
|
||||||
|
// Note that sometimes we use a lowercase //sys name and
|
||||||
|
// wrap it in our own nicer implementation.
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Note is a string describing a process note.
|
||||||
|
// It implements the os.Signal interface.
|
||||||
|
type Note string
|
||||||
|
|
||||||
|
func (n Note) Signal() {}
|
||||||
|
|
||||||
|
func (n Note) String() string {
|
||||||
|
return string(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Stdin = 0
|
||||||
|
Stdout = 1
|
||||||
|
Stderr = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// For testing: clients can set this flag to force
|
||||||
|
// creation of IPv6 sockets to return EAFNOSUPPORT.
|
||||||
|
var SocketDisableIPv6 bool
|
||||||
|
|
||||||
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
|
||||||
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
|
||||||
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||||
|
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
||||||
|
|
||||||
|
func atoi(b []byte) (n uint) {
|
||||||
|
n = 0
|
||||||
|
for i := 0; i < len(b); i++ {
|
||||||
|
n = n*10 + uint(b[i]-'0')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func cstring(s []byte) string {
|
||||||
|
i := bytes.IndexByte(s, 0)
|
||||||
|
if i == -1 {
|
||||||
|
i = len(s)
|
||||||
|
}
|
||||||
|
return string(s[:i])
|
||||||
|
}
|
||||||
|
|
||||||
|
func errstr() string {
|
||||||
|
var buf [ERRMAX]byte
|
||||||
|
|
||||||
|
RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
|
||||||
|
|
||||||
|
buf[len(buf)-1] = 0
|
||||||
|
return cstring(buf[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implemented in assembly to import from runtime.
|
||||||
|
func exit(code int)
|
||||||
|
|
||||||
|
func Exit(code int) { exit(code) }
|
||||||
|
|
||||||
|
func readnum(path string) (uint, error) {
|
||||||
|
var b [12]byte
|
||||||
|
|
||||||
|
fd, e := Open(path, O_RDONLY)
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
defer Close(fd)
|
||||||
|
|
||||||
|
n, e := Pread(fd, b[:], 0)
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
|
||||||
|
m := 0
|
||||||
|
for ; m < n && b[m] == ' '; m++ {
|
||||||
|
}
|
||||||
|
|
||||||
|
return atoi(b[m : n-1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getpid() (pid int) {
|
||||||
|
n, _ := readnum("#c/pid")
|
||||||
|
return int(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getppid() (ppid int) {
|
||||||
|
n, _ := readnum("#c/ppid")
|
||||||
|
return int(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Read(fd int, p []byte) (n int, err error) {
|
||||||
|
return Pread(fd, p, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Write(fd int, p []byte) (n int, err error) {
|
||||||
|
return Pwrite(fd, p, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ioSync int64
|
||||||
|
|
||||||
|
//sys fd2path(fd int, buf []byte) (err error)
|
||||||
|
|
||||||
|
func Fd2path(fd int) (path string, err error) {
|
||||||
|
var buf [512]byte
|
||||||
|
|
||||||
|
e := fd2path(fd, buf[:])
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
return cstring(buf[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys pipe(p *[2]int32) (err error)
|
||||||
|
|
||||||
|
func Pipe(p []int) (err error) {
|
||||||
|
if len(p) != 2 {
|
||||||
|
return syscall.ErrorString("bad arg in system call")
|
||||||
|
}
|
||||||
|
var pp [2]int32
|
||||||
|
err = pipe(&pp)
|
||||||
|
if err == nil {
|
||||||
|
p[0] = int(pp[0])
|
||||||
|
p[1] = int(pp[1])
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Underlying system call writes to newoffset via pointer.
|
||||||
|
// Implemented in assembly to avoid allocation.
|
||||||
|
func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
|
||||||
|
|
||||||
|
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
||||||
|
newoffset, e := seek(0, fd, offset, whence)
|
||||||
|
|
||||||
|
if newoffset == -1 {
|
||||||
|
err = syscall.ErrorString(e)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Mkdir(path string, mode uint32) (err error) {
|
||||||
|
fd, err := Create(path, O_RDONLY, DMDIR|mode)
|
||||||
|
|
||||||
|
if fd != -1 {
|
||||||
|
Close(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type Waitmsg struct {
|
||||||
|
Pid int
|
||||||
|
Time [3]uint32
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w Waitmsg) Exited() bool { return true }
|
||||||
|
func (w Waitmsg) Signaled() bool { return false }
|
||||||
|
|
||||||
|
func (w Waitmsg) ExitStatus() int {
|
||||||
|
if len(w.Msg) == 0 {
|
||||||
|
// a normal exit returns no message
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys await(s []byte) (n int, err error)
|
||||||
|
|
||||||
|
func Await(w *Waitmsg) (err error) {
|
||||||
|
var buf [512]byte
|
||||||
|
var f [5][]byte
|
||||||
|
|
||||||
|
n, err := await(buf[:])
|
||||||
|
|
||||||
|
if err != nil || w == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nf := 0
|
||||||
|
p := 0
|
||||||
|
for i := 0; i < n && nf < len(f)-1; i++ {
|
||||||
|
if buf[i] == ' ' {
|
||||||
|
f[nf] = buf[p:i]
|
||||||
|
p = i + 1
|
||||||
|
nf++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f[nf] = buf[p:]
|
||||||
|
nf++
|
||||||
|
|
||||||
|
if nf != len(f) {
|
||||||
|
return syscall.ErrorString("invalid wait message")
|
||||||
|
}
|
||||||
|
w.Pid = int(atoi(f[0]))
|
||||||
|
w.Time[0] = uint32(atoi(f[1]))
|
||||||
|
w.Time[1] = uint32(atoi(f[2]))
|
||||||
|
w.Time[2] = uint32(atoi(f[3]))
|
||||||
|
w.Msg = cstring(f[4])
|
||||||
|
if w.Msg == "''" {
|
||||||
|
// await() returns '' for no error
|
||||||
|
w.Msg = ""
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unmount(name, old string) (err error) {
|
||||||
|
fixwd()
|
||||||
|
oldp, err := BytePtrFromString(old)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oldptr := uintptr(unsafe.Pointer(oldp))
|
||||||
|
|
||||||
|
var r0 uintptr
|
||||||
|
var e syscall.ErrorString
|
||||||
|
|
||||||
|
// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
|
||||||
|
if name == "" {
|
||||||
|
r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
|
||||||
|
} else {
|
||||||
|
namep, err := BytePtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fchdir(fd int) (err error) {
|
||||||
|
path, err := Fd2path(fd)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return Chdir(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Timespec struct {
|
||||||
|
Sec int32
|
||||||
|
Nsec int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Timeval struct {
|
||||||
|
Sec int32
|
||||||
|
Usec int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
|
nsec += 999 // round up to microsecond
|
||||||
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
|
tv.Sec = int32(nsec / 1e9)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func nsec() int64 {
|
||||||
|
var scratch int64
|
||||||
|
|
||||||
|
r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
|
||||||
|
// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
|
||||||
|
if r0 == 0 {
|
||||||
|
return scratch
|
||||||
|
}
|
||||||
|
return int64(r0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Gettimeofday(tv *Timeval) error {
|
||||||
|
nsec := nsec()
|
||||||
|
*tv = NsecToTimeval(nsec)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getpagesize() int { return 0x1000 }
|
||||||
|
|
||||||
|
func Getegid() (egid int) { return -1 }
|
||||||
|
func Geteuid() (euid int) { return -1 }
|
||||||
|
func Getgid() (gid int) { return -1 }
|
||||||
|
func Getuid() (uid int) { return -1 }
|
||||||
|
|
||||||
|
func Getgroups() (gids []int, err error) {
|
||||||
|
return make([]int, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys open(path string, mode int) (fd int, err error)
|
||||||
|
|
||||||
|
func Open(path string, mode int) (fd int, err error) {
|
||||||
|
fixwd()
|
||||||
|
return open(path, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys create(path string, mode int, perm uint32) (fd int, err error)
|
||||||
|
|
||||||
|
func Create(path string, mode int, perm uint32) (fd int, err error) {
|
||||||
|
fixwd()
|
||||||
|
return create(path, mode, perm)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys remove(path string) (err error)
|
||||||
|
|
||||||
|
func Remove(path string) error {
|
||||||
|
fixwd()
|
||||||
|
return remove(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys stat(path string, edir []byte) (n int, err error)
|
||||||
|
|
||||||
|
func Stat(path string, edir []byte) (n int, err error) {
|
||||||
|
fixwd()
|
||||||
|
return stat(path, edir)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys bind(name string, old string, flag int) (err error)
|
||||||
|
|
||||||
|
func Bind(name string, old string, flag int) (err error) {
|
||||||
|
fixwd()
|
||||||
|
return bind(name, old, flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys mount(fd int, afd int, old string, flag int, aname string) (err error)
|
||||||
|
|
||||||
|
func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
|
||||||
|
fixwd()
|
||||||
|
return mount(fd, afd, old, flag, aname)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys wstat(path string, edir []byte) (err error)
|
||||||
|
|
||||||
|
func Wstat(path string, edir []byte) (err error) {
|
||||||
|
fixwd()
|
||||||
|
return wstat(path, edir)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys chdir(path string) (err error)
|
||||||
|
//sys Dup(oldfd int, newfd int) (fd int, err error)
|
||||||
|
//sys Pread(fd int, p []byte, offset int64) (n int, err error)
|
||||||
|
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
|
||||||
|
//sys Close(fd int) (err error)
|
||||||
|
//sys Fstat(fd int, edir []byte) (n int, err error)
|
||||||
|
//sys Fwstat(fd int, edir []byte) (err error)
|
||||||
284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go
generated
vendored
Normal file
284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go
generated
vendored
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
// go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go
|
||||||
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build plan9 && 386
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func fd2path(fd int, buf []byte) (err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&buf[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func pipe(p *[2]int32) (err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func await(s []byte) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(s) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&s[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func open(path string, mode int) (fd int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func create(path string, mode int, perm uint32) (fd int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func remove(path string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func stat(path string, edir []byte) (n int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func bind(name string, old string, flag int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = BytePtrFromString(old)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(old)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = BytePtrFromString(aname)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func wstat(path string, edir []byte) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func chdir(path string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Dup(oldfd int, newfd int) (fd int, err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pread(fd int, p []byte, offset int64) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Close(fd int) (err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fstat(fd int, edir []byte) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fwstat(fd int, edir []byte) (err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go
generated
vendored
Normal file
284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
// go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go
|
||||||
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build plan9 && amd64
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func fd2path(fd int, buf []byte) (err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&buf[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func pipe(p *[2]int32) (err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func await(s []byte) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(s) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&s[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func open(path string, mode int) (fd int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func create(path string, mode int, perm uint32) (fd int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func remove(path string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func stat(path string, edir []byte) (n int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func bind(name string, old string, flag int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = BytePtrFromString(old)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(old)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = BytePtrFromString(aname)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func wstat(path string, edir []byte) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func chdir(path string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Dup(oldfd int, newfd int) (fd int, err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pread(fd int, p []byte, offset int64) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Close(fd int) (err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fstat(fd int, edir []byte) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fwstat(fd int, edir []byte) (err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go
generated
vendored
Normal file
284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go
generated
vendored
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
// go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go
|
||||||
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build plan9 && arm
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func fd2path(fd int, buf []byte) (err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&buf[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func pipe(p *[2]int32) (err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func await(s []byte) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(s) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&s[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func open(path string, mode int) (fd int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func create(path string, mode int, perm uint32) (fd int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func remove(path string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func stat(path string, edir []byte) (n int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func bind(name string, old string, flag int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = BytePtrFromString(old)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(old)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = BytePtrFromString(aname)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func wstat(path string, edir []byte) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func chdir(path string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Dup(oldfd int, newfd int) (fd int, err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
|
||||||
|
fd = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pread(fd int, p []byte, offset int64) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(p) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&p[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Close(fd int) (err error) {
|
||||||
|
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fstat(fd int, edir []byte) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
n = int(r0)
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fwstat(fd int, edir []byte) (err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(edir) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&edir[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
|
||||||
|
if int32(r0) == -1 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
49
vendor/golang.org/x/sys/plan9/zsysnum_plan9.go
generated
vendored
Normal file
49
vendor/golang.org/x/sys/plan9/zsysnum_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// mksysnum_plan9.sh /opt/plan9/sys/src/libc/9syscall/sys.h
|
||||||
|
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||||
|
|
||||||
|
package plan9
|
||||||
|
|
||||||
|
const (
|
||||||
|
SYS_SYSR1 = 0
|
||||||
|
SYS_BIND = 2
|
||||||
|
SYS_CHDIR = 3
|
||||||
|
SYS_CLOSE = 4
|
||||||
|
SYS_DUP = 5
|
||||||
|
SYS_ALARM = 6
|
||||||
|
SYS_EXEC = 7
|
||||||
|
SYS_EXITS = 8
|
||||||
|
SYS_FAUTH = 10
|
||||||
|
SYS_SEGBRK = 12
|
||||||
|
SYS_OPEN = 14
|
||||||
|
SYS_OSEEK = 16
|
||||||
|
SYS_SLEEP = 17
|
||||||
|
SYS_RFORK = 19
|
||||||
|
SYS_PIPE = 21
|
||||||
|
SYS_CREATE = 22
|
||||||
|
SYS_FD2PATH = 23
|
||||||
|
SYS_BRK_ = 24
|
||||||
|
SYS_REMOVE = 25
|
||||||
|
SYS_NOTIFY = 28
|
||||||
|
SYS_NOTED = 29
|
||||||
|
SYS_SEGATTACH = 30
|
||||||
|
SYS_SEGDETACH = 31
|
||||||
|
SYS_SEGFREE = 32
|
||||||
|
SYS_SEGFLUSH = 33
|
||||||
|
SYS_RENDEZVOUS = 34
|
||||||
|
SYS_UNMOUNT = 35
|
||||||
|
SYS_SEMACQUIRE = 37
|
||||||
|
SYS_SEMRELEASE = 38
|
||||||
|
SYS_SEEK = 39
|
||||||
|
SYS_FVERSION = 40
|
||||||
|
SYS_ERRSTR = 41
|
||||||
|
SYS_STAT = 42
|
||||||
|
SYS_FSTAT = 43
|
||||||
|
SYS_WSTAT = 44
|
||||||
|
SYS_FWSTAT = 45
|
||||||
|
SYS_MOUNT = 46
|
||||||
|
SYS_AWAIT = 47
|
||||||
|
SYS_PREAD = 50
|
||||||
|
SYS_PWRITE = 51
|
||||||
|
SYS_TSEMACQUIRE = 52
|
||||||
|
SYS_NSEC = 53
|
||||||
|
)
|
||||||
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
Normal file
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
_obj/
|
||||||
|
unix.test
|
||||||
184
vendor/golang.org/x/sys/unix/README.md
generated
vendored
Normal file
184
vendor/golang.org/x/sys/unix/README.md
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
# Building `sys/unix`
|
||||||
|
|
||||||
|
The sys/unix package provides access to the raw system call interface of the
|
||||||
|
underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
|
||||||
|
|
||||||
|
Porting Go to a new architecture/OS combination or adding syscalls, types, or
|
||||||
|
constants to an existing architecture/OS pair requires some manual effort;
|
||||||
|
however, there are tools that automate much of the process.
|
||||||
|
|
||||||
|
## Build Systems
|
||||||
|
|
||||||
|
There are currently two ways we generate the necessary files. We are currently
|
||||||
|
migrating the build system to use containers so the builds are reproducible.
|
||||||
|
This is being done on an OS-by-OS basis. Please update this documentation as
|
||||||
|
components of the build system change.
|
||||||
|
|
||||||
|
### Old Build System (currently for `GOOS != "linux"`)
|
||||||
|
|
||||||
|
The old build system generates the Go files based on the C header files
|
||||||
|
present on your system. This means that files
|
||||||
|
for a given GOOS/GOARCH pair must be generated on a system with that OS and
|
||||||
|
architecture. This also means that the generated code can differ from system
|
||||||
|
to system, based on differences in the header files.
|
||||||
|
|
||||||
|
To avoid this, if you are using the old build system, only generate the Go
|
||||||
|
files on an installation with unmodified header files. It is also important to
|
||||||
|
keep track of which version of the OS the files were generated from (ex.
|
||||||
|
Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
|
||||||
|
and have each OS upgrade correspond to a single change.
|
||||||
|
|
||||||
|
To build the files for your current OS and architecture, make sure GOOS and
|
||||||
|
GOARCH are set correctly and run `mkall.sh`. This will generate the files for
|
||||||
|
your specific system. Running `mkall.sh -n` shows the commands that will be run.
|
||||||
|
|
||||||
|
Requirements: bash, go
|
||||||
|
|
||||||
|
### New Build System (currently for `GOOS == "linux"`)
|
||||||
|
|
||||||
|
The new build system uses a Docker container to generate the go files directly
|
||||||
|
from source checkouts of the kernel and various system libraries. This means
|
||||||
|
that on any platform that supports Docker, all the files using the new build
|
||||||
|
system can be generated at once, and generated files will not change based on
|
||||||
|
what the person running the scripts has installed on their computer.
|
||||||
|
|
||||||
|
The OS specific files for the new build system are located in the `${GOOS}`
|
||||||
|
directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
|
||||||
|
the kernel or system library updates, modify the Dockerfile at
|
||||||
|
`${GOOS}/Dockerfile` to checkout the new release of the source.
|
||||||
|
|
||||||
|
To build all the files under the new build system, you must be on an amd64/Linux
|
||||||
|
system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
|
||||||
|
then generate all of the files for all of the GOOS/GOARCH pairs in the new build
|
||||||
|
system. Running `mkall.sh -n` shows the commands that will be run.
|
||||||
|
|
||||||
|
Requirements: bash, go, docker
|
||||||
|
|
||||||
|
## Component files
|
||||||
|
|
||||||
|
This section describes the various files used in the code generation process.
|
||||||
|
It also contains instructions on how to modify these files to add a new
|
||||||
|
architecture/OS or to add additional syscalls, types, or constants. Note that
|
||||||
|
if you are using the new build system, the scripts/programs cannot be called normally.
|
||||||
|
They must be called from within the docker container.
|
||||||
|
|
||||||
|
### asm files
|
||||||
|
|
||||||
|
The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
|
||||||
|
call dispatch. There are three entry points:
|
||||||
|
```
|
||||||
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||||
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
||||||
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||||
|
```
|
||||||
|
The first and second are the standard ones; they differ only in how many
|
||||||
|
arguments can be passed to the kernel. The third is for low-level use by the
|
||||||
|
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
|
||||||
|
let it know that a system call is running.
|
||||||
|
|
||||||
|
When porting Go to a new architecture/OS, this file must be implemented for
|
||||||
|
each GOOS/GOARCH pair.
|
||||||
|
|
||||||
|
### mksysnum
|
||||||
|
|
||||||
|
Mksysnum is a Go program located at `${GOOS}/mksysnum.go` (or `mksysnum_${GOOS}.go`
|
||||||
|
for the old system). This program takes in a list of header files containing the
|
||||||
|
syscall number declarations and parses them to produce the corresponding list of
|
||||||
|
Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
|
||||||
|
constants.
|
||||||
|
|
||||||
|
Adding new syscall numbers is mostly done by running the build on a sufficiently
|
||||||
|
new installation of the target OS (or updating the source checkouts for the
|
||||||
|
new build system). However, depending on the OS, you may need to update the
|
||||||
|
parsing in mksysnum.
|
||||||
|
|
||||||
|
### mksyscall.go
|
||||||
|
|
||||||
|
The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
|
||||||
|
hand-written Go files which implement system calls (for unix, the specific OS,
|
||||||
|
or the specific OS/Architecture pair respectively) that need special handling
|
||||||
|
and list `//sys` comments giving prototypes for ones that can be generated.
|
||||||
|
|
||||||
|
The mksyscall.go program takes the `//sys` and `//sysnb` comments and converts
|
||||||
|
them into syscalls. This requires the name of the prototype in the comment to
|
||||||
|
match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
|
||||||
|
prototype can be exported (capitalized) or not.
|
||||||
|
|
||||||
|
Adding a new syscall often just requires adding a new `//sys` function prototype
|
||||||
|
with the desired arguments and a capitalized name so it is exported. However, if
|
||||||
|
you want the interface to the syscall to be different, often one will make an
|
||||||
|
unexported `//sys` prototype, and then write a custom wrapper in
|
||||||
|
`syscall_${GOOS}.go`.
|
||||||
|
|
||||||
|
### types files
|
||||||
|
|
||||||
|
For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
|
||||||
|
`types_${GOOS}.go` on the old system). This file includes standard C headers and
|
||||||
|
creates Go type aliases to the corresponding C types. The file is then fed
|
||||||
|
through godef to get the Go compatible definitions. Finally, the generated code
|
||||||
|
is fed though mkpost.go to format the code correctly and remove any hidden or
|
||||||
|
private identifiers. This cleaned-up code is written to
|
||||||
|
`ztypes_${GOOS}_${GOARCH}.go`.
|
||||||
|
|
||||||
|
The hardest part about preparing this file is figuring out which headers to
|
||||||
|
include and which symbols need to be `#define`d to get the actual data
|
||||||
|
structures that pass through to the kernel system calls. Some C libraries
|
||||||
|
preset alternate versions for binary compatibility and translate them on the
|
||||||
|
way in and out of system calls, but there is almost always a `#define` that can
|
||||||
|
get the real ones.
|
||||||
|
See `types_darwin.go` and `linux/types.go` for examples.
|
||||||
|
|
||||||
|
To add a new type, add in the necessary include statement at the top of the
|
||||||
|
file (if it is not already there) and add in a type alias line. Note that if
|
||||||
|
your type is significantly different on different architectures, you may need
|
||||||
|
some `#if/#elif` macros in your include statements.
|
||||||
|
|
||||||
|
### mkerrors.sh
|
||||||
|
|
||||||
|
This script is used to generate the system's various constants. This doesn't
|
||||||
|
just include the error numbers and error strings, but also the signal numbers
|
||||||
|
and a wide variety of miscellaneous constants. The constants come from the list
|
||||||
|
of include files in the `includes_${uname}` variable. A regex then picks out
|
||||||
|
the desired `#define` statements, and generates the corresponding Go constants.
|
||||||
|
The error numbers and strings are generated from `#include <errno.h>`, and the
|
||||||
|
signal numbers and strings are generated from `#include <signal.h>`. All of
|
||||||
|
these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
|
||||||
|
`_errors.c`, which prints out all the constants.
|
||||||
|
|
||||||
|
To add a constant, add the header that includes it to the appropriate variable.
|
||||||
|
Then, edit the regex (if necessary) to match the desired constant. Avoid making
|
||||||
|
the regex too broad to avoid matching unintended constants.
|
||||||
|
|
||||||
|
### internal/mkmerge
|
||||||
|
|
||||||
|
This program is used to extract duplicate const, func, and type declarations
|
||||||
|
from the generated architecture-specific files listed below, and merge these
|
||||||
|
into a common file for each OS.
|
||||||
|
|
||||||
|
The merge is performed in the following steps:
|
||||||
|
1. Construct the set of common code that is identical in all architecture-specific files.
|
||||||
|
2. Write this common code to the merged file.
|
||||||
|
3. Remove the common code from all architecture-specific files.
|
||||||
|
|
||||||
|
|
||||||
|
## Generated files
|
||||||
|
|
||||||
|
### `zerrors_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A file containing all of the system's generated error numbers, error strings,
|
||||||
|
signal numbers, and constants. Generated by `mkerrors.sh` (see above).
|
||||||
|
|
||||||
|
### `zsyscall_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A file containing all the generated syscalls for a specific GOOS and GOARCH.
|
||||||
|
Generated by `mksyscall.go` (see above).
|
||||||
|
|
||||||
|
### `zsysnum_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A list of numeric constants for all the syscall number of the specific GOOS
|
||||||
|
and GOARCH. Generated by mksysnum (see above).
|
||||||
|
|
||||||
|
### `ztypes_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A file containing Go types for passing into (or returning from) syscalls.
|
||||||
|
Generated by godefs and the types file (see above).
|
||||||
86
vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
Normal file
86
vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// CPU affinity functions
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/bits"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
|
||||||
|
|
||||||
|
// CPUSet represents a CPU affinity mask.
|
||||||
|
type CPUSet [cpuSetSize]cpuMask
|
||||||
|
|
||||||
|
func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
|
||||||
|
_, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set)))
|
||||||
|
if e != 0 {
|
||||||
|
return errnoErr(e)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
|
||||||
|
// If pid is 0 the calling thread is used.
|
||||||
|
func SchedGetaffinity(pid int, set *CPUSet) error {
|
||||||
|
return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
|
||||||
|
// If pid is 0 the calling thread is used.
|
||||||
|
func SchedSetaffinity(pid int, set *CPUSet) error {
|
||||||
|
return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero clears the set s, so that it contains no CPUs.
|
||||||
|
func (s *CPUSet) Zero() {
|
||||||
|
for i := range s {
|
||||||
|
s[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpuBitsIndex(cpu int) int {
|
||||||
|
return cpu / _NCPUBITS
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpuBitsMask(cpu int) cpuMask {
|
||||||
|
return cpuMask(1 << (uint(cpu) % _NCPUBITS))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set adds cpu to the set s.
|
||||||
|
func (s *CPUSet) Set(cpu int) {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
s[i] |= cpuBitsMask(cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes cpu from the set s.
|
||||||
|
func (s *CPUSet) Clear(cpu int) {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
s[i] &^= cpuBitsMask(cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet reports whether cpu is in the set s.
|
||||||
|
func (s *CPUSet) IsSet(cpu int) bool {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
return s[i]&cpuBitsMask(cpu) != 0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of CPUs in the set s.
|
||||||
|
func (s *CPUSet) Count() int {
|
||||||
|
c := 0
|
||||||
|
for _, b := range s {
|
||||||
|
c += bits.OnesCount64(uint64(b))
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
13
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
Normal file
13
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
type Signal = syscall.Signal
|
||||||
|
type Errno = syscall.Errno
|
||||||
|
type SysProcAttr = syscall.SysProcAttr
|
||||||
17
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
Normal file
17
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go
|
||||||
|
//
|
||||||
|
|
||||||
|
TEXT ·syscall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·rawSyscall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·rawSyscall6(SB)
|
||||||
27
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
Normal file
27
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for 386 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
27
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
Normal file
27
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for AMD64 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
27
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
Normal file
27
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for ARM BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||||
|
B syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·RawSyscall6(SB)
|
||||||
27
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
Normal file
27
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for ARM64 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
29
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for ppc64, BSD
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
27
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
Normal file
27
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for RISCV64 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
65
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
Normal file
65
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for 386, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80
|
||||||
|
// instead of the glibc-specific "CALL 0x10(GS)".
|
||||||
|
#define INVOKE_SYSCALL INT $0x80
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVL trap+0(FP), AX // syscall entry
|
||||||
|
MOVL a1+4(FP), BX
|
||||||
|
MOVL a2+8(FP), CX
|
||||||
|
MOVL a3+12(FP), DX
|
||||||
|
MOVL $0, SI
|
||||||
|
MOVL $0, DI
|
||||||
|
INVOKE_SYSCALL
|
||||||
|
MOVL AX, r1+16(FP)
|
||||||
|
MOVL DX, r2+20(FP)
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVL trap+0(FP), AX // syscall entry
|
||||||
|
MOVL a1+4(FP), BX
|
||||||
|
MOVL a2+8(FP), CX
|
||||||
|
MOVL a3+12(FP), DX
|
||||||
|
MOVL $0, SI
|
||||||
|
MOVL $0, DI
|
||||||
|
INVOKE_SYSCALL
|
||||||
|
MOVL AX, r1+16(FP)
|
||||||
|
MOVL DX, r2+20(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·socketcall(SB),NOSPLIT,$0-36
|
||||||
|
JMP syscall·socketcall(SB)
|
||||||
|
|
||||||
|
TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
|
||||||
|
JMP syscall·rawsocketcall(SB)
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·seek(SB)
|
||||||
57
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
Normal file
57
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for AMD64, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVQ a1+8(FP), DI
|
||||||
|
MOVQ a2+16(FP), SI
|
||||||
|
MOVQ a3+24(FP), DX
|
||||||
|
MOVQ $0, R10
|
||||||
|
MOVQ $0, R8
|
||||||
|
MOVQ $0, R9
|
||||||
|
MOVQ trap+0(FP), AX // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVQ AX, r1+32(FP)
|
||||||
|
MOVQ DX, r2+40(FP)
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVQ a1+8(FP), DI
|
||||||
|
MOVQ a2+16(FP), SI
|
||||||
|
MOVQ a3+24(FP), DX
|
||||||
|
MOVQ $0, R10
|
||||||
|
MOVQ $0, R8
|
||||||
|
MOVQ $0, R9
|
||||||
|
MOVQ trap+0(FP), AX // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVQ AX, r1+32(FP)
|
||||||
|
MOVQ DX, r2+40(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·gettimeofday(SB),NOSPLIT,$0-16
|
||||||
|
JMP syscall·gettimeofday(SB)
|
||||||
56
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
Normal file
56
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for arm, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVW trap+0(FP), R7
|
||||||
|
MOVW a1+4(FP), R0
|
||||||
|
MOVW a2+8(FP), R1
|
||||||
|
MOVW a3+12(FP), R2
|
||||||
|
MOVW $0, R3
|
||||||
|
MOVW $0, R4
|
||||||
|
MOVW $0, R5
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, r1+16(FP)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW R0, r2+20(FP)
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVW trap+0(FP), R7 // syscall entry
|
||||||
|
MOVW a1+4(FP), R0
|
||||||
|
MOVW a2+8(FP), R1
|
||||||
|
MOVW a3+12(FP), R2
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, r1+16(FP)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW R0, r2+20(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·seek(SB)
|
||||||
50
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
Normal file
50
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build linux && arm64 && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
B syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R0
|
||||||
|
MOVD a2+16(FP), R1
|
||||||
|
MOVD a3+24(FP), R2
|
||||||
|
MOVD $0, R3
|
||||||
|
MOVD $0, R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD trap+0(FP), R8 // syscall entry
|
||||||
|
SVC
|
||||||
|
MOVD R0, r1+32(FP) // r1
|
||||||
|
MOVD R1, r2+40(FP) // r2
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
B syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVD a1+8(FP), R0
|
||||||
|
MOVD a2+16(FP), R1
|
||||||
|
MOVD a3+24(FP), R2
|
||||||
|
MOVD $0, R3
|
||||||
|
MOVD $0, R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD trap+0(FP), R8 // syscall entry
|
||||||
|
SVC
|
||||||
|
MOVD R0, r1+32(FP)
|
||||||
|
MOVD R1, r2+40(FP)
|
||||||
|
RET
|
||||||
51
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
Normal file
51
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build linux && loong64 && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
JAL runtime·entersyscall(SB)
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R11 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R4, r1+32(FP)
|
||||||
|
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||||
|
JAL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R11 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R4, r1+32(FP)
|
||||||
|
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||||
|
RET
|
||||||
54
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
Normal file
54
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build linux && (mips64 || mips64le) && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for mips64, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
JAL runtime·entersyscall(SB)
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R2, r1+32(FP)
|
||||||
|
MOVV R3, r2+40(FP)
|
||||||
|
JAL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R2, r1+32(FP)
|
||||||
|
MOVV R3, r2+40(FP)
|
||||||
|
RET
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user