289b30715d
This commit converts the dependency management from Godeps to the vendor folder, also switching the tool from godep to trash. Since the upstream tool lacks a few features proposed via a few PRs, until those PRs are merged in (if), use github.com/karalabe/trash. You can update dependencies via trash --update. All dependencies have been updated to their latest version. Parts of the build system are reworked to drop old notions of Godeps and invocation of the go vet command so that it doesn't run against the vendor folder, as that will just blow up during vetting. The conversion drops OpenCL (and hence GPU mining support) from ethash and our codebase. The short reasoning is that there's noone to maintain and having opencl libs in our deps messes up builds as go install ./... tries to build them, failing with unsatisfied link errors for the C OpenCL deps. golang.org/x/net/context is not vendored in. We expect it to be fetched by the user (i.e. using go get). To keep ci.go builds reproducible the package is "vendored" in build/_vendor.
649 lines
10 KiB
Go
649 lines
10 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build ignore
|
|
|
|
package main
|
|
|
|
// This program generates table.go and table_test.go.
|
|
// Invoke as
|
|
//
|
|
// go run gen.go |gofmt >table.go
|
|
// go run gen.go -test |gofmt >table_test.go
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"math/rand"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// identifier converts s to a Go exported identifier.
|
|
// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
|
|
func identifier(s string) string {
|
|
b := make([]byte, 0, len(s))
|
|
cap := true
|
|
for _, c := range s {
|
|
if c == '-' {
|
|
cap = true
|
|
continue
|
|
}
|
|
if cap && 'a' <= c && c <= 'z' {
|
|
c -= 'a' - 'A'
|
|
}
|
|
cap = false
|
|
b = append(b, byte(c))
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
var test = flag.Bool("test", false, "generate table_test.go")
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
var all []string
|
|
all = append(all, elements...)
|
|
all = append(all, attributes...)
|
|
all = append(all, eventHandlers...)
|
|
all = append(all, extra...)
|
|
sort.Strings(all)
|
|
|
|
if *test {
|
|
fmt.Printf("// generated by go run gen.go -test; DO NOT EDIT\n\n")
|
|
fmt.Printf("package atom\n\n")
|
|
fmt.Printf("var testAtomList = []string{\n")
|
|
for _, s := range all {
|
|
fmt.Printf("\t%q,\n", s)
|
|
}
|
|
fmt.Printf("}\n")
|
|
return
|
|
}
|
|
|
|
// uniq - lists have dups
|
|
// compute max len too
|
|
maxLen := 0
|
|
w := 0
|
|
for _, s := range all {
|
|
if w == 0 || all[w-1] != s {
|
|
if maxLen < len(s) {
|
|
maxLen = len(s)
|
|
}
|
|
all[w] = s
|
|
w++
|
|
}
|
|
}
|
|
all = all[:w]
|
|
|
|
// Find hash that minimizes table size.
|
|
var best *table
|
|
for i := 0; i < 1000000; i++ {
|
|
if best != nil && 1<<(best.k-1) < len(all) {
|
|
break
|
|
}
|
|
h := rand.Uint32()
|
|
for k := uint(0); k <= 16; k++ {
|
|
if best != nil && k >= best.k {
|
|
break
|
|
}
|
|
var t table
|
|
if t.init(h, k, all) {
|
|
best = &t
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if best == nil {
|
|
fmt.Fprintf(os.Stderr, "failed to construct string table\n")
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Lay out strings, using overlaps when possible.
|
|
layout := append([]string{}, all...)
|
|
|
|
// Remove strings that are substrings of other strings
|
|
for changed := true; changed; {
|
|
changed = false
|
|
for i, s := range layout {
|
|
if s == "" {
|
|
continue
|
|
}
|
|
for j, t := range layout {
|
|
if i != j && t != "" && strings.Contains(s, t) {
|
|
changed = true
|
|
layout[j] = ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Join strings where one suffix matches another prefix.
|
|
for {
|
|
// Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
|
|
// maximizing overlap length k.
|
|
besti := -1
|
|
bestj := -1
|
|
bestk := 0
|
|
for i, s := range layout {
|
|
if s == "" {
|
|
continue
|
|
}
|
|
for j, t := range layout {
|
|
if i == j {
|
|
continue
|
|
}
|
|
for k := bestk + 1; k <= len(s) && k <= len(t); k++ {
|
|
if s[len(s)-k:] == t[:k] {
|
|
besti = i
|
|
bestj = j
|
|
bestk = k
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if bestk > 0 {
|
|
layout[besti] += layout[bestj][bestk:]
|
|
layout[bestj] = ""
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
|
|
text := strings.Join(layout, "")
|
|
|
|
atom := map[string]uint32{}
|
|
for _, s := range all {
|
|
off := strings.Index(text, s)
|
|
if off < 0 {
|
|
panic("lost string " + s)
|
|
}
|
|
atom[s] = uint32(off<<8 | len(s))
|
|
}
|
|
|
|
// Generate the Go code.
|
|
fmt.Printf("// generated by go run gen.go; DO NOT EDIT\n\n")
|
|
fmt.Printf("package atom\n\nconst (\n")
|
|
for _, s := range all {
|
|
fmt.Printf("\t%s Atom = %#x\n", identifier(s), atom[s])
|
|
}
|
|
fmt.Printf(")\n\n")
|
|
|
|
fmt.Printf("const hash0 = %#x\n\n", best.h0)
|
|
fmt.Printf("const maxAtomLen = %d\n\n", maxLen)
|
|
|
|
fmt.Printf("var table = [1<<%d]Atom{\n", best.k)
|
|
for i, s := range best.tab {
|
|
if s == "" {
|
|
continue
|
|
}
|
|
fmt.Printf("\t%#x: %#x, // %s\n", i, atom[s], s)
|
|
}
|
|
fmt.Printf("}\n")
|
|
datasize := (1 << best.k) * 4
|
|
|
|
fmt.Printf("const atomText =\n")
|
|
textsize := len(text)
|
|
for len(text) > 60 {
|
|
fmt.Printf("\t%q +\n", text[:60])
|
|
text = text[60:]
|
|
}
|
|
fmt.Printf("\t%q\n\n", text)
|
|
|
|
fmt.Fprintf(os.Stderr, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
|
|
}
|
|
|
|
type byLen []string
|
|
|
|
func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
|
|
func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
|
func (x byLen) Len() int { return len(x) }
|
|
|
|
// fnv computes the FNV hash with an arbitrary starting value h.
|
|
func fnv(h uint32, s string) uint32 {
|
|
for i := 0; i < len(s); i++ {
|
|
h ^= uint32(s[i])
|
|
h *= 16777619
|
|
}
|
|
return h
|
|
}
|
|
|
|
// A table represents an attempt at constructing the lookup table.
|
|
// The lookup table uses cuckoo hashing, meaning that each string
|
|
// can be found in one of two positions.
|
|
type table struct {
|
|
h0 uint32
|
|
k uint
|
|
mask uint32
|
|
tab []string
|
|
}
|
|
|
|
// hash returns the two hashes for s.
|
|
func (t *table) hash(s string) (h1, h2 uint32) {
|
|
h := fnv(t.h0, s)
|
|
h1 = h & t.mask
|
|
h2 = (h >> 16) & t.mask
|
|
return
|
|
}
|
|
|
|
// init initializes the table with the given parameters.
|
|
// h0 is the initial hash value,
|
|
// k is the number of bits of hash value to use, and
|
|
// x is the list of strings to store in the table.
|
|
// init returns false if the table cannot be constructed.
|
|
func (t *table) init(h0 uint32, k uint, x []string) bool {
|
|
t.h0 = h0
|
|
t.k = k
|
|
t.tab = make([]string, 1<<k)
|
|
t.mask = 1<<k - 1
|
|
for _, s := range x {
|
|
if !t.insert(s) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// insert inserts s in the table.
|
|
func (t *table) insert(s string) bool {
|
|
h1, h2 := t.hash(s)
|
|
if t.tab[h1] == "" {
|
|
t.tab[h1] = s
|
|
return true
|
|
}
|
|
if t.tab[h2] == "" {
|
|
t.tab[h2] = s
|
|
return true
|
|
}
|
|
if t.push(h1, 0) {
|
|
t.tab[h1] = s
|
|
return true
|
|
}
|
|
if t.push(h2, 0) {
|
|
t.tab[h2] = s
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// push attempts to push aside the entry in slot i.
|
|
func (t *table) push(i uint32, depth int) bool {
|
|
if depth > len(t.tab) {
|
|
return false
|
|
}
|
|
s := t.tab[i]
|
|
h1, h2 := t.hash(s)
|
|
j := h1 + h2 - i
|
|
if t.tab[j] != "" && !t.push(j, depth+1) {
|
|
return false
|
|
}
|
|
t.tab[j] = s
|
|
return true
|
|
}
|
|
|
|
// The lists of element names and attribute keys were taken from
|
|
// https://html.spec.whatwg.org/multipage/indices.html#index
|
|
// as of the "HTML Living Standard - Last Updated 21 February 2015" version.
|
|
|
|
var elements = []string{
|
|
"a",
|
|
"abbr",
|
|
"address",
|
|
"area",
|
|
"article",
|
|
"aside",
|
|
"audio",
|
|
"b",
|
|
"base",
|
|
"bdi",
|
|
"bdo",
|
|
"blockquote",
|
|
"body",
|
|
"br",
|
|
"button",
|
|
"canvas",
|
|
"caption",
|
|
"cite",
|
|
"code",
|
|
"col",
|
|
"colgroup",
|
|
"command",
|
|
"data",
|
|
"datalist",
|
|
"dd",
|
|
"del",
|
|
"details",
|
|
"dfn",
|
|
"dialog",
|
|
"div",
|
|
"dl",
|
|
"dt",
|
|
"em",
|
|
"embed",
|
|
"fieldset",
|
|
"figcaption",
|
|
"figure",
|
|
"footer",
|
|
"form",
|
|
"h1",
|
|
"h2",
|
|
"h3",
|
|
"h4",
|
|
"h5",
|
|
"h6",
|
|
"head",
|
|
"header",
|
|
"hgroup",
|
|
"hr",
|
|
"html",
|
|
"i",
|
|
"iframe",
|
|
"img",
|
|
"input",
|
|
"ins",
|
|
"kbd",
|
|
"keygen",
|
|
"label",
|
|
"legend",
|
|
"li",
|
|
"link",
|
|
"map",
|
|
"mark",
|
|
"menu",
|
|
"menuitem",
|
|
"meta",
|
|
"meter",
|
|
"nav",
|
|
"noscript",
|
|
"object",
|
|
"ol",
|
|
"optgroup",
|
|
"option",
|
|
"output",
|
|
"p",
|
|
"param",
|
|
"pre",
|
|
"progress",
|
|
"q",
|
|
"rp",
|
|
"rt",
|
|
"ruby",
|
|
"s",
|
|
"samp",
|
|
"script",
|
|
"section",
|
|
"select",
|
|
"small",
|
|
"source",
|
|
"span",
|
|
"strong",
|
|
"style",
|
|
"sub",
|
|
"summary",
|
|
"sup",
|
|
"table",
|
|
"tbody",
|
|
"td",
|
|
"template",
|
|
"textarea",
|
|
"tfoot",
|
|
"th",
|
|
"thead",
|
|
"time",
|
|
"title",
|
|
"tr",
|
|
"track",
|
|
"u",
|
|
"ul",
|
|
"var",
|
|
"video",
|
|
"wbr",
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
|
|
|
|
var attributes = []string{
|
|
"abbr",
|
|
"accept",
|
|
"accept-charset",
|
|
"accesskey",
|
|
"action",
|
|
"alt",
|
|
"async",
|
|
"autocomplete",
|
|
"autofocus",
|
|
"autoplay",
|
|
"challenge",
|
|
"charset",
|
|
"checked",
|
|
"cite",
|
|
"class",
|
|
"cols",
|
|
"colspan",
|
|
"command",
|
|
"content",
|
|
"contenteditable",
|
|
"contextmenu",
|
|
"controls",
|
|
"coords",
|
|
"crossorigin",
|
|
"data",
|
|
"datetime",
|
|
"default",
|
|
"defer",
|
|
"dir",
|
|
"dirname",
|
|
"disabled",
|
|
"download",
|
|
"draggable",
|
|
"dropzone",
|
|
"enctype",
|
|
"for",
|
|
"form",
|
|
"formaction",
|
|
"formenctype",
|
|
"formmethod",
|
|
"formnovalidate",
|
|
"formtarget",
|
|
"headers",
|
|
"height",
|
|
"hidden",
|
|
"high",
|
|
"href",
|
|
"hreflang",
|
|
"http-equiv",
|
|
"icon",
|
|
"id",
|
|
"inputmode",
|
|
"ismap",
|
|
"itemid",
|
|
"itemprop",
|
|
"itemref",
|
|
"itemscope",
|
|
"itemtype",
|
|
"keytype",
|
|
"kind",
|
|
"label",
|
|
"lang",
|
|
"list",
|
|
"loop",
|
|
"low",
|
|
"manifest",
|
|
"max",
|
|
"maxlength",
|
|
"media",
|
|
"mediagroup",
|
|
"method",
|
|
"min",
|
|
"minlength",
|
|
"multiple",
|
|
"muted",
|
|
"name",
|
|
"novalidate",
|
|
"open",
|
|
"optimum",
|
|
"pattern",
|
|
"ping",
|
|
"placeholder",
|
|
"poster",
|
|
"preload",
|
|
"radiogroup",
|
|
"readonly",
|
|
"rel",
|
|
"required",
|
|
"reversed",
|
|
"rows",
|
|
"rowspan",
|
|
"sandbox",
|
|
"spellcheck",
|
|
"scope",
|
|
"scoped",
|
|
"seamless",
|
|
"selected",
|
|
"shape",
|
|
"size",
|
|
"sizes",
|
|
"sortable",
|
|
"sorted",
|
|
"span",
|
|
"src",
|
|
"srcdoc",
|
|
"srclang",
|
|
"start",
|
|
"step",
|
|
"style",
|
|
"tabindex",
|
|
"target",
|
|
"title",
|
|
"translate",
|
|
"type",
|
|
"typemustmatch",
|
|
"usemap",
|
|
"value",
|
|
"width",
|
|
"wrap",
|
|
}
|
|
|
|
var eventHandlers = []string{
|
|
"onabort",
|
|
"onautocomplete",
|
|
"onautocompleteerror",
|
|
"onafterprint",
|
|
"onbeforeprint",
|
|
"onbeforeunload",
|
|
"onblur",
|
|
"oncancel",
|
|
"oncanplay",
|
|
"oncanplaythrough",
|
|
"onchange",
|
|
"onclick",
|
|
"onclose",
|
|
"oncontextmenu",
|
|
"oncuechange",
|
|
"ondblclick",
|
|
"ondrag",
|
|
"ondragend",
|
|
"ondragenter",
|
|
"ondragleave",
|
|
"ondragover",
|
|
"ondragstart",
|
|
"ondrop",
|
|
"ondurationchange",
|
|
"onemptied",
|
|
"onended",
|
|
"onerror",
|
|
"onfocus",
|
|
"onhashchange",
|
|
"oninput",
|
|
"oninvalid",
|
|
"onkeydown",
|
|
"onkeypress",
|
|
"onkeyup",
|
|
"onlanguagechange",
|
|
"onload",
|
|
"onloadeddata",
|
|
"onloadedmetadata",
|
|
"onloadstart",
|
|
"onmessage",
|
|
"onmousedown",
|
|
"onmousemove",
|
|
"onmouseout",
|
|
"onmouseover",
|
|
"onmouseup",
|
|
"onmousewheel",
|
|
"onoffline",
|
|
"ononline",
|
|
"onpagehide",
|
|
"onpageshow",
|
|
"onpause",
|
|
"onplay",
|
|
"onplaying",
|
|
"onpopstate",
|
|
"onprogress",
|
|
"onratechange",
|
|
"onreset",
|
|
"onresize",
|
|
"onscroll",
|
|
"onseeked",
|
|
"onseeking",
|
|
"onselect",
|
|
"onshow",
|
|
"onsort",
|
|
"onstalled",
|
|
"onstorage",
|
|
"onsubmit",
|
|
"onsuspend",
|
|
"ontimeupdate",
|
|
"ontoggle",
|
|
"onunload",
|
|
"onvolumechange",
|
|
"onwaiting",
|
|
}
|
|
|
|
// extra are ad-hoc values not covered by any of the lists above.
|
|
var extra = []string{
|
|
"align",
|
|
"annotation",
|
|
"annotation-xml",
|
|
"applet",
|
|
"basefont",
|
|
"bgsound",
|
|
"big",
|
|
"blink",
|
|
"center",
|
|
"color",
|
|
"desc",
|
|
"face",
|
|
"font",
|
|
"foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
|
|
"foreignobject",
|
|
"frame",
|
|
"frameset",
|
|
"image",
|
|
"isindex",
|
|
"listing",
|
|
"malignmark",
|
|
"marquee",
|
|
"math",
|
|
"mglyph",
|
|
"mi",
|
|
"mn",
|
|
"mo",
|
|
"ms",
|
|
"mtext",
|
|
"nobr",
|
|
"noembed",
|
|
"noframes",
|
|
"plaintext",
|
|
"prompt",
|
|
"public",
|
|
"spacer",
|
|
"strike",
|
|
"svg",
|
|
"system",
|
|
"tt",
|
|
"xmp",
|
|
}
|