<commit_before>// Copyright 2012 Martin Schnabel. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package diff implements a difference algorithm.
// The algorithm is described in "An O(ND) Difference Algorithm and its Variations", Eugene Myers, Algorithmica Vol. 1 No. 2, 1986, pp. 251-266.
package diff

// A type that satisfies diff.Data can be diffed by this package.
// It typically has two sequences A and B of comparable elements.
type Data interface {
	// Equal returns whether the elements at i and j are considered equal.
	Equal(i, j int) bool
}

// ByteStrings returns the differences of two strings in bytes.
func ByteStrings(a, b string) []Change {
	return Diff(len(a), len(b), &strings{a, b})
}

type strings struct{ a, b string }

func (d *strings) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Bytes returns the difference of two byte slices
func Bytes(a, b []byte) []Change {
	return Diff(len(a), len(b), &bytes{a, b})
}

type bytes struct{ a, b []byte }

func (d *bytes) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Ints returns the difference of two int slices
func Ints(a, b []int) []Change {
	return Diff(len(a), len(b), &ints{a, b})
}

type ints struct{ a, b []int }

func (d *ints) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Runes returns the difference of two rune slices
func Runes(a, b []rune) []Change {
	return Diff(len(a), len(b), &runes{a, b})
}

type runes struct{ a, b []rune }

func (d *runes) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Granular merges neighboring changes smaller than the specified granularity.
// The changes must be ordered by ascending positions as returned by this package.
func Granular(granularity int, changes []Change) []Change {
	if len(changes) == 0 {
		return changes
	}
	gap := 0
	for i := 1; i < len(changes); i++ {
		curr := changes[i]
		prev := changes[i-gap-1]
		// same as curr.B-(prev.B+prev.Ins); consistency is key
		if curr.A-(prev.A+prev.Del) <= granularity {
			// merge changes:
			curr = Change{
				A: prev.A, B: prev.B, // start at same spot
				Del: curr.A - prev.A + curr.Del, // from first to end of second
				Ins: curr.B - prev.B + curr.Ins, // from first to end of second
			}
			gap++
		}
		changes[i-gap] = curr
	}
	return changes[:len(changes)-gap : len(changes)-gap]
}

// Diff returns the differences of data.
// data.Equal is called repeatedly with 0<=i<n and 0<=j<m
func Diff(n, m int, data Data) []Change {
	c := &context{data: data}
	if n > m {
		c.flags = make([]byte, n)
	} else {
		c.flags = make([]byte, m)
	}
	c.max = n + m + 1
	c.compare(0, 0, n, m)
	return c.result(n, m)
}

// A Change contains one or more deletions or inserts
// at one position in two sequences.
type Change struct {
	A, B int // position in input a and b
	Del  int // delete Del elements from input a
	Ins  int // insert Ins elements from input b
}

type context struct {
	data  Data
	flags []byte // element bits 1 delete, 2 insert
	max   int
	// forward and reverse d-path endpoint x components
	forward, reverse []int
}

func (c *context) compare(aoffset, boffset, alimit, blimit int) {
	// eat common prefix
	for aoffset < alimit && boffset < blimit && c.data.Equal(aoffset, boffset) {
		aoffset++
		boffset++
	}
	// eat common suffix
	for alimit > aoffset && blimit > boffset && c.data.Equal(alimit-1, blimit-1) {
		alimit--
		blimit--
	}
	// both equal or b inserts
	if aoffset == alimit {
		for boffset < blimit {
			c.flags[boffset] |= 2
			boffset++
		}
		return
	}
	// a deletes
	if boffset == blimit {
		for aoffset < alimit {
			c.flags[aoffset] |= 1
			aoffset++
		}
		return
	}
	x, y := c.findMiddleSnake(aoffset, boffset, alimit, blimit)
	c.compare(aoffset, boffset, x, y)
	c.compare(x, y, alimit, blimit)
}

func (c *context) findMiddleSnake(aoffset, boffset, alimit, blimit int) (int, int) {
	// midpoints
	fmid := aoffset - boffset
	rmid := alimit - blimit
	// correct offset in d-path slices
	foff := c.max - fmid
	roff := c.max - rmid
	isodd := (rmid-fmid)&1 != 0
	maxd := (alimit - aoffset + blimit - boffset + 2) / 2
	// allocate when first used
	if c.forward == nil {
		c.forward = make([]int, 2*c.max)
		c.reverse = make([]int, 2*c.max)
	}
	c.forward[c.max+1] = aoffset
	c.reverse[c.max-1] = alimit
	var x, y int
	for d := 0; d <= maxd; d++ {
		// forward search
		for k := fmid - d; k <= fmid+d; k += 2 {
			if k == fmid-d || k != fmid+d && c.forward[foff+k+1] > c.forward[foff+k-1] {
				x = c.forward[foff+k+1] // down
			} else {
				x = c.forward[foff+k-1] + 1 // right
			}
			y = x - k
			for x < alimit && y < blimit && c.data.Equal(x, y) {
				x++
				y++
			}
			c.forward[foff+k] = x
			if isodd && k > rmid-d && k < rmid+d {
				if c.reverse[roff+k] <= c.forward[foff+k] {
					return x, x - k
				}
			}
		}
		// reverse search x,y correspond to u,v
		for k := rmid - d; k <= rmid+d; k += 2 {
			if k == rmid+d || k != rmid-d && c.reverse[roff+k-1] < c.reverse[roff+k+1] {
				x = c.reverse[roff+k-1] // up
			} else {
				x = c.reverse[roff+k+1] - 1 // left
			}
			y = x - k
			for x > aoffset && y > boffset && c.data.Equal(x-1, y-1) {
				x--
				y--
			}
			c.reverse[roff+k] = x
			if !isodd && k >= fmid-d && k <= fmid+d {
				if c.reverse[roff+k] <= c.forward[foff+k] {
					// lookup opposite end
					x = c.forward[foff+k]
					return x, x - k
				}
			}
		}
	}
	panic("should never be reached")
}

func (c *context) result(n, m int) (res []Change) {
	var x, y int
	for x < n || y < m {
		if x < n && y < m && c.flags[x]&1 == 0 && c.flags[y]&2 == 0 {
			x++
			y++
		} else {
			a := x
			b := y
			for x < n && (y >= m || c.flags[x]&1 != 0) {
				x++
			}
			for y < m && (x >= n || c.flags[y]&2 != 0) {
				y++
			}
			if a < x || b < y {
				res = append(res, Change{a, b, x - a, y - b})
			}
		}
	}
	return
}
<commit_msg>fixes compatibility issue #3. slicing the capacity is not really important here.<commit_after>// Copyright 2012 Martin Schnabel. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package diff implements a difference algorithm.
// The algorithm is described in "An O(ND) Difference Algorithm and its Variations", Eugene Myers, Algorithmica Vol. 1 No. 2, 1986, pp. 251-266.
package diff

// A type that satisfies diff.Data can be diffed by this package.
// It typically has two sequences A and B of comparable elements.
type Data interface {
	// Equal returns whether the elements at i and j are considered equal.
	Equal(i, j int) bool
}

// ByteStrings returns the differences of two strings in bytes.
func ByteStrings(a, b string) []Change {
	return Diff(len(a), len(b), &strings{a, b})
}

type strings struct{ a, b string }

func (d *strings) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Bytes returns the difference of two byte slices
func Bytes(a, b []byte) []Change {
	return Diff(len(a), len(b), &bytes{a, b})
}

type bytes struct{ a, b []byte }

func (d *bytes) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Ints returns the difference of two int slices
func Ints(a, b []int) []Change {
	return Diff(len(a), len(b), &ints{a, b})
}

type ints struct{ a, b []int }

func (d *ints) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Runes returns the difference of two rune slices
func Runes(a, b []rune) []Change {
	return Diff(len(a), len(b), &runes{a, b})
}

type runes struct{ a, b []rune }

func (d *runes) Equal(i, j int) bool { return d.a[i] == d.b[j] }

// Granular merges neighboring changes smaller than the specified granularity.
// The changes must be ordered by ascending positions as returned by this package.
func Granular(granularity int, changes []Change) []Change {
	if len(changes) == 0 {
		return changes
	}
	gap := 0
	for i := 1; i < len(changes); i++ {
		curr := changes[i]
		prev := changes[i-gap-1]
		// same as curr.B-(prev.B+prev.Ins); consistency is key
		if curr.A-(prev.A+prev.Del) <= granularity {
			// merge changes:
			curr = Change{
				A: prev.A, B: prev.B, // start at same spot
				Del: curr.A - prev.A + curr.Del, // from first to end of second
				Ins: curr.B - prev.B + curr.Ins, // from first to end of second
			}
			gap++
		}
		changes[i-gap] = curr
	}
	return changes[:len(changes)-gap]
}

// Diff returns the differences of data.
// data.Equal is called repeatedly with 0<=i<n and 0<=j<m
func Diff(n, m int, data Data) []Change {
	c := &context{data: data}
	if n > m {
		c.flags = make([]byte, n)
	} else {
		c.flags = make([]byte, m)
	}
	c.max = n + m + 1
	c.compare(0, 0, n, m)
	return c.result(n, m)
}

// A Change contains one or more deletions or inserts
// at one position in two sequences.
type Change struct {
	A, B int // position in input a and b
	Del  int // delete Del elements from input a
	Ins  int // insert Ins elements from input b
}

type context struct {
	data  Data
	flags []byte // element bits 1 delete, 2 insert
	max   int
	// forward and reverse d-path endpoint x components
	forward, reverse []int
}

func (c *context) compare(aoffset, boffset, alimit, blimit int) {
	// eat common prefix
	for aoffset < alimit && boffset < blimit && c.data.Equal(aoffset, boffset) {
		aoffset++
		boffset++
	}
	// eat common suffix
	for alimit > aoffset && blimit > boffset && c.data.Equal(alimit-1, blimit-1) {
		alimit--
		blimit--
	}
	// both equal or b inserts
	if aoffset == alimit {
		for boffset < blimit {
			c.flags[boffset] |= 2
			boffset++
		}
		return
	}
	// a deletes
	if boffset == blimit {
		for aoffset < alimit {
			c.flags[aoffset] |= 1
			aoffset++
		}
		return
	}
	x, y := c.findMiddleSnake(aoffset, boffset, alimit, blimit)
	c.compare(aoffset, boffset, x, y)
	c.compare(x, y, alimit, blimit)
}

func (c *context) findMiddleSnake(aoffset, boffset, alimit, blimit int) (int, int) {
	// midpoints
	fmid := aoffset - boffset
	rmid := alimit - blimit
	// correct offset in d-path slices
	foff := c.max - fmid
	roff := c.max - rmid
	isodd := (rmid-fmid)&1 != 0
	maxd := (alimit - aoffset + blimit - boffset + 2) / 2
	// allocate when first used
	if c.forward == nil {
		c.forward = make([]int, 2*c.max)
		c.reverse = make([]int, 2*c.max)
	}
	c.forward[c.max+1] = aoffset
	c.reverse[c.max-1] = alimit
	var x, y int
	for d := 0; d <= maxd; d++ {
		// forward search
		for k := fmid - d; k <= fmid+d; k += 2 {
			if k == fmid-d || k != fmid+d && c.forward[foff+k+1] > c.forward[foff+k-1] {
				x = c.forward[foff+k+1] // down
			} else {
				x = c.forward[foff+k-1] + 1 // right
			}
			y = x - k
			for x < alimit && y < blimit && c.data.Equal(x, y) {
				x++
				y++
			}
			c.forward[foff+k] = x
			if isodd && k > rmid-d && k < rmid+d {
				if c.reverse[roff+k] <= c.forward[foff+k] {
					return x, x - k
				}
			}
		}
		// reverse search x,y correspond to u,v
		for k := rmid - d; k <= rmid+d; k += 2 {
			if k == rmid+d || k != rmid-d && c.reverse[roff+k-1] < c.reverse[roff+k+1] {
				x = c.reverse[roff+k-1] // up
			} else {
				x = c.reverse[roff+k+1] - 1 // left
			}
			y = x - k
			for x > aoffset && y > boffset && c.data.Equal(x-1, y-1) {
				x--
				y--
			}
			c.reverse[roff+k] = x
			if !isodd && k >= fmid-d && k <= fmid+d {
				if c.reverse[roff+k] <= c.forward[foff+k] {
					// lookup opposite end
					x = c.forward[foff+k]
					return x, x - k
				}
			}
		}
	}
	panic("should never be reached")
}

func (c *context) result(n, m int) (res []Change) {
	var x, y int
	for x < n || y < m {
		if x < n && y < m && c.flags[x]&1 == 0 && c.flags[y]&2 == 0 {
			x++
			y++
		} else {
			a := x
			b := y
			for x < n && (y >= m || c.flags[x]&1 != 0) {
				x++
			}
			for y < m && (x >= n || c.flags[y]&2 != 0) {
				y++
			}
			if a < x || b < y {
				res = append(res, Change{a, b, x - a, y - b})
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"net"
	"os"
	"os/signal"
	"sync"

	"github.com/anacrolix/log"
	"github.com/davecgh/go-spew/spew"

	_ "github.com/anacrolix/envpprof"
	"github.com/anacrolix/tagflag"

	"github.com/anacrolix/dht/v2"
)

func main() {
	code := mainErr()
	if code != 0 {
		os.Exit(code)
	}
}

func mainErr() int {
	flags := struct {
		Port   int
		Debug  bool
		Scrape bool
		tagflag.StartPos
		Infohash [][20]byte
	}{}
	tagflag.Parse(&flags)
	if !flags.Debug {
		log.Default = log.Default.FilterLevel(log.Info)
	}
	s, err := dht.NewServer(func() *dht.ServerConfig {
		sc := dht.NewDefaultServerConfig()
		sc.Logger = log.Default
		return sc
	}())
	if err != nil {
		log.Printf("error creating server: %s", err)
		return 1
	}
	defer s.Close()
	var wg sync.WaitGroup
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
	defer cancel()
	addrs := make(map[[20]byte]map[string]struct{}, len(flags.Infohash))
	for _, ih := range flags.Infohash {
		// PSA: Go sucks.
		a, err := s.Announce(ih, flags.Port, false, func() (ret []dht.AnnounceOpt) {
			if flags.Scrape {
				ret = append(ret, dht.Scrape())
			}
			return
		}()...)
		if err != nil {
			log.Printf("error announcing %s: %s", ih, err)
			continue
		}
		wg.Add(1)
		addrs[ih] = make(map[string]struct{})
		go func(ih [20]byte) {
			defer wg.Done()
			defer a.Close()
		getPeers:
			for {
				select {
				case <-ctx.Done():
					a.StopTraversing()
					break getPeers
				case ps, ok := <-a.Peers:
					if !ok {
						break getPeers
					}
					for _, p := range ps.Peers {
						s := p.String()
						if _, ok := addrs[ih][s]; !ok {
							log.Printf("got peer %s for %x from %s", p, ih, ps.NodeInfo)
							addrs[ih][s] = struct{}{}
						}
					}
					if bf := ps.BFpe; bf != nil {
						log.Printf("%v claims %v peers for %x", ps.NodeInfo, bf.EstimateCount(), ih)
					}
					if bf := ps.BFsd; bf != nil {
						log.Printf("%v claims %v seeds for %x", ps.NodeInfo, bf.EstimateCount(), ih)
					}
				}
			}
			log.Levelf(log.Debug, "finishing traversal")
			<-a.Finished()
			log.Printf("%v contacted %v nodes", a, a.NumContacted())
		}(ih)
	}
	wg.Wait()
	spew.Dump(s.Stats())
	for _, ih := range flags.Infohash {
		ips := make(map[string]struct{}, len(addrs[ih]))
		for s := range addrs[ih] {
			ip, _, err := net.SplitHostPort(s)
			if err != nil {
				log.Printf("error parsing addr: %s", err)
			}
			ips[ip] = struct{}{}
		}
		log.Printf("%x: %d addrs %d distinct ips", ih, len(addrs[ih]), len(ips))
	}
	return 0
}
<commit_msg>cmd/dht-announce: Add addr flag<commit_after>package main

import (
	"context"
	"net"
	"os"
	"os/signal"
	"sync"

	"github.com/anacrolix/log"
	"github.com/davecgh/go-spew/spew"

	_ "github.com/anacrolix/envpprof"
	"github.com/anacrolix/tagflag"

	"github.com/anacrolix/dht/v2"
)

func main() {
	code := mainErr()
	if code != 0 {
		os.Exit(code)
	}
}

func mainErr() int {
	flags := struct {
		Port   int
		Debug  bool
		Scrape bool
		Addr   string
		tagflag.StartPos
		Infohash [][20]byte
	}{}
	tagflag.Parse(&flags)
	if !flags.Debug {
		log.Default = log.Default.FilterLevel(log.Info)
	}
	s, err := dht.NewServer(func() *dht.ServerConfig {
		sc := dht.NewDefaultServerConfig()
		if flags.Addr != "" {
			conn, err := net.ListenPacket("udp", flags.Addr)
			if err != nil {
				panic(err)
			}
			sc.Conn = conn
		}
		sc.Logger = log.Default
		return sc
	}())
	if err != nil {
		log.Printf("error creating server: %s", err)
		return 1
	}
	log.Printf("dht server at %v", s)
	defer s.Close()
	var wg sync.WaitGroup
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
	defer cancel()
	addrs := make(map[[20]byte]map[string]struct{}, len(flags.Infohash))
	for _, ih := range flags.Infohash {
		// PSA: Go sucks.
		a, err := s.Announce(ih, flags.Port, false, func() (ret []dht.AnnounceOpt) {
			if flags.Scrape {
				ret = append(ret, dht.Scrape())
			}
			return
		}()...)
		if err != nil {
			log.Printf("error announcing %s: %s", ih, err)
			continue
		}
		wg.Add(1)
		addrs[ih] = make(map[string]struct{})
		go func(ih [20]byte) {
			defer wg.Done()
			defer a.Close()
		getPeers:
			for {
				select {
				case <-ctx.Done():
					a.StopTraversing()
					break getPeers
				case ps, ok := <-a.Peers:
					if !ok {
						break getPeers
					}
					for _, p := range ps.Peers {
						s := p.String()
						if _, ok := addrs[ih][s]; !ok {
							log.Printf("got peer %s for %x from %s", p, ih, ps.NodeInfo)
							addrs[ih][s] = struct{}{}
						}
					}
					if bf := ps.BFpe; bf != nil {
						log.Printf("%v claims %v peers for %x", ps.NodeInfo, bf.EstimateCount(), ih)
					}
					if bf := ps.BFsd; bf != nil {
						log.Printf("%v claims %v seeds for %x", ps.NodeInfo, bf.EstimateCount(), ih)
					}
				}
			}
			log.Levelf(log.Debug, "finishing traversal")
			<-a.Finished()
			log.Printf("%v contacted %v nodes", a, a.NumContacted())
		}(ih)
	}
	wg.Wait()
	spew.Dump(s.Stats())
	for _, ih := range flags.Infohash {
		ips := make(map[string]struct{}, len(addrs[ih]))
		for s := range addrs[ih] {
			ip, _, err := net.SplitHostPort(s)
			if err != nil {
				log.Printf("error parsing addr: %s", err)
			}
			ips[ip] = struct{}{}
		}
		log.Printf("%x: %d addrs %d distinct ips", ih, len(addrs[ih]), len(ips))
	}
	return 0
}
<|endoftext|>


<commit_before>package chalmers_chop

type Allergen int

const (
	Gluten Allergen = iota
	Egg
	Milk
)

type Dish struct {
	Name string
	Contents string
	Price int
	Allergens []Allergen
}

func NewDish(name, contents string) *Dish {
	return &Dish{
		Name: name,
		Contents: contents,
	}
}
<commit_msg>Correct “Milk” allergen to “Lactose”<commit_after>package chalmers_chop

type Allergen int

const (
	Gluten Allergen = iota
	Egg
	Lactose
)

type Dish struct {
	Name string
	Contents string
	Price int
	Allergens []Allergen
}

func NewDish(name, contents string) *Dish {
	return &Dish{
		Name: name,
		Contents: contents,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"feiertage"
	"flag"
	"fmt"
	"strconv"
	"strings"
)

func fmtTaskjuggler(reg feiertage.Region) string {
	s := fmt.Sprintf("// publich holidays for %s (%s)", reg.Name, reg.Shortname)
	for _, f := range reg.Feiertage {
		s = fmt.Sprintf("%s \n leaves holiday \"%s\" 2011-12-24 +3d", s, f)
	}
	return s
}

func getRegion(region string, year int, includingSundays bool) feiertage.Region {
	rs := strings.ToLower(region)
	rep := strings.NewReplacer("-", "", "ä", "ae", "ö", "oe", "ü", "ue", "ß", "ss")
	rs = rep.Replace(rs)
	fmt.Println(includingSundays)
	var r feiertage.Region
	switch rs {
	case "badenwuerttemberg":
		r = feiertage.BadenWürttemberg(year, includingSundays)
	case "bayern":
		r = feiertage.Bayern(year, includingSundays)
	case "berlin":
		r = feiertage.Berlin(year, includingSundays)
	case "brandenburg":
		r = feiertage.Brandenburg(year, includingSundays)
	case "bremen":
		r = feiertage.Bremen(year, includingSundays)
	case "hamburg":
		r = feiertage.Hamburg(year, includingSundays)
	case "hessen":
		r = feiertage.Hessen(year, includingSundays)
	case "mecklenburgvorpommern":
		r = feiertage.MecklenburgVorpommern(year, includingSundays)
	case "niedersachsen":
		r = feiertage.Niedersachsen(year, includingSundays)
	case "nordrheinwestfalen":
		r = feiertage.NordrheinWestfalen(year, includingSundays)
	case "rheinlandpfalz":
		r = feiertage.RheinlandPfalz(year, includingSundays)
	case "saarland":
		r = feiertage.Saarland(year, includingSundays)
	case "sachsen":
		r = feiertage.Sachsen(year, includingSundays)
	case "sachsenanhalt":
		r = feiertage.SachsenAnhalt(year, includingSundays)
	case "schleswigholstein":
		r = feiertage.SchleswigHolstein(year, includingSundays)
	case "thueringen":
		r = feiertage.Thüringen(year, includingSundays)
	case "deutschland":
		r = feiertage.Deutschland(year, includingSundays)
	default:
		r = feiertage.All(year, includingSundays)
	}
	return r
}

func main() {
	var region = flag.String("region", "all", "Feiertag für Region 'string'.\n"+
		"\tRegion kann sein:\n"+
		"\t\tBadenWürttemberg\n"+
		"\t\tBayern\n"+
		"\t\tBerlin\n"+
		"\t\tBrandenburg\n"+
		"\t\tBremen\n"+
		"\t\tHamburg\n"+
		"\t\tHessen\n"+
		"\t\tMecklenburgVorpommern\n"+
		"\t\tNiedersachsen\n"+
		"\t\tNordrheinWestfalen\n"+
		"\t\tRheinlandPfalz\n"+
		"\t\tSaarland\n"+
		"\t\tSachsen\n"+
		"\t\tSachsenAnhalt\n"+
		"\t\tSchleswigHolstein\n"+
		"\t\tThüringen\n"+
		"\t\tDeutschland\n"+
		"\t\tAll\n")
	var includingSundays = flag.Bool("inklusiveSonntage", false, "Sollen Feiertag an Sonntagen mit ausgegeben werden?")
	var asTaskjugglerCode = flag.Bool("asTaskjugglerCode", false, "Taskjuggler Code ausgeben.")
	flag.Parse()
	if len(flag.Args()) > 0 {
		year, err := strconv.Atoi(flag.Args()[0])
		if err != nil {
			fmt.Println("Jahr muss eine Zahl sein.")
		} else {
			reg := getRegion(*region, year, *includingSundays)
			if *asTaskjugglerCode {
				fmt.Println(fmtTaskjuggler(reg))
			} else {
				fmt.Println(reg)
			}
		}
	} else {
		fmt.Println("Kein Jahr angegeben.")
	}
}
<commit_msg>added Takjuggler code generation to command line tool.<commit_after>package main

import (
	"feiertage"
	"flag"
	"fmt"
	"strconv"
	"strings"
)

func fmtTaskjuggler(reg feiertage.Region) string {
	s := fmt.Sprintf("# public holidays for %s (%s)", reg.Name, reg.Shortname)
	for _, f := range reg.Feiertage {
		s = fmt.Sprintf("%s,\n leaves holiday \"%s\" %s", s, f.Text, f.Format("2006-01-02"))
	}
	return s
}

func getRegion(region string, year int, includingSundays bool) feiertage.Region {
	rs := strings.ToLower(region)
	rep := strings.NewReplacer("-", "", "ä", "ae", "ö", "oe", "ü", "ue", "ß", "ss")
	rs = rep.Replace(rs)
	fmt.Println(includingSundays)
	var r feiertage.Region
	switch rs {
	case "badenwuerttemberg":
		r = feiertage.BadenWürttemberg(year, includingSundays)
	case "bayern":
		r = feiertage.Bayern(year, includingSundays)
	case "berlin":
		r = feiertage.Berlin(year, includingSundays)
	case "brandenburg":
		r = feiertage.Brandenburg(year, includingSundays)
	case "bremen":
		r = feiertage.Bremen(year, includingSundays)
	case "hamburg":
		r = feiertage.Hamburg(year, includingSundays)
	case "hessen":
		r = feiertage.Hessen(year, includingSundays)
	case "mecklenburgvorpommern":
		r = feiertage.MecklenburgVorpommern(year, includingSundays)
	case "niedersachsen":
		r = feiertage.Niedersachsen(year, includingSundays)
	case "nordrheinwestfalen":
		r = feiertage.NordrheinWestfalen(year, includingSundays)
	case "rheinlandpfalz":
		r = feiertage.RheinlandPfalz(year, includingSundays)
	case "saarland":
		r = feiertage.Saarland(year, includingSundays)
	case "sachsen":
		r = feiertage.Sachsen(year, includingSundays)
	case "sachsenanhalt":
		r = feiertage.SachsenAnhalt(year, includingSundays)
	case "schleswigholstein":
		r = feiertage.SchleswigHolstein(year, includingSundays)
	case "thueringen":
		r = feiertage.Thüringen(year, includingSundays)
	case "deutschland":
		r = feiertage.Deutschland(year, includingSundays)
	default:
		r = feiertage.All(year, includingSundays)
	}
	return r
}

func main() {
	var region = flag.String("region", "all", "Feiertag für Region 'string'.\n"+
		"\tRegion kann sein:\n"+
		"\t\tBadenWürttemberg\n"+
		"\t\tBayern\n"+
		"\t\tBerlin\n"+
		"\t\tBrandenburg\n"+
		"\t\tBremen\n"+
		"\t\tHamburg\n"+
		"\t\tHessen\n"+
		"\t\tMecklenburgVorpommern\n"+
		"\t\tNiedersachsen\n"+
		"\t\tNordrheinWestfalen\n"+
		"\t\tRheinlandPfalz\n"+
		"\t\tSaarland\n"+
		"\t\tSachsen\n"+
		"\t\tSachsenAnhalt\n"+
		"\t\tSchleswigHolstein\n"+
		"\t\tThüringen\n"+
		"\t\tDeutschland\n"+
		"\t\tAll\n")
	var includingSundays = flag.Bool("inklusiveSonntage", false, "Sollen Feiertag an Sonntagen mit ausgegeben werden?")
	var asTaskjugglerCode = flag.Bool("asTaskjugglerCode", false, "Taskjuggler Code ausgeben.")
	flag.Parse()
	if len(flag.Args()) > 0 {
		year, err := strconv.Atoi(flag.Args()[0])
		if err != nil {
			fmt.Println("Jahr muss eine Zahl sein.")
		} else {
			reg := getRegion(*region, year, *includingSundays)
			if *asTaskjugglerCode {
				fmt.Println(fmtTaskjuggler(reg))
			} else {
				fmt.Println(reg)
			}
		}
	} else {
		fmt.Println("Kein Jahr angegeben.")
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"hash/fnv"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"syscall"
	"time"

	consul "github.com/hashicorp/consul/api"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/route"
	"golang.org/x/net/context"

	"github.com/prometheus/prometheus/frankenstein"
	"github.com/prometheus/prometheus/frankenstein/api"
	"github.com/prometheus/prometheus/storage/local"
)

const (
	distributor = "distributor"
	ingestor    = "ingestor"
	infName     = "eth0"
)

func main() {
	var (
		mode                 string
		listenPort           int
		consulHost           string
		consulPrefix         string
		s3URL                string
		dynamodbURL          string
		dynamodbCreateTables bool
		memcachedHostname    string
		memcachedTimeout     time.Duration
		memcachedExpiration  time.Duration
		memcachedService     string
		remoteTimeout        time.Duration
	)

	flag.StringVar(&mode, "mode", distributor, "Mode (distributor, ingestor).")
	flag.IntVar(&listenPort, "web.listen-port", 9094, "HTTP server listen port.")
	flag.StringVar(&consulHost, "consul.hostname", "localhost:8500", "Hostname and port of Consul.")
	flag.StringVar(&consulPrefix, "consul.prefix", "collectors/", "Prefix for keys in Consul.")
	flag.StringVar(&s3URL, "s3.url", "localhost:4569", "S3 endpoint URL.")
	flag.StringVar(&dynamodbURL, "dynamodb.url", "localhost:8000", "DynamoDB endpoint URL.")
	flag.BoolVar(&dynamodbCreateTables, "dynamodb.create-tables", false, "Create required DynamoDB tables on startup.")
	flag.StringVar(&memcachedHostname, "memcached.hostname", "", "Hostname for memcached service to use when caching chunks. If empty, no memcached will be used.")
	flag.DurationVar(&memcachedTimeout, "memcached.timeout", 100*time.Millisecond, "Maximum time to wait before giving up on memcached requests.")
	flag.DurationVar(&memcachedExpiration, "memcached.expiration", 2*15*time.Second, "How long chunks stay in the memcache.")
	flag.StringVar(&memcachedService, "memcached.service", "memcached", "SRV service used to discover memcache servers.")
	flag.DurationVar(&remoteTimeout, "remote.timeout", 100*time.Millisecond, "Timeout for downstream ingestors.")
	flag.Parse()

	consul, err := frankenstein.NewConsulClient(consulHost)
	if err != nil {
		log.Fatalf("Error initializing Consul client: %v", err)
	}

	var memcache *frankenstein.MemcacheClient
	if memcachedHostname != "" {
		memcache = frankenstein.NewMemcacheClient(frankenstein.MemcacheConfig{
			Host:           memcachedHostname,
			Service:        memcachedService,
			Timeout:        memcachedTimeout,
			UpdateInterval: 1 * time.Minute,
		})
	}
	chunkStore, err := frankenstein.NewAWSChunkStore(frankenstein.ChunkStoreConfig{
		S3URL:          s3URL,
		DynamoDBURL:    dynamodbURL,
		MemcacheClient: memcache,
	})
	if err != nil {
		log.Fatal(err)
	}
	if dynamodbCreateTables {
		if err = chunkStore.CreateTables(); err != nil {
			log.Fatal(err)
		}
	}

	switch mode {
	case distributor:
		setupDistributor(consul, consulPrefix, chunkStore, remoteTimeout)
	case ingestor:
		ingestor := setupIngestor(consul, consulPrefix, chunkStore, listenPort)
		defer ingestor.Stop()
		defer deleteIngestorConfigFromConsul(consul, consulPrefix)
	default:
		log.Fatalf("Mode %s not supported!", mode)
	}

	http.Handle("/metrics", prometheus.Handler())
	go http.ListenAndServe(fmt.Sprintf(":%d", listenPort), nil)

	term := make(chan os.Signal)
	signal.Notify(term, os.Interrupt, syscall.SIGTERM)
	<-term
	log.Warn("Received SIGTERM, exiting gracefully...")
}

func setupDistributor(
	consulClient frankenstein.ConsulClient,
	consulPrefix string,
	chunkStore frankenstein.ChunkStore,
	remoteTimeout time.Duration,
) {
	clientFactory := func(hostname string) (*frankenstein.IngesterClient, error) {
		return frankenstein.NewIngesterClient(hostname, remoteTimeout), nil
	}

	distributor, err := frankenstein.NewDistributor(frankenstein.DistributorConfig{
		ConsulClient:  consulClient,
		ConsulPrefix:  consulPrefix,
		ClientFactory: clientFactory,
	})
	if err != nil {
		log.Fatal(err)
	}

	// This sets up a complete querying pipeline:
	//
	// PromQL -> MergeQuerier -> Distributor -> IngesterQuerier -> Ingester
	//              |
	//              +----------> ChunkQuerier -> DynamoDB/S3
	//
	// TODO: Move querier to separate binary.
	newQuerier := func(ctx context.Context) local.Querier {
		return frankenstein.MergeQuerier{
			Queriers: []frankenstein.Querier{
				distributor,
				&frankenstein.ChunkQuerier{
					Store: chunkStore,
				},
			},
			Context: ctx,
		}
	}

	api := api.New(newQuerier)
	router := route.New()
	api.Register(router.WithPrefix("/api/v1"))
	http.Handle("/", router)

	http.Handle("/api/prom/push", frankenstein.AppenderHandler(distributor))
}

func setupIngestor(
	consulClient frankenstein.ConsulClient,
	consulPrefix string,
	chunkStore frankenstein.ChunkStore,
	listenPort int,
) *local.Ingestor {
	for i := 0; i < 10; i++ {
		if err := writeIngestorConfigToConsul(consulClient, consulPrefix, listenPort); err == nil {
			break
		} else {
			log.Errorf("Failed to write to consul, sleeping: %v", err)
			time.Sleep(1 * time.Second)
		}
	}

	ingestor, err := local.NewIngestor(chunkStore)
	if err != nil {
		log.Fatal(err)
	}
	prometheus.MustRegister(ingestor)
	http.Handle("/push", frankenstein.AppenderHandler(ingestor))
	http.Handle("/query", frankenstein.QueryHandler(ingestor))
	return ingestor
}

// GetFirstAddressOf returns the first IPv4 address of the supplied interface name.
func GetFirstAddressOf(name string) (string, error) {
	inf, err := net.InterfaceByName(name)
	if err != nil {
		return "", err
	}

	addrs, err := inf.Addrs()
	if err != nil {
		return "", err
	}
	if len(addrs) <= 0 {
		return "", fmt.Errorf("No address found for %s", name)
	}

	for _, addr := range addrs {
		switch v := addr.(type) {
		case *net.IPNet:
			if ip := v.IP.To4(); ip != nil {
				return v.IP.String(), nil
			}
		}
	}

	return "", fmt.Errorf("No address found for %s", name)
}

func writeIngestorConfigToConsul(consulClient frankenstein.ConsulClient, consulPrefix string, listenPort int) error {
	log.Info("Adding ingestor to consul")

	hostname, err := os.Hostname()
	if err != nil {
		return err
	}

	addr, err := GetFirstAddressOf(infName)
	if err != nil {
		return err
	}

	tokenHasher := fnv.New64()
	tokenHasher.Write([]byte(hostname))

	buf, err := json.Marshal(frankenstein.Collector{
		Hostname: fmt.Sprintf("%s:%d", addr, listenPort),
		Tokens:   []uint64{tokenHasher.Sum64()},
	})
	if err != nil {
		return err
	}

	_, err = consulClient.Put(&consul.KVPair{
		Key:   consulPrefix + hostname,
		Value: buf,
	}, &consul.WriteOptions{})
	return err
}

func deleteIngestorConfigFromConsul(consulClient frankenstein.ConsulClient, consulPrefix string) error {
	log.Info("Removing ingestor from consul")

	hostname, err := os.Hostname()
	if err != nil {
		return err
	}

	buf, err := json.Marshal(frankenstein.Collector{
		Hostname: "",
		Tokens:   []uint64{},
	})
	if err != nil {
		return err
	}

	_, err = consulClient.Put(&consul.KVPair{
		Key:   consulPrefix + hostname,
		Value: buf,
	}, &consul.WriteOptions{})
	return err
}
<commit_msg>Add prefix /api/prom to query api<commit_after>// Copyright 2016 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"hash/fnv"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"syscall"
	"time"

	consul "github.com/hashicorp/consul/api"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/route"
	"golang.org/x/net/context"

	"github.com/prometheus/prometheus/frankenstein"
	"github.com/prometheus/prometheus/frankenstein/api"
	"github.com/prometheus/prometheus/storage/local"
)

const (
	distributor = "distributor"
	ingestor    = "ingestor"
	infName     = "eth0"
)

func main() {
	var (
		mode                 string
		listenPort           int
		consulHost           string
		consulPrefix         string
		s3URL                string
		dynamodbURL          string
		dynamodbCreateTables bool
		memcachedHostname    string
		memcachedTimeout     time.Duration
		memcachedExpiration  time.Duration
		memcachedService     string
		remoteTimeout        time.Duration
	)

	flag.StringVar(&mode, "mode", distributor, "Mode (distributor, ingestor).")
	flag.IntVar(&listenPort, "web.listen-port", 9094, "HTTP server listen port.")
	flag.StringVar(&consulHost, "consul.hostname", "localhost:8500", "Hostname and port of Consul.")
	flag.StringVar(&consulPrefix, "consul.prefix", "collectors/", "Prefix for keys in Consul.")
	flag.StringVar(&s3URL, "s3.url", "localhost:4569", "S3 endpoint URL.")
	flag.StringVar(&dynamodbURL, "dynamodb.url", "localhost:8000", "DynamoDB endpoint URL.")
	flag.BoolVar(&dynamodbCreateTables, "dynamodb.create-tables", false, "Create required DynamoDB tables on startup.")
	flag.StringVar(&memcachedHostname, "memcached.hostname", "", "Hostname for memcached service to use when caching chunks. If empty, no memcached will be used.")
	flag.DurationVar(&memcachedTimeout, "memcached.timeout", 100*time.Millisecond, "Maximum time to wait before giving up on memcached requests.")
	flag.DurationVar(&memcachedExpiration, "memcached.expiration", 2*15*time.Second, "How long chunks stay in the memcache.")
	flag.StringVar(&memcachedService, "memcached.service", "memcached", "SRV service used to discover memcache servers.")
	flag.DurationVar(&remoteTimeout, "remote.timeout", 100*time.Millisecond, "Timeout for downstream ingestors.")
	flag.Parse()

	consul, err := frankenstein.NewConsulClient(consulHost)
	if err != nil {
		log.Fatalf("Error initializing Consul client: %v", err)
	}

	var memcache *frankenstein.MemcacheClient
	if memcachedHostname != "" {
		memcache = frankenstein.NewMemcacheClient(frankenstein.MemcacheConfig{
			Host:           memcachedHostname,
			Service:        memcachedService,
			Timeout:        memcachedTimeout,
			UpdateInterval: 1 * time.Minute,
		})
	}
	chunkStore, err := frankenstein.NewAWSChunkStore(frankenstein.ChunkStoreConfig{
		S3URL:          s3URL,
		DynamoDBURL:    dynamodbURL,
		MemcacheClient: memcache,
	})
	if err != nil {
		log.Fatal(err)
	}
	if dynamodbCreateTables {
		if err = chunkStore.CreateTables(); err != nil {
			log.Fatal(err)
		}
	}

	switch mode {
	case distributor:
		setupDistributor(consul, consulPrefix, chunkStore, remoteTimeout)
	case ingestor:
		ingestor := setupIngestor(consul, consulPrefix, chunkStore, listenPort)
		defer ingestor.Stop()
		defer deleteIngestorConfigFromConsul(consul, consulPrefix)
	default:
		log.Fatalf("Mode %s not supported!", mode)
	}

	http.Handle("/metrics", prometheus.Handler())
	go http.ListenAndServe(fmt.Sprintf(":%d", listenPort), nil)

	term := make(chan os.Signal)
	signal.Notify(term, os.Interrupt, syscall.SIGTERM)
	<-term
	log.Warn("Received SIGTERM, exiting gracefully...")
}

func setupDistributor(
	consulClient frankenstein.ConsulClient,
	consulPrefix string,
	chunkStore frankenstein.ChunkStore,
	remoteTimeout time.Duration,
) {
	clientFactory := func(hostname string) (*frankenstein.IngesterClient, error) {
		return frankenstein.NewIngesterClient(hostname, remoteTimeout), nil
	}
	distributor, err := frankenstein.NewDistributor(frankenstein.DistributorConfig{
		ConsulClient:  consulClient,
		ConsulPrefix:  consulPrefix,
		ClientFactory: clientFactory,
	})
	if err != nil {
		log.Fatal(err)
	}
	http.Handle("/api/prom/push", frankenstein.AppenderHandler(distributor))

	// This sets up a complete querying pipeline:
	//
	// PromQL -> MergeQuerier -> Distributor -> IngesterQuerier -> Ingester
	//              |
	//              +----------> ChunkQuerier -> DynamoDB/S3
	//
	// TODO: Move querier to separate binary.
	newQuerier := func(ctx context.Context) local.Querier {
		return frankenstein.MergeQuerier{
			Queriers: []frankenstein.Querier{
				distributor,
				&frankenstein.ChunkQuerier{
					Store: chunkStore,
				},
			},
			Context: ctx,
		}
	}

	api := api.New(newQuerier)
	router := route.New()
	api.Register(router.WithPrefix("/api/prom/api/v1"))
	http.Handle("/", router)
}

func setupIngestor(
	consulClient frankenstein.ConsulClient,
	consulPrefix string,
	chunkStore frankenstein.ChunkStore,
	listenPort int,
) *local.Ingestor {
	for i := 0; i < 10; i++ {
		if err := writeIngestorConfigToConsul(consulClient, consulPrefix, listenPort); err == nil {
			break
		} else {
			log.Errorf("Failed to write to consul, sleeping: %v", err)
			time.Sleep(1 * time.Second)
		}
	}

	ingestor, err := local.NewIngestor(chunkStore)
	if err != nil {
		log.Fatal(err)
	}
	prometheus.MustRegister(ingestor)
	http.Handle("/push", frankenstein.AppenderHandler(ingestor))
	http.Handle("/query", frankenstein.QueryHandler(ingestor))
	return ingestor
}

// GetFirstAddressOf returns the first IPv4 address of the supplied interface name.
func GetFirstAddressOf(name string) (string, error) {
	inf, err := net.InterfaceByName(name)
	if err != nil {
		return "", err
	}

	addrs, err := inf.Addrs()
	if err != nil {
		return "", err
	}
	if len(addrs) <= 0 {
		return "", fmt.Errorf("No address found for %s", name)
	}

	for _, addr := range addrs {
		switch v := addr.(type) {
		case *net.IPNet:
			if ip := v.IP.To4(); ip != nil {
				return v.IP.String(), nil
			}
		}
	}

	return "", fmt.Errorf("No address found for %s", name)
}

func writeIngestorConfigToConsul(consulClient frankenstein.ConsulClient, consulPrefix string, listenPort int) error {
	log.Info("Adding ingestor to consul")

	hostname, err := os.Hostname()
	if err != nil {
		return err
	}

	addr, err := GetFirstAddressOf(infName)
	if err != nil {
		return err
	}

	tokenHasher := fnv.New64()
	tokenHasher.Write([]byte(hostname))

	buf, err := json.Marshal(frankenstein.Collector{
		Hostname: fmt.Sprintf("%s:%d", addr, listenPort),
		Tokens:   []uint64{tokenHasher.Sum64()},
	})
	if err != nil {
		return err
	}

	_, err = consulClient.Put(&consul.KVPair{
		Key:   consulPrefix + hostname,
		Value: buf,
	}, &consul.WriteOptions{})
	return err
}

func deleteIngestorConfigFromConsul(consulClient frankenstein.ConsulClient, consulPrefix string) error {
	log.Info("Removing ingestor from consul")

	hostname, err := os.Hostname()
	if err != nil {
		return err
	}

	buf, err := json.Marshal(frankenstein.Collector{
		Hostname: "",
		Tokens:   []uint64{},
	})
	if err != nil {
		return err
	}

	_, err = consulClient.Put(&consul.KVPair{
		Key:   consulPrefix + hostname,
		Value: buf,
	}, &consul.WriteOptions{})
	return err
}
<|endoftext|>


<commit_before>package prove

import (
	"bytes"
	"fmt"
	"log"
	"runtime"
	"time"

	"github.com/nelhage/taktician/tak"
)

type evaluation int8

const (
	evalUnknown evaluation = iota
	evalTrue
	evalFalse
)

const (
	flagIrreversible = 1 << iota
	flagExpanded     = 1 << iota
)

const inf = ^uint64(0)

type node struct {
	parent          *node
	position        *tak.Position
	proof, disproof uint64

	value evaluation
	flags int32

	children []*node
}

func (n *node) expanded() bool {
	return n.flags&flagExpanded != 0
}

func (n *node) depth() int {
	d := 0
	for n.parent != nil {
		n = n.parent
		d += 1
	}
	return d
}

type prover struct {
	stats struct {
		nodes     uint64
		proved    uint64
		disproved uint64
		dropped   uint64
	}
	player tak.Color
	root   *node
}

func prove(pos *tak.Position) {
	p := prover{
		player: pos.ToMove(),
	}
	p.prove(pos)
}

const kProgressFrequency = 10000

func (p *prover) prove(pos *tak.Position) {
	start := time.Now()
	p.stats.nodes += 1
	p.root = &node{
		position: pos,
		parent:   nil,
	}
	p.evaluate(p.root)
	p.setNumbers(p.root)
	var i uint64
	current := p.root
	for p.root.proof != 0 && p.root.disproof != 0 {
		i++
		next := p.selectMostProving(current)

		if i%kProgressFrequency == 0 {
			var stats runtime.MemStats
			runtime.ReadMemStats(&stats)
			log.Printf("time=%s nodes=%d live=%d done=%d/%d/%d root=(%d, %d) heap=%d",
				time.Since(start),
				p.stats.nodes,
				p.stats.nodes-(p.stats.proved+p.stats.disproved+p.stats.dropped),
				p.stats.proved,
				p.stats.disproved,
				p.stats.dropped,
				p.root.proof,
				p.root.disproof,
				stats.HeapAlloc,
			)
			/*
				log.Printf("  children=%s", formatChildren(p.root.children))
			*/

		}

		p.expand(next)
		current = p.updateAncestors(next)
	}
	log.Printf("Done in %s, nodes=%d proof=%d disproof=%d",
		time.Since(start),
		p.stats.nodes,
		p.root.proof,
		p.root.disproof,
	)
}

func (p *prover) checkRepetition(n *node) bool {
	if (n.flags & flagIrreversible) != 0 {
		return false
	}
	count := 1
	walk := n.parent
	for walk != nil && (walk.flags&flagIrreversible) == 0 && count < 3 {
		if walk.position.Equal(n.position) {
			count += 1
		}
		walk = walk.parent
	}
	return count == 3
}

func (p *prover) evaluate(node *node) {
	if over, who := node.position.GameOver(); over {
		if who == p.player {
			node.value = evalTrue
		} else {
			node.value = evalFalse
		}
	} else {
		if p.checkRepetition(node) {
			node.value = evalFalse
		} else {
			node.value = evalUnknown
		}

	}
}

func (p *prover) setNumbers(node *node) {
	if node.expanded() {
		if p.andNode(node) {
			node.proof = 0
			node.disproof = inf
			for _, c := range node.children {
				node.proof += c.proof
				if c.disproof < node.disproof {
					node.disproof = c.disproof
				}
			}
			if node.disproof == 0 {
				node.proof = inf
			}
		} else {
			node.proof = inf
			node.disproof = 0
			for _, c := range node.children {
				node.disproof += c.disproof
				if c.proof < node.proof {
					node.proof = c.proof
				}
			}
			if node.proof == 0 {
				node.disproof = inf
			}
		}
	} else {
		switch node.value {
		case evalTrue:
			node.proof = 0
			node.disproof = inf
		case evalFalse:
			node.proof = inf
			node.disproof = 0
		case evalUnknown:
			node.proof = 1
			node.disproof = 1
		}
	}
}

func formatChildren(children []*node) string {
	var buf bytes.Buffer
	for _, c := range children {
		fmt.Fprintf(&buf, "(%d, %d) ", c.proof, c.disproof)
	}
	return buf.String()
}

func (p *prover) selectMostProving(current *node) *node {
	for current.expanded() {
		var child *node
		if p.andNode(current) {
			for _, c := range current.children {
				if c.disproof == current.disproof {
					child = c
					break
				}
			}

		} else {
			for _, c := range current.children {
				if c.proof == current.proof {
					child = c
					break
				}
			}
		}
		if child == nil {
			var ty string
			if p.andNode(current) {
				ty = "AND"
			} else {
				ty = "OR"
			}
			log.Printf("consistency error depth=%d type=%s proof=%d disproof=%d",
				current.depth(),
				ty,
				current.proof,
				current.disproof,
			)
			log.Printf("children: %s", formatChildren(current.children))
			panic("consistency error")
		}
		current = child
	}
	return current
}

func (p *prover) andNode(n *node) bool {
	return n.position.ToMove() != p.player
}

func (p *prover) expand(n *node) {
	var buffer [30]tak.Move
	allMoves := n.position.AllMoves(buffer[:])
	for _, m := range allMoves {
		cn, e := n.position.Move(m)
		if e != nil {
			continue
		}
		p.stats.nodes += 1
		child := &node{
			position: cn,
			parent:   n,
		}

		dx, dy := m.Dest()
		reversible := m.IsSlide() && n.position.Top(int(dx), int(dy)).Kind() != tak.Standing
		if !reversible {
			child.flags |= flagIrreversible
		}
		p.evaluate(child)
		p.setNumbers(child)
		n.children = append(n.children, child)
		if (p.andNode(n) && child.proof == 0) || (!p.andNode(n) && child.disproof == 0) {
			break
		}
	}
	n.flags |= flagExpanded
}

func (p *prover) updateAncestors(node *node) *node {
	for true {
		oldproof := node.proof
		olddisproof := node.disproof
		p.setNumbers(node)
		if node.proof == 0 || node.disproof == 0 {
			if node.proof == 0 {
				p.stats.proved += 1
				if !p.andNode(node) {
					p.stats.dropped += uint64(len(node.children) - 1)
				}
			} else {
				p.stats.disproved += 1
				if p.andNode(node) {
					p.stats.dropped += uint64(len(node.children) - 1)
				}
			}
			node.children = nil
		} else if node.proof == oldproof && node.disproof == olddisproof {
			return node
		}

		if node.parent == nil {
			return node
		}
		node = node.parent
	}
	return node
}
<commit_msg>We can use 32 bits for these<commit_after>package prove

import (
	"bytes"
	"fmt"
	"log"
	"runtime"
	"time"

	"github.com/nelhage/taktician/tak"
)

type evaluation int8

const (
	evalUnknown evaluation = iota
	evalTrue
	evalFalse
)

const (
	flagIrreversible = 1 << iota
	flagExpanded     = 1 << iota
)

const inf = ^uint32(0)

type node struct {
	parent          *node
	position        *tak.Position
	proof, disproof uint32

	value evaluation
	flags int32

	children []*node
}

func (n *node) expanded() bool {
	return n.flags&flagExpanded != 0
}

func (n *node) depth() int {
	d := 0
	for n.parent != nil {
		n = n.parent
		d += 1
	}
	return d
}

type prover struct {
	stats struct {
		nodes     uint64
		proved    uint64
		disproved uint64
		dropped   uint64
	}
	player tak.Color
	root   *node
}

func prove(pos *tak.Position) {
	p := prover{
		player: pos.ToMove(),
	}
	p.prove(pos)
}

const kProgressFrequency = 10000

func (p *prover) prove(pos *tak.Position) {
	start := time.Now()
	p.stats.nodes += 1
	p.root = &node{
		position: pos,
		parent:   nil,
	}
	p.evaluate(p.root)
	p.setNumbers(p.root)
	var i uint64
	current := p.root
	for p.root.proof != 0 && p.root.disproof != 0 {
		i++
		next := p.selectMostProving(current)

		if i%kProgressFrequency == 0 {
			var stats runtime.MemStats
			runtime.ReadMemStats(&stats)
			log.Printf("time=%s nodes=%d live=%d done=%d/%d/%d root=(%d, %d) heap=%d",
				time.Since(start),
				p.stats.nodes,
				p.stats.nodes-(p.stats.proved+p.stats.disproved+p.stats.dropped),
				p.stats.proved,
				p.stats.disproved,
				p.stats.dropped,
				p.root.proof,
				p.root.disproof,
				stats.HeapAlloc,
			)
			/*
				log.Printf("  children=%s", formatChildren(p.root.children))
			*/

		}

		p.expand(next)
		current = p.updateAncestors(next)
	}
	log.Printf("Done in %s, nodes=%d proof=%d disproof=%d",
		time.Since(start),
		p.stats.nodes,
		p.root.proof,
		p.root.disproof,
	)
}

func (p *prover) checkRepetition(n *node) bool {
	if (n.flags & flagIrreversible) != 0 {
		return false
	}
	count := 1
	walk := n.parent
	for walk != nil && (walk.flags&flagIrreversible) == 0 && count < 3 {
		if walk.position.Equal(n.position) {
			count += 1
		}
		walk = walk.parent
	}
	return count == 3
}

func (p *prover) evaluate(node *node) {
	if over, who := node.position.GameOver(); over {
		if who == p.player {
			node.value = evalTrue
		} else {
			node.value = evalFalse
		}
	} else {
		if p.checkRepetition(node) {
			node.value = evalFalse
		} else {
			node.value = evalUnknown
		}

	}
}

func (p *prover) setNumbers(node *node) {
	if node.expanded() {
		if p.andNode(node) {
			node.proof = 0
			node.disproof = inf
			for _, c := range node.children {
				node.proof += c.proof
				if c.disproof < node.disproof {
					node.disproof = c.disproof
				}
			}
			if node.disproof == 0 {
				node.proof = inf
			}
		} else {
			node.proof = inf
			node.disproof = 0
			for _, c := range node.children {
				node.disproof += c.disproof
				if c.proof < node.proof {
					node.proof = c.proof
				}
			}
			if node.proof == 0 {
				node.disproof = inf
			}
		}
	} else {
		switch node.value {
		case evalTrue:
			node.proof = 0
			node.disproof = inf
		case evalFalse:
			node.proof = inf
			node.disproof = 0
		case evalUnknown:
			node.proof = 1
			node.disproof = 1
		}
	}
}

func formatChildren(children []*node) string {
	var buf bytes.Buffer
	for _, c := range children {
		fmt.Fprintf(&buf, "(%d, %d) ", c.proof, c.disproof)
	}
	return buf.String()
}

func (p *prover) selectMostProving(current *node) *node {
	for current.expanded() {
		var child *node
		if p.andNode(current) {
			for _, c := range current.children {
				if c.disproof == current.disproof {
					child = c
					break
				}
			}

		} else {
			for _, c := range current.children {
				if c.proof == current.proof {
					child = c
					break
				}
			}
		}
		if child == nil {
			var ty string
			if p.andNode(current) {
				ty = "AND"
			} else {
				ty = "OR"
			}
			log.Printf("consistency error depth=%d type=%s proof=%d disproof=%d",
				current.depth(),
				ty,
				current.proof,
				current.disproof,
			)
			log.Printf("children: %s", formatChildren(current.children))
			panic("consistency error")
		}
		current = child
	}
	return current
}

func (p *prover) andNode(n *node) bool {
	return n.position.ToMove() != p.player
}

func (p *prover) expand(n *node) {
	var buffer [30]tak.Move
	allMoves := n.position.AllMoves(buffer[:])
	for _, m := range allMoves {
		cn, e := n.position.Move(m)
		if e != nil {
			continue
		}
		p.stats.nodes += 1
		child := &node{
			position: cn,
			parent:   n,
		}

		dx, dy := m.Dest()
		reversible := m.IsSlide() && n.position.Top(int(dx), int(dy)).Kind() != tak.Standing
		if !reversible {
			child.flags |= flagIrreversible
		}
		p.evaluate(child)
		p.setNumbers(child)
		n.children = append(n.children, child)
		if (p.andNode(n) && child.proof == 0) || (!p.andNode(n) && child.disproof == 0) {
			break
		}
	}
	n.flags |= flagExpanded
}

func (p *prover) updateAncestors(node *node) *node {
	for true {
		oldproof := node.proof
		olddisproof := node.disproof
		p.setNumbers(node)
		if node.proof == 0 || node.disproof == 0 {
			if node.proof == 0 {
				p.stats.proved += 1
				if !p.andNode(node) {
					p.stats.dropped += uint64(len(node.children) - 1)
				}
			} else {
				p.stats.disproved += 1
				if p.andNode(node) {
					p.stats.dropped += uint64(len(node.children) - 1)
				}
			}
			node.children = nil
		} else if node.proof == oldproof && node.disproof == olddisproof {
			return node
		}

		if node.parent == nil {
			return node
		}
		node = node.parent
	}
	return node
}
<|endoftext|>


<commit_before>package dlog

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	// SEPARATOR = "▶"
	SEPARATOR = ":"
)

// round robin color
var i = 0

// terminal colors
var colors = []uint8{
	31,
	32,
	33,
	34,
	35,
	36,
}

var enabled = false

// as long as DLOG env is not empty -> show log
func init() {
	if os.Getenv("DLOG") != "" {
		enabled = true
	}
}

type Option struct {
	Name   string
	Writer io.Writer
	Hook   chan<- *Log
}

// Caller: function name
type Log struct {
	Name   string `json:"name"`
	Caller string `json:"caller"`

	Timestamp time.Time     `json:"timestamp"`
	Delta     time.Duration `json:"delta"`

	Data []interface{} `json:"data"`
}

func New(opt *Option) func(...interface{}) {
	// disable dlog
	// or should we send it to dev/null ?
	if !enabled {
		return func(...interface{}) {}
	}

	// blank option as default
	if opt == nil {
		opt = &Option{}
	}

	// color
	color := colors[i%len(colors)]
	i++

	// save for delta
	prevTime := time.Now()

	return func(arg ...interface{}) {
		now := time.Now()

		delta := now.Sub(prevTime)
		prevTime = now

		log := &Log{
			Name:   opt.Name,
			Caller: getCaller(),

			Timestamp: now,
			Delta:     delta,

			Data: arg,
		}

		// writer to writer
		write(opt.Writer, log, color)

		// send to hook
		if opt.Hook != nil {
			opt.Hook <- log
		}
	}
}

func write(writer io.Writer, log *Log, color uint8) {
	if writer != nil && writer != os.Stdout {
		jsonStr, err := json.Marshal(log)

		// skip err
		if err != nil {
			return
		}

		// skip err
		fmt.Fprintln(writer, string(jsonStr))
		return
	}

	writer = os.Stdout

	timestamp := log.Timestamp.Format("15:04:05.000")

	prefix := fmt.Sprintf("\033[%vm%v %-6s %-10s #%v %v\033[0m", color, timestamp, humanizeNano(log.Delta), log.Name, log.Caller, SEPARATOR)

	arg := append([]interface{}{prefix}, log.Data...)

	// skip err
	fmt.Fprintln(writer, arg...)
}

func getCaller() (caller string) {
	caller = ""

	pc := make([]uintptr, 1)

	if runtime.Callers(3, pc) == 1 {
		f := runtime.FuncForPC(pc[0])
		caller = trimCaller(f.Name())
	}

	return
}

// "github.com/ddo/request.(*Client).Request"
// -> (*Client).Request
// or
// "github.com/ddo/request.New"
// -> New
func trimCaller(funcName string) string {
	// ex:
	// funcName = "github.com/ddo/request.(*Client).Request"
	// arrDir = [github.com ddo request.(*Client).Request]
	// lastDir = request.(*Client).Request
	// arrCaller = [request. (*Client).Request]

	arrDir := strings.Split(funcName, "/")
	lastDir := arrDir[len(arrDir)-1]
	arrCaller := strings.SplitAfterN(lastDir, ".", 2)

	if len(arrCaller) < 2 {
		return ""
	}

	return arrCaller[1]
}

// copty from TJ
func humanizeNano(n time.Duration) string {
	var suffix string

	switch {
	case n > 1e9:
		n /= 1e9
		suffix = "s"
	case n > 1e6:
		n /= 1e6
		suffix = "ms"
	case n > 1e3:
		n /= 1e3
		suffix = "us"
	default:
		suffix = "ns"
	}

	return strconv.Itoa(int(n)) + suffix
}
<commit_msg>name is a separated param<commit_after>package dlog

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	// SEPARATOR = "▶"
	SEPARATOR = ":"
)

// round robin color
var i = 0

// terminal colors
var colors = []uint8{
	31,
	32,
	33,
	34,
	35,
	36,
}

var enabled = false

// as long as DLOG env is not empty -> show log
func init() {
	if os.Getenv("DLOG") != "" {
		enabled = true
	}
}

type Option struct {
	Writer io.Writer
	Hook   chan<- *Log
}

// Caller: function name
type Log struct {
	Name   string `json:"name"`
	Caller string `json:"caller"`

	Timestamp time.Time     `json:"timestamp"`
	Delta     time.Duration `json:"delta"`

	Data []interface{} `json:"data"`
}

func New(name string, opt *Option) func(...interface{}) {
	// disable dlog
	// or should we send it to dev/null ?
	if !enabled {
		return func(...interface{}) {}
	}

	// blank option as default
	if opt == nil {
		opt = &Option{}
	}

	// color
	color := colors[i%len(colors)]
	i++

	// save for delta
	prevTime := time.Now()

	return func(arg ...interface{}) {
		now := time.Now()

		delta := now.Sub(prevTime)
		prevTime = now

		log := &Log{
			Name:   name,
			Caller: getCaller(),

			Timestamp: now,
			Delta:     delta,

			Data: arg,
		}

		// writer to writer
		write(opt.Writer, log, color)

		// send to hook
		if opt.Hook != nil {
			opt.Hook <- log
		}
	}
}

func write(writer io.Writer, log *Log, color uint8) {
	if writer != nil && writer != os.Stdout {
		jsonStr, err := json.Marshal(log)

		// skip err
		if err != nil {
			return
		}

		// skip err
		fmt.Fprintln(writer, string(jsonStr))
		return
	}

	writer = os.Stdout

	timestamp := log.Timestamp.Format("15:04:05.000")

	prefix := fmt.Sprintf("\033[%vm%v %-6s %-10s #%v %v\033[0m", color, timestamp, humanizeNano(log.Delta), log.Name, log.Caller, SEPARATOR)

	arg := append([]interface{}{prefix}, log.Data...)

	// skip err
	fmt.Fprintln(writer, arg...)
}

func getCaller() (caller string) {
	caller = ""

	pc := make([]uintptr, 1)

	if runtime.Callers(3, pc) == 1 {
		f := runtime.FuncForPC(pc[0])
		caller = trimCaller(f.Name())
	}

	return
}

// "github.com/ddo/request.(*Client).Request"
// -> (*Client).Request
// or
// "github.com/ddo/request.New"
// -> New
func trimCaller(funcName string) string {
	// ex:
	// funcName = "github.com/ddo/request.(*Client).Request"
	// arrDir = [github.com ddo request.(*Client).Request]
	// lastDir = request.(*Client).Request
	// arrCaller = [request. (*Client).Request]

	arrDir := strings.Split(funcName, "/")
	lastDir := arrDir[len(arrDir)-1]
	arrCaller := strings.SplitAfterN(lastDir, ".", 2)

	if len(arrCaller) < 2 {
		return ""
	}

	return arrCaller[1]
}

// copty from TJ
func humanizeNano(n time.Duration) string {
	var suffix string

	switch {
	case n > 1e9:
		n /= 1e9
		suffix = "s"
	case n > 1e6:
		n /= 1e6
		suffix = "ms"
	case n > 1e3:
		n /= 1e3
		suffix = "us"
	default:
		suffix = "ns"
	}

	return strconv.Itoa(int(n)) + suffix
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof" // Comment this line to disable pprof endpoint.
	"os"
	"os/signal"
	"runtime"
	"strings"
	"syscall"

	"github.com/influxdata/telegraf/agent"
	"github.com/influxdata/telegraf/internal/config"
	"github.com/influxdata/telegraf/logger"
	_ "github.com/influxdata/telegraf/plugins/aggregators/all"
	"github.com/influxdata/telegraf/plugins/inputs"
	_ "github.com/influxdata/telegraf/plugins/inputs/all"
	"github.com/influxdata/telegraf/plugins/outputs"
	_ "github.com/influxdata/telegraf/plugins/outputs/all"
	_ "github.com/influxdata/telegraf/plugins/processors/all"
	"github.com/kardianos/service"
)

var fDebug = flag.Bool("debug", false,
	"turn on debug logging")
var pprofAddr = flag.String("pprof-addr", "",
	"pprof address to listen on, not activate pprof if empty")
var fQuiet = flag.Bool("quiet", false,
	"run in quiet mode")
var fTest = flag.Bool("test", false, "gather metrics, print them out, and exit")
var fConfig = flag.String("config", "", "configuration file to load")
var fConfigDirectory = flag.String("config-directory", "",
	"directory containing additional *.conf files")
var fVersion = flag.Bool("version", false, "display the version")
var fSampleConfig = flag.Bool("sample-config", false,
	"print out full sample configuration")
var fPidfile = flag.String("pidfile", "", "file to write our pid to")
var fInputFilters = flag.String("input-filter", "",
	"filter the inputs to enable, separator is :")
var fInputList = flag.Bool("input-list", false,
	"print available input plugins.")
var fOutputFilters = flag.String("output-filter", "",
	"filter the outputs to enable, separator is :")
var fOutputList = flag.Bool("output-list", false,
	"print available output plugins.")
var fAggregatorFilters = flag.String("aggregator-filter", "",
	"filter the aggregators to enable, separator is :")
var fProcessorFilters = flag.String("processor-filter", "",
	"filter the processors to enable, separator is :")
var fUsage = flag.String("usage", "",
	"print usage for a plugin, ie, 'telegraf --usage mysql'")
var fService = flag.String("service", "",
	"operate on the service")

// Telegraf version, populated linker.
//   ie, -ldflags "-X main.version=`git describe --always --tags`"

var (
	nextVersion = "1.5.0"
	version     string
	commit      string
	branch      string
)

func init() {
	// If commit or branch are not set, make that clear.
	if commit == "" {
		commit = "unknown"
	}
	if branch == "" {
		branch = "unknown"
	}
}

const usage = `Telegraf, The plugin-driven server agent for collecting and reporting metrics.

Usage:

  telegraf [commands|flags]

The commands & flags are:

  config              print out full sample configuration to stdout
  version             print the version to stdout

  --config <file>     configuration file to load
  --test              gather metrics once, print them to stdout, and exit
  --config-directory  directory containing additional *.conf files
  --input-filter      filter the input plugins to enable, separator is :
  --output-filter     filter the output plugins to enable, separator is :
  --usage             print usage for a plugin, ie, 'telegraf --usage mysql'
  --debug             print metrics as they're generated to stdout
  --pprof-addr        pprof address to listen on, format: localhost:6060 or :6060
  --quiet             run in quiet mode

Examples:

  # generate a telegraf config file:
  telegraf config > telegraf.conf

  # generate config with only cpu input & influxdb output plugins defined
  telegraf --input-filter cpu --output-filter influxdb config

  # run a single telegraf collection, outputing metrics to stdout
  telegraf --config telegraf.conf --test

  # run telegraf with all plugins defined in config file
  telegraf --config telegraf.conf

  # run telegraf, enabling the cpu & memory input, and influxdb output plugins
  telegraf --config telegraf.conf --input-filter cpu:mem --output-filter influxdb

  # run telegraf with pprof
  telegraf --config telegraf.conf --pprof-addr localhost:6060
`

var stop chan struct{}

func reloadLoop(
	stop chan struct{},
	inputFilters []string,
	outputFilters []string,
	aggregatorFilters []string,
	processorFilters []string,
) {
	reload := make(chan bool, 1)
	reload <- true
	for <-reload {
		reload <- false

		// If no other options are specified, load the config file and run.
		c := config.NewConfig()
		c.OutputFilters = outputFilters
		c.InputFilters = inputFilters
		err := c.LoadConfig(*fConfig)
		if err != nil {
			log.Fatal("E! " + err.Error())
		}

		if *fConfigDirectory != "" {
			err = c.LoadDirectory(*fConfigDirectory)
			if err != nil {
				log.Fatal("E! " + err.Error())
			}
		}
		if !*fTest && len(c.Outputs) == 0 {
			log.Fatalf("E! Error: no outputs found, did you provide a valid config file?")
		}
		if len(c.Inputs) == 0 {
			log.Fatalf("E! Error: no inputs found, did you provide a valid config file?")
		}

		if int64(c.Agent.Interval.Duration) <= 0 {
			log.Fatalf("E! Agent interval must be positive, found %s",
				c.Agent.Interval.Duration)
		}

		if int64(c.Agent.FlushInterval.Duration) <= 0 {
			log.Fatalf("E! Agent flush_interval must be positive; found %s",
				c.Agent.Interval.Duration)
		}

		ag, err := agent.NewAgent(c)
		if err != nil {
			log.Fatal("E! " + err.Error())
		}

		// Setup logging
		logger.SetupLogging(
			ag.Config.Agent.Debug || *fDebug,
			ag.Config.Agent.Quiet || *fQuiet,
			ag.Config.Agent.Logfile,
		)

		if *fTest {
			err = ag.Test()
			if err != nil {
				log.Fatal("E! " + err.Error())
			}
			os.Exit(0)
		}

		err = ag.Connect()
		if err != nil {
			log.Fatal("E! " + err.Error())
		}

		shutdown := make(chan struct{})
		signals := make(chan os.Signal)
		signal.Notify(signals, os.Interrupt, syscall.SIGHUP)
		go func() {
			select {
			case sig := <-signals:
				if sig == os.Interrupt {
					close(shutdown)
				}
				if sig == syscall.SIGHUP {
					log.Printf("I! Reloading Telegraf config\n")
					<-reload
					reload <- true
					close(shutdown)
				}
			case <-stop:
				close(shutdown)
			}
		}()

		log.Printf("I! Starting Telegraf %s\n", displayVersion())
		log.Printf("I! Loaded outputs: %s", strings.Join(c.OutputNames(), " "))
		log.Printf("I! Loaded inputs: %s", strings.Join(c.InputNames(), " "))
		log.Printf("I! Tags enabled: %s", c.ListTags())

		if *fPidfile != "" {
			f, err := os.OpenFile(*fPidfile, os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				log.Printf("E! Unable to create pidfile: %s", err)
			} else {
				fmt.Fprintf(f, "%d\n", os.Getpid())

				f.Close()

				defer func() {
					err := os.Remove(*fPidfile)
					if err != nil {
						log.Printf("E! Unable to remove pidfile: %s", err)
					}
				}()
			}
		}

		ag.Run(shutdown)
	}
}

func usageExit(rc int) {
	fmt.Println(usage)
	os.Exit(rc)
}

type program struct {
	inputFilters      []string
	outputFilters     []string
	aggregatorFilters []string
	processorFilters  []string
}

func (p *program) Start(s service.Service) error {
	go p.run()
	return nil
}
func (p *program) run() {
	stop = make(chan struct{})
	reloadLoop(
		stop,
		p.inputFilters,
		p.outputFilters,
		p.aggregatorFilters,
		p.processorFilters,
	)
}
func (p *program) Stop(s service.Service) error {
	close(stop)
	return nil
}

func displayVersion() string {
	if version == "" {
		return fmt.Sprintf("v%s~%s", nextVersion, commit)
	}
	return "v" + version
}

func main() {
	flag.Usage = func() { usageExit(0) }
	flag.Parse()
	args := flag.Args()

	inputFilters, outputFilters := []string{}, []string{}
	if *fInputFilters != "" {
		inputFilters = strings.Split(":"+strings.TrimSpace(*fInputFilters)+":", ":")
	}
	if *fOutputFilters != "" {
		outputFilters = strings.Split(":"+strings.TrimSpace(*fOutputFilters)+":", ":")
	}

	aggregatorFilters, processorFilters := []string{}, []string{}
	if *fAggregatorFilters != "" {
		aggregatorFilters = strings.Split(":"+strings.TrimSpace(*fAggregatorFilters)+":", ":")
	}
	if *fProcessorFilters != "" {
		processorFilters = strings.Split(":"+strings.TrimSpace(*fProcessorFilters)+":", ":")
	}

	if *pprofAddr != "" {
		go func() {
			pprofHostPort := *pprofAddr
			parts := strings.Split(pprofHostPort, ":")
			if len(parts) == 2 && parts[0] == "" {
				pprofHostPort = fmt.Sprintf("localhost:%s", parts[1])
			}
			pprofHostPort = "http://" + pprofHostPort + "/debug/pprof"

			log.Printf("I! Starting pprof HTTP server at: %s", pprofHostPort)

			if err := http.ListenAndServe(*pprofAddr, nil); err != nil {
				log.Fatal("E! " + err.Error())
			}
		}()
	}

	if len(args) > 0 {
		switch args[0] {
		case "version":
			fmt.Printf("Telegraf %s (git: %s %s)\n", displayVersion(), branch, commit)
			return
		case "config":
			config.PrintSampleConfig(
				inputFilters,
				outputFilters,
				aggregatorFilters,
				processorFilters,
			)
			return
		}
	}

	// switch for flags which just do something and exit immediately
	switch {
	case *fOutputList:
		fmt.Println("Available Output Plugins:")
		for k, _ := range outputs.Outputs {
			fmt.Printf("  %s\n", k)
		}
		return
	case *fInputList:
		fmt.Println("Available Input Plugins:")
		for k, _ := range inputs.Inputs {
			fmt.Printf("  %s\n", k)
		}
		return
	case *fVersion:
		fmt.Printf("Telegraf %s (git: %s %s)\n", displayVersion(), branch, commit)
		return
	case *fSampleConfig:
		config.PrintSampleConfig(
			inputFilters,
			outputFilters,
			aggregatorFilters,
			processorFilters,
		)
		return
	case *fUsage != "":
		err := config.PrintInputConfig(*fUsage)
		err2 := config.PrintOutputConfig(*fUsage)
		if err != nil && err2 != nil {
			log.Fatalf("E! %s and %s", err, err2)
		}
		return
	}

	if runtime.GOOS == "windows" {
		svcConfig := &service.Config{
			Name:        "telegraf",
			DisplayName: "Telegraf Data Collector Service",
			Description: "Collects data using a series of plugins and publishes it to" +
				"another series of plugins.",
			Arguments: []string{"-config", "C:\\Program Files\\Telegraf\\telegraf.conf"},
		}

		prg := &program{
			inputFilters:      inputFilters,
			outputFilters:     outputFilters,
			aggregatorFilters: aggregatorFilters,
			processorFilters:  processorFilters,
		}
		s, err := service.New(prg, svcConfig)
		if err != nil {
			log.Fatal("E! " + err.Error())
		}
		// Handle the -service flag here to prevent any issues with tooling that
		// may not have an interactive session, e.g. installing from Ansible.
		if *fService != "" {
			if *fConfig != "" {
				(*svcConfig).Arguments = []string{"-config", *fConfig}
			}
			if *fConfigDirectory != "" {
				(*svcConfig).Arguments = append((*svcConfig).Arguments, "-config-directory", *fConfigDirectory)
			}
			err := service.Control(s, *fService)
			if err != nil {
				log.Fatal("E! " + err.Error())
			}
			os.Exit(0)
		} else {
			err = s.Run()
			if err != nil {
				log.Println("E! " + err.Error())
			}
		}
	} else {
		stop = make(chan struct{})
		reloadLoop(
			stop,
			inputFilters,
			outputFilters,
			aggregatorFilters,
			processorFilters,
		)
	}
}
<commit_msg>Remove incorrect comment about linker options<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof" // Comment this line to disable pprof endpoint.
	"os"
	"os/signal"
	"runtime"
	"strings"
	"syscall"

	"github.com/influxdata/telegraf/agent"
	"github.com/influxdata/telegraf/internal/config"
	"github.com/influxdata/telegraf/logger"
	_ "github.com/influxdata/telegraf/plugins/aggregators/all"
	"github.com/influxdata/telegraf/plugins/inputs"
	_ "github.com/influxdata/telegraf/plugins/inputs/all"
	"github.com/influxdata/telegraf/plugins/outputs"
	_ "github.com/influxdata/telegraf/plugins/outputs/all"
	_ "github.com/influxdata/telegraf/plugins/processors/all"
	"github.com/kardianos/service"
)

var fDebug = flag.Bool("debug", false,
	"turn on debug logging")
var pprofAddr = flag.String("pprof-addr", "",
	"pprof address to listen on, not activate pprof if empty")
var fQuiet = flag.Bool("quiet", false,
	"run in quiet mode")
var fTest = flag.Bool("test", false, "gather metrics, print them out, and exit")
var fConfig = flag.String("config", "", "configuration file to load")
var fConfigDirectory = flag.String("config-directory", "",
	"directory containing additional *.conf files")
var fVersion = flag.Bool("version", false, "display the version")
var fSampleConfig = flag.Bool("sample-config", false,
	"print out full sample configuration")
var fPidfile = flag.String("pidfile", "", "file to write our pid to")
var fInputFilters = flag.String("input-filter", "",
	"filter the inputs to enable, separator is :")
var fInputList = flag.Bool("input-list", false,
	"print available input plugins.")
var fOutputFilters = flag.String("output-filter", "",
	"filter the outputs to enable, separator is :")
var fOutputList = flag.Bool("output-list", false,
	"print available output plugins.")
var fAggregatorFilters = flag.String("aggregator-filter", "",
	"filter the aggregators to enable, separator is :")
var fProcessorFilters = flag.String("processor-filter", "",
	"filter the processors to enable, separator is :")
var fUsage = flag.String("usage", "",
	"print usage for a plugin, ie, 'telegraf --usage mysql'")
var fService = flag.String("service", "",
	"operate on the service")

var (
	nextVersion = "1.5.0"
	version     string
	commit      string
	branch      string
)

func init() {
	// If commit or branch are not set, make that clear.
	if commit == "" {
		commit = "unknown"
	}
	if branch == "" {
		branch = "unknown"
	}
}

const usage = `Telegraf, The plugin-driven server agent for collecting and reporting metrics.

Usage:

  telegraf [commands|flags]

The commands & flags are:

  config              print out full sample configuration to stdout
  version             print the version to stdout

  --config <file>     configuration file to load
  --test              gather metrics once, print them to stdout, and exit
  --config-directory  directory containing additional *.conf files
  --input-filter      filter the input plugins to enable, separator is :
  --output-filter     filter the output plugins to enable, separator is :
  --usage             print usage for a plugin, ie, 'telegraf --usage mysql'
  --debug             print metrics as they're generated to stdout
  --pprof-addr        pprof address to listen on, format: localhost:6060 or :6060
  --quiet             run in quiet mode

Examples:

  # generate a telegraf config file:
  telegraf config > telegraf.conf

  # generate config with only cpu input & influxdb output plugins defined
  telegraf --input-filter cpu --output-filter influxdb config

  # run a single telegraf collection, outputing metrics to stdout
  telegraf --config telegraf.conf --test

  # run telegraf with all plugins defined in config file
  telegraf --config telegraf.conf

  # run telegraf, enabling the cpu & memory input, and influxdb output plugins
  telegraf --config telegraf.conf --input-filter cpu:mem --output-filter influxdb

  # run telegraf with pprof
  telegraf --config telegraf.conf --pprof-addr localhost:6060
`

var stop chan struct{}

func reloadLoop(
	stop chan struct{},
	inputFilters []string,
	outputFilters []string,
	aggregatorFilters []string,
	processorFilters []string,
) {
	reload := make(chan bool, 1)
	reload <- true
	for <-reload {
		reload <- false

		// If no other options are specified, load the config file and run.
		c := config.NewConfig()
		c.OutputFilters = outputFilters
		c.InputFilters = inputFilters
		err := c.LoadConfig(*fConfig)
		if err != nil {
			log.Fatal("E! " + err.Error())
		}

		if *fConfigDirectory != "" {
			err = c.LoadDirectory(*fConfigDirectory)
			if err != nil {
				log.Fatal("E! " + err.Error())
			}
		}
		if !*fTest && len(c.Outputs) == 0 {
			log.Fatalf("E! Error: no outputs found, did you provide a valid config file?")
		}
		if len(c.Inputs) == 0 {
			log.Fatalf("E! Error: no inputs found, did you provide a valid config file?")
		}

		if int64(c.Agent.Interval.Duration) <= 0 {
			log.Fatalf("E! Agent interval must be positive, found %s",
				c.Agent.Interval.Duration)
		}

		if int64(c.Agent.FlushInterval.Duration) <= 0 {
			log.Fatalf("E! Agent flush_interval must be positive; found %s",
				c.Agent.Interval.Duration)
		}

		ag, err := agent.NewAgent(c)
		if err != nil {
			log.Fatal("E! " + err.Error())
		}

		// Setup logging
		logger.SetupLogging(
			ag.Config.Agent.Debug || *fDebug,
			ag.Config.Agent.Quiet || *fQuiet,
			ag.Config.Agent.Logfile,
		)

		if *fTest {
			err = ag.Test()
			if err != nil {
				log.Fatal("E! " + err.Error())
			}
			os.Exit(0)
		}

		err = ag.Connect()
		if err != nil {
			log.Fatal("E! " + err.Error())
		}

		shutdown := make(chan struct{})
		signals := make(chan os.Signal)
		signal.Notify(signals, os.Interrupt, syscall.SIGHUP)
		go func() {
			select {
			case sig := <-signals:
				if sig == os.Interrupt {
					close(shutdown)
				}
				if sig == syscall.SIGHUP {
					log.Printf("I! Reloading Telegraf config\n")
					<-reload
					reload <- true
					close(shutdown)
				}
			case <-stop:
				close(shutdown)
			}
		}()

		log.Printf("I! Starting Telegraf %s\n", displayVersion())
		log.Printf("I! Loaded outputs: %s", strings.Join(c.OutputNames(), " "))
		log.Printf("I! Loaded inputs: %s", strings.Join(c.InputNames(), " "))
		log.Printf("I! Tags enabled: %s", c.ListTags())

		if *fPidfile != "" {
			f, err := os.OpenFile(*fPidfile, os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				log.Printf("E! Unable to create pidfile: %s", err)
			} else {
				fmt.Fprintf(f, "%d\n", os.Getpid())

				f.Close()

				defer func() {
					err := os.Remove(*fPidfile)
					if err != nil {
						log.Printf("E! Unable to remove pidfile: %s", err)
					}
				}()
			}
		}

		ag.Run(shutdown)
	}
}

func usageExit(rc int) {
	fmt.Println(usage)
	os.Exit(rc)
}

type program struct {
	inputFilters      []string
	outputFilters     []string
	aggregatorFilters []string
	processorFilters  []string
}

func (p *program) Start(s service.Service) error {
	go p.run()
	return nil
}
func (p *program) run() {
	stop = make(chan struct{})
	reloadLoop(
		stop,
		p.inputFilters,
		p.outputFilters,
		p.aggregatorFilters,
		p.processorFilters,
	)
}
func (p *program) Stop(s service.Service) error {
	close(stop)
	return nil
}

func displayVersion() string {
	if version == "" {
		return fmt.Sprintf("v%s~%s", nextVersion, commit)
	}
	return "v" + version
}

func main() {
	flag.Usage = func() { usageExit(0) }
	flag.Parse()
	args := flag.Args()

	inputFilters, outputFilters := []string{}, []string{}
	if *fInputFilters != "" {
		inputFilters = strings.Split(":"+strings.TrimSpace(*fInputFilters)+":", ":")
	}
	if *fOutputFilters != "" {
		outputFilters = strings.Split(":"+strings.TrimSpace(*fOutputFilters)+":", ":")
	}

	aggregatorFilters, processorFilters := []string{}, []string{}
	if *fAggregatorFilters != "" {
		aggregatorFilters = strings.Split(":"+strings.TrimSpace(*fAggregatorFilters)+":", ":")
	}
	if *fProcessorFilters != "" {
		processorFilters = strings.Split(":"+strings.TrimSpace(*fProcessorFilters)+":", ":")
	}

	if *pprofAddr != "" {
		go func() {
			pprofHostPort := *pprofAddr
			parts := strings.Split(pprofHostPort, ":")
			if len(parts) == 2 && parts[0] == "" {
				pprofHostPort = fmt.Sprintf("localhost:%s", parts[1])
			}
			pprofHostPort = "http://" + pprofHostPort + "/debug/pprof"

			log.Printf("I! Starting pprof HTTP server at: %s", pprofHostPort)

			if err := http.ListenAndServe(*pprofAddr, nil); err != nil {
				log.Fatal("E! " + err.Error())
			}
		}()
	}

	if len(args) > 0 {
		switch args[0] {
		case "version":
			fmt.Printf("Telegraf %s (git: %s %s)\n", displayVersion(), branch, commit)
			return
		case "config":
			config.PrintSampleConfig(
				inputFilters,
				outputFilters,
				aggregatorFilters,
				processorFilters,
			)
			return
		}
	}

	// switch for flags which just do something and exit immediately
	switch {
	case *fOutputList:
		fmt.Println("Available Output Plugins:")
		for k, _ := range outputs.Outputs {
			fmt.Printf("  %s\n", k)
		}
		return
	case *fInputList:
		fmt.Println("Available Input Plugins:")
		for k, _ := range inputs.Inputs {
			fmt.Printf("  %s\n", k)
		}
		return
	case *fVersion:
		fmt.Printf("Telegraf %s (git: %s %s)\n", displayVersion(), branch, commit)
		return
	case *fSampleConfig:
		config.PrintSampleConfig(
			inputFilters,
			outputFilters,
			aggregatorFilters,
			processorFilters,
		)
		return
	case *fUsage != "":
		err := config.PrintInputConfig(*fUsage)
		err2 := config.PrintOutputConfig(*fUsage)
		if err != nil && err2 != nil {
			log.Fatalf("E! %s and %s", err, err2)
		}
		return
	}

	if runtime.GOOS == "windows" {
		svcConfig := &service.Config{
			Name:        "telegraf",
			DisplayName: "Telegraf Data Collector Service",
			Description: "Collects data using a series of plugins and publishes it to" +
				"another series of plugins.",
			Arguments: []string{"-config", "C:\\Program Files\\Telegraf\\telegraf.conf"},
		}

		prg := &program{
			inputFilters:      inputFilters,
			outputFilters:     outputFilters,
			aggregatorFilters: aggregatorFilters,
			processorFilters:  processorFilters,
		}
		s, err := service.New(prg, svcConfig)
		if err != nil {
			log.Fatal("E! " + err.Error())
		}
		// Handle the -service flag here to prevent any issues with tooling that
		// may not have an interactive session, e.g. installing from Ansible.
		if *fService != "" {
			if *fConfig != "" {
				(*svcConfig).Arguments = []string{"-config", *fConfig}
			}
			if *fConfigDirectory != "" {
				(*svcConfig).Arguments = append((*svcConfig).Arguments, "-config-directory", *fConfigDirectory)
			}
			err := service.Control(s, *fService)
			if err != nil {
				log.Fatal("E! " + err.Error())
			}
			os.Exit(0)
		} else {
			err = s.Run()
			if err != nil {
				log.Println("E! " + err.Error())
			}
		}
	} else {
		stop = make(chan struct{})
		reloadLoop(
			stop,
			inputFilters,
			outputFilters,
			aggregatorFilters,
			processorFilters,
		)
	}
}
<|endoftext|>


<commit_before>package uct

import "flag"
import "strconv"
import "fmt"

var ArduinoReserved = []string{
	"char", "on", "off",
}

//This is the Java compiler for uct.
var Arduino bool

func init() {
	flag.BoolVar(&Arduino, "arduino", false, "Target the Arduino")

	RegisterAssembler(ArduinoAssembly, &Arduino, "ino", "//")

	for _, word := range ArduinoReserved {
		ArduinoAssembly[word] = Reserved()
	}
}

var ArduinoAssembly = Assemblable{
	//Special commands.
	"HEADER": Instruction{
		Data:   `

//System configiration.
	//Tweak these values based upon the amount of RAM your microcontroller has.
	const int HEAP_SIZE = 48; //This is how many blocks the system can allocate before running out of memory.
	const int BLOCK_SIZE = 15; //This is the how many integers a block can hold.
//End configuriation.

enum {
	length_pos, refcount_pos, nesting_pos, data_pos
};

struct Block {
	int index[BLOCK_SIZE];
	Block *next;
};

int ERROR;
Block *activearray;

Block *arrays[5];
int array_pointer;
int numbers[5];
int number_pointer;

int (*pipes[5])();
int pipe_pointer;

//Garbage collection.
volatile int nesting;
Block *heap[HEAP_SIZE];

void collect_block(Block *b) {
	if (b->index[length_pos] > (BLOCK_SIZE-data_pos)) {
		collect_block(b->next);
	}
	b->index[length_pos] = -2;
}

void stack_collect() {
  nesting--;

  for (int i = 0; i < HEAP_SIZE; i++) {
		if (heap[i] && heap[i]->index[length_pos] >= 0) {
			int nest = heap[i]->index[nesting_pos];
			int refcount = heap[i]->index[refcount_pos];

			if (refcount == 0 && nest > nesting) {
				collect_block(heap[i]);
			}
		}
   }
}

void stack_push(int num) {
  numbers[number_pointer] = num;
  number_pointer++;
}

int stack_pull() {
  number_pointer--;
  return numbers[number_pointer];
}

Block *get_free_block() {

	for (int i = 0; i < HEAP_SIZE; i++) {
		if (heap[i] && heap[i]->index[length_pos] == -2) {
		  	return heap[i];
		}
 	}

	return new Block();
}

//Create a new array.
Block *stack_array(int l) {
  //Need to check if there is a block which we can recycle!
  Block *arr = get_free_block();

  if (arr->index[length_pos] == -2) {

  	arr->index[length_pos] = l;
  	arr->index[refcount_pos] = 0;
  	arr->index[nesting_pos] = nesting;
  	activearray = arr;
  	return arr;

  } else {

    int done = 0;
    for (int i = 0; i < HEAP_SIZE; i++) {
      if (heap[i] == 0) {
        heap[i] = arr;
        activearray = arr;
        done = 1;
        break;
      }
    }

    if (done) {
    	arr->index[length_pos] = l;
      return arr;
    } else {
      Serial.println(F("[ERROR] Out of memory!"));
      exit(1);
    }
  }
}

int *stack_get_array_segment(Block *arr, int length) {
	//Linked list time!
  	//I hope this works!

	Block *next;

  	if (!(arr->next)) {
  	  arr->next = get_free_block();
  	  next = arr->next;
  	  next->index[0] = -1;
  	} else {
  	  next = arr->next;
  	}

  	length -= (BLOCK_SIZE - data_pos);
  	while (length > BLOCK_SIZE-1) {
  		if (!(next->next)) {
	  		next->next = get_free_block();
	  		next = next->next;
	  		next->index[0] = -1;
	  	} else {
	  		next = next->next;
	  	}
  		length -= (BLOCK_SIZE-1);
  	}

  	return &(next->index[length+1]);
}

void stack_put(int value) {
  int length = activearray->index[length_pos];

  if (length >= (BLOCK_SIZE - data_pos)) {

  	int *pointer = stack_get_array_segment(activearray, length);
  	*pointer = value;
  	activearray->index[length_pos] = length + 1;

  } else {
	  activearray->index[length+data_pos] = value;
	  activearray->index[length_pos] = length + 1;
  }
}

int stack_pop() {
  int length = activearray->index[length_pos];

	if (length >= (BLOCK_SIZE - data_pos)) {

		int value = *stack_get_array_segment(activearray, length);
		activearray->index[length_pos] = length - 1;
		return value;

	} else {
		int value = activearray->index[length+data_pos];
		activearray->index[length_pos] = length - 1;
		return value;
	}
}

void stack_heap() {
	int mode = stack_pull();

	if (mode == 0) {
	  int address = (int)stack_array(0);
		stack_push(address);
	}
	if (mode > 0) {

	  Block *tmp = mode;
		stack_share(tmp);
	}
	if (mode < 0) {
	 Block *tmp = mode;
		tmp->index[length_pos] = -2;
	}
}

int stack_get() {
  int index = stack_pull();
  int length = activearray->index[length_pos];
  if (length == 0) {
    return 0;
  }

  index = index % length;

  if (index < (BLOCK_SIZE - data_pos)) {
    return activearray->index[index+data_pos];
  } else {
  	return *(stack_get_array_segment(activearray, index));
  }
}

int stack_set(int value) {
  int index = stack_pull();
  int length = activearray->index[length_pos];
  index = index % length;

  if (index < (BLOCK_SIZE - data_pos)) {
    activearray->index[index+data_pos] = value;
  }
 int *pointer = stack_get_array_segment(activearray, index);
  *pointer = value;
}

void stack_relay(int (*pipe)()) {
  pipes[pipe_pointer] = pipe;
  pipe_pointer++;
}

int (*stack_take())() {
  pipe_pointer--;
  return pipes[pipe_pointer];
}

void stack_share(Block *arr) {
  arrays[array_pointer] = arr;
  arr->index[refcount_pos]++;
  array_pointer++;
}

int powint(int x, int y)
{
 int val=x;
 for(int z=0;z<=y;z++)
 {
   if(z==0)
     val=1;
   else
     val=val*x;
 }
 return val;
}

Block *stack_grab() {
  array_pointer--;
  Block *arr = arrays[array_pointer];
  arr->index[refcount_pos]--;
  arr->index[nesting_pos] = nesting;
  return arr;
}

Block *stack_join(Block *a, Block *b) {
	Block *c = stack_array(0);
	for (int i = 0; i < a->index[length_pos]; i++) {
		activearray = a;
		stack_push(i);
		int value = stack_get();

		activearray = c;
		stack_put(value);
	}
	for (int i = 0; i < b->index[length_pos]; i++) {
		activearray = b;
		stack_push(i);
		int value = stack_get();

		activearray = c;
		stack_put(value);
	}

	return c;
}

Block *stack_data(int data[]) {
  int length = sizeof(data) / sizeof(int);
  Block *a = stack_array(length);
  for (int i = 0; i < length; i++) {
    stack_put(data[i]);
  }
  a->index[refcount_pos] = 1;
  return a;
}

void stack_stdout() {
  nesting++;
  Block *arr = stack_grab();

  for (int i = 0; i < arr->index[length_pos]; i++) {
    if (i < (BLOCK_SIZE - data_pos)) {
      Serial.write(arr->index[i+data_pos]);
    } else {
      Serial.write(*(stack_get_array_segment(arr, i)));
    }
    Serial.flush();
  }

  stack_collect();
}

//Toaster-level stdin.
void stack_stdin() {

}
`,
		Args:   1,
	},

	"FOOTER": Instruction{
		Data:        "",
	},

	//Don't need a stack file.
	"FILE": Instruction{},

	"ARDUINO": Instruction{All:true},

	//"EVAL": is("Class[] cArg = new Class[1]; cArg[0] = Stack.class; try { new Object() { }.getClass().getEnclosingClass().getDeclaredMethod(stack.grab().String(), cArg).invoke(null, stack); } catch (Exception e) { throw new RuntimeException(e); }"),

	//BigInts are not supported yet.. there is a BC library ported to the Arduino, I don't know if it should be added or not, arduino's are just hardware restricted.
	"NUMBER": is("%s", 1),
	"BIG": is("%s", 1),

	"SIZE":   is("%s->index[length_pos]", 1),
	"ERRORS":  is("ERROR", 1),

	"SOFTWARE": Instruction{
		Data:   "void setup() { Serial.begin(9600);",
		Indent: 1,
	},
	"EXIT": Instruction{
		Indented:    1,
		Data:        "stack_collect(); } void loop(){ exit(0); }\n",
		Indent:      -1,
		Indentation: -1,
		Else: &Instruction{
			Data: "exit(ERROR);",
		},
	},

	"FUNCTION": is("void %s() { nesting++;", 1, 1),
	"RETURN": Instruction{
		Indented:    1,
		Data:        "stack_collect(); }\n",
		Indent:      -1,
		Indentation: -1,
		Else: &Instruction{
			Data: "stack_collect(); return;",
		},
	},

	"SCOPE": is(`stack_relay(&%s);`, 1),

	"EXE": is("(*%s)();", 1),

	"PUSH": is("stack_push(%s);", 1),
	"PULL": is("int %s = stack_pull();", 1),

	"PUT":   is("stack_put(%s);", 1),
	"POP":   is("int %s = stack_pop();", 1),
	"PLACE": is("activearray = %s;", 1),

	"ARRAY":  is("Block *%s = stack_array(0);", 1),
	"MAKE":  is("stack_share(stack_array(stack_pull()));"),
	"RENAME": is("%s = activearray;", 1),

	"RELOAD": is("%s = stack.take();", 1),

	"SHARE": is("stack_share(%s);", 1),
	"GRAB":  is("Block *%s = stack_grab();", 1),

	"RELAY": is("stack_relay(%s);", 1),
	"TAKE":  is("int (*%s)() = stack_take();", 1),

	"GET": is("int %s = stack_get();", 1),
	"SET": is("stack_set(%s);", 1),

	"VAR": is("int %s = 0;", 1),

	"OPEN":   is(""),
	"DELETE":   is(""),
	"EXECUTE":   is(""),
	"LOAD":   is(""),
	"OUT":    is(""),
	"STAT":   is(""),
	"IN":     is(""),
	"STDOUT": is("stack_stdout();"),
	"STDIN":  is("stack_stdin();"),
	"HEAP":   is("stack_heap();"),
	"LINK":   is(""),
	"CONNECT":   is(""),
	"SLICE":   is(""),

	"CLOSE": is("", 1),

	"LOOP":   is("while (1) { nesting++;", 0, 1),
	"BREAK":  is("stack_collect(); break;"),
	"REPEAT": is("stack_collect(); }", 0, -1, -1),

	"IF":   is("if (%s) { nesting++;", 1, 1),
	"ELSE": is("stack_collect(); } else { nesting++;", 0, 0, -1),
	"END":  is("stack_collect(); }", 0, -1, -1),

	"RUN":  is("%s();", 1),

	"DATA":  is("Block %s[]=%s;", 2),
	"STRING": Instruction{
		Args: 1,
		Data: " ",
		Function: func(args []string) string {
			str, _ := strconv.Unquote(args[0])

			var result string = "{"+fmt.Sprint(len(str))+", 0, 0,"
			for _, char := range str {
				result += fmt.Sprint(int(char))+", "
			}
			result = result[:len(result)-2]
			result += "}"
			return result
		},
	},

	"FORK": is("{ Stack s = stack.copy(); Stack.ThreadPool.execute(() -> %s(s)); }\n", 1),

	"ADD": is("%s = %s + %s;", 3),
	"SUB": is("%s = %s - %s;", 3),
	"MUL": is("%s = %s * %s;", 3),
	"DIV": is("%s = %s / %s;", 3),
	"MOD": is("%s = %s %% %s;", 3),
	"POW": is("%s = powint(%s, %s);", 3),

	"SLT": is("%s = (%s < %s) ? 1 : 0;", 3),
	"SEQ": is("%s = (%s == %s) ? 1 : 0;", 3),
	"SGE": is("%s = (%s >= %s)  ? 1 : 0;", 3),
	"SGT": is("%s = (%s > %s) ? 1 : 0;", 3),
	"SNE": is("%s = (%s != %s) ? 1 : 0;", 3),
	"SLE": is("%s = (%s <= %s) ? 1 : 0;", 3),

	"JOIN": is("%s = stack_join(%s, %s);", 3),
	"ERROR": is("ERROR = %s;", 1),
}
<commit_msg>Update Arduino support, although there are significant flaws with the implementation.<commit_after>package uct

import "flag"
import "strconv"
import "fmt"

var ArduinoReserved = []string{
	"char", "on", "off", "lcd",
}

//This is the Java compiler for uct.
var Arduino bool

func init() {
	flag.BoolVar(&Arduino, "arduino", false, "Target the Arduino")

	RegisterAssembler(ArduinoAssembly, &Arduino, "ino", "//")

	for _, word := range ArduinoReserved {
		ArduinoAssembly[word] = Reserved()
	}
}

var ArduinoAssembly = Assemblable{
	//Special commands.
	"HEADER": Instruction{
		Data:   `

//System configiration.
	//Tweak these values based upon the amount of RAM your microcontroller has.
	const int HEAP_SIZE = 48; //This is how many blocks the system can allocate before running out of memory.
	const int BLOCK_SIZE = 15; //This is the how many integers a block can hold.
//End configuriation.

enum {
	length_pos, refcount_pos, nesting_pos, data_pos
};

struct Block {
	int index[BLOCK_SIZE];
	Block *next;
};

int ERROR;
Block *activearray;

Block *arrays[5];
int array_pointer;
int numbers[10];
int number_pointer;

int (*pipes[5])();
int pipe_pointer;

//Garbage collection.
volatile int nesting;
Block *heap[HEAP_SIZE];

void collect_block(Block *b) {
	if (b->index[length_pos] > (BLOCK_SIZE-data_pos)) {
		collect_block(b->next);
	}
	b->index[length_pos] = -2;
}

void stack_collect() {
  nesting--;

  for (int i = 0; i < HEAP_SIZE; i++) {
		if (heap[i] && heap[i]->index[length_pos] >= 0) {
			int nest = heap[i]->index[nesting_pos];
			int refcount = heap[i]->index[refcount_pos];

			if (refcount == 0 && nest > nesting) {
				collect_block(heap[i]);
			}
		}
   }
}

void stack_push(int num) {
  numbers[number_pointer] = num;
  number_pointer++;
}

int stack_pull() {
  number_pointer--;
  return numbers[number_pointer];
}

Block *get_free_block() {

	for (int i = 0; i < HEAP_SIZE; i++) {
		if (heap[i] && heap[i]->index[length_pos] == -2) {
		  	return heap[i];
		}
 	}

	return new Block();
}

//Create a new array.
Block *stack_array(int l) {
  //Need to check if there is a block which we can recycle!
  Block *arr = get_free_block();

  if (arr->index[length_pos] == -2) {

  	arr->index[length_pos] = l;
  	arr->index[refcount_pos] = 0;
  	arr->index[nesting_pos] = nesting;
  	activearray = arr;
  	return arr;

  } else {

    int done = 0;
    for (int i = 0; i < HEAP_SIZE; i++) {
      if (heap[i] == 0) {
        heap[i] = arr;
        activearray = arr;
        done = 1;
        break;
      }
    }

    if (done) {
    	arr->index[length_pos] = l;
      return arr;
    } else {
      Serial.println(F("[ERROR] Out of memory!"));
      exit(1);
    }
  }
}

int *stack_get_array_segment(Block *arr, int length) {
	//Linked list time!
  	//I hope this works!

	Block *next;

  	if (!(arr->next)) {
  	  arr->next = get_free_block();
  	  next = arr->next;
  	  next->index[0] = -1;
  	} else {
  	  next = arr->next;
  	}

  	length -= (BLOCK_SIZE - data_pos);
  	while (length > BLOCK_SIZE-1) {
  		if (!(next->next)) {
	  		next->next = get_free_block();
	  		next = next->next;
	  		next->index[0] = -1;
	  	} else {
	  		next = next->next;
	  	}
  		length -= (BLOCK_SIZE-1);
  	}

  	return &(next->index[length+1]);
}

void stack_put(int value) {
  int length = activearray->index[length_pos];

  if (length >= (BLOCK_SIZE - data_pos)) {

  	int *pointer = stack_get_array_segment(activearray, length);
  	*pointer = value;
  	activearray->index[length_pos] = length + 1;

  } else {
	  activearray->index[length+data_pos] = value;
	  activearray->index[length_pos] = length + 1;
  }
}

int stack_pop() {
  int length = activearray->index[length_pos];

	if (length >= (BLOCK_SIZE - data_pos)) {

		int value = *stack_get_array_segment(activearray, length);
		activearray->index[length_pos] = length - 1;
		return value;

	} else {
		int value = activearray->index[length+data_pos];
		activearray->index[length_pos] = length - 1;
		return value;
	}
}

void stack_share(Block *arr) {
  arrays[array_pointer] = arr;
  arr->index[refcount_pos]++;
  array_pointer++;
}

void stack_heap() {
	int mode = stack_pull();

	if (mode == 0) {
	  int address = (int)stack_array(0);
		stack_push(address);
	}
	if (mode > 0) {

	  Block *tmp = mode;
		stack_share(tmp);
	}
	if (mode < 0) {
	 Block *tmp = mode;
		tmp->index[length_pos] = -2;
	}
}

int stack_get() {
  int index = stack_pull();
  int length = activearray->index[length_pos];
  if (length == 0) {
    return 0;
  }

  index = index % length;

  if (index < (BLOCK_SIZE - data_pos)) {
    return activearray->index[index+data_pos];
  } else {
  	return *(stack_get_array_segment(activearray, index));
  }
}

int stack_set(int value) {
  int index = stack_pull();
  int length = activearray->index[length_pos];
  index = index % length;

  if (index < (BLOCK_SIZE - data_pos)) {
    activearray->index[index+data_pos] = value;
  }
 int *pointer = stack_get_array_segment(activearray, index);
  *pointer = value;
}

void stack_relay(int (*pipe)()) {
  pipes[pipe_pointer] = pipe;
  pipe_pointer++;
}

int (*stack_take())() {
  pipe_pointer--;
  return pipes[pipe_pointer];
}

int powint(int x, int y)
{
 int val=x;
 for(int z=0;z<=y;z++)
 {
   if(z==0)
     val=1;
   else
     val=val*x;
 }
 return val;
}

Block *stack_grab() {
  array_pointer--;
  Block *arr = arrays[array_pointer];
  arr->index[refcount_pos]--;
  arr->index[nesting_pos] = nesting;
  return arr;
}

Block *stack_join(Block *a, Block *b) {
	Block *c = stack_array(0);
	for (int i = 0; i < a->index[length_pos]; i++) {
		activearray = a;
		stack_push(i);
		int value = stack_get();

		activearray = c;
		stack_put(value);
	}
	for (int i = 0; i < b->index[length_pos]; i++) {
		activearray = b;
		stack_push(i);
		int value = stack_get();

		activearray = c;
		stack_put(value);
	}

	return c;
}

Block *stack_data(int data[]) {
  int length = sizeof(data) / sizeof(int);
  Block *a = stack_array(length);
  for (int i = 0; i < length; i++) {
    stack_put(data[i]);
  }
  a->index[refcount_pos] = 1;
  return a;
}

void stack_stdout() {
  nesting++;
  Block *arr = stack_grab();

  for (int i = 0; i < arr->index[length_pos]; i++) {
    if (i < (BLOCK_SIZE - data_pos)) {
      Serial.write(arr->index[i+data_pos]);
    } else {
      Serial.write(*(stack_get_array_segment(arr, i)));
    }
    Serial.flush();
  }

  stack_collect();
}

//Toaster-level stdin.
void stack_stdin() {

}
`,
		Args:   1,
	},

	"FOOTER": Instruction{
		Data:        "",
	},

	//Don't need a stack file.
	"FILE": Instruction{},

	"ARDUINO": Instruction{All:true},

	//"EVAL": is("Class[] cArg = new Class[1]; cArg[0] = Stack.class; try { new Object() { }.getClass().getEnclosingClass().getDeclaredMethod(stack.grab().String(), cArg).invoke(null, stack); } catch (Exception e) { throw new RuntimeException(e); }"),

	//BigInts are not supported yet.. there is a BC library ported to the Arduino, I don't know if it should be added or not, arduino's are just hardware restricted.
	"NUMBER": is("%s", 1),
	"BIG": is("%s", 1),

	"SIZE":   is("%s->index[length_pos]", 1),
	"ERRORS":  is("ERROR", 1),

	"SOFTWARE": Instruction{
		Data:   "void setup() { Serial.begin(9600);",
		Indent: 1,
	},
	"EXIT": Instruction{
		Indented:    1,
		Data:        "stack_collect(); } void loop(){ exit(0); }\n",
		Indent:      -1,
		Indentation: -1,
		Else: &Instruction{
			Data: "exit(ERROR);",
		},
	},

	"FUNCTION": is("void %s() { nesting++;", 1, 1),
	"RETURN": Instruction{
		Indented:    1,
		Data:        "stack_collect(); }\n",
		Indent:      -1,
		Indentation: -1,
		Else: &Instruction{
			Data: "stack_collect(); return;",
		},
	},

	"SCOPE": is(`stack_relay(&%s);`, 1),

	"EXE": is("(*%s)();", 1),

	"PUSH": is("stack_push(%s);", 1),
	"PULL": is("int %s = stack_pull();", 1),

	"PUT":   is("stack_put(%s);", 1),
	"POP":   is("int %s = stack_pop();", 1),
	"PLACE": is("activearray = %s;", 1),

	"ARRAY":  is("Block *%s = stack_array(0);", 1),
	"MAKE":  is("stack_share(stack_array(stack_pull()));"),
	"RENAME": is("%s = activearray;", 1),

	"RELOAD": is("%s = stack.take();", 1),

	"SHARE": is("stack_share(%s);", 1),
	"GRAB":  is("Block *%s = stack_grab();", 1),

	"RELAY": is("stack_relay(%s);", 1),
	"TAKE":  is("int (*%s)() = stack_take();", 1),

	"GET": is("int %s = stack_get();", 1),
	"SET": is("stack_set(%s);", 1),

	"VAR": is("int %s = 0;", 1),

	"OPEN":   is(""),
	"DELETE":   is(""),
	"EXECUTE":   is(""),
	"LOAD":   is(""),
	"OUT":    is(""),
	"STAT":   is(""),
	"IN":     is(""),
	"STDOUT": is("stack_stdout();"),
	"STDIN":  is("stack_stdin();"),
	"HEAP":   is("stack_heap();"),
	"LINK":   is(""),
	"CONNECT":   is(""),
	"SLICE":   is(""),

	"CLOSE": is("", 1),

	"LOOP":   is("while (1) { nesting++;", 0, 1),
	"BREAK":  is("stack_collect(); break;"),
	"REPEAT": is("stack_collect(); }", 0, -1, -1),

	"IF":   is("if (%s) { nesting++;", 1, 1),
	"ELSE": is("stack_collect(); } else { nesting++;", 0, 0, -1),
	"END":  is("stack_collect(); }", 0, -1, -1),

	"RUN":  is("%s();", 1),

	"DATA":  is("Block %s[]=%s;", 2),
	"STRING": Instruction{
		Args: 1,
		Data: " ",
		Function: func(args []string) string {
			str, _ := strconv.Unquote(args[0])

			var result string = "{"+fmt.Sprint(len(str))+", 0, 0,"
			for _, char := range str {
				result += fmt.Sprint(int(char))+", "
			}
			result = result[:len(result)-2]
			result += "}"
			return result
		},
	},

	"FORK": is("{ Stack s = stack.copy(); Stack.ThreadPool.execute(() -> %s(s)); }\n", 1),

	"ADD": is("%s = %s + %s;", 3),
	"SUB": is("%s = %s - %s;", 3),
	"MUL": is("%s = %s * %s;", 3),
	"DIV": is("%s = %s / %s;", 3),
	"MOD": is("%s = %s %% %s;", 3),
	"POW": is("%s = powint(%s, %s);", 3),

	"SLT": is("%s = (%s < %s) ? 1 : 0;", 3),
	"SEQ": is("%s = (%s == %s) ? 1 : 0;", 3),
	"SGE": is("%s = (%s >= %s)  ? 1 : 0;", 3),
	"SGT": is("%s = (%s > %s) ? 1 : 0;", 3),
	"SNE": is("%s = (%s != %s) ? 1 : 0;", 3),
	"SLE": is("%s = (%s <= %s) ? 1 : 0;", 3),

	"JOIN": is("%s = stack_join(%s, %s);", 3),
	"ERROR": is("ERROR = %s;", 1),
}
<|endoftext|>