diff options
216 files changed, 11944 insertions, 8669 deletions
@@ -11,6 +11,7 @@ Abhinav Gupta <abhinav.g90@gmail.com> Adrian O'Grady <elpollouk@gmail.com> Albert Strasheim <fullung@gmail.com> +Aleksandar Dezelin <dezelin@gmail.com> Alex Brainman <alex.brainman@gmail.com> Alexander Orlov <alexander.orlov@loxal.net> Alexey Borzenkov <snaury@gmail.com> @@ -112,6 +113,7 @@ Mikio Hara <mikioh.mikioh@gmail.com> Mikkel Krautz <mikkel@krautz.dk> Moriyoshi Koizumi <mozo@mozo.jp> Môshe van der Sterre <moshevds@gmail.com> +ngmoco, LLC Nicholas Waples <nwaples@gmail.com> Nigel Kerr <nigel.kerr@gmail.com> Olivier Antoine <olivier.antoine@gmail.com> diff --git a/CONTRIBUTORS b/CONTRIBUTORS index fe38c0381..293df0bb2 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -35,6 +35,7 @@ Abhinav Gupta <abhinav.g90@gmail.com> Adam Langley <agl@golang.org> Adrian O'Grady <elpollouk@gmail.com> Albert Strasheim <fullung@gmail.com> +Aleksandar Dezelin <dezelin@gmail.com> Alex Brainman <alex.brainman@gmail.com> Alexander Orlov <alexander.orlov@loxal.net> Alexey Borzenkov <snaury@gmail.com> @@ -79,6 +80,7 @@ Daniel Fleischman <danielfleischman@gmail.com> Daniel Nadasi <dnadasi@google.com> Daniel Theophanes <kardianos@gmail.com> Dave Cheney <dave@cheney.net> +Dave Grijalva <dgrijalva@ngmoco.com> David Anderson <danderson@google.com> David Crawshaw <david.crawshaw@zentus.com> David Forsythe <dforsythe@gmail.com> @@ -167,6 +169,7 @@ Michael Hoisie <hoisie@gmail.com> Michael T. Jones <mtj@google.com> <michael.jones@gmail.com> Miek Gieben <miek@miek.nl> <remigius.gieben@gmail.com> Mikael Tillenius <mikti42@gmail.com> +Mike Samuel <mikesamuel@gmail.com> Mike Solomon <msolo@gmail.com> Mikio Hara <mikioh.mikioh@gmail.com> Mikkel Krautz <mikkel@krautz.dk> <krautz@gmail.com> @@ -213,6 +216,7 @@ Spring Mc <heresy.mc@gmail.com> Stefan Nilsson <snilsson@nada.kth.se> Stephen Ma <stephenm@golang.org> Stephen Weinberg <stephen@q5comm.com> +Sugu Sougoumarane <ssougou@gmail.com> Sven Almgren <sven@tras.se> Tarmigan Casebolt <tarmigan@gmail.com> Timo Savola <timo.savola@gmail.com> diff --git a/doc/codelab/wiki/edit.html b/doc/codelab/wiki/edit.html index 7a5768ce9..c14953b17 100644 --- a/doc/codelab/wiki/edit.html +++ b/doc/codelab/wiki/edit.html @@ -1,6 +1,6 @@ -<h1>Editing {Title}</h1> +<h1>Editing {{.Title |html}}</h1> -<form action="/save/{Title}" method="POST"> -<div><textarea name="body" rows="20" cols="80">{Body|html}</textarea></div> +<form action="/save/{{.Title |html}}" method="POST"> +<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div> <div><input type="submit" value="Save"></div> </form> diff --git a/doc/codelab/wiki/final-noclosure.go b/doc/codelab/wiki/final-noclosure.go index d09a0d7ab..067f502c6 100644 --- a/doc/codelab/wiki/final-noclosure.go +++ b/doc/codelab/wiki/final-noclosure.go @@ -68,7 +68,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { } func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { - t, err := template.ParseFile(tmpl+".html", nil) + t, err := template.ParseFile(tmpl+".html") if err != nil { http.Error(w, err.String(), http.StatusInternalServerError) return diff --git a/doc/codelab/wiki/final-noerror.go b/doc/codelab/wiki/final-noerror.go index 5fcf1de76..b8edbee9b 100644 --- a/doc/codelab/wiki/final-noerror.go +++ b/doc/codelab/wiki/final-noerror.go @@ -34,14 +34,14 @@ func editHandler(w http.ResponseWriter, r *http.Request) { if err != nil { p = &Page{Title: title} } - t, _ := template.ParseFile("edit.html", nil) + t, _ := template.ParseFile("edit.html") t.Execute(w, p) } func viewHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[lenPath:] p, _ := loadPage(title) - t, _ := template.ParseFile("view.html", nil) + t, _ := template.ParseFile("view.html") t.Execute(w, p) } diff --git a/doc/codelab/wiki/final.go b/doc/codelab/wiki/final.go index c97a699d4..47a4c3473 100644 --- a/doc/codelab/wiki/final.go +++ b/doc/codelab/wiki/final.go @@ -59,7 +59,8 @@ var templates = make(map[string]*template.Template) func init() { for _, tmpl := range []string{"edit", "view"} { - templates[tmpl] = template.MustParseFile(tmpl+".html", nil) + t := template.Must(template.ParseFile(tmpl+".html")) + templates[tmpl] = t } } diff --git a/doc/codelab/wiki/htmlify.go b/doc/codelab/wiki/htmlify.go index 456d06fd5..9e7605b92 100644 --- a/doc/codelab/wiki/htmlify.go +++ b/doc/codelab/wiki/htmlify.go @@ -1,12 +1,12 @@ package main import ( - "os" "template" + "os" "io/ioutil" ) func main() { b, _ := ioutil.ReadAll(os.Stdin) - template.HTMLFormatter(os.Stdout, "", b) + template.HTMLEscape(os.Stdout, b) } diff --git a/doc/codelab/wiki/index.html b/doc/codelab/wiki/index.html index cc187ad90..50e9db5e9 100644 --- a/doc/codelab/wiki/index.html +++ b/doc/codelab/wiki/index.html @@ -429,7 +429,9 @@ Of course, there is a better way. <h2>The <code>template</code> package</h2> <p> -The <code>template</code> package is part of the Go standard library. We can +The <code>template</code> package is part of the Go standard library. +(A new template package is coming; this code lab will be updated soon.) +We can use <code>template</code> to keep the HTML in a separate file, allowing us to change the layout of our edit page without modifying the underlying Go code. @@ -454,10 +456,10 @@ Open a new file named <code>edit.html</code>, and add the following lines: </p> <pre> -<h1>Editing {Title}</h1> +<h1>Editing {{.Title |html}}</h1> -<form action="/save/{Title}" method="POST"> -<div><textarea name="body" rows="20" cols="80">{Body|html}</textarea></div> +<form action="/save/{{.Title |html}}" method="POST"> +<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div> <div><input type="submit" value="Save"></div> </form> </pre> @@ -474,7 +476,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) { if err != nil { p = &Page{Title: title} } - t, _ := template.ParseFile("edit.html", nil) + t, _ := template.ParseFile("edit.html") t.Execute(w, p) } </pre> @@ -485,19 +487,21 @@ The function <code>template.ParseFile</code> will read the contents of </p> <p> -The method <code>t.Execute</code> replaces all occurrences of -<code>{Title}</code> and <code>{Body}</code> with the values of -<code>p.Title</code> and <code>p.Body</code>, and writes the resultant -HTML to the <code>http.ResponseWriter</code>. +The method <code>t.Execute</code> executes the template, writing the +generated HTML to the <code>http.ResponseWriter</code>. +The <code>.Title</code> and <code>.Body</code> dotted identifiers refer to +<code>p.Title</code> and <code>p.Body</code>. </p> <p> -Note that we've used <code>{Body|html}</code> in the above template. -The <code>|html</code> part asks the template engine to pass the value -<code>Body</code> through the <code>html</code> formatter before outputting it, -which escapes HTML characters (such as replacing <code>></code> with -<code>&gt;</code>). -This will prevent user data from corrupting the form HTML. +Template directives are enclosed in double curly braces. +The <code>printf "%s" .Body</code> instruction is a function call +that outputs <code>.Body</code> as a string instead of a stream of bytes, +the same as a call to <code>fmt.Printf</code>. +The <code>|html</code> part of each directive pipes the value through the +<code>html</code> formatter before outputting it, which escapes HTML +characters (such as replacing <code>></code> with <code>&gt;</code>), +preventing user data from corrupting the form HTML. </p> <p> @@ -511,11 +515,11 @@ While we're working with templates, let's create a template for our </p> <pre> -<h1>{Title}</h1> +<h1>{{.Title |html}}</h1> -<p>[<a href="/edit/{Title}">edit</a>]</p> +<p>[<a href="/edit/{{.Title |html}}">edit</a>]</p> -<div>{Body}</div> +<div>{{printf "%s" .Body |html}}</div> </pre> <p> @@ -526,7 +530,7 @@ Modify <code>viewHandler</code> accordingly: func viewHandler(w http.ResponseWriter, r *http.Request) { title := r.URL.Path[lenPath:] p, _ := loadPage(title) - t, _ := template.ParseFile("view.html", nil) + t, _ := template.ParseFile("view.html") t.Execute(w, p) } </pre> @@ -706,16 +710,17 @@ var templates = make(map[string]*template.Template) <p> Then we create an <code>init</code> function, which will be called before <code>main</code> at program initialization. The function -<code>template.MustParseFile</code> is a convenience wrapper around -<code>ParseFile</code> that does not return an error code; instead, it panics -if an error is encountered. A panic is appropriate here; if the templates can't -be loaded the only sensible thing to do is exit the program. +<code>template.Must</code> is a convenience wrapper that panics when passed a +non-nil <code>os.Error</code> value, and otherwise returns the +<code>*Template</code> unaltered. A panic is appropriate here; if the templates +can't be loaded the only sensible thing to do is exit the program. </p> <pre> func init() { for _, tmpl := range []string{"edit", "view"} { - templates[tmpl] = template.MustParseFile(tmpl+".html", nil) + t := template.Must(template.ParseFile(tmpl + ".html")) + templates[tmpl] = t } } </pre> @@ -761,10 +766,9 @@ var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$") <p> The function <code>regexp.MustCompile</code> will parse and compile the regular expression, and return a <code>regexp.Regexp</code>. -<code>MustCompile</code>, like <code>template.MustParseFile</code>, -is distinct from <code>Compile</code> in that it will panic if -the expression compilation fails, while <code>Compile</code> returns an -<code>os.Error</code> as a second parameter. +<code>MustCompile</code> is distinct from <code>Compile</code> in that it will +panic if the expression compilation fails, while <code>Compile</code> returns +an <code>os.Error</code> as a second parameter. </p> <p> diff --git a/doc/codelab/wiki/srcextract.go b/doc/codelab/wiki/srcextract.go index 67294784e..6b5fbcb43 100644 --- a/doc/codelab/wiki/srcextract.go +++ b/doc/codelab/wiki/srcextract.go @@ -8,8 +8,8 @@ import ( "go/ast" "go/token" "log" - "os" "template" + "os" ) var ( diff --git a/doc/codelab/wiki/view.html b/doc/codelab/wiki/view.html index ca2ffc20b..023391577 100644 --- a/doc/codelab/wiki/view.html +++ b/doc/codelab/wiki/view.html @@ -1,5 +1,5 @@ -<h1>{Title}</h1> +<h1>{{.Title |html}}</h1> -<p>[<a href="/edit/{Title}">edit</a>]</p> +<p>[<a href="/edit/{{.Title |html}}">edit</a>]</p> -<div>{Body}</div> +<div>{{printf "%s" .Body |html}}</div> diff --git a/doc/codelab/wiki/wiki.html b/doc/codelab/wiki/wiki.html index 4db880b9d..634babd8b 100644 --- a/doc/codelab/wiki/wiki.html +++ b/doc/codelab/wiki/wiki.html @@ -369,7 +369,9 @@ Of course, there is a better way. <h2>The <code>template</code> package</h2> <p> -The <code>template</code> package is part of the Go standard library. We can +The <code>template</code> package is part of the Go standard library. +(A new template package is coming; this code lab will be updated soon.) +We can use <code>template</code> to keep the HTML in a separate file, allowing us to change the layout of our edit page without modifying the underlying Go code. @@ -412,19 +414,21 @@ The function <code>template.ParseFile</code> will read the contents of </p> <p> -The method <code>t.Execute</code> replaces all occurrences of -<code>{Title}</code> and <code>{Body}</code> with the values of -<code>p.Title</code> and <code>p.Body</code>, and writes the resultant -HTML to the <code>http.ResponseWriter</code>. +The method <code>t.Execute</code> executes the template, writing the +generated HTML to the <code>http.ResponseWriter</code>. +The <code>.Title</code> and <code>.Body</code> dotted identifiers refer to +<code>p.Title</code> and <code>p.Body</code>. </p> <p> -Note that we've used <code>{Body|html}</code> in the above template. -The <code>|html</code> part asks the template engine to pass the value -<code>Body</code> through the <code>html</code> formatter before outputting it, -which escapes HTML characters (such as replacing <code>></code> with -<code>&gt;</code>). -This will prevent user data from corrupting the form HTML. +Template directives are enclosed in double curly braces. +The <code>printf "%s" .Body</code> instruction is a function call +that outputs <code>.Body</code> as a string instead of a stream of bytes, +the same as a call to <code>fmt.Printf</code>. +The <code>|html</code> part of each directive pipes the value through the +<code>html</code> formatter before outputting it, which escapes HTML +characters (such as replacing <code>></code> with <code>&gt;</code>), +preventing user data from corrupting the form HTML. </p> <p> @@ -570,10 +574,10 @@ our <code>*Template</code> values, keyed by <code>string</code> <p> Then we create an <code>init</code> function, which will be called before <code>main</code> at program initialization. The function -<code>template.MustParseFile</code> is a convenience wrapper around -<code>ParseFile</code> that does not return an error code; instead, it panics -if an error is encountered. A panic is appropriate here; if the templates can't -be loaded the only sensible thing to do is exit the program. +<code>template.Must</code> is a convenience wrapper that panics when passed a +non-nil <code>os.Error</code> value, and otherwise returns the +<code>*Template</code> unaltered. A panic is appropriate here; if the templates +can't be loaded the only sensible thing to do is exit the program. </p> <pre> @@ -616,10 +620,9 @@ Then we can create a global variable to store our validation regexp: <p> The function <code>regexp.MustCompile</code> will parse and compile the regular expression, and return a <code>regexp.Regexp</code>. -<code>MustCompile</code>, like <code>template.MustParseFile</code>, -is distinct from <code>Compile</code> in that it will panic if -the expression compilation fails, while <code>Compile</code> returns an -<code>os.Error</code> as a second parameter. +<code>MustCompile</code> is distinct from <code>Compile</code> in that it will +panic if the expression compilation fails, while <code>Compile</code> returns +an <code>os.Error</code> as a second parameter. </p> <p> diff --git a/doc/codewalk/markov.go b/doc/codewalk/markov.go new file mode 100644 index 000000000..959c2b158 --- /dev/null +++ b/doc/codewalk/markov.go @@ -0,0 +1,130 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Generating random text: a Markov chain algorithm + +Based on the program presented in the "Design and Implementation" chapter +of The Practice of Programming (Kernighan and Pike, Addison-Wesley 1999). +See also Computer Recreations, Scientific American 260, 122 - 125 (1989). + +A Markov chain algorithm generates text by creating a statistical model of +potential textual suffixes for a given prefix. Consider this text: + + I am not a number! I am a free man! + +Our Markov chain algorithm would arrange this text into this set of prefixes +and suffixes, or "chain": (This table assumes a prefix length of two words.) + + Prefix Suffix + + "" "" I + "" I am + I am a + I am not + a free man! + am a free + am not a + a number! I + number! I am + not a number! + +To generate text using this table we select an initial prefix ("I am", for +example), choose one of the suffixes associated with that prefix at random +with probability determined by the input statistics ("a"), +and then create a new prefix by removing the first word from the prefix +and appending the suffix (making the new prefix is "am a"). Repeat this process +until we can't find any suffixes for the current prefix or we exceed the word +limit. (The word limit is necessary as the chain table may contain cycles.) + +Our version of this program reads text from standard input, parsing it into a +Markov chain, and writes generated text to standard output. +The prefix and output lengths can be specified using the -prefix and -words +flags on the command-line. +*/ +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "os" + "rand" + "strings" + "time" +) + +// Prefix is a Markov chain prefix of one or more words. +type Prefix []string + +// String returns the Prefix as a string (for use as a map key). +func (p Prefix) String() string { + return strings.Join(p, " ") +} + +// Shift removes the first word from the Prefix and appends the given word. +func (p Prefix) Shift(word string) { + copy(p, p[1:]) + p[len(p)-1] = word +} + +// Chain contains a map ("chain") of prefixes to a list of suffixes. +// A prefix is a string of prefixLen words joined with spaces. +// A suffix is a single word. A prefix can have multiple suffixes. +type Chain struct { + chain map[string][]string + prefixLen int +} + +// NewChain returns a new Chain with prefixes of prefixLen words. +func NewChain(prefixLen int) *Chain { + return &Chain{make(map[string][]string), prefixLen} +} + +// Build reads text from the provided Reader and +// parses it into prefixes and suffixes that are stored in Chain. +func (c *Chain) Build(r io.Reader) { + br := bufio.NewReader(r) + p := make(Prefix, c.prefixLen) + for { + var s string + if _, err := fmt.Fscan(br, &s); err != nil { + break + } + key := p.String() + c.chain[key] = append(c.chain[key], s) + p.Shift(s) + } +} + +// Generate returns a string of at most n words generated from Chain. +func (c *Chain) Generate(n int) string { + p := make(Prefix, c.prefixLen) + var words []string + for i := 0; i < n; i++ { + choices := c.chain[p.String()] + if len(choices) == 0 { + break + } + next := choices[rand.Intn(len(choices))] + words = append(words, next) + p.Shift(next) + } + return strings.Join(words, " ") +} + +func main() { + // Register command-line flags. + numWords := flag.Int("words", 100, "maximum number of words to print") + prefixLen := flag.Int("prefix", 2, "prefix length in words") + + flag.Parse() // Parse command-line flags. + rand.Seed(time.Nanoseconds()) // Seed the random number generator. + + c := NewChain(*prefixLen) // Initialize a new Chain. + c.Build(os.Stdin) // Build chains from standard input. + text := c.Generate(*numWords) // Generate text. + fmt.Println(text) // Write text to standard output. +} diff --git a/doc/codewalk/markov.xml b/doc/codewalk/markov.xml new file mode 100644 index 000000000..a89b4d0ce --- /dev/null +++ b/doc/codewalk/markov.xml @@ -0,0 +1,308 @@ +<!-- +Copyright 2011 The Go Authors. All rights reserved. +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file. +--> + +<codewalk title="Generating arbitrary text: a Markov chain algorithm"> + +<step title="Introduction" src="doc/codewalk/markov.go:/Generating/,/line\./"> + This codewalk describes a program that generates random text using + a Markov chain algorithm. The package comment describes the algorithm + and the operation of the program. Please read it before continuing. +</step> + +<step title="Modeling Markov chains" src="doc/codewalk/markov.go:/ chain/"> + A chain consists of a prefix and a suffix. Each prefix is a set + number of words, while a suffix is a single word. + A prefix can have an arbitrary number of suffixes. + To model this data, we use a <code>map[string][]string</code>. + Each map key is a prefix (a <code>string</code>) and its values are + lists of suffixes (a slice of strings, <code>[]string</code>). + <br/><br/> + Here is the example table from the package comment + as modeled by this data structure: + <pre> +map[string][]string{ + " ": {"I"}, + " I": {"am"}, + "I am": {"a", "not"}, + "a free": {"man!"}, + "am a": {"free"}, + "am not": {"a"}, + "a number!": {"I"}, + "number! I": {"am"}, + "not a": {"number!"}, +}</pre> + While each prefix consists of multiple words, we + store prefixes in the map as a single <code>string</code>. + It would seem more natural to store the prefix as a + <code>[]string</code>, but we can't do this with a map because the + key type of a map must implement equality (and slices do not). + <br/><br/> + Therefore, in most of our code we will model prefixes as a + <code>[]string</code> and join the strings together with a space + to generate the map key: + <pre> +Prefix Map key + +[]string{"", ""} " " +[]string{"", "I"} " I" +[]string{"I", "am"} "I am" +</pre> +</step> + +<step title="The Chain struct" src="doc/codewalk/markov.go:/type Chain/,/}/"> + The complete state of the chain table consists of the table itself and + the word length of the prefixes. The <code>Chain</code> struct stores + this data. +</step> + +<step title="The NewChain constructor function" src="doc/codewalk/markov.go:/func New/,/}/"> + The <code>Chain</code> struct has two unexported fields (those that + do not begin with an upper case character), and so we write a + <code>NewChain</code> constructor function that initializes the + <code>chain</code> map with <code>make</code> and sets the + <code>prefixLen</code> field. + <br/><br/> + This is constructor function is not strictly necessary as this entire + program is within a single package (<code>main</code>) and therefore + there is little practical difference between exported and unexported + fields. We could just as easily write out the contents of this function + when we want to construct a new Chain. + But using these unexported fields is good practice; it clearly denotes + that only methods of Chain and its constructor function should access + those fields. Also, structuring <code>Chain</code> like this means we + could easily move it into its own package at some later date. +</step> + +<step title="The Prefix type" src="doc/codewalk/markov.go:/type Prefix/"> + Since we'll be working with prefixes often, we define a + <code>Prefix</code> type with the concrete type <code>[]string</code>. + Defining a named type clearly allows us to be explicit when we are + working with a prefix instead of just a <code>[]string</code>. + Also, in Go we can define methods on any named type (not just structs), + so we can add methods that operate on <code>Prefix</code> if we need to. +</step> + +<step title="The String method" src="doc/codewalk/markov.go:/func[^\n]+String/,/}/"> + The first method we define on <code>Prefix</code> is + <code>String</code>. It returns a <code>string</code> representation + of a <code>Prefix</code> by joining the slice elements together with + spaces. We will use this method to generate keys when working with + the chain map. +</step> + +<step title="Building the chain" src="doc/codewalk/markov.go:/func[^\n]+Build/,/\n}/"> + The <code>Build</code> method reads text from an <code>io.Reader</code> + and parses it into prefixes and suffixes that are stored in the + <code>Chain</code>. + <br/><br/> + The <code><a href="/pkg/io/#Reader">io.Reader</a></code> is an + interface type that is widely used by the standard library and + other Go code. Our code uses the + <code><a href="/pkg/fmt/#Fscan">fmt.Fscan</a></code> function, which + reads space-separated values from an <code>io.Reader</code>. + <br/><br/> + The <code>Build</code> method returns once the <code>Reader</code>'s + <code>Read</code> method returns <code>os.EOF</code> (end of file) + or some other read error occurs. +</step> + +<step title="Buffering the input" src="doc/codewalk/markov.go:/bufio\.NewReader/"> + This function does many small reads, which can be inefficient for some + <code>Readers</code>. For efficiency we wrap the provided + <code>io.Reader</code> with + <code><a href="/pkg/bufio/">bufio.NewReader</a></code> to create a + new <code>io.Reader</code> that provides buffering. +</step> + +<step title="The Prefix variable" src="doc/codewalk/markov.go:/make\(Prefix/"> + At the top of the function we make a <code>Prefix</code> slice + <code>p</code> using the <code>Chain</code>'s <code>prefixLen</code> + field as its length. + We'll use this variable to hold the current prefix and mutate it with + each new word we encounter. +</step> + +<step title="Scanning words" src="doc/codewalk/markov.go:/var s string/,/\n }/"> + In our loop we read words from the <code>Reader</code> into a + <code>string</code> variable <code>s</code> using + <code>fmt.Fscan</code>. Since <code>Fscan</code> uses space to + separate each input value, each call will yield just one word + (including punctuation), which is exactly what we need. + <br/><br/> + <code>Fscan</code> returns an error if it encounters a read error + (<code>os.EOF</code>, for example) or if it can't scan the requested + value (in our case, a single string). In either case we just want to + stop scanning, so we <code>break</code> out of the loop. +</step> + +<step title="Adding a prefix and suffix to the chain" src="doc/codewalk/markov.go:/ key/,/key\], s\)"> + The word stored in <code>s</code> is a new suffix. We add the new + prefix/suffix combination to the <code>chain</code> map by computing + the map key with <code>p.String</code> and appending the suffix + to the slice stored under that key. + <br/><br/> + The built-in <code>append</code> function appends elements to a slice + and allocates new storage when necessary. When the provided slice is + <code>nil</code>, <code>append</code> allocates a new slice. + This behavior conveniently ties in with the semantics of our map: + retrieving an unset key returns the zero value of the value type and + the zero value of <code>[]string</code> is <code>nil</code>. + When our program encounters a new prefix (yielding a <code>nil</code> + value in the map) <code>append</code> will allocate a new slice. + <br/><br/> + For more information about the <code>append</code> function and slices + in general see the + <a href="http://blog.golang.org/2011/01/go-slices-usage-and-internals.html">Slices: usage and internals</a> article. +</step> + +<step title="Pushing the suffix onto the prefix" src="doc/codewalk/markov.go:/p\.Shift/"> + Before reading the next word our algorithm requires us to drop the + first word from the prefix and push the current suffix onto the prefix. + <br/><br/> + When in this state + <pre> +p == Prefix{"I", "am"} +s == "not" </pre> + the new value for <code>p</code> would be + <pre> +p == Prefix{"am", "not"}</pre> + This operation is also required during text generation so we put + the code to perform this mutation of the slice inside a method on + <code>Prefix</code> named <code>Shift</code>. +</step> + +<step title="The Shift method" src="doc/codewalk/markov.go:/func[^\n]+Shift/,/\n}/"> + The <code>Shift</code> method uses the built-in <code>copy</code> + function to copy the last len(p)-1 elements of <code>p</code> to + the start of the slice, effectively moving the elements + one index to the left (if you consider zero as the leftmost index). + <pre> +p := Prefix{"I", "am"} +copy(p, p[:1]) +// p == Prefix{"am", "am"}</pre> + We then assign the provided <code>word</code> to the last index + of the slice: + <pre> +// suffix == "not" +p[len(p)-1] = suffix +// p == Prefix{"am", "not"}</pre> +</step> + +<step title="Generating text" src="doc/codewalk/markov.go:/func[^\n]+Generate/,/\n}/"> + The <code>Generate</code> method is similar to <code>Build</code> + except that instead of reading words from a <code>Reader</code> + and storing them in a map, it reads words from the map and + appends them to a slice (<code>words</code>). + <br/><br/> + <code>Generate</code> uses a conditional for loop to generate + up to <code>n</code> words. +</step> + +<step title="Getting potential suffixes" src="doc/codewalk/markov.go:/choices/,/}\n/"> + At each iteration of the loop we retrieve a list of potential suffixes + for the current prefix. We access the <code>chain</code> map at key + <code>p.String()</code> and assign its contents to <code>choices</code>. + <br/><br/> + If <code>len(choices)</code> is zero we break out of the loop as there + are no potential suffixes for that prefix. + This test also works if the key isn't present in the map at all: + in that case, <code>choices</code> will be <code>nil</code> and the + length of a <code>nil</code> slice is zero. +</step> + +<step title="Choosing a suffix at random" src="doc/codewalk/markov.go:/next := choices/,/Shift/"> + To choose a suffix we use the + <code><a href="/pkg/rand/#Intn">rand.Intn</a></code> function. + It returns a random integer up to (but not including) the provided + value. Passing in <code>len(choices)</code> gives us a random index + into the full length of the list. + <br/><br/> + We use that index to pick our new suffix, assign it to + <code>next</code> and append it to the <code>words</code> slice. + <br/><br/> + Next, we <code>Shift</code> the new suffix onto the prefix just as + we did in the <code>Build</code> method. +</step> + +<step title="Returning the generated text" src="doc/codewalk/markov.go:/Join\(words/"> + Before returning the generated text as a string, we use the + <code>strings.Join</code> function to join the elements of + the <code>words</code> slice together, separated by spaces. +</step> + +<step title="Command-line flags" src="doc/codewalk/markov.go:/Register command-line flags/,/prefixLen/"> + To make it easy to tweak the prefix and generated text lengths we + use the <code><a href="/pkg/flag/">flag</a></code> package to parse + command-line flags. + <br/><br/> + These calls to <code>flag.Int</code> register new flags with the + <code>flag</code> package. The arguments to <code>Int</code> are the + flag name, its default value, and a description. The <code>Int</code> + function returns a pointer to an integer that will contain the + user-supplied value (or the default value if the flag was omitted on + the command-line). +</step> + +<step title="Program set up" src="doc/codewalk/markov.go:/flag.Parse/,/rand.Seed/"> + The <code>main</code> function begins by parsing the command-line + flags with <code>flag.Parse</code> and seeding the <code>rand</code> + package's random number generator with the current time. + <br/><br/> + If the command-line flags provided by the user are invalid the + <code>flag.Parse</code> function will print an informative usage + message and terminate the program. +</step> + +<step title="Creating and building a new Chain" src="doc/codewalk/markov.go:/c := NewChain/,/c\.Build/"> + To create the new <code>Chain</code> we call <code>NewChain</code> + with the value of the <code>prefix</code> flag. + <br/><br/> + To build the chain we call <code>Build</code> with + <code>os.Stdin</code> (which implements <code>io.Reader</code>) so + that it will read its input from standard input. +</step> + +<step title="Generating and printing text" src="doc/codewalk/markov.go:/c\.Generate/,/fmt.Println/"> + Finally, to generate text we call <code>Generate</code> with + the value of the <code>words</code> flag and assigning the result + to the variable <code>text</code>. + <br/><br/> + Then we call <code>fmt.Println</code> to write the text to standard + output, followed by a carriage return. +</step> + +<step title="Using this program" src="doc/codewalk/markov.go"> + To use this program, first compile and link it. + If you are using <code>6g</code> as your compiler, the command + would look something like this: + <pre> +$ 6g markov.go && 6l -o markov markov.6</pre> + And then execute it while piping in some input text: + <pre> +$ echo "a man a plan a canal panama" | ./markov -prefix=1 +a plan a man a plan a canal panama + </pre> + Here's a transcript of generating some text using the Go distribution's + README file as source material: + <pre> +$ ./markov -words=10 < $GOROOT/go/README +This is the source code repository for the Go source +$ ./markov -prefix=1 -words=10 < $GOROOT/go/README +This is the go directory (the one containing this README). +$ ./markov -prefix=1 -words=10 < $GOROOT/go/README +This is the variable if you have just untarred a</pre> +</step> + +<step title="An exercise for the reader" src="doc/codewalk/markov.go"> + The <code>Generate</code> function does a lot of allocations when it + builds the <code>words</code> slice. As an exercise, modify it to + take an <code>io.Writer</code> to which it incrementally writes the + generated text with <code>Fprint</code>. + Aside from being more efficient this makes <code>Generate</code> + more symmetrical to <code>Build</code>. +</step> + +</codewalk> diff --git a/doc/devel/weekly.html b/doc/devel/weekly.html index bd30c3530..5a9e3d99e 100644 --- a/doc/devel/weekly.html +++ b/doc/devel/weekly.html @@ -14,6 +14,69 @@ hg pull hg update weekly.<i>YYYY-MM-DD</i> </pre> +<h2 id="2011-08-17">2011-08-17</h2> + +<pre> +This weekly contains some package re-shuffling. Users of the http and +template packages may be affected. + +This weekly replaces the template package with exp/template. +The original template package is still available as old/template. +The old/template package is deprecated and will be removed at some point +in the future. The Go tree has been updated to use the new template package. +We encourage users of the old template package to switch to the new one. +Code that uses template or exp/template will need to change +its import lines to "old/template" or "template", respectively. + +The http package's URL parsing and query escaping code (such as ParseURL and +URLEscape) has been moved to the new url package, with several simplifications +to the names. Client code can be updated automatically with gofix. + +* asn1: support unmarshalling structs with int32 members (thanks Dave Cheney). +* build: allow builds without cgo or hg, + support versioning without hg (thanks Gustavo Niemeyer). +* builtin: add documentation for builtins. +* cgo: omit duplicate symbols in writeDefs (thanks Julian Phillips). +* misc: add support for OpenBSD. +* doc/codewalk: new Markov chain codewalk. +* exp/norm: added trie lookup code and associated tests, + generate trie struct in triegen.go for better encapsulation, + implementation of decomposition and composing functionality. +* exp/template/html: new experimental package for auto-escaping HTML templates. +* exp/template: don't panic on range of nil interface, + rename Parse*File and Parse*Files for clarity, + support field syntax on maps (thanks Gustavo Niemeyer), and + many other fixes and changes. +* gc: implement nil chan and nil map support. +* go/parser: range clause and type literal fixes. +* godoc: show all top-level decls for (fake) package builtin. +* goinstall: really report all newly-installed public packages. +* html: parse more malformed tags. +* http: fix ParseMultipartForm after MultipartReader error, + fix side effects in DefaultTransport's RoundTrip method (thanks Dave Grijalva). +* json: fix []unmarshaler case. +* ld: make addaddrplus4 static (thanks Lucio De Re). +* syscall: move multicast address handling to the net package. +* net: Plan 9 support (thanks Fazlul Shahriar), + add SetTimeout to Listener interface (thanks Aleksandar Dezelin), + add multicast stubs for OpenBSD, + return correct local address for an accepted TCP connection (thanks Mikio Hara). +* reflect: panic on Invalid Interface call (thanks Gustavo Niemeyer). +* rpc: implement ServeRequest to synchronously serve a single request, + make Server.Mutex unexported. +* runtime: better checks for syscall.NewCallback parameter (thanks Alex Brainman), + correct SEH installation during callbacks (thanks Alex Brainman), + fix GC bitmap corruption, + fix pseudo-randomness on some selects (thanks Gustavo Niemeyer). +* syscall: make LazyDLL/LazyProc.Mutex unexported. +* test: allow multiple patterns in errchk, + new nil semantics. +* time: take fractional seconds even if not in the format string. +* url: new package. +* utf8: rename some internal constants to remove leading underscores. +* xml: escape string chardata in xml.Marshal. +</pre> + <h2 id="2011-08-10">2011-08-10</h2> <pre> diff --git a/doc/effective_go.html b/doc/effective_go.html index ab109280f..37cb516b0 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -2926,7 +2926,7 @@ import ( "http" "io" "log" - "template" + "old/template" // New template package coming soon... ) var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18 diff --git a/doc/tmpltohtml.go b/doc/tmpltohtml.go index 0a509d90b..f4d2e2c2c 100644 --- a/doc/tmpltohtml.go +++ b/doc/tmpltohtml.go @@ -46,7 +46,7 @@ func main() { // Read and parse the input. name := flag.Args()[0] tmpl := template.New(name).Funcs(template.FuncMap{"code": code}) - if err := tmpl.ParseFile(name); err != nil { + if _, err := tmpl.ParseFile(name); err != nil { log.Fatal(err) } diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py index adaff3287..63f67fff9 100644 --- a/lib/codereview/codereview.py +++ b/lib/codereview/codereview.py @@ -1722,6 +1722,7 @@ def submit(ui, repo, *pats, **opts): print Indent('\n'.join(cl.files), "\t") return "dry run; not submitted" + set_status("pushing " + cl.name + " to remote server") m = match.exact(repo.root, repo.getcwd(), cl.files) node = repo.commit(ustr(opts['message']), ustr(userline), opts.get('date'), m) if not node: diff --git a/lib/godoc/codewalk.html b/lib/godoc/codewalk.html index 47f8a22e2..2835c6e82 100644 --- a/lib/godoc/codewalk.html +++ b/lib/godoc/codewalk.html @@ -18,9 +18,9 @@ <img title="View code in new window" alt="Pop Out Code" src="/doc/codewalk/popout.png" style="display: block; float: right;"/> </a> <select id="code-selector"> - {.repeated section File} - <option value="/doc/codewalk/?fileprint=/{@|html-esc}">{@|html-esc}</option> - {.end} + {{range .File}} + <option value="/doc/codewalk/?fileprint=/{{urlquery .}}">{{html .}}</option> + {{end}} </select> </div> <div id="code"> @@ -35,19 +35,19 @@ </div> <div class="right" id="comment-column"> <div id="comment-area"> - {.repeated section Step} + {{range .Step}} <div class="comment first last"> - <a class="comment-link" href="/doc/codewalk/?fileprint=/{File|html-esc}&lo={Lo|html-esc}&hi={Hi|html-esc}#mark" target="code-display"></a> - <div class="comment-title">{Title|html-esc}</div> + <a class="comment-link" href="/doc/codewalk/?fileprint=/{{urlquery .File}}&lo={{urlquery .Lo}}&hi={{urlquery .Hi}}#mark" target="code-display"></a> + <div class="comment-title">{{html .Title}}</div> <div class="comment-text"> - {.section Err} - ERROR LOADING FILE: {Err|html-esc}<br/><br/> - {.end} - {XML} + {{with .Err}} + ERROR LOADING FILE: {{html .}}<br/><br/> + {{end}} + {{.XML}} </div> - <div class="comment-text file-name"><span class="path-file">{@|html-esc}</span></div> + <div class="comment-text file-name"><span class="path-file">{{html .}}</span></div> </div> - {.end} + {{end}} </div> <div id="comment-options" class="setting"> <a id="prev-comment" href="#"><span class="hotkey">p</span>revious step</a> diff --git a/lib/godoc/codewalkdir.html b/lib/godoc/codewalkdir.html index 61a9a8b3b..b7674c6ce 100644 --- a/lib/godoc/codewalkdir.html +++ b/lib/godoc/codewalkdir.html @@ -5,11 +5,12 @@ --> <table class="layout"> -{.repeated section @} +{{range .}} <tr> - <td><a href="{Name|html-esc}">{Name|html-esc}</a></td> - <td width="25"> </td> - <td>{Title|html-esc}</td> + {{$name_html := html .Name}} + <td><a href="{{$name_html}}">{{$name_html}}</a></td> + <td width="25"> </td> + <td>{{html .Title}}</td> </tr> -{.end} +{{end}} </table> diff --git a/lib/godoc/dirlist.html b/lib/godoc/dirlist.html index 29b4b2435..a3e1a2fa8 100644 --- a/lib/godoc/dirlist.html +++ b/lib/godoc/dirlist.html @@ -16,14 +16,16 @@ <tr> <td><a href="..">..</a></td> </tr> -{.repeated section @} +{{range .}} <tr> - <td align="left"><a href="{@|fileInfoName}">{@|fileInfoName}</a></td> + {{$name_html := fileInfoName . | html}} + <td align="left"><a href="{{$name_html}}">{{$name_html}}</a></td> <td></td> - <td align="right">{@|fileInfoSize}</td> + <td align="right">{{html .Size}}</td> <td></td> - <td align="left">{@|fileInfoTime}</td> + <td align="left">{{fileInfoTime . | html}}</td> </tr> -{.end} +{{end}} + </table> </p> diff --git a/lib/godoc/error.html b/lib/godoc/error.html index c14c57405..7573aa236 100644 --- a/lib/godoc/error.html +++ b/lib/godoc/error.html @@ -5,5 +5,5 @@ --> <p> -<span class="alert" style="font-size:120%">{@|html-esc}</span> +<span class="alert" style="font-size:120%">{{html .}}</span> </p> diff --git a/lib/godoc/godoc.html b/lib/godoc/godoc.html index bd53f2615..671160d5a 100644 --- a/lib/godoc/godoc.html +++ b/lib/godoc/godoc.html @@ -2,11 +2,11 @@ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> -{.section Title} - <title>{@|html-esc} - The Go Programming Language</title> -{.or} +{{with .Title}} + <title>{{html .}} - The Go Programming Language</title> +{{else}} <title>The Go Programming Language</title> -{.end} +{{end}} <link rel="stylesheet" href="/doc/all.css" type="text/css" media="all" charset="utf-8"> <!--[if lt IE 8]> <link rel="stylesheet" href="/doc/ie.css" type="text/css"> @@ -23,19 +23,17 @@ </ul> <div class="quickref"> <form method="GET" action="/search"> - {.section PkgRoots} - {.repeated section PkgRoots} - <a href="/pkg/{@|html-esc}">{@|html-esc}</a> <span class="sep">|</span> - {.end} - {.or} + {{range .PkgRoots}} + <a href="/pkg/{{html .}}">{{html .}}</a> <span class="sep">|</span> + {{else}} References: - {.end} + {{end}} <a href="/pkg/">Packages</a> <span class="sep">|</span> <a href="/cmd/">Commands</a> <span class="sep">|</span> <a href="/doc/go_spec.html">Specification</a> - {.section SearchBox} - <input id="search" type="search" name="q" value="{.section Query}{Query|html-esc}{.end}" class="{.section Query}{.or}inactive{.end}" placeholder="code search" results="0" /> - {.end} + {{if .SearchBox}} + <input id="search" type="search" name="q" value="{{with .Query}}{{html .}}{{end}}" class="{{if not .Query}}inactive{{end}}" placeholder="code search" results="0" /> + {{end}} </form> </div> </div> @@ -43,28 +41,28 @@ </div> <div id="content"> <!-- Menu is HTML-escaped elsewhere --> - {.section Menu} + {{with .Menu}} <div id="menu"> - {@} + {{printf "%s" .}} </div> - {.end} + {{end}} - {.section Title} - <h1 id="generatedHeader">{@|html-esc}</h1> - {.end} - {.section Subtitle} - <span class="subtitle">{@|html-esc}</span> - {.end} + {{with .Title}} + <h1 id="generatedHeader">{{html .}}</h1> + {{end}} + {{with .Subtitle}} + <span class="subtitle">{{html .}}</span> + {{end}} <!-- The Table of Contents is automatically inserted in this <div>. Do not delete this <div>. --> <div id="nav"></div> <!-- Content is HTML-escaped elsewhere --> - {Content} + {{printf "%s" .Content}} </div> <div id="site-info"> - <p>Build version {Version|html-esc}. Except as noted, this content is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License</a>.</p> + <p>Build version {{html .Version}}. Except as noted, this content is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License</a>.</p> </div> </div> </body> diff --git a/lib/godoc/package.html b/lib/godoc/package.html index cb3ffa2a7..7a89d780c 100644 --- a/lib/godoc/package.html +++ b/lib/godoc/package.html @@ -3,119 +3,120 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> - -{.section PAst} - <pre>{@ FSet|html-esc}</pre> -{.end} -{.section PDoc} +{{with .PAst}} + <pre>{{node_html . $.FSet}}</pre> +{{end}} +{{with .PDoc}} <!-- PackageName is printed as title by the top-level template --> - {.section IsPkg} - {# ImportPath is a string - no need for FSet} - <p><code>import "{ImportPath|html-esc}"</code></p> - {.end} - {Doc|html-comment} - {.section IsPkg} - {.section Filenames} - {# Filenames are strings - no need for FSet} + {{if $.IsPkg}} + <p><code>import "{{html .ImportPath}}"</code></p> + {{end}} + {{comment_html .Doc}} + {{if $.IsPkg}} + {{with .Filenames}} <p> <h4>Package files</h4> <span style="font-size:90%"> - {.repeated section @} - <a href="/{@|url-src}">{@|localname}</a> - {.end} + {{range .}} + <a href="/{{.|srcLink}}">{{.|filename|html}}</a> + {{end}} </span> </p> - {.end} - {.end} - {.section Consts} + {{end}} + {{end}} + {{with .Consts}} <h2 id="Constants">Constants</h2> - {.repeated section @} - {Doc|html-comment} - <pre>{Decl FSet|html-esc}</pre> - {.end} - {.end} - {.section Vars} + {{range .}} + {{comment_html .Doc}} + <pre>{{node_html .Decl $.FSet}}</pre> + {{end}} + {{end}} + {{with .Vars}} <h2 id="Variables">Variables</h2> - {.repeated section @} - {Doc|html-comment} - <pre>{Decl FSet|html-esc}</pre> - {.end} - {.end} - {.section Funcs} - {.repeated section @} - {# Name is a string - no need for FSet} - <h2 id="{Name|html-esc}">func <a href="/{Decl FSet|url-pos}">{Name|html-esc}</a></h2> - <p><code>{Decl FSet|html-esc}</code></p> - {Doc|html-comment} - {.end} - {.end} - {.section Types} - {.repeated section @} - <h2 id="{Type.Name FSet|html-esc}">type <a href="/{Decl FSet|url-pos}">{Type.Name FSet|html-esc}</a></h2> - {Doc|html-comment} - <p><pre>{Decl FSet|html-esc}</pre></p> - {.repeated section Consts} - {Doc|html-comment} - <pre>{Decl FSet|html-esc}</pre> - {.end} - {.repeated section Vars} - {Doc|html-comment} - <pre>{Decl FSet|html-esc}</pre> - {.end} - {.repeated section Factories} - <h3 id="{Type.Name FSet|html-esc}.{Name|html-esc}">func <a href="/{Decl FSet|url-pos}">{Name|html-esc}</a></h3> - <p><code>{Decl FSet|html-esc}</code></p> - {Doc|html-comment} - {.end} - {.repeated section Methods} - <h3 id="{Type.Name FSet|html-esc}.{Name|html-esc}">func ({Recv FSet|html-esc}) <a href="/{Decl FSet|url-pos}">{Name|html-esc}</a></h3> - <p><code>{Decl FSet|html-esc}</code></p> - {Doc|html-comment} - {.end} - {.end} - {.end} - {.section Bugs} + {{range .}} + {{comment_html .Doc}} + <pre>{{node_html .Decl $.FSet}}</pre> + {{end}} + {{end}} + {{with .Funcs}} + {{range .}} + {{/* Name is a string - no need for FSet */}} + {{$name_html := html .Name}} + <h2 id="{{$name_html}}">func <a href="/{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h2> + <p><code>{{node_html .Decl $.FSet}}</code></p> + {{comment_html .Doc}} + {{end}} + {{end}} + {{with .Types}} + {{range .}} + {{$tname_html := node_html .Type.Name $.FSet}} + <h2 id="{{$tname_html}}">type <a href="/{{posLink_url .Decl $.FSet}}">{{$tname_html}}</a></h2> + {{comment_html .Doc}} + <p><pre>{{node_html .Decl $.FSet}}</pre></p> + {{range .Consts}} + {{comment_html .Doc}} + <pre>{{node_html .Decl $.FSet}}</pre> + {{end}} + {{range .Vars}} + {{comment_html .Doc}} + <pre>{{node_html .Decl $.FSet}}</pre> + {{end}} + {{range .Factories}} + {{$name_html := html .Name}} + <h3 id="{{$tname_html}}.{{$name_html}}">func <a href="/{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h3> + <p><code>{{node_html .Decl $.FSet}}</code></p> + {{comment_html .Doc}} + {{end}} + {{range .Methods}} + {{$name_html := html .Name}} + <h3 id="{{$tname_html}}.{{$name_html}}">func ({{node_html .Recv $.FSet}}) <a href="/{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h3> + <p><code>{{node_html .Decl $.FSet}}</code></p> + {{comment_html .Doc}} + {{end}} + {{end}} + {{end}} + {{with .Bugs}} <h2 id="Bugs">Bugs</h2> - {.repeated section @} - {@|html-comment} - {.end} - {.end} -{.end} -{.section PList} + {{range .}} + {{comment_html .}} + {{end}} + {{end}} +{{end}} +{{with .PList}} <h2>Other packages</h2> <p> - {# PLIst entries are strings - no need for FSet} - {.repeated section @} - <a href="?p={@|html-esc}">{@|html-esc}</a><br /> - {.end} + {{/* PList entries are strings - no need for FSet */}} + {{range .}} + <a href="?p={{urlquery .}}">{{html .}}</a><br /> + {{end}} </p> -{.end} -{.section Dirs} +{{end}} +{{with .Dirs}} <p class="detail"> Need more packages? The <a href="http://godashboard.appspot.com/package">Package Dashboard</a> provides a list of <a href="/cmd/goinstall/">goinstallable</a> packages. </p> - {# DirList entries are numbers and strings - no need for FSet} + {{/* DirList entries are numbers and strings - no need for FSet */}} <h2 id="Subdirectories">Subdirectories</h2> <p> <table class="layout"> <tr> - <th align="left" colspan="{MaxHeight|html-esc}">Name</th> + <th align="left" colspan="{{html .MaxHeight}}">Name</th> <td width="25"> </td> <th align="left">Synopsis</th> </tr> <tr> <th align="left"><a href="..">..</a></th> </tr> - {.repeated section List} + {{range .List}} <tr> - {Depth|padding} - <td align="left" colspan="{Height|html-esc}"><a href="{Path|html-esc}">{Name|html-esc}</a></td> + {{repeat `<td width="25"></td>` .Depth}} + <td align="left" colspan="{{html .Height}}"><a href="{{html .Path}}">{{html .Name}}</a></td> <td></td> - <td align="left">{Synopsis|html-esc}</td> + <td align="left">{{html .Synopsis}}</td> </tr> - {.end} + {{end}} </table> </p> -{.end} +{{end}} diff --git a/lib/godoc/package.txt b/lib/godoc/package.txt index 6fe992dbe..179b33493 100644 --- a/lib/godoc/package.txt +++ b/lib/godoc/package.txt @@ -1,95 +1,82 @@ -{.section PAst} -{@ FSet} -{.end} -{.section PDoc} -{.section IsPkg} -PACKAGE - -package {PackageName} -import "{ImportPath}" -{.or} -COMMAND DOCUMENTATION -{.end} -{.section Doc} - -{@ FSet} -{.end} -{.section Consts} +{{with .PAst}}{{node . $.FSet}}{{end}}{{/* +--------------------------------------- + +*/}}{{with .PDoc}}{{if $.IsPkg}}PACKAGE + +package {{.PackageName}} +import "{{.ImportPath}}" + +{{else}}COMMAND DOCUMENTATION + +{{end}}{{.Doc}}{{/* + +--------------------------------------- + +*/}}{{with .Consts}} CONSTANTS -{.repeated section @} -{Decl FSet} -{Doc} -{.end} -{.end} -{.section Vars} +{{range .}}{{node .Decl $.FSet}} +{{.Doc}}{{end}} +{{end}}{{/* +--------------------------------------- + +*/}}{{with .Vars}} VARIABLES -{.repeated section @} -{Decl FSet} -{Doc} -{.end} -{.end} -{.section Funcs} +{{range .}}{{node .Decl $.FSet}} +{{.Doc}}{{end}} +{{end}}{{/* + +--------------------------------------- +*/}}{{with .Funcs}} FUNCTIONS -{.repeated section @} -{Decl FSet} -{Doc} -{.end} -{.end} -{.section Types} +{{range .}}{{node .Decl $.FSet}} +{{.Doc}} +{{end}}{{end}}{{/* -TYPES +--------------------------------------- -{.repeated section @} -{Decl FSet} -{Doc} -{.repeated section Consts} -{Decl FSet} -{Doc} -{.end} -{.repeated section Vars} -{Decl FSet} -{Doc} -{.end} -{.repeated section Factories} -{Decl FSet} -{Doc} -{.end} -{.repeated section Methods} -{Decl FSet} -{Doc} -{.end} -{.end} -{.end} -{.section Bugs} +*/}}{{with .Types}} +TYPES +{{range .}}{{node .Decl $.FSet}} +{{.Doc}} +{{range .Consts}}{{node .Decl $.FSet}} +{{.Doc}} +{{end}}{{range .Vars}}{{node .Decl $.FSet}} +{{.Doc}} +{{end}}{{range .Factories}}{{node .Decl $.FSet}} +{{.Doc}} +{{end}}{{range .Methods}}{{node .Decl $.FSet}} +{{.Doc}} +{{end}}{{end}}{{end}}{{/* + +--------------------------------------- + +*/}}{{with .Bugs}} BUGS -{.repeated section @} -{@} -{.end} -{.end} -{.end} -{.section PList} +{{range .}}{{.}} +{{end}}{{end}}{{end}}{{/* + +--------------------------------------- +*/}}{{with .PList}} OTHER PACKAGES -{.repeated section @} -{@} -{.end} -{.end} -{.section Dirs} -{.section Dirs} +{{range .}} +{{.}}{{end}} +{{end}}{{/* + +--------------------------------------- +*/}}{{with .Dirs}} SUBDIRECTORIES -{.repeated section List} - {Name} -{.end} -{.end} -{.end} +{{range .List}} + {{.Name}}{{end}} +{{end}} diff --git a/lib/godoc/search.html b/lib/godoc/search.html index 58a933fef..36c34f54d 100644 --- a/lib/godoc/search.html +++ b/lib/godoc/search.html @@ -3,93 +3,96 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> - -{.section Alert} +{{$query_url := urlquery .Query}} +{{with .Alert}} <p> - <span class="alert" style="font-size:120%">{@}</span> + <span class="alert" style="font-size:120%">{{html .}}</span> </p> -{.end} -{.section Alt} +{{end}} +{{with .Alt}} <p> <span class="alert" style="font-size:120%">Did you mean: </span> - {.repeated section Alts} - <a href="search?q={@|html-esc}" style="font-size:120%">{@|html-esc}</a> - {.end} + {{range .Alts}} + <a href="search?q={{urlquery .}}" style="font-size:120%">{{html .}}</a> + {{end}} </p> -{.end} -{.section Hit} - {.section Decls} +{{end}} +{{with .Hit}} + {{with .Decls}} <h2 id="Global">Package-level declarations</h2> - {.repeated section @} - <h3 id="Global_{Pak.Path|url-pkg}">package <a href="/{Pak.Path|url-pkg}">{Pak.Name|html-esc}</a></h3> - {.repeated section Files} - {.repeated section Groups} - {.repeated section Infos} - <a href="/{File.Path|url-src}?h={Query|urlquery-esc}#L{@|infoLine}">{File.Path|url-src}:{@|infoLine}</a> - {@|infoSnippet} - {.end} - {.end} - {.end} - {.end} - {.end} - {.section Others} + {{range .}} + {{$pkg_html := pkgLink .Pak.Path | html}} + <h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3> + {{range .Files}} + {{$src_html := srcLink .File.Path | html}} + {{range .Groups}} + {{range .Infos}} + <a href="/{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{$src_html}}:{{infoLine .}}</a> + {{infoSnippet_html .}} + {{end}} + {{end}} + {{end}} + {{end}} + {{end}} + {{with .Others}} <h2 id="Local">Local declarations and uses</h2> - {.repeated section @} - <h3 id="Local_{Pak.Path|url-pkg}">package <a href="/{Pak.Path|url-pkg}">{Pak.Name|html-esc}</a></h3> - {.repeated section Files} - <a href="/{File.Path|url-src}?h={Query|urlquery-esc}">{File.Path|url-src}</a> + {{range .}} + {{$pkg_html := pkgLink .Pak.Path | html}} + <h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3> + {{range .Files}} + {{$src_html := srcLink .File.Path | html}} + <a href="/{{$src_html}}?h={{$query_url}}">{{$src_html}}</a> <table class="layout"> - {.repeated section Groups} + {{range .Groups}} <tr> <td width="25"></td> - <th align="left" valign="top">{Kind|infoKind}</th> + <th align="left" valign="top">{{infoKind_html .Kind}}</th> <td align="left" width="4"></td> <td> - {.repeated section Infos} - <a href="/{File.Path|url-src}?h={Query|urlquery-esc}#L{@|infoLine}">{@|infoLine}</a> - {.end} + {{range .Infos}} + <a href="/{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{infoLine .}}</a> + {{end}} </td> </tr> - {.end} + {{end}} </table> - {.end} - {.end} - {.end} -{.end} -{.section Textual} - {.section Complete} - <h2 id="Textual">{Found|html-esc} textual occurrences</h2> - {.or} - <h2 id="Textual">More than {Found|html-esc} textual occurrences</h2> + {{end}} + {{end}} + {{end}} +{{end}} +{{with .Textual}} + {{if $.Complete}} + <h2 id="Textual">{{html $.Found}} textual occurrences</h2> + {{else}} + <h2 id="Textual">More than {{html $.Found}} textual occurrences</h2> <p> - <span class="alert" style="font-size:120%">Not all files or lines containing "{Query|html-esc}" are shown.</span> + <span class="alert" style="font-size:120%">Not all files or lines containing "{{html $.Query}}" are shown.</span> </p> - {.end} + {{end}} <p> <table class="layout"> - {.repeated section @} + {{range .}} + {{$src_html := srcLink .Filename | html}} <tr> <td align="left" valign="top"> - <a href="/{Filename|url-src}?h={Query|urlquery-esc}">{Filename|url-src}</a>: + <a href="/{{$src_html}}?h={{$query_url}}">{{$src_html}}</a>: </td> <td align="left" width="4"></td> - <th align="left" valign="top">{Lines|numlines}</th> + <th align="left" valign="top">{{len .Lines}}</th> <td align="left" width="4"></td> <td align="left"> - {.repeated section Lines} - <a href="/{Filename|url-src}?h={Query|urlquery-esc}#L{@|html-esc}">{@|html-esc}</a> - {.end} - {.section Complete} - {.or} + {{range .Lines}} + <a href="/{{$src_html}}?h={{$query_url}}#L{{html .}}">{{html .}}</a> + {{end}} + {{if not $.Complete}} ... - {.end} + {{end}} </td> </tr> - {.end} - {.section Complete} - {.or} + {{end}} + {{if not $.Complete}} <tr><td align="left">...</td></tr> - {.end} + {{end}} </table> </p> -{.end} +{{end}} diff --git a/lib/godoc/search.txt b/lib/godoc/search.txt index 967c1ac01..1dd64afdb 100644 --- a/lib/godoc/search.txt +++ b/lib/godoc/search.txt @@ -1,61 +1,40 @@ QUERY - {Query} + {{.Query}} +{{with .Alert}} +{{.}} +{{end}}{{/* .Alert */}}{{/* -{.section Alert} -{@} +--------------------------------------- -{.end} -{.section Alt} +*/}}{{with .Alt}} DID YOU MEAN -{.repeated section Alts} - {@} -{.end} +{{range .Alts}} {{.}} +{{end}}{{end}}{{/* .Alts */}}{{/* -{.end} -{.section Hit} -{.section Decls} +--------------------------------------- + +*/}}{{with .Hit}}{{with .Decls}} PACKAGE-LEVEL DECLARATIONS -{.repeated section @} -package {Pak.Name} -{.repeated section Files} -{.repeated section Groups} -{.repeated section Infos} - {File.Path|url-src}:{@|infoLine} -{.end} -{.end} -{.end} - -{.end} -{.end} -{.section Others} +{{range .}}package {{.Pak.Name}} +{{range $file := .Files}}{{range .Groups}}{{range .Infos}} {{srcLink $file.File.Path}}:{{infoLine .}}{{end}} +{{end}}{{end}}{{/* .Files */}} +{{end}}{{end}}{{/* .Decls */}}{{/* + +--------------------------------------- + +*/}}{{with .Others}} LOCAL DECLARATIONS AND USES -{.repeated section @} -package {Pak.Name} -{.repeated section Files} -{.repeated section Groups} -{.repeated section Infos} - {File.Path|url-src}:{@|infoLine} -{.end} -{.end} -{.end} - -{.end} -{.end} -{.end} -{.section Textual} -{.section Complete} -{Found} TEXTUAL OCCURRENCES -{.or} -MORE THAN {Found} TEXTUAL OCCURRENCES -{.end} - -{.repeated section @} -{Lines|numlines} {Filename|url-src} -{.end} -{.section Complete} -{.or} -... ... -{.end} -{.end} +{{range .}}package {{.Pak.Name}} +{{range $file := .Files}}{{range .Groups}}{{range .Infos}} {{srcLink $file.File.Path}}:{{infoLine .}} +{{end}}{{end}}{{end}}{{/* .Files */}} +{{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/* + +--------------------------------------- + +*/}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}} + +{{range .Textual}}{{len .Lines}} {{srcLink .Filename}} +{{end}}{{if not .Complete}}... ... +{{end}}{{end}} diff --git a/misc/cgo/test/Makefile b/misc/cgo/test/Makefile index f26f97289..d4309be3c 100644 --- a/misc/cgo/test/Makefile +++ b/misc/cgo/test/Makefile @@ -15,6 +15,7 @@ CGOFILES=\ issue1222.go\ issue1328.go\ issue1560.go\ + duplicate_symbol.go\ CGO_OFILES=\ callback_c.o\ diff --git a/misc/cgo/test/duplicate_symbol.go b/misc/cgo/test/duplicate_symbol.go new file mode 100644 index 000000000..69600de9c --- /dev/null +++ b/misc/cgo/test/duplicate_symbol.go @@ -0,0 +1,21 @@ +// Copyright 2010 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. + +// This file contains test cases for cgo. + +package cgotest + +/* +int base_symbol = 0; + +#define alias_one base_symbol +#define alias_two base_symbol +*/ +import "C" + +import "fmt" + +func duplicateSymbols() { + fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two) +} diff --git a/misc/dashboard/builder/http.go b/misc/dashboard/builder/http.go index 98400c51a..abef8faa4 100644 --- a/misc/dashboard/builder/http.go +++ b/misc/dashboard/builder/http.go @@ -12,6 +12,7 @@ import ( "log" "os" "strconv" + "url" ) type param map[string]string @@ -26,7 +27,7 @@ func dash(meth, cmd string, resp interface{}, args param) os.Error { log.Println("dash", cmd, args) } cmd = "http://" + *dashboard + "/" + cmd - vals := make(http.Values) + vals := make(url.Values) for k, v := range args { vals.Add(k, v) } diff --git a/misc/goplay/goplay.go b/misc/goplay/goplay.go index f1dc1bca5..bbc388ba4 100644 --- a/misc/goplay/goplay.go +++ b/misc/goplay/goplay.go @@ -142,18 +142,10 @@ func run(cmd ...string) ([]byte, os.Error) { return exec.Command(cmd[0], cmd[1:]...).CombinedOutput() } -var frontPage, output *template.Template // HTML templates +var frontPage = template.Must(template.New("frontPage").Parse(frontPageText)) // HTML template +var output = template.Must(template.New("output").Parse(outputText)) // HTML template -func init() { - frontPage = template.New(nil) - frontPage.SetDelims("«", "»") - if err := frontPage.Parse(frontPageText); err != nil { - panic(err) - } - output = template.MustParse(outputText, nil) -} - -var outputText = `<pre>{@|html}</pre>` +var outputText = `<pre>{{html .}}</pre>` var frontPageText = `<!doctype html> <html> @@ -264,7 +256,7 @@ function compileUpdate() { </head> <body> <table width="100%"><tr><td width="60%" valign="top"> -<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">«@|html»</textarea> +<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">{{html .}}</textarea> <div class="hints"> (Shift-Enter to compile and run.) <input type="checkbox" id="autocompile" value="checked" /> Compile and run after each keystroke diff --git a/misc/vim/autoload/go/complete.vim b/misc/vim/autoload/go/complete.vim new file mode 100644 index 000000000..d4ae3b97f --- /dev/null +++ b/misc/vim/autoload/go/complete.vim @@ -0,0 +1,49 @@ +" Copyright 2011 The Go Authors. All rights reserved. +" Use of this source code is governed by a BSD-style +" license that can be found in the LICENSE file. +" +" This file provides a utility function that performs auto-completion of +" package names, for use by other commands. + +let s:goos = $GOOS +let s:goarch = $GOARCH + +if len(s:goos) == 0 + if exists('g:golang_goos') + let s:goos = g:golang_goos + elseif has('win32') || has('win64') + let s:goos = 'windows' + elseif has('macunix') + let s:goos = 'darwin' + else + let s:goos = '*' + endif +endif + +if len(s:goarch) == 0 + if exists('g:golang_goarch') + let s:goarch = g:golang_goarch + else + let s:goarch = '*' + endif +endif + +function! go#complete#Package(ArgLead, CmdLine, CursorPos) + let goroot = $GOROOT + if len(goroot) == 0 + " should not occur. + return [] + endif + let ret = {} + let root = expand(goroot.'/pkg/'.s:goos.'_'.s:goarch) + for i in split(globpath(root, a:ArgLead.'*'), "\n") + if isdirectory(i) + let i .= '/' + elseif i !~ '\.a$' + continue + endif + let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g') + let ret[i] = i + endfor + return sort(keys(ret)) +endfunction diff --git a/misc/vim/ftplugin/go/import.vim b/misc/vim/ftplugin/go/import.vim index b5814ca5d..6705a476b 100644 --- a/misc/vim/ftplugin/go/import.vim +++ b/misc/vim/ftplugin/go/import.vim @@ -36,9 +36,9 @@ if exists("b:did_ftplugin") finish endif -command! -buffer -nargs=? Drop call s:SwitchImport(0, '', <f-args>) -command! -buffer -nargs=1 Import call s:SwitchImport(1, '', <f-args>) -command! -buffer -nargs=* ImportAs call s:SwitchImport(1, <f-args>) +command! -buffer -nargs=? -complete=customlist,go#complete#Package Drop call s:SwitchImport(0, '', <f-args>) +command! -buffer -nargs=1 -complete=customlist,go#complete#Package Import call s:SwitchImport(1, '', <f-args>) +command! -buffer -nargs=* -complete=customlist,go#complete#Package ImportAs call s:SwitchImport(1, <f-args>) map <buffer> <LocalLeader>f :Import fmt<CR> map <buffer> <LocalLeader>F :Drop fmt<CR> diff --git a/misc/vim/plugin/godoc.vim b/misc/vim/plugin/godoc.vim index 5d7ce14ad..fdb496631 100644 --- a/misc/vim/plugin/godoc.vim +++ b/misc/vim/plugin/godoc.vim @@ -11,8 +11,6 @@ let g:loaded_godoc = 1 let s:buf_nr = -1 let s:last_word = '' -let s:goos = $GOOS -let s:goarch = $GOARCH function! s:GodocView() if !bufexists(s:buf_nr) @@ -81,43 +79,7 @@ function! s:Godoc(...) call s:GodocWord(word) endfunction -function! s:GodocComplete(ArgLead, CmdLine, CursorPos) - if len($GOROOT) == 0 - return [] - endif - if len(s:goos) == 0 - if exists('g:godoc_goos') - let s:goos = g:godoc_goos - elseif has('win32') || has('win64') - let s:goos = 'windows' - elseif has('macunix') - let s:goos = 'darwin' - else - let s:goos = '*' - endif - endif - if len(s:goarch) == 0 - if exists('g:godoc_goarch') - let s:goarch = g:godoc_goarch - else - let s:goarch = g:godoc_goarch - endif - endif - let ret = {} - let root = expand($GOROOT.'/pkg/'.s:goos.'_'.s:goarch) - for i in split(globpath(root, a:ArgLead.'*'), "\n") - if isdirectory(i) - let i .= '/' - elseif i !~ '\.a$' - continue - endif - let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g') - let ret[i] = i - endfor - return sort(keys(ret)) -endfunction - -command! -nargs=* -range -complete=customlist,s:GodocComplete Godoc :call s:Godoc(<q-args>) +command! -nargs=* -range -complete=customlist,go#complete#Package Godoc :call s:Godoc(<q-args>) nnoremap <silent> <Plug>(godoc-keyword) :<C-u>call <SID>Godoc('')<CR> " vim:ts=4:sw=4:et diff --git a/misc/vim/readme.txt b/misc/vim/readme.txt index e6bdf0e11..fe15da993 100644 --- a/misc/vim/readme.txt +++ b/misc/vim/readme.txt @@ -1,5 +1,17 @@ -Vim syntax highlighting for Go (http://golang.org) -================================================== +Vim plugins for Go (http://golang.org) +====================================== + +To use all the Vim plugins, add these lines to your vimrc. + + set rtp+=$GOROOT/misc/vim + filetype plugin indent on + syntax on + +If you want to select fewer plugins, use the instructions in the rest of +this file. + +Vim syntax highlighting +----------------------- To install automatic syntax highlighting for GO programs: @@ -18,15 +30,17 @@ commands: mkdir -p $HOME/.vim/ftdetect mkdir -p $HOME/.vim/syntax + mkdir -p $HOME/.vim/autoload/go ln -s $GOROOT/misc/vim/ftdetect/gofiletype.vim $HOME/.vim/ftdetect/ ln -s $GOROOT/misc/vim/syntax/go.vim $HOME/.vim/syntax + ln -s $GOROOT/misc/vim/autoload/go/complete.vim $HOME/.vim/autoload/go echo "syntax on" >> $HOME/.vimrc -Vim filetype plugins for Go -=========================== +Vim filetype plugins +-------------------- -To install one of the available filetype plugins for Go: +To install one of the available filetype plugins: 1. Same as 1 above. 2. Copy or link one or more plugins from ftplugin/go/*.vim to the @@ -37,10 +51,10 @@ To install one of the available filetype plugins for Go: filetype plugin on -Vim indentation plugin for Go -============================= +Vim indentation plugin +---------------------- -To install automatic indentation for Go: +To install automatic indentation: 1. Same as 1 above. 2. Copy or link indent/go.vim to the indent directory underneath your vim @@ -51,11 +65,12 @@ To install automatic indentation for Go: Godoc plugin -============ +------------ To install godoc plugin: 1. Same as 1 above. 2. Copy or link plugin/godoc.vim to $HOME/.vim/plugin/godoc, syntax/godoc.vim to $HOME/.vim/syntax/godoc.vim, - and ftplugin/go/godoc.vim to $HOME/.vim/ftplugin/go/godoc.vim. + ftplugin/go/godoc.vim to $HOME/.vim/ftplugin/go/godoc.vim. + and autoload/go/complete.vim to $HOME/.vim/autoload/go/complete.vim. diff --git a/src/Make.inc b/src/Make.inc index a6edb165a..8f549f624 100644 --- a/src/Make.inc +++ b/src/Make.inc @@ -121,6 +121,21 @@ HOST_CFLAGS=-I"$(GOROOT)/include" $(HOST_EXTRA_CFLAGS) HOST_LDFLAGS=$(HOST_EXTRA_LDFLAGS) PWD=$(shell pwd) +# Decide whether use of cgo is okay. +ifeq ($(CGO_ENABLED),) +# Default on... +CGO_ENABLED:=1 +ifeq ($(GOARCH),arm) # ... but not on ARM +CGO_ENABLED:=0 +endif +ifeq ($(GOOS),plan9) # ... and not on Plan 9 +CGO_ENABLED:=0 +endif +ifeq ($(GOOS),openbsd) # ... and not on OpenBSD +CGO_ENABLED:=0 +endif +endif + # Make environment more standard. LANG:= LC_ALL:=C @@ -130,11 +145,12 @@ GREP_COLORS:= export LANG LC_ALL LC_CTYPE GREP_OPTIONS GREP_COLORS go-env: - @echo export GOARCH=$(GOARCH) - @echo export GOOS=$(GOOS) - @echo export GOHOSTARCH=$(GOHOSTARCH) - @echo export GOHOSTOS=$(GOHOSTOS) - @echo export O=$O + @echo export GOARCH="$(GOARCH)" + @echo export GOOS="$(GOOS)" + @echo export GOHOSTARCH="$(GOHOSTARCH)" + @echo export GOHOSTOS="$(GOHOSTOS)" + @echo export CGO_ENABLED="$(CGO_ENABLED)" + @echo export O="$O" @echo export AS="$(AS)" @echo export CC="$(CC)" @echo export GC="$(GC)" diff --git a/src/cmd/5c/reg.c b/src/cmd/5c/reg.c index 50b814598..1ccf74a35 100644 --- a/src/cmd/5c/reg.c +++ b/src/cmd/5c/reg.c @@ -66,6 +66,7 @@ rcmp(const void *a1, const void *a2) void regopt(Prog *p) { + USED(p); // TODO(kaib): optimizer disabled because it smashes R8 when running out of registers // the disable is unconventionally here because the call is in common code shared by 5c/6c/8c return; diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index e00f536a7..dabe93d37 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -324,6 +324,7 @@ EXTERN Prog* prog_modu; #pragma varargck type "N" Adr* #pragma varargck type "P" Prog* #pragma varargck type "S" char* +#pragma varargck type "Z" char* #pragma varargck type "i" char* int Aconv(Fmt*); diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c index 7aa4aa976..7f717dcbb 100644 --- a/src/cmd/6c/cgen.c +++ b/src/cmd/6c/cgen.c @@ -930,9 +930,6 @@ cgen(Node *n, Node *nn) return; } - o = 0; - if(REGARG >= 0) - o = reg[REGARG]; gargs(r, &nod, &nod1); if(l->addable < INDEXED) { reglcgen(&nod, l, nn); @@ -941,9 +938,8 @@ cgen(Node *n, Node *nn) regfree(&nod); } else gopcode(OFUNC, n->type, Z, l); - if(REGARG >= 0) - if(o != reg[REGARG]) - reg[REGARG]--; + if(REGARG >= 0 && reg[REGARG]) + reg[REGARG]--; if(nn != Z) { regret(&nod, n); gmove(&nod, nn); diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index f59a59efb..3a8223e65 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -298,6 +298,9 @@ adddynrel(Sym *s, Reloc *r) int archreloc(Reloc *r, Sym *s, vlong *val) { + USED(r); + USED(s); + USED(val); return -1; } @@ -859,7 +862,7 @@ asmb(void) startva = INITTEXT - HEADR; /* This null SHdr must appear before all others */ - sh = newElfShdr(elfstr[ElfStrEmpty]); + newElfShdr(elfstr[ElfStrEmpty]); /* program header info */ pph = newElfPhdr(); diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index 043568585..b291d5f3d 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -410,6 +410,7 @@ uint32 machheadr(void); #pragma varargck type "D" Adr* #pragma varargck type "P" Prog* #pragma varargck type "R" int +#pragma varargck type "Z" char* #pragma varargck type "A" int #pragma varargck argpos diag 1 diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index 94cbfc26a..4ee0db967 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -46,10 +46,6 @@ enum #define P ((Prog*)0) #define S ((Sym*)0) #define TNAME (cursym?cursym->name:noname) -#define cput(c)\ - { *cbp++ = c;\ - if(--cbc <= 0)\ - cflush(); } typedef struct Adr Adr; typedef struct Prog Prog; @@ -254,6 +250,7 @@ enum #pragma varargck type "R" int #pragma varargck type "S" char* #pragma varargck type "Y" Sym* +#pragma varargck type "Z" char* #pragma varargck type "i" char* EXTERN int32 HEADR; diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 9c962b8ff..498ab1566 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -59,17 +59,21 @@ func (p *Package) writeDefs() { fmt.Fprintf(fc, cProlog) - var cVars []string + cVars := make(map[string]bool) for _, n := range p.Name { if n.Kind != "var" { continue } - cVars = append(cVars, n.C) - fmt.Fprintf(fm, "extern char %s[];\n", n.C) - fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) + if !cVars[n.C] { + fmt.Fprintf(fm, "extern char %s[];\n", n.C) + fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) + + fmt.Fprintf(fc, "extern byte *%s;\n", n.C) + + cVars[n.C] = true + } - fmt.Fprintf(fc, "extern byte *%s;\n", n.C) fmt.Fprintf(fc, "void *·%s = &%s;\n", n.Mangle, n.C) fmt.Fprintf(fc, "\n") diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile index 286618ec1..0af7659e4 100644 --- a/src/cmd/gc/Makefile +++ b/src/cmd/gc/Makefile @@ -65,3 +65,7 @@ opnames.h: mkopnames go.h ./mkopnames go.h >opnames.h CLEANFILES+=*.[568] [568].out y1.tab.c yerr.h mkbuiltin1 builtin.c _builtin.c opnames.h + +mkbuiltin1: mkbuiltin1.$O + $(HOST_LD) -o $@ mkbuiltin1.$O -L"$(GOROOT)"/lib -lbio -l9 -lm $(HOST_LDFLAGS) + diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index 6419873a2..190c56008 100644 --- a/src/cmd/gc/builtin.c.boot +++ b/src/cmd/gc/builtin.c.boot @@ -57,24 +57,23 @@ char *runtimeimport = "func \"\".efaceeq (i1 any, i2 any) bool\n" "func \"\".ifacethash (i1 any) uint32\n" "func \"\".efacethash (i1 any) uint32\n" - "func \"\".makemap (key *uint8, val *uint8, hint int64) map[any] any\n" - "func \"\".mapaccess1 (hmap map[any] any, key any) any\n" - "func \"\".mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n" - "func \"\".mapassign1 (hmap map[any] any, key any, val any)\n" - "func \"\".mapassign2 (hmap map[any] any, key any, val any, pres bool)\n" - "func \"\".mapiterinit (hmap map[any] any, hiter *any)\n" + "func \"\".makemap (mapType *uint8, hint int64) map[any] any\n" + "func \"\".mapaccess1 (mapType *uint8, hmap map[any] any, key any) any\n" + "func \"\".mapaccess2 (mapType *uint8, hmap map[any] any, key any) (val any, pres bool)\n" + "func \"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n" + "func \"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n" + "func \"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n" "func \"\".mapiternext (hiter *any)\n" "func \"\".mapiter1 (hiter *any) any\n" "func \"\".mapiter2 (hiter *any) (key any, val any)\n" - "func \"\".makechan (elem *uint8, hint int64) chan any\n" - "func \"\".chanrecv1 (hchan <-chan any) any\n" - "func \"\".chanrecv2 (hchan <-chan any) (elem any, received bool)\n" - "func \"\".chansend1 (hchan chan<- any, elem any)\n" + "func \"\".makechan (chanType *uint8, hint int64) chan any\n" + "func \"\".chanrecv1 (chanType *uint8, hchan <-chan any) any\n" + "func \"\".chanrecv2 (chanType *uint8, hchan <-chan any) (elem any, received bool)\n" + "func \"\".chansend1 (chanType *uint8, hchan chan<- any, elem any)\n" "func \"\".closechan (hchan any)\n" - "func \"\".closedchan (hchan any) bool\n" - "func \"\".selectnbsend (hchan chan<- any, elem any) bool\n" - "func \"\".selectnbrecv (elem *any, hchan <-chan any) bool\n" - "func \"\".selectnbrecv2 (elem *any, received *bool, hchan <-chan any) bool\n" + "func \"\".selectnbsend (chanType *uint8, hchan chan<- any, elem any) bool\n" + "func \"\".selectnbrecv (chanType *uint8, elem *any, hchan <-chan any) bool\n" + "func \"\".selectnbrecv2 (chanType *uint8, elem *any, received *bool, hchan <-chan any) bool\n" "func \"\".newselect (size int) *uint8\n" "func \"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n" "func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n" diff --git a/src/cmd/gc/mkbuiltin b/src/cmd/gc/mkbuiltin index 4dfff1caa..cfd6e59c1 100755 --- a/src/cmd/gc/mkbuiltin +++ b/src/cmd/gc/mkbuiltin @@ -16,7 +16,7 @@ if [ -z "$GC" ]; then exit 1 fi -gcc -o mkbuiltin1 mkbuiltin1.c +gomake mkbuiltin1 rm -f _builtin.c for i in runtime unsafe do diff --git a/src/cmd/gc/mkbuiltin1.c b/src/cmd/gc/mkbuiltin1.c index baa87fec9..ad83c0346 100644 --- a/src/cmd/gc/mkbuiltin1.c +++ b/src/cmd/gc/mkbuiltin1.c @@ -10,7 +10,7 @@ void esc(char*); -int +void main(int argc, char **argv) { char *name; @@ -64,13 +64,13 @@ begin: } esc(p); - printf("\\n\"\n", p); + printf("\\n\"\n"); } sysfatal("did not find end of imports\n"); end: printf("\t\"$$\\n\";\n"); - return 0; + exits(0); } void diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c index fb33e4e48..5ce693ae3 100644 --- a/src/cmd/gc/range.c +++ b/src/cmd/gc/range.c @@ -175,7 +175,7 @@ walkrange(Node *n) argtype(fn, t->down); argtype(fn, t->type); argtype(fn, th); - init = list(init, mkcall1(fn, T, nil, ha, nod(OADDR, hit, N))); + init = list(init, mkcall1(fn, T, nil, typename(t), ha, nod(OADDR, hit, N))); n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil()); fn = syslook("mapiternext", 1); diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index 7254f874e..549f7abe3 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -80,27 +80,26 @@ func ifacethash(i1 any) (ret uint32) func efacethash(i1 any) (ret uint32) // *byte is really *runtime.Type -func makemap(key, val *byte, hint int64) (hmap map[any]any) -func mapaccess1(hmap map[any]any, key any) (val any) -func mapaccess2(hmap map[any]any, key any) (val any, pres bool) -func mapassign1(hmap map[any]any, key any, val any) -func mapassign2(hmap map[any]any, key any, val any, pres bool) -func mapiterinit(hmap map[any]any, hiter *any) +func makemap(mapType *byte, hint int64) (hmap map[any]any) +func mapaccess1(mapType *byte, hmap map[any]any, key any) (val any) +func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool) +func mapassign1(mapType *byte, hmap map[any]any, key any, val any) +func mapassign2(mapType *byte, hmap map[any]any, key any, val any, pres bool) +func mapiterinit(mapType *byte, hmap map[any]any, hiter *any) func mapiternext(hiter *any) func mapiter1(hiter *any) (key any) func mapiter2(hiter *any) (key any, val any) // *byte is really *runtime.Type -func makechan(elem *byte, hint int64) (hchan chan any) -func chanrecv1(hchan <-chan any) (elem any) -func chanrecv2(hchan <-chan any) (elem any, received bool) -func chansend1(hchan chan<- any, elem any) +func makechan(chanType *byte, hint int64) (hchan chan any) +func chanrecv1(chanType *byte, hchan <-chan any) (elem any) +func chanrecv2(chanType *byte, hchan <-chan any) (elem any, received bool) +func chansend1(chanType *byte, hchan chan<- any, elem any) func closechan(hchan any) -func closedchan(hchan any) bool -func selectnbsend(hchan chan<- any, elem any) bool -func selectnbrecv(elem *any, hchan <-chan any) bool -func selectnbrecv2(elem *any, received *bool, hchan <-chan any) bool +func selectnbsend(chanType *byte, hchan chan<- any, elem any) bool +func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool +func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool func newselect(size int) (sel *byte) func selectsend(sel *byte, hchan chan<- any, elem *any) (selected bool) diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c index 8395dda31..909ad3aa4 100644 --- a/src/cmd/gc/select.c +++ b/src/cmd/gc/select.c @@ -250,9 +250,8 @@ walkselect(Node *sel) case OSEND: // if c != nil && selectnbsend(c, v) { body } else { default body } ch = cheapexpr(n->left, &r->ninit); - r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()), - mkcall1(chanfn("selectnbsend", 2, ch->type), - types[TBOOL], &r->ninit, ch, n->right)); + r->ntest = mkcall1(chanfn("selectnbsend", 2, ch->type), + types[TBOOL], &r->ninit, typename(ch->type), ch, n->right); break; case OSELRECV: @@ -260,9 +259,8 @@ walkselect(Node *sel) r = nod(OIF, N, N); r->ninit = cas->ninit; ch = cheapexpr(n->right->left, &r->ninit); - r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()), - mkcall1(chanfn("selectnbrecv", 2, ch->type), - types[TBOOL], &r->ninit, n->left, ch)); + r->ntest = mkcall1(chanfn("selectnbrecv", 2, ch->type), + types[TBOOL], &r->ninit, typename(ch->type), n->left, ch); break; case OSELRECV2: @@ -270,9 +268,8 @@ walkselect(Node *sel) r = nod(OIF, N, N); r->ninit = cas->ninit; ch = cheapexpr(n->right->left, &r->ninit); - r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()), - mkcall1(chanfn("selectnbrecv2", 2, ch->type), - types[TBOOL], &r->ninit, n->left, n->ntest, ch)); + r->ntest = mkcall1(chanfn("selectnbrecv2", 2, ch->type), + types[TBOOL], &r->ninit, typename(ch->type), n->left, n->ntest, ch); break; } typecheck(&r->ntest, Erv); diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 0383e5a6a..9cd4ee919 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -591,7 +591,7 @@ walkexpr(Node **np, NodeList **init) walkexprlistsafe(n->list, init); walkexpr(&r->left, init); fn = chanfn("chanrecv2", 2, r->left->type); - r = mkcall1(fn, getoutargx(fn->type), init, r->left); + r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left); n->rlist->n = r; n->op = OAS2FUNC; goto as2func; @@ -604,7 +604,7 @@ walkexpr(Node **np, NodeList **init) walkexprlistsafe(n->list, init); walkexpr(&r->left, init); fn = mapfn("mapaccess2", r->left->type); - r = mkcall1(fn, getoutargx(fn->type), init, r->left, r->right); + r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right); n->rlist = list1(r); n->op = OAS2FUNC; goto as2func; @@ -617,7 +617,7 @@ walkexpr(Node **np, NodeList **init) walkexprlistsafe(n->list, init); l = n->list->n; t = l->left->type; - n = mkcall1(mapfn("mapassign2", t), T, init, l->left, l->right, n->rlist->n, n->rlist->next->n); + n = mkcall1(mapfn("mapassign2", t), T, init, typename(t), l->left, l->right, n->rlist->n, n->rlist->next->n); goto ret; case OAS2DOTTYPE: @@ -852,13 +852,13 @@ walkexpr(Node **np, NodeList **init) goto ret; t = n->left->type; - n = mkcall1(mapfn("mapaccess1", t), t->type, init, n->left, n->right); + n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right); goto ret; case ORECV: walkexpr(&n->left, init); walkexpr(&n->right, init); - n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, n->left); + n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, typename(n->left->type), n->left); goto ret; case OSLICE: @@ -1078,7 +1078,7 @@ walkexpr(Node **np, NodeList **init) case OMAKECHAN: n = mkcall1(chanfn("makechan", 1, n->type), n->type, init, - typename(n->type->type), + typename(n->type), conv(n->left, types[TINT64])); goto ret; @@ -1090,8 +1090,7 @@ walkexpr(Node **np, NodeList **init) argtype(fn, t->type); // any-2 n = mkcall1(fn, n->type, init, - typename(t->down), // key type - typename(t->type), // value type + typename(n->type), conv(n->left, types[TINT64])); goto ret; @@ -1164,7 +1163,7 @@ walkexpr(Node **np, NodeList **init) goto ret; case OSEND: - n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, n->left, n->right); + n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n->right); goto ret; case OCLOSURE: @@ -1697,6 +1696,7 @@ convas(Node *n, NodeList **init) if(n->left->op == OINDEXMAP) { n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init, + typename(n->left->left->type), n->left->left, n->left->right, n->right); goto out; } diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 03ac1b98b..b8a839404 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -371,143 +371,24 @@ func writeNode(w io.Writer, fset *token.FileSet, x interface{}) { (&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x) } -// Write anything to w. -func writeAny(w io.Writer, fset *token.FileSet, x interface{}) { - switch v := x.(type) { - case []byte: - w.Write(v) - case string: - w.Write([]byte(v)) - case ast.Decl, ast.Expr, ast.Stmt, *ast.File: - writeNode(w, fset, x) - default: - fmt.Fprint(w, x) - } -} - -// Write anything html-escaped to w. -func writeAnyHTML(w io.Writer, fset *token.FileSet, x interface{}) { - switch v := x.(type) { - case []byte: - template.HTMLEscape(w, v) - case string: - template.HTMLEscape(w, []byte(v)) - case ast.Decl, ast.Expr, ast.Stmt, *ast.File: - var buf bytes.Buffer - writeNode(&buf, fset, x) - FormatText(w, buf.Bytes(), -1, true, "", nil) - default: - var buf bytes.Buffer - fmt.Fprint(&buf, x) - template.HTMLEscape(w, buf.Bytes()) - } +func filenameFunc(path string) string { + _, localname := filepath.Split(path) + return localname } -func fileset(x []interface{}) *token.FileSet { - if len(x) > 1 { - if fset, ok := x[1].(*token.FileSet); ok { - return fset - } +func fileInfoNameFunc(fi FileInfo) string { + name := fi.Name() + if fi.IsDirectory() { + name += "/" } - return nil -} - -// Template formatter for "html-esc" format. -func htmlEscFmt(w io.Writer, format string, x ...interface{}) { - writeAnyHTML(w, fileset(x), x[0]) -} - -// Template formatter for "html-comment" format. -func htmlCommentFmt(w io.Writer, format string, x ...interface{}) { - var buf bytes.Buffer - writeAny(&buf, fileset(x), x[0]) - // TODO(gri) Provide list of words (e.g. function parameters) - // to be emphasized by ToHTML. - doc.ToHTML(w, buf.Bytes(), nil) // does html-escaping -} - -// Template formatter for "" (default) format. -func textFmt(w io.Writer, format string, x ...interface{}) { - writeAny(w, fileset(x), x[0]) + return name } -// Template formatter for "urlquery-esc" format. -func urlQueryEscFmt(w io.Writer, format string, x ...interface{}) { - var buf bytes.Buffer - writeAny(&buf, fileset(x), x[0]) - template.HTMLEscape(w, []byte(http.URLEscape(string(buf.Bytes())))) -} - -// Template formatter for the various "url-xxx" formats excluding url-esc. -func urlFmt(w io.Writer, format string, x ...interface{}) { - var path string - var line int - var low, high int // selection - - // determine path and position info, if any - type positioner interface { - Pos() token.Pos - End() token.Pos - } - switch t := x[0].(type) { - case string: - path = t - case positioner: - fset := fileset(x) - if p := t.Pos(); p.IsValid() { - pos := fset.Position(p) - path = pos.Filename - line = pos.Line - low = pos.Offset - } - if p := t.End(); p.IsValid() { - high = fset.Position(p).Offset - } - default: - // we should never reach here, but be resilient - // and assume the position is invalid (empty path, - // and line 0) - log.Printf("INTERNAL ERROR: urlFmt(%s) without a string or positioner", format) - } - - // map path - relpath := relativeURL(path) - - // convert to relative URLs so that they can also - // be used as relative file names in .txt templates - switch format { - default: - // we should never reach here, but be resilient - // and assume the url-pkg format instead - log.Printf("INTERNAL ERROR: urlFmt(%s)", format) - fallthrough - case "url-pkg": - // because of the irregular mapping under goroot - // we need to correct certain relative paths - if strings.HasPrefix(relpath, "src/pkg/") { - relpath = relpath[len("src/pkg/"):] - } - template.HTMLEscape(w, []byte(pkgHandler.pattern[1:]+relpath)) // remove trailing '/' for relative URL - case "url-src": - template.HTMLEscape(w, []byte(relpath)) - case "url-pos": - template.HTMLEscape(w, []byte(relpath)) - // selection ranges are of form "s=low:high" - if low < high { - fmt.Fprintf(w, "?s=%d:%d", low, high) - // if we have a selection, position the page - // such that the selection is a bit below the top - line -= 10 - if line < 1 { - line = 1 - } - } - // line id's in html-printed source are of the - // form "L%d" where %d stands for the line number - if line > 0 { - fmt.Fprintf(w, "#L%d", line) - } +func fileInfoTimeFunc(fi FileInfo) string { + if t := fi.Mtime_ns(); t != 0 { + return time.SecondsToLocalTime(t / 1e9).String() } + return "" // don't return epoch if time is obviously not set } // The strings in infoKinds must be properly html-escaped. @@ -522,14 +403,11 @@ var infoKinds = [nKinds]string{ Use: "use", } -// Template formatter for "infoKind" format. -func infoKindFmt(w io.Writer, format string, x ...interface{}) { - fmt.Fprintf(w, infoKinds[x[0].(SpotKind)]) // infoKind entries are html-escaped +func infoKind_htmlFunc(kind SpotKind) string { + return infoKinds[kind] // infoKind entries are html-escaped } -// Template formatter for "infoLine" format. -func infoLineFmt(w io.Writer, format string, x ...interface{}) { - info := x[0].(SpotInfo) +func infoLineFunc(info SpotInfo) int { line := info.Lori() if info.IsIndex() { index, _ := searchIndex.get() @@ -543,80 +421,113 @@ func infoLineFmt(w io.Writer, format string, x ...interface{}) { line = 0 } } - fmt.Fprintf(w, "%d", line) + return line } -// Template formatter for "infoSnippet" format. -func infoSnippetFmt(w io.Writer, format string, x ...interface{}) { - info := x[0].(SpotInfo) - text := []byte(`<span class="alert">no snippet text available</span>`) +func infoSnippet_htmlFunc(info SpotInfo) string { if info.IsIndex() { index, _ := searchIndex.get() - // no escaping of snippet text needed; - // snippet text is escaped when generated - text = index.(*Index).Snippet(info.Lori()).Text + // Snippet.Text was HTML-escaped when it was generated + return index.(*Index).Snippet(info.Lori()).Text } - w.Write(text) + return `<span class="alert">no snippet text available</span>` } -// Template formatter for "padding" format. -func paddingFmt(w io.Writer, format string, x ...interface{}) { - for i := x[0].(int); i > 0; i-- { - fmt.Fprint(w, `<td width="25"></td>`) - } +func nodeFunc(node interface{}, fset *token.FileSet) string { + var buf bytes.Buffer + writeNode(&buf, fset, node) + return buf.String() } -// Template formatter for "localname" format. -func localnameFmt(w io.Writer, format string, x ...interface{}) { - _, localname := filepath.Split(x[0].(string)) - template.HTMLEscape(w, []byte(localname)) +func node_htmlFunc(node interface{}, fset *token.FileSet) string { + var buf1 bytes.Buffer + writeNode(&buf1, fset, node) + var buf2 bytes.Buffer + FormatText(&buf2, buf1.Bytes(), -1, true, "", nil) + return buf2.String() } -// Template formatter for "fileInfoName" format. -func fileInfoNameFmt(w io.Writer, format string, x ...interface{}) { - fi := x[0].(FileInfo) - template.HTMLEscape(w, []byte(fi.Name())) - if fi.IsDirectory() { - w.Write([]byte{'/'}) - } +func comment_htmlFunc(comment string) string { + var buf bytes.Buffer + // TODO(gri) Provide list of words (e.g. function parameters) + // to be emphasized by ToHTML. + doc.ToHTML(&buf, []byte(comment), nil) // does html-escaping + return buf.String() } -// Template formatter for "fileInfoSize" format. -func fileInfoSizeFmt(w io.Writer, format string, x ...interface{}) { - fmt.Fprintf(w, "%d", x[0].(FileInfo).Size()) +func pkgLinkFunc(path string) string { + relpath := relativeURL(path) + // because of the irregular mapping under goroot + // we need to correct certain relative paths + if strings.HasPrefix(relpath, "src/pkg/") { + relpath = relpath[len("src/pkg/"):] + } + return pkgHandler.pattern[1:] + relpath // remove trailing '/' for relative URL } -// Template formatter for "fileInfoTime" format. -func fileInfoTimeFmt(w io.Writer, format string, x ...interface{}) { - if t := x[0].(FileInfo).Mtime_ns(); t != 0 { - template.HTMLEscape(w, []byte(time.SecondsToLocalTime(t/1e9).String())) +func posLink_urlFunc(node ast.Node, fset *token.FileSet) string { + var relpath string + var line int + var low, high int // selection + + if p := node.Pos(); p.IsValid() { + pos := fset.Position(p) + relpath = relativeURL(pos.Filename) + line = pos.Line + low = pos.Offset + } + if p := node.End(); p.IsValid() { + high = fset.Position(p).Offset + } + + var buf bytes.Buffer + template.HTMLEscape(&buf, []byte(relpath)) + // selection ranges are of form "s=low:high" + if low < high { + fmt.Fprintf(&buf, "?s=%d:%d", low, high) // no need for URL escaping + // if we have a selection, position the page + // such that the selection is a bit below the top + line -= 10 + if line < 1 { + line = 1 + } + } + // line id's in html-printed source are of the + // form "L%d" where %d stands for the line number + if line > 0 { + fmt.Fprintf(&buf, "#L%d", line) // no need for URL escaping } - // don't print epoch if time is obviously not set -} -// Template formatter for "numlines" format. -func numlinesFmt(w io.Writer, format string, x ...interface{}) { - list := x[0].([]int) - fmt.Fprintf(w, "%d", len(list)) + return buf.String() } -var fmap = template.FormatterMap{ - "": textFmt, - "html-esc": htmlEscFmt, - "html-comment": htmlCommentFmt, - "urlquery-esc": urlQueryEscFmt, - "url-pkg": urlFmt, - "url-src": urlFmt, - "url-pos": urlFmt, - "infoKind": infoKindFmt, - "infoLine": infoLineFmt, - "infoSnippet": infoSnippetFmt, - "padding": paddingFmt, - "fileInfoName": fileInfoNameFmt, - "fileInfoSize": fileInfoSizeFmt, - "fileInfoTime": fileInfoTimeFmt, - "localname": localnameFmt, - "numlines": numlinesFmt, +// fmap describes the template functions installed with all godoc templates. +// Convention: template function names ending in "_html" or "_url" produce +// HTML- or URL-escaped strings; all other function results may +// require explicit escaping in the template. +var fmap = template.FuncMap{ + // various helpers + "filename": filenameFunc, + "repeat": strings.Repeat, + + // accss to FileInfos (directory listings) + "fileInfoName": fileInfoNameFunc, + "fileInfoTime": fileInfoTimeFunc, + + // access to search result information + "infoKind_html": infoKind_htmlFunc, + "infoLine": infoLineFunc, + "infoSnippet_html": infoSnippet_htmlFunc, + + // formatting of AST nodes + "node": nodeFunc, + "node_html": node_htmlFunc, + "comment_html": comment_htmlFunc, + + // support for URL attributes + "pkgLink": pkgLinkFunc, + "srcLink": relativeURL, + "posLink_url": posLink_urlFunc, } func readTemplate(name string) *template.Template { @@ -629,15 +540,7 @@ func readTemplate(name string) *template.Template { path = defaultpath } } - data, err := fs.ReadFile(path) - if err != nil { - log.Fatalf("ReadFile %s: %v", path, err) - } - t, err := template.Parse(string(data), fmap) - if err != nil { - log.Fatalf("%s: %v", name, err) - } - return t + return template.Must(template.New(name).Funcs(fmap).ParseFile(path)) } var ( @@ -864,6 +767,10 @@ func serveFile(w http.ResponseWriter, r *http.Request) { const fakePkgFile = "doc.go" const fakePkgName = "documentation" +// Fake relative package path for built-ins. Documentation for all globals +// (not just exported ones) will be shown for packages in this directory. +const builtinPkgPath = "builtin/" + type PageInfoMode uint const ( @@ -1038,7 +945,10 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { relpath := r.URL.Path[len(h.pattern):] abspath := absolutePath(relpath, h.fsRoot) - mode := exportsOnly + var mode PageInfoMode + if relpath != builtinPkgPath { + mode = exportsOnly + } if r.FormValue("m") != "src" { mode |= genDoc } @@ -1061,7 +971,7 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { title = "Package " + info.PAst.Name.Name case info.PDoc != nil: switch { - case h.isPkg: + case info.IsPkg: title = "Package " + info.PDoc.PackageName case info.PDoc.PackageName == fakePkgName: // assume that the directory name is the command name diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go index 943c81cfb..89b12b9ac 100644 --- a/src/cmd/godoc/main.go +++ b/src/cmd/godoc/main.go @@ -44,6 +44,7 @@ import ( "runtime" "strings" "time" + "url" ) const defaultAddr = ":6060" // default webserver address @@ -160,7 +161,7 @@ func loggingHandler(h http.Handler) http.Handler { } func remoteSearch(query string) (res *http.Response, err os.Error) { - search := "/search?f=text&q=" + http.URLEscape(query) + search := "/search?f=text&q=" + url.QueryEscape(query) // list of addresses to try var addrs []string @@ -401,9 +402,11 @@ func main() { fmt.Println() } if *html { - writeAnyHTML(os.Stdout, info.FSet, d) + var buf bytes.Buffer + writeNode(&buf, info.FSet, d) + FormatText(os.Stdout, buf.Bytes(), -1, true, "", nil) } else { - writeAny(os.Stdout, info.FSet, d) + writeNode(os.Stdout, info.FSet, d) } fmt.Println() } diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go index 626b01455..68e27d9a0 100755 --- a/src/cmd/godoc/snippet.go +++ b/src/cmd/godoc/snippet.go @@ -18,7 +18,7 @@ import ( type Snippet struct { Line int - Text []byte + Text string // HTML-escaped } func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet { @@ -30,7 +30,7 @@ func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet { buf2.WriteString("<pre>") FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil) buf2.WriteString("</pre>") - return &Snippet{fset.Position(id.Pos()).Line, buf2.Bytes()} + return &Snippet{fset.Position(id.Pos()).Line, buf2.String()} } func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec { @@ -94,10 +94,7 @@ func NewSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) (s *Snippet) if s == nil { var buf bytes.Buffer fmt.Fprintf(&buf, `<span class="alert">could not generate a snippet for <span class="highlight">%s</span></span>`, id.Name) - s = &Snippet{ - fset.Position(id.Pos()).Line, - buf.Bytes(), - } + s = &Snippet{fset.Position(id.Pos()).Line, buf.String()} } return } diff --git a/src/cmd/gofix/Makefile b/src/cmd/gofix/Makefile index 7ce21e8aa..22033d7f8 100644 --- a/src/cmd/gofix/Makefile +++ b/src/cmd/gofix/Makefile @@ -23,6 +23,7 @@ GOFILES=\ sortslice.go\ stringssplit.go\ typecheck.go\ + url.go\ include ../../Make.cmd diff --git a/src/cmd/gofix/fix.go b/src/cmd/gofix/fix.go index c1c5a746c..cc85ceafa 100644 --- a/src/cmd/gofix/fix.go +++ b/src/cmd/gofix/fix.go @@ -71,17 +71,21 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) { walkBeforeAfter(*n, before, after) case **ast.FuncType: walkBeforeAfter(*n, before, after) + case **ast.Ident: + walkBeforeAfter(*n, before, after) // pointers to slices - case *[]ast.Stmt: + case *[]ast.Decl: walkBeforeAfter(*n, before, after) case *[]ast.Expr: walkBeforeAfter(*n, before, after) - case *[]ast.Decl: + case *[]*ast.File: + walkBeforeAfter(*n, before, after) + case *[]*ast.Ident: walkBeforeAfter(*n, before, after) case *[]ast.Spec: walkBeforeAfter(*n, before, after) - case *[]*ast.File: + case *[]ast.Stmt: walkBeforeAfter(*n, before, after) // These are ordered and grouped to match ../../pkg/go/ast/ast.go @@ -212,6 +216,7 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) { case *ast.ValueSpec: walkBeforeAfter(&n.Type, before, after) walkBeforeAfter(&n.Values, before, after) + walkBeforeAfter(&n.Names, before, after) case *ast.TypeSpec: walkBeforeAfter(&n.Type, before, after) @@ -245,6 +250,10 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) { for i := range n { walkBeforeAfter(&n[i], before, after) } + case []*ast.Ident: + for i := range n { + walkBeforeAfter(&n[i], before, after) + } case []ast.Stmt: for i := range n { walkBeforeAfter(&n[i], before, after) diff --git a/src/cmd/gofix/url.go b/src/cmd/gofix/url.go new file mode 100644 index 000000000..c1e47bd4e --- /dev/null +++ b/src/cmd/gofix/url.go @@ -0,0 +1,106 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "os" + "go/ast" +) + +var _ fmt.Stringer +var _ os.Error + +var urlFix = fix{ + "url", + url, + `Move the URL pieces of package http into a new package, url. + +http://codereview.appspot.com/4893043 +`, +} + +func init() { + register(urlFix) +} + +var urlRenames = []struct{ in, out string }{ + {"ParseURL", "Parse"}, + {"ParseURLReference", "ParseWithReference"}, + {"ParseQuery", "ParseQuery"}, + {"Values", "Values"}, + {"URLEscape", "QueryEscape"}, + {"URLUnescape", "QueryUnescape"}, + {"URLError", "Error"}, + {"URLEscapeError", "EscapeError"}, +} + +func url(f *ast.File) bool { + if imports(f, "url") || !imports(f, "http") { + return false + } + + fixed := false + + // Update URL code. + urlWalk := func(n interface{}) { + // Is it an identifier? + if ident, ok := n.(*ast.Ident); ok && ident.Name == "url" { + ident.Name = "url_" + return + } + // Parameter and result names. + if fn, ok := n.(*ast.FuncType); ok { + fixed = urlDoFields(fn.Params) || fixed + fixed = urlDoFields(fn.Results) || fixed + } + } + + // Fix up URL code and add import, at most once. + fix := func() { + if fixed { + return + } + walk(f, urlWalk) + addImport(f, "url") + fixed = true + } + + walk(f, func(n interface{}) { + // Rename functions and methods. + if expr, ok := n.(ast.Expr); ok { + for _, s := range urlRenames { + if isPkgDot(expr, "http", s.in) { + fix() + expr.(*ast.SelectorExpr).X.(*ast.Ident).Name = "url" + expr.(*ast.SelectorExpr).Sel.Name = s.out + return + } + } + } + }) + + // Remove the http import if no longer needed. + if fixed && !usesImport(f, "http") { + deleteImport(f, "http") + } + + return fixed +} + +func urlDoFields(list *ast.FieldList) (fixed bool) { + if list == nil { + return + } + for _, field := range list.List { + for _, ident := range field.Names { + if ident.Name == "url" { + fixed = true + ident.Name = "url_" + } + } + } + return +} diff --git a/src/cmd/gofix/url_test.go b/src/cmd/gofix/url_test.go new file mode 100644 index 000000000..1a7095a5d --- /dev/null +++ b/src/cmd/gofix/url_test.go @@ -0,0 +1,147 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func init() { + addTestCases(urlTests) +} + +var urlTests = []testCase{ + { + Name: "url.0", + In: `package main + +import ( + "http" +) + +func f() { + http.ParseURL(a) + http.ParseURLReference(a) + http.ParseQuery(a) + m := http.Values{a: b} + http.URLEscape(a) + http.URLUnescape(a) + var x http.URLError + var y http.URLEscapeError +} +`, + Out: `package main + +import "url" + +func f() { + url.Parse(a) + url.ParseWithReference(a) + url.ParseQuery(a) + m := url.Values{a: b} + url.QueryEscape(a) + url.QueryUnescape(a) + var x url.Error + var y url.EscapeError +} +`, + }, + { + Name: "url.1", + In: `package main + +import ( + "http" +) + +func f() { + http.ParseURL(a) + var x http.Request +} +`, + Out: `package main + +import ( + "http" + "url" +) + +func f() { + url.Parse(a) + var x http.Request +} +`, + }, + { + Name: "url.2", + In: `package main + +import ( + "http" +) + +func f() { + http.ParseURL(a) + var url = 23 + url, x := 45, y +} + +func g(url string) string { + return url +} + +func h() (url string) { + return url +} +`, + Out: `package main + +import "url" + +func f() { + url.Parse(a) + var url_ = 23 + url_, x := 45, y +} + +func g(url_ string) string { + return url_ +} + +func h() (url_ string) { + return url_ +} +`, + }, + { + Name: "url.3", + In: `package main + +import "http" + +type U struct{ url string } + +func f() { + var u U + u.url = "x" +} + +func (url *T) m() string { + return url +} +`, + Out: `package main + +import "http" + +type U struct{ url string } + +func f() { + var u U + u.url = "x" +} + +func (url *T) m() string { + return url +} +`, + }, +} diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh index 3e63d0c26..063a0727f 100755 --- a/src/cmd/gofmt/test.sh +++ b/src/cmd/gofmt/test.sh @@ -43,7 +43,7 @@ apply1() { bug226.go | bug228.go | bug248.go | bug274.go | bug280.go | \ bug282.go | bug287.go | bug298.go | bug299.go | bug300.go | \ bug302.go | bug306.go | bug322.go | bug324.go | bug335.go | \ - bug340.go | bug349.go | bug351.go ) return ;; + bug340.go | bug349.go | bug351.go | bug358.go ) return ;; esac # the following directories are skipped because they contain test # cases for syntax errors and thus won't parse in the first place: diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go index 86e490e24..910ab7090 100644 --- a/src/cmd/goinstall/main.go +++ b/src/cmd/goinstall/main.go @@ -196,9 +196,17 @@ func install(pkg, parent string) { } // Download remote packages if not found or forced with -u flag. remote, public := isRemote(pkg), false - if remote && (err == build.ErrNotFound || (err == nil && *update)) { - printf("%s: download\n", pkg) - public, err = download(pkg, tree.SrcDir()) + if remote { + if err == build.ErrNotFound || (err == nil && *update) { + // Download remote package. + printf("%s: download\n", pkg) + public, err = download(pkg, tree.SrcDir()) + } else { + // Test if this is a public repository + // (for reporting to dashboard). + m, _ := findPublicRepo(pkg) + public = m != nil + } } if err != nil { errorf("%s: %v\n", pkg, err) diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go index 25f79d60d..38a70ddfd 100644 --- a/src/cmd/goinstall/make.go +++ b/src/cmd/goinstall/make.go @@ -8,11 +8,11 @@ package main import ( "bytes" - "exp/template" "go/build" "os" "path/filepath" "strings" + "template" ) // domake builds the package in dir. diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 974c08708..e7269169e 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -687,7 +687,7 @@ addaddrplus(Sym *s, Sym *t, int32 add) return i; } -vlong +static vlong addaddrplus4(Sym *s, Sym *t, int32 add) { vlong i; diff --git a/src/pkg/Makefile b/src/pkg/Makefile index c824f508c..ac36aaf0c 100644 --- a/src/pkg/Makefile +++ b/src/pkg/Makefile @@ -82,8 +82,7 @@ DIRS=\ exp/gui/x11\ exp/norm\ exp/regexp/syntax\ - exp/template\ - exp/template/parse\ + exp/template/html\ expvar\ flag\ fmt\ @@ -130,6 +129,7 @@ DIRS=\ net/dict\ net/textproto\ netchan\ + old/template\ os\ os/signal\ os/user\ @@ -156,6 +156,7 @@ DIRS=\ syslog\ tabwriter\ template\ + template/parse\ testing\ testing/iotest\ testing/quick\ @@ -163,6 +164,7 @@ DIRS=\ time\ try\ unicode\ + url\ utf16\ utf8\ websocket\ diff --git a/src/pkg/asn1/asn1.go b/src/pkg/asn1/asn1.go index 2dcdcfea6..39b676b41 100644 --- a/src/pkg/asn1/asn1.go +++ b/src/pkg/asn1/asn1.go @@ -681,23 +681,21 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam } err = err1 return - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - switch val.Type().Kind() { - case reflect.Int: - parsedInt, err1 := parseInt(innerBytes) - if err1 == nil { - val.SetInt(int64(parsedInt)) - } - err = err1 - return - case reflect.Int64: - parsedInt, err1 := parseInt64(innerBytes) - if err1 == nil { - val.SetInt(parsedInt) - } - err = err1 - return + case reflect.Int, reflect.Int32: + parsedInt, err1 := parseInt(innerBytes) + if err1 == nil { + val.SetInt(int64(parsedInt)) } + err = err1 + return + case reflect.Int64: + parsedInt, err1 := parseInt64(innerBytes) + if err1 == nil { + val.SetInt(parsedInt) + } + err = err1 + return + // TODO(dfc) Add support for the remaining integer types case reflect.Struct: structType := fieldType @@ -760,7 +758,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam } return } - err = StructuralError{"unknown Go type"} + err = StructuralError{"unsupported: " + v.Type().String()} return } @@ -787,7 +785,7 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { // Because Unmarshal uses the reflect package, the structs // being written to must use upper case field names. // -// An ASN.1 INTEGER can be written to an int or int64. +// An ASN.1 INTEGER can be written to an int, int32 or int64. // If the encoded value does not fit in the Go type, // Unmarshal returns a parse error. // diff --git a/src/pkg/asn1/asn1_test.go b/src/pkg/asn1/asn1_test.go index 8487a14b6..9f48f7bdd 100644 --- a/src/pkg/asn1/asn1_test.go +++ b/src/pkg/asn1/asn1_test.go @@ -42,6 +42,37 @@ func TestParseInt64(t *testing.T) { } } +type int32Test struct { + in []byte + ok bool + out int32 +} + +var int32TestData = []int32Test{ + {[]byte{0x00}, true, 0}, + {[]byte{0x7f}, true, 127}, + {[]byte{0x00, 0x80}, true, 128}, + {[]byte{0x01, 0x00}, true, 256}, + {[]byte{0x80}, true, -128}, + {[]byte{0xff, 0x7f}, true, -129}, + {[]byte{0xff, 0xff, 0xff, 0xff}, true, -1}, + {[]byte{0xff}, true, -1}, + {[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648}, + {[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0}, +} + +func TestParseInt32(t *testing.T) { + for i, test := range int32TestData { + ret, err := parseInt(test.in) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) + } + if test.ok && int32(ret) != test.out { + t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) + } + } +} + var bigIntTests = []struct { in []byte base10 string diff --git a/src/pkg/builtin/builtin.go b/src/pkg/builtin/builtin.go new file mode 100644 index 000000000..07acce4f7 --- /dev/null +++ b/src/pkg/builtin/builtin.go @@ -0,0 +1,135 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + Package builtin provides documentation for Go's built-in functions. + The functions documented here are not actually in package builtin + but their descriptions here allow godoc to present documentation + for the language's special functions. +*/ +package builtin + +// Type is here for the purposes of documentation only. It is a stand-in +// for any Go type, but represents the same type for any given function +// invocation. +type Type int + +// IntegerType is here for the purposes of documentation only. It is a stand-in +// for any integer type: int, uint, int8 etc. +type IntegerType int + +// FloatType is here for the purposes of documentation only. It is a stand-in +// for either float type: float32 or float64. +type FloatType int + +// ComplexType is here for the purposes of documentation only. It is a +// stand-in for either complex type: complex64 or complex128. +type ComplexType int + +// The append built-in function appends elements to the end of a slice. If +// it has sufficient capacity, the destination is resliced to accommodate the +// new elements. If it does not, a new underlying array will be allocated. +// Append returns the updated slice. It is therefore necessary to store the +// result of append, often in the variable holding the slice itself: +// slice = append(slice, elem1, elem2) +// slice = append(slice, anotherSlice...) +func append(slice []Type, elems ...Type) []Type + +// The copy built-in function copies elements from a source slice into a +// destination slice. (As a special case, it also will copy bytes from a +// string to a slice of bytes.) The source and destination may overlap. Copy +// returns the number of elements copied, which will be the minimum of +// len(src) and len(dst). +func copy(dst, src []Type) int + +// The len built-in function returns the length of v, according to its type: +// Array: the number of elements in v. +// Pointer to array: the number of elements in *v (even if v is nil). +// Slice, or map: the number of elements in v; if v is nil, len(v) is zero. +// String: the number of bytes in v. +// Channel: the number of elements queued (unread) in the channel buffer; +// if v is nil, len(v) is zero. +func len(v Type) int + +// The cap built-in function returns the capacity of v, according to its type: +// Array: the number of elements in v (same as len(v)). +// Pointer to array: the number of elements in *v (same as len(v)). +// Slice: the maximum length the slice can reach when resliced; +// if v is nil, cap(v) is zero. +// Channel: the channel buffer capacity, in units of elements; +// if v is nil, cap(v) is zero. +func cap(v Type) int + +// The make built-in function allocates and initializes an object of type +// slice, map, or chan (only). Like new, the first argument is a type, not a +// value. Unlike new, make's return type is the same as the type of its +// argument, not a pointer to it. The specification of the result depends on +// the type: +// Slice: The size specifies the length. The capacity of the slice is +// equal to its length. A second integer argument may be provided to +// specify a different capacity; it must be no smaller than the +// length, so make([]int, 0, 10) allocates a slice of length 0 and +// capacity 10. +// Map: An initial allocation is made according to the size but the +// resulting map has length 0. The size may be omitted, in which case +// a small starting size is allocated. +// Channel: The channel's buffer is initialized with the specified +// buffer capacity. If zero, or the size is omitted, the channel is +// unbuffered. +func make(Type, size IntegerType) Type + +// The new built-in function allocates memory. The first argument is a type, +// not a value, and the value returned is a pointer to a newly +// allocated zero value of that type. +func new(Type) *Type + +// The complex built-in function constructs a complex value from two +// floating-point values. The real and imaginary parts must be of the same +// size, either float32 or float64 (or assignable to them), and the return +// value will be the corresponding complex type (complex64 for float32, +// complex128 for float64). +func complex(r, i FloatType) ComplexType + +// The real built-in function returns the real part of the complex number c. +// The return value will be floating point type corresponding to the type of c. +func real(c ComplexType) FloatType + +// The imaginary built-in function returns the imaginary part of the complex +// number c. The return value will be floating point type corresponding to +// the type of c. +func imag(c ComplexType) FloatType + +// The close built-in function closes a channel, which must be either +// bidirectional or send-only. It should be executed only by the sender, +// never the receiver, and has the effect of shutting down the channel after +// the last sent value is received. After the last value has been received +// from a closed channel c, any receive from c will succeed without +// blocking, returning the zero value for the channel element. The form +// x, ok := <-c +// will also set ok to false for a closed channel. +func close(c chan<- Type) + +// The panic built-in function stops normal execution of the current +// goroutine. When a function F calls panic, normal execution of F stops +// immediately. Any functions whose execution was deferred by F are run in +// the usual way, and then F returns to its caller. To the caller G, the +// invocation of F then behaves like a call to panic, terminating G's +// execution and running any deferred functions. This continues until all +// functions in the executing goroutine have stopped, in reverse order. At +// that point, the program is terminated and the error condition is reported, +// including the value of the argument to panic. This termination sequence +// is called panicking and can be controlled by the built-in function +// recover. +func panic(v interface{}) + +// The recover built-in function allows a program to manage behavior of a +// panicking goroutine. Executing a call to recover inside a deferred +// function (but not any function called by it) stops the panicking sequence +// by restoring normal execution and retrieves the error value passed to the +// call of panic. If recover is called outside the deferred function it will +// not stop a panicking sequence. In this case, or when the goroutine is not +// panicking, or if the argument supplied to panic was nil, recover returns +// nil. Thus the return value from recover reports whether the goroutine is +// panicking. +func recover() interface{} diff --git a/src/pkg/crypto/rand/Makefile b/src/pkg/crypto/rand/Makefile index d1321297d..d1a3d45e8 100644 --- a/src/pkg/crypto/rand/Makefile +++ b/src/pkg/crypto/rand/Makefile @@ -19,6 +19,9 @@ GOFILES_darwin=\ GOFILES_linux=\ rand_unix.go\ +GOFILES_openbsd=\ + rand_unix.go\ + GOFILES_windows=\ rand_windows.go\ diff --git a/src/pkg/exec/Makefile b/src/pkg/exec/Makefile index 90bb74b41..ba19d0e4d 100644 --- a/src/pkg/exec/Makefile +++ b/src/pkg/exec/Makefile @@ -17,6 +17,9 @@ GOFILES_darwin=\ GOFILES_linux=\ lp_unix.go\ +GOFILES_openbsd=\ + lp_unix.go\ + GOFILES_windows=\ lp_windows.go\ diff --git a/src/pkg/exp/norm/Makefile b/src/pkg/exp/norm/Makefile index 906661d28..a4dfb43f7 100644 --- a/src/pkg/exp/norm/Makefile +++ b/src/pkg/exp/norm/Makefile @@ -6,23 +6,35 @@ include ../../../Make.inc TARG=exp/norm GOFILES=\ + composition.go\ + forminfo.go\ + normalize.go\ tables.go\ + trie.go\ include ../../../Make.pkg -CLEANFILES+=maketables +CLEANFILES+=maketables maketesttables -maketables: maketables.go - $(GC) maketables.go +maketables: maketables.go triegen.go + $(GC) maketables.go triegen.go $(LD) -o maketables maketables.$O +maketesttables: maketesttables.go triegen.go + $(GC) maketesttables.go triegen.go + $(LD) -o maketesttables maketesttables.$O + tables: maketables ./maketables > tables.go gofmt -w tables.go +trietesttables: maketesttables + ./maketesttables > triedata_test.go + gofmt -w triedata_test.go + # Build (but do not run) maketables during testing, # just to make sure it still compiles. -testshort: maketables +testshort: maketables maketesttables # Downloads from www.unicode.org, so not part # of standard test scripts. diff --git a/src/pkg/exp/norm/composition.go b/src/pkg/exp/norm/composition.go new file mode 100644 index 000000000..b2d2abaf6 --- /dev/null +++ b/src/pkg/exp/norm/composition.go @@ -0,0 +1,344 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package norm + +import "utf8" + +const ( + maxCombiningChars = 30 + 2 // +2 to hold CGJ and Hangul overflow. + maxBackRunes = maxCombiningChars - 1 + maxNFCExpansion = 3 // NFC(0x1D160) + maxNFKCExpansion = 18 // NFKC(0xFDFA) + + maxRuneSizeInDecomp = 4 + // Need to multiply by 2 as we don't reuse byte buffer space for recombining. + maxByteBufferSize = 2 * maxRuneSizeInDecomp * maxCombiningChars // 256 +) + +// reorderBuffer is used to normalize a single segment. Characters inserted with +// insert() are decomposed and reordered based on CCC. The compose() method can +// be used to recombine characters. Note that the byte buffer does not hold +// the UTF-8 characters in order. Only the rune array is maintained in sorted +// order. flush() writes the resulting segment to a byte array. +type reorderBuffer struct { + rune [maxCombiningChars]runeInfo // Per character info. + byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos. + nrune int // Number of runeInfos. + nbyte uint8 // Number or bytes. + f formInfo +} + +// reset discards all characters from the buffer. +func (rb *reorderBuffer) reset() { + rb.nrune = 0 + rb.nbyte = 0 +} + +// flush appends the normalized segment to out and resets rb. +func (rb *reorderBuffer) flush(out []byte) []byte { + for i := 0; i < rb.nrune; i++ { + start := rb.rune[i].pos + end := start + rb.rune[i].size + out = append(out, rb.byte[start:end]...) + } + rb.reset() + return out +} + +// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class. +// It returns false if the buffer is not large enough to hold the rune. +// It is used internally by insert. +func (rb *reorderBuffer) insertOrdered(info runeInfo) bool { + n := rb.nrune + if n >= maxCombiningChars { + return false + } + b := rb.rune[:] + cc := info.ccc + if cc > 0 { + // Find insertion position + move elements to make room. + for ; n > 0; n-- { + if b[n-1].ccc <= cc { + break + } + b[n] = b[n-1] + } + } + rb.nrune += 1 + pos := uint8(rb.nbyte) + rb.nbyte += info.size + info.pos = pos + b[n] = info + return true +} + +// insert inserts the given rune in the buffer ordered by CCC. +// It returns true if the buffer was large enough to hold the decomposed rune. +func (rb *reorderBuffer) insert(src []byte, info runeInfo) bool { + if info.size == 3 && isHangul(src) { + rune, _ := utf8.DecodeRune(src) + return rb.decomposeHangul(uint32(rune)) + } + pos := rb.nbyte + if info.flags.hasDecomposition() { + dcomp := rb.f.decompose(src) + for i := 0; i < len(dcomp); i += int(info.size) { + info = rb.f.info(dcomp[i:]) + if !rb.insertOrdered(info) { + return false + } + } + copy(rb.byte[pos:], dcomp) + } else { + if !rb.insertOrdered(info) { + return false + } + copy(rb.byte[pos:], src[:info.size]) + } + return true +} + +// insertString inserts the given rune in the buffer ordered by CCC. +// It returns true if the buffer was large enough to hold the decomposed rune. +func (rb *reorderBuffer) insertString(src string, info runeInfo) bool { + if info.size == 3 && isHangulString(src) { + rune, _ := utf8.DecodeRuneInString(src) + return rb.decomposeHangul(uint32(rune)) + } + pos := rb.nbyte + dcomp := rb.f.decomposeString(src) + dn := len(dcomp) + if dn != 0 { + for i := 0; i < dn; i += int(info.size) { + info = rb.f.info(dcomp[i:]) + if !rb.insertOrdered(info) { + return false + } + } + copy(rb.byte[pos:], dcomp) + } else { + if !rb.insertOrdered(info) { + return false + } + copy(rb.byte[pos:], src[:info.size]) + } + return true +} + +// appendRune inserts a rune at the end of the buffer. It is used for Hangul. +func (rb *reorderBuffer) appendRune(rune uint32) { + bn := rb.nbyte + sz := utf8.EncodeRune(rb.byte[bn:], int(rune)) + rb.nbyte += uint8(sz) + rb.rune[rb.nrune] = runeInfo{bn, uint8(sz), 0, 0} + rb.nrune++ +} + +// assignRune sets a rune at position pos. It is used for Hangul and recomposition. +func (rb *reorderBuffer) assignRune(pos int, rune uint32) { + bn := rb.nbyte + sz := utf8.EncodeRune(rb.byte[bn:], int(rune)) + rb.rune[pos] = runeInfo{bn, uint8(sz), 0, 0} + rb.nbyte += uint8(sz) +} + +// runeAt returns the rune at position n. It is used for Hangul and recomposition. +func (rb *reorderBuffer) runeAt(n int) uint32 { + inf := rb.rune[n] + rune, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size]) + return uint32(rune) +} + +// bytesAt returns the UTF-8 encoding of the rune at position n. +// It is used for Hangul and recomposition. +func (rb *reorderBuffer) bytesAt(n int) []byte { + inf := rb.rune[n] + return rb.byte[inf.pos : int(inf.pos)+int(inf.size)] +} + +// For Hangul we combine algorithmically, instead of using tables. +const ( + hangulBase = 0xAC00 // UTF-8(hangulBase) -> EA B0 80 + hangulBase0 = 0xEA + hangulBase1 = 0xB0 + hangulBase2 = 0x80 + + hangulEnd = hangulBase + jamoLVTCount // UTF-8(0xD7A4) -> ED 9E A4 + hangulEnd0 = 0xED + hangulEnd1 = 0x9E + hangulEnd2 = 0xA4 + + jamoLBase = 0x1100 // UTF-8(jamoLBase) -> E1 84 00 + jamoLBase0 = 0xE1 + jamoLBase1 = 0x84 + jamoLEnd = 0x1113 + jamoVBase = 0x1161 + jamoVEnd = 0x1176 + jamoTBase = 0x11A7 + jamoTEnd = 0x11C3 + + jamoTCount = 28 + jamoVCount = 21 + jamoVTCount = 21 * 28 + jamoLVTCount = 19 * 21 * 28 +) + +// Caller must verify that len(b) >= 3. +func isHangul(b []byte) bool { + b0 := b[0] + if b0 < hangulBase0 { + return false + } + b1 := b[1] + switch { + case b0 == hangulBase0: + return b1 >= hangulBase1 + case b0 < hangulEnd0: + return true + case b0 > hangulEnd0: + return false + case b1 < hangulEnd1: + return true + } + return b1 == hangulEnd1 && b[2] < hangulEnd2 +} + +// Caller must verify that len(b) >= 3. +func isHangulString(b string) bool { + b0 := b[0] + if b0 < hangulBase0 { + return false + } + b1 := b[1] + switch { + case b0 == hangulBase0: + return b1 >= hangulBase1 + case b0 < hangulEnd0: + return true + case b0 > hangulEnd0: + return false + case b1 < hangulEnd1: + return true + } + return b1 == hangulEnd1 && b[2] < hangulEnd2 +} + +// Caller must ensure len(b) >= 2. +func isJamoVT(b []byte) bool { + // True if (rune & 0xff00) == jamoLBase + return b[0] == jamoLBase0 && (b[1]&0xFC) == jamoLBase1 +} + +func isHangulWithoutJamoT(b []byte) bool { + c, _ := utf8.DecodeRune(b) + c -= hangulBase + return c < jamoLVTCount && c%jamoTCount == 0 +} + +// decomposeHangul algorithmically decomposes a Hangul rune into +// its Jamo components. +// See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul. +func (rb *reorderBuffer) decomposeHangul(rune uint32) bool { + b := rb.rune[:] + n := rb.nrune + if n+3 > len(b) { + return false + } + rune -= hangulBase + x := rune % jamoTCount + rune /= jamoTCount + rb.appendRune(jamoLBase + rune/jamoVCount) + rb.appendRune(jamoVBase + rune%jamoVCount) + if x != 0 { + rb.appendRune(jamoTBase + x) + } + return true +} + +// combineHangul algorithmically combines Jamo character components into Hangul. +// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul. +func (rb *reorderBuffer) combineHangul() { + k := 1 + b := rb.rune[:] + bn := rb.nrune + for s, i := 0, 1; i < bn; i++ { + cccB := b[k-1].ccc + cccC := b[i].ccc + if cccB == 0 { + s = k - 1 + } + if s != k-1 && cccB >= cccC { + // b[i] is blocked by greater-equal cccX below it + b[k] = b[i] + k++ + } else { + l := rb.runeAt(s) // also used to compare to hangulBase + v := rb.runeAt(i) // also used to compare to jamoT + switch { + case jamoLBase <= l && l < jamoLEnd && + jamoVBase <= v && v < jamoVEnd: + // 11xx plus 116x to LV + rb.assignRune(s, hangulBase+ + (l-jamoLBase)*jamoVTCount+(v-jamoVBase)*jamoTCount) + case hangulBase <= l && l < hangulEnd && + jamoTBase < v && v < jamoTEnd && + ((l-hangulBase)%jamoTCount) == 0: + // ACxx plus 11Ax to LVT + rb.assignRune(s, l+v-jamoTBase) + default: + b[k] = b[i] + k++ + } + } + } + rb.nrune = k +} + +// compose recombines the runes in the buffer. +// It should only be used to recompose a single segment, as it will not +// handle alternations between Hangul and non-Hangul characters correctly. +func (rb *reorderBuffer) compose() { + // UAX #15, section X5 , including Corrigendum #5 + // "In any character sequence beginning with starter S, a character C is + // blocked from S if and only if there is some character B between S + // and C, and either B is a starter or it has the same or higher + // combining class as C." + k := 1 + b := rb.rune[:] + bn := rb.nrune + for s, i := 0, 1; i < bn; i++ { + if isJamoVT(rb.bytesAt(i)) { + // Redo from start in Hangul mode. Necessary to support + // U+320E..U+321E in NFKC mode. + rb.combineHangul() + return + } + ii := b[i] + // We can only use combineForward as a filter if we later + // get the info for the combined character. This is more + // expensive than using the filter. Using combinesBackward() + // is safe. + if ii.flags.combinesBackward() { + cccB := b[k-1].ccc + cccC := ii.ccc + blocked := false // b[i] blocked by starter or greater or equal CCC? + if cccB == 0 { + s = k - 1 + } else { + blocked = s != k-1 && cccB >= cccC + } + if !blocked { + combined := combine(rb.runeAt(s), rb.runeAt(i)) + if combined != 0 { + rb.assignRune(s, combined) + continue + } + } + } + b[k] = b[i] + k++ + } + rb.nrune = k +} diff --git a/src/pkg/exp/norm/composition_test.go b/src/pkg/exp/norm/composition_test.go new file mode 100644 index 000000000..195a0c1e8 --- /dev/null +++ b/src/pkg/exp/norm/composition_test.go @@ -0,0 +1,138 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package norm + +import "testing" + +// TestCase is used for most tests. +type TestCase struct { + in []int + out []int +} + +type insertFunc func(rb *reorderBuffer, rune int) bool + +func insert(rb *reorderBuffer, rune int) bool { + b := []byte(string(rune)) + return rb.insert(b, rb.f.info(b)) +} + +func insertString(rb *reorderBuffer, rune int) bool { + s := string(rune) + return rb.insertString(s, rb.f.infoString(s)) +} + +func runTests(t *testing.T, name string, rb *reorderBuffer, f insertFunc, tests []TestCase) { + for i, test := range tests { + rb.reset() + for j, rune := range test.in { + b := []byte(string(rune)) + if !rb.insert(b, rb.f.info(b)) { + t.Errorf("%s:%d: insert failed for rune %d", name, i, j) + } + } + if rb.f.composing { + rb.compose() + } + if rb.nrune != len(test.out) { + t.Errorf("%s:%d: length = %d; want %d", name, i, rb.nrune, len(test.out)) + continue + } + for j, want := range test.out { + found := int(rb.runeAt(j)) + if found != want { + t.Errorf("%s:%d: runeAt(%d) = %U; want %U", name, i, j, found, want) + } + } + } +} + +func TestFlush(t *testing.T) { + rb := &reorderBuffer{f: *formTable[NFC]} + out := make([]byte, 0) + + out = rb.flush(out) + if len(out) != 0 { + t.Errorf("wrote bytes on flush of empty buffer. (len(out) = %d)", len(out)) + } + + for _, r := range []int("world!") { + insert(rb, r) + } + + out = []byte("Hello ") + out = rb.flush(out) + want := "Hello world!" + if string(out) != want { + t.Errorf(`output after flush was "%s"; want "%s"`, string(out), want) + } + if rb.nrune != 0 { + t.Errorf("flush: non-null size of info buffer (rb.nrune == %d)", rb.nrune) + } + if rb.nbyte != 0 { + t.Errorf("flush: non-null size of byte buffer (rb.nbyte == %d)", rb.nbyte) + } +} + +var insertTests = []TestCase{ + {[]int{'a'}, []int{'a'}}, + {[]int{0x300}, []int{0x300}}, + {[]int{0x300, 0x316}, []int{0x316, 0x300}}, // CCC(0x300)==230; CCC(0x316)==220 + {[]int{0x316, 0x300}, []int{0x316, 0x300}}, + {[]int{0x41, 0x316, 0x300}, []int{0x41, 0x316, 0x300}}, + {[]int{0x41, 0x300, 0x316}, []int{0x41, 0x316, 0x300}}, + {[]int{0x300, 0x316, 0x41}, []int{0x316, 0x300, 0x41}}, + {[]int{0x41, 0x300, 0x40, 0x316}, []int{0x41, 0x300, 0x40, 0x316}}, +} + +func TestInsert(t *testing.T) { + rb := &reorderBuffer{f: *formTable[NFD]} + runTests(t, "TestInsert", rb, insert, insertTests) +} + +func TestInsertString(t *testing.T) { + rb := &reorderBuffer{f: *formTable[NFD]} + runTests(t, "TestInsertString", rb, insertString, insertTests) +} + +var decompositionNFDTest = []TestCase{ + {[]int{0xC0}, []int{0x41, 0x300}}, + {[]int{0xAC00}, []int{0x1100, 0x1161}}, + {[]int{0x01C4}, []int{0x01C4}}, + {[]int{0x320E}, []int{0x320E}}, + {[]int("음ẻ과"), []int{0x110B, 0x1173, 0x11B7, 0x65, 0x309, 0x1100, 0x116A}}, +} + +var decompositionNFKDTest = []TestCase{ + {[]int{0xC0}, []int{0x41, 0x300}}, + {[]int{0xAC00}, []int{0x1100, 0x1161}}, + {[]int{0x01C4}, []int{0x44, 0x5A, 0x030C}}, + {[]int{0x320E}, []int{0x28, 0x1100, 0x1161, 0x29}}, +} + +func TestDecomposition(t *testing.T) { + rb := &reorderBuffer{} + rb.f = *formTable[NFD] + runTests(t, "TestDecompositionNFD", rb, insert, decompositionNFDTest) + rb.f = *formTable[NFKD] + runTests(t, "TestDecompositionNFKD", rb, insert, decompositionNFKDTest) +} + +var compositionTest = []TestCase{ + {[]int{0x41, 0x300}, []int{0xC0}}, + {[]int{0x41, 0x316}, []int{0x41, 0x316}}, + {[]int{0x41, 0x300, 0x35D}, []int{0xC0, 0x35D}}, + {[]int{0x41, 0x316, 0x300}, []int{0xC0, 0x316}}, + // blocking starter + {[]int{0x41, 0x316, 0x40, 0x300}, []int{0x41, 0x316, 0x40, 0x300}}, + {[]int{0x1100, 0x1161}, []int{0xAC00}}, + // parenthesized Hangul, alternate between ASCII and Hangul. + {[]int{0x28, 0x1100, 0x1161, 0x29}, []int{0x28, 0xAC00, 0x29}}, +} + +func TestComposition(t *testing.T) { + rb := &reorderBuffer{f: *formTable[NFC]} + runTests(t, "TestComposition", rb, insert, compositionTest) +} diff --git a/src/pkg/exp/norm/forminfo.go b/src/pkg/exp/norm/forminfo.go new file mode 100644 index 000000000..ee3edb8ea --- /dev/null +++ b/src/pkg/exp/norm/forminfo.go @@ -0,0 +1,188 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package norm + +// This file contains Form-specific logic and wrappers for data in tables.go. + +type runeInfo struct { + pos uint8 // start position in reorderBuffer; used in composition.go + size uint8 // length of UTF-8 encoding of this rune + ccc uint8 // canonical combining class + flags qcInfo // quick check flags +} + +// functions dispatchable per form +type boundaryFunc func(f *formInfo, info runeInfo) bool +type lookupFunc func(b []byte) runeInfo +type lookupFuncString func(s string) runeInfo +type decompFunc func(b []byte) []byte +type decompFuncString func(s string) []byte + +// formInfo holds Form-specific functions and tables. +type formInfo struct { + form Form + + composing, compatibility bool // form type + + decompose decompFunc + decomposeString decompFuncString + info lookupFunc + infoString lookupFuncString + boundaryBefore boundaryFunc + boundaryAfter boundaryFunc +} + +var formTable []*formInfo + +func init() { + formTable = make([]*formInfo, 4) + + for i := range formTable { + f := &formInfo{} + formTable[i] = f + f.form = Form(i) + if Form(i) == NFKD || Form(i) == NFKC { + f.compatibility = true + f.decompose = decomposeNFKC + f.decomposeString = decomposeStringNFKC + f.info = lookupInfoNFKC + f.infoString = lookupInfoStringNFKC + } else { + f.decompose = decomposeNFC + f.decomposeString = decomposeStringNFC + f.info = lookupInfoNFC + f.infoString = lookupInfoStringNFC + } + if Form(i) == NFC || Form(i) == NFKC { + f.composing = true + f.boundaryBefore = compBoundaryBefore + f.boundaryAfter = compBoundaryAfter + } else { + f.boundaryBefore = decompBoundary + f.boundaryAfter = decompBoundary + } + } +} + +func decompBoundary(f *formInfo, info runeInfo) bool { + if info.ccc == 0 && info.flags.isYesD() { // Implies isHangul(b) == true + return true + } + // We assume that the CCC of the first character in a decomposition + // is always non-zero if different from info.ccc and that we can return + // false at this point. This is verified by maketables. + return false +} + +func compBoundaryBefore(f *formInfo, info runeInfo) bool { + if info.ccc == 0 && info.flags.isYesC() { + return true + } + // We assume that the CCC of the first character in a decomposition + // is always non-zero if different from info.ccc and that we can return + // false at this point. This is verified by maketables. + return false +} + +func compBoundaryAfter(f *formInfo, info runeInfo) bool { + // This misses values where the last char in a decomposition is a + // boundary such as Hangul with JamoT. + // TODO(mpvl): verify this does not lead to segments that do + // not fit in the reorderBuffer. + return info.flags.isInert() +} + +// We pack quick check data in 4 bits: +// 0: NFD_QC Yes (0) or No (1). No also means there is a decomposition. +// 1..2: NFC_QC Yes(00), No (01), or Maybe (11) +// 3: Combines forward (0 == false, 1 == true) +// +// When all 4 bits are zero, the character is inert, meaning it is never +// influenced by normalization. +// +// We pack the bits for both NFC/D and NFKC/D in one byte. +type qcInfo uint8 + +func (i qcInfo) isYesC() bool { return i&0x2 == 0 } +func (i qcInfo) isNoC() bool { return i&0x6 == 0x2 } +func (i qcInfo) isMaybe() bool { return i&0x4 != 0 } +func (i qcInfo) isYesD() bool { return i&0x1 == 0 } +func (i qcInfo) isNoD() bool { return i&0x1 != 0 } +func (i qcInfo) isInert() bool { return i&0xf == 0 } + +func (i qcInfo) combinesForward() bool { return i&0x8 != 0 } +func (i qcInfo) combinesBackward() bool { return i&0x4 != 0 } // == isMaybe +func (i qcInfo) hasDecomposition() bool { return i&0x1 != 0 } // == isNoD + +// Wrappers for tables.go + +// The 16-bit value of the decompostion tries is an index into a byte +// array of UTF-8 decomposition sequences. The first byte is the number +// of bytes in the decomposition (excluding this length byte). The actual +// sequence starts at the offset+1. +func decomposeNFC(b []byte) []byte { + p := nfcDecompTrie.lookupUnsafe(b) + n := decomps[p] + p++ + return decomps[p : p+uint16(n)] +} + +func decomposeNFKC(b []byte) []byte { + p := nfkcDecompTrie.lookupUnsafe(b) + n := decomps[p] + p++ + return decomps[p : p+uint16(n)] +} + +func decomposeStringNFC(s string) []byte { + p := nfcDecompTrie.lookupStringUnsafe(s) + n := decomps[p] + p++ + return decomps[p : p+uint16(n)] +} + +func decomposeStringNFKC(s string) []byte { + p := nfkcDecompTrie.lookupStringUnsafe(s) + n := decomps[p] + p++ + return decomps[p : p+uint16(n)] +} + +// Recomposition +// We use 32-bit keys instead of 64-bit for the two codepoint keys. +// This clips off the bits of three entries, but we know this will not +// result in a collision. In the unlikely event that changes to +// UnicodeData.txt introduce collisions, the compiler will catch it. +// Note that the recomposition map for NFC and NFKC are identical. + +// combine returns the combined rune or 0 if it doesn't exist. +func combine(a, b uint32) uint32 { + key := uint32(uint16(a))<<16 + uint32(uint16(b)) + return recompMap[key] +} + +// The 16-bit character info has the following bit layout: +// 0..7 CCC value. +// 8..11 qcInfo for NFC/NFD +// 12..15 qcInfo for NFKC/NFKD +func lookupInfoNFC(b []byte) runeInfo { + v, sz := charInfoTrie.lookup(b) + return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 8)} +} + +func lookupInfoStringNFC(s string) runeInfo { + v, sz := charInfoTrie.lookupString(s) + return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 8)} +} + +func lookupInfoNFKC(b []byte) runeInfo { + v, sz := charInfoTrie.lookup(b) + return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 12)} +} + +func lookupInfoStringNFKC(s string) runeInfo { + v, sz := charInfoTrie.lookupString(s) + return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 12)} +} diff --git a/src/pkg/exp/norm/maketables.go b/src/pkg/exp/norm/maketables.go index 0064b2cbe..e3e5700a6 100644 --- a/src/pkg/exp/norm/maketables.go +++ b/src/pkg/exp/norm/maketables.go @@ -12,7 +12,6 @@ import ( "bytes" "flag" "fmt" - "hash/crc32" "http" "io" "log" @@ -20,7 +19,6 @@ import ( "regexp" "strconv" "strings" - "utf8" ) func main() { @@ -118,7 +116,6 @@ const ( MNumberOfModes ) - // This contains only the properties we're interested in. type Char struct { name string @@ -269,7 +266,7 @@ func parseCharacter(line string) { } x, err = strconv.Atoui64(field[FCanonicalCombiningClass]) if err != nil { - logger.Fatal("%U: bad ccc field: %s", int(x), err) + logger.Fatalf("%U: bad ccc field: %s", int(x), err) } ccc := uint8(x) decmap := field[FDecompMapping] @@ -440,7 +437,6 @@ func decomposeRecursive(form int, rune int, d Decomposition) Decomposition { return d } - func completeCharFields(form int) { // Phase 0: pre-expand decomposition. for i := range chars { @@ -535,130 +531,6 @@ func completeCharFields(form int) { } } -// Intermediate trie structure -type trieNode struct { - table [256]*trieNode - value uint16 - b byte - leaf bool -} - -func newNode() *trieNode { - return new(trieNode) -} - -type nodeIndex struct { - lookupBlocks []*trieNode - valueBlocks []*trieNode - - lookupBlockIdx map[uint32]uint16 - valueBlockIdx map[uint32]uint16 -} - -func newIndex() *nodeIndex { - index := &nodeIndex{} - index.lookupBlocks = make([]*trieNode, 0) - index.valueBlocks = make([]*trieNode, 0) - index.lookupBlockIdx = make(map[uint32]uint16) - index.valueBlockIdx = make(map[uint32]uint16) - return index -} - -func (n trieNode) isInternal() bool { - internal := true - for i := 0; i < 256; i++ { - if nn := n.table[i]; nn != nil { - if !internal && !nn.leaf { - panic("Node contains both leaf and non-leaf children.") - } - internal = internal && !nn.leaf - } - } - return internal -} - -func (n *trieNode) insert(rune int, value uint16) { - var p [utf8.UTFMax]byte - sz := utf8.EncodeRune(p[:], rune) - - for i := 0; i < sz; i++ { - if n.leaf { - panic("Node should not be a leaf") - } - nn := n.table[int(p[i])] - if nn == nil { - nn = newNode() - nn.b = p[i] - n.table[int(p[i])] = nn - } - n = nn - } - n.value = value - n.leaf = true -} - -func computeOffsets(index *nodeIndex, n *trieNode) uint16 { - if n.leaf { - return n.value - } - hasher := crc32.New(crc32.MakeTable(crc32.IEEE)) - // We only index continuation bytes. - for i := 0; i < 64; i++ { - var v uint16 = 0 - if nn := n.table[0x80+i]; nn != nil { - v = computeOffsets(index, nn) - } - hasher.Write([]byte{uint8(v >> 8), uint8(v)}) - } - h := hasher.Sum32() - if n.isInternal() { - v, ok := index.lookupBlockIdx[h] - if !ok { - v = uint16(len(index.lookupBlocks)) - index.lookupBlocks = append(index.lookupBlocks, n) - index.lookupBlockIdx[h] = v - } - n.value = v - } else { - v, ok := index.valueBlockIdx[h] - if !ok { - v = uint16(len(index.valueBlocks)) - index.valueBlocks = append(index.valueBlocks, n) - index.valueBlockIdx[h] = v - } - n.value = v - } - return n.value -} - -func printValueBlock(nr int, n *trieNode, offset int) { - fmt.Printf("\n// Block %X", nr) - for i := 0; i < 64; i++ { - if i%8 == 0 { - fmt.Printf("\n") - } - var v uint16 = 0 - if nn := n.table[i+offset]; nn != nil { - v = nn.value - } - fmt.Printf("0x%.4X, ", v) - } -} - -func printLookupBlock(nr int, n *trieNode, offset int) { - fmt.Printf("\n// Block %X", nr) - for i := 0; i < 64; i++ { - if i%8 == 0 { - fmt.Printf("\n") - } - var v uint16 = 0 - if nn := n.table[i+offset]; nn != nil { - v = nn.value - } - fmt.Printf("0x%.2X, ", v) - } -} - func printBytes(b []byte, name string) { fmt.Printf("// %s: %d bytes\n", name, len(b)) fmt.Printf("var %s = [...]byte {", name) @@ -674,48 +546,6 @@ func printBytes(b []byte, name string) { fmt.Print("\n}\n\n") } -// printTrieTables returns the size of the generated tables. -func printTrieTables(t *trieNode, name string) int { - index := newIndex() - // Directly add first 128 values of UTF-8, followed by nil block. - index.valueBlocks = append(index.valueBlocks, nil, nil, nil) - // First byte of multi-byte UTF-8 codepoints are indexed in 4th block. - index.lookupBlocks = append(index.lookupBlocks, nil, nil, nil, nil) - // Index starter bytes of multi-byte UTF-8. - for i := 0xC0; i < 0x100; i++ { - if t.table[i] != nil { - computeOffsets(index, t.table[i]) - } - } - - nv := len(index.valueBlocks) * 64 - - fmt.Printf("// %sValues: %d entries, %d bytes\n", name, nv, nv*2) - fmt.Printf("// Block 2 is the null block.\n") - fmt.Printf("var %sValues = [...]uint16 {", name) - printValueBlock(0, t, 0) - printValueBlock(1, t, 64) - printValueBlock(2, newNode(), 0) - for i := 3; i < len(index.valueBlocks); i++ { - printValueBlock(i, index.valueBlocks[i], 0x80) - } - fmt.Print("\n}\n\n") - - ni := len(index.lookupBlocks) * 64 - fmt.Printf("// %sLookup: %d bytes\n", name, ni) - fmt.Printf("// Block 0 is the null block.\n") - fmt.Printf("var %sLookup = [...]uint8 {", name) - printLookupBlock(0, newNode(), 0) - printLookupBlock(1, newNode(), 0) - printLookupBlock(2, newNode(), 0) - printLookupBlock(3, t, 0xC0) - for i := 4; i < len(index.lookupBlocks); i++ { - printLookupBlock(i, index.lookupBlocks[i], 0x80) - } - fmt.Print("\n}\n\n") - return nv*2 + ni -} - // See forminfo.go for format. func makeEntry(f *FormInfo) uint16 { e := uint16(0) @@ -757,7 +587,7 @@ func printCharInfoTables() int { t.insert(i, v) } } - return printTrieTables(t, "charInfo") + return t.printTables("charInfo") } func printDecompositionTables() int { @@ -791,14 +621,26 @@ func printDecompositionTables() int { d := c.forms[FCanonical].expandedDecomp if len(d) != 0 { nfcT.insert(i, positionMap[string([]int(d))]) + if ccc(c.codePoint) != ccc(d[0]) { + // We assume the lead ccc of a decomposition is !=0 in this case. + if ccc(d[0]) == 0 { + logger.Fatal("Expected differing CCC to be non-zero.") + } + } } d = c.forms[FCompatibility].expandedDecomp if len(d) != 0 { nfkcT.insert(i, positionMap[string([]int(d))]) + if ccc(c.codePoint) != ccc(d[0]) { + // We assume the lead ccc of a decomposition is !=0 in this case. + if ccc(d[0]) == 0 { + logger.Fatal("Expected differing CCC to be non-zero.") + } + } } } - size += printTrieTables(nfcT, "nfcDecomp") - size += printTrieTables(nfkcT, "nfkcDecomp") + size += nfcT.printTables("nfcDecomp") + size += nfkcT.printTables("nfkcDecomp") return size } diff --git a/src/pkg/exp/norm/maketesttables.go b/src/pkg/exp/norm/maketesttables.go new file mode 100644 index 000000000..c5f6a6436 --- /dev/null +++ b/src/pkg/exp/norm/maketesttables.go @@ -0,0 +1,42 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Generate test data for trie code. + +package main + +import ( + "fmt" +) + +func main() { + printTestTables() +} + +// We take the smallest, largest and an arbitrary value for each +// of the UTF-8 sequence lengths. +var testRunes = []int{ + 0x01, 0x0C, 0x7F, // 1-byte sequences + 0x80, 0x100, 0x7FF, // 2-byte sequences + 0x800, 0x999, 0xFFFF, // 3-byte sequences + 0x10000, 0x10101, 0x10FFFF, // 4-byte sequences +} + +const fileHeader = `// Generated by running +// maketesttables +// DO NOT EDIT + +package norm + +` + +func printTestTables() { + fmt.Print(fileHeader) + fmt.Printf("var testRunes = %#v\n\n", testRunes) + t := newNode() + for i, r := range testRunes { + t.insert(r, uint16(i)) + } + t.printTables("testdata") +} diff --git a/src/pkg/exp/norm/normalize.go b/src/pkg/exp/norm/normalize.go index 81311bfcb..e9d18dd9e 100644 --- a/src/pkg/exp/norm/normalize.go +++ b/src/pkg/exp/norm/normalize.go @@ -31,45 +31,69 @@ const ( ) // Bytes returns f(b). May return b if f(b) = b. -func (f Form) Bytes(b []byte) []byte +func (f Form) Bytes(b []byte) []byte { + panic("not implemented") +} // String returns f(s). -func (f Form) String(s string) string +func (f Form) String(s string) string { + panic("not implemented") +} // IsNormal returns true if b == f(b). -func (f Form) IsNormal(b []byte) bool +func (f Form) IsNormal(b []byte) bool { + panic("not implemented") +} // IsNormalString returns true if s == f(s). -func (f Form) IsNormalString(s string) bool +func (f Form) IsNormalString(s string) bool { + panic("not implemented") +} // Append returns f(append(out, b...)). // The buffer out must be empty or equal to f(out). -func (f Form) Append(out, b []byte) []byte +func (f Form) Append(out, b []byte) []byte { + panic("not implemented") +} // AppendString returns f(append(out, []byte(s))). // The buffer out must be empty or equal to f(out). -func (f Form) AppendString(out []byte, s string) []byte +func (f Form) AppendString(out []byte, s string) []byte { + panic("not implemented") +} // QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]). // It is not guaranteed to return the largest such n. -func (f Form) QuickSpan(b []byte) int +func (f Form) QuickSpan(b []byte) int { + panic("not implemented") +} // QuickSpanString returns a boundary n such that b[0:n] == f(s[0:n]). // It is not guaranteed to return the largest such n. -func (f Form) QuickSpanString(s string) int +func (f Form) QuickSpanString(s string) int { + panic("not implemented") +} // FirstBoundary returns the position i of the first boundary in b. // It returns len(b), false if b contains no boundaries. -func (f Form) FirstBoundary(b []byte) (i int, ok bool) +func (f Form) FirstBoundary(b []byte) (i int, ok bool) { + panic("not implemented") +} // FirstBoundaryInString return the position i of the first boundary in s. // It returns len(s), false if s contains no boundaries. -func (f Form) FirstBoundaryInString(s string) (i int, ok bool) +func (f Form) FirstBoundaryInString(s string) (i int, ok bool) { + panic("not implemented") +} // LastBoundaryIn returns the position i of the last boundary in b. // It returns 0, false if b contains no boundary. -func (f Form) LastBoundary(b []byte) (i int, ok bool) +func (f Form) LastBoundary(b []byte) (i int, ok bool) { + panic("not implemented") +} // LastBoundaryInString returns the position i of the last boundary in s. // It returns 0, false if s contains no boundary. -func (f Form) LastBoundaryInString(s string) (i int, ok bool) +func (f Form) LastBoundaryInString(s string) (i int, ok bool) { + panic("not implemented") +} diff --git a/src/pkg/exp/norm/tables.go b/src/pkg/exp/norm/tables.go index 7addc4771..76995c2fa 100644 --- a/src/pkg/exp/norm/tables.go +++ b/src/pkg/exp/norm/tables.go @@ -2492,2409 +2492,1935 @@ var decomps = [...]byte{ // nfcDecompValues: 4992 entries, 9984 bytes // Block 2 is the null block. -var nfcDecompValues = [...]uint16{ - // Block 0 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3 - 0x0032, 0x0036, 0x003A, 0x003E, 0x0042, 0x0046, 0x0000, 0x004A, - 0x004E, 0x0052, 0x0056, 0x005A, 0x005E, 0x0062, 0x0066, 0x006A, - 0x0000, 0x006E, 0x0072, 0x0076, 0x007A, 0x007E, 0x0082, 0x0000, - 0x0000, 0x0086, 0x008A, 0x008E, 0x0092, 0x0096, 0x0000, 0x0000, - 0x009A, 0x009E, 0x00A2, 0x00A6, 0x00AA, 0x00AE, 0x0000, 0x00B2, - 0x00B6, 0x00BA, 0x00BE, 0x00C2, 0x00C6, 0x00CA, 0x00CE, 0x00D2, - 0x0000, 0x00D6, 0x00DA, 0x00DE, 0x00E2, 0x00E6, 0x00EA, 0x0000, - 0x0000, 0x00EE, 0x00F2, 0x00F6, 0x00FA, 0x00FE, 0x0000, 0x0102, - // Block 4 - 0x0106, 0x010A, 0x010E, 0x0112, 0x0116, 0x011A, 0x011E, 0x0122, - 0x0126, 0x012A, 0x012E, 0x0132, 0x0136, 0x013A, 0x013E, 0x0142, - 0x0000, 0x0000, 0x0146, 0x014A, 0x014E, 0x0152, 0x0156, 0x015A, - 0x015E, 0x0162, 0x0166, 0x016A, 0x016E, 0x0172, 0x0176, 0x017A, - 0x017E, 0x0182, 0x0186, 0x018A, 0x018E, 0x0192, 0x0000, 0x0000, - 0x0196, 0x019A, 0x019E, 0x01A2, 0x01A6, 0x01AA, 0x01AE, 0x01B2, - 0x01B6, 0x0000, 0x0000, 0x0000, 0x01C0, 0x01C4, 0x01C8, 0x01CC, - 0x0000, 0x01D0, 0x01D4, 0x01D8, 0x01DC, 0x01E0, 0x01E4, 0x0000, - // Block 5 - 0x0000, 0x0000, 0x0000, 0x01F0, 0x01F4, 0x01F8, 0x01FC, 0x0200, - 0x0204, 0x0000, 0x0000, 0x0000, 0x020C, 0x0210, 0x0214, 0x0218, - 0x021C, 0x0220, 0x0000, 0x0000, 0x0224, 0x0228, 0x022C, 0x0230, - 0x0234, 0x0238, 0x023C, 0x0240, 0x0244, 0x0248, 0x024C, 0x0250, - 0x0254, 0x0258, 0x025C, 0x0260, 0x0264, 0x0268, 0x0000, 0x0000, - 0x026C, 0x0270, 0x0274, 0x0278, 0x027C, 0x0280, 0x0284, 0x0288, - 0x028C, 0x0290, 0x0294, 0x0298, 0x029C, 0x02A0, 0x02A4, 0x02A8, - 0x02AC, 0x02B0, 0x02B4, 0x02B8, 0x02BC, 0x02C0, 0x02C4, 0x0000, - // Block 6 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x02CA, 0x02CE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02D2, - 0x02D6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02FB, 0x02FF, 0x0303, - 0x0307, 0x030B, 0x030F, 0x0313, 0x0317, 0x031B, 0x0321, 0x0327, - 0x032D, 0x0333, 0x0339, 0x033F, 0x0345, 0x0000, 0x034B, 0x0351, - 0x0357, 0x035D, 0x0363, 0x0368, 0x0000, 0x0000, 0x036D, 0x0371, - 0x0375, 0x0379, 0x037D, 0x0381, 0x0385, 0x038B, 0x0391, 0x0396, - 0x039B, 0x0000, 0x0000, 0x0000, 0x03A8, 0x03AC, 0x0000, 0x0000, - 0x03B0, 0x03B4, 0x03B8, 0x03BE, 0x03C4, 0x03C9, 0x03CE, 0x03D3, - // Block 8 - 0x03D8, 0x03DC, 0x03E0, 0x03E4, 0x03E8, 0x03EC, 0x03F0, 0x03F4, - 0x03F8, 0x03FC, 0x0400, 0x0404, 0x0408, 0x040C, 0x0410, 0x0414, - 0x0418, 0x041C, 0x0420, 0x0424, 0x0428, 0x042C, 0x0430, 0x0434, - 0x0438, 0x043C, 0x0440, 0x0444, 0x0000, 0x0000, 0x0448, 0x044C, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0450, 0x0454, - 0x0458, 0x045C, 0x0460, 0x0466, 0x046C, 0x0472, 0x0478, 0x047C, - 0x0480, 0x0486, 0x048C, 0x0490, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 9 - 0x04CC, 0x04CF, 0x0000, 0x04D2, 0x04D5, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x04DA, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x04E1, 0x0000, - // Block A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x04E3, 0x04EE, 0x04F3, - 0x04F6, 0x04FB, 0x0500, 0x0000, 0x0505, 0x0000, 0x050A, 0x050F, - 0x0514, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x051B, 0x0520, 0x0525, 0x052A, 0x052F, 0x0534, - 0x0539, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0540, 0x0545, 0x054A, 0x054F, 0x0554, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0562, 0x0567, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block C - 0x0584, 0x0589, 0x0000, 0x058E, 0x0000, 0x0000, 0x0000, 0x0593, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0598, 0x059D, 0x05A2, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x05A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x05AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x05B1, 0x05B6, 0x0000, 0x05BB, 0x0000, 0x0000, 0x0000, 0x05C0, - 0x0000, 0x0000, 0x0000, 0x0000, 0x05C5, 0x05CA, 0x05CF, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x05D4, 0x05D9, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block E - 0x0000, 0x05DE, 0x05E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x05E8, 0x05ED, 0x05F2, 0x05F7, 0x0000, 0x0000, 0x05FC, 0x0601, - 0x0000, 0x0000, 0x0606, 0x060B, 0x0610, 0x0615, 0x061A, 0x061F, - 0x0000, 0x0000, 0x0624, 0x0629, 0x062E, 0x0633, 0x0638, 0x063D, - 0x0000, 0x0000, 0x0642, 0x0647, 0x064C, 0x0651, 0x0656, 0x065B, - 0x0660, 0x0665, 0x066A, 0x066F, 0x0674, 0x0679, 0x0000, 0x0000, - 0x067E, 0x0683, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x068D, 0x0692, 0x0697, 0x069C, 0x06A1, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 10 - 0x06BA, 0x0000, 0x06BF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x06C4, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 11 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x06C9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x06D0, 0x0000, 0x0000, 0x06D7, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 12 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x06DE, 0x06E5, 0x06EC, 0x06F3, 0x06FA, 0x0701, 0x0708, 0x070F, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 13 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0716, 0x071D, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0724, 0x072B, 0x0000, 0x0732, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 14 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0739, 0x0000, 0x0000, 0x0740, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 15 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0747, 0x074E, 0x0755, 0x0000, 0x0000, 0x075C, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 16 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0763, 0x0000, 0x0000, 0x076A, 0x0771, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0778, 0x077F, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 17 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0786, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 18 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x078D, 0x0794, 0x079B, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 19 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x07A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1A - 0x07A9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07B0, - 0x07B7, 0x0000, 0x07BE, 0x07C5, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x07CF, 0x07D6, 0x07DD, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x07E4, 0x0000, 0x07EB, 0x07F2, 0x07FC, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1D - 0x0000, 0x0000, 0x0000, 0x0823, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x082A, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0831, 0x0000, 0x0000, 0x0000, 0x0000, 0x0838, - 0x0000, 0x0000, 0x0000, 0x0000, 0x083F, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0846, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x084D, 0x0000, 0x0854, 0x085B, 0x0000, - 0x086C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1E - 0x0000, 0x087D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0884, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x088B, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0892, 0x0000, 0x0000, 0x0000, 0x0000, 0x0899, - 0x0000, 0x0000, 0x0000, 0x0000, 0x08A0, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x08A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x08AE, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 20 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x08B9, 0x0000, - 0x08C0, 0x0000, 0x08C7, 0x0000, 0x08CE, 0x0000, 0x08D5, 0x0000, - 0x0000, 0x0000, 0x08DC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x08E3, 0x0000, 0x08EA, 0x0000, 0x0000, - // Block 21 - 0x08F1, 0x08F8, 0x0000, 0x08FF, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 22 - 0x09EA, 0x09EE, 0x09F2, 0x09F6, 0x09FA, 0x09FE, 0x0A02, 0x0A06, - 0x0A0A, 0x0A10, 0x0A16, 0x0A1A, 0x0A1E, 0x0A22, 0x0A26, 0x0A2A, - 0x0A2E, 0x0A32, 0x0A36, 0x0A3A, 0x0A3E, 0x0A44, 0x0A4A, 0x0A50, - 0x0A56, 0x0A5A, 0x0A5E, 0x0A62, 0x0A66, 0x0A6C, 0x0A72, 0x0A76, - 0x0A7A, 0x0A7E, 0x0A82, 0x0A86, 0x0A8A, 0x0A8E, 0x0A92, 0x0A96, - 0x0A9A, 0x0A9E, 0x0AA2, 0x0AA6, 0x0AAA, 0x0AAE, 0x0AB2, 0x0AB8, - 0x0ABE, 0x0AC2, 0x0AC6, 0x0ACA, 0x0ACE, 0x0AD2, 0x0AD6, 0x0ADA, - 0x0ADE, 0x0AE4, 0x0AEA, 0x0AEE, 0x0AF2, 0x0AF6, 0x0AFA, 0x0AFE, - // Block 23 - 0x0B02, 0x0B06, 0x0B0A, 0x0B0E, 0x0B12, 0x0B16, 0x0B1A, 0x0B1E, - 0x0B22, 0x0B26, 0x0B2A, 0x0B2E, 0x0B32, 0x0B38, 0x0B3E, 0x0B44, - 0x0B4A, 0x0B50, 0x0B56, 0x0B5C, 0x0B62, 0x0B66, 0x0B6A, 0x0B6E, - 0x0B72, 0x0B76, 0x0B7A, 0x0B7E, 0x0B82, 0x0B88, 0x0B8E, 0x0B92, - 0x0B96, 0x0B9A, 0x0B9E, 0x0BA2, 0x0BA6, 0x0BAC, 0x0BB2, 0x0BB8, - 0x0BBE, 0x0BC4, 0x0BCA, 0x0BCE, 0x0BD2, 0x0BD6, 0x0BDA, 0x0BDE, - 0x0BE2, 0x0BE6, 0x0BEA, 0x0BEE, 0x0BF2, 0x0BF6, 0x0BFA, 0x0BFE, - 0x0C02, 0x0C08, 0x0C0E, 0x0C14, 0x0C1A, 0x0C1E, 0x0C22, 0x0C26, - // Block 24 - 0x0C2A, 0x0C2E, 0x0C32, 0x0C36, 0x0C3A, 0x0C3E, 0x0C42, 0x0C46, - 0x0C4A, 0x0C4E, 0x0C52, 0x0C56, 0x0C5A, 0x0C5E, 0x0C62, 0x0C66, - 0x0C6A, 0x0C6E, 0x0C72, 0x0C76, 0x0C7A, 0x0C7E, 0x0C82, 0x0C86, - 0x0C8A, 0x0C8E, 0x0000, 0x0C96, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0C9B, 0x0C9F, 0x0CA3, 0x0CA7, 0x0CAB, 0x0CB1, 0x0CB7, 0x0CBD, - 0x0CC3, 0x0CC9, 0x0CCF, 0x0CD5, 0x0CDB, 0x0CE1, 0x0CE7, 0x0CED, - 0x0CF3, 0x0CF9, 0x0CFF, 0x0D05, 0x0D0B, 0x0D11, 0x0D17, 0x0D1D, - 0x0D23, 0x0D27, 0x0D2B, 0x0D2F, 0x0D33, 0x0D37, 0x0D3B, 0x0D41, - // Block 25 - 0x0D47, 0x0D4D, 0x0D53, 0x0D59, 0x0D5F, 0x0D65, 0x0D6B, 0x0D71, - 0x0D77, 0x0D7B, 0x0D7F, 0x0D83, 0x0D87, 0x0D8B, 0x0D8F, 0x0D93, - 0x0D97, 0x0D9D, 0x0DA3, 0x0DA9, 0x0DAF, 0x0DB5, 0x0DBB, 0x0DC1, - 0x0DC7, 0x0DCD, 0x0DD3, 0x0DD9, 0x0DDF, 0x0DE5, 0x0DEB, 0x0DF1, - 0x0DF7, 0x0DFD, 0x0E03, 0x0E09, 0x0E0F, 0x0E13, 0x0E17, 0x0E1B, - 0x0E1F, 0x0E25, 0x0E2B, 0x0E31, 0x0E37, 0x0E3D, 0x0E43, 0x0E49, - 0x0E4F, 0x0E55, 0x0E5B, 0x0E5F, 0x0E63, 0x0E67, 0x0E6B, 0x0E6F, - 0x0E73, 0x0E77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 26 - 0x0E7B, 0x0E80, 0x0E85, 0x0E8C, 0x0E93, 0x0E9A, 0x0EA1, 0x0EA8, - 0x0EAF, 0x0EB4, 0x0EB9, 0x0EC0, 0x0EC7, 0x0ECE, 0x0ED5, 0x0EDC, - 0x0EE3, 0x0EE8, 0x0EED, 0x0EF4, 0x0EFB, 0x0F02, 0x0000, 0x0000, - 0x0F09, 0x0F0E, 0x0F13, 0x0F1A, 0x0F21, 0x0F28, 0x0000, 0x0000, - 0x0F2F, 0x0F34, 0x0F39, 0x0F40, 0x0F47, 0x0F4E, 0x0F55, 0x0F5C, - 0x0F63, 0x0F68, 0x0F6D, 0x0F74, 0x0F7B, 0x0F82, 0x0F89, 0x0F90, - 0x0F97, 0x0F9C, 0x0FA1, 0x0FA8, 0x0FAF, 0x0FB6, 0x0FBD, 0x0FC4, - 0x0FCB, 0x0FD0, 0x0FD5, 0x0FDC, 0x0FE3, 0x0FEA, 0x0FF1, 0x0FF8, - // Block 27 - 0x0FFF, 0x1004, 0x1009, 0x1010, 0x1017, 0x101E, 0x0000, 0x0000, - 0x1025, 0x102A, 0x102F, 0x1036, 0x103D, 0x1044, 0x0000, 0x0000, - 0x104B, 0x1050, 0x1055, 0x105C, 0x1063, 0x106A, 0x1071, 0x1078, - 0x0000, 0x107F, 0x0000, 0x1084, 0x0000, 0x108B, 0x0000, 0x1092, - 0x1099, 0x109E, 0x10A3, 0x10AA, 0x10B1, 0x10B8, 0x10BF, 0x10C6, - 0x10CD, 0x10D2, 0x10D7, 0x10DE, 0x10E5, 0x10EC, 0x10F3, 0x10FA, - 0x1101, 0x0525, 0x1106, 0x052A, 0x110B, 0x052F, 0x1110, 0x0534, - 0x1115, 0x054A, 0x111A, 0x054F, 0x111F, 0x0554, 0x0000, 0x0000, - // Block 28 - 0x1124, 0x112B, 0x1132, 0x113B, 0x1144, 0x114D, 0x1156, 0x115F, - 0x1168, 0x116F, 0x1176, 0x117F, 0x1188, 0x1191, 0x119A, 0x11A3, - 0x11AC, 0x11B3, 0x11BA, 0x11C3, 0x11CC, 0x11D5, 0x11DE, 0x11E7, - 0x11F0, 0x11F7, 0x11FE, 0x1207, 0x1210, 0x1219, 0x1222, 0x122B, - 0x1234, 0x123B, 0x1242, 0x124B, 0x1254, 0x125D, 0x1266, 0x126F, - 0x1278, 0x127F, 0x1286, 0x128F, 0x1298, 0x12A1, 0x12AA, 0x12B3, - 0x12BC, 0x12C1, 0x12C6, 0x12CD, 0x12D2, 0x0000, 0x12D9, 0x12DE, - 0x12E5, 0x12EA, 0x12EF, 0x04EE, 0x12F4, 0x0000, 0x12FD, 0x0000, - // Block 29 - 0x0000, 0x1304, 0x130F, 0x1316, 0x131B, 0x0000, 0x1322, 0x1327, - 0x132E, 0x04F6, 0x1333, 0x04FB, 0x1338, 0x133D, 0x1349, 0x1355, - 0x1361, 0x1366, 0x136B, 0x0514, 0x0000, 0x0000, 0x1372, 0x1377, - 0x137E, 0x1383, 0x1388, 0x0500, 0x0000, 0x138D, 0x1399, 0x13A5, - 0x13B1, 0x13B6, 0x13BB, 0x0539, 0x13C2, 0x13C7, 0x13CC, 0x13D1, - 0x13D8, 0x13DD, 0x13E2, 0x050A, 0x13E7, 0x13EC, 0x04E3, 0x13F7, - 0x0000, 0x0000, 0x13F9, 0x1400, 0x1405, 0x0000, 0x140C, 0x1411, - 0x1418, 0x0505, 0x141D, 0x050F, 0x1422, 0x1427, 0x0000, 0x0000, - // Block 2A - 0x142E, 0x1432, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x14D6, 0x0000, - 0x0000, 0x0000, 0x091C, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x159F, 0x15A5, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x15AB, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x15B1, 0x15B7, 0x15BD, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2E - 0x0000, 0x0000, 0x0000, 0x0000, 0x15C3, 0x0000, 0x0000, 0x0000, - 0x0000, 0x15C9, 0x0000, 0x0000, 0x15CF, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x15D5, 0x0000, 0x15DB, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2F - 0x0000, 0x1603, 0x0000, 0x0000, 0x1609, 0x0000, 0x0000, 0x160F, - 0x0000, 0x1615, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x161B, 0x0000, 0x161F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1625, 0x162B, 0x162F, - 0x1633, 0x1639, 0x0000, 0x0000, 0x163F, 0x1645, 0x0000, 0x0000, - 0x164B, 0x1651, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 30 - 0x1657, 0x165D, 0x0000, 0x0000, 0x1663, 0x1669, 0x0000, 0x0000, - 0x166F, 0x1675, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x167B, 0x1681, 0x1687, 0x168D, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 31 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1693, 0x1699, 0x169F, 0x16A5, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x16AB, 0x16B1, 0x16B7, 0x16BD, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 32 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x16C3, 0x16C7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 33 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1814, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 34 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1B8A, 0x0000, 0x1B91, 0x0000, - 0x1B98, 0x0000, 0x1B9F, 0x0000, 0x1BA6, 0x0000, 0x1BAD, 0x0000, - 0x1BB4, 0x0000, 0x1BBB, 0x0000, 0x1BC2, 0x0000, 0x1BC9, 0x0000, - 0x1BD0, 0x0000, 0x1BD7, 0x0000, 0x0000, 0x1BDE, 0x0000, 0x1BE5, - 0x0000, 0x1BEC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1BF3, 0x1BFA, 0x0000, 0x1C01, 0x1C08, 0x0000, 0x1C0F, 0x1C16, - 0x0000, 0x1C1D, 0x1C24, 0x0000, 0x1C2B, 0x1C32, 0x0000, 0x0000, - // Block 35 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1C39, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C4A, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1C58, 0x0000, 0x1C5F, 0x0000, - 0x1C66, 0x0000, 0x1C6D, 0x0000, 0x1C74, 0x0000, 0x1C7B, 0x0000, - 0x1C82, 0x0000, 0x1C89, 0x0000, 0x1C90, 0x0000, 0x1C97, 0x0000, - // Block 36 - 0x1C9E, 0x0000, 0x1CA5, 0x0000, 0x0000, 0x1CAC, 0x0000, 0x1CB3, - 0x0000, 0x1CBA, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1CC1, 0x1CC8, 0x0000, 0x1CCF, 0x1CD6, 0x0000, 0x1CDD, 0x1CE4, - 0x0000, 0x1CEB, 0x1CF2, 0x0000, 0x1CF9, 0x1D00, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1D07, 0x0000, 0x0000, 0x1D0E, - 0x1D15, 0x1D1C, 0x1D23, 0x0000, 0x0000, 0x0000, 0x1D2A, 0x0000, - // Block 37 - 0x2A81, 0x2A85, 0x1A9E, 0x2A89, 0x2A8D, 0x2A91, 0x2A95, 0x1B76, - 0x1B76, 0x2A99, 0x1ABE, 0x2A9D, 0x2AA1, 0x2AA5, 0x2AA9, 0x2AAD, - 0x2AB1, 0x2AB5, 0x2AB9, 0x2ABD, 0x2AC1, 0x2AC5, 0x2AC9, 0x2ACD, - 0x2AD1, 0x2AD5, 0x2AD9, 0x2ADD, 0x2AE1, 0x2AE5, 0x2AE9, 0x2AED, - 0x2AF1, 0x2AF5, 0x2AF9, 0x2AFD, 0x2B01, 0x2B05, 0x2B09, 0x2B0D, - 0x2B11, 0x2B15, 0x2B19, 0x2B1D, 0x2B21, 0x2B25, 0x2B29, 0x2B2D, - 0x2B31, 0x2B35, 0x2B39, 0x2B3D, 0x1A16, 0x2B41, 0x2B45, 0x2B49, - 0x2B4D, 0x2B51, 0x2B55, 0x2B59, 0x2B5D, 0x2B61, 0x2B65, 0x2B69, - // Block 38 - 0x1B3A, 0x2B6D, 0x2B71, 0x2B75, 0x2B79, 0x2B7D, 0x2B81, 0x2B85, - 0x2B89, 0x2B8D, 0x2B91, 0x2B95, 0x2B99, 0x2B9D, 0x2BA1, 0x2BA5, - 0x2BA9, 0x2BAD, 0x2BB1, 0x2BB5, 0x2BB9, 0x2BBD, 0x2BC1, 0x2BC5, - 0x2BC9, 0x2BCD, 0x2BD1, 0x2BD5, 0x2AC1, 0x2BD9, 0x2BDD, 0x2BE1, - 0x2BE5, 0x2BE9, 0x2BED, 0x2BF1, 0x2BF5, 0x2BF9, 0x2BFD, 0x2C01, - 0x2C05, 0x2C09, 0x2C0D, 0x2C11, 0x2C15, 0x2C19, 0x2C1D, 0x2C21, - 0x2C25, 0x1AA6, 0x2C29, 0x2C2D, 0x2C31, 0x2C35, 0x2C39, 0x2C3D, - 0x2C41, 0x2C45, 0x2C49, 0x2C4D, 0x2C51, 0x2C55, 0x2C59, 0x2C5D, - // Block 39 - 0x2C61, 0x18BA, 0x2C65, 0x2C69, 0x2C6D, 0x2C71, 0x2C75, 0x2C79, - 0x2C7D, 0x2C81, 0x186E, 0x2C85, 0x2C89, 0x2C8D, 0x2C91, 0x2C95, - 0x2C99, 0x2C9D, 0x2CA1, 0x2CA5, 0x2CA9, 0x2CAD, 0x2CB1, 0x2CB5, - 0x2CB9, 0x2CBD, 0x2CC1, 0x2CC5, 0x2CC9, 0x2CCD, 0x2CD1, 0x2CD5, - 0x2CD9, 0x2C21, 0x2CDD, 0x2CE1, 0x2CE5, 0x2CE9, 0x2CED, 0x2CF1, - 0x2CF5, 0x2CF9, 0x2BE1, 0x2CFD, 0x2D01, 0x2D05, 0x2D09, 0x2D0D, - 0x2D11, 0x2D15, 0x2D19, 0x2D1D, 0x2D21, 0x2D25, 0x2D29, 0x2D2D, - 0x2D31, 0x2D35, 0x2D39, 0x2D3D, 0x2D41, 0x2D45, 0x2D49, 0x2AC1, - // Block 3A - 0x2D4D, 0x2D51, 0x2D55, 0x2D59, 0x1B72, 0x2D5D, 0x2D61, 0x2D65, - 0x2D69, 0x2D6D, 0x2D71, 0x2D75, 0x2D79, 0x2D7D, 0x2D81, 0x2D85, - 0x2D89, 0x2173, 0x2D8D, 0x2D91, 0x2D95, 0x2D99, 0x2D9D, 0x2DA1, - 0x2DA5, 0x2DA9, 0x2DAD, 0x2BE9, 0x2DB1, 0x2DB5, 0x2DB9, 0x2DBD, - 0x2DC1, 0x2DC5, 0x2DC9, 0x2DCD, 0x2DD1, 0x2DD5, 0x2DD9, 0x2DDD, - 0x2DE1, 0x1ABA, 0x2DE5, 0x2DE9, 0x2DED, 0x2DF1, 0x2DF5, 0x2DF9, - 0x2DFD, 0x2E01, 0x2E05, 0x2E09, 0x2E0D, 0x2E11, 0x2E15, 0x19F6, - 0x2E19, 0x2E1D, 0x2E21, 0x2E25, 0x2E29, 0x2E2D, 0x2E31, 0x2E35, - // Block 3B - 0x2E39, 0x2E3D, 0x2E41, 0x2E45, 0x2E49, 0x2E4D, 0x2E51, 0x2E55, - 0x1A62, 0x2E59, 0x1A6E, 0x2E5D, 0x2E61, 0x2E65, 0x0000, 0x0000, - 0x2E69, 0x0000, 0x2E6D, 0x0000, 0x0000, 0x2E71, 0x2E75, 0x2E79, - 0x2E7D, 0x2E81, 0x2E85, 0x2E89, 0x2E8D, 0x2E91, 0x1A12, 0x0000, - 0x2E95, 0x0000, 0x2E99, 0x0000, 0x0000, 0x2E9D, 0x2EA1, 0x0000, - 0x0000, 0x0000, 0x2EA5, 0x2EA9, 0x2EAD, 0x2EB1, 0x0000, 0x0000, - 0x2EB5, 0x2EB9, 0x2EBD, 0x2EC1, 0x2EC5, 0x2EC9, 0x2ECD, 0x2ED1, - 0x2ED5, 0x2ED9, 0x2EDD, 0x2EE1, 0x18D6, 0x2EE5, 0x2EE9, 0x2EED, - // Block 3C - 0x2EF1, 0x2EF5, 0x2EF9, 0x2EFD, 0x2F01, 0x2F05, 0x2F09, 0x2F0D, - 0x2F11, 0x2F15, 0x2F19, 0x2F1D, 0x2187, 0x2F21, 0x2F25, 0x2F29, - 0x2F2D, 0x2197, 0x2F31, 0x2F35, 0x2F39, 0x2F3D, 0x2F41, 0x2CB1, - 0x2F45, 0x2F49, 0x2F4D, 0x2F51, 0x2F55, 0x2F59, 0x2F59, 0x2F5D, - 0x2F61, 0x2F65, 0x2F69, 0x2F6D, 0x2F71, 0x2F75, 0x2F79, 0x2E9D, - 0x2F7D, 0x2F81, 0x2F85, 0x2F89, 0x2F8D, 0x2F92, 0x0000, 0x0000, - 0x2F96, 0x2F9A, 0x2F9E, 0x2FA2, 0x2FA6, 0x2FAA, 0x2FAE, 0x2FB2, - 0x2ECD, 0x2FB6, 0x2FBA, 0x2FBE, 0x2E69, 0x2FC2, 0x2FC6, 0x2FCA, - // Block 3D - 0x2FCE, 0x2FD2, 0x2FD6, 0x2FDA, 0x2FDE, 0x2FE2, 0x2FE6, 0x2FEA, - 0x2FEE, 0x2EED, 0x2FF2, 0x2EF1, 0x2FF6, 0x2FFA, 0x2FFE, 0x3002, - 0x3006, 0x2E6D, 0x2B15, 0x300A, 0x300E, 0x195A, 0x2C25, 0x2D71, - 0x3012, 0x3016, 0x2F0D, 0x301A, 0x2F11, 0x301E, 0x3022, 0x3026, - 0x2E75, 0x302A, 0x302E, 0x3032, 0x3036, 0x303A, 0x2E79, 0x303E, - 0x3042, 0x3046, 0x304A, 0x304E, 0x3052, 0x2F41, 0x3056, 0x305A, - 0x2CB1, 0x305E, 0x2F51, 0x3062, 0x3066, 0x306A, 0x306E, 0x3072, - 0x2F65, 0x3076, 0x2E99, 0x307A, 0x2F69, 0x2BD9, 0x307E, 0x2F6D, - // Block 3E - 0x3082, 0x2F75, 0x3086, 0x308A, 0x308E, 0x3092, 0x3096, 0x2F7D, - 0x2E8D, 0x309A, 0x2F81, 0x309E, 0x2F85, 0x30A2, 0x1B76, 0x30A6, - 0x30AB, 0x30B0, 0x30B5, 0x30B9, 0x30BD, 0x30C1, 0x30C6, 0x30CB, - 0x30D0, 0x30D4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3105, 0x0000, 0x310A, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x3124, 0x3129, 0x312E, 0x3135, 0x313C, 0x3141, - 0x3146, 0x314B, 0x3150, 0x3155, 0x315A, 0x315F, 0x3164, 0x0000, - 0x3169, 0x316E, 0x3173, 0x3178, 0x317D, 0x0000, 0x3182, 0x0000, - // Block 40 - 0x3187, 0x318C, 0x0000, 0x3191, 0x3196, 0x0000, 0x319B, 0x31A0, - 0x31A5, 0x31AA, 0x31AF, 0x31B4, 0x31B9, 0x31BE, 0x31C3, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 41 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x3A73, 0x0000, 0x3A7C, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3A85, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 42 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3A8E, 0x3A97, - 0x3AA0, 0x3AAD, 0x3ABA, 0x3AC7, 0x3AD4, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 43 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3AE1, 0x3AEA, 0x3AF3, 0x3B00, 0x3B0D, - // Block 44 - 0x3B1A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 45 - 0x3D23, 0x3D27, 0x3D2B, 0x3D2F, 0x3D34, 0x2EB5, 0x3D38, 0x3D3C, - 0x3D40, 0x3D44, 0x2EB9, 0x3D48, 0x3D4C, 0x3D50, 0x2EBD, 0x3D55, - 0x3D59, 0x3D5D, 0x3D61, 0x3D66, 0x3D6A, 0x3C71, 0x3D6E, 0x3D73, - 0x3D77, 0x3D7B, 0x3D7F, 0x2F9A, 0x3D83, 0x1866, 0x3D88, 0x3D8C, - 0x3D90, 0x3D94, 0x3CB9, 0x3D98, 0x3D9C, 0x2FAE, 0x2EC1, 0x2EC5, - 0x2FB2, 0x3DA0, 0x3DA4, 0x2BF1, 0x3DA8, 0x2EC9, 0x3DAC, 0x3DB0, - 0x3DB4, 0x3DB8, 0x3DB8, 0x3DB8, 0x3DBC, 0x3DC1, 0x3DC5, 0x3DC9, - 0x3DCD, 0x3DD2, 0x3DD6, 0x3DDA, 0x3DDE, 0x3DE2, 0x3DE6, 0x3DEA, - // Block 46 - 0x3DEE, 0x3DF2, 0x3DF6, 0x3DFA, 0x3DFE, 0x3E02, 0x3E02, 0x2FBA, - 0x3E06, 0x3E0A, 0x3E0E, 0x3E12, 0x2ED1, 0x3E16, 0x3E1A, 0x3E1E, - 0x2E39, 0x3E22, 0x3E26, 0x3E2A, 0x3E2E, 0x3E32, 0x3E36, 0x3E3A, - 0x3E3E, 0x3E42, 0x3E47, 0x3E4B, 0x3E4F, 0x3C55, 0x3E53, 0x3E57, - 0x3E5B, 0x3E60, 0x3E65, 0x3E69, 0x3E6D, 0x3E71, 0x3E75, 0x3E79, - 0x3E7D, 0x3E81, 0x3E85, 0x3E85, 0x3E89, 0x3E8E, 0x3E92, 0x2BE1, - 0x3E96, 0x3E9A, 0x3E9F, 0x3EA3, 0x3EA7, 0x18CE, 0x3EAB, 0x3EAF, - 0x18D6, 0x3EB3, 0x3EB7, 0x3EBB, 0x3EC0, 0x3EC4, 0x3EC9, 0x3ECD, - // Block 47 - 0x3ED1, 0x3ED5, 0x3ED9, 0x3EDD, 0x3EE1, 0x3EE5, 0x3EE9, 0x3EED, - 0x3EF1, 0x3EF5, 0x3EFA, 0x3EFE, 0x3F02, 0x3F06, 0x2B11, 0x3F0A, - 0x18FE, 0x3F0F, 0x3F0F, 0x3F14, 0x3F18, 0x3F18, 0x3F1C, 0x3F20, - 0x3F25, 0x3F2A, 0x3F2E, 0x3F32, 0x3F36, 0x3F3A, 0x3F3E, 0x3F42, - 0x3F46, 0x3F4A, 0x3F4E, 0x2EE5, 0x3F52, 0x3F57, 0x3F5B, 0x3F5F, - 0x2FEA, 0x3F5F, 0x3F63, 0x2EED, 0x3F67, 0x3F6B, 0x3F6F, 0x3F73, - 0x2EF1, 0x2AA5, 0x3F77, 0x3F7B, 0x3F7F, 0x3F83, 0x3F87, 0x3F8B, - 0x3F8F, 0x3F94, 0x3F98, 0x3F9C, 0x3FA0, 0x3FA4, 0x3FA8, 0x3FAD, - // Block 48 - 0x3FB1, 0x3FB5, 0x3FB9, 0x3FBD, 0x3FC1, 0x3FC5, 0x3FC9, 0x3FCD, - 0x2EF5, 0x3FD1, 0x3FD5, 0x3FDA, 0x3FDE, 0x3FE2, 0x3FE6, 0x2EFD, - 0x3FEA, 0x3FEE, 0x3FF2, 0x3FF6, 0x3FFA, 0x3FFE, 0x4002, 0x4006, - 0x2B15, 0x300A, 0x400A, 0x400E, 0x4012, 0x4016, 0x401B, 0x401F, - 0x4023, 0x4027, 0x2F01, 0x402B, 0x4030, 0x4034, 0x4038, 0x30B5, - 0x403C, 0x4040, 0x4044, 0x4048, 0x404C, 0x4051, 0x4055, 0x4059, - 0x405D, 0x4062, 0x4066, 0x406A, 0x406E, 0x2C25, 0x4072, 0x4076, - 0x407B, 0x4080, 0x4085, 0x4089, 0x408E, 0x4092, 0x4096, 0x409A, - // Block 49 - 0x409E, 0x2F05, 0x2D71, 0x40A2, 0x40A6, 0x40AA, 0x40AE, 0x40B3, - 0x40B7, 0x40BB, 0x40BF, 0x3016, 0x40C3, 0x40C7, 0x40CC, 0x40D0, - 0x40D4, 0x40D9, 0x40DE, 0x40E2, 0x301A, 0x40E6, 0x40EA, 0x40EE, - 0x40F2, 0x40F6, 0x40FA, 0x40FE, 0x4103, 0x4107, 0x410C, 0x4110, - 0x4115, 0x3022, 0x4119, 0x411D, 0x4122, 0x4126, 0x412A, 0x412F, - 0x4134, 0x4138, 0x413C, 0x4140, 0x4144, 0x4144, 0x4148, 0x414C, - 0x302A, 0x4150, 0x4154, 0x4158, 0x415C, 0x4160, 0x4165, 0x4169, - 0x2BED, 0x416E, 0x4173, 0x4177, 0x417C, 0x4181, 0x4186, 0x418A, - // Block 4A - 0x3042, 0x418E, 0x4193, 0x4198, 0x419D, 0x41A2, 0x41A6, 0x41A6, - 0x3046, 0x30BD, 0x41AA, 0x41AE, 0x41B2, 0x41B6, 0x41BB, 0x2B59, - 0x304E, 0x41BF, 0x41C3, 0x2F2D, 0x41C8, 0x41CD, 0x2E89, 0x41D2, - 0x41D6, 0x2F39, 0x41DA, 0x41DE, 0x41E2, 0x41E7, 0x41E7, 0x41EC, - 0x41F0, 0x41F4, 0x41F9, 0x41FD, 0x4201, 0x4205, 0x420A, 0x420E, - 0x4212, 0x4216, 0x421A, 0x421E, 0x4223, 0x4227, 0x422B, 0x422F, - 0x4233, 0x4237, 0x423B, 0x4240, 0x4245, 0x4249, 0x424E, 0x4252, - 0x4257, 0x425B, 0x2F51, 0x425F, 0x4264, 0x4269, 0x426D, 0x4272, - // Block 4B - 0x4276, 0x427B, 0x427F, 0x4283, 0x4287, 0x428B, 0x428F, 0x4293, - 0x4298, 0x429D, 0x42A2, 0x3F14, 0x42A7, 0x42AB, 0x42AF, 0x42B3, - 0x42B7, 0x42BB, 0x42BF, 0x42C3, 0x42C7, 0x42CB, 0x42CF, 0x42D3, - 0x2C31, 0x42D8, 0x42DC, 0x42E0, 0x42E4, 0x42E8, 0x42EC, 0x2F5D, - 0x42F0, 0x42F4, 0x42F8, 0x42FC, 0x4300, 0x4305, 0x430A, 0x430F, - 0x4313, 0x4317, 0x431B, 0x431F, 0x4324, 0x4328, 0x432D, 0x4331, - 0x4335, 0x433A, 0x433F, 0x4343, 0x2B45, 0x4347, 0x434B, 0x434F, - 0x4353, 0x4357, 0x435B, 0x306A, 0x435F, 0x4363, 0x4367, 0x436B, - // Block 4C - 0x436F, 0x4373, 0x4377, 0x437B, 0x1A66, 0x437F, 0x4384, 0x4388, - 0x438C, 0x4390, 0x4394, 0x4398, 0x439D, 0x43A2, 0x43A6, 0x43AA, - 0x307E, 0x3082, 0x1A82, 0x43AE, 0x43B3, 0x43B7, 0x43BB, 0x43BF, - 0x43C3, 0x43C8, 0x43CD, 0x43D1, 0x43D5, 0x43D9, 0x43DE, 0x3086, - 0x43E2, 0x43E7, 0x43EC, 0x43F0, 0x43F4, 0x43F8, 0x43FD, 0x4401, - 0x4405, 0x4409, 0x440D, 0x4411, 0x4415, 0x4419, 0x441E, 0x4422, - 0x4426, 0x442A, 0x442F, 0x4433, 0x4437, 0x443B, 0x443F, 0x4444, - 0x4449, 0x444D, 0x4451, 0x4455, 0x445A, 0x445E, 0x309E, 0x309E, - // Block 4D - 0x4463, 0x4467, 0x446C, 0x4470, 0x4474, 0x4478, 0x447C, 0x4480, - 0x4484, 0x4488, 0x30A2, 0x448D, 0x4491, 0x4495, 0x4499, 0x449D, - 0x44A1, 0x44A6, 0x44AA, 0x44AF, 0x44B4, 0x1B42, 0x44B9, 0x1B52, - 0x44BD, 0x44C1, 0x44C5, 0x44C9, 0x1B66, 0x44CD, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +var nfcDecompValues = [4992]uint16{ + // Block 0x0, offset 0x0 + // Block 0x1, offset 0x40 + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x00c0: 0x0032, 0x00c1: 0x0036, 0x00c2: 0x003a, 0x00c3: 0x003e, 0x00c4: 0x0042, 0x00c5: 0x0046, + 0x00c7: 0x004a, 0x00c8: 0x004e, 0x00c9: 0x0052, 0x00ca: 0x0056, 0x00cb: 0x005a, + 0x00cc: 0x005e, 0x00cd: 0x0062, 0x00ce: 0x0066, 0x00cf: 0x006a, 0x00d1: 0x006e, + 0x00d2: 0x0072, 0x00d3: 0x0076, 0x00d4: 0x007a, 0x00d5: 0x007e, 0x00d6: 0x0082, + 0x00d9: 0x0086, 0x00da: 0x008a, 0x00db: 0x008e, 0x00dc: 0x0092, 0x00dd: 0x0096, + 0x00e0: 0x009a, 0x00e1: 0x009e, 0x00e2: 0x00a2, 0x00e3: 0x00a6, + 0x00e4: 0x00aa, 0x00e5: 0x00ae, 0x00e7: 0x00b2, 0x00e8: 0x00b6, 0x00e9: 0x00ba, + 0x00ea: 0x00be, 0x00eb: 0x00c2, 0x00ec: 0x00c6, 0x00ed: 0x00ca, 0x00ee: 0x00ce, 0x00ef: 0x00d2, + 0x00f1: 0x00d6, 0x00f2: 0x00da, 0x00f3: 0x00de, 0x00f4: 0x00e2, 0x00f5: 0x00e6, + 0x00f6: 0x00ea, 0x00f9: 0x00ee, 0x00fa: 0x00f2, 0x00fb: 0x00f6, + 0x00fc: 0x00fa, 0x00fd: 0x00fe, 0x00ff: 0x0102, + // Block 0x4, offset 0x100 + 0x0100: 0x0106, 0x0101: 0x010a, 0x0102: 0x010e, 0x0103: 0x0112, 0x0104: 0x0116, 0x0105: 0x011a, + 0x0106: 0x011e, 0x0107: 0x0122, 0x0108: 0x0126, 0x0109: 0x012a, 0x010a: 0x012e, 0x010b: 0x0132, + 0x010c: 0x0136, 0x010d: 0x013a, 0x010e: 0x013e, 0x010f: 0x0142, + 0x0112: 0x0146, 0x0113: 0x014a, 0x0114: 0x014e, 0x0115: 0x0152, 0x0116: 0x0156, 0x0117: 0x015a, + 0x0118: 0x015e, 0x0119: 0x0162, 0x011a: 0x0166, 0x011b: 0x016a, 0x011c: 0x016e, 0x011d: 0x0172, + 0x011e: 0x0176, 0x011f: 0x017a, 0x0120: 0x017e, 0x0121: 0x0182, 0x0122: 0x0186, 0x0123: 0x018a, + 0x0124: 0x018e, 0x0125: 0x0192, 0x0128: 0x0196, 0x0129: 0x019a, + 0x012a: 0x019e, 0x012b: 0x01a2, 0x012c: 0x01a6, 0x012d: 0x01aa, 0x012e: 0x01ae, 0x012f: 0x01b2, + 0x0130: 0x01b6, 0x0134: 0x01c0, 0x0135: 0x01c4, + 0x0136: 0x01c8, 0x0137: 0x01cc, 0x0139: 0x01d0, 0x013a: 0x01d4, 0x013b: 0x01d8, + 0x013c: 0x01dc, 0x013d: 0x01e0, 0x013e: 0x01e4, + // Block 0x5, offset 0x140 + 0x0143: 0x01f0, 0x0144: 0x01f4, 0x0145: 0x01f8, + 0x0146: 0x01fc, 0x0147: 0x0200, 0x0148: 0x0204, + 0x014c: 0x020c, 0x014d: 0x0210, 0x014e: 0x0214, 0x014f: 0x0218, 0x0150: 0x021c, 0x0151: 0x0220, + 0x0154: 0x0224, 0x0155: 0x0228, 0x0156: 0x022c, 0x0157: 0x0230, + 0x0158: 0x0234, 0x0159: 0x0238, 0x015a: 0x023c, 0x015b: 0x0240, 0x015c: 0x0244, 0x015d: 0x0248, + 0x015e: 0x024c, 0x015f: 0x0250, 0x0160: 0x0254, 0x0161: 0x0258, 0x0162: 0x025c, 0x0163: 0x0260, + 0x0164: 0x0264, 0x0165: 0x0268, 0x0168: 0x026c, 0x0169: 0x0270, + 0x016a: 0x0274, 0x016b: 0x0278, 0x016c: 0x027c, 0x016d: 0x0280, 0x016e: 0x0284, 0x016f: 0x0288, + 0x0170: 0x028c, 0x0171: 0x0290, 0x0172: 0x0294, 0x0173: 0x0298, 0x0174: 0x029c, 0x0175: 0x02a0, + 0x0176: 0x02a4, 0x0177: 0x02a8, 0x0178: 0x02ac, 0x0179: 0x02b0, 0x017a: 0x02b4, 0x017b: 0x02b8, + 0x017c: 0x02bc, 0x017d: 0x02c0, 0x017e: 0x02c4, + // Block 0x6, offset 0x180 + 0x01a0: 0x02ca, 0x01a1: 0x02ce, + 0x01af: 0x02d2, + 0x01b0: 0x02d6, + // Block 0x7, offset 0x1c0 + 0x01cd: 0x02fb, 0x01ce: 0x02ff, 0x01cf: 0x0303, 0x01d0: 0x0307, 0x01d1: 0x030b, + 0x01d2: 0x030f, 0x01d3: 0x0313, 0x01d4: 0x0317, 0x01d5: 0x031b, 0x01d6: 0x0321, 0x01d7: 0x0327, + 0x01d8: 0x032d, 0x01d9: 0x0333, 0x01da: 0x0339, 0x01db: 0x033f, 0x01dc: 0x0345, + 0x01de: 0x034b, 0x01df: 0x0351, 0x01e0: 0x0357, 0x01e1: 0x035d, 0x01e2: 0x0363, 0x01e3: 0x0368, + 0x01e6: 0x036d, 0x01e7: 0x0371, 0x01e8: 0x0375, 0x01e9: 0x0379, + 0x01ea: 0x037d, 0x01eb: 0x0381, 0x01ec: 0x0385, 0x01ed: 0x038b, 0x01ee: 0x0391, 0x01ef: 0x0396, + 0x01f0: 0x039b, 0x01f4: 0x03a8, 0x01f5: 0x03ac, + 0x01f8: 0x03b0, 0x01f9: 0x03b4, 0x01fa: 0x03b8, 0x01fb: 0x03be, + 0x01fc: 0x03c4, 0x01fd: 0x03c9, 0x01fe: 0x03ce, 0x01ff: 0x03d3, + // Block 0x8, offset 0x200 + 0x0200: 0x03d8, 0x0201: 0x03dc, 0x0202: 0x03e0, 0x0203: 0x03e4, 0x0204: 0x03e8, 0x0205: 0x03ec, + 0x0206: 0x03f0, 0x0207: 0x03f4, 0x0208: 0x03f8, 0x0209: 0x03fc, 0x020a: 0x0400, 0x020b: 0x0404, + 0x020c: 0x0408, 0x020d: 0x040c, 0x020e: 0x0410, 0x020f: 0x0414, 0x0210: 0x0418, 0x0211: 0x041c, + 0x0212: 0x0420, 0x0213: 0x0424, 0x0214: 0x0428, 0x0215: 0x042c, 0x0216: 0x0430, 0x0217: 0x0434, + 0x0218: 0x0438, 0x0219: 0x043c, 0x021a: 0x0440, 0x021b: 0x0444, + 0x021e: 0x0448, 0x021f: 0x044c, + 0x0226: 0x0450, 0x0227: 0x0454, 0x0228: 0x0458, 0x0229: 0x045c, + 0x022a: 0x0460, 0x022b: 0x0466, 0x022c: 0x046c, 0x022d: 0x0472, 0x022e: 0x0478, 0x022f: 0x047c, + 0x0230: 0x0480, 0x0231: 0x0486, 0x0232: 0x048c, 0x0233: 0x0490, + // Block 0x9, offset 0x240 + 0x0240: 0x04cc, 0x0241: 0x04cf, 0x0243: 0x04d2, 0x0244: 0x04d5, + 0x0274: 0x04da, + 0x027e: 0x04e1, + // Block 0xa, offset 0x280 + 0x0285: 0x04e3, + 0x0286: 0x04ee, 0x0287: 0x04f3, 0x0288: 0x04f6, 0x0289: 0x04fb, 0x028a: 0x0500, + 0x028c: 0x0505, 0x028e: 0x050a, 0x028f: 0x050f, 0x0290: 0x0514, + 0x02aa: 0x051b, 0x02ab: 0x0520, 0x02ac: 0x0525, 0x02ad: 0x052a, 0x02ae: 0x052f, 0x02af: 0x0534, + 0x02b0: 0x0539, + // Block 0xb, offset 0x2c0 + 0x02ca: 0x0540, 0x02cb: 0x0545, + 0x02cc: 0x054a, 0x02cd: 0x054f, 0x02ce: 0x0554, + 0x02d3: 0x0562, 0x02d4: 0x0567, + // Block 0xc, offset 0x300 + 0x0300: 0x0584, 0x0301: 0x0589, 0x0303: 0x058e, + 0x0307: 0x0593, + 0x030c: 0x0598, 0x030d: 0x059d, 0x030e: 0x05a2, + 0x0319: 0x05a7, + 0x0339: 0x05ac, + // Block 0xd, offset 0x340 + 0x0350: 0x05b1, 0x0351: 0x05b6, + 0x0353: 0x05bb, 0x0357: 0x05c0, + 0x035c: 0x05c5, 0x035d: 0x05ca, + 0x035e: 0x05cf, + 0x0376: 0x05d4, 0x0377: 0x05d9, + // Block 0xe, offset 0x380 + 0x0381: 0x05de, 0x0382: 0x05e3, + 0x0390: 0x05e8, 0x0391: 0x05ed, + 0x0392: 0x05f2, 0x0393: 0x05f7, 0x0396: 0x05fc, 0x0397: 0x0601, + 0x039a: 0x0606, 0x039b: 0x060b, 0x039c: 0x0610, 0x039d: 0x0615, + 0x039e: 0x061a, 0x039f: 0x061f, 0x03a2: 0x0624, 0x03a3: 0x0629, + 0x03a4: 0x062e, 0x03a5: 0x0633, 0x03a6: 0x0638, 0x03a7: 0x063d, + 0x03aa: 0x0642, 0x03ab: 0x0647, 0x03ac: 0x064c, 0x03ad: 0x0651, 0x03ae: 0x0656, 0x03af: 0x065b, + 0x03b0: 0x0660, 0x03b1: 0x0665, 0x03b2: 0x066a, 0x03b3: 0x066f, 0x03b4: 0x0674, 0x03b5: 0x0679, + 0x03b8: 0x067e, 0x03b9: 0x0683, + // Block 0xf, offset 0x3c0 + 0x03e2: 0x068d, 0x03e3: 0x0692, + 0x03e4: 0x0697, 0x03e5: 0x069c, 0x03e6: 0x06a1, + // Block 0x10, offset 0x400 + 0x0400: 0x06ba, 0x0402: 0x06bf, + 0x0413: 0x06c4, + // Block 0x11, offset 0x440 + 0x0469: 0x06c9, + 0x0471: 0x06d0, 0x0474: 0x06d7, + // Block 0x12, offset 0x480 + 0x0498: 0x06de, 0x0499: 0x06e5, 0x049a: 0x06ec, 0x049b: 0x06f3, 0x049c: 0x06fa, 0x049d: 0x0701, + 0x049e: 0x0708, 0x049f: 0x070f, + // Block 0x13, offset 0x4c0 + 0x04cb: 0x0716, + 0x04cc: 0x071d, + 0x04dc: 0x0724, 0x04dd: 0x072b, + 0x04df: 0x0732, + // Block 0x14, offset 0x500 + 0x0533: 0x0739, + 0x0536: 0x0740, + // Block 0x15, offset 0x540 + 0x0559: 0x0747, 0x055a: 0x074e, 0x055b: 0x0755, + 0x055e: 0x075c, + // Block 0x16, offset 0x580 + 0x0588: 0x0763, 0x058b: 0x076a, + 0x058c: 0x0771, + 0x059c: 0x0778, 0x059d: 0x077f, + // Block 0x17, offset 0x5c0 + 0x05d4: 0x0786, + // Block 0x18, offset 0x600 + 0x060a: 0x078d, 0x060b: 0x0794, + 0x060c: 0x079b, + // Block 0x19, offset 0x640 + 0x0648: 0x07a2, + // Block 0x1a, offset 0x680 + 0x0680: 0x07a9, + 0x0687: 0x07b0, 0x0688: 0x07b7, 0x068a: 0x07be, 0x068b: 0x07c5, + // Block 0x1b, offset 0x6c0 + 0x06ca: 0x07cf, 0x06cb: 0x07d6, + 0x06cc: 0x07dd, + // Block 0x1c, offset 0x700 + 0x071a: 0x07e4, 0x071c: 0x07eb, 0x071d: 0x07f2, + 0x071e: 0x07fc, + // Block 0x1d, offset 0x740 + 0x0743: 0x0823, + 0x074d: 0x082a, + 0x0752: 0x0831, 0x0757: 0x0838, + 0x075c: 0x083f, + 0x0769: 0x0846, + 0x0773: 0x084d, 0x0775: 0x0854, + 0x0776: 0x085b, 0x0778: 0x086c, + // Block 0x1e, offset 0x780 + 0x0781: 0x087d, + 0x0793: 0x0884, + 0x079d: 0x088b, + 0x07a2: 0x0892, + 0x07a7: 0x0899, + 0x07ac: 0x08a0, + 0x07b9: 0x08a7, + // Block 0x1f, offset 0x7c0 + 0x07e6: 0x08ae, + // Block 0x20, offset 0x800 + 0x0806: 0x08b9, 0x0808: 0x08c0, 0x080a: 0x08c7, + 0x080c: 0x08ce, 0x080e: 0x08d5, + 0x0812: 0x08dc, + 0x083b: 0x08e3, + 0x083d: 0x08ea, + // Block 0x21, offset 0x840 + 0x0840: 0x08f1, 0x0841: 0x08f8, 0x0843: 0x08ff, + // Block 0x22, offset 0x880 + 0x0880: 0x09ea, 0x0881: 0x09ee, 0x0882: 0x09f2, 0x0883: 0x09f6, 0x0884: 0x09fa, 0x0885: 0x09fe, + 0x0886: 0x0a02, 0x0887: 0x0a06, 0x0888: 0x0a0a, 0x0889: 0x0a10, 0x088a: 0x0a16, 0x088b: 0x0a1a, + 0x088c: 0x0a1e, 0x088d: 0x0a22, 0x088e: 0x0a26, 0x088f: 0x0a2a, 0x0890: 0x0a2e, 0x0891: 0x0a32, + 0x0892: 0x0a36, 0x0893: 0x0a3a, 0x0894: 0x0a3e, 0x0895: 0x0a44, 0x0896: 0x0a4a, 0x0897: 0x0a50, + 0x0898: 0x0a56, 0x0899: 0x0a5a, 0x089a: 0x0a5e, 0x089b: 0x0a62, 0x089c: 0x0a66, 0x089d: 0x0a6c, + 0x089e: 0x0a72, 0x089f: 0x0a76, 0x08a0: 0x0a7a, 0x08a1: 0x0a7e, 0x08a2: 0x0a82, 0x08a3: 0x0a86, + 0x08a4: 0x0a8a, 0x08a5: 0x0a8e, 0x08a6: 0x0a92, 0x08a7: 0x0a96, 0x08a8: 0x0a9a, 0x08a9: 0x0a9e, + 0x08aa: 0x0aa2, 0x08ab: 0x0aa6, 0x08ac: 0x0aaa, 0x08ad: 0x0aae, 0x08ae: 0x0ab2, 0x08af: 0x0ab8, + 0x08b0: 0x0abe, 0x08b1: 0x0ac2, 0x08b2: 0x0ac6, 0x08b3: 0x0aca, 0x08b4: 0x0ace, 0x08b5: 0x0ad2, + 0x08b6: 0x0ad6, 0x08b7: 0x0ada, 0x08b8: 0x0ade, 0x08b9: 0x0ae4, 0x08ba: 0x0aea, 0x08bb: 0x0aee, + 0x08bc: 0x0af2, 0x08bd: 0x0af6, 0x08be: 0x0afa, 0x08bf: 0x0afe, + // Block 0x23, offset 0x8c0 + 0x08c0: 0x0b02, 0x08c1: 0x0b06, 0x08c2: 0x0b0a, 0x08c3: 0x0b0e, 0x08c4: 0x0b12, 0x08c5: 0x0b16, + 0x08c6: 0x0b1a, 0x08c7: 0x0b1e, 0x08c8: 0x0b22, 0x08c9: 0x0b26, 0x08ca: 0x0b2a, 0x08cb: 0x0b2e, + 0x08cc: 0x0b32, 0x08cd: 0x0b38, 0x08ce: 0x0b3e, 0x08cf: 0x0b44, 0x08d0: 0x0b4a, 0x08d1: 0x0b50, + 0x08d2: 0x0b56, 0x08d3: 0x0b5c, 0x08d4: 0x0b62, 0x08d5: 0x0b66, 0x08d6: 0x0b6a, 0x08d7: 0x0b6e, + 0x08d8: 0x0b72, 0x08d9: 0x0b76, 0x08da: 0x0b7a, 0x08db: 0x0b7e, 0x08dc: 0x0b82, 0x08dd: 0x0b88, + 0x08de: 0x0b8e, 0x08df: 0x0b92, 0x08e0: 0x0b96, 0x08e1: 0x0b9a, 0x08e2: 0x0b9e, 0x08e3: 0x0ba2, + 0x08e4: 0x0ba6, 0x08e5: 0x0bac, 0x08e6: 0x0bb2, 0x08e7: 0x0bb8, 0x08e8: 0x0bbe, 0x08e9: 0x0bc4, + 0x08ea: 0x0bca, 0x08eb: 0x0bce, 0x08ec: 0x0bd2, 0x08ed: 0x0bd6, 0x08ee: 0x0bda, 0x08ef: 0x0bde, + 0x08f0: 0x0be2, 0x08f1: 0x0be6, 0x08f2: 0x0bea, 0x08f3: 0x0bee, 0x08f4: 0x0bf2, 0x08f5: 0x0bf6, + 0x08f6: 0x0bfa, 0x08f7: 0x0bfe, 0x08f8: 0x0c02, 0x08f9: 0x0c08, 0x08fa: 0x0c0e, 0x08fb: 0x0c14, + 0x08fc: 0x0c1a, 0x08fd: 0x0c1e, 0x08fe: 0x0c22, 0x08ff: 0x0c26, + // Block 0x24, offset 0x900 + 0x0900: 0x0c2a, 0x0901: 0x0c2e, 0x0902: 0x0c32, 0x0903: 0x0c36, 0x0904: 0x0c3a, 0x0905: 0x0c3e, + 0x0906: 0x0c42, 0x0907: 0x0c46, 0x0908: 0x0c4a, 0x0909: 0x0c4e, 0x090a: 0x0c52, 0x090b: 0x0c56, + 0x090c: 0x0c5a, 0x090d: 0x0c5e, 0x090e: 0x0c62, 0x090f: 0x0c66, 0x0910: 0x0c6a, 0x0911: 0x0c6e, + 0x0912: 0x0c72, 0x0913: 0x0c76, 0x0914: 0x0c7a, 0x0915: 0x0c7e, 0x0916: 0x0c82, 0x0917: 0x0c86, + 0x0918: 0x0c8a, 0x0919: 0x0c8e, 0x091b: 0x0c96, + 0x0920: 0x0c9b, 0x0921: 0x0c9f, 0x0922: 0x0ca3, 0x0923: 0x0ca7, + 0x0924: 0x0cab, 0x0925: 0x0cb1, 0x0926: 0x0cb7, 0x0927: 0x0cbd, 0x0928: 0x0cc3, 0x0929: 0x0cc9, + 0x092a: 0x0ccf, 0x092b: 0x0cd5, 0x092c: 0x0cdb, 0x092d: 0x0ce1, 0x092e: 0x0ce7, 0x092f: 0x0ced, + 0x0930: 0x0cf3, 0x0931: 0x0cf9, 0x0932: 0x0cff, 0x0933: 0x0d05, 0x0934: 0x0d0b, 0x0935: 0x0d11, + 0x0936: 0x0d17, 0x0937: 0x0d1d, 0x0938: 0x0d23, 0x0939: 0x0d27, 0x093a: 0x0d2b, 0x093b: 0x0d2f, + 0x093c: 0x0d33, 0x093d: 0x0d37, 0x093e: 0x0d3b, 0x093f: 0x0d41, + // Block 0x25, offset 0x940 + 0x0940: 0x0d47, 0x0941: 0x0d4d, 0x0942: 0x0d53, 0x0943: 0x0d59, 0x0944: 0x0d5f, 0x0945: 0x0d65, + 0x0946: 0x0d6b, 0x0947: 0x0d71, 0x0948: 0x0d77, 0x0949: 0x0d7b, 0x094a: 0x0d7f, 0x094b: 0x0d83, + 0x094c: 0x0d87, 0x094d: 0x0d8b, 0x094e: 0x0d8f, 0x094f: 0x0d93, 0x0950: 0x0d97, 0x0951: 0x0d9d, + 0x0952: 0x0da3, 0x0953: 0x0da9, 0x0954: 0x0daf, 0x0955: 0x0db5, 0x0956: 0x0dbb, 0x0957: 0x0dc1, + 0x0958: 0x0dc7, 0x0959: 0x0dcd, 0x095a: 0x0dd3, 0x095b: 0x0dd9, 0x095c: 0x0ddf, 0x095d: 0x0de5, + 0x095e: 0x0deb, 0x095f: 0x0df1, 0x0960: 0x0df7, 0x0961: 0x0dfd, 0x0962: 0x0e03, 0x0963: 0x0e09, + 0x0964: 0x0e0f, 0x0965: 0x0e13, 0x0966: 0x0e17, 0x0967: 0x0e1b, 0x0968: 0x0e1f, 0x0969: 0x0e25, + 0x096a: 0x0e2b, 0x096b: 0x0e31, 0x096c: 0x0e37, 0x096d: 0x0e3d, 0x096e: 0x0e43, 0x096f: 0x0e49, + 0x0970: 0x0e4f, 0x0971: 0x0e55, 0x0972: 0x0e5b, 0x0973: 0x0e5f, 0x0974: 0x0e63, 0x0975: 0x0e67, + 0x0976: 0x0e6b, 0x0977: 0x0e6f, 0x0978: 0x0e73, 0x0979: 0x0e77, + // Block 0x26, offset 0x980 + 0x0980: 0x0e7b, 0x0981: 0x0e80, 0x0982: 0x0e85, 0x0983: 0x0e8c, 0x0984: 0x0e93, 0x0985: 0x0e9a, + 0x0986: 0x0ea1, 0x0987: 0x0ea8, 0x0988: 0x0eaf, 0x0989: 0x0eb4, 0x098a: 0x0eb9, 0x098b: 0x0ec0, + 0x098c: 0x0ec7, 0x098d: 0x0ece, 0x098e: 0x0ed5, 0x098f: 0x0edc, 0x0990: 0x0ee3, 0x0991: 0x0ee8, + 0x0992: 0x0eed, 0x0993: 0x0ef4, 0x0994: 0x0efb, 0x0995: 0x0f02, + 0x0998: 0x0f09, 0x0999: 0x0f0e, 0x099a: 0x0f13, 0x099b: 0x0f1a, 0x099c: 0x0f21, 0x099d: 0x0f28, + 0x09a0: 0x0f2f, 0x09a1: 0x0f34, 0x09a2: 0x0f39, 0x09a3: 0x0f40, + 0x09a4: 0x0f47, 0x09a5: 0x0f4e, 0x09a6: 0x0f55, 0x09a7: 0x0f5c, 0x09a8: 0x0f63, 0x09a9: 0x0f68, + 0x09aa: 0x0f6d, 0x09ab: 0x0f74, 0x09ac: 0x0f7b, 0x09ad: 0x0f82, 0x09ae: 0x0f89, 0x09af: 0x0f90, + 0x09b0: 0x0f97, 0x09b1: 0x0f9c, 0x09b2: 0x0fa1, 0x09b3: 0x0fa8, 0x09b4: 0x0faf, 0x09b5: 0x0fb6, + 0x09b6: 0x0fbd, 0x09b7: 0x0fc4, 0x09b8: 0x0fcb, 0x09b9: 0x0fd0, 0x09ba: 0x0fd5, 0x09bb: 0x0fdc, + 0x09bc: 0x0fe3, 0x09bd: 0x0fea, 0x09be: 0x0ff1, 0x09bf: 0x0ff8, + // Block 0x27, offset 0x9c0 + 0x09c0: 0x0fff, 0x09c1: 0x1004, 0x09c2: 0x1009, 0x09c3: 0x1010, 0x09c4: 0x1017, 0x09c5: 0x101e, + 0x09c8: 0x1025, 0x09c9: 0x102a, 0x09ca: 0x102f, 0x09cb: 0x1036, + 0x09cc: 0x103d, 0x09cd: 0x1044, 0x09d0: 0x104b, 0x09d1: 0x1050, + 0x09d2: 0x1055, 0x09d3: 0x105c, 0x09d4: 0x1063, 0x09d5: 0x106a, 0x09d6: 0x1071, 0x09d7: 0x1078, + 0x09d9: 0x107f, 0x09db: 0x1084, 0x09dd: 0x108b, + 0x09df: 0x1092, 0x09e0: 0x1099, 0x09e1: 0x109e, 0x09e2: 0x10a3, 0x09e3: 0x10aa, + 0x09e4: 0x10b1, 0x09e5: 0x10b8, 0x09e6: 0x10bf, 0x09e7: 0x10c6, 0x09e8: 0x10cd, 0x09e9: 0x10d2, + 0x09ea: 0x10d7, 0x09eb: 0x10de, 0x09ec: 0x10e5, 0x09ed: 0x10ec, 0x09ee: 0x10f3, 0x09ef: 0x10fa, + 0x09f0: 0x1101, 0x09f1: 0x0525, 0x09f2: 0x1106, 0x09f3: 0x052a, 0x09f4: 0x110b, 0x09f5: 0x052f, + 0x09f6: 0x1110, 0x09f7: 0x0534, 0x09f8: 0x1115, 0x09f9: 0x054a, 0x09fa: 0x111a, 0x09fb: 0x054f, + 0x09fc: 0x111f, 0x09fd: 0x0554, + // Block 0x28, offset 0xa00 + 0x0a00: 0x1124, 0x0a01: 0x112b, 0x0a02: 0x1132, 0x0a03: 0x113b, 0x0a04: 0x1144, 0x0a05: 0x114d, + 0x0a06: 0x1156, 0x0a07: 0x115f, 0x0a08: 0x1168, 0x0a09: 0x116f, 0x0a0a: 0x1176, 0x0a0b: 0x117f, + 0x0a0c: 0x1188, 0x0a0d: 0x1191, 0x0a0e: 0x119a, 0x0a0f: 0x11a3, 0x0a10: 0x11ac, 0x0a11: 0x11b3, + 0x0a12: 0x11ba, 0x0a13: 0x11c3, 0x0a14: 0x11cc, 0x0a15: 0x11d5, 0x0a16: 0x11de, 0x0a17: 0x11e7, + 0x0a18: 0x11f0, 0x0a19: 0x11f7, 0x0a1a: 0x11fe, 0x0a1b: 0x1207, 0x0a1c: 0x1210, 0x0a1d: 0x1219, + 0x0a1e: 0x1222, 0x0a1f: 0x122b, 0x0a20: 0x1234, 0x0a21: 0x123b, 0x0a22: 0x1242, 0x0a23: 0x124b, + 0x0a24: 0x1254, 0x0a25: 0x125d, 0x0a26: 0x1266, 0x0a27: 0x126f, 0x0a28: 0x1278, 0x0a29: 0x127f, + 0x0a2a: 0x1286, 0x0a2b: 0x128f, 0x0a2c: 0x1298, 0x0a2d: 0x12a1, 0x0a2e: 0x12aa, 0x0a2f: 0x12b3, + 0x0a30: 0x12bc, 0x0a31: 0x12c1, 0x0a32: 0x12c6, 0x0a33: 0x12cd, 0x0a34: 0x12d2, + 0x0a36: 0x12d9, 0x0a37: 0x12de, 0x0a38: 0x12e5, 0x0a39: 0x12ea, 0x0a3a: 0x12ef, 0x0a3b: 0x04ee, + 0x0a3c: 0x12f4, 0x0a3e: 0x12fd, + // Block 0x29, offset 0xa40 + 0x0a41: 0x1304, 0x0a42: 0x130f, 0x0a43: 0x1316, 0x0a44: 0x131b, + 0x0a46: 0x1322, 0x0a47: 0x1327, 0x0a48: 0x132e, 0x0a49: 0x04f6, 0x0a4a: 0x1333, 0x0a4b: 0x04fb, + 0x0a4c: 0x1338, 0x0a4d: 0x133d, 0x0a4e: 0x1349, 0x0a4f: 0x1355, 0x0a50: 0x1361, 0x0a51: 0x1366, + 0x0a52: 0x136b, 0x0a53: 0x0514, 0x0a56: 0x1372, 0x0a57: 0x1377, + 0x0a58: 0x137e, 0x0a59: 0x1383, 0x0a5a: 0x1388, 0x0a5b: 0x0500, 0x0a5d: 0x138d, + 0x0a5e: 0x1399, 0x0a5f: 0x13a5, 0x0a60: 0x13b1, 0x0a61: 0x13b6, 0x0a62: 0x13bb, 0x0a63: 0x0539, + 0x0a64: 0x13c2, 0x0a65: 0x13c7, 0x0a66: 0x13cc, 0x0a67: 0x13d1, 0x0a68: 0x13d8, 0x0a69: 0x13dd, + 0x0a6a: 0x13e2, 0x0a6b: 0x050a, 0x0a6c: 0x13e7, 0x0a6d: 0x13ec, 0x0a6e: 0x04e3, 0x0a6f: 0x13f7, + 0x0a72: 0x13f9, 0x0a73: 0x1400, 0x0a74: 0x1405, + 0x0a76: 0x140c, 0x0a77: 0x1411, 0x0a78: 0x1418, 0x0a79: 0x0505, 0x0a7a: 0x141d, 0x0a7b: 0x050f, + 0x0a7c: 0x1422, 0x0a7d: 0x1427, + // Block 0x2a, offset 0xa80 + 0x0a80: 0x142e, 0x0a81: 0x1432, + // Block 0x2b, offset 0xac0 + 0x0ae6: 0x14d6, + 0x0aea: 0x091c, 0x0aeb: 0x0046, + // Block 0x2c, offset 0xb00 + 0x0b1a: 0x159f, 0x0b1b: 0x15a5, + 0x0b2e: 0x15ab, + // Block 0x2d, offset 0xb40 + 0x0b4d: 0x15b1, 0x0b4e: 0x15b7, 0x0b4f: 0x15bd, + // Block 0x2e, offset 0xb80 + 0x0b84: 0x15c3, + 0x0b89: 0x15c9, + 0x0b8c: 0x15cf, + 0x0ba4: 0x15d5, 0x0ba6: 0x15db, + // Block 0x2f, offset 0xbc0 + 0x0bc1: 0x1603, 0x0bc4: 0x1609, + 0x0bc7: 0x160f, 0x0bc9: 0x1615, + 0x0be0: 0x161b, 0x0be2: 0x161f, + 0x0bed: 0x1625, 0x0bee: 0x162b, 0x0bef: 0x162f, + 0x0bf0: 0x1633, 0x0bf1: 0x1639, 0x0bf4: 0x163f, 0x0bf5: 0x1645, + 0x0bf8: 0x164b, 0x0bf9: 0x1651, + // Block 0x30, offset 0xc00 + 0x0c00: 0x1657, 0x0c01: 0x165d, 0x0c04: 0x1663, 0x0c05: 0x1669, + 0x0c08: 0x166f, 0x0c09: 0x1675, + 0x0c2c: 0x167b, 0x0c2d: 0x1681, 0x0c2e: 0x1687, 0x0c2f: 0x168d, + // Block 0x31, offset 0xc40 + 0x0c60: 0x1693, 0x0c61: 0x1699, 0x0c62: 0x169f, 0x0c63: 0x16a5, + 0x0c6a: 0x16ab, 0x0c6b: 0x16b1, 0x0c6c: 0x16b7, 0x0c6d: 0x16bd, + // Block 0x32, offset 0xc80 + 0x0ca9: 0x16c3, + 0x0caa: 0x16c7, + // Block 0x33, offset 0xcc0 + 0x0cdc: 0x1814, + // Block 0x34, offset 0xd00 + 0x0d0c: 0x1b8a, 0x0d0e: 0x1b91, 0x0d10: 0x1b98, + 0x0d12: 0x1b9f, 0x0d14: 0x1ba6, 0x0d16: 0x1bad, + 0x0d18: 0x1bb4, 0x0d1a: 0x1bbb, 0x0d1c: 0x1bc2, + 0x0d1e: 0x1bc9, 0x0d20: 0x1bd0, 0x0d22: 0x1bd7, + 0x0d25: 0x1bde, 0x0d27: 0x1be5, 0x0d29: 0x1bec, + 0x0d30: 0x1bf3, 0x0d31: 0x1bfa, 0x0d33: 0x1c01, 0x0d34: 0x1c08, + 0x0d36: 0x1c0f, 0x0d37: 0x1c16, 0x0d39: 0x1c1d, 0x0d3a: 0x1c24, + 0x0d3c: 0x1c2b, 0x0d3d: 0x1c32, + // Block 0x35, offset 0xd40 + 0x0d54: 0x1c39, + 0x0d5e: 0x1c4a, + 0x0d6c: 0x1c58, 0x0d6e: 0x1c5f, + 0x0d70: 0x1c66, 0x0d72: 0x1c6d, 0x0d74: 0x1c74, + 0x0d76: 0x1c7b, 0x0d78: 0x1c82, 0x0d7a: 0x1c89, + 0x0d7c: 0x1c90, 0x0d7e: 0x1c97, + // Block 0x36, offset 0xd80 + 0x0d80: 0x1c9e, 0x0d82: 0x1ca5, 0x0d85: 0x1cac, + 0x0d87: 0x1cb3, 0x0d89: 0x1cba, + 0x0d90: 0x1cc1, 0x0d91: 0x1cc8, + 0x0d93: 0x1ccf, 0x0d94: 0x1cd6, 0x0d96: 0x1cdd, 0x0d97: 0x1ce4, + 0x0d99: 0x1ceb, 0x0d9a: 0x1cf2, 0x0d9c: 0x1cf9, 0x0d9d: 0x1d00, + 0x0db4: 0x1d07, + 0x0db7: 0x1d0e, 0x0db8: 0x1d15, 0x0db9: 0x1d1c, 0x0dba: 0x1d23, + 0x0dbe: 0x1d2a, + // Block 0x37, offset 0xdc0 + 0x0dc0: 0x2a81, 0x0dc1: 0x2a85, 0x0dc2: 0x1a9e, 0x0dc3: 0x2a89, 0x0dc4: 0x2a8d, 0x0dc5: 0x2a91, + 0x0dc6: 0x2a95, 0x0dc7: 0x1b76, 0x0dc8: 0x1b76, 0x0dc9: 0x2a99, 0x0dca: 0x1abe, 0x0dcb: 0x2a9d, + 0x0dcc: 0x2aa1, 0x0dcd: 0x2aa5, 0x0dce: 0x2aa9, 0x0dcf: 0x2aad, 0x0dd0: 0x2ab1, 0x0dd1: 0x2ab5, + 0x0dd2: 0x2ab9, 0x0dd3: 0x2abd, 0x0dd4: 0x2ac1, 0x0dd5: 0x2ac5, 0x0dd6: 0x2ac9, 0x0dd7: 0x2acd, + 0x0dd8: 0x2ad1, 0x0dd9: 0x2ad5, 0x0dda: 0x2ad9, 0x0ddb: 0x2add, 0x0ddc: 0x2ae1, 0x0ddd: 0x2ae5, + 0x0dde: 0x2ae9, 0x0ddf: 0x2aed, 0x0de0: 0x2af1, 0x0de1: 0x2af5, 0x0de2: 0x2af9, 0x0de3: 0x2afd, + 0x0de4: 0x2b01, 0x0de5: 0x2b05, 0x0de6: 0x2b09, 0x0de7: 0x2b0d, 0x0de8: 0x2b11, 0x0de9: 0x2b15, + 0x0dea: 0x2b19, 0x0deb: 0x2b1d, 0x0dec: 0x2b21, 0x0ded: 0x2b25, 0x0dee: 0x2b29, 0x0def: 0x2b2d, + 0x0df0: 0x2b31, 0x0df1: 0x2b35, 0x0df2: 0x2b39, 0x0df3: 0x2b3d, 0x0df4: 0x1a16, 0x0df5: 0x2b41, + 0x0df6: 0x2b45, 0x0df7: 0x2b49, 0x0df8: 0x2b4d, 0x0df9: 0x2b51, 0x0dfa: 0x2b55, 0x0dfb: 0x2b59, + 0x0dfc: 0x2b5d, 0x0dfd: 0x2b61, 0x0dfe: 0x2b65, 0x0dff: 0x2b69, + // Block 0x38, offset 0xe00 + 0x0e00: 0x1b3a, 0x0e01: 0x2b6d, 0x0e02: 0x2b71, 0x0e03: 0x2b75, 0x0e04: 0x2b79, 0x0e05: 0x2b7d, + 0x0e06: 0x2b81, 0x0e07: 0x2b85, 0x0e08: 0x2b89, 0x0e09: 0x2b8d, 0x0e0a: 0x2b91, 0x0e0b: 0x2b95, + 0x0e0c: 0x2b99, 0x0e0d: 0x2b9d, 0x0e0e: 0x2ba1, 0x0e0f: 0x2ba5, 0x0e10: 0x2ba9, 0x0e11: 0x2bad, + 0x0e12: 0x2bb1, 0x0e13: 0x2bb5, 0x0e14: 0x2bb9, 0x0e15: 0x2bbd, 0x0e16: 0x2bc1, 0x0e17: 0x2bc5, + 0x0e18: 0x2bc9, 0x0e19: 0x2bcd, 0x0e1a: 0x2bd1, 0x0e1b: 0x2bd5, 0x0e1c: 0x2ac1, 0x0e1d: 0x2bd9, + 0x0e1e: 0x2bdd, 0x0e1f: 0x2be1, 0x0e20: 0x2be5, 0x0e21: 0x2be9, 0x0e22: 0x2bed, 0x0e23: 0x2bf1, + 0x0e24: 0x2bf5, 0x0e25: 0x2bf9, 0x0e26: 0x2bfd, 0x0e27: 0x2c01, 0x0e28: 0x2c05, 0x0e29: 0x2c09, + 0x0e2a: 0x2c0d, 0x0e2b: 0x2c11, 0x0e2c: 0x2c15, 0x0e2d: 0x2c19, 0x0e2e: 0x2c1d, 0x0e2f: 0x2c21, + 0x0e30: 0x2c25, 0x0e31: 0x1aa6, 0x0e32: 0x2c29, 0x0e33: 0x2c2d, 0x0e34: 0x2c31, 0x0e35: 0x2c35, + 0x0e36: 0x2c39, 0x0e37: 0x2c3d, 0x0e38: 0x2c41, 0x0e39: 0x2c45, 0x0e3a: 0x2c49, 0x0e3b: 0x2c4d, + 0x0e3c: 0x2c51, 0x0e3d: 0x2c55, 0x0e3e: 0x2c59, 0x0e3f: 0x2c5d, + // Block 0x39, offset 0xe40 + 0x0e40: 0x2c61, 0x0e41: 0x18ba, 0x0e42: 0x2c65, 0x0e43: 0x2c69, 0x0e44: 0x2c6d, 0x0e45: 0x2c71, + 0x0e46: 0x2c75, 0x0e47: 0x2c79, 0x0e48: 0x2c7d, 0x0e49: 0x2c81, 0x0e4a: 0x186e, 0x0e4b: 0x2c85, + 0x0e4c: 0x2c89, 0x0e4d: 0x2c8d, 0x0e4e: 0x2c91, 0x0e4f: 0x2c95, 0x0e50: 0x2c99, 0x0e51: 0x2c9d, + 0x0e52: 0x2ca1, 0x0e53: 0x2ca5, 0x0e54: 0x2ca9, 0x0e55: 0x2cad, 0x0e56: 0x2cb1, 0x0e57: 0x2cb5, + 0x0e58: 0x2cb9, 0x0e59: 0x2cbd, 0x0e5a: 0x2cc1, 0x0e5b: 0x2cc5, 0x0e5c: 0x2cc9, 0x0e5d: 0x2ccd, + 0x0e5e: 0x2cd1, 0x0e5f: 0x2cd5, 0x0e60: 0x2cd9, 0x0e61: 0x2c21, 0x0e62: 0x2cdd, 0x0e63: 0x2ce1, + 0x0e64: 0x2ce5, 0x0e65: 0x2ce9, 0x0e66: 0x2ced, 0x0e67: 0x2cf1, 0x0e68: 0x2cf5, 0x0e69: 0x2cf9, + 0x0e6a: 0x2be1, 0x0e6b: 0x2cfd, 0x0e6c: 0x2d01, 0x0e6d: 0x2d05, 0x0e6e: 0x2d09, 0x0e6f: 0x2d0d, + 0x0e70: 0x2d11, 0x0e71: 0x2d15, 0x0e72: 0x2d19, 0x0e73: 0x2d1d, 0x0e74: 0x2d21, 0x0e75: 0x2d25, + 0x0e76: 0x2d29, 0x0e77: 0x2d2d, 0x0e78: 0x2d31, 0x0e79: 0x2d35, 0x0e7a: 0x2d39, 0x0e7b: 0x2d3d, + 0x0e7c: 0x2d41, 0x0e7d: 0x2d45, 0x0e7e: 0x2d49, 0x0e7f: 0x2ac1, + // Block 0x3a, offset 0xe80 + 0x0e80: 0x2d4d, 0x0e81: 0x2d51, 0x0e82: 0x2d55, 0x0e83: 0x2d59, 0x0e84: 0x1b72, 0x0e85: 0x2d5d, + 0x0e86: 0x2d61, 0x0e87: 0x2d65, 0x0e88: 0x2d69, 0x0e89: 0x2d6d, 0x0e8a: 0x2d71, 0x0e8b: 0x2d75, + 0x0e8c: 0x2d79, 0x0e8d: 0x2d7d, 0x0e8e: 0x2d81, 0x0e8f: 0x2d85, 0x0e90: 0x2d89, 0x0e91: 0x2173, + 0x0e92: 0x2d8d, 0x0e93: 0x2d91, 0x0e94: 0x2d95, 0x0e95: 0x2d99, 0x0e96: 0x2d9d, 0x0e97: 0x2da1, + 0x0e98: 0x2da5, 0x0e99: 0x2da9, 0x0e9a: 0x2dad, 0x0e9b: 0x2be9, 0x0e9c: 0x2db1, 0x0e9d: 0x2db5, + 0x0e9e: 0x2db9, 0x0e9f: 0x2dbd, 0x0ea0: 0x2dc1, 0x0ea1: 0x2dc5, 0x0ea2: 0x2dc9, 0x0ea3: 0x2dcd, + 0x0ea4: 0x2dd1, 0x0ea5: 0x2dd5, 0x0ea6: 0x2dd9, 0x0ea7: 0x2ddd, 0x0ea8: 0x2de1, 0x0ea9: 0x1aba, + 0x0eaa: 0x2de5, 0x0eab: 0x2de9, 0x0eac: 0x2ded, 0x0ead: 0x2df1, 0x0eae: 0x2df5, 0x0eaf: 0x2df9, + 0x0eb0: 0x2dfd, 0x0eb1: 0x2e01, 0x0eb2: 0x2e05, 0x0eb3: 0x2e09, 0x0eb4: 0x2e0d, 0x0eb5: 0x2e11, + 0x0eb6: 0x2e15, 0x0eb7: 0x19f6, 0x0eb8: 0x2e19, 0x0eb9: 0x2e1d, 0x0eba: 0x2e21, 0x0ebb: 0x2e25, + 0x0ebc: 0x2e29, 0x0ebd: 0x2e2d, 0x0ebe: 0x2e31, 0x0ebf: 0x2e35, + // Block 0x3b, offset 0xec0 + 0x0ec0: 0x2e39, 0x0ec1: 0x2e3d, 0x0ec2: 0x2e41, 0x0ec3: 0x2e45, 0x0ec4: 0x2e49, 0x0ec5: 0x2e4d, + 0x0ec6: 0x2e51, 0x0ec7: 0x2e55, 0x0ec8: 0x1a62, 0x0ec9: 0x2e59, 0x0eca: 0x1a6e, 0x0ecb: 0x2e5d, + 0x0ecc: 0x2e61, 0x0ecd: 0x2e65, 0x0ed0: 0x2e69, + 0x0ed2: 0x2e6d, 0x0ed5: 0x2e71, 0x0ed6: 0x2e75, 0x0ed7: 0x2e79, + 0x0ed8: 0x2e7d, 0x0ed9: 0x2e81, 0x0eda: 0x2e85, 0x0edb: 0x2e89, 0x0edc: 0x2e8d, 0x0edd: 0x2e91, + 0x0ede: 0x1a12, 0x0ee0: 0x2e95, 0x0ee2: 0x2e99, + 0x0ee5: 0x2e9d, 0x0ee6: 0x2ea1, + 0x0eea: 0x2ea5, 0x0eeb: 0x2ea9, 0x0eec: 0x2ead, 0x0eed: 0x2eb1, + 0x0ef0: 0x2eb5, 0x0ef1: 0x2eb9, 0x0ef2: 0x2ebd, 0x0ef3: 0x2ec1, 0x0ef4: 0x2ec5, 0x0ef5: 0x2ec9, + 0x0ef6: 0x2ecd, 0x0ef7: 0x2ed1, 0x0ef8: 0x2ed5, 0x0ef9: 0x2ed9, 0x0efa: 0x2edd, 0x0efb: 0x2ee1, + 0x0efc: 0x18d6, 0x0efd: 0x2ee5, 0x0efe: 0x2ee9, 0x0eff: 0x2eed, + // Block 0x3c, offset 0xf00 + 0x0f00: 0x2ef1, 0x0f01: 0x2ef5, 0x0f02: 0x2ef9, 0x0f03: 0x2efd, 0x0f04: 0x2f01, 0x0f05: 0x2f05, + 0x0f06: 0x2f09, 0x0f07: 0x2f0d, 0x0f08: 0x2f11, 0x0f09: 0x2f15, 0x0f0a: 0x2f19, 0x0f0b: 0x2f1d, + 0x0f0c: 0x2187, 0x0f0d: 0x2f21, 0x0f0e: 0x2f25, 0x0f0f: 0x2f29, 0x0f10: 0x2f2d, 0x0f11: 0x2197, + 0x0f12: 0x2f31, 0x0f13: 0x2f35, 0x0f14: 0x2f39, 0x0f15: 0x2f3d, 0x0f16: 0x2f41, 0x0f17: 0x2cb1, + 0x0f18: 0x2f45, 0x0f19: 0x2f49, 0x0f1a: 0x2f4d, 0x0f1b: 0x2f51, 0x0f1c: 0x2f55, 0x0f1d: 0x2f59, + 0x0f1e: 0x2f59, 0x0f1f: 0x2f5d, 0x0f20: 0x2f61, 0x0f21: 0x2f65, 0x0f22: 0x2f69, 0x0f23: 0x2f6d, + 0x0f24: 0x2f71, 0x0f25: 0x2f75, 0x0f26: 0x2f79, 0x0f27: 0x2e9d, 0x0f28: 0x2f7d, 0x0f29: 0x2f81, + 0x0f2a: 0x2f85, 0x0f2b: 0x2f89, 0x0f2c: 0x2f8d, 0x0f2d: 0x2f92, + 0x0f30: 0x2f96, 0x0f31: 0x2f9a, 0x0f32: 0x2f9e, 0x0f33: 0x2fa2, 0x0f34: 0x2fa6, 0x0f35: 0x2faa, + 0x0f36: 0x2fae, 0x0f37: 0x2fb2, 0x0f38: 0x2ecd, 0x0f39: 0x2fb6, 0x0f3a: 0x2fba, 0x0f3b: 0x2fbe, + 0x0f3c: 0x2e69, 0x0f3d: 0x2fc2, 0x0f3e: 0x2fc6, 0x0f3f: 0x2fca, + // Block 0x3d, offset 0xf40 + 0x0f40: 0x2fce, 0x0f41: 0x2fd2, 0x0f42: 0x2fd6, 0x0f43: 0x2fda, 0x0f44: 0x2fde, 0x0f45: 0x2fe2, + 0x0f46: 0x2fe6, 0x0f47: 0x2fea, 0x0f48: 0x2fee, 0x0f49: 0x2eed, 0x0f4a: 0x2ff2, 0x0f4b: 0x2ef1, + 0x0f4c: 0x2ff6, 0x0f4d: 0x2ffa, 0x0f4e: 0x2ffe, 0x0f4f: 0x3002, 0x0f50: 0x3006, 0x0f51: 0x2e6d, + 0x0f52: 0x2b15, 0x0f53: 0x300a, 0x0f54: 0x300e, 0x0f55: 0x195a, 0x0f56: 0x2c25, 0x0f57: 0x2d71, + 0x0f58: 0x3012, 0x0f59: 0x3016, 0x0f5a: 0x2f0d, 0x0f5b: 0x301a, 0x0f5c: 0x2f11, 0x0f5d: 0x301e, + 0x0f5e: 0x3022, 0x0f5f: 0x3026, 0x0f60: 0x2e75, 0x0f61: 0x302a, 0x0f62: 0x302e, 0x0f63: 0x3032, + 0x0f64: 0x3036, 0x0f65: 0x303a, 0x0f66: 0x2e79, 0x0f67: 0x303e, 0x0f68: 0x3042, 0x0f69: 0x3046, + 0x0f6a: 0x304a, 0x0f6b: 0x304e, 0x0f6c: 0x3052, 0x0f6d: 0x2f41, 0x0f6e: 0x3056, 0x0f6f: 0x305a, + 0x0f70: 0x2cb1, 0x0f71: 0x305e, 0x0f72: 0x2f51, 0x0f73: 0x3062, 0x0f74: 0x3066, 0x0f75: 0x306a, + 0x0f76: 0x306e, 0x0f77: 0x3072, 0x0f78: 0x2f65, 0x0f79: 0x3076, 0x0f7a: 0x2e99, 0x0f7b: 0x307a, + 0x0f7c: 0x2f69, 0x0f7d: 0x2bd9, 0x0f7e: 0x307e, 0x0f7f: 0x2f6d, + // Block 0x3e, offset 0xf80 + 0x0f80: 0x3082, 0x0f81: 0x2f75, 0x0f82: 0x3086, 0x0f83: 0x308a, 0x0f84: 0x308e, 0x0f85: 0x3092, + 0x0f86: 0x3096, 0x0f87: 0x2f7d, 0x0f88: 0x2e8d, 0x0f89: 0x309a, 0x0f8a: 0x2f81, 0x0f8b: 0x309e, + 0x0f8c: 0x2f85, 0x0f8d: 0x30a2, 0x0f8e: 0x1b76, 0x0f8f: 0x30a6, 0x0f90: 0x30ab, 0x0f91: 0x30b0, + 0x0f92: 0x30b5, 0x0f93: 0x30b9, 0x0f94: 0x30bd, 0x0f95: 0x30c1, 0x0f96: 0x30c6, 0x0f97: 0x30cb, + 0x0f98: 0x30d0, 0x0f99: 0x30d4, + // Block 0x3f, offset 0xfc0 + 0x0fdd: 0x3105, + 0x0fdf: 0x310a, + 0x0fea: 0x3124, 0x0feb: 0x3129, 0x0fec: 0x312e, 0x0fed: 0x3135, 0x0fee: 0x313c, 0x0fef: 0x3141, + 0x0ff0: 0x3146, 0x0ff1: 0x314b, 0x0ff2: 0x3150, 0x0ff3: 0x3155, 0x0ff4: 0x315a, 0x0ff5: 0x315f, + 0x0ff6: 0x3164, 0x0ff8: 0x3169, 0x0ff9: 0x316e, 0x0ffa: 0x3173, 0x0ffb: 0x3178, + 0x0ffc: 0x317d, 0x0ffe: 0x3182, + // Block 0x40, offset 0x1000 + 0x1000: 0x3187, 0x1001: 0x318c, 0x1003: 0x3191, 0x1004: 0x3196, + 0x1006: 0x319b, 0x1007: 0x31a0, 0x1008: 0x31a5, 0x1009: 0x31aa, 0x100a: 0x31af, 0x100b: 0x31b4, + 0x100c: 0x31b9, 0x100d: 0x31be, 0x100e: 0x31c3, + // Block 0x41, offset 0x1040 + 0x105a: 0x3a73, 0x105c: 0x3a7c, + 0x106b: 0x3a85, + // Block 0x42, offset 0x1080 + 0x109e: 0x3a8e, 0x109f: 0x3a97, 0x10a0: 0x3aa0, 0x10a1: 0x3aad, 0x10a2: 0x3aba, 0x10a3: 0x3ac7, + 0x10a4: 0x3ad4, + // Block 0x43, offset 0x10c0 + 0x10fb: 0x3ae1, + 0x10fc: 0x3aea, 0x10fd: 0x3af3, 0x10fe: 0x3b00, 0x10ff: 0x3b0d, + // Block 0x44, offset 0x1100 + 0x1100: 0x3b1a, + // Block 0x45, offset 0x1140 + 0x1140: 0x3d23, 0x1141: 0x3d27, 0x1142: 0x3d2b, 0x1143: 0x3d2f, 0x1144: 0x3d34, 0x1145: 0x2eb5, + 0x1146: 0x3d38, 0x1147: 0x3d3c, 0x1148: 0x3d40, 0x1149: 0x3d44, 0x114a: 0x2eb9, 0x114b: 0x3d48, + 0x114c: 0x3d4c, 0x114d: 0x3d50, 0x114e: 0x2ebd, 0x114f: 0x3d55, 0x1150: 0x3d59, 0x1151: 0x3d5d, + 0x1152: 0x3d61, 0x1153: 0x3d66, 0x1154: 0x3d6a, 0x1155: 0x3c71, 0x1156: 0x3d6e, 0x1157: 0x3d73, + 0x1158: 0x3d77, 0x1159: 0x3d7b, 0x115a: 0x3d7f, 0x115b: 0x2f9a, 0x115c: 0x3d83, 0x115d: 0x1866, + 0x115e: 0x3d88, 0x115f: 0x3d8c, 0x1160: 0x3d90, 0x1161: 0x3d94, 0x1162: 0x3cb9, 0x1163: 0x3d98, + 0x1164: 0x3d9c, 0x1165: 0x2fae, 0x1166: 0x2ec1, 0x1167: 0x2ec5, 0x1168: 0x2fb2, 0x1169: 0x3da0, + 0x116a: 0x3da4, 0x116b: 0x2bf1, 0x116c: 0x3da8, 0x116d: 0x2ec9, 0x116e: 0x3dac, 0x116f: 0x3db0, + 0x1170: 0x3db4, 0x1171: 0x3db8, 0x1172: 0x3db8, 0x1173: 0x3db8, 0x1174: 0x3dbc, 0x1175: 0x3dc1, + 0x1176: 0x3dc5, 0x1177: 0x3dc9, 0x1178: 0x3dcd, 0x1179: 0x3dd2, 0x117a: 0x3dd6, 0x117b: 0x3dda, + 0x117c: 0x3dde, 0x117d: 0x3de2, 0x117e: 0x3de6, 0x117f: 0x3dea, + // Block 0x46, offset 0x1180 + 0x1180: 0x3dee, 0x1181: 0x3df2, 0x1182: 0x3df6, 0x1183: 0x3dfa, 0x1184: 0x3dfe, 0x1185: 0x3e02, + 0x1186: 0x3e02, 0x1187: 0x2fba, 0x1188: 0x3e06, 0x1189: 0x3e0a, 0x118a: 0x3e0e, 0x118b: 0x3e12, + 0x118c: 0x2ed1, 0x118d: 0x3e16, 0x118e: 0x3e1a, 0x118f: 0x3e1e, 0x1190: 0x2e39, 0x1191: 0x3e22, + 0x1192: 0x3e26, 0x1193: 0x3e2a, 0x1194: 0x3e2e, 0x1195: 0x3e32, 0x1196: 0x3e36, 0x1197: 0x3e3a, + 0x1198: 0x3e3e, 0x1199: 0x3e42, 0x119a: 0x3e47, 0x119b: 0x3e4b, 0x119c: 0x3e4f, 0x119d: 0x3c55, + 0x119e: 0x3e53, 0x119f: 0x3e57, 0x11a0: 0x3e5b, 0x11a1: 0x3e60, 0x11a2: 0x3e65, 0x11a3: 0x3e69, + 0x11a4: 0x3e6d, 0x11a5: 0x3e71, 0x11a6: 0x3e75, 0x11a7: 0x3e79, 0x11a8: 0x3e7d, 0x11a9: 0x3e81, + 0x11aa: 0x3e85, 0x11ab: 0x3e85, 0x11ac: 0x3e89, 0x11ad: 0x3e8e, 0x11ae: 0x3e92, 0x11af: 0x2be1, + 0x11b0: 0x3e96, 0x11b1: 0x3e9a, 0x11b2: 0x3e9f, 0x11b3: 0x3ea3, 0x11b4: 0x3ea7, 0x11b5: 0x18ce, + 0x11b6: 0x3eab, 0x11b7: 0x3eaf, 0x11b8: 0x18d6, 0x11b9: 0x3eb3, 0x11ba: 0x3eb7, 0x11bb: 0x3ebb, + 0x11bc: 0x3ec0, 0x11bd: 0x3ec4, 0x11be: 0x3ec9, 0x11bf: 0x3ecd, + // Block 0x47, offset 0x11c0 + 0x11c0: 0x3ed1, 0x11c1: 0x3ed5, 0x11c2: 0x3ed9, 0x11c3: 0x3edd, 0x11c4: 0x3ee1, 0x11c5: 0x3ee5, + 0x11c6: 0x3ee9, 0x11c7: 0x3eed, 0x11c8: 0x3ef1, 0x11c9: 0x3ef5, 0x11ca: 0x3efa, 0x11cb: 0x3efe, + 0x11cc: 0x3f02, 0x11cd: 0x3f06, 0x11ce: 0x2b11, 0x11cf: 0x3f0a, 0x11d0: 0x18fe, 0x11d1: 0x3f0f, + 0x11d2: 0x3f0f, 0x11d3: 0x3f14, 0x11d4: 0x3f18, 0x11d5: 0x3f18, 0x11d6: 0x3f1c, 0x11d7: 0x3f20, + 0x11d8: 0x3f25, 0x11d9: 0x3f2a, 0x11da: 0x3f2e, 0x11db: 0x3f32, 0x11dc: 0x3f36, 0x11dd: 0x3f3a, + 0x11de: 0x3f3e, 0x11df: 0x3f42, 0x11e0: 0x3f46, 0x11e1: 0x3f4a, 0x11e2: 0x3f4e, 0x11e3: 0x2ee5, + 0x11e4: 0x3f52, 0x11e5: 0x3f57, 0x11e6: 0x3f5b, 0x11e7: 0x3f5f, 0x11e8: 0x2fea, 0x11e9: 0x3f5f, + 0x11ea: 0x3f63, 0x11eb: 0x2eed, 0x11ec: 0x3f67, 0x11ed: 0x3f6b, 0x11ee: 0x3f6f, 0x11ef: 0x3f73, + 0x11f0: 0x2ef1, 0x11f1: 0x2aa5, 0x11f2: 0x3f77, 0x11f3: 0x3f7b, 0x11f4: 0x3f7f, 0x11f5: 0x3f83, + 0x11f6: 0x3f87, 0x11f7: 0x3f8b, 0x11f8: 0x3f8f, 0x11f9: 0x3f94, 0x11fa: 0x3f98, 0x11fb: 0x3f9c, + 0x11fc: 0x3fa0, 0x11fd: 0x3fa4, 0x11fe: 0x3fa8, 0x11ff: 0x3fad, + // Block 0x48, offset 0x1200 + 0x1200: 0x3fb1, 0x1201: 0x3fb5, 0x1202: 0x3fb9, 0x1203: 0x3fbd, 0x1204: 0x3fc1, 0x1205: 0x3fc5, + 0x1206: 0x3fc9, 0x1207: 0x3fcd, 0x1208: 0x2ef5, 0x1209: 0x3fd1, 0x120a: 0x3fd5, 0x120b: 0x3fda, + 0x120c: 0x3fde, 0x120d: 0x3fe2, 0x120e: 0x3fe6, 0x120f: 0x2efd, 0x1210: 0x3fea, 0x1211: 0x3fee, + 0x1212: 0x3ff2, 0x1213: 0x3ff6, 0x1214: 0x3ffa, 0x1215: 0x3ffe, 0x1216: 0x4002, 0x1217: 0x4006, + 0x1218: 0x2b15, 0x1219: 0x300a, 0x121a: 0x400a, 0x121b: 0x400e, 0x121c: 0x4012, 0x121d: 0x4016, + 0x121e: 0x401b, 0x121f: 0x401f, 0x1220: 0x4023, 0x1221: 0x4027, 0x1222: 0x2f01, 0x1223: 0x402b, + 0x1224: 0x4030, 0x1225: 0x4034, 0x1226: 0x4038, 0x1227: 0x30b5, 0x1228: 0x403c, 0x1229: 0x4040, + 0x122a: 0x4044, 0x122b: 0x4048, 0x122c: 0x404c, 0x122d: 0x4051, 0x122e: 0x4055, 0x122f: 0x4059, + 0x1230: 0x405d, 0x1231: 0x4062, 0x1232: 0x4066, 0x1233: 0x406a, 0x1234: 0x406e, 0x1235: 0x2c25, + 0x1236: 0x4072, 0x1237: 0x4076, 0x1238: 0x407b, 0x1239: 0x4080, 0x123a: 0x4085, 0x123b: 0x4089, + 0x123c: 0x408e, 0x123d: 0x4092, 0x123e: 0x4096, 0x123f: 0x409a, + // Block 0x49, offset 0x1240 + 0x1240: 0x409e, 0x1241: 0x2f05, 0x1242: 0x2d71, 0x1243: 0x40a2, 0x1244: 0x40a6, 0x1245: 0x40aa, + 0x1246: 0x40ae, 0x1247: 0x40b3, 0x1248: 0x40b7, 0x1249: 0x40bb, 0x124a: 0x40bf, 0x124b: 0x3016, + 0x124c: 0x40c3, 0x124d: 0x40c7, 0x124e: 0x40cc, 0x124f: 0x40d0, 0x1250: 0x40d4, 0x1251: 0x40d9, + 0x1252: 0x40de, 0x1253: 0x40e2, 0x1254: 0x301a, 0x1255: 0x40e6, 0x1256: 0x40ea, 0x1257: 0x40ee, + 0x1258: 0x40f2, 0x1259: 0x40f6, 0x125a: 0x40fa, 0x125b: 0x40fe, 0x125c: 0x4103, 0x125d: 0x4107, + 0x125e: 0x410c, 0x125f: 0x4110, 0x1260: 0x4115, 0x1261: 0x3022, 0x1262: 0x4119, 0x1263: 0x411d, + 0x1264: 0x4122, 0x1265: 0x4126, 0x1266: 0x412a, 0x1267: 0x412f, 0x1268: 0x4134, 0x1269: 0x4138, + 0x126a: 0x413c, 0x126b: 0x4140, 0x126c: 0x4144, 0x126d: 0x4144, 0x126e: 0x4148, 0x126f: 0x414c, + 0x1270: 0x302a, 0x1271: 0x4150, 0x1272: 0x4154, 0x1273: 0x4158, 0x1274: 0x415c, 0x1275: 0x4160, + 0x1276: 0x4165, 0x1277: 0x4169, 0x1278: 0x2bed, 0x1279: 0x416e, 0x127a: 0x4173, 0x127b: 0x4177, + 0x127c: 0x417c, 0x127d: 0x4181, 0x127e: 0x4186, 0x127f: 0x418a, + // Block 0x4a, offset 0x1280 + 0x1280: 0x3042, 0x1281: 0x418e, 0x1282: 0x4193, 0x1283: 0x4198, 0x1284: 0x419d, 0x1285: 0x41a2, + 0x1286: 0x41a6, 0x1287: 0x41a6, 0x1288: 0x3046, 0x1289: 0x30bd, 0x128a: 0x41aa, 0x128b: 0x41ae, + 0x128c: 0x41b2, 0x128d: 0x41b6, 0x128e: 0x41bb, 0x128f: 0x2b59, 0x1290: 0x304e, 0x1291: 0x41bf, + 0x1292: 0x41c3, 0x1293: 0x2f2d, 0x1294: 0x41c8, 0x1295: 0x41cd, 0x1296: 0x2e89, 0x1297: 0x41d2, + 0x1298: 0x41d6, 0x1299: 0x2f39, 0x129a: 0x41da, 0x129b: 0x41de, 0x129c: 0x41e2, 0x129d: 0x41e7, + 0x129e: 0x41e7, 0x129f: 0x41ec, 0x12a0: 0x41f0, 0x12a1: 0x41f4, 0x12a2: 0x41f9, 0x12a3: 0x41fd, + 0x12a4: 0x4201, 0x12a5: 0x4205, 0x12a6: 0x420a, 0x12a7: 0x420e, 0x12a8: 0x4212, 0x12a9: 0x4216, + 0x12aa: 0x421a, 0x12ab: 0x421e, 0x12ac: 0x4223, 0x12ad: 0x4227, 0x12ae: 0x422b, 0x12af: 0x422f, + 0x12b0: 0x4233, 0x12b1: 0x4237, 0x12b2: 0x423b, 0x12b3: 0x4240, 0x12b4: 0x4245, 0x12b5: 0x4249, + 0x12b6: 0x424e, 0x12b7: 0x4252, 0x12b8: 0x4257, 0x12b9: 0x425b, 0x12ba: 0x2f51, 0x12bb: 0x425f, + 0x12bc: 0x4264, 0x12bd: 0x4269, 0x12be: 0x426d, 0x12bf: 0x4272, + // Block 0x4b, offset 0x12c0 + 0x12c0: 0x4276, 0x12c1: 0x427b, 0x12c2: 0x427f, 0x12c3: 0x4283, 0x12c4: 0x4287, 0x12c5: 0x428b, + 0x12c6: 0x428f, 0x12c7: 0x4293, 0x12c8: 0x4298, 0x12c9: 0x429d, 0x12ca: 0x42a2, 0x12cb: 0x3f14, + 0x12cc: 0x42a7, 0x12cd: 0x42ab, 0x12ce: 0x42af, 0x12cf: 0x42b3, 0x12d0: 0x42b7, 0x12d1: 0x42bb, + 0x12d2: 0x42bf, 0x12d3: 0x42c3, 0x12d4: 0x42c7, 0x12d5: 0x42cb, 0x12d6: 0x42cf, 0x12d7: 0x42d3, + 0x12d8: 0x2c31, 0x12d9: 0x42d8, 0x12da: 0x42dc, 0x12db: 0x42e0, 0x12dc: 0x42e4, 0x12dd: 0x42e8, + 0x12de: 0x42ec, 0x12df: 0x2f5d, 0x12e0: 0x42f0, 0x12e1: 0x42f4, 0x12e2: 0x42f8, 0x12e3: 0x42fc, + 0x12e4: 0x4300, 0x12e5: 0x4305, 0x12e6: 0x430a, 0x12e7: 0x430f, 0x12e8: 0x4313, 0x12e9: 0x4317, + 0x12ea: 0x431b, 0x12eb: 0x431f, 0x12ec: 0x4324, 0x12ed: 0x4328, 0x12ee: 0x432d, 0x12ef: 0x4331, + 0x12f0: 0x4335, 0x12f1: 0x433a, 0x12f2: 0x433f, 0x12f3: 0x4343, 0x12f4: 0x2b45, 0x12f5: 0x4347, + 0x12f6: 0x434b, 0x12f7: 0x434f, 0x12f8: 0x4353, 0x12f9: 0x4357, 0x12fa: 0x435b, 0x12fb: 0x306a, + 0x12fc: 0x435f, 0x12fd: 0x4363, 0x12fe: 0x4367, 0x12ff: 0x436b, + // Block 0x4c, offset 0x1300 + 0x1300: 0x436f, 0x1301: 0x4373, 0x1302: 0x4377, 0x1303: 0x437b, 0x1304: 0x1a66, 0x1305: 0x437f, + 0x1306: 0x4384, 0x1307: 0x4388, 0x1308: 0x438c, 0x1309: 0x4390, 0x130a: 0x4394, 0x130b: 0x4398, + 0x130c: 0x439d, 0x130d: 0x43a2, 0x130e: 0x43a6, 0x130f: 0x43aa, 0x1310: 0x307e, 0x1311: 0x3082, + 0x1312: 0x1a82, 0x1313: 0x43ae, 0x1314: 0x43b3, 0x1315: 0x43b7, 0x1316: 0x43bb, 0x1317: 0x43bf, + 0x1318: 0x43c3, 0x1319: 0x43c8, 0x131a: 0x43cd, 0x131b: 0x43d1, 0x131c: 0x43d5, 0x131d: 0x43d9, + 0x131e: 0x43de, 0x131f: 0x3086, 0x1320: 0x43e2, 0x1321: 0x43e7, 0x1322: 0x43ec, 0x1323: 0x43f0, + 0x1324: 0x43f4, 0x1325: 0x43f8, 0x1326: 0x43fd, 0x1327: 0x4401, 0x1328: 0x4405, 0x1329: 0x4409, + 0x132a: 0x440d, 0x132b: 0x4411, 0x132c: 0x4415, 0x132d: 0x4419, 0x132e: 0x441e, 0x132f: 0x4422, + 0x1330: 0x4426, 0x1331: 0x442a, 0x1332: 0x442f, 0x1333: 0x4433, 0x1334: 0x4437, 0x1335: 0x443b, + 0x1336: 0x443f, 0x1337: 0x4444, 0x1338: 0x4449, 0x1339: 0x444d, 0x133a: 0x4451, 0x133b: 0x4455, + 0x133c: 0x445a, 0x133d: 0x445e, 0x133e: 0x309e, 0x133f: 0x309e, + // Block 0x4d, offset 0x1340 + 0x1340: 0x4463, 0x1341: 0x4467, 0x1342: 0x446c, 0x1343: 0x4470, 0x1344: 0x4474, 0x1345: 0x4478, + 0x1346: 0x447c, 0x1347: 0x4480, 0x1348: 0x4484, 0x1349: 0x4488, 0x134a: 0x30a2, 0x134b: 0x448d, + 0x134c: 0x4491, 0x134d: 0x4495, 0x134e: 0x4499, 0x134f: 0x449d, 0x1350: 0x44a1, 0x1351: 0x44a6, + 0x1352: 0x44aa, 0x1353: 0x44af, 0x1354: 0x44b4, 0x1355: 0x1b42, 0x1356: 0x44b9, 0x1357: 0x1b52, + 0x1358: 0x44bd, 0x1359: 0x44c1, 0x135a: 0x44c5, 0x135b: 0x44c9, 0x135c: 0x1b66, 0x135d: 0x44cd, } // nfcDecompLookup: 832 bytes // Block 0 is the null block. -var nfcDecompLookup = [...]uint8{ - // Block 0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 2 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 3 - 0x00, 0x00, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 4 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x11, 0x12, 0x00, 0x13, - 0x14, 0x15, 0x00, 0x00, 0x00, 0x16, 0x17, 0x18, - 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x1C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x1E, 0x00, - // Block 5 - 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - // Block 6 - 0x2A, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x2C, 0x2D, - 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 7 - 0x00, 0x34, 0x35, 0x36, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 8 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x3A, - 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 9 - 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block A - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block B - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, - 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block C - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +var nfcDecompLookup = [832]uint8{ + // Block 0x0, offset 0x0 + // Block 0x1, offset 0x40 + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x0c3: 0x03, 0x0c4: 0x04, 0x0c5: 0x05, 0x0c6: 0x06, 0x0c7: 0x07, + 0x0c8: 0x08, 0x0cd: 0x09, 0x0ce: 0x0a, 0x0cf: 0x0b, + 0x0d0: 0x0c, 0x0d1: 0x0d, 0x0d3: 0x0e, + 0x0d8: 0x0f, 0x0db: 0x10, + 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07, + 0x0ef: 0x08, + 0x0f0: 0x0c, + // Block 0x4, offset 0x100 + 0x124: 0x11, 0x125: 0x12, 0x127: 0x13, + 0x128: 0x14, 0x129: 0x15, 0x12d: 0x16, 0x12e: 0x17, 0x12f: 0x18, + 0x131: 0x19, 0x133: 0x1a, 0x135: 0x1b, 0x137: 0x1c, + 0x13d: 0x1d, 0x13e: 0x1e, + // Block 0x5, offset 0x140 + 0x140: 0x1f, + 0x16c: 0x20, 0x16d: 0x21, + 0x178: 0x22, 0x179: 0x23, 0x17a: 0x24, 0x17b: 0x25, 0x17c: 0x26, 0x17d: 0x27, 0x17e: 0x28, 0x17f: 0x29, + // Block 0x6, offset 0x180 + 0x180: 0x2a, 0x184: 0x2b, 0x186: 0x2c, 0x187: 0x2d, + 0x188: 0x2e, 0x189: 0x2f, 0x18a: 0x30, 0x18b: 0x31, 0x18c: 0x32, + 0x1ab: 0x33, + // Block 0x7, offset 0x1c0 + 0x1c1: 0x34, 0x1c2: 0x35, 0x1c3: 0x36, + // Block 0x8, offset 0x200 + 0x224: 0x37, 0x225: 0x38, 0x226: 0x39, 0x227: 0x3a, + 0x228: 0x3b, 0x229: 0x3c, 0x22a: 0x3d, 0x22b: 0x3e, 0x22c: 0x3f, 0x22d: 0x40, + // Block 0x9, offset 0x240 + 0x242: 0x41, + // Block 0xa, offset 0x280 + 0x285: 0x42, 0x286: 0x43, 0x287: 0x44, + // Block 0xb, offset 0x2c0 + 0x2e0: 0x45, 0x2e1: 0x46, 0x2e2: 0x47, 0x2e3: 0x48, 0x2e4: 0x49, 0x2e5: 0x4a, 0x2e6: 0x4b, 0x2e7: 0x4c, + 0x2e8: 0x4d, + // Block 0xc, offset 0x300 + 0x311: 0x09, + 0x31d: 0x0a, + 0x32f: 0x0b, } +var nfcDecompTrie = trie{nfcDecompLookup[:], nfcDecompValues[:]} + // nfkcDecompValues: 10176 entries, 20352 bytes // Block 2 is the null block. -var nfkcDecompValues = [...]uint16{ - // Block 0 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0003, 0x0000, 0x0007, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, - 0x0000, 0x0000, 0x000D, 0x000F, 0x0011, 0x0015, 0x0000, 0x0000, - 0x0018, 0x001C, 0x001E, 0x0000, 0x0020, 0x0026, 0x002C, 0x0000, - // Block 4 - 0x0032, 0x0036, 0x003A, 0x003E, 0x0042, 0x0046, 0x0000, 0x004A, - 0x004E, 0x0052, 0x0056, 0x005A, 0x005E, 0x0062, 0x0066, 0x006A, - 0x0000, 0x006E, 0x0072, 0x0076, 0x007A, 0x007E, 0x0082, 0x0000, - 0x0000, 0x0086, 0x008A, 0x008E, 0x0092, 0x0096, 0x0000, 0x0000, - 0x009A, 0x009E, 0x00A2, 0x00A6, 0x00AA, 0x00AE, 0x0000, 0x00B2, - 0x00B6, 0x00BA, 0x00BE, 0x00C2, 0x00C6, 0x00CA, 0x00CE, 0x00D2, - 0x0000, 0x00D6, 0x00DA, 0x00DE, 0x00E2, 0x00E6, 0x00EA, 0x0000, - 0x0000, 0x00EE, 0x00F2, 0x00F6, 0x00FA, 0x00FE, 0x0000, 0x0102, - // Block 5 - 0x0106, 0x010A, 0x010E, 0x0112, 0x0116, 0x011A, 0x011E, 0x0122, - 0x0126, 0x012A, 0x012E, 0x0132, 0x0136, 0x013A, 0x013E, 0x0142, - 0x0000, 0x0000, 0x0146, 0x014A, 0x014E, 0x0152, 0x0156, 0x015A, - 0x015E, 0x0162, 0x0166, 0x016A, 0x016E, 0x0172, 0x0176, 0x017A, - 0x017E, 0x0182, 0x0186, 0x018A, 0x018E, 0x0192, 0x0000, 0x0000, - 0x0196, 0x019A, 0x019E, 0x01A2, 0x01A6, 0x01AA, 0x01AE, 0x01B2, - 0x01B6, 0x0000, 0x01BA, 0x01BD, 0x01C0, 0x01C4, 0x01C8, 0x01CC, - 0x0000, 0x01D0, 0x01D4, 0x01D8, 0x01DC, 0x01E0, 0x01E4, 0x01E8, - // Block 6 - 0x01EC, 0x0000, 0x0000, 0x01F0, 0x01F4, 0x01F8, 0x01FC, 0x0200, - 0x0204, 0x0208, 0x0000, 0x0000, 0x020C, 0x0210, 0x0214, 0x0218, - 0x021C, 0x0220, 0x0000, 0x0000, 0x0224, 0x0228, 0x022C, 0x0230, - 0x0234, 0x0238, 0x023C, 0x0240, 0x0244, 0x0248, 0x024C, 0x0250, - 0x0254, 0x0258, 0x025C, 0x0260, 0x0264, 0x0268, 0x0000, 0x0000, - 0x026C, 0x0270, 0x0274, 0x0278, 0x027C, 0x0280, 0x0284, 0x0288, - 0x028C, 0x0290, 0x0294, 0x0298, 0x029C, 0x02A0, 0x02A4, 0x02A8, - 0x02AC, 0x02B0, 0x02B4, 0x02B8, 0x02BC, 0x02C0, 0x02C4, 0x02C8, - // Block 7 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x02CA, 0x02CE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02D2, - 0x02D6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 8 - 0x0000, 0x0000, 0x0000, 0x0000, 0x02DA, 0x02DF, 0x02E4, 0x02E9, - 0x02EC, 0x02EF, 0x02F2, 0x02F5, 0x02F8, 0x02FB, 0x02FF, 0x0303, - 0x0307, 0x030B, 0x030F, 0x0313, 0x0317, 0x031B, 0x0321, 0x0327, - 0x032D, 0x0333, 0x0339, 0x033F, 0x0345, 0x0000, 0x034B, 0x0351, - 0x0357, 0x035D, 0x0363, 0x0368, 0x0000, 0x0000, 0x036D, 0x0371, - 0x0375, 0x0379, 0x037D, 0x0381, 0x0385, 0x038B, 0x0391, 0x0396, - 0x039B, 0x039F, 0x03A2, 0x03A5, 0x03A8, 0x03AC, 0x0000, 0x0000, - 0x03B0, 0x03B4, 0x03B8, 0x03BE, 0x03C4, 0x03C9, 0x03CE, 0x03D3, - // Block 9 - 0x03D8, 0x03DC, 0x03E0, 0x03E4, 0x03E8, 0x03EC, 0x03F0, 0x03F4, - 0x03F8, 0x03FC, 0x0400, 0x0404, 0x0408, 0x040C, 0x0410, 0x0414, - 0x0418, 0x041C, 0x0420, 0x0424, 0x0428, 0x042C, 0x0430, 0x0434, - 0x0438, 0x043C, 0x0440, 0x0444, 0x0000, 0x0000, 0x0448, 0x044C, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0450, 0x0454, - 0x0458, 0x045C, 0x0460, 0x0466, 0x046C, 0x0472, 0x0478, 0x047C, - 0x0480, 0x0486, 0x048C, 0x0490, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0494, 0x0496, 0x0499, 0x049B, 0x049D, 0x04A0, 0x04A3, 0x04A6, - 0x04A8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x04AA, 0x04AE, 0x04B2, 0x04B6, 0x04BA, 0x04BE, 0x0000, 0x0000, - 0x04C2, 0x04C5, 0x02C8, 0x04C7, 0x04C9, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block C - 0x04CC, 0x04CF, 0x0000, 0x04D2, 0x04D5, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x04DA, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x04DD, 0x0000, 0x0000, 0x0000, 0x04E1, 0x0000, - // Block D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0011, 0x04E8, 0x04EE, 0x04F3, - 0x04F6, 0x04FB, 0x0500, 0x0000, 0x0505, 0x0000, 0x050A, 0x050F, - 0x0514, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x051B, 0x0520, 0x0525, 0x052A, 0x052F, 0x0534, - 0x0539, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0540, 0x0545, 0x054A, 0x054F, 0x0554, 0x0000, - 0x0559, 0x055C, 0x055F, 0x050A, 0x0520, 0x056C, 0x056F, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0572, 0x0575, 0x0578, 0x0000, 0x057B, 0x057E, 0x0000, 0x0000, - 0x0000, 0x0581, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block F - 0x0584, 0x0589, 0x0000, 0x058E, 0x0000, 0x0000, 0x0000, 0x0593, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0598, 0x059D, 0x05A2, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x05A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x05AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 10 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x05B1, 0x05B6, 0x0000, 0x05BB, 0x0000, 0x0000, 0x0000, 0x05C0, - 0x0000, 0x0000, 0x0000, 0x0000, 0x05C5, 0x05CA, 0x05CF, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x05D4, 0x05D9, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 11 - 0x0000, 0x05DE, 0x05E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x05E8, 0x05ED, 0x05F2, 0x05F7, 0x0000, 0x0000, 0x05FC, 0x0601, - 0x0000, 0x0000, 0x0606, 0x060B, 0x0610, 0x0615, 0x061A, 0x061F, - 0x0000, 0x0000, 0x0624, 0x0629, 0x062E, 0x0633, 0x0638, 0x063D, - 0x0000, 0x0000, 0x0642, 0x0647, 0x064C, 0x0651, 0x0656, 0x065B, - 0x0660, 0x0665, 0x066A, 0x066F, 0x0674, 0x0679, 0x0000, 0x0000, - 0x067E, 0x0683, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 12 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0688, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 13 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x068D, 0x0692, 0x0697, 0x069C, 0x06A1, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 14 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x06A6, 0x06AB, 0x06B0, - 0x06B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 15 - 0x06BA, 0x0000, 0x06BF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x06C4, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 16 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x06C9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x06D0, 0x0000, 0x0000, 0x06D7, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 17 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x06DE, 0x06E5, 0x06EC, 0x06F3, 0x06FA, 0x0701, 0x0708, 0x070F, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 18 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0716, 0x071D, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0724, 0x072B, 0x0000, 0x0732, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 19 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0739, 0x0000, 0x0000, 0x0740, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0747, 0x074E, 0x0755, 0x0000, 0x0000, 0x075C, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0763, 0x0000, 0x0000, 0x076A, 0x0771, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0778, 0x077F, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0786, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x078D, 0x0794, 0x079B, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x07A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1F - 0x07A9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07B0, - 0x07B7, 0x0000, 0x07BE, 0x07C5, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 20 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x07CF, 0x07D6, 0x07DD, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 21 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x07E4, 0x0000, 0x07EB, 0x07F2, 0x07FC, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 22 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0803, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 23 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x080A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 24 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0811, 0x0818, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 25 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x081F, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 26 - 0x0000, 0x0000, 0x0000, 0x0823, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x082A, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0831, 0x0000, 0x0000, 0x0000, 0x0000, 0x0838, - 0x0000, 0x0000, 0x0000, 0x0000, 0x083F, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0846, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x084D, 0x0000, 0x0854, 0x085B, 0x0862, - 0x086C, 0x0873, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 27 - 0x0000, 0x087D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0884, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x088B, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0892, 0x0000, 0x0000, 0x0000, 0x0000, 0x0899, - 0x0000, 0x0000, 0x0000, 0x0000, 0x08A0, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x08A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 28 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x08AE, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 29 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x08B5, 0x0000, 0x0000, 0x0000, - // Block 2A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x08B9, 0x0000, - 0x08C0, 0x0000, 0x08C7, 0x0000, 0x08CE, 0x0000, 0x08D5, 0x0000, - 0x0000, 0x0000, 0x08DC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x08E3, 0x0000, 0x08EA, 0x0000, 0x0000, - // Block 2B - 0x08F1, 0x08F8, 0x0000, 0x08FF, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0906, 0x0908, 0x090B, 0x0000, - 0x090D, 0x090F, 0x0911, 0x0914, 0x0916, 0x0918, 0x091A, 0x091C, - 0x091E, 0x0920, 0x0922, 0x0000, 0x0924, 0x0926, 0x0929, 0x092B, - // Block 2D - 0x092D, 0x092F, 0x0931, 0x0007, 0x0933, 0x0936, 0x0939, 0x093D, - 0x093F, 0x0941, 0x0943, 0x0946, 0x0949, 0x094C, 0x0000, 0x094E, - 0x0950, 0x0952, 0x001E, 0x0955, 0x0958, 0x095C, 0x0960, 0x0962, - 0x0964, 0x0966, 0x096A, 0x096D, 0x096F, 0x0559, 0x0973, 0x0976, - 0x056C, 0x0979, 0x097C, 0x049B, 0x0964, 0x096D, 0x0559, 0x0973, - 0x0575, 0x056C, 0x0979, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x097E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0981, 0x0984, 0x0986, 0x0989, 0x0949, - 0x098C, 0x098E, 0x0991, 0x0994, 0x0997, 0x099A, 0x099D, 0x09A0, - 0x09A4, 0x09A7, 0x09AA, 0x09AE, 0x09B1, 0x09B4, 0x09B7, 0x09BA, - 0x09BD, 0x09C0, 0x09C3, 0x09C6, 0x09C9, 0x09CC, 0x09CF, 0x09D2, - 0x09D5, 0x09D9, 0x09DC, 0x09DF, 0x09E1, 0x09E4, 0x09E7, 0x055C, - // Block 2F - 0x09EA, 0x09EE, 0x09F2, 0x09F6, 0x09FA, 0x09FE, 0x0A02, 0x0A06, - 0x0A0A, 0x0A10, 0x0A16, 0x0A1A, 0x0A1E, 0x0A22, 0x0A26, 0x0A2A, - 0x0A2E, 0x0A32, 0x0A36, 0x0A3A, 0x0A3E, 0x0A44, 0x0A4A, 0x0A50, - 0x0A56, 0x0A5A, 0x0A5E, 0x0A62, 0x0A66, 0x0A6C, 0x0A72, 0x0A76, - 0x0A7A, 0x0A7E, 0x0A82, 0x0A86, 0x0A8A, 0x0A8E, 0x0A92, 0x0A96, - 0x0A9A, 0x0A9E, 0x0AA2, 0x0AA6, 0x0AAA, 0x0AAE, 0x0AB2, 0x0AB8, - 0x0ABE, 0x0AC2, 0x0AC6, 0x0ACA, 0x0ACE, 0x0AD2, 0x0AD6, 0x0ADA, - 0x0ADE, 0x0AE4, 0x0AEA, 0x0AEE, 0x0AF2, 0x0AF6, 0x0AFA, 0x0AFE, - // Block 30 - 0x0B02, 0x0B06, 0x0B0A, 0x0B0E, 0x0B12, 0x0B16, 0x0B1A, 0x0B1E, - 0x0B22, 0x0B26, 0x0B2A, 0x0B2E, 0x0B32, 0x0B38, 0x0B3E, 0x0B44, - 0x0B4A, 0x0B50, 0x0B56, 0x0B5C, 0x0B62, 0x0B66, 0x0B6A, 0x0B6E, - 0x0B72, 0x0B76, 0x0B7A, 0x0B7E, 0x0B82, 0x0B88, 0x0B8E, 0x0B92, - 0x0B96, 0x0B9A, 0x0B9E, 0x0BA2, 0x0BA6, 0x0BAC, 0x0BB2, 0x0BB8, - 0x0BBE, 0x0BC4, 0x0BCA, 0x0BCE, 0x0BD2, 0x0BD6, 0x0BDA, 0x0BDE, - 0x0BE2, 0x0BE6, 0x0BEA, 0x0BEE, 0x0BF2, 0x0BF6, 0x0BFA, 0x0BFE, - 0x0C02, 0x0C08, 0x0C0E, 0x0C14, 0x0C1A, 0x0C1E, 0x0C22, 0x0C26, - // Block 31 - 0x0C2A, 0x0C2E, 0x0C32, 0x0C36, 0x0C3A, 0x0C3E, 0x0C42, 0x0C46, - 0x0C4A, 0x0C4E, 0x0C52, 0x0C56, 0x0C5A, 0x0C5E, 0x0C62, 0x0C66, - 0x0C6A, 0x0C6E, 0x0C72, 0x0C76, 0x0C7A, 0x0C7E, 0x0C82, 0x0C86, - 0x0C8A, 0x0C8E, 0x0C92, 0x0B9A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0C9B, 0x0C9F, 0x0CA3, 0x0CA7, 0x0CAB, 0x0CB1, 0x0CB7, 0x0CBD, - 0x0CC3, 0x0CC9, 0x0CCF, 0x0CD5, 0x0CDB, 0x0CE1, 0x0CE7, 0x0CED, - 0x0CF3, 0x0CF9, 0x0CFF, 0x0D05, 0x0D0B, 0x0D11, 0x0D17, 0x0D1D, - 0x0D23, 0x0D27, 0x0D2B, 0x0D2F, 0x0D33, 0x0D37, 0x0D3B, 0x0D41, - // Block 32 - 0x0D47, 0x0D4D, 0x0D53, 0x0D59, 0x0D5F, 0x0D65, 0x0D6B, 0x0D71, - 0x0D77, 0x0D7B, 0x0D7F, 0x0D83, 0x0D87, 0x0D8B, 0x0D8F, 0x0D93, - 0x0D97, 0x0D9D, 0x0DA3, 0x0DA9, 0x0DAF, 0x0DB5, 0x0DBB, 0x0DC1, - 0x0DC7, 0x0DCD, 0x0DD3, 0x0DD9, 0x0DDF, 0x0DE5, 0x0DEB, 0x0DF1, - 0x0DF7, 0x0DFD, 0x0E03, 0x0E09, 0x0E0F, 0x0E13, 0x0E17, 0x0E1B, - 0x0E1F, 0x0E25, 0x0E2B, 0x0E31, 0x0E37, 0x0E3D, 0x0E43, 0x0E49, - 0x0E4F, 0x0E55, 0x0E5B, 0x0E5F, 0x0E63, 0x0E67, 0x0E6B, 0x0E6F, - 0x0E73, 0x0E77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 33 - 0x0E7B, 0x0E80, 0x0E85, 0x0E8C, 0x0E93, 0x0E9A, 0x0EA1, 0x0EA8, - 0x0EAF, 0x0EB4, 0x0EB9, 0x0EC0, 0x0EC7, 0x0ECE, 0x0ED5, 0x0EDC, - 0x0EE3, 0x0EE8, 0x0EED, 0x0EF4, 0x0EFB, 0x0F02, 0x0000, 0x0000, - 0x0F09, 0x0F0E, 0x0F13, 0x0F1A, 0x0F21, 0x0F28, 0x0000, 0x0000, - 0x0F2F, 0x0F34, 0x0F39, 0x0F40, 0x0F47, 0x0F4E, 0x0F55, 0x0F5C, - 0x0F63, 0x0F68, 0x0F6D, 0x0F74, 0x0F7B, 0x0F82, 0x0F89, 0x0F90, - 0x0F97, 0x0F9C, 0x0FA1, 0x0FA8, 0x0FAF, 0x0FB6, 0x0FBD, 0x0FC4, - 0x0FCB, 0x0FD0, 0x0FD5, 0x0FDC, 0x0FE3, 0x0FEA, 0x0FF1, 0x0FF8, - // Block 34 - 0x0FFF, 0x1004, 0x1009, 0x1010, 0x1017, 0x101E, 0x0000, 0x0000, - 0x1025, 0x102A, 0x102F, 0x1036, 0x103D, 0x1044, 0x0000, 0x0000, - 0x104B, 0x1050, 0x1055, 0x105C, 0x1063, 0x106A, 0x1071, 0x1078, - 0x0000, 0x107F, 0x0000, 0x1084, 0x0000, 0x108B, 0x0000, 0x1092, - 0x1099, 0x109E, 0x10A3, 0x10AA, 0x10B1, 0x10B8, 0x10BF, 0x10C6, - 0x10CD, 0x10D2, 0x10D7, 0x10DE, 0x10E5, 0x10EC, 0x10F3, 0x10FA, - 0x1101, 0x0525, 0x1106, 0x052A, 0x110B, 0x052F, 0x1110, 0x0534, - 0x1115, 0x054A, 0x111A, 0x054F, 0x111F, 0x0554, 0x0000, 0x0000, - // Block 35 - 0x1124, 0x112B, 0x1132, 0x113B, 0x1144, 0x114D, 0x1156, 0x115F, - 0x1168, 0x116F, 0x1176, 0x117F, 0x1188, 0x1191, 0x119A, 0x11A3, - 0x11AC, 0x11B3, 0x11BA, 0x11C3, 0x11CC, 0x11D5, 0x11DE, 0x11E7, - 0x11F0, 0x11F7, 0x11FE, 0x1207, 0x1210, 0x1219, 0x1222, 0x122B, - 0x1234, 0x123B, 0x1242, 0x124B, 0x1254, 0x125D, 0x1266, 0x126F, - 0x1278, 0x127F, 0x1286, 0x128F, 0x1298, 0x12A1, 0x12AA, 0x12B3, - 0x12BC, 0x12C1, 0x12C6, 0x12CD, 0x12D2, 0x0000, 0x12D9, 0x12DE, - 0x12E5, 0x12EA, 0x12EF, 0x04EE, 0x12F4, 0x12F9, 0x12FD, 0x12F9, - // Block 36 - 0x1300, 0x1309, 0x130F, 0x1316, 0x131B, 0x0000, 0x1322, 0x1327, - 0x132E, 0x04F6, 0x1333, 0x04FB, 0x1338, 0x1343, 0x134F, 0x135B, - 0x1361, 0x1366, 0x136B, 0x0514, 0x0000, 0x0000, 0x1372, 0x1377, - 0x137E, 0x1383, 0x1388, 0x0500, 0x0000, 0x1393, 0x139F, 0x13AB, - 0x13B1, 0x13B6, 0x13BB, 0x0539, 0x13C2, 0x13C7, 0x13CC, 0x13D1, - 0x13D8, 0x13DD, 0x13E2, 0x050A, 0x13E7, 0x13F1, 0x04E8, 0x13F7, - 0x0000, 0x0000, 0x13F9, 0x1400, 0x1405, 0x0000, 0x140C, 0x1411, - 0x1418, 0x0505, 0x141D, 0x050F, 0x1422, 0x0011, 0x142A, 0x0000, - // Block 37 - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x1436, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x143A, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x143E, 0x1440, 0x1443, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, - 0x0000, 0x0000, 0x0000, 0x1447, 0x144E, 0x0000, 0x1458, 0x145F, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1469, 0x0000, 0x146C, 0x0000, - // Block 38 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1470, - 0x1473, 0x1476, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1479, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1486, 0x097C, 0x0000, 0x0000, 0x1488, 0x148A, 0x148C, 0x148E, - 0x1490, 0x1492, 0x1494, 0x1496, 0x149A, 0x149C, 0x149E, 0x14A0, - // Block 39 - 0x1486, 0x001C, 0x000D, 0x000F, 0x1488, 0x148A, 0x148C, 0x148E, - 0x1490, 0x1492, 0x1494, 0x1496, 0x149A, 0x149C, 0x149E, 0x0000, - 0x0007, 0x0941, 0x001E, 0x04C7, 0x0943, 0x0494, 0x094E, 0x04C5, - 0x0950, 0x14A0, 0x0960, 0x02C8, 0x0962, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x14A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3A - 0x14A5, 0x14A9, 0x14AD, 0x14AF, 0x0000, 0x14B3, 0x14B7, 0x14BB, - 0x0000, 0x14BE, 0x094C, 0x0916, 0x0916, 0x0916, 0x0494, 0x14C2, - 0x0918, 0x0918, 0x091E, 0x04C5, 0x0000, 0x0922, 0x14C5, 0x0000, - 0x0000, 0x0929, 0x14C8, 0x092B, 0x092B, 0x092B, 0x0000, 0x0000, - 0x14CA, 0x14CD, 0x14D1, 0x0000, 0x14D4, 0x0000, 0x14D6, 0x0000, - 0x14D4, 0x0000, 0x091C, 0x0046, 0x090B, 0x14AD, 0x0000, 0x0941, - 0x090F, 0x14D9, 0x0000, 0x0920, 0x001E, 0x14DB, 0x14DE, 0x14E1, - 0x14E4, 0x097C, 0x0000, 0x14E7, 0x056F, 0x0973, 0x14EB, 0x14EE, - // Block 3B - 0x14F1, 0x0000, 0x0000, 0x0000, 0x0000, 0x090D, 0x093F, 0x0941, - 0x097C, 0x0499, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x14F5, 0x14FB, 0x1501, 0x1508, 0x150E, 0x1514, 0x151A, 0x1520, - 0x1526, 0x152C, 0x1532, 0x1538, 0x153E, 0x1544, 0x154A, 0x1550, - 0x0918, 0x1555, 0x1558, 0x155C, 0x155F, 0x1561, 0x1564, 0x1568, - 0x156D, 0x1570, 0x1572, 0x1575, 0x091E, 0x14AD, 0x090D, 0x0920, - 0x097C, 0x1579, 0x157C, 0x1580, 0x096D, 0x1583, 0x1586, 0x158A, - 0x158F, 0x04C7, 0x1592, 0x1595, 0x04C5, 0x0984, 0x093F, 0x0950, - // Block 3C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x1599, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x159F, 0x15A5, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x15AB, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x15B1, 0x15B7, 0x15BD, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3E - 0x0000, 0x0000, 0x0000, 0x0000, 0x15C3, 0x0000, 0x0000, 0x0000, - 0x0000, 0x15C9, 0x0000, 0x0000, 0x15CF, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x15D5, 0x0000, 0x15DB, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x15E1, 0x15E8, 0x0000, 0x15F2, - 0x15F9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3F - 0x0000, 0x1603, 0x0000, 0x0000, 0x1609, 0x0000, 0x0000, 0x160F, - 0x0000, 0x1615, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x161B, 0x0000, 0x161F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1625, 0x162B, 0x162F, - 0x1633, 0x1639, 0x0000, 0x0000, 0x163F, 0x1645, 0x0000, 0x0000, - 0x164B, 0x1651, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 40 - 0x1657, 0x165D, 0x0000, 0x0000, 0x1663, 0x1669, 0x0000, 0x0000, - 0x166F, 0x1675, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x167B, 0x1681, 0x1687, 0x168D, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 41 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1693, 0x1699, 0x169F, 0x16A5, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x16AB, 0x16B1, 0x16B7, 0x16BD, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 42 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x16C3, 0x16C7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 43 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x001C, 0x000D, 0x000F, 0x1488, 0x148A, 0x148C, 0x148E, 0x1490, - 0x1492, 0x16CB, 0x16CE, 0x16D1, 0x16D4, 0x16D7, 0x16DA, 0x16DD, - 0x16E0, 0x16E3, 0x16E6, 0x16E9, 0x16EC, 0x16F0, 0x16F4, 0x16F8, - 0x16FC, 0x1700, 0x1704, 0x1708, 0x170C, 0x1710, 0x1715, 0x171A, - // Block 44 - 0x171F, 0x1724, 0x1729, 0x172E, 0x1733, 0x1738, 0x173D, 0x1742, - 0x1747, 0x174A, 0x174D, 0x1750, 0x1753, 0x1756, 0x1759, 0x175C, - 0x175F, 0x1762, 0x1766, 0x176A, 0x176E, 0x1772, 0x1776, 0x177A, - 0x177E, 0x1782, 0x1786, 0x178A, 0x178E, 0x1792, 0x1796, 0x179A, - 0x179E, 0x17A2, 0x17A6, 0x17AA, 0x17AE, 0x17B2, 0x17B6, 0x17BA, - 0x17BE, 0x17C2, 0x17C6, 0x17CA, 0x17CE, 0x17D2, 0x17D6, 0x17DA, - 0x17DE, 0x17E2, 0x17E6, 0x17EA, 0x17EE, 0x17F2, 0x0906, 0x090B, - 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, 0x0918, 0x091A, - // Block 45 - 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, 0x14C8, 0x092B, - 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, 0x17F8, 0x14D4, - 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, 0x094C, 0x0494, - 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, 0x001E, 0x0960, - 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, 0x04C7, - 0x04A8, 0x09DF, 0x1486, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 46 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x17FC, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 47 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1809, 0x180D, 0x1810, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 48 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1814, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 49 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0499, 0x155F, 0x0000, 0x0000, - // Block 4A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x181A, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 4B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x181E, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 4C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x1822, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 4D - 0x1826, 0x182A, 0x182E, 0x1832, 0x1836, 0x183A, 0x183E, 0x1842, - 0x1846, 0x184A, 0x184E, 0x1852, 0x1856, 0x185A, 0x185E, 0x1862, - 0x1866, 0x186A, 0x186E, 0x1872, 0x1876, 0x187A, 0x187E, 0x1882, - 0x1886, 0x188A, 0x188E, 0x1892, 0x1896, 0x189A, 0x189E, 0x18A2, - 0x18A6, 0x18AA, 0x18AE, 0x18B2, 0x18B6, 0x18BA, 0x18BE, 0x18C2, - 0x18C6, 0x18CA, 0x18CE, 0x18D2, 0x18D6, 0x18DA, 0x18DE, 0x18E2, - 0x18E6, 0x18EA, 0x18EE, 0x18F2, 0x18F6, 0x18FA, 0x18FE, 0x1902, - 0x1906, 0x190A, 0x190E, 0x1912, 0x1916, 0x191A, 0x191E, 0x1922, - // Block 4E - 0x1926, 0x192A, 0x192E, 0x1932, 0x1936, 0x193A, 0x193E, 0x1942, - 0x1946, 0x194A, 0x194E, 0x1952, 0x1956, 0x195A, 0x195E, 0x1962, - 0x1966, 0x196A, 0x196E, 0x1972, 0x1976, 0x197A, 0x197E, 0x1982, - 0x1986, 0x198A, 0x198E, 0x1992, 0x1996, 0x199A, 0x199E, 0x19A2, - 0x19A6, 0x19AA, 0x19AE, 0x19B2, 0x19B6, 0x19BA, 0x19BE, 0x19C2, - 0x19C6, 0x19CA, 0x19CE, 0x19D2, 0x19D6, 0x19DA, 0x19DE, 0x19E2, - 0x19E6, 0x19EA, 0x19EE, 0x19F2, 0x19F6, 0x19FA, 0x19FE, 0x1A02, - 0x1A06, 0x1A0A, 0x1A0E, 0x1A12, 0x1A16, 0x1A1A, 0x1A1E, 0x1A22, - // Block 4F - 0x1A26, 0x1A2A, 0x1A2E, 0x1A32, 0x1A36, 0x1A3A, 0x1A3E, 0x1A42, - 0x1A46, 0x1A4A, 0x1A4E, 0x1A52, 0x1A56, 0x1A5A, 0x1A5E, 0x1A62, - 0x1A66, 0x1A6A, 0x1A6E, 0x1A72, 0x1A76, 0x1A7A, 0x1A7E, 0x1A82, - 0x1A86, 0x1A8A, 0x1A8E, 0x1A92, 0x1A96, 0x1A9A, 0x1A9E, 0x1AA2, - 0x1AA6, 0x1AAA, 0x1AAE, 0x1AB2, 0x1AB6, 0x1ABA, 0x1ABE, 0x1AC2, - 0x1AC6, 0x1ACA, 0x1ACE, 0x1AD2, 0x1AD6, 0x1ADA, 0x1ADE, 0x1AE2, - 0x1AE6, 0x1AEA, 0x1AEE, 0x1AF2, 0x1AF6, 0x1AFA, 0x1AFE, 0x1B02, - 0x1B06, 0x1B0A, 0x1B0E, 0x1B12, 0x1B16, 0x1B1A, 0x1B1E, 0x1B22, - // Block 50 - 0x1B26, 0x1B2A, 0x1B2E, 0x1B32, 0x1B36, 0x1B3A, 0x1B3E, 0x1B42, - 0x1B46, 0x1B4A, 0x1B4E, 0x1B52, 0x1B56, 0x1B5A, 0x1B5E, 0x1B62, - 0x1B66, 0x1B6A, 0x1B6E, 0x1B72, 0x1B76, 0x1B7A, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 51 - 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1B7E, 0x0000, - 0x1882, 0x1B82, 0x1B86, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 52 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1B8A, 0x0000, 0x1B91, 0x0000, - 0x1B98, 0x0000, 0x1B9F, 0x0000, 0x1BA6, 0x0000, 0x1BAD, 0x0000, - 0x1BB4, 0x0000, 0x1BBB, 0x0000, 0x1BC2, 0x0000, 0x1BC9, 0x0000, - 0x1BD0, 0x0000, 0x1BD7, 0x0000, 0x0000, 0x1BDE, 0x0000, 0x1BE5, - 0x0000, 0x1BEC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1BF3, 0x1BFA, 0x0000, 0x1C01, 0x1C08, 0x0000, 0x1C0F, 0x1C16, - 0x0000, 0x1C1D, 0x1C24, 0x0000, 0x1C2B, 0x1C32, 0x0000, 0x0000, - // Block 53 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1C39, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x1C40, 0x1C45, 0x0000, 0x1C4A, 0x1C51, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1C58, 0x0000, 0x1C5F, 0x0000, - 0x1C66, 0x0000, 0x1C6D, 0x0000, 0x1C74, 0x0000, 0x1C7B, 0x0000, - 0x1C82, 0x0000, 0x1C89, 0x0000, 0x1C90, 0x0000, 0x1C97, 0x0000, - // Block 54 - 0x1C9E, 0x0000, 0x1CA5, 0x0000, 0x0000, 0x1CAC, 0x0000, 0x1CB3, - 0x0000, 0x1CBA, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1CC1, 0x1CC8, 0x0000, 0x1CCF, 0x1CD6, 0x0000, 0x1CDD, 0x1CE4, - 0x0000, 0x1CEB, 0x1CF2, 0x0000, 0x1CF9, 0x1D00, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1D07, 0x0000, 0x0000, 0x1D0E, - 0x1D15, 0x1D1C, 0x1D23, 0x0000, 0x0000, 0x0000, 0x1D2A, 0x1D31, - // Block 55 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x1D38, 0x1D3C, 0x1D40, 0x1D44, 0x1D48, 0x1D4C, 0x1D50, - 0x1D54, 0x1D58, 0x1D5C, 0x1D60, 0x1D64, 0x1D68, 0x1D6C, 0x1D70, - // Block 56 - 0x1D74, 0x1D78, 0x1D7C, 0x1D80, 0x1D84, 0x1D88, 0x1D8C, 0x1D90, - 0x1D94, 0x1D98, 0x1D9C, 0x1DA0, 0x1DA4, 0x1DA8, 0x1DAC, 0x1DB0, - 0x1DB4, 0x1DB8, 0x1DBC, 0x1DC0, 0x1DC4, 0x1DC8, 0x1DCC, 0x1DD0, - 0x1DD4, 0x1DD8, 0x1DDC, 0x1DE0, 0x1DE4, 0x1DE8, 0x1DEC, 0x1DF0, - 0x1DF4, 0x1DF8, 0x1DFC, 0x1E00, 0x1E04, 0x1E08, 0x1E0C, 0x1E10, - 0x1E14, 0x1E18, 0x1E1C, 0x1E20, 0x1E24, 0x1E28, 0x1E2C, 0x1E30, - 0x1E34, 0x1E38, 0x1E3C, 0x1E40, 0x1E44, 0x1E48, 0x1E4C, 0x1E50, - 0x1E54, 0x1E58, 0x1E5C, 0x1E60, 0x1E64, 0x1E68, 0x1E6C, 0x1E70, - // Block 57 - 0x1E74, 0x1E78, 0x1E7C, 0x1E80, 0x1E84, 0x1E88, 0x1E8C, 0x1E90, - 0x1E94, 0x1E98, 0x1E9C, 0x1EA0, 0x1EA4, 0x1EA8, 0x1EAC, 0x0000, - 0x0000, 0x0000, 0x1826, 0x183E, 0x1EB0, 0x1EB4, 0x1EB8, 0x1EBC, - 0x1EC0, 0x1EC4, 0x1836, 0x1EC8, 0x1ECC, 0x1ED0, 0x1ED4, 0x1846, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 58 - 0x1ED8, 0x1EDE, 0x1EE4, 0x1EEA, 0x1EF0, 0x1EF6, 0x1EFC, 0x1F02, - 0x1F08, 0x1F0E, 0x1F14, 0x1F1A, 0x1F20, 0x1F26, 0x1F2C, 0x1F35, - 0x1F3E, 0x1F47, 0x1F50, 0x1F59, 0x1F62, 0x1F6B, 0x1F74, 0x1F7D, - 0x1F86, 0x1F8F, 0x1F98, 0x1FA1, 0x1FAA, 0x1FB3, 0x1FC5, 0x0000, - 0x1FD4, 0x1FDA, 0x1FE0, 0x1FE6, 0x1FEC, 0x1FF2, 0x1FF8, 0x1FFE, - 0x2004, 0x200A, 0x2010, 0x2016, 0x201C, 0x2022, 0x2028, 0x202E, - 0x2034, 0x203A, 0x2040, 0x2046, 0x204C, 0x2052, 0x2058, 0x205E, - 0x2064, 0x206A, 0x2070, 0x2076, 0x207C, 0x2082, 0x2088, 0x208E, - // Block 59 - 0x2094, 0x209A, 0x20A0, 0x20A6, 0x20AC, 0x20B0, 0x192E, 0x20B4, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x20B8, 0x20BC, 0x20BF, 0x20C2, 0x20C5, 0x20C8, 0x20CB, 0x20CE, - 0x20D1, 0x20D4, 0x20D7, 0x20DA, 0x20DD, 0x20E0, 0x20E3, 0x20E6, - 0x1D38, 0x1D44, 0x1D50, 0x1D58, 0x1D78, 0x1D7C, 0x1D88, 0x1D90, - 0x1D94, 0x1D9C, 0x1DA0, 0x1DA4, 0x1DA8, 0x1DAC, 0x20E9, 0x20F0, - 0x20F7, 0x20FE, 0x2105, 0x210C, 0x2113, 0x211A, 0x2121, 0x2128, - 0x212F, 0x2136, 0x213D, 0x2144, 0x214B, 0x215B, 0x2168, 0x0000, - // Block 5A - 0x1826, 0x183E, 0x1EB0, 0x1EB4, 0x216F, 0x2173, 0x2177, 0x1852, - 0x217B, 0x1882, 0x194A, 0x197A, 0x1976, 0x194E, 0x1ABE, 0x18A2, - 0x1942, 0x217F, 0x2183, 0x2187, 0x218B, 0x218F, 0x2193, 0x2197, - 0x219B, 0x219F, 0x21A3, 0x18BA, 0x21A7, 0x21AB, 0x21AF, 0x21B3, - 0x21B7, 0x21BB, 0x21BF, 0x21C3, 0x1EB8, 0x1EBC, 0x1EC0, 0x21C7, - 0x21CB, 0x21CF, 0x21D3, 0x21D7, 0x21DB, 0x21DF, 0x21E3, 0x21E7, - 0x21EB, 0x21EF, 0x21F2, 0x21F5, 0x21F8, 0x21FB, 0x21FE, 0x2201, - 0x2204, 0x2207, 0x220A, 0x220D, 0x2210, 0x2213, 0x2216, 0x2219, - // Block 5B - 0x221C, 0x2221, 0x2226, 0x222B, 0x2230, 0x2235, 0x223A, 0x223F, - 0x2244, 0x2249, 0x224F, 0x2255, 0x225B, 0x225E, 0x2262, 0x2265, - 0x2269, 0x226D, 0x2271, 0x2275, 0x2279, 0x227D, 0x2281, 0x2285, - 0x2289, 0x228D, 0x2291, 0x2295, 0x2299, 0x229D, 0x22A1, 0x22A5, - 0x22A9, 0x22AD, 0x22B1, 0x22B5, 0x22B9, 0x22BD, 0x22C1, 0x22C5, - 0x22C9, 0x22CD, 0x22D1, 0x22D5, 0x22D9, 0x22DD, 0x22E1, 0x22E5, - 0x22E9, 0x22ED, 0x22F1, 0x22F5, 0x22F9, 0x22FD, 0x2301, 0x2305, - 0x2309, 0x230D, 0x2311, 0x2315, 0x2319, 0x231D, 0x2321, 0x0000, - // Block 5C - 0x2325, 0x2335, 0x2342, 0x2352, 0x235C, 0x236C, 0x2376, 0x2380, - 0x2393, 0x23A0, 0x23AA, 0x23B4, 0x23BE, 0x23CB, 0x23D8, 0x23E5, - 0x23F2, 0x23FF, 0x240C, 0x2419, 0x242C, 0x2433, 0x2446, 0x2459, - 0x2469, 0x2476, 0x2489, 0x249C, 0x24A9, 0x24B3, 0x24BD, 0x24CA, - 0x24D7, 0x24E7, 0x24F7, 0x2501, 0x250B, 0x2518, 0x2522, 0x252C, - 0x2533, 0x253A, 0x2544, 0x254E, 0x2561, 0x256E, 0x257E, 0x2591, - 0x259E, 0x25A8, 0x25B2, 0x25C5, 0x25D2, 0x25E5, 0x25EF, 0x25FF, - 0x2609, 0x2616, 0x2620, 0x262D, 0x263D, 0x264A, 0x265A, 0x2667, - // Block 5D - 0x266E, 0x267E, 0x2688, 0x2692, 0x269F, 0x26A9, 0x26B3, 0x26BD, - 0x26CD, 0x26DA, 0x26E1, 0x26F4, 0x26FE, 0x270E, 0x271B, 0x2728, - 0x2732, 0x273C, 0x2749, 0x2750, 0x275D, 0x276D, 0x2774, 0x2787, - 0x2791, 0x2796, 0x279B, 0x27A0, 0x27A5, 0x27AA, 0x27AF, 0x27B4, - 0x27B9, 0x27BE, 0x27C3, 0x27C9, 0x27CF, 0x27D5, 0x27DB, 0x27E1, - 0x27E7, 0x27ED, 0x27F3, 0x27F9, 0x27FF, 0x2805, 0x280B, 0x2811, - 0x2817, 0x281D, 0x2821, 0x2824, 0x2827, 0x282B, 0x282E, 0x2831, - 0x2834, 0x2838, 0x283C, 0x283F, 0x2846, 0x284D, 0x2854, 0x285B, - // Block 5E - 0x2868, 0x286B, 0x286E, 0x2872, 0x2875, 0x2878, 0x287B, 0x287E, - 0x2881, 0x2885, 0x288A, 0x288D, 0x2890, 0x2894, 0x2898, 0x289B, - 0x289E, 0x28A1, 0x28A5, 0x28A9, 0x28AD, 0x28B1, 0x28B5, 0x28B8, - 0x28BB, 0x28BE, 0x28C1, 0x28C4, 0x28C8, 0x28CB, 0x28CE, 0x28D1, - 0x28D5, 0x28D9, 0x28DC, 0x28E0, 0x28E4, 0x28E8, 0x28EB, 0x28EF, - 0x28F5, 0x28FC, 0x28FF, 0x2903, 0x2907, 0x290B, 0x290F, 0x2917, - 0x2920, 0x2923, 0x2926, 0x292A, 0x292D, 0x2930, 0x2933, 0x2937, - 0x293A, 0x293D, 0x2940, 0x2943, 0x2946, 0x294A, 0x294D, 0x2950, - // Block 5F - 0x2953, 0x2957, 0x295B, 0x2960, 0x2963, 0x2966, 0x2969, 0x2970, - 0x2974, 0x2977, 0x297A, 0x297D, 0x2980, 0x2983, 0x2986, 0x2989, - 0x298C, 0x298F, 0x2992, 0x2996, 0x2999, 0x299C, 0x29A0, 0x29A4, - 0x29A7, 0x29AC, 0x29B0, 0x29B3, 0x29B6, 0x29B9, 0x29BC, 0x29C2, - 0x29C8, 0x29CD, 0x29D2, 0x29D7, 0x29DC, 0x29E1, 0x29E6, 0x29EB, - 0x29F0, 0x29F5, 0x29FB, 0x2A01, 0x2A07, 0x2A0D, 0x2A13, 0x2A19, - 0x2A1F, 0x2A25, 0x2A2B, 0x2A31, 0x2A37, 0x2A3D, 0x2A43, 0x2A49, - 0x2A4F, 0x2A55, 0x2A5B, 0x2A61, 0x2A67, 0x2A6D, 0x2A73, 0x2A79, - // Block 60 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x2A7D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 61 - 0x2A81, 0x2A85, 0x1A9E, 0x2A89, 0x2A8D, 0x2A91, 0x2A95, 0x1B76, - 0x1B76, 0x2A99, 0x1ABE, 0x2A9D, 0x2AA1, 0x2AA5, 0x2AA9, 0x2AAD, - 0x2AB1, 0x2AB5, 0x2AB9, 0x2ABD, 0x2AC1, 0x2AC5, 0x2AC9, 0x2ACD, - 0x2AD1, 0x2AD5, 0x2AD9, 0x2ADD, 0x2AE1, 0x2AE5, 0x2AE9, 0x2AED, - 0x2AF1, 0x2AF5, 0x2AF9, 0x2AFD, 0x2B01, 0x2B05, 0x2B09, 0x2B0D, - 0x2B11, 0x2B15, 0x2B19, 0x2B1D, 0x2B21, 0x2B25, 0x2B29, 0x2B2D, - 0x2B31, 0x2B35, 0x2B39, 0x2B3D, 0x1A16, 0x2B41, 0x2B45, 0x2B49, - 0x2B4D, 0x2B51, 0x2B55, 0x2B59, 0x2B5D, 0x2B61, 0x2B65, 0x2B69, - // Block 62 - 0x1B3A, 0x2B6D, 0x2B71, 0x2B75, 0x2B79, 0x2B7D, 0x2B81, 0x2B85, - 0x2B89, 0x2B8D, 0x2B91, 0x2B95, 0x2B99, 0x2B9D, 0x2BA1, 0x2BA5, - 0x2BA9, 0x2BAD, 0x2BB1, 0x2BB5, 0x2BB9, 0x2BBD, 0x2BC1, 0x2BC5, - 0x2BC9, 0x2BCD, 0x2BD1, 0x2BD5, 0x2AC1, 0x2BD9, 0x2BDD, 0x2BE1, - 0x2BE5, 0x2BE9, 0x2BED, 0x2BF1, 0x2BF5, 0x2BF9, 0x2BFD, 0x2C01, - 0x2C05, 0x2C09, 0x2C0D, 0x2C11, 0x2C15, 0x2C19, 0x2C1D, 0x2C21, - 0x2C25, 0x1AA6, 0x2C29, 0x2C2D, 0x2C31, 0x2C35, 0x2C39, 0x2C3D, - 0x2C41, 0x2C45, 0x2C49, 0x2C4D, 0x2C51, 0x2C55, 0x2C59, 0x2C5D, - // Block 63 - 0x2C61, 0x18BA, 0x2C65, 0x2C69, 0x2C6D, 0x2C71, 0x2C75, 0x2C79, - 0x2C7D, 0x2C81, 0x186E, 0x2C85, 0x2C89, 0x2C8D, 0x2C91, 0x2C95, - 0x2C99, 0x2C9D, 0x2CA1, 0x2CA5, 0x2CA9, 0x2CAD, 0x2CB1, 0x2CB5, - 0x2CB9, 0x2CBD, 0x2CC1, 0x2CC5, 0x2CC9, 0x2CCD, 0x2CD1, 0x2CD5, - 0x2CD9, 0x2C21, 0x2CDD, 0x2CE1, 0x2CE5, 0x2CE9, 0x2CED, 0x2CF1, - 0x2CF5, 0x2CF9, 0x2BE1, 0x2CFD, 0x2D01, 0x2D05, 0x2D09, 0x2D0D, - 0x2D11, 0x2D15, 0x2D19, 0x2D1D, 0x2D21, 0x2D25, 0x2D29, 0x2D2D, - 0x2D31, 0x2D35, 0x2D39, 0x2D3D, 0x2D41, 0x2D45, 0x2D49, 0x2AC1, - // Block 64 - 0x2D4D, 0x2D51, 0x2D55, 0x2D59, 0x1B72, 0x2D5D, 0x2D61, 0x2D65, - 0x2D69, 0x2D6D, 0x2D71, 0x2D75, 0x2D79, 0x2D7D, 0x2D81, 0x2D85, - 0x2D89, 0x2173, 0x2D8D, 0x2D91, 0x2D95, 0x2D99, 0x2D9D, 0x2DA1, - 0x2DA5, 0x2DA9, 0x2DAD, 0x2BE9, 0x2DB1, 0x2DB5, 0x2DB9, 0x2DBD, - 0x2DC1, 0x2DC5, 0x2DC9, 0x2DCD, 0x2DD1, 0x2DD5, 0x2DD9, 0x2DDD, - 0x2DE1, 0x1ABA, 0x2DE5, 0x2DE9, 0x2DED, 0x2DF1, 0x2DF5, 0x2DF9, - 0x2DFD, 0x2E01, 0x2E05, 0x2E09, 0x2E0D, 0x2E11, 0x2E15, 0x19F6, - 0x2E19, 0x2E1D, 0x2E21, 0x2E25, 0x2E29, 0x2E2D, 0x2E31, 0x2E35, - // Block 65 - 0x2E39, 0x2E3D, 0x2E41, 0x2E45, 0x2E49, 0x2E4D, 0x2E51, 0x2E55, - 0x1A62, 0x2E59, 0x1A6E, 0x2E5D, 0x2E61, 0x2E65, 0x0000, 0x0000, - 0x2E69, 0x0000, 0x2E6D, 0x0000, 0x0000, 0x2E71, 0x2E75, 0x2E79, - 0x2E7D, 0x2E81, 0x2E85, 0x2E89, 0x2E8D, 0x2E91, 0x1A12, 0x0000, - 0x2E95, 0x0000, 0x2E99, 0x0000, 0x0000, 0x2E9D, 0x2EA1, 0x0000, - 0x0000, 0x0000, 0x2EA5, 0x2EA9, 0x2EAD, 0x2EB1, 0x0000, 0x0000, - 0x2EB5, 0x2EB9, 0x2EBD, 0x2EC1, 0x2EC5, 0x2EC9, 0x2ECD, 0x2ED1, - 0x2ED5, 0x2ED9, 0x2EDD, 0x2EE1, 0x18D6, 0x2EE5, 0x2EE9, 0x2EED, - // Block 66 - 0x2EF1, 0x2EF5, 0x2EF9, 0x2EFD, 0x2F01, 0x2F05, 0x2F09, 0x2F0D, - 0x2F11, 0x2F15, 0x2F19, 0x2F1D, 0x2187, 0x2F21, 0x2F25, 0x2F29, - 0x2F2D, 0x2197, 0x2F31, 0x2F35, 0x2F39, 0x2F3D, 0x2F41, 0x2CB1, - 0x2F45, 0x2F49, 0x2F4D, 0x2F51, 0x2F55, 0x2F59, 0x2F59, 0x2F5D, - 0x2F61, 0x2F65, 0x2F69, 0x2F6D, 0x2F71, 0x2F75, 0x2F79, 0x2E9D, - 0x2F7D, 0x2F81, 0x2F85, 0x2F89, 0x2F8D, 0x2F92, 0x0000, 0x0000, - 0x2F96, 0x2F9A, 0x2F9E, 0x2FA2, 0x2FA6, 0x2FAA, 0x2FAE, 0x2FB2, - 0x2ECD, 0x2FB6, 0x2FBA, 0x2FBE, 0x2E69, 0x2FC2, 0x2FC6, 0x2FCA, - // Block 67 - 0x2FCE, 0x2FD2, 0x2FD6, 0x2FDA, 0x2FDE, 0x2FE2, 0x2FE6, 0x2FEA, - 0x2FEE, 0x2EED, 0x2FF2, 0x2EF1, 0x2FF6, 0x2FFA, 0x2FFE, 0x3002, - 0x3006, 0x2E6D, 0x2B15, 0x300A, 0x300E, 0x195A, 0x2C25, 0x2D71, - 0x3012, 0x3016, 0x2F0D, 0x301A, 0x2F11, 0x301E, 0x3022, 0x3026, - 0x2E75, 0x302A, 0x302E, 0x3032, 0x3036, 0x303A, 0x2E79, 0x303E, - 0x3042, 0x3046, 0x304A, 0x304E, 0x3052, 0x2F41, 0x3056, 0x305A, - 0x2CB1, 0x305E, 0x2F51, 0x3062, 0x3066, 0x306A, 0x306E, 0x3072, - 0x2F65, 0x3076, 0x2E99, 0x307A, 0x2F69, 0x2BD9, 0x307E, 0x2F6D, - // Block 68 - 0x3082, 0x2F75, 0x3086, 0x308A, 0x308E, 0x3092, 0x3096, 0x2F7D, - 0x2E8D, 0x309A, 0x2F81, 0x309E, 0x2F85, 0x30A2, 0x1B76, 0x30A6, - 0x30AB, 0x30B0, 0x30B5, 0x30B9, 0x30BD, 0x30C1, 0x30C6, 0x30CB, - 0x30D0, 0x30D4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 69 - 0x30D8, 0x30DB, 0x30DE, 0x30E1, 0x30E5, 0x30E9, 0x30E9, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x30EC, 0x30F1, 0x30F6, 0x30FB, 0x3100, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3105, 0x0000, 0x310A, - 0x310F, 0x14DB, 0x14E4, 0x3112, 0x3115, 0x3118, 0x311B, 0x311E, - 0x3121, 0x1494, 0x3124, 0x3129, 0x312E, 0x3135, 0x313C, 0x3141, - 0x3146, 0x314B, 0x3150, 0x3155, 0x315A, 0x315F, 0x3164, 0x0000, - 0x3169, 0x316E, 0x3173, 0x3178, 0x317D, 0x0000, 0x3182, 0x0000, - // Block 6A - 0x3187, 0x318C, 0x0000, 0x3191, 0x3196, 0x0000, 0x319B, 0x31A0, - 0x31A5, 0x31AA, 0x31AF, 0x31B4, 0x31B9, 0x31BE, 0x31C3, 0x31C8, - 0x31CD, 0x31CD, 0x31D0, 0x31D0, 0x31D0, 0x31D0, 0x31D3, 0x31D3, - 0x31D3, 0x31D3, 0x31D6, 0x31D6, 0x31D6, 0x31D6, 0x31D9, 0x31D9, - 0x31D9, 0x31D9, 0x31DC, 0x31DC, 0x31DC, 0x31DC, 0x31DF, 0x31DF, - 0x31DF, 0x31DF, 0x31E2, 0x31E2, 0x31E2, 0x31E2, 0x31E5, 0x31E5, - 0x31E5, 0x31E5, 0x31E8, 0x31E8, 0x31E8, 0x31E8, 0x31EB, 0x31EB, - 0x31EB, 0x31EB, 0x31EE, 0x31EE, 0x31EE, 0x31EE, 0x31F1, 0x31F1, - // Block 6B - 0x31F1, 0x31F1, 0x31F4, 0x31F4, 0x31F7, 0x31F7, 0x31FA, 0x31FA, - 0x31FD, 0x31FD, 0x3200, 0x3200, 0x3203, 0x3203, 0x3206, 0x3206, - 0x3206, 0x3206, 0x3209, 0x3209, 0x3209, 0x3209, 0x320C, 0x320C, - 0x320C, 0x320C, 0x320F, 0x320F, 0x320F, 0x320F, 0x3212, 0x3212, - 0x3215, 0x3215, 0x3215, 0x3215, 0x06BA, 0x06BA, 0x3218, 0x3218, - 0x3218, 0x3218, 0x321B, 0x321B, 0x321B, 0x321B, 0x321E, 0x321E, - 0x06C4, 0x06C4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 6C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3221, 0x3221, 0x3221, 0x3221, 0x3224, - 0x3224, 0x3227, 0x3227, 0x322A, 0x322A, 0x06B0, 0x322D, 0x322D, - 0x3230, 0x3230, 0x3233, 0x3233, 0x3236, 0x3236, 0x3236, 0x3236, - 0x3239, 0x3239, 0x323C, 0x323C, 0x3243, 0x3243, 0x324A, 0x324A, - 0x3251, 0x3251, 0x3258, 0x3258, 0x325F, 0x325F, 0x3266, 0x3266, - 0x3266, 0x326D, 0x326D, 0x326D, 0x3274, 0x3274, 0x3274, 0x3274, - // Block 6D - 0x3277, 0x327E, 0x3285, 0x326D, 0x328C, 0x3293, 0x3298, 0x329D, - 0x32A2, 0x32A7, 0x32AC, 0x32B1, 0x32B6, 0x32BB, 0x32C0, 0x32C5, - 0x32CA, 0x32CF, 0x32D4, 0x32D9, 0x32DE, 0x32E3, 0x32E8, 0x32ED, - 0x32F2, 0x32F7, 0x32FC, 0x3301, 0x3306, 0x330B, 0x3310, 0x3315, - 0x331A, 0x331F, 0x3324, 0x3329, 0x332E, 0x3333, 0x3338, 0x333D, - 0x3342, 0x3347, 0x334C, 0x3351, 0x3356, 0x335B, 0x3360, 0x3365, - 0x336A, 0x336F, 0x3374, 0x3379, 0x337E, 0x3383, 0x3388, 0x338D, - 0x3392, 0x3397, 0x339C, 0x33A1, 0x33A6, 0x33AB, 0x33B0, 0x33B5, - // Block 6E - 0x33BA, 0x33BF, 0x33C4, 0x33C9, 0x33CE, 0x33D3, 0x33D8, 0x33DD, - 0x33E2, 0x33E7, 0x33EC, 0x33F1, 0x33F6, 0x33FB, 0x3400, 0x3405, - 0x340A, 0x340F, 0x3414, 0x3419, 0x341E, 0x3423, 0x3428, 0x342D, - 0x3432, 0x3437, 0x343C, 0x3441, 0x3446, 0x344B, 0x3450, 0x3456, - 0x345C, 0x3462, 0x3468, 0x346E, 0x3474, 0x347B, 0x3285, 0x3482, - 0x326D, 0x328C, 0x3489, 0x348E, 0x32A2, 0x3493, 0x32A7, 0x32AC, - 0x3498, 0x349D, 0x32C0, 0x34A2, 0x32C5, 0x32CA, 0x34A7, 0x34AC, - 0x32D4, 0x34B1, 0x32D9, 0x32DE, 0x336F, 0x3374, 0x3383, 0x3388, - // Block 6F - 0x338D, 0x33A1, 0x33A6, 0x33AB, 0x33B0, 0x33C4, 0x33C9, 0x33CE, - 0x34B6, 0x33E2, 0x34BB, 0x34C0, 0x3400, 0x34C5, 0x3405, 0x340A, - 0x344B, 0x34CA, 0x34CF, 0x3432, 0x34D4, 0x3437, 0x343C, 0x3277, - 0x327E, 0x34D9, 0x3285, 0x34E0, 0x3293, 0x3298, 0x329D, 0x32A2, - 0x34E7, 0x32B1, 0x32B6, 0x32BB, 0x32C0, 0x34EC, 0x32D4, 0x32E3, - 0x32E8, 0x32ED, 0x32F2, 0x32F7, 0x3301, 0x3306, 0x330B, 0x3310, - 0x3315, 0x331A, 0x34F1, 0x331F, 0x3324, 0x3329, 0x332E, 0x3333, - 0x3338, 0x3342, 0x3347, 0x334C, 0x3351, 0x3356, 0x335B, 0x3360, - // Block 70 - 0x3365, 0x336A, 0x3379, 0x337E, 0x3392, 0x3397, 0x339C, 0x33A1, - 0x33A6, 0x33B5, 0x33BA, 0x33BF, 0x33C4, 0x34F6, 0x33D3, 0x33D8, - 0x33DD, 0x33E2, 0x33F1, 0x33F6, 0x33FB, 0x3400, 0x34FB, 0x340F, - 0x3414, 0x3500, 0x3423, 0x3428, 0x342D, 0x3432, 0x3505, 0x3285, - 0x34E0, 0x32A2, 0x34E7, 0x32C0, 0x34EC, 0x32D4, 0x350A, 0x3315, - 0x350F, 0x3514, 0x3519, 0x33A1, 0x33A6, 0x33C4, 0x3400, 0x34FB, - 0x3432, 0x3505, 0x351E, 0x3525, 0x352C, 0x3533, 0x3538, 0x353D, - 0x3542, 0x3547, 0x354C, 0x3551, 0x3556, 0x355B, 0x3560, 0x3565, - // Block 71 - 0x356A, 0x356F, 0x3574, 0x3579, 0x357E, 0x3583, 0x3588, 0x358D, - 0x3592, 0x3597, 0x359C, 0x35A1, 0x3514, 0x35A6, 0x35AB, 0x35B0, - 0x35B5, 0x3533, 0x3538, 0x353D, 0x3542, 0x3547, 0x354C, 0x3551, - 0x3556, 0x355B, 0x3560, 0x3565, 0x356A, 0x356F, 0x3574, 0x3579, - 0x357E, 0x3583, 0x3588, 0x358D, 0x3592, 0x3597, 0x359C, 0x35A1, - 0x3514, 0x35A6, 0x35AB, 0x35B0, 0x35B5, 0x3597, 0x359C, 0x35A1, - 0x3514, 0x350F, 0x3519, 0x333D, 0x3306, 0x330B, 0x3310, 0x3597, - 0x359C, 0x35A1, 0x333D, 0x3342, 0x35BA, 0x35BA, 0x0000, 0x0000, - // Block 72 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x35BF, 0x35C6, 0x35C6, 0x35CD, 0x35D4, 0x35DB, 0x35E2, 0x35E9, - 0x35F0, 0x35F0, 0x35F7, 0x35FE, 0x3605, 0x360C, 0x3613, 0x361A, - 0x361A, 0x3621, 0x3628, 0x3628, 0x362F, 0x362F, 0x3636, 0x363D, - 0x363D, 0x3644, 0x364B, 0x364B, 0x3652, 0x3652, 0x3659, 0x3660, - 0x3660, 0x3667, 0x3667, 0x366E, 0x3675, 0x367C, 0x3683, 0x3683, - 0x368A, 0x3691, 0x3698, 0x369F, 0x36A6, 0x36A6, 0x36AD, 0x36B4, - // Block 73 - 0x36BB, 0x36C2, 0x36C9, 0x36D0, 0x36D0, 0x36D7, 0x36D7, 0x36DE, - 0x36DE, 0x36E5, 0x36EC, 0x36F3, 0x36FA, 0x3701, 0x3708, 0x370F, - 0x0000, 0x0000, 0x3716, 0x371D, 0x3724, 0x372B, 0x3732, 0x3739, - 0x3739, 0x3740, 0x3747, 0x374E, 0x3755, 0x3755, 0x375C, 0x3763, - 0x376A, 0x3771, 0x3778, 0x377F, 0x3786, 0x378D, 0x3794, 0x379B, - 0x37A2, 0x37A9, 0x37B0, 0x37B7, 0x37BE, 0x37C5, 0x37CC, 0x37D3, - 0x37DA, 0x37E1, 0x37E8, 0x37EF, 0x36AD, 0x36BB, 0x37F6, 0x37FD, - 0x3804, 0x380B, 0x3812, 0x3819, 0x3812, 0x3804, 0x3820, 0x3827, - // Block 74 - 0x382E, 0x3835, 0x383C, 0x3819, 0x367C, 0x3636, 0x3843, 0x384A, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3851, 0x3858, 0x385F, 0x3868, 0x3871, 0x387A, 0x3883, 0x388C, - 0x3895, 0x389E, 0x38A5, 0x38C7, 0x38D7, 0x0000, 0x0000, 0x0000, - // Block 75 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x38E0, 0x38E2, 0x38E6, 0x38EA, 0x04E1, 0x38EC, 0x38EE, 0x38F0, - 0x38F4, 0x1443, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1440, 0x38F8, 0x38FC, 0x3900, 0x3900, 0x149C, 0x149E, 0x3902, - 0x3904, 0x3906, 0x390A, 0x390E, 0x3912, 0x3916, 0x391A, 0x16C3, - // Block 76 - 0x16C7, 0x391E, 0x3922, 0x3926, 0x392A, 0x0000, 0x0000, 0x392E, - 0x3930, 0x146C, 0x146C, 0x146C, 0x146C, 0x3900, 0x3900, 0x3900, - 0x38E0, 0x38E2, 0x143E, 0x0000, 0x04E1, 0x38EA, 0x38EE, 0x38EC, - 0x38F8, 0x149C, 0x149E, 0x3902, 0x3904, 0x3906, 0x390A, 0x3932, - 0x3934, 0x3936, 0x1494, 0x3938, 0x393A, 0x393C, 0x149A, 0x0000, - 0x393E, 0x3940, 0x3942, 0x3944, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3946, 0x394A, 0x394F, 0x0000, 0x3953, 0x0000, 0x3957, 0x395B, - 0x3960, 0x3964, 0x3969, 0x396D, 0x3972, 0x3976, 0x397B, 0x397F, - // Block 77 - 0x3984, 0x068D, 0x068D, 0x0692, 0x0692, 0x0697, 0x0697, 0x069C, - 0x069C, 0x06A1, 0x06A1, 0x06A1, 0x06A1, 0x3987, 0x3987, 0x398A, - 0x398A, 0x398A, 0x398A, 0x398D, 0x398D, 0x3990, 0x3990, 0x3990, - 0x3990, 0x3993, 0x3993, 0x3993, 0x3993, 0x3996, 0x3996, 0x3996, - 0x3996, 0x3999, 0x3999, 0x3999, 0x3999, 0x399C, 0x399C, 0x399C, - 0x399C, 0x399F, 0x399F, 0x39A2, 0x39A2, 0x39A5, 0x39A5, 0x39A8, - 0x39A8, 0x39AB, 0x39AB, 0x39AB, 0x39AB, 0x39AE, 0x39AE, 0x39AE, - 0x39AE, 0x39B1, 0x39B1, 0x39B1, 0x39B1, 0x39B4, 0x39B4, 0x39B4, - // Block 78 - 0x39B4, 0x39B7, 0x39B7, 0x39B7, 0x39B7, 0x39BA, 0x39BA, 0x39BA, - 0x39BA, 0x39BD, 0x39BD, 0x39BD, 0x39BD, 0x39C0, 0x39C0, 0x39C0, - 0x39C0, 0x39C3, 0x39C3, 0x39C3, 0x39C3, 0x39C6, 0x39C6, 0x39C6, - 0x39C6, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CC, 0x39CC, 0x39CC, - 0x39CC, 0x39CF, 0x39CF, 0x39CF, 0x39CF, 0x39D2, 0x39D2, 0x39D2, - 0x39D2, 0x39D5, 0x39D5, 0x39D5, 0x39D5, 0x39D8, 0x39D8, 0x3239, - 0x3239, 0x39DB, 0x39DB, 0x39DB, 0x39DB, 0x39DE, 0x39DE, 0x39E5, - 0x39E5, 0x39EC, 0x39EC, 0x39F3, 0x39F3, 0x0000, 0x0000, 0x0000, - // Block 79 - 0x0000, 0x38EC, 0x39F8, 0x3932, 0x3940, 0x3942, 0x3934, 0x39FA, - 0x149C, 0x149E, 0x3936, 0x1494, 0x38E0, 0x3938, 0x143E, 0x39FC, - 0x1486, 0x001C, 0x000D, 0x000F, 0x1488, 0x148A, 0x148C, 0x148E, - 0x1490, 0x1492, 0x38EA, 0x04E1, 0x393A, 0x149A, 0x393C, 0x38EE, - 0x3944, 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, - 0x0916, 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, - 0x0929, 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, - 0x1570, 0x17F8, 0x14D4, 0x392E, 0x393E, 0x3930, 0x39FE, 0x3900, - // Block 7A - 0x13F7, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, 0x094C, - 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, 0x001E, - 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, - 0x04C7, 0x04A8, 0x09DF, 0x3902, 0x3A00, 0x3904, 0x3A02, 0x3A04, - 0x3A08, 0x38E6, 0x391E, 0x3922, 0x38E2, 0x3A0C, 0x2321, 0x3A10, - 0x3A14, 0x3A18, 0x3A1C, 0x3A20, 0x3A24, 0x3A28, 0x3A2C, 0x3A30, - 0x3A34, 0x2269, 0x226D, 0x2271, 0x2275, 0x2279, 0x227D, 0x2281, - 0x2285, 0x2289, 0x228D, 0x2291, 0x2295, 0x2299, 0x229D, 0x22A1, - // Block 7B - 0x22A5, 0x22A9, 0x22AD, 0x22B1, 0x22B5, 0x22B9, 0x22BD, 0x22C1, - 0x22C5, 0x22C9, 0x22CD, 0x22D1, 0x22D5, 0x22D9, 0x22DD, 0x22E1, - 0x22E5, 0x22E9, 0x22ED, 0x22F1, 0x22F5, 0x22F9, 0x22FD, 0x2301, - 0x2305, 0x2309, 0x230D, 0x2311, 0x2315, 0x3A38, 0x3A3C, 0x3A40, - 0x1E04, 0x1D38, 0x1D3C, 0x1D40, 0x1D44, 0x1D48, 0x1D4C, 0x1D50, - 0x1D54, 0x1D58, 0x1D5C, 0x1D60, 0x1D64, 0x1D68, 0x1D6C, 0x1D70, - 0x1D74, 0x1D78, 0x1D7C, 0x1D80, 0x1D84, 0x1D88, 0x1D8C, 0x1D90, - 0x1D94, 0x1D98, 0x1D9C, 0x1DA0, 0x1DA4, 0x1DA8, 0x1DAC, 0x0000, - // Block 7C - 0x0000, 0x0000, 0x1DB0, 0x1DB4, 0x1DB8, 0x1DBC, 0x1DC0, 0x1DC4, - 0x0000, 0x0000, 0x1DC8, 0x1DCC, 0x1DD0, 0x1DD4, 0x1DD8, 0x1DDC, - 0x0000, 0x0000, 0x1DE0, 0x1DE4, 0x1DE8, 0x1DEC, 0x1DF0, 0x1DF4, - 0x0000, 0x0000, 0x1DF8, 0x1DFC, 0x1E00, 0x0000, 0x0000, 0x0000, - 0x3A44, 0x3A47, 0x3A4A, 0x0009, 0x3A4D, 0x3A50, 0x3A53, 0x0000, - 0x3A57, 0x3A5B, 0x3A5F, 0x3A63, 0x3A67, 0x3A6B, 0x3A6F, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x3A73, 0x0000, 0x3A7C, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3A85, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3A8E, 0x3A97, - 0x3AA0, 0x3AAD, 0x3ABA, 0x3AC7, 0x3AD4, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3AE1, 0x3AEA, 0x3AF3, 0x3B00, 0x3B0D, - // Block 80 - 0x3B1A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 81 - 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, - 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - 0x17F8, 0x14D4, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, - 0x094C, 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, - 0x001E, 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, - 0x04A6, 0x04C7, 0x04A8, 0x09DF, 0x0906, 0x090B, 0x14AD, 0x090D, - 0x090F, 0x14D9, 0x0914, 0x0916, 0x0918, 0x091A, 0x091C, 0x091E, - // Block 82 - 0x0920, 0x0922, 0x0924, 0x0929, 0x14C8, 0x092B, 0x17F6, 0x092D, - 0x092F, 0x155F, 0x0931, 0x1570, 0x17F8, 0x14D4, 0x0007, 0x093D, - 0x0984, 0x093F, 0x0941, 0x098C, 0x094C, 0x0000, 0x097C, 0x0499, - 0x094E, 0x04C5, 0x0950, 0x14A0, 0x001E, 0x0960, 0x17FA, 0x049B, - 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, 0x04C7, 0x04A8, 0x09DF, - 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, - 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - // Block 83 - 0x17F8, 0x14D4, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, - 0x094C, 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, - 0x001E, 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, - 0x04A6, 0x04C7, 0x04A8, 0x09DF, 0x0906, 0x0000, 0x14AD, 0x090D, - 0x0000, 0x0000, 0x0914, 0x0000, 0x0000, 0x091A, 0x091C, 0x0000, - 0x0000, 0x0922, 0x0924, 0x0929, 0x14C8, 0x0000, 0x17F6, 0x092D, - 0x092F, 0x155F, 0x0931, 0x1570, 0x17F8, 0x14D4, 0x0007, 0x093D, - 0x0984, 0x093F, 0x0000, 0x098C, 0x0000, 0x0494, 0x097C, 0x0499, - // Block 84 - 0x094E, 0x04C5, 0x0950, 0x14A0, 0x0000, 0x0960, 0x17FA, 0x049B, - 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, 0x04C7, 0x04A8, 0x09DF, - 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, - 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - 0x17F8, 0x14D4, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, - 0x094C, 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, - 0x001E, 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, - // Block 85 - 0x04A6, 0x04C7, 0x04A8, 0x09DF, 0x0906, 0x090B, 0x0000, 0x090D, - 0x090F, 0x14D9, 0x0914, 0x0000, 0x0000, 0x091A, 0x091C, 0x091E, - 0x0920, 0x0922, 0x0924, 0x0929, 0x14C8, 0x0000, 0x17F6, 0x092D, - 0x092F, 0x155F, 0x0931, 0x1570, 0x17F8, 0x0000, 0x0007, 0x093D, - 0x0984, 0x093F, 0x0941, 0x098C, 0x094C, 0x0494, 0x097C, 0x0499, - 0x094E, 0x04C5, 0x0950, 0x14A0, 0x001E, 0x0960, 0x17FA, 0x049B, - 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, 0x04C7, 0x04A8, 0x09DF, - 0x0906, 0x090B, 0x0000, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0000, - // Block 86 - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0000, 0x0924, 0x0000, - 0x0000, 0x0000, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - 0x17F8, 0x0000, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, - 0x094C, 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, - 0x001E, 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, - 0x04A6, 0x04C7, 0x04A8, 0x09DF, 0x0906, 0x090B, 0x14AD, 0x090D, - 0x090F, 0x14D9, 0x0914, 0x0916, 0x0918, 0x091A, 0x091C, 0x091E, - 0x0920, 0x0922, 0x0924, 0x0929, 0x14C8, 0x092B, 0x17F6, 0x092D, - // Block 87 - 0x092F, 0x155F, 0x0931, 0x1570, 0x17F8, 0x14D4, 0x0007, 0x093D, - 0x0984, 0x093F, 0x0941, 0x098C, 0x094C, 0x0494, 0x097C, 0x0499, - 0x094E, 0x04C5, 0x0950, 0x14A0, 0x001E, 0x0960, 0x17FA, 0x049B, - 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, 0x04C7, 0x04A8, 0x09DF, - 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, - 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - 0x17F8, 0x14D4, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, - // Block 88 - 0x094C, 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, - 0x001E, 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, - 0x04A6, 0x04C7, 0x04A8, 0x09DF, 0x0906, 0x090B, 0x14AD, 0x090D, - 0x090F, 0x14D9, 0x0914, 0x0916, 0x0918, 0x091A, 0x091C, 0x091E, - 0x0920, 0x0922, 0x0924, 0x0929, 0x14C8, 0x092B, 0x17F6, 0x092D, - 0x092F, 0x155F, 0x0931, 0x1570, 0x17F8, 0x14D4, 0x0007, 0x093D, - 0x0984, 0x093F, 0x0941, 0x098C, 0x094C, 0x0494, 0x097C, 0x0499, - 0x094E, 0x04C5, 0x0950, 0x14A0, 0x001E, 0x0960, 0x17FA, 0x049B, - // Block 89 - 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, 0x04C7, 0x04A8, 0x09DF, - 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, - 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - 0x17F8, 0x14D4, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, - 0x094C, 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, - 0x001E, 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, - 0x04A6, 0x04C7, 0x04A8, 0x09DF, 0x0906, 0x090B, 0x14AD, 0x090D, - // Block 8A - 0x090F, 0x14D9, 0x0914, 0x0916, 0x0918, 0x091A, 0x091C, 0x091E, - 0x0920, 0x0922, 0x0924, 0x0929, 0x14C8, 0x092B, 0x17F6, 0x092D, - 0x092F, 0x155F, 0x0931, 0x1570, 0x17F8, 0x14D4, 0x0007, 0x093D, - 0x0984, 0x093F, 0x0941, 0x098C, 0x094C, 0x0494, 0x097C, 0x0499, - 0x094E, 0x04C5, 0x0950, 0x14A0, 0x001E, 0x0960, 0x17FA, 0x049B, - 0x02C8, 0x0962, 0x0964, 0x096D, 0x04A6, 0x04C7, 0x04A8, 0x09DF, - 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, - // Block 8B - 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - 0x17F8, 0x14D4, 0x0007, 0x093D, 0x0984, 0x093F, 0x0941, 0x098C, - 0x094C, 0x0494, 0x097C, 0x0499, 0x094E, 0x04C5, 0x0950, 0x14A0, - 0x001E, 0x0960, 0x17FA, 0x049B, 0x02C8, 0x0962, 0x0964, 0x096D, - 0x04A6, 0x04C7, 0x04A8, 0x09DF, 0x3B27, 0x3B2A, 0x0000, 0x0000, - 0x3B2D, 0x3B30, 0x14EB, 0x3B33, 0x3B36, 0x3B39, 0x3B3C, 0x057B, - 0x3B3F, 0x3B42, 0x3B45, 0x3B48, 0x3B4B, 0x3B4E, 0x3B51, 0x14EE, - 0x3B54, 0x057B, 0x0581, 0x3B57, 0x055F, 0x3B5A, 0x3B5D, 0x3B60, - // Block 8C - 0x14D6, 0x3B63, 0x3B67, 0x0559, 0x0973, 0x0976, 0x057E, 0x3B6A, - 0x3B6D, 0x055C, 0x12FD, 0x0572, 0x3B70, 0x0015, 0x3B73, 0x3B76, - 0x3B79, 0x056F, 0x0575, 0x0578, 0x3B7C, 0x3B7F, 0x3B82, 0x056C, - 0x0979, 0x3B85, 0x3B88, 0x3B8B, 0x057E, 0x055C, 0x0572, 0x056C, - 0x0575, 0x056F, 0x3B2D, 0x3B30, 0x14EB, 0x3B33, 0x3B36, 0x3B39, - 0x3B3C, 0x057B, 0x3B3F, 0x3B42, 0x3B45, 0x3B48, 0x3B4B, 0x3B4E, - 0x3B51, 0x14EE, 0x3B54, 0x057B, 0x0581, 0x3B57, 0x055F, 0x3B5A, - 0x3B5D, 0x3B60, 0x14D6, 0x3B63, 0x3B67, 0x0559, 0x0973, 0x0976, - // Block 8D - 0x057E, 0x3B6A, 0x3B6D, 0x055C, 0x12FD, 0x0572, 0x3B70, 0x0015, - 0x3B73, 0x3B76, 0x3B79, 0x056F, 0x0575, 0x0578, 0x3B7C, 0x3B7F, - 0x3B82, 0x056C, 0x0979, 0x3B85, 0x3B88, 0x3B8B, 0x057E, 0x055C, - 0x0572, 0x056C, 0x0575, 0x056F, 0x3B2D, 0x3B30, 0x14EB, 0x3B33, - 0x3B36, 0x3B39, 0x3B3C, 0x057B, 0x3B3F, 0x3B42, 0x3B45, 0x3B48, - 0x3B4B, 0x3B4E, 0x3B51, 0x14EE, 0x3B54, 0x057B, 0x0581, 0x3B57, - 0x055F, 0x3B5A, 0x3B5D, 0x3B60, 0x14D6, 0x3B63, 0x3B67, 0x0559, - 0x0973, 0x0976, 0x057E, 0x3B6A, 0x3B6D, 0x055C, 0x12FD, 0x0572, - // Block 8E - 0x3B70, 0x0015, 0x3B73, 0x3B76, 0x3B79, 0x056F, 0x0575, 0x0578, - 0x3B7C, 0x3B7F, 0x3B82, 0x056C, 0x0979, 0x3B85, 0x3B88, 0x3B8B, - 0x057E, 0x055C, 0x0572, 0x056C, 0x0575, 0x056F, 0x3B2D, 0x3B30, - 0x14EB, 0x3B33, 0x3B36, 0x3B39, 0x3B3C, 0x057B, 0x3B3F, 0x3B42, - 0x3B45, 0x3B48, 0x3B4B, 0x3B4E, 0x3B51, 0x14EE, 0x3B54, 0x057B, - 0x0581, 0x3B57, 0x055F, 0x3B5A, 0x3B5D, 0x3B60, 0x14D6, 0x3B63, - 0x3B67, 0x0559, 0x0973, 0x0976, 0x057E, 0x3B6A, 0x3B6D, 0x055C, - 0x12FD, 0x0572, 0x3B70, 0x0015, 0x3B73, 0x3B76, 0x3B79, 0x056F, - // Block 8F - 0x0575, 0x0578, 0x3B7C, 0x3B7F, 0x3B82, 0x056C, 0x0979, 0x3B85, - 0x3B88, 0x3B8B, 0x057E, 0x055C, 0x0572, 0x056C, 0x0575, 0x056F, - 0x3B2D, 0x3B30, 0x14EB, 0x3B33, 0x3B36, 0x3B39, 0x3B3C, 0x057B, - 0x3B3F, 0x3B42, 0x3B45, 0x3B48, 0x3B4B, 0x3B4E, 0x3B51, 0x14EE, - 0x3B54, 0x057B, 0x0581, 0x3B57, 0x055F, 0x3B5A, 0x3B5D, 0x3B60, - 0x14D6, 0x3B63, 0x3B67, 0x0559, 0x0973, 0x0976, 0x057E, 0x3B6A, - 0x3B6D, 0x055C, 0x12FD, 0x0572, 0x3B70, 0x0015, 0x3B73, 0x3B76, - 0x3B79, 0x056F, 0x0575, 0x0578, 0x3B7C, 0x3B7F, 0x3B82, 0x056C, - // Block 90 - 0x0979, 0x3B85, 0x3B88, 0x3B8B, 0x057E, 0x055C, 0x0572, 0x056C, - 0x0575, 0x056F, 0x3B8F, 0x3B92, 0x0000, 0x0000, 0x1486, 0x001C, - 0x000D, 0x000F, 0x1488, 0x148A, 0x148C, 0x148E, 0x1490, 0x1492, - 0x1486, 0x001C, 0x000D, 0x000F, 0x1488, 0x148A, 0x148C, 0x148E, - 0x1490, 0x1492, 0x1486, 0x001C, 0x000D, 0x000F, 0x1488, 0x148A, - 0x148C, 0x148E, 0x1490, 0x1492, 0x1486, 0x001C, 0x000D, 0x000F, - 0x1488, 0x148A, 0x148C, 0x148E, 0x1490, 0x1492, 0x1486, 0x001C, - 0x000D, 0x000F, 0x1488, 0x148A, 0x148C, 0x148E, 0x1490, 0x1492, - // Block 91 - 0x3B95, 0x3B98, 0x3B9B, 0x3B9E, 0x3BA1, 0x3BA4, 0x3BA7, 0x3BAA, - 0x3BAD, 0x3BB0, 0x3BB3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3BB6, 0x3BBA, 0x3BBE, 0x3BC2, 0x3BC6, 0x3BCA, 0x3BCE, 0x3BD2, - 0x3BD6, 0x3BDA, 0x3BDE, 0x3BE2, 0x3BE6, 0x3BEA, 0x3BEE, 0x3BF2, - 0x3BF6, 0x3BFA, 0x3BFE, 0x3C02, 0x3C06, 0x3C0A, 0x3C0E, 0x3C12, - 0x3C16, 0x3C1A, 0x3C1E, 0x14AD, 0x092B, 0x3C26, 0x3C29, 0x0000, - 0x0906, 0x090B, 0x14AD, 0x090D, 0x090F, 0x14D9, 0x0914, 0x0916, - 0x0918, 0x091A, 0x091C, 0x091E, 0x0920, 0x0922, 0x0924, 0x0929, - // Block 92 - 0x14C8, 0x092B, 0x17F6, 0x092D, 0x092F, 0x155F, 0x0931, 0x1570, - 0x17F8, 0x14D4, 0x3C2C, 0x293D, 0x3C2F, 0x3C32, 0x3C35, 0x3C39, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 93 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3C3C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 94 - 0x3C3F, 0x3C46, 0x2291, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1922, 0x3C4D, 0x3C51, 0x1CB3, 0x183E, 0x3C55, 0x3C59, 0x1ED0, - 0x3C5D, 0x3C61, 0x3C65, 0x2D49, 0x3C69, 0x3C6D, 0x3C71, 0x3C75, - 0x3C79, 0x3C7D, 0x19B2, 0x3C81, 0x3C85, 0x3C89, 0x3C8D, 0x3C91, - 0x3C95, 0x1826, 0x1EB0, 0x3C99, 0x21C7, 0x1EBC, 0x21CB, 0x3C9D, - 0x1A92, 0x3CA1, 0x3CA5, 0x3CA9, 0x3CAD, 0x3CB1, 0x2183, 0x194A, - 0x3CB5, 0x3CB9, 0x3CBD, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 95 - 0x3CC1, 0x3CCB, 0x3CD5, 0x3CDF, 0x3CE9, 0x3CF3, 0x3CFD, 0x3D07, - 0x3D11, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3D1B, 0x3D1F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 96 - 0x3D23, 0x3D27, 0x3D2B, 0x3D2F, 0x3D34, 0x2EB5, 0x3D38, 0x3D3C, - 0x3D40, 0x3D44, 0x2EB9, 0x3D48, 0x3D4C, 0x3D50, 0x2EBD, 0x3D55, - 0x3D59, 0x3D5D, 0x3D61, 0x3D66, 0x3D6A, 0x3C71, 0x3D6E, 0x3D73, - 0x3D77, 0x3D7B, 0x3D7F, 0x2F9A, 0x3D83, 0x1866, 0x3D88, 0x3D8C, - 0x3D90, 0x3D94, 0x3CB9, 0x3D98, 0x3D9C, 0x2FAE, 0x2EC1, 0x2EC5, - 0x2FB2, 0x3DA0, 0x3DA4, 0x2BF1, 0x3DA8, 0x2EC9, 0x3DAC, 0x3DB0, - 0x3DB4, 0x3DB8, 0x3DB8, 0x3DB8, 0x3DBC, 0x3DC1, 0x3DC5, 0x3DC9, - 0x3DCD, 0x3DD2, 0x3DD6, 0x3DDA, 0x3DDE, 0x3DE2, 0x3DE6, 0x3DEA, - // Block 97 - 0x3DEE, 0x3DF2, 0x3DF6, 0x3DFA, 0x3DFE, 0x3E02, 0x3E02, 0x2FBA, - 0x3E06, 0x3E0A, 0x3E0E, 0x3E12, 0x2ED1, 0x3E16, 0x3E1A, 0x3E1E, - 0x2E39, 0x3E22, 0x3E26, 0x3E2A, 0x3E2E, 0x3E32, 0x3E36, 0x3E3A, - 0x3E3E, 0x3E42, 0x3E47, 0x3E4B, 0x3E4F, 0x3C55, 0x3E53, 0x3E57, - 0x3E5B, 0x3E60, 0x3E65, 0x3E69, 0x3E6D, 0x3E71, 0x3E75, 0x3E79, - 0x3E7D, 0x3E81, 0x3E85, 0x3E85, 0x3E89, 0x3E8E, 0x3E92, 0x2BE1, - 0x3E96, 0x3E9A, 0x3E9F, 0x3EA3, 0x3EA7, 0x18CE, 0x3EAB, 0x3EAF, - 0x18D6, 0x3EB3, 0x3EB7, 0x3EBB, 0x3EC0, 0x3EC4, 0x3EC9, 0x3ECD, - // Block 98 - 0x3ED1, 0x3ED5, 0x3ED9, 0x3EDD, 0x3EE1, 0x3EE5, 0x3EE9, 0x3EED, - 0x3EF1, 0x3EF5, 0x3EFA, 0x3EFE, 0x3F02, 0x3F06, 0x2B11, 0x3F0A, - 0x18FE, 0x3F0F, 0x3F0F, 0x3F14, 0x3F18, 0x3F18, 0x3F1C, 0x3F20, - 0x3F25, 0x3F2A, 0x3F2E, 0x3F32, 0x3F36, 0x3F3A, 0x3F3E, 0x3F42, - 0x3F46, 0x3F4A, 0x3F4E, 0x2EE5, 0x3F52, 0x3F57, 0x3F5B, 0x3F5F, - 0x2FEA, 0x3F5F, 0x3F63, 0x2EED, 0x3F67, 0x3F6B, 0x3F6F, 0x3F73, - 0x2EF1, 0x2AA5, 0x3F77, 0x3F7B, 0x3F7F, 0x3F83, 0x3F87, 0x3F8B, - 0x3F8F, 0x3F94, 0x3F98, 0x3F9C, 0x3FA0, 0x3FA4, 0x3FA8, 0x3FAD, - // Block 99 - 0x3FB1, 0x3FB5, 0x3FB9, 0x3FBD, 0x3FC1, 0x3FC5, 0x3FC9, 0x3FCD, - 0x2EF5, 0x3FD1, 0x3FD5, 0x3FDA, 0x3FDE, 0x3FE2, 0x3FE6, 0x2EFD, - 0x3FEA, 0x3FEE, 0x3FF2, 0x3FF6, 0x3FFA, 0x3FFE, 0x4002, 0x4006, - 0x2B15, 0x300A, 0x400A, 0x400E, 0x4012, 0x4016, 0x401B, 0x401F, - 0x4023, 0x4027, 0x2F01, 0x402B, 0x4030, 0x4034, 0x4038, 0x30B5, - 0x403C, 0x4040, 0x4044, 0x4048, 0x404C, 0x4051, 0x4055, 0x4059, - 0x405D, 0x4062, 0x4066, 0x406A, 0x406E, 0x2C25, 0x4072, 0x4076, - 0x407B, 0x4080, 0x4085, 0x4089, 0x408E, 0x4092, 0x4096, 0x409A, - // Block 9A - 0x409E, 0x2F05, 0x2D71, 0x40A2, 0x40A6, 0x40AA, 0x40AE, 0x40B3, - 0x40B7, 0x40BB, 0x40BF, 0x3016, 0x40C3, 0x40C7, 0x40CC, 0x40D0, - 0x40D4, 0x40D9, 0x40DE, 0x40E2, 0x301A, 0x40E6, 0x40EA, 0x40EE, - 0x40F2, 0x40F6, 0x40FA, 0x40FE, 0x4103, 0x4107, 0x410C, 0x4110, - 0x4115, 0x3022, 0x4119, 0x411D, 0x4122, 0x4126, 0x412A, 0x412F, - 0x4134, 0x4138, 0x413C, 0x4140, 0x4144, 0x4144, 0x4148, 0x414C, - 0x302A, 0x4150, 0x4154, 0x4158, 0x415C, 0x4160, 0x4165, 0x4169, - 0x2BED, 0x416E, 0x4173, 0x4177, 0x417C, 0x4181, 0x4186, 0x418A, - // Block 9B - 0x3042, 0x418E, 0x4193, 0x4198, 0x419D, 0x41A2, 0x41A6, 0x41A6, - 0x3046, 0x30BD, 0x41AA, 0x41AE, 0x41B2, 0x41B6, 0x41BB, 0x2B59, - 0x304E, 0x41BF, 0x41C3, 0x2F2D, 0x41C8, 0x41CD, 0x2E89, 0x41D2, - 0x41D6, 0x2F39, 0x41DA, 0x41DE, 0x41E2, 0x41E7, 0x41E7, 0x41EC, - 0x41F0, 0x41F4, 0x41F9, 0x41FD, 0x4201, 0x4205, 0x420A, 0x420E, - 0x4212, 0x4216, 0x421A, 0x421E, 0x4223, 0x4227, 0x422B, 0x422F, - 0x4233, 0x4237, 0x423B, 0x4240, 0x4245, 0x4249, 0x424E, 0x4252, - 0x4257, 0x425B, 0x2F51, 0x425F, 0x4264, 0x4269, 0x426D, 0x4272, - // Block 9C - 0x4276, 0x427B, 0x427F, 0x4283, 0x4287, 0x428B, 0x428F, 0x4293, - 0x4298, 0x429D, 0x42A2, 0x3F14, 0x42A7, 0x42AB, 0x42AF, 0x42B3, - 0x42B7, 0x42BB, 0x42BF, 0x42C3, 0x42C7, 0x42CB, 0x42CF, 0x42D3, - 0x2C31, 0x42D8, 0x42DC, 0x42E0, 0x42E4, 0x42E8, 0x42EC, 0x2F5D, - 0x42F0, 0x42F4, 0x42F8, 0x42FC, 0x4300, 0x4305, 0x430A, 0x430F, - 0x4313, 0x4317, 0x431B, 0x431F, 0x4324, 0x4328, 0x432D, 0x4331, - 0x4335, 0x433A, 0x433F, 0x4343, 0x2B45, 0x4347, 0x434B, 0x434F, - 0x4353, 0x4357, 0x435B, 0x306A, 0x435F, 0x4363, 0x4367, 0x436B, - // Block 9D - 0x436F, 0x4373, 0x4377, 0x437B, 0x1A66, 0x437F, 0x4384, 0x4388, - 0x438C, 0x4390, 0x4394, 0x4398, 0x439D, 0x43A2, 0x43A6, 0x43AA, - 0x307E, 0x3082, 0x1A82, 0x43AE, 0x43B3, 0x43B7, 0x43BB, 0x43BF, - 0x43C3, 0x43C8, 0x43CD, 0x43D1, 0x43D5, 0x43D9, 0x43DE, 0x3086, - 0x43E2, 0x43E7, 0x43EC, 0x43F0, 0x43F4, 0x43F8, 0x43FD, 0x4401, - 0x4405, 0x4409, 0x440D, 0x4411, 0x4415, 0x4419, 0x441E, 0x4422, - 0x4426, 0x442A, 0x442F, 0x4433, 0x4437, 0x443B, 0x443F, 0x4444, - 0x4449, 0x444D, 0x4451, 0x4455, 0x445A, 0x445E, 0x309E, 0x309E, - // Block 9E - 0x4463, 0x4467, 0x446C, 0x4470, 0x4474, 0x4478, 0x447C, 0x4480, - 0x4484, 0x4488, 0x30A2, 0x448D, 0x4491, 0x4495, 0x4499, 0x449D, - 0x44A1, 0x44A6, 0x44AA, 0x44AF, 0x44B4, 0x1B42, 0x44B9, 0x1B52, - 0x44BD, 0x44C1, 0x44C5, 0x44C9, 0x1B66, 0x44CD, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +var nfkcDecompValues = [10176]uint16{ + // Block 0x0, offset 0x0 + // Block 0x1, offset 0x40 + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x00e0: 0x0001, + 0x00e8: 0x0003, + 0x00ea: 0x0007, 0x00ef: 0x0009, + 0x00f2: 0x000d, 0x00f3: 0x000f, 0x00f4: 0x0011, 0x00f5: 0x0015, + 0x00f8: 0x0018, 0x00f9: 0x001c, 0x00fa: 0x001e, + 0x00fc: 0x0020, 0x00fd: 0x0026, 0x00fe: 0x002c, + // Block 0x4, offset 0x100 + 0x0100: 0x0032, 0x0101: 0x0036, 0x0102: 0x003a, 0x0103: 0x003e, 0x0104: 0x0042, 0x0105: 0x0046, + 0x0107: 0x004a, 0x0108: 0x004e, 0x0109: 0x0052, 0x010a: 0x0056, 0x010b: 0x005a, + 0x010c: 0x005e, 0x010d: 0x0062, 0x010e: 0x0066, 0x010f: 0x006a, 0x0111: 0x006e, + 0x0112: 0x0072, 0x0113: 0x0076, 0x0114: 0x007a, 0x0115: 0x007e, 0x0116: 0x0082, + 0x0119: 0x0086, 0x011a: 0x008a, 0x011b: 0x008e, 0x011c: 0x0092, 0x011d: 0x0096, + 0x0120: 0x009a, 0x0121: 0x009e, 0x0122: 0x00a2, 0x0123: 0x00a6, + 0x0124: 0x00aa, 0x0125: 0x00ae, 0x0127: 0x00b2, 0x0128: 0x00b6, 0x0129: 0x00ba, + 0x012a: 0x00be, 0x012b: 0x00c2, 0x012c: 0x00c6, 0x012d: 0x00ca, 0x012e: 0x00ce, 0x012f: 0x00d2, + 0x0131: 0x00d6, 0x0132: 0x00da, 0x0133: 0x00de, 0x0134: 0x00e2, 0x0135: 0x00e6, + 0x0136: 0x00ea, 0x0139: 0x00ee, 0x013a: 0x00f2, 0x013b: 0x00f6, + 0x013c: 0x00fa, 0x013d: 0x00fe, 0x013f: 0x0102, + // Block 0x5, offset 0x140 + 0x0140: 0x0106, 0x0141: 0x010a, 0x0142: 0x010e, 0x0143: 0x0112, 0x0144: 0x0116, 0x0145: 0x011a, + 0x0146: 0x011e, 0x0147: 0x0122, 0x0148: 0x0126, 0x0149: 0x012a, 0x014a: 0x012e, 0x014b: 0x0132, + 0x014c: 0x0136, 0x014d: 0x013a, 0x014e: 0x013e, 0x014f: 0x0142, + 0x0152: 0x0146, 0x0153: 0x014a, 0x0154: 0x014e, 0x0155: 0x0152, 0x0156: 0x0156, 0x0157: 0x015a, + 0x0158: 0x015e, 0x0159: 0x0162, 0x015a: 0x0166, 0x015b: 0x016a, 0x015c: 0x016e, 0x015d: 0x0172, + 0x015e: 0x0176, 0x015f: 0x017a, 0x0160: 0x017e, 0x0161: 0x0182, 0x0162: 0x0186, 0x0163: 0x018a, + 0x0164: 0x018e, 0x0165: 0x0192, 0x0168: 0x0196, 0x0169: 0x019a, + 0x016a: 0x019e, 0x016b: 0x01a2, 0x016c: 0x01a6, 0x016d: 0x01aa, 0x016e: 0x01ae, 0x016f: 0x01b2, + 0x0170: 0x01b6, 0x0172: 0x01ba, 0x0173: 0x01bd, 0x0174: 0x01c0, 0x0175: 0x01c4, + 0x0176: 0x01c8, 0x0177: 0x01cc, 0x0179: 0x01d0, 0x017a: 0x01d4, 0x017b: 0x01d8, + 0x017c: 0x01dc, 0x017d: 0x01e0, 0x017e: 0x01e4, 0x017f: 0x01e8, + // Block 0x6, offset 0x180 + 0x0180: 0x01ec, 0x0183: 0x01f0, 0x0184: 0x01f4, 0x0185: 0x01f8, + 0x0186: 0x01fc, 0x0187: 0x0200, 0x0188: 0x0204, 0x0189: 0x0208, + 0x018c: 0x020c, 0x018d: 0x0210, 0x018e: 0x0214, 0x018f: 0x0218, 0x0190: 0x021c, 0x0191: 0x0220, + 0x0194: 0x0224, 0x0195: 0x0228, 0x0196: 0x022c, 0x0197: 0x0230, + 0x0198: 0x0234, 0x0199: 0x0238, 0x019a: 0x023c, 0x019b: 0x0240, 0x019c: 0x0244, 0x019d: 0x0248, + 0x019e: 0x024c, 0x019f: 0x0250, 0x01a0: 0x0254, 0x01a1: 0x0258, 0x01a2: 0x025c, 0x01a3: 0x0260, + 0x01a4: 0x0264, 0x01a5: 0x0268, 0x01a8: 0x026c, 0x01a9: 0x0270, + 0x01aa: 0x0274, 0x01ab: 0x0278, 0x01ac: 0x027c, 0x01ad: 0x0280, 0x01ae: 0x0284, 0x01af: 0x0288, + 0x01b0: 0x028c, 0x01b1: 0x0290, 0x01b2: 0x0294, 0x01b3: 0x0298, 0x01b4: 0x029c, 0x01b5: 0x02a0, + 0x01b6: 0x02a4, 0x01b7: 0x02a8, 0x01b8: 0x02ac, 0x01b9: 0x02b0, 0x01ba: 0x02b4, 0x01bb: 0x02b8, + 0x01bc: 0x02bc, 0x01bd: 0x02c0, 0x01be: 0x02c4, 0x01bf: 0x02c8, + // Block 0x7, offset 0x1c0 + 0x01e0: 0x02ca, 0x01e1: 0x02ce, + 0x01ef: 0x02d2, + 0x01f0: 0x02d6, + // Block 0x8, offset 0x200 + 0x0204: 0x02da, 0x0205: 0x02df, + 0x0206: 0x02e4, 0x0207: 0x02e9, 0x0208: 0x02ec, 0x0209: 0x02ef, 0x020a: 0x02f2, 0x020b: 0x02f5, + 0x020c: 0x02f8, 0x020d: 0x02fb, 0x020e: 0x02ff, 0x020f: 0x0303, 0x0210: 0x0307, 0x0211: 0x030b, + 0x0212: 0x030f, 0x0213: 0x0313, 0x0214: 0x0317, 0x0215: 0x031b, 0x0216: 0x0321, 0x0217: 0x0327, + 0x0218: 0x032d, 0x0219: 0x0333, 0x021a: 0x0339, 0x021b: 0x033f, 0x021c: 0x0345, + 0x021e: 0x034b, 0x021f: 0x0351, 0x0220: 0x0357, 0x0221: 0x035d, 0x0222: 0x0363, 0x0223: 0x0368, + 0x0226: 0x036d, 0x0227: 0x0371, 0x0228: 0x0375, 0x0229: 0x0379, + 0x022a: 0x037d, 0x022b: 0x0381, 0x022c: 0x0385, 0x022d: 0x038b, 0x022e: 0x0391, 0x022f: 0x0396, + 0x0230: 0x039b, 0x0231: 0x039f, 0x0232: 0x03a2, 0x0233: 0x03a5, 0x0234: 0x03a8, 0x0235: 0x03ac, + 0x0238: 0x03b0, 0x0239: 0x03b4, 0x023a: 0x03b8, 0x023b: 0x03be, + 0x023c: 0x03c4, 0x023d: 0x03c9, 0x023e: 0x03ce, 0x023f: 0x03d3, + // Block 0x9, offset 0x240 + 0x0240: 0x03d8, 0x0241: 0x03dc, 0x0242: 0x03e0, 0x0243: 0x03e4, 0x0244: 0x03e8, 0x0245: 0x03ec, + 0x0246: 0x03f0, 0x0247: 0x03f4, 0x0248: 0x03f8, 0x0249: 0x03fc, 0x024a: 0x0400, 0x024b: 0x0404, + 0x024c: 0x0408, 0x024d: 0x040c, 0x024e: 0x0410, 0x024f: 0x0414, 0x0250: 0x0418, 0x0251: 0x041c, + 0x0252: 0x0420, 0x0253: 0x0424, 0x0254: 0x0428, 0x0255: 0x042c, 0x0256: 0x0430, 0x0257: 0x0434, + 0x0258: 0x0438, 0x0259: 0x043c, 0x025a: 0x0440, 0x025b: 0x0444, + 0x025e: 0x0448, 0x025f: 0x044c, + 0x0266: 0x0450, 0x0267: 0x0454, 0x0268: 0x0458, 0x0269: 0x045c, + 0x026a: 0x0460, 0x026b: 0x0466, 0x026c: 0x046c, 0x026d: 0x0472, 0x026e: 0x0478, 0x026f: 0x047c, + 0x0270: 0x0480, 0x0271: 0x0486, 0x0272: 0x048c, 0x0273: 0x0490, + // Block 0xa, offset 0x280 + 0x02b0: 0x0494, 0x02b1: 0x0496, 0x02b2: 0x0499, 0x02b3: 0x049b, 0x02b4: 0x049d, 0x02b5: 0x04a0, + 0x02b6: 0x04a3, 0x02b7: 0x04a6, 0x02b8: 0x04a8, + // Block 0xb, offset 0x2c0 + 0x02d8: 0x04aa, 0x02d9: 0x04ae, 0x02da: 0x04b2, 0x02db: 0x04b6, 0x02dc: 0x04ba, 0x02dd: 0x04be, + 0x02e0: 0x04c2, 0x02e1: 0x04c5, 0x02e2: 0x02c8, 0x02e3: 0x04c7, + 0x02e4: 0x04c9, + // Block 0xc, offset 0x300 + 0x0300: 0x04cc, 0x0301: 0x04cf, 0x0303: 0x04d2, 0x0304: 0x04d5, + 0x0334: 0x04da, + 0x033a: 0x04dd, + 0x033e: 0x04e1, + // Block 0xd, offset 0x340 + 0x0344: 0x0011, 0x0345: 0x04e8, + 0x0346: 0x04ee, 0x0347: 0x04f3, 0x0348: 0x04f6, 0x0349: 0x04fb, 0x034a: 0x0500, + 0x034c: 0x0505, 0x034e: 0x050a, 0x034f: 0x050f, 0x0350: 0x0514, + 0x036a: 0x051b, 0x036b: 0x0520, 0x036c: 0x0525, 0x036d: 0x052a, 0x036e: 0x052f, 0x036f: 0x0534, + 0x0370: 0x0539, + // Block 0xe, offset 0x380 + 0x038a: 0x0540, 0x038b: 0x0545, + 0x038c: 0x054a, 0x038d: 0x054f, 0x038e: 0x0554, 0x0390: 0x0559, 0x0391: 0x055c, + 0x0392: 0x055f, 0x0393: 0x050a, 0x0394: 0x0520, 0x0395: 0x056c, 0x0396: 0x056f, + 0x03b0: 0x0572, 0x03b1: 0x0575, 0x03b2: 0x0578, 0x03b4: 0x057b, 0x03b5: 0x057e, + 0x03b9: 0x0581, + // Block 0xf, offset 0x3c0 + 0x03c0: 0x0584, 0x03c1: 0x0589, 0x03c3: 0x058e, + 0x03c7: 0x0593, + 0x03cc: 0x0598, 0x03cd: 0x059d, 0x03ce: 0x05a2, + 0x03d9: 0x05a7, + 0x03f9: 0x05ac, + // Block 0x10, offset 0x400 + 0x0410: 0x05b1, 0x0411: 0x05b6, + 0x0413: 0x05bb, 0x0417: 0x05c0, + 0x041c: 0x05c5, 0x041d: 0x05ca, + 0x041e: 0x05cf, + 0x0436: 0x05d4, 0x0437: 0x05d9, + // Block 0x11, offset 0x440 + 0x0441: 0x05de, 0x0442: 0x05e3, + 0x0450: 0x05e8, 0x0451: 0x05ed, + 0x0452: 0x05f2, 0x0453: 0x05f7, 0x0456: 0x05fc, 0x0457: 0x0601, + 0x045a: 0x0606, 0x045b: 0x060b, 0x045c: 0x0610, 0x045d: 0x0615, + 0x045e: 0x061a, 0x045f: 0x061f, 0x0462: 0x0624, 0x0463: 0x0629, + 0x0464: 0x062e, 0x0465: 0x0633, 0x0466: 0x0638, 0x0467: 0x063d, + 0x046a: 0x0642, 0x046b: 0x0647, 0x046c: 0x064c, 0x046d: 0x0651, 0x046e: 0x0656, 0x046f: 0x065b, + 0x0470: 0x0660, 0x0471: 0x0665, 0x0472: 0x066a, 0x0473: 0x066f, 0x0474: 0x0674, 0x0475: 0x0679, + 0x0478: 0x067e, 0x0479: 0x0683, + // Block 0x12, offset 0x480 + 0x0487: 0x0688, + // Block 0x13, offset 0x4c0 + 0x04e2: 0x068d, 0x04e3: 0x0692, + 0x04e4: 0x0697, 0x04e5: 0x069c, 0x04e6: 0x06a1, + // Block 0x14, offset 0x500 + 0x0535: 0x06a6, + 0x0536: 0x06ab, 0x0537: 0x06b0, 0x0538: 0x06b5, + // Block 0x15, offset 0x540 + 0x0540: 0x06ba, 0x0542: 0x06bf, + 0x0553: 0x06c4, + // Block 0x16, offset 0x580 + 0x05a9: 0x06c9, + 0x05b1: 0x06d0, 0x05b4: 0x06d7, + // Block 0x17, offset 0x5c0 + 0x05d8: 0x06de, 0x05d9: 0x06e5, 0x05da: 0x06ec, 0x05db: 0x06f3, 0x05dc: 0x06fa, 0x05dd: 0x0701, + 0x05de: 0x0708, 0x05df: 0x070f, + // Block 0x18, offset 0x600 + 0x060b: 0x0716, + 0x060c: 0x071d, + 0x061c: 0x0724, 0x061d: 0x072b, + 0x061f: 0x0732, + // Block 0x19, offset 0x640 + 0x0673: 0x0739, + 0x0676: 0x0740, + // Block 0x1a, offset 0x680 + 0x0699: 0x0747, 0x069a: 0x074e, 0x069b: 0x0755, + 0x069e: 0x075c, + // Block 0x1b, offset 0x6c0 + 0x06c8: 0x0763, 0x06cb: 0x076a, + 0x06cc: 0x0771, + 0x06dc: 0x0778, 0x06dd: 0x077f, + // Block 0x1c, offset 0x700 + 0x0714: 0x0786, + // Block 0x1d, offset 0x740 + 0x074a: 0x078d, 0x074b: 0x0794, + 0x074c: 0x079b, + // Block 0x1e, offset 0x780 + 0x0788: 0x07a2, + // Block 0x1f, offset 0x7c0 + 0x07c0: 0x07a9, + 0x07c7: 0x07b0, 0x07c8: 0x07b7, 0x07ca: 0x07be, 0x07cb: 0x07c5, + // Block 0x20, offset 0x800 + 0x080a: 0x07cf, 0x080b: 0x07d6, + 0x080c: 0x07dd, + // Block 0x21, offset 0x840 + 0x085a: 0x07e4, 0x085c: 0x07eb, 0x085d: 0x07f2, + 0x085e: 0x07fc, + // Block 0x22, offset 0x880 + 0x08b3: 0x0803, + // Block 0x23, offset 0x8c0 + 0x08f3: 0x080a, + // Block 0x24, offset 0x900 + 0x091c: 0x0811, 0x091d: 0x0818, + // Block 0x25, offset 0x940 + 0x094c: 0x081f, + // Block 0x26, offset 0x980 + 0x0983: 0x0823, + 0x098d: 0x082a, + 0x0992: 0x0831, 0x0997: 0x0838, + 0x099c: 0x083f, + 0x09a9: 0x0846, + 0x09b3: 0x084d, 0x09b5: 0x0854, + 0x09b6: 0x085b, 0x09b7: 0x0862, 0x09b8: 0x086c, 0x09b9: 0x0873, + // Block 0x27, offset 0x9c0 + 0x09c1: 0x087d, + 0x09d3: 0x0884, + 0x09dd: 0x088b, + 0x09e2: 0x0892, + 0x09e7: 0x0899, + 0x09ec: 0x08a0, + 0x09f9: 0x08a7, + // Block 0x28, offset 0xa00 + 0x0a26: 0x08ae, + // Block 0x29, offset 0xa40 + 0x0a7c: 0x08b5, + // Block 0x2a, offset 0xa80 + 0x0a86: 0x08b9, 0x0a88: 0x08c0, 0x0a8a: 0x08c7, + 0x0a8c: 0x08ce, 0x0a8e: 0x08d5, + 0x0a92: 0x08dc, + 0x0abb: 0x08e3, + 0x0abd: 0x08ea, + // Block 0x2b, offset 0xac0 + 0x0ac0: 0x08f1, 0x0ac1: 0x08f8, 0x0ac3: 0x08ff, + // Block 0x2c, offset 0xb00 + 0x0b2c: 0x0906, 0x0b2d: 0x0908, 0x0b2e: 0x090b, + 0x0b30: 0x090d, 0x0b31: 0x090f, 0x0b32: 0x0911, 0x0b33: 0x0914, 0x0b34: 0x0916, 0x0b35: 0x0918, + 0x0b36: 0x091a, 0x0b37: 0x091c, 0x0b38: 0x091e, 0x0b39: 0x0920, 0x0b3a: 0x0922, + 0x0b3c: 0x0924, 0x0b3d: 0x0926, 0x0b3e: 0x0929, 0x0b3f: 0x092b, + // Block 0x2d, offset 0xb40 + 0x0b40: 0x092d, 0x0b41: 0x092f, 0x0b42: 0x0931, 0x0b43: 0x0007, 0x0b44: 0x0933, 0x0b45: 0x0936, + 0x0b46: 0x0939, 0x0b47: 0x093d, 0x0b48: 0x093f, 0x0b49: 0x0941, 0x0b4a: 0x0943, 0x0b4b: 0x0946, + 0x0b4c: 0x0949, 0x0b4d: 0x094c, 0x0b4f: 0x094e, 0x0b50: 0x0950, 0x0b51: 0x0952, + 0x0b52: 0x001e, 0x0b53: 0x0955, 0x0b54: 0x0958, 0x0b55: 0x095c, 0x0b56: 0x0960, 0x0b57: 0x0962, + 0x0b58: 0x0964, 0x0b59: 0x0966, 0x0b5a: 0x096a, 0x0b5b: 0x096d, 0x0b5c: 0x096f, 0x0b5d: 0x0559, + 0x0b5e: 0x0973, 0x0b5f: 0x0976, 0x0b60: 0x056c, 0x0b61: 0x0979, 0x0b62: 0x097c, 0x0b63: 0x049b, + 0x0b64: 0x0964, 0x0b65: 0x096d, 0x0b66: 0x0559, 0x0b67: 0x0973, 0x0b68: 0x0575, 0x0b69: 0x056c, + 0x0b6a: 0x0979, + 0x0b78: 0x097e, + // Block 0x2e, offset 0xb80 + 0x0b9b: 0x0981, 0x0b9c: 0x0984, 0x0b9d: 0x0986, + 0x0b9e: 0x0989, 0x0b9f: 0x0949, 0x0ba0: 0x098c, 0x0ba1: 0x098e, 0x0ba2: 0x0991, 0x0ba3: 0x0994, + 0x0ba4: 0x0997, 0x0ba5: 0x099a, 0x0ba6: 0x099d, 0x0ba7: 0x09a0, 0x0ba8: 0x09a4, 0x0ba9: 0x09a7, + 0x0baa: 0x09aa, 0x0bab: 0x09ae, 0x0bac: 0x09b1, 0x0bad: 0x09b4, 0x0bae: 0x09b7, 0x0baf: 0x09ba, + 0x0bb0: 0x09bd, 0x0bb1: 0x09c0, 0x0bb2: 0x09c3, 0x0bb3: 0x09c6, 0x0bb4: 0x09c9, 0x0bb5: 0x09cc, + 0x0bb6: 0x09cf, 0x0bb7: 0x09d2, 0x0bb8: 0x09d5, 0x0bb9: 0x09d9, 0x0bba: 0x09dc, 0x0bbb: 0x09df, + 0x0bbc: 0x09e1, 0x0bbd: 0x09e4, 0x0bbe: 0x09e7, 0x0bbf: 0x055c, + // Block 0x2f, offset 0xbc0 + 0x0bc0: 0x09ea, 0x0bc1: 0x09ee, 0x0bc2: 0x09f2, 0x0bc3: 0x09f6, 0x0bc4: 0x09fa, 0x0bc5: 0x09fe, + 0x0bc6: 0x0a02, 0x0bc7: 0x0a06, 0x0bc8: 0x0a0a, 0x0bc9: 0x0a10, 0x0bca: 0x0a16, 0x0bcb: 0x0a1a, + 0x0bcc: 0x0a1e, 0x0bcd: 0x0a22, 0x0bce: 0x0a26, 0x0bcf: 0x0a2a, 0x0bd0: 0x0a2e, 0x0bd1: 0x0a32, + 0x0bd2: 0x0a36, 0x0bd3: 0x0a3a, 0x0bd4: 0x0a3e, 0x0bd5: 0x0a44, 0x0bd6: 0x0a4a, 0x0bd7: 0x0a50, + 0x0bd8: 0x0a56, 0x0bd9: 0x0a5a, 0x0bda: 0x0a5e, 0x0bdb: 0x0a62, 0x0bdc: 0x0a66, 0x0bdd: 0x0a6c, + 0x0bde: 0x0a72, 0x0bdf: 0x0a76, 0x0be0: 0x0a7a, 0x0be1: 0x0a7e, 0x0be2: 0x0a82, 0x0be3: 0x0a86, + 0x0be4: 0x0a8a, 0x0be5: 0x0a8e, 0x0be6: 0x0a92, 0x0be7: 0x0a96, 0x0be8: 0x0a9a, 0x0be9: 0x0a9e, + 0x0bea: 0x0aa2, 0x0beb: 0x0aa6, 0x0bec: 0x0aaa, 0x0bed: 0x0aae, 0x0bee: 0x0ab2, 0x0bef: 0x0ab8, + 0x0bf0: 0x0abe, 0x0bf1: 0x0ac2, 0x0bf2: 0x0ac6, 0x0bf3: 0x0aca, 0x0bf4: 0x0ace, 0x0bf5: 0x0ad2, + 0x0bf6: 0x0ad6, 0x0bf7: 0x0ada, 0x0bf8: 0x0ade, 0x0bf9: 0x0ae4, 0x0bfa: 0x0aea, 0x0bfb: 0x0aee, + 0x0bfc: 0x0af2, 0x0bfd: 0x0af6, 0x0bfe: 0x0afa, 0x0bff: 0x0afe, + // Block 0x30, offset 0xc00 + 0x0c00: 0x0b02, 0x0c01: 0x0b06, 0x0c02: 0x0b0a, 0x0c03: 0x0b0e, 0x0c04: 0x0b12, 0x0c05: 0x0b16, + 0x0c06: 0x0b1a, 0x0c07: 0x0b1e, 0x0c08: 0x0b22, 0x0c09: 0x0b26, 0x0c0a: 0x0b2a, 0x0c0b: 0x0b2e, + 0x0c0c: 0x0b32, 0x0c0d: 0x0b38, 0x0c0e: 0x0b3e, 0x0c0f: 0x0b44, 0x0c10: 0x0b4a, 0x0c11: 0x0b50, + 0x0c12: 0x0b56, 0x0c13: 0x0b5c, 0x0c14: 0x0b62, 0x0c15: 0x0b66, 0x0c16: 0x0b6a, 0x0c17: 0x0b6e, + 0x0c18: 0x0b72, 0x0c19: 0x0b76, 0x0c1a: 0x0b7a, 0x0c1b: 0x0b7e, 0x0c1c: 0x0b82, 0x0c1d: 0x0b88, + 0x0c1e: 0x0b8e, 0x0c1f: 0x0b92, 0x0c20: 0x0b96, 0x0c21: 0x0b9a, 0x0c22: 0x0b9e, 0x0c23: 0x0ba2, + 0x0c24: 0x0ba6, 0x0c25: 0x0bac, 0x0c26: 0x0bb2, 0x0c27: 0x0bb8, 0x0c28: 0x0bbe, 0x0c29: 0x0bc4, + 0x0c2a: 0x0bca, 0x0c2b: 0x0bce, 0x0c2c: 0x0bd2, 0x0c2d: 0x0bd6, 0x0c2e: 0x0bda, 0x0c2f: 0x0bde, + 0x0c30: 0x0be2, 0x0c31: 0x0be6, 0x0c32: 0x0bea, 0x0c33: 0x0bee, 0x0c34: 0x0bf2, 0x0c35: 0x0bf6, + 0x0c36: 0x0bfa, 0x0c37: 0x0bfe, 0x0c38: 0x0c02, 0x0c39: 0x0c08, 0x0c3a: 0x0c0e, 0x0c3b: 0x0c14, + 0x0c3c: 0x0c1a, 0x0c3d: 0x0c1e, 0x0c3e: 0x0c22, 0x0c3f: 0x0c26, + // Block 0x31, offset 0xc40 + 0x0c40: 0x0c2a, 0x0c41: 0x0c2e, 0x0c42: 0x0c32, 0x0c43: 0x0c36, 0x0c44: 0x0c3a, 0x0c45: 0x0c3e, + 0x0c46: 0x0c42, 0x0c47: 0x0c46, 0x0c48: 0x0c4a, 0x0c49: 0x0c4e, 0x0c4a: 0x0c52, 0x0c4b: 0x0c56, + 0x0c4c: 0x0c5a, 0x0c4d: 0x0c5e, 0x0c4e: 0x0c62, 0x0c4f: 0x0c66, 0x0c50: 0x0c6a, 0x0c51: 0x0c6e, + 0x0c52: 0x0c72, 0x0c53: 0x0c76, 0x0c54: 0x0c7a, 0x0c55: 0x0c7e, 0x0c56: 0x0c82, 0x0c57: 0x0c86, + 0x0c58: 0x0c8a, 0x0c59: 0x0c8e, 0x0c5a: 0x0c92, 0x0c5b: 0x0b9a, + 0x0c60: 0x0c9b, 0x0c61: 0x0c9f, 0x0c62: 0x0ca3, 0x0c63: 0x0ca7, + 0x0c64: 0x0cab, 0x0c65: 0x0cb1, 0x0c66: 0x0cb7, 0x0c67: 0x0cbd, 0x0c68: 0x0cc3, 0x0c69: 0x0cc9, + 0x0c6a: 0x0ccf, 0x0c6b: 0x0cd5, 0x0c6c: 0x0cdb, 0x0c6d: 0x0ce1, 0x0c6e: 0x0ce7, 0x0c6f: 0x0ced, + 0x0c70: 0x0cf3, 0x0c71: 0x0cf9, 0x0c72: 0x0cff, 0x0c73: 0x0d05, 0x0c74: 0x0d0b, 0x0c75: 0x0d11, + 0x0c76: 0x0d17, 0x0c77: 0x0d1d, 0x0c78: 0x0d23, 0x0c79: 0x0d27, 0x0c7a: 0x0d2b, 0x0c7b: 0x0d2f, + 0x0c7c: 0x0d33, 0x0c7d: 0x0d37, 0x0c7e: 0x0d3b, 0x0c7f: 0x0d41, + // Block 0x32, offset 0xc80 + 0x0c80: 0x0d47, 0x0c81: 0x0d4d, 0x0c82: 0x0d53, 0x0c83: 0x0d59, 0x0c84: 0x0d5f, 0x0c85: 0x0d65, + 0x0c86: 0x0d6b, 0x0c87: 0x0d71, 0x0c88: 0x0d77, 0x0c89: 0x0d7b, 0x0c8a: 0x0d7f, 0x0c8b: 0x0d83, + 0x0c8c: 0x0d87, 0x0c8d: 0x0d8b, 0x0c8e: 0x0d8f, 0x0c8f: 0x0d93, 0x0c90: 0x0d97, 0x0c91: 0x0d9d, + 0x0c92: 0x0da3, 0x0c93: 0x0da9, 0x0c94: 0x0daf, 0x0c95: 0x0db5, 0x0c96: 0x0dbb, 0x0c97: 0x0dc1, + 0x0c98: 0x0dc7, 0x0c99: 0x0dcd, 0x0c9a: 0x0dd3, 0x0c9b: 0x0dd9, 0x0c9c: 0x0ddf, 0x0c9d: 0x0de5, + 0x0c9e: 0x0deb, 0x0c9f: 0x0df1, 0x0ca0: 0x0df7, 0x0ca1: 0x0dfd, 0x0ca2: 0x0e03, 0x0ca3: 0x0e09, + 0x0ca4: 0x0e0f, 0x0ca5: 0x0e13, 0x0ca6: 0x0e17, 0x0ca7: 0x0e1b, 0x0ca8: 0x0e1f, 0x0ca9: 0x0e25, + 0x0caa: 0x0e2b, 0x0cab: 0x0e31, 0x0cac: 0x0e37, 0x0cad: 0x0e3d, 0x0cae: 0x0e43, 0x0caf: 0x0e49, + 0x0cb0: 0x0e4f, 0x0cb1: 0x0e55, 0x0cb2: 0x0e5b, 0x0cb3: 0x0e5f, 0x0cb4: 0x0e63, 0x0cb5: 0x0e67, + 0x0cb6: 0x0e6b, 0x0cb7: 0x0e6f, 0x0cb8: 0x0e73, 0x0cb9: 0x0e77, + // Block 0x33, offset 0xcc0 + 0x0cc0: 0x0e7b, 0x0cc1: 0x0e80, 0x0cc2: 0x0e85, 0x0cc3: 0x0e8c, 0x0cc4: 0x0e93, 0x0cc5: 0x0e9a, + 0x0cc6: 0x0ea1, 0x0cc7: 0x0ea8, 0x0cc8: 0x0eaf, 0x0cc9: 0x0eb4, 0x0cca: 0x0eb9, 0x0ccb: 0x0ec0, + 0x0ccc: 0x0ec7, 0x0ccd: 0x0ece, 0x0cce: 0x0ed5, 0x0ccf: 0x0edc, 0x0cd0: 0x0ee3, 0x0cd1: 0x0ee8, + 0x0cd2: 0x0eed, 0x0cd3: 0x0ef4, 0x0cd4: 0x0efb, 0x0cd5: 0x0f02, + 0x0cd8: 0x0f09, 0x0cd9: 0x0f0e, 0x0cda: 0x0f13, 0x0cdb: 0x0f1a, 0x0cdc: 0x0f21, 0x0cdd: 0x0f28, + 0x0ce0: 0x0f2f, 0x0ce1: 0x0f34, 0x0ce2: 0x0f39, 0x0ce3: 0x0f40, + 0x0ce4: 0x0f47, 0x0ce5: 0x0f4e, 0x0ce6: 0x0f55, 0x0ce7: 0x0f5c, 0x0ce8: 0x0f63, 0x0ce9: 0x0f68, + 0x0cea: 0x0f6d, 0x0ceb: 0x0f74, 0x0cec: 0x0f7b, 0x0ced: 0x0f82, 0x0cee: 0x0f89, 0x0cef: 0x0f90, + 0x0cf0: 0x0f97, 0x0cf1: 0x0f9c, 0x0cf2: 0x0fa1, 0x0cf3: 0x0fa8, 0x0cf4: 0x0faf, 0x0cf5: 0x0fb6, + 0x0cf6: 0x0fbd, 0x0cf7: 0x0fc4, 0x0cf8: 0x0fcb, 0x0cf9: 0x0fd0, 0x0cfa: 0x0fd5, 0x0cfb: 0x0fdc, + 0x0cfc: 0x0fe3, 0x0cfd: 0x0fea, 0x0cfe: 0x0ff1, 0x0cff: 0x0ff8, + // Block 0x34, offset 0xd00 + 0x0d00: 0x0fff, 0x0d01: 0x1004, 0x0d02: 0x1009, 0x0d03: 0x1010, 0x0d04: 0x1017, 0x0d05: 0x101e, + 0x0d08: 0x1025, 0x0d09: 0x102a, 0x0d0a: 0x102f, 0x0d0b: 0x1036, + 0x0d0c: 0x103d, 0x0d0d: 0x1044, 0x0d10: 0x104b, 0x0d11: 0x1050, + 0x0d12: 0x1055, 0x0d13: 0x105c, 0x0d14: 0x1063, 0x0d15: 0x106a, 0x0d16: 0x1071, 0x0d17: 0x1078, + 0x0d19: 0x107f, 0x0d1b: 0x1084, 0x0d1d: 0x108b, + 0x0d1f: 0x1092, 0x0d20: 0x1099, 0x0d21: 0x109e, 0x0d22: 0x10a3, 0x0d23: 0x10aa, + 0x0d24: 0x10b1, 0x0d25: 0x10b8, 0x0d26: 0x10bf, 0x0d27: 0x10c6, 0x0d28: 0x10cd, 0x0d29: 0x10d2, + 0x0d2a: 0x10d7, 0x0d2b: 0x10de, 0x0d2c: 0x10e5, 0x0d2d: 0x10ec, 0x0d2e: 0x10f3, 0x0d2f: 0x10fa, + 0x0d30: 0x1101, 0x0d31: 0x0525, 0x0d32: 0x1106, 0x0d33: 0x052a, 0x0d34: 0x110b, 0x0d35: 0x052f, + 0x0d36: 0x1110, 0x0d37: 0x0534, 0x0d38: 0x1115, 0x0d39: 0x054a, 0x0d3a: 0x111a, 0x0d3b: 0x054f, + 0x0d3c: 0x111f, 0x0d3d: 0x0554, + // Block 0x35, offset 0xd40 + 0x0d40: 0x1124, 0x0d41: 0x112b, 0x0d42: 0x1132, 0x0d43: 0x113b, 0x0d44: 0x1144, 0x0d45: 0x114d, + 0x0d46: 0x1156, 0x0d47: 0x115f, 0x0d48: 0x1168, 0x0d49: 0x116f, 0x0d4a: 0x1176, 0x0d4b: 0x117f, + 0x0d4c: 0x1188, 0x0d4d: 0x1191, 0x0d4e: 0x119a, 0x0d4f: 0x11a3, 0x0d50: 0x11ac, 0x0d51: 0x11b3, + 0x0d52: 0x11ba, 0x0d53: 0x11c3, 0x0d54: 0x11cc, 0x0d55: 0x11d5, 0x0d56: 0x11de, 0x0d57: 0x11e7, + 0x0d58: 0x11f0, 0x0d59: 0x11f7, 0x0d5a: 0x11fe, 0x0d5b: 0x1207, 0x0d5c: 0x1210, 0x0d5d: 0x1219, + 0x0d5e: 0x1222, 0x0d5f: 0x122b, 0x0d60: 0x1234, 0x0d61: 0x123b, 0x0d62: 0x1242, 0x0d63: 0x124b, + 0x0d64: 0x1254, 0x0d65: 0x125d, 0x0d66: 0x1266, 0x0d67: 0x126f, 0x0d68: 0x1278, 0x0d69: 0x127f, + 0x0d6a: 0x1286, 0x0d6b: 0x128f, 0x0d6c: 0x1298, 0x0d6d: 0x12a1, 0x0d6e: 0x12aa, 0x0d6f: 0x12b3, + 0x0d70: 0x12bc, 0x0d71: 0x12c1, 0x0d72: 0x12c6, 0x0d73: 0x12cd, 0x0d74: 0x12d2, + 0x0d76: 0x12d9, 0x0d77: 0x12de, 0x0d78: 0x12e5, 0x0d79: 0x12ea, 0x0d7a: 0x12ef, 0x0d7b: 0x04ee, + 0x0d7c: 0x12f4, 0x0d7d: 0x12f9, 0x0d7e: 0x12fd, 0x0d7f: 0x12f9, + // Block 0x36, offset 0xd80 + 0x0d80: 0x1300, 0x0d81: 0x1309, 0x0d82: 0x130f, 0x0d83: 0x1316, 0x0d84: 0x131b, + 0x0d86: 0x1322, 0x0d87: 0x1327, 0x0d88: 0x132e, 0x0d89: 0x04f6, 0x0d8a: 0x1333, 0x0d8b: 0x04fb, + 0x0d8c: 0x1338, 0x0d8d: 0x1343, 0x0d8e: 0x134f, 0x0d8f: 0x135b, 0x0d90: 0x1361, 0x0d91: 0x1366, + 0x0d92: 0x136b, 0x0d93: 0x0514, 0x0d96: 0x1372, 0x0d97: 0x1377, + 0x0d98: 0x137e, 0x0d99: 0x1383, 0x0d9a: 0x1388, 0x0d9b: 0x0500, 0x0d9d: 0x1393, + 0x0d9e: 0x139f, 0x0d9f: 0x13ab, 0x0da0: 0x13b1, 0x0da1: 0x13b6, 0x0da2: 0x13bb, 0x0da3: 0x0539, + 0x0da4: 0x13c2, 0x0da5: 0x13c7, 0x0da6: 0x13cc, 0x0da7: 0x13d1, 0x0da8: 0x13d8, 0x0da9: 0x13dd, + 0x0daa: 0x13e2, 0x0dab: 0x050a, 0x0dac: 0x13e7, 0x0dad: 0x13f1, 0x0dae: 0x04e8, 0x0daf: 0x13f7, + 0x0db2: 0x13f9, 0x0db3: 0x1400, 0x0db4: 0x1405, + 0x0db6: 0x140c, 0x0db7: 0x1411, 0x0db8: 0x1418, 0x0db9: 0x0505, 0x0dba: 0x141d, 0x0dbb: 0x050f, + 0x0dbc: 0x1422, 0x0dbd: 0x0011, 0x0dbe: 0x142a, + // Block 0x37, offset 0xdc0 + 0x0dc0: 0x0001, 0x0dc1: 0x0001, 0x0dc2: 0x0001, 0x0dc3: 0x0001, 0x0dc4: 0x0001, 0x0dc5: 0x0001, + 0x0dc6: 0x0001, 0x0dc7: 0x0001, 0x0dc8: 0x0001, 0x0dc9: 0x0001, 0x0dca: 0x0001, + 0x0dd1: 0x1436, + 0x0dd7: 0x143a, + 0x0de4: 0x143e, 0x0de5: 0x1440, 0x0de6: 0x1443, + 0x0def: 0x0001, + 0x0df3: 0x1447, 0x0df4: 0x144e, + 0x0df6: 0x1458, 0x0df7: 0x145f, + 0x0dfc: 0x1469, 0x0dfe: 0x146c, + // Block 0x38, offset 0xe00 + 0x0e07: 0x1470, 0x0e08: 0x1473, 0x0e09: 0x1476, + 0x0e17: 0x1479, + 0x0e1f: 0x0001, + 0x0e30: 0x1486, 0x0e31: 0x097c, 0x0e34: 0x1488, 0x0e35: 0x148a, + 0x0e36: 0x148c, 0x0e37: 0x148e, 0x0e38: 0x1490, 0x0e39: 0x1492, 0x0e3a: 0x1494, 0x0e3b: 0x1496, + 0x0e3c: 0x149a, 0x0e3d: 0x149c, 0x0e3e: 0x149e, 0x0e3f: 0x14a0, + // Block 0x39, offset 0xe40 + 0x0e40: 0x1486, 0x0e41: 0x001c, 0x0e42: 0x000d, 0x0e43: 0x000f, 0x0e44: 0x1488, 0x0e45: 0x148a, + 0x0e46: 0x148c, 0x0e47: 0x148e, 0x0e48: 0x1490, 0x0e49: 0x1492, 0x0e4a: 0x1494, 0x0e4b: 0x1496, + 0x0e4c: 0x149a, 0x0e4d: 0x149c, 0x0e4e: 0x149e, 0x0e50: 0x0007, 0x0e51: 0x0941, + 0x0e52: 0x001e, 0x0e53: 0x04c7, 0x0e54: 0x0943, 0x0e55: 0x0494, 0x0e56: 0x094e, 0x0e57: 0x04c5, + 0x0e58: 0x0950, 0x0e59: 0x14a0, 0x0e5a: 0x0960, 0x0e5b: 0x02c8, 0x0e5c: 0x0962, + 0x0e68: 0x14a2, + // Block 0x3a, offset 0xe80 + 0x0e80: 0x14a5, 0x0e81: 0x14a9, 0x0e82: 0x14ad, 0x0e83: 0x14af, 0x0e85: 0x14b3, + 0x0e86: 0x14b7, 0x0e87: 0x14bb, 0x0e89: 0x14be, 0x0e8a: 0x094c, 0x0e8b: 0x0916, + 0x0e8c: 0x0916, 0x0e8d: 0x0916, 0x0e8e: 0x0494, 0x0e8f: 0x14c2, 0x0e90: 0x0918, 0x0e91: 0x0918, + 0x0e92: 0x091e, 0x0e93: 0x04c5, 0x0e95: 0x0922, 0x0e96: 0x14c5, + 0x0e99: 0x0929, 0x0e9a: 0x14c8, 0x0e9b: 0x092b, 0x0e9c: 0x092b, 0x0e9d: 0x092b, + 0x0ea0: 0x14ca, 0x0ea1: 0x14cd, 0x0ea2: 0x14d1, + 0x0ea4: 0x14d4, 0x0ea6: 0x14d6, 0x0ea8: 0x14d4, + 0x0eaa: 0x091c, 0x0eab: 0x0046, 0x0eac: 0x090b, 0x0ead: 0x14ad, 0x0eaf: 0x0941, + 0x0eb0: 0x090f, 0x0eb1: 0x14d9, 0x0eb3: 0x0920, 0x0eb4: 0x001e, 0x0eb5: 0x14db, + 0x0eb6: 0x14de, 0x0eb7: 0x14e1, 0x0eb8: 0x14e4, 0x0eb9: 0x097c, 0x0ebb: 0x14e7, + 0x0ebc: 0x056f, 0x0ebd: 0x0973, 0x0ebe: 0x14eb, 0x0ebf: 0x14ee, + // Block 0x3b, offset 0xec0 + 0x0ec0: 0x14f1, 0x0ec5: 0x090d, + 0x0ec6: 0x093f, 0x0ec7: 0x0941, 0x0ec8: 0x097c, 0x0ec9: 0x0499, + 0x0ed0: 0x14f5, 0x0ed1: 0x14fb, + 0x0ed2: 0x1501, 0x0ed3: 0x1508, 0x0ed4: 0x150e, 0x0ed5: 0x1514, 0x0ed6: 0x151a, 0x0ed7: 0x1520, + 0x0ed8: 0x1526, 0x0ed9: 0x152c, 0x0eda: 0x1532, 0x0edb: 0x1538, 0x0edc: 0x153e, 0x0edd: 0x1544, + 0x0ede: 0x154a, 0x0edf: 0x1550, 0x0ee0: 0x0918, 0x0ee1: 0x1555, 0x0ee2: 0x1558, 0x0ee3: 0x155c, + 0x0ee4: 0x155f, 0x0ee5: 0x1561, 0x0ee6: 0x1564, 0x0ee7: 0x1568, 0x0ee8: 0x156d, 0x0ee9: 0x1570, + 0x0eea: 0x1572, 0x0eeb: 0x1575, 0x0eec: 0x091e, 0x0eed: 0x14ad, 0x0eee: 0x090d, 0x0eef: 0x0920, + 0x0ef0: 0x097c, 0x0ef1: 0x1579, 0x0ef2: 0x157c, 0x0ef3: 0x1580, 0x0ef4: 0x096d, 0x0ef5: 0x1583, + 0x0ef6: 0x1586, 0x0ef7: 0x158a, 0x0ef8: 0x158f, 0x0ef9: 0x04c7, 0x0efa: 0x1592, 0x0efb: 0x1595, + 0x0efc: 0x04c5, 0x0efd: 0x0984, 0x0efe: 0x093f, 0x0eff: 0x0950, + // Block 0x3c, offset 0xf00 + 0x0f09: 0x1599, + 0x0f1a: 0x159f, 0x0f1b: 0x15a5, + 0x0f2e: 0x15ab, + // Block 0x3d, offset 0xf40 + 0x0f4d: 0x15b1, 0x0f4e: 0x15b7, 0x0f4f: 0x15bd, + // Block 0x3e, offset 0xf80 + 0x0f84: 0x15c3, + 0x0f89: 0x15c9, + 0x0f8c: 0x15cf, + 0x0fa4: 0x15d5, 0x0fa6: 0x15db, + 0x0fac: 0x15e1, 0x0fad: 0x15e8, 0x0faf: 0x15f2, + 0x0fb0: 0x15f9, + // Block 0x3f, offset 0xfc0 + 0x0fc1: 0x1603, 0x0fc4: 0x1609, + 0x0fc7: 0x160f, 0x0fc9: 0x1615, + 0x0fe0: 0x161b, 0x0fe2: 0x161f, + 0x0fed: 0x1625, 0x0fee: 0x162b, 0x0fef: 0x162f, + 0x0ff0: 0x1633, 0x0ff1: 0x1639, 0x0ff4: 0x163f, 0x0ff5: 0x1645, + 0x0ff8: 0x164b, 0x0ff9: 0x1651, + // Block 0x40, offset 0x1000 + 0x1000: 0x1657, 0x1001: 0x165d, 0x1004: 0x1663, 0x1005: 0x1669, + 0x1008: 0x166f, 0x1009: 0x1675, + 0x102c: 0x167b, 0x102d: 0x1681, 0x102e: 0x1687, 0x102f: 0x168d, + // Block 0x41, offset 0x1040 + 0x1060: 0x1693, 0x1061: 0x1699, 0x1062: 0x169f, 0x1063: 0x16a5, + 0x106a: 0x16ab, 0x106b: 0x16b1, 0x106c: 0x16b7, 0x106d: 0x16bd, + // Block 0x42, offset 0x1080 + 0x10a9: 0x16c3, + 0x10aa: 0x16c7, + // Block 0x43, offset 0x10c0 + 0x10e0: 0x001c, 0x10e1: 0x000d, 0x10e2: 0x000f, 0x10e3: 0x1488, + 0x10e4: 0x148a, 0x10e5: 0x148c, 0x10e6: 0x148e, 0x10e7: 0x1490, 0x10e8: 0x1492, 0x10e9: 0x16cb, + 0x10ea: 0x16ce, 0x10eb: 0x16d1, 0x10ec: 0x16d4, 0x10ed: 0x16d7, 0x10ee: 0x16da, 0x10ef: 0x16dd, + 0x10f0: 0x16e0, 0x10f1: 0x16e3, 0x10f2: 0x16e6, 0x10f3: 0x16e9, 0x10f4: 0x16ec, 0x10f5: 0x16f0, + 0x10f6: 0x16f4, 0x10f7: 0x16f8, 0x10f8: 0x16fc, 0x10f9: 0x1700, 0x10fa: 0x1704, 0x10fb: 0x1708, + 0x10fc: 0x170c, 0x10fd: 0x1710, 0x10fe: 0x1715, 0x10ff: 0x171a, + // Block 0x44, offset 0x1100 + 0x1100: 0x171f, 0x1101: 0x1724, 0x1102: 0x1729, 0x1103: 0x172e, 0x1104: 0x1733, 0x1105: 0x1738, + 0x1106: 0x173d, 0x1107: 0x1742, 0x1108: 0x1747, 0x1109: 0x174a, 0x110a: 0x174d, 0x110b: 0x1750, + 0x110c: 0x1753, 0x110d: 0x1756, 0x110e: 0x1759, 0x110f: 0x175c, 0x1110: 0x175f, 0x1111: 0x1762, + 0x1112: 0x1766, 0x1113: 0x176a, 0x1114: 0x176e, 0x1115: 0x1772, 0x1116: 0x1776, 0x1117: 0x177a, + 0x1118: 0x177e, 0x1119: 0x1782, 0x111a: 0x1786, 0x111b: 0x178a, 0x111c: 0x178e, 0x111d: 0x1792, + 0x111e: 0x1796, 0x111f: 0x179a, 0x1120: 0x179e, 0x1121: 0x17a2, 0x1122: 0x17a6, 0x1123: 0x17aa, + 0x1124: 0x17ae, 0x1125: 0x17b2, 0x1126: 0x17b6, 0x1127: 0x17ba, 0x1128: 0x17be, 0x1129: 0x17c2, + 0x112a: 0x17c6, 0x112b: 0x17ca, 0x112c: 0x17ce, 0x112d: 0x17d2, 0x112e: 0x17d6, 0x112f: 0x17da, + 0x1130: 0x17de, 0x1131: 0x17e2, 0x1132: 0x17e6, 0x1133: 0x17ea, 0x1134: 0x17ee, 0x1135: 0x17f2, + 0x1136: 0x0906, 0x1137: 0x090b, 0x1138: 0x14ad, 0x1139: 0x090d, 0x113a: 0x090f, 0x113b: 0x14d9, + 0x113c: 0x0914, 0x113d: 0x0916, 0x113e: 0x0918, 0x113f: 0x091a, + // Block 0x45, offset 0x1140 + 0x1140: 0x091c, 0x1141: 0x091e, 0x1142: 0x0920, 0x1143: 0x0922, 0x1144: 0x0924, 0x1145: 0x0929, + 0x1146: 0x14c8, 0x1147: 0x092b, 0x1148: 0x17f6, 0x1149: 0x092d, 0x114a: 0x092f, 0x114b: 0x155f, + 0x114c: 0x0931, 0x114d: 0x1570, 0x114e: 0x17f8, 0x114f: 0x14d4, 0x1150: 0x0007, 0x1151: 0x093d, + 0x1152: 0x0984, 0x1153: 0x093f, 0x1154: 0x0941, 0x1155: 0x098c, 0x1156: 0x094c, 0x1157: 0x0494, + 0x1158: 0x097c, 0x1159: 0x0499, 0x115a: 0x094e, 0x115b: 0x04c5, 0x115c: 0x0950, 0x115d: 0x14a0, + 0x115e: 0x001e, 0x115f: 0x0960, 0x1160: 0x17fa, 0x1161: 0x049b, 0x1162: 0x02c8, 0x1163: 0x0962, + 0x1164: 0x0964, 0x1165: 0x096d, 0x1166: 0x04a6, 0x1167: 0x04c7, 0x1168: 0x04a8, 0x1169: 0x09df, + 0x116a: 0x1486, + // Block 0x46, offset 0x1180 + 0x118c: 0x17fc, + // Block 0x47, offset 0x11c0 + 0x11f4: 0x1809, 0x11f5: 0x180d, + 0x11f6: 0x1810, + // Block 0x48, offset 0x1200 + 0x121c: 0x1814, + // Block 0x49, offset 0x1240 + 0x127c: 0x0499, 0x127d: 0x155f, + // Block 0x4a, offset 0x1280 + 0x12af: 0x181a, + // Block 0x4b, offset 0x12c0 + 0x12df: 0x181e, + // Block 0x4c, offset 0x1300 + 0x1333: 0x1822, + // Block 0x4d, offset 0x1340 + 0x1340: 0x1826, 0x1341: 0x182a, 0x1342: 0x182e, 0x1343: 0x1832, 0x1344: 0x1836, 0x1345: 0x183a, + 0x1346: 0x183e, 0x1347: 0x1842, 0x1348: 0x1846, 0x1349: 0x184a, 0x134a: 0x184e, 0x134b: 0x1852, + 0x134c: 0x1856, 0x134d: 0x185a, 0x134e: 0x185e, 0x134f: 0x1862, 0x1350: 0x1866, 0x1351: 0x186a, + 0x1352: 0x186e, 0x1353: 0x1872, 0x1354: 0x1876, 0x1355: 0x187a, 0x1356: 0x187e, 0x1357: 0x1882, + 0x1358: 0x1886, 0x1359: 0x188a, 0x135a: 0x188e, 0x135b: 0x1892, 0x135c: 0x1896, 0x135d: 0x189a, + 0x135e: 0x189e, 0x135f: 0x18a2, 0x1360: 0x18a6, 0x1361: 0x18aa, 0x1362: 0x18ae, 0x1363: 0x18b2, + 0x1364: 0x18b6, 0x1365: 0x18ba, 0x1366: 0x18be, 0x1367: 0x18c2, 0x1368: 0x18c6, 0x1369: 0x18ca, + 0x136a: 0x18ce, 0x136b: 0x18d2, 0x136c: 0x18d6, 0x136d: 0x18da, 0x136e: 0x18de, 0x136f: 0x18e2, + 0x1370: 0x18e6, 0x1371: 0x18ea, 0x1372: 0x18ee, 0x1373: 0x18f2, 0x1374: 0x18f6, 0x1375: 0x18fa, + 0x1376: 0x18fe, 0x1377: 0x1902, 0x1378: 0x1906, 0x1379: 0x190a, 0x137a: 0x190e, 0x137b: 0x1912, + 0x137c: 0x1916, 0x137d: 0x191a, 0x137e: 0x191e, 0x137f: 0x1922, + // Block 0x4e, offset 0x1380 + 0x1380: 0x1926, 0x1381: 0x192a, 0x1382: 0x192e, 0x1383: 0x1932, 0x1384: 0x1936, 0x1385: 0x193a, + 0x1386: 0x193e, 0x1387: 0x1942, 0x1388: 0x1946, 0x1389: 0x194a, 0x138a: 0x194e, 0x138b: 0x1952, + 0x138c: 0x1956, 0x138d: 0x195a, 0x138e: 0x195e, 0x138f: 0x1962, 0x1390: 0x1966, 0x1391: 0x196a, + 0x1392: 0x196e, 0x1393: 0x1972, 0x1394: 0x1976, 0x1395: 0x197a, 0x1396: 0x197e, 0x1397: 0x1982, + 0x1398: 0x1986, 0x1399: 0x198a, 0x139a: 0x198e, 0x139b: 0x1992, 0x139c: 0x1996, 0x139d: 0x199a, + 0x139e: 0x199e, 0x139f: 0x19a2, 0x13a0: 0x19a6, 0x13a1: 0x19aa, 0x13a2: 0x19ae, 0x13a3: 0x19b2, + 0x13a4: 0x19b6, 0x13a5: 0x19ba, 0x13a6: 0x19be, 0x13a7: 0x19c2, 0x13a8: 0x19c6, 0x13a9: 0x19ca, + 0x13aa: 0x19ce, 0x13ab: 0x19d2, 0x13ac: 0x19d6, 0x13ad: 0x19da, 0x13ae: 0x19de, 0x13af: 0x19e2, + 0x13b0: 0x19e6, 0x13b1: 0x19ea, 0x13b2: 0x19ee, 0x13b3: 0x19f2, 0x13b4: 0x19f6, 0x13b5: 0x19fa, + 0x13b6: 0x19fe, 0x13b7: 0x1a02, 0x13b8: 0x1a06, 0x13b9: 0x1a0a, 0x13ba: 0x1a0e, 0x13bb: 0x1a12, + 0x13bc: 0x1a16, 0x13bd: 0x1a1a, 0x13be: 0x1a1e, 0x13bf: 0x1a22, + // Block 0x4f, offset 0x13c0 + 0x13c0: 0x1a26, 0x13c1: 0x1a2a, 0x13c2: 0x1a2e, 0x13c3: 0x1a32, 0x13c4: 0x1a36, 0x13c5: 0x1a3a, + 0x13c6: 0x1a3e, 0x13c7: 0x1a42, 0x13c8: 0x1a46, 0x13c9: 0x1a4a, 0x13ca: 0x1a4e, 0x13cb: 0x1a52, + 0x13cc: 0x1a56, 0x13cd: 0x1a5a, 0x13ce: 0x1a5e, 0x13cf: 0x1a62, 0x13d0: 0x1a66, 0x13d1: 0x1a6a, + 0x13d2: 0x1a6e, 0x13d3: 0x1a72, 0x13d4: 0x1a76, 0x13d5: 0x1a7a, 0x13d6: 0x1a7e, 0x13d7: 0x1a82, + 0x13d8: 0x1a86, 0x13d9: 0x1a8a, 0x13da: 0x1a8e, 0x13db: 0x1a92, 0x13dc: 0x1a96, 0x13dd: 0x1a9a, + 0x13de: 0x1a9e, 0x13df: 0x1aa2, 0x13e0: 0x1aa6, 0x13e1: 0x1aaa, 0x13e2: 0x1aae, 0x13e3: 0x1ab2, + 0x13e4: 0x1ab6, 0x13e5: 0x1aba, 0x13e6: 0x1abe, 0x13e7: 0x1ac2, 0x13e8: 0x1ac6, 0x13e9: 0x1aca, + 0x13ea: 0x1ace, 0x13eb: 0x1ad2, 0x13ec: 0x1ad6, 0x13ed: 0x1ada, 0x13ee: 0x1ade, 0x13ef: 0x1ae2, + 0x13f0: 0x1ae6, 0x13f1: 0x1aea, 0x13f2: 0x1aee, 0x13f3: 0x1af2, 0x13f4: 0x1af6, 0x13f5: 0x1afa, + 0x13f6: 0x1afe, 0x13f7: 0x1b02, 0x13f8: 0x1b06, 0x13f9: 0x1b0a, 0x13fa: 0x1b0e, 0x13fb: 0x1b12, + 0x13fc: 0x1b16, 0x13fd: 0x1b1a, 0x13fe: 0x1b1e, 0x13ff: 0x1b22, + // Block 0x50, offset 0x1400 + 0x1400: 0x1b26, 0x1401: 0x1b2a, 0x1402: 0x1b2e, 0x1403: 0x1b32, 0x1404: 0x1b36, 0x1405: 0x1b3a, + 0x1406: 0x1b3e, 0x1407: 0x1b42, 0x1408: 0x1b46, 0x1409: 0x1b4a, 0x140a: 0x1b4e, 0x140b: 0x1b52, + 0x140c: 0x1b56, 0x140d: 0x1b5a, 0x140e: 0x1b5e, 0x140f: 0x1b62, 0x1410: 0x1b66, 0x1411: 0x1b6a, + 0x1412: 0x1b6e, 0x1413: 0x1b72, 0x1414: 0x1b76, 0x1415: 0x1b7a, + // Block 0x51, offset 0x1440 + 0x1440: 0x0001, + 0x1476: 0x1b7e, 0x1478: 0x1882, 0x1479: 0x1b82, 0x147a: 0x1b86, + // Block 0x52, offset 0x1480 + 0x148c: 0x1b8a, 0x148e: 0x1b91, 0x1490: 0x1b98, + 0x1492: 0x1b9f, 0x1494: 0x1ba6, 0x1496: 0x1bad, + 0x1498: 0x1bb4, 0x149a: 0x1bbb, 0x149c: 0x1bc2, + 0x149e: 0x1bc9, 0x14a0: 0x1bd0, 0x14a2: 0x1bd7, + 0x14a5: 0x1bde, 0x14a7: 0x1be5, 0x14a9: 0x1bec, + 0x14b0: 0x1bf3, 0x14b1: 0x1bfa, 0x14b3: 0x1c01, 0x14b4: 0x1c08, + 0x14b6: 0x1c0f, 0x14b7: 0x1c16, 0x14b9: 0x1c1d, 0x14ba: 0x1c24, + 0x14bc: 0x1c2b, 0x14bd: 0x1c32, + // Block 0x53, offset 0x14c0 + 0x14d4: 0x1c39, + 0x14db: 0x1c40, 0x14dc: 0x1c45, + 0x14de: 0x1c4a, 0x14df: 0x1c51, + 0x14ec: 0x1c58, 0x14ee: 0x1c5f, + 0x14f0: 0x1c66, 0x14f2: 0x1c6d, 0x14f4: 0x1c74, + 0x14f6: 0x1c7b, 0x14f8: 0x1c82, 0x14fa: 0x1c89, + 0x14fc: 0x1c90, 0x14fe: 0x1c97, + // Block 0x54, offset 0x1500 + 0x1500: 0x1c9e, 0x1502: 0x1ca5, 0x1505: 0x1cac, + 0x1507: 0x1cb3, 0x1509: 0x1cba, + 0x1510: 0x1cc1, 0x1511: 0x1cc8, + 0x1513: 0x1ccf, 0x1514: 0x1cd6, 0x1516: 0x1cdd, 0x1517: 0x1ce4, + 0x1519: 0x1ceb, 0x151a: 0x1cf2, 0x151c: 0x1cf9, 0x151d: 0x1d00, + 0x1534: 0x1d07, + 0x1537: 0x1d0e, 0x1538: 0x1d15, 0x1539: 0x1d1c, 0x153a: 0x1d23, + 0x153e: 0x1d2a, 0x153f: 0x1d31, + // Block 0x55, offset 0x1540 + 0x1571: 0x1d38, 0x1572: 0x1d3c, 0x1573: 0x1d40, 0x1574: 0x1d44, 0x1575: 0x1d48, + 0x1576: 0x1d4c, 0x1577: 0x1d50, 0x1578: 0x1d54, 0x1579: 0x1d58, 0x157a: 0x1d5c, 0x157b: 0x1d60, + 0x157c: 0x1d64, 0x157d: 0x1d68, 0x157e: 0x1d6c, 0x157f: 0x1d70, + // Block 0x56, offset 0x1580 + 0x1580: 0x1d74, 0x1581: 0x1d78, 0x1582: 0x1d7c, 0x1583: 0x1d80, 0x1584: 0x1d84, 0x1585: 0x1d88, + 0x1586: 0x1d8c, 0x1587: 0x1d90, 0x1588: 0x1d94, 0x1589: 0x1d98, 0x158a: 0x1d9c, 0x158b: 0x1da0, + 0x158c: 0x1da4, 0x158d: 0x1da8, 0x158e: 0x1dac, 0x158f: 0x1db0, 0x1590: 0x1db4, 0x1591: 0x1db8, + 0x1592: 0x1dbc, 0x1593: 0x1dc0, 0x1594: 0x1dc4, 0x1595: 0x1dc8, 0x1596: 0x1dcc, 0x1597: 0x1dd0, + 0x1598: 0x1dd4, 0x1599: 0x1dd8, 0x159a: 0x1ddc, 0x159b: 0x1de0, 0x159c: 0x1de4, 0x159d: 0x1de8, + 0x159e: 0x1dec, 0x159f: 0x1df0, 0x15a0: 0x1df4, 0x15a1: 0x1df8, 0x15a2: 0x1dfc, 0x15a3: 0x1e00, + 0x15a4: 0x1e04, 0x15a5: 0x1e08, 0x15a6: 0x1e0c, 0x15a7: 0x1e10, 0x15a8: 0x1e14, 0x15a9: 0x1e18, + 0x15aa: 0x1e1c, 0x15ab: 0x1e20, 0x15ac: 0x1e24, 0x15ad: 0x1e28, 0x15ae: 0x1e2c, 0x15af: 0x1e30, + 0x15b0: 0x1e34, 0x15b1: 0x1e38, 0x15b2: 0x1e3c, 0x15b3: 0x1e40, 0x15b4: 0x1e44, 0x15b5: 0x1e48, + 0x15b6: 0x1e4c, 0x15b7: 0x1e50, 0x15b8: 0x1e54, 0x15b9: 0x1e58, 0x15ba: 0x1e5c, 0x15bb: 0x1e60, + 0x15bc: 0x1e64, 0x15bd: 0x1e68, 0x15be: 0x1e6c, 0x15bf: 0x1e70, + // Block 0x57, offset 0x15c0 + 0x15c0: 0x1e74, 0x15c1: 0x1e78, 0x15c2: 0x1e7c, 0x15c3: 0x1e80, 0x15c4: 0x1e84, 0x15c5: 0x1e88, + 0x15c6: 0x1e8c, 0x15c7: 0x1e90, 0x15c8: 0x1e94, 0x15c9: 0x1e98, 0x15ca: 0x1e9c, 0x15cb: 0x1ea0, + 0x15cc: 0x1ea4, 0x15cd: 0x1ea8, 0x15ce: 0x1eac, + 0x15d2: 0x1826, 0x15d3: 0x183e, 0x15d4: 0x1eb0, 0x15d5: 0x1eb4, 0x15d6: 0x1eb8, 0x15d7: 0x1ebc, + 0x15d8: 0x1ec0, 0x15d9: 0x1ec4, 0x15da: 0x1836, 0x15db: 0x1ec8, 0x15dc: 0x1ecc, 0x15dd: 0x1ed0, + 0x15de: 0x1ed4, 0x15df: 0x1846, + // Block 0x58, offset 0x1600 + 0x1600: 0x1ed8, 0x1601: 0x1ede, 0x1602: 0x1ee4, 0x1603: 0x1eea, 0x1604: 0x1ef0, 0x1605: 0x1ef6, + 0x1606: 0x1efc, 0x1607: 0x1f02, 0x1608: 0x1f08, 0x1609: 0x1f0e, 0x160a: 0x1f14, 0x160b: 0x1f1a, + 0x160c: 0x1f20, 0x160d: 0x1f26, 0x160e: 0x1f2c, 0x160f: 0x1f35, 0x1610: 0x1f3e, 0x1611: 0x1f47, + 0x1612: 0x1f50, 0x1613: 0x1f59, 0x1614: 0x1f62, 0x1615: 0x1f6b, 0x1616: 0x1f74, 0x1617: 0x1f7d, + 0x1618: 0x1f86, 0x1619: 0x1f8f, 0x161a: 0x1f98, 0x161b: 0x1fa1, 0x161c: 0x1faa, 0x161d: 0x1fb3, + 0x161e: 0x1fc5, 0x1620: 0x1fd4, 0x1621: 0x1fda, 0x1622: 0x1fe0, 0x1623: 0x1fe6, + 0x1624: 0x1fec, 0x1625: 0x1ff2, 0x1626: 0x1ff8, 0x1627: 0x1ffe, 0x1628: 0x2004, 0x1629: 0x200a, + 0x162a: 0x2010, 0x162b: 0x2016, 0x162c: 0x201c, 0x162d: 0x2022, 0x162e: 0x2028, 0x162f: 0x202e, + 0x1630: 0x2034, 0x1631: 0x203a, 0x1632: 0x2040, 0x1633: 0x2046, 0x1634: 0x204c, 0x1635: 0x2052, + 0x1636: 0x2058, 0x1637: 0x205e, 0x1638: 0x2064, 0x1639: 0x206a, 0x163a: 0x2070, 0x163b: 0x2076, + 0x163c: 0x207c, 0x163d: 0x2082, 0x163e: 0x2088, 0x163f: 0x208e, + // Block 0x59, offset 0x1640 + 0x1640: 0x2094, 0x1641: 0x209a, 0x1642: 0x20a0, 0x1643: 0x20a6, 0x1644: 0x20ac, 0x1645: 0x20b0, + 0x1646: 0x192e, 0x1647: 0x20b4, + 0x1650: 0x20b8, 0x1651: 0x20bc, + 0x1652: 0x20bf, 0x1653: 0x20c2, 0x1654: 0x20c5, 0x1655: 0x20c8, 0x1656: 0x20cb, 0x1657: 0x20ce, + 0x1658: 0x20d1, 0x1659: 0x20d4, 0x165a: 0x20d7, 0x165b: 0x20da, 0x165c: 0x20dd, 0x165d: 0x20e0, + 0x165e: 0x20e3, 0x165f: 0x20e6, 0x1660: 0x1d38, 0x1661: 0x1d44, 0x1662: 0x1d50, 0x1663: 0x1d58, + 0x1664: 0x1d78, 0x1665: 0x1d7c, 0x1666: 0x1d88, 0x1667: 0x1d90, 0x1668: 0x1d94, 0x1669: 0x1d9c, + 0x166a: 0x1da0, 0x166b: 0x1da4, 0x166c: 0x1da8, 0x166d: 0x1dac, 0x166e: 0x20e9, 0x166f: 0x20f0, + 0x1670: 0x20f7, 0x1671: 0x20fe, 0x1672: 0x2105, 0x1673: 0x210c, 0x1674: 0x2113, 0x1675: 0x211a, + 0x1676: 0x2121, 0x1677: 0x2128, 0x1678: 0x212f, 0x1679: 0x2136, 0x167a: 0x213d, 0x167b: 0x2144, + 0x167c: 0x214b, 0x167d: 0x215b, 0x167e: 0x2168, + // Block 0x5a, offset 0x1680 + 0x1680: 0x1826, 0x1681: 0x183e, 0x1682: 0x1eb0, 0x1683: 0x1eb4, 0x1684: 0x216f, 0x1685: 0x2173, + 0x1686: 0x2177, 0x1687: 0x1852, 0x1688: 0x217b, 0x1689: 0x1882, 0x168a: 0x194a, 0x168b: 0x197a, + 0x168c: 0x1976, 0x168d: 0x194e, 0x168e: 0x1abe, 0x168f: 0x18a2, 0x1690: 0x1942, 0x1691: 0x217f, + 0x1692: 0x2183, 0x1693: 0x2187, 0x1694: 0x218b, 0x1695: 0x218f, 0x1696: 0x2193, 0x1697: 0x2197, + 0x1698: 0x219b, 0x1699: 0x219f, 0x169a: 0x21a3, 0x169b: 0x18ba, 0x169c: 0x21a7, 0x169d: 0x21ab, + 0x169e: 0x21af, 0x169f: 0x21b3, 0x16a0: 0x21b7, 0x16a1: 0x21bb, 0x16a2: 0x21bf, 0x16a3: 0x21c3, + 0x16a4: 0x1eb8, 0x16a5: 0x1ebc, 0x16a6: 0x1ec0, 0x16a7: 0x21c7, 0x16a8: 0x21cb, 0x16a9: 0x21cf, + 0x16aa: 0x21d3, 0x16ab: 0x21d7, 0x16ac: 0x21db, 0x16ad: 0x21df, 0x16ae: 0x21e3, 0x16af: 0x21e7, + 0x16b0: 0x21eb, 0x16b1: 0x21ef, 0x16b2: 0x21f2, 0x16b3: 0x21f5, 0x16b4: 0x21f8, 0x16b5: 0x21fb, + 0x16b6: 0x21fe, 0x16b7: 0x2201, 0x16b8: 0x2204, 0x16b9: 0x2207, 0x16ba: 0x220a, 0x16bb: 0x220d, + 0x16bc: 0x2210, 0x16bd: 0x2213, 0x16be: 0x2216, 0x16bf: 0x2219, + // Block 0x5b, offset 0x16c0 + 0x16c0: 0x221c, 0x16c1: 0x2221, 0x16c2: 0x2226, 0x16c3: 0x222b, 0x16c4: 0x2230, 0x16c5: 0x2235, + 0x16c6: 0x223a, 0x16c7: 0x223f, 0x16c8: 0x2244, 0x16c9: 0x2249, 0x16ca: 0x224f, 0x16cb: 0x2255, + 0x16cc: 0x225b, 0x16cd: 0x225e, 0x16ce: 0x2262, 0x16cf: 0x2265, 0x16d0: 0x2269, 0x16d1: 0x226d, + 0x16d2: 0x2271, 0x16d3: 0x2275, 0x16d4: 0x2279, 0x16d5: 0x227d, 0x16d6: 0x2281, 0x16d7: 0x2285, + 0x16d8: 0x2289, 0x16d9: 0x228d, 0x16da: 0x2291, 0x16db: 0x2295, 0x16dc: 0x2299, 0x16dd: 0x229d, + 0x16de: 0x22a1, 0x16df: 0x22a5, 0x16e0: 0x22a9, 0x16e1: 0x22ad, 0x16e2: 0x22b1, 0x16e3: 0x22b5, + 0x16e4: 0x22b9, 0x16e5: 0x22bd, 0x16e6: 0x22c1, 0x16e7: 0x22c5, 0x16e8: 0x22c9, 0x16e9: 0x22cd, + 0x16ea: 0x22d1, 0x16eb: 0x22d5, 0x16ec: 0x22d9, 0x16ed: 0x22dd, 0x16ee: 0x22e1, 0x16ef: 0x22e5, + 0x16f0: 0x22e9, 0x16f1: 0x22ed, 0x16f2: 0x22f1, 0x16f3: 0x22f5, 0x16f4: 0x22f9, 0x16f5: 0x22fd, + 0x16f6: 0x2301, 0x16f7: 0x2305, 0x16f8: 0x2309, 0x16f9: 0x230d, 0x16fa: 0x2311, 0x16fb: 0x2315, + 0x16fc: 0x2319, 0x16fd: 0x231d, 0x16fe: 0x2321, + // Block 0x5c, offset 0x1700 + 0x1700: 0x2325, 0x1701: 0x2335, 0x1702: 0x2342, 0x1703: 0x2352, 0x1704: 0x235c, 0x1705: 0x236c, + 0x1706: 0x2376, 0x1707: 0x2380, 0x1708: 0x2393, 0x1709: 0x23a0, 0x170a: 0x23aa, 0x170b: 0x23b4, + 0x170c: 0x23be, 0x170d: 0x23cb, 0x170e: 0x23d8, 0x170f: 0x23e5, 0x1710: 0x23f2, 0x1711: 0x23ff, + 0x1712: 0x240c, 0x1713: 0x2419, 0x1714: 0x242c, 0x1715: 0x2433, 0x1716: 0x2446, 0x1717: 0x2459, + 0x1718: 0x2469, 0x1719: 0x2476, 0x171a: 0x2489, 0x171b: 0x249c, 0x171c: 0x24a9, 0x171d: 0x24b3, + 0x171e: 0x24bd, 0x171f: 0x24ca, 0x1720: 0x24d7, 0x1721: 0x24e7, 0x1722: 0x24f7, 0x1723: 0x2501, + 0x1724: 0x250b, 0x1725: 0x2518, 0x1726: 0x2522, 0x1727: 0x252c, 0x1728: 0x2533, 0x1729: 0x253a, + 0x172a: 0x2544, 0x172b: 0x254e, 0x172c: 0x2561, 0x172d: 0x256e, 0x172e: 0x257e, 0x172f: 0x2591, + 0x1730: 0x259e, 0x1731: 0x25a8, 0x1732: 0x25b2, 0x1733: 0x25c5, 0x1734: 0x25d2, 0x1735: 0x25e5, + 0x1736: 0x25ef, 0x1737: 0x25ff, 0x1738: 0x2609, 0x1739: 0x2616, 0x173a: 0x2620, 0x173b: 0x262d, + 0x173c: 0x263d, 0x173d: 0x264a, 0x173e: 0x265a, 0x173f: 0x2667, + // Block 0x5d, offset 0x1740 + 0x1740: 0x266e, 0x1741: 0x267e, 0x1742: 0x2688, 0x1743: 0x2692, 0x1744: 0x269f, 0x1745: 0x26a9, + 0x1746: 0x26b3, 0x1747: 0x26bd, 0x1748: 0x26cd, 0x1749: 0x26da, 0x174a: 0x26e1, 0x174b: 0x26f4, + 0x174c: 0x26fe, 0x174d: 0x270e, 0x174e: 0x271b, 0x174f: 0x2728, 0x1750: 0x2732, 0x1751: 0x273c, + 0x1752: 0x2749, 0x1753: 0x2750, 0x1754: 0x275d, 0x1755: 0x276d, 0x1756: 0x2774, 0x1757: 0x2787, + 0x1758: 0x2791, 0x1759: 0x2796, 0x175a: 0x279b, 0x175b: 0x27a0, 0x175c: 0x27a5, 0x175d: 0x27aa, + 0x175e: 0x27af, 0x175f: 0x27b4, 0x1760: 0x27b9, 0x1761: 0x27be, 0x1762: 0x27c3, 0x1763: 0x27c9, + 0x1764: 0x27cf, 0x1765: 0x27d5, 0x1766: 0x27db, 0x1767: 0x27e1, 0x1768: 0x27e7, 0x1769: 0x27ed, + 0x176a: 0x27f3, 0x176b: 0x27f9, 0x176c: 0x27ff, 0x176d: 0x2805, 0x176e: 0x280b, 0x176f: 0x2811, + 0x1770: 0x2817, 0x1771: 0x281d, 0x1772: 0x2821, 0x1773: 0x2824, 0x1774: 0x2827, 0x1775: 0x282b, + 0x1776: 0x282e, 0x1777: 0x2831, 0x1778: 0x2834, 0x1779: 0x2838, 0x177a: 0x283c, 0x177b: 0x283f, + 0x177c: 0x2846, 0x177d: 0x284d, 0x177e: 0x2854, 0x177f: 0x285b, + // Block 0x5e, offset 0x1780 + 0x1780: 0x2868, 0x1781: 0x286b, 0x1782: 0x286e, 0x1783: 0x2872, 0x1784: 0x2875, 0x1785: 0x2878, + 0x1786: 0x287b, 0x1787: 0x287e, 0x1788: 0x2881, 0x1789: 0x2885, 0x178a: 0x288a, 0x178b: 0x288d, + 0x178c: 0x2890, 0x178d: 0x2894, 0x178e: 0x2898, 0x178f: 0x289b, 0x1790: 0x289e, 0x1791: 0x28a1, + 0x1792: 0x28a5, 0x1793: 0x28a9, 0x1794: 0x28ad, 0x1795: 0x28b1, 0x1796: 0x28b5, 0x1797: 0x28b8, + 0x1798: 0x28bb, 0x1799: 0x28be, 0x179a: 0x28c1, 0x179b: 0x28c4, 0x179c: 0x28c8, 0x179d: 0x28cb, + 0x179e: 0x28ce, 0x179f: 0x28d1, 0x17a0: 0x28d5, 0x17a1: 0x28d9, 0x17a2: 0x28dc, 0x17a3: 0x28e0, + 0x17a4: 0x28e4, 0x17a5: 0x28e8, 0x17a6: 0x28eb, 0x17a7: 0x28ef, 0x17a8: 0x28f5, 0x17a9: 0x28fc, + 0x17aa: 0x28ff, 0x17ab: 0x2903, 0x17ac: 0x2907, 0x17ad: 0x290b, 0x17ae: 0x290f, 0x17af: 0x2917, + 0x17b0: 0x2920, 0x17b1: 0x2923, 0x17b2: 0x2926, 0x17b3: 0x292a, 0x17b4: 0x292d, 0x17b5: 0x2930, + 0x17b6: 0x2933, 0x17b7: 0x2937, 0x17b8: 0x293a, 0x17b9: 0x293d, 0x17ba: 0x2940, 0x17bb: 0x2943, + 0x17bc: 0x2946, 0x17bd: 0x294a, 0x17be: 0x294d, 0x17bf: 0x2950, + // Block 0x5f, offset 0x17c0 + 0x17c0: 0x2953, 0x17c1: 0x2957, 0x17c2: 0x295b, 0x17c3: 0x2960, 0x17c4: 0x2963, 0x17c5: 0x2966, + 0x17c6: 0x2969, 0x17c7: 0x2970, 0x17c8: 0x2974, 0x17c9: 0x2977, 0x17ca: 0x297a, 0x17cb: 0x297d, + 0x17cc: 0x2980, 0x17cd: 0x2983, 0x17ce: 0x2986, 0x17cf: 0x2989, 0x17d0: 0x298c, 0x17d1: 0x298f, + 0x17d2: 0x2992, 0x17d3: 0x2996, 0x17d4: 0x2999, 0x17d5: 0x299c, 0x17d6: 0x29a0, 0x17d7: 0x29a4, + 0x17d8: 0x29a7, 0x17d9: 0x29ac, 0x17da: 0x29b0, 0x17db: 0x29b3, 0x17dc: 0x29b6, 0x17dd: 0x29b9, + 0x17de: 0x29bc, 0x17df: 0x29c2, 0x17e0: 0x29c8, 0x17e1: 0x29cd, 0x17e2: 0x29d2, 0x17e3: 0x29d7, + 0x17e4: 0x29dc, 0x17e5: 0x29e1, 0x17e6: 0x29e6, 0x17e7: 0x29eb, 0x17e8: 0x29f0, 0x17e9: 0x29f5, + 0x17ea: 0x29fb, 0x17eb: 0x2a01, 0x17ec: 0x2a07, 0x17ed: 0x2a0d, 0x17ee: 0x2a13, 0x17ef: 0x2a19, + 0x17f0: 0x2a1f, 0x17f1: 0x2a25, 0x17f2: 0x2a2b, 0x17f3: 0x2a31, 0x17f4: 0x2a37, 0x17f5: 0x2a3d, + 0x17f6: 0x2a43, 0x17f7: 0x2a49, 0x17f8: 0x2a4f, 0x17f9: 0x2a55, 0x17fa: 0x2a5b, 0x17fb: 0x2a61, + 0x17fc: 0x2a67, 0x17fd: 0x2a6d, 0x17fe: 0x2a73, 0x17ff: 0x2a79, + // Block 0x60, offset 0x1800 + 0x1830: 0x2a7d, + // Block 0x61, offset 0x1840 + 0x1840: 0x2a81, 0x1841: 0x2a85, 0x1842: 0x1a9e, 0x1843: 0x2a89, 0x1844: 0x2a8d, 0x1845: 0x2a91, + 0x1846: 0x2a95, 0x1847: 0x1b76, 0x1848: 0x1b76, 0x1849: 0x2a99, 0x184a: 0x1abe, 0x184b: 0x2a9d, + 0x184c: 0x2aa1, 0x184d: 0x2aa5, 0x184e: 0x2aa9, 0x184f: 0x2aad, 0x1850: 0x2ab1, 0x1851: 0x2ab5, + 0x1852: 0x2ab9, 0x1853: 0x2abd, 0x1854: 0x2ac1, 0x1855: 0x2ac5, 0x1856: 0x2ac9, 0x1857: 0x2acd, + 0x1858: 0x2ad1, 0x1859: 0x2ad5, 0x185a: 0x2ad9, 0x185b: 0x2add, 0x185c: 0x2ae1, 0x185d: 0x2ae5, + 0x185e: 0x2ae9, 0x185f: 0x2aed, 0x1860: 0x2af1, 0x1861: 0x2af5, 0x1862: 0x2af9, 0x1863: 0x2afd, + 0x1864: 0x2b01, 0x1865: 0x2b05, 0x1866: 0x2b09, 0x1867: 0x2b0d, 0x1868: 0x2b11, 0x1869: 0x2b15, + 0x186a: 0x2b19, 0x186b: 0x2b1d, 0x186c: 0x2b21, 0x186d: 0x2b25, 0x186e: 0x2b29, 0x186f: 0x2b2d, + 0x1870: 0x2b31, 0x1871: 0x2b35, 0x1872: 0x2b39, 0x1873: 0x2b3d, 0x1874: 0x1a16, 0x1875: 0x2b41, + 0x1876: 0x2b45, 0x1877: 0x2b49, 0x1878: 0x2b4d, 0x1879: 0x2b51, 0x187a: 0x2b55, 0x187b: 0x2b59, + 0x187c: 0x2b5d, 0x187d: 0x2b61, 0x187e: 0x2b65, 0x187f: 0x2b69, + // Block 0x62, offset 0x1880 + 0x1880: 0x1b3a, 0x1881: 0x2b6d, 0x1882: 0x2b71, 0x1883: 0x2b75, 0x1884: 0x2b79, 0x1885: 0x2b7d, + 0x1886: 0x2b81, 0x1887: 0x2b85, 0x1888: 0x2b89, 0x1889: 0x2b8d, 0x188a: 0x2b91, 0x188b: 0x2b95, + 0x188c: 0x2b99, 0x188d: 0x2b9d, 0x188e: 0x2ba1, 0x188f: 0x2ba5, 0x1890: 0x2ba9, 0x1891: 0x2bad, + 0x1892: 0x2bb1, 0x1893: 0x2bb5, 0x1894: 0x2bb9, 0x1895: 0x2bbd, 0x1896: 0x2bc1, 0x1897: 0x2bc5, + 0x1898: 0x2bc9, 0x1899: 0x2bcd, 0x189a: 0x2bd1, 0x189b: 0x2bd5, 0x189c: 0x2ac1, 0x189d: 0x2bd9, + 0x189e: 0x2bdd, 0x189f: 0x2be1, 0x18a0: 0x2be5, 0x18a1: 0x2be9, 0x18a2: 0x2bed, 0x18a3: 0x2bf1, + 0x18a4: 0x2bf5, 0x18a5: 0x2bf9, 0x18a6: 0x2bfd, 0x18a7: 0x2c01, 0x18a8: 0x2c05, 0x18a9: 0x2c09, + 0x18aa: 0x2c0d, 0x18ab: 0x2c11, 0x18ac: 0x2c15, 0x18ad: 0x2c19, 0x18ae: 0x2c1d, 0x18af: 0x2c21, + 0x18b0: 0x2c25, 0x18b1: 0x1aa6, 0x18b2: 0x2c29, 0x18b3: 0x2c2d, 0x18b4: 0x2c31, 0x18b5: 0x2c35, + 0x18b6: 0x2c39, 0x18b7: 0x2c3d, 0x18b8: 0x2c41, 0x18b9: 0x2c45, 0x18ba: 0x2c49, 0x18bb: 0x2c4d, + 0x18bc: 0x2c51, 0x18bd: 0x2c55, 0x18be: 0x2c59, 0x18bf: 0x2c5d, + // Block 0x63, offset 0x18c0 + 0x18c0: 0x2c61, 0x18c1: 0x18ba, 0x18c2: 0x2c65, 0x18c3: 0x2c69, 0x18c4: 0x2c6d, 0x18c5: 0x2c71, + 0x18c6: 0x2c75, 0x18c7: 0x2c79, 0x18c8: 0x2c7d, 0x18c9: 0x2c81, 0x18ca: 0x186e, 0x18cb: 0x2c85, + 0x18cc: 0x2c89, 0x18cd: 0x2c8d, 0x18ce: 0x2c91, 0x18cf: 0x2c95, 0x18d0: 0x2c99, 0x18d1: 0x2c9d, + 0x18d2: 0x2ca1, 0x18d3: 0x2ca5, 0x18d4: 0x2ca9, 0x18d5: 0x2cad, 0x18d6: 0x2cb1, 0x18d7: 0x2cb5, + 0x18d8: 0x2cb9, 0x18d9: 0x2cbd, 0x18da: 0x2cc1, 0x18db: 0x2cc5, 0x18dc: 0x2cc9, 0x18dd: 0x2ccd, + 0x18de: 0x2cd1, 0x18df: 0x2cd5, 0x18e0: 0x2cd9, 0x18e1: 0x2c21, 0x18e2: 0x2cdd, 0x18e3: 0x2ce1, + 0x18e4: 0x2ce5, 0x18e5: 0x2ce9, 0x18e6: 0x2ced, 0x18e7: 0x2cf1, 0x18e8: 0x2cf5, 0x18e9: 0x2cf9, + 0x18ea: 0x2be1, 0x18eb: 0x2cfd, 0x18ec: 0x2d01, 0x18ed: 0x2d05, 0x18ee: 0x2d09, 0x18ef: 0x2d0d, + 0x18f0: 0x2d11, 0x18f1: 0x2d15, 0x18f2: 0x2d19, 0x18f3: 0x2d1d, 0x18f4: 0x2d21, 0x18f5: 0x2d25, + 0x18f6: 0x2d29, 0x18f7: 0x2d2d, 0x18f8: 0x2d31, 0x18f9: 0x2d35, 0x18fa: 0x2d39, 0x18fb: 0x2d3d, + 0x18fc: 0x2d41, 0x18fd: 0x2d45, 0x18fe: 0x2d49, 0x18ff: 0x2ac1, + // Block 0x64, offset 0x1900 + 0x1900: 0x2d4d, 0x1901: 0x2d51, 0x1902: 0x2d55, 0x1903: 0x2d59, 0x1904: 0x1b72, 0x1905: 0x2d5d, + 0x1906: 0x2d61, 0x1907: 0x2d65, 0x1908: 0x2d69, 0x1909: 0x2d6d, 0x190a: 0x2d71, 0x190b: 0x2d75, + 0x190c: 0x2d79, 0x190d: 0x2d7d, 0x190e: 0x2d81, 0x190f: 0x2d85, 0x1910: 0x2d89, 0x1911: 0x2173, + 0x1912: 0x2d8d, 0x1913: 0x2d91, 0x1914: 0x2d95, 0x1915: 0x2d99, 0x1916: 0x2d9d, 0x1917: 0x2da1, + 0x1918: 0x2da5, 0x1919: 0x2da9, 0x191a: 0x2dad, 0x191b: 0x2be9, 0x191c: 0x2db1, 0x191d: 0x2db5, + 0x191e: 0x2db9, 0x191f: 0x2dbd, 0x1920: 0x2dc1, 0x1921: 0x2dc5, 0x1922: 0x2dc9, 0x1923: 0x2dcd, + 0x1924: 0x2dd1, 0x1925: 0x2dd5, 0x1926: 0x2dd9, 0x1927: 0x2ddd, 0x1928: 0x2de1, 0x1929: 0x1aba, + 0x192a: 0x2de5, 0x192b: 0x2de9, 0x192c: 0x2ded, 0x192d: 0x2df1, 0x192e: 0x2df5, 0x192f: 0x2df9, + 0x1930: 0x2dfd, 0x1931: 0x2e01, 0x1932: 0x2e05, 0x1933: 0x2e09, 0x1934: 0x2e0d, 0x1935: 0x2e11, + 0x1936: 0x2e15, 0x1937: 0x19f6, 0x1938: 0x2e19, 0x1939: 0x2e1d, 0x193a: 0x2e21, 0x193b: 0x2e25, + 0x193c: 0x2e29, 0x193d: 0x2e2d, 0x193e: 0x2e31, 0x193f: 0x2e35, + // Block 0x65, offset 0x1940 + 0x1940: 0x2e39, 0x1941: 0x2e3d, 0x1942: 0x2e41, 0x1943: 0x2e45, 0x1944: 0x2e49, 0x1945: 0x2e4d, + 0x1946: 0x2e51, 0x1947: 0x2e55, 0x1948: 0x1a62, 0x1949: 0x2e59, 0x194a: 0x1a6e, 0x194b: 0x2e5d, + 0x194c: 0x2e61, 0x194d: 0x2e65, 0x1950: 0x2e69, + 0x1952: 0x2e6d, 0x1955: 0x2e71, 0x1956: 0x2e75, 0x1957: 0x2e79, + 0x1958: 0x2e7d, 0x1959: 0x2e81, 0x195a: 0x2e85, 0x195b: 0x2e89, 0x195c: 0x2e8d, 0x195d: 0x2e91, + 0x195e: 0x1a12, 0x1960: 0x2e95, 0x1962: 0x2e99, + 0x1965: 0x2e9d, 0x1966: 0x2ea1, + 0x196a: 0x2ea5, 0x196b: 0x2ea9, 0x196c: 0x2ead, 0x196d: 0x2eb1, + 0x1970: 0x2eb5, 0x1971: 0x2eb9, 0x1972: 0x2ebd, 0x1973: 0x2ec1, 0x1974: 0x2ec5, 0x1975: 0x2ec9, + 0x1976: 0x2ecd, 0x1977: 0x2ed1, 0x1978: 0x2ed5, 0x1979: 0x2ed9, 0x197a: 0x2edd, 0x197b: 0x2ee1, + 0x197c: 0x18d6, 0x197d: 0x2ee5, 0x197e: 0x2ee9, 0x197f: 0x2eed, + // Block 0x66, offset 0x1980 + 0x1980: 0x2ef1, 0x1981: 0x2ef5, 0x1982: 0x2ef9, 0x1983: 0x2efd, 0x1984: 0x2f01, 0x1985: 0x2f05, + 0x1986: 0x2f09, 0x1987: 0x2f0d, 0x1988: 0x2f11, 0x1989: 0x2f15, 0x198a: 0x2f19, 0x198b: 0x2f1d, + 0x198c: 0x2187, 0x198d: 0x2f21, 0x198e: 0x2f25, 0x198f: 0x2f29, 0x1990: 0x2f2d, 0x1991: 0x2197, + 0x1992: 0x2f31, 0x1993: 0x2f35, 0x1994: 0x2f39, 0x1995: 0x2f3d, 0x1996: 0x2f41, 0x1997: 0x2cb1, + 0x1998: 0x2f45, 0x1999: 0x2f49, 0x199a: 0x2f4d, 0x199b: 0x2f51, 0x199c: 0x2f55, 0x199d: 0x2f59, + 0x199e: 0x2f59, 0x199f: 0x2f5d, 0x19a0: 0x2f61, 0x19a1: 0x2f65, 0x19a2: 0x2f69, 0x19a3: 0x2f6d, + 0x19a4: 0x2f71, 0x19a5: 0x2f75, 0x19a6: 0x2f79, 0x19a7: 0x2e9d, 0x19a8: 0x2f7d, 0x19a9: 0x2f81, + 0x19aa: 0x2f85, 0x19ab: 0x2f89, 0x19ac: 0x2f8d, 0x19ad: 0x2f92, + 0x19b0: 0x2f96, 0x19b1: 0x2f9a, 0x19b2: 0x2f9e, 0x19b3: 0x2fa2, 0x19b4: 0x2fa6, 0x19b5: 0x2faa, + 0x19b6: 0x2fae, 0x19b7: 0x2fb2, 0x19b8: 0x2ecd, 0x19b9: 0x2fb6, 0x19ba: 0x2fba, 0x19bb: 0x2fbe, + 0x19bc: 0x2e69, 0x19bd: 0x2fc2, 0x19be: 0x2fc6, 0x19bf: 0x2fca, + // Block 0x67, offset 0x19c0 + 0x19c0: 0x2fce, 0x19c1: 0x2fd2, 0x19c2: 0x2fd6, 0x19c3: 0x2fda, 0x19c4: 0x2fde, 0x19c5: 0x2fe2, + 0x19c6: 0x2fe6, 0x19c7: 0x2fea, 0x19c8: 0x2fee, 0x19c9: 0x2eed, 0x19ca: 0x2ff2, 0x19cb: 0x2ef1, + 0x19cc: 0x2ff6, 0x19cd: 0x2ffa, 0x19ce: 0x2ffe, 0x19cf: 0x3002, 0x19d0: 0x3006, 0x19d1: 0x2e6d, + 0x19d2: 0x2b15, 0x19d3: 0x300a, 0x19d4: 0x300e, 0x19d5: 0x195a, 0x19d6: 0x2c25, 0x19d7: 0x2d71, + 0x19d8: 0x3012, 0x19d9: 0x3016, 0x19da: 0x2f0d, 0x19db: 0x301a, 0x19dc: 0x2f11, 0x19dd: 0x301e, + 0x19de: 0x3022, 0x19df: 0x3026, 0x19e0: 0x2e75, 0x19e1: 0x302a, 0x19e2: 0x302e, 0x19e3: 0x3032, + 0x19e4: 0x3036, 0x19e5: 0x303a, 0x19e6: 0x2e79, 0x19e7: 0x303e, 0x19e8: 0x3042, 0x19e9: 0x3046, + 0x19ea: 0x304a, 0x19eb: 0x304e, 0x19ec: 0x3052, 0x19ed: 0x2f41, 0x19ee: 0x3056, 0x19ef: 0x305a, + 0x19f0: 0x2cb1, 0x19f1: 0x305e, 0x19f2: 0x2f51, 0x19f3: 0x3062, 0x19f4: 0x3066, 0x19f5: 0x306a, + 0x19f6: 0x306e, 0x19f7: 0x3072, 0x19f8: 0x2f65, 0x19f9: 0x3076, 0x19fa: 0x2e99, 0x19fb: 0x307a, + 0x19fc: 0x2f69, 0x19fd: 0x2bd9, 0x19fe: 0x307e, 0x19ff: 0x2f6d, + // Block 0x68, offset 0x1a00 + 0x1a00: 0x3082, 0x1a01: 0x2f75, 0x1a02: 0x3086, 0x1a03: 0x308a, 0x1a04: 0x308e, 0x1a05: 0x3092, + 0x1a06: 0x3096, 0x1a07: 0x2f7d, 0x1a08: 0x2e8d, 0x1a09: 0x309a, 0x1a0a: 0x2f81, 0x1a0b: 0x309e, + 0x1a0c: 0x2f85, 0x1a0d: 0x30a2, 0x1a0e: 0x1b76, 0x1a0f: 0x30a6, 0x1a10: 0x30ab, 0x1a11: 0x30b0, + 0x1a12: 0x30b5, 0x1a13: 0x30b9, 0x1a14: 0x30bd, 0x1a15: 0x30c1, 0x1a16: 0x30c6, 0x1a17: 0x30cb, + 0x1a18: 0x30d0, 0x1a19: 0x30d4, + // Block 0x69, offset 0x1a40 + 0x1a40: 0x30d8, 0x1a41: 0x30db, 0x1a42: 0x30de, 0x1a43: 0x30e1, 0x1a44: 0x30e5, 0x1a45: 0x30e9, + 0x1a46: 0x30e9, + 0x1a53: 0x30ec, 0x1a54: 0x30f1, 0x1a55: 0x30f6, 0x1a56: 0x30fb, 0x1a57: 0x3100, + 0x1a5d: 0x3105, + 0x1a5f: 0x310a, 0x1a60: 0x310f, 0x1a61: 0x14db, 0x1a62: 0x14e4, 0x1a63: 0x3112, + 0x1a64: 0x3115, 0x1a65: 0x3118, 0x1a66: 0x311b, 0x1a67: 0x311e, 0x1a68: 0x3121, 0x1a69: 0x1494, + 0x1a6a: 0x3124, 0x1a6b: 0x3129, 0x1a6c: 0x312e, 0x1a6d: 0x3135, 0x1a6e: 0x313c, 0x1a6f: 0x3141, + 0x1a70: 0x3146, 0x1a71: 0x314b, 0x1a72: 0x3150, 0x1a73: 0x3155, 0x1a74: 0x315a, 0x1a75: 0x315f, + 0x1a76: 0x3164, 0x1a78: 0x3169, 0x1a79: 0x316e, 0x1a7a: 0x3173, 0x1a7b: 0x3178, + 0x1a7c: 0x317d, 0x1a7e: 0x3182, + // Block 0x6a, offset 0x1a80 + 0x1a80: 0x3187, 0x1a81: 0x318c, 0x1a83: 0x3191, 0x1a84: 0x3196, + 0x1a86: 0x319b, 0x1a87: 0x31a0, 0x1a88: 0x31a5, 0x1a89: 0x31aa, 0x1a8a: 0x31af, 0x1a8b: 0x31b4, + 0x1a8c: 0x31b9, 0x1a8d: 0x31be, 0x1a8e: 0x31c3, 0x1a8f: 0x31c8, 0x1a90: 0x31cd, 0x1a91: 0x31cd, + 0x1a92: 0x31d0, 0x1a93: 0x31d0, 0x1a94: 0x31d0, 0x1a95: 0x31d0, 0x1a96: 0x31d3, 0x1a97: 0x31d3, + 0x1a98: 0x31d3, 0x1a99: 0x31d3, 0x1a9a: 0x31d6, 0x1a9b: 0x31d6, 0x1a9c: 0x31d6, 0x1a9d: 0x31d6, + 0x1a9e: 0x31d9, 0x1a9f: 0x31d9, 0x1aa0: 0x31d9, 0x1aa1: 0x31d9, 0x1aa2: 0x31dc, 0x1aa3: 0x31dc, + 0x1aa4: 0x31dc, 0x1aa5: 0x31dc, 0x1aa6: 0x31df, 0x1aa7: 0x31df, 0x1aa8: 0x31df, 0x1aa9: 0x31df, + 0x1aaa: 0x31e2, 0x1aab: 0x31e2, 0x1aac: 0x31e2, 0x1aad: 0x31e2, 0x1aae: 0x31e5, 0x1aaf: 0x31e5, + 0x1ab0: 0x31e5, 0x1ab1: 0x31e5, 0x1ab2: 0x31e8, 0x1ab3: 0x31e8, 0x1ab4: 0x31e8, 0x1ab5: 0x31e8, + 0x1ab6: 0x31eb, 0x1ab7: 0x31eb, 0x1ab8: 0x31eb, 0x1ab9: 0x31eb, 0x1aba: 0x31ee, 0x1abb: 0x31ee, + 0x1abc: 0x31ee, 0x1abd: 0x31ee, 0x1abe: 0x31f1, 0x1abf: 0x31f1, + // Block 0x6b, offset 0x1ac0 + 0x1ac0: 0x31f1, 0x1ac1: 0x31f1, 0x1ac2: 0x31f4, 0x1ac3: 0x31f4, 0x1ac4: 0x31f7, 0x1ac5: 0x31f7, + 0x1ac6: 0x31fa, 0x1ac7: 0x31fa, 0x1ac8: 0x31fd, 0x1ac9: 0x31fd, 0x1aca: 0x3200, 0x1acb: 0x3200, + 0x1acc: 0x3203, 0x1acd: 0x3203, 0x1ace: 0x3206, 0x1acf: 0x3206, 0x1ad0: 0x3206, 0x1ad1: 0x3206, + 0x1ad2: 0x3209, 0x1ad3: 0x3209, 0x1ad4: 0x3209, 0x1ad5: 0x3209, 0x1ad6: 0x320c, 0x1ad7: 0x320c, + 0x1ad8: 0x320c, 0x1ad9: 0x320c, 0x1ada: 0x320f, 0x1adb: 0x320f, 0x1adc: 0x320f, 0x1add: 0x320f, + 0x1ade: 0x3212, 0x1adf: 0x3212, 0x1ae0: 0x3215, 0x1ae1: 0x3215, 0x1ae2: 0x3215, 0x1ae3: 0x3215, + 0x1ae4: 0x06ba, 0x1ae5: 0x06ba, 0x1ae6: 0x3218, 0x1ae7: 0x3218, 0x1ae8: 0x3218, 0x1ae9: 0x3218, + 0x1aea: 0x321b, 0x1aeb: 0x321b, 0x1aec: 0x321b, 0x1aed: 0x321b, 0x1aee: 0x321e, 0x1aef: 0x321e, + 0x1af0: 0x06c4, 0x1af1: 0x06c4, + // Block 0x6c, offset 0x1b00 + 0x1b13: 0x3221, 0x1b14: 0x3221, 0x1b15: 0x3221, 0x1b16: 0x3221, 0x1b17: 0x3224, + 0x1b18: 0x3224, 0x1b19: 0x3227, 0x1b1a: 0x3227, 0x1b1b: 0x322a, 0x1b1c: 0x322a, 0x1b1d: 0x06b0, + 0x1b1e: 0x322d, 0x1b1f: 0x322d, 0x1b20: 0x3230, 0x1b21: 0x3230, 0x1b22: 0x3233, 0x1b23: 0x3233, + 0x1b24: 0x3236, 0x1b25: 0x3236, 0x1b26: 0x3236, 0x1b27: 0x3236, 0x1b28: 0x3239, 0x1b29: 0x3239, + 0x1b2a: 0x323c, 0x1b2b: 0x323c, 0x1b2c: 0x3243, 0x1b2d: 0x3243, 0x1b2e: 0x324a, 0x1b2f: 0x324a, + 0x1b30: 0x3251, 0x1b31: 0x3251, 0x1b32: 0x3258, 0x1b33: 0x3258, 0x1b34: 0x325f, 0x1b35: 0x325f, + 0x1b36: 0x3266, 0x1b37: 0x3266, 0x1b38: 0x3266, 0x1b39: 0x326d, 0x1b3a: 0x326d, 0x1b3b: 0x326d, + 0x1b3c: 0x3274, 0x1b3d: 0x3274, 0x1b3e: 0x3274, 0x1b3f: 0x3274, + // Block 0x6d, offset 0x1b40 + 0x1b40: 0x3277, 0x1b41: 0x327e, 0x1b42: 0x3285, 0x1b43: 0x326d, 0x1b44: 0x328c, 0x1b45: 0x3293, + 0x1b46: 0x3298, 0x1b47: 0x329d, 0x1b48: 0x32a2, 0x1b49: 0x32a7, 0x1b4a: 0x32ac, 0x1b4b: 0x32b1, + 0x1b4c: 0x32b6, 0x1b4d: 0x32bb, 0x1b4e: 0x32c0, 0x1b4f: 0x32c5, 0x1b50: 0x32ca, 0x1b51: 0x32cf, + 0x1b52: 0x32d4, 0x1b53: 0x32d9, 0x1b54: 0x32de, 0x1b55: 0x32e3, 0x1b56: 0x32e8, 0x1b57: 0x32ed, + 0x1b58: 0x32f2, 0x1b59: 0x32f7, 0x1b5a: 0x32fc, 0x1b5b: 0x3301, 0x1b5c: 0x3306, 0x1b5d: 0x330b, + 0x1b5e: 0x3310, 0x1b5f: 0x3315, 0x1b60: 0x331a, 0x1b61: 0x331f, 0x1b62: 0x3324, 0x1b63: 0x3329, + 0x1b64: 0x332e, 0x1b65: 0x3333, 0x1b66: 0x3338, 0x1b67: 0x333d, 0x1b68: 0x3342, 0x1b69: 0x3347, + 0x1b6a: 0x334c, 0x1b6b: 0x3351, 0x1b6c: 0x3356, 0x1b6d: 0x335b, 0x1b6e: 0x3360, 0x1b6f: 0x3365, + 0x1b70: 0x336a, 0x1b71: 0x336f, 0x1b72: 0x3374, 0x1b73: 0x3379, 0x1b74: 0x337e, 0x1b75: 0x3383, + 0x1b76: 0x3388, 0x1b77: 0x338d, 0x1b78: 0x3392, 0x1b79: 0x3397, 0x1b7a: 0x339c, 0x1b7b: 0x33a1, + 0x1b7c: 0x33a6, 0x1b7d: 0x33ab, 0x1b7e: 0x33b0, 0x1b7f: 0x33b5, + // Block 0x6e, offset 0x1b80 + 0x1b80: 0x33ba, 0x1b81: 0x33bf, 0x1b82: 0x33c4, 0x1b83: 0x33c9, 0x1b84: 0x33ce, 0x1b85: 0x33d3, + 0x1b86: 0x33d8, 0x1b87: 0x33dd, 0x1b88: 0x33e2, 0x1b89: 0x33e7, 0x1b8a: 0x33ec, 0x1b8b: 0x33f1, + 0x1b8c: 0x33f6, 0x1b8d: 0x33fb, 0x1b8e: 0x3400, 0x1b8f: 0x3405, 0x1b90: 0x340a, 0x1b91: 0x340f, + 0x1b92: 0x3414, 0x1b93: 0x3419, 0x1b94: 0x341e, 0x1b95: 0x3423, 0x1b96: 0x3428, 0x1b97: 0x342d, + 0x1b98: 0x3432, 0x1b99: 0x3437, 0x1b9a: 0x343c, 0x1b9b: 0x3441, 0x1b9c: 0x3446, 0x1b9d: 0x344b, + 0x1b9e: 0x3450, 0x1b9f: 0x3456, 0x1ba0: 0x345c, 0x1ba1: 0x3462, 0x1ba2: 0x3468, 0x1ba3: 0x346e, + 0x1ba4: 0x3474, 0x1ba5: 0x347b, 0x1ba6: 0x3285, 0x1ba7: 0x3482, 0x1ba8: 0x326d, 0x1ba9: 0x328c, + 0x1baa: 0x3489, 0x1bab: 0x348e, 0x1bac: 0x32a2, 0x1bad: 0x3493, 0x1bae: 0x32a7, 0x1baf: 0x32ac, + 0x1bb0: 0x3498, 0x1bb1: 0x349d, 0x1bb2: 0x32c0, 0x1bb3: 0x34a2, 0x1bb4: 0x32c5, 0x1bb5: 0x32ca, + 0x1bb6: 0x34a7, 0x1bb7: 0x34ac, 0x1bb8: 0x32d4, 0x1bb9: 0x34b1, 0x1bba: 0x32d9, 0x1bbb: 0x32de, + 0x1bbc: 0x336f, 0x1bbd: 0x3374, 0x1bbe: 0x3383, 0x1bbf: 0x3388, + // Block 0x6f, offset 0x1bc0 + 0x1bc0: 0x338d, 0x1bc1: 0x33a1, 0x1bc2: 0x33a6, 0x1bc3: 0x33ab, 0x1bc4: 0x33b0, 0x1bc5: 0x33c4, + 0x1bc6: 0x33c9, 0x1bc7: 0x33ce, 0x1bc8: 0x34b6, 0x1bc9: 0x33e2, 0x1bca: 0x34bb, 0x1bcb: 0x34c0, + 0x1bcc: 0x3400, 0x1bcd: 0x34c5, 0x1bce: 0x3405, 0x1bcf: 0x340a, 0x1bd0: 0x344b, 0x1bd1: 0x34ca, + 0x1bd2: 0x34cf, 0x1bd3: 0x3432, 0x1bd4: 0x34d4, 0x1bd5: 0x3437, 0x1bd6: 0x343c, 0x1bd7: 0x3277, + 0x1bd8: 0x327e, 0x1bd9: 0x34d9, 0x1bda: 0x3285, 0x1bdb: 0x34e0, 0x1bdc: 0x3293, 0x1bdd: 0x3298, + 0x1bde: 0x329d, 0x1bdf: 0x32a2, 0x1be0: 0x34e7, 0x1be1: 0x32b1, 0x1be2: 0x32b6, 0x1be3: 0x32bb, + 0x1be4: 0x32c0, 0x1be5: 0x34ec, 0x1be6: 0x32d4, 0x1be7: 0x32e3, 0x1be8: 0x32e8, 0x1be9: 0x32ed, + 0x1bea: 0x32f2, 0x1beb: 0x32f7, 0x1bec: 0x3301, 0x1bed: 0x3306, 0x1bee: 0x330b, 0x1bef: 0x3310, + 0x1bf0: 0x3315, 0x1bf1: 0x331a, 0x1bf2: 0x34f1, 0x1bf3: 0x331f, 0x1bf4: 0x3324, 0x1bf5: 0x3329, + 0x1bf6: 0x332e, 0x1bf7: 0x3333, 0x1bf8: 0x3338, 0x1bf9: 0x3342, 0x1bfa: 0x3347, 0x1bfb: 0x334c, + 0x1bfc: 0x3351, 0x1bfd: 0x3356, 0x1bfe: 0x335b, 0x1bff: 0x3360, + // Block 0x70, offset 0x1c00 + 0x1c00: 0x3365, 0x1c01: 0x336a, 0x1c02: 0x3379, 0x1c03: 0x337e, 0x1c04: 0x3392, 0x1c05: 0x3397, + 0x1c06: 0x339c, 0x1c07: 0x33a1, 0x1c08: 0x33a6, 0x1c09: 0x33b5, 0x1c0a: 0x33ba, 0x1c0b: 0x33bf, + 0x1c0c: 0x33c4, 0x1c0d: 0x34f6, 0x1c0e: 0x33d3, 0x1c0f: 0x33d8, 0x1c10: 0x33dd, 0x1c11: 0x33e2, + 0x1c12: 0x33f1, 0x1c13: 0x33f6, 0x1c14: 0x33fb, 0x1c15: 0x3400, 0x1c16: 0x34fb, 0x1c17: 0x340f, + 0x1c18: 0x3414, 0x1c19: 0x3500, 0x1c1a: 0x3423, 0x1c1b: 0x3428, 0x1c1c: 0x342d, 0x1c1d: 0x3432, + 0x1c1e: 0x3505, 0x1c1f: 0x3285, 0x1c20: 0x34e0, 0x1c21: 0x32a2, 0x1c22: 0x34e7, 0x1c23: 0x32c0, + 0x1c24: 0x34ec, 0x1c25: 0x32d4, 0x1c26: 0x350a, 0x1c27: 0x3315, 0x1c28: 0x350f, 0x1c29: 0x3514, + 0x1c2a: 0x3519, 0x1c2b: 0x33a1, 0x1c2c: 0x33a6, 0x1c2d: 0x33c4, 0x1c2e: 0x3400, 0x1c2f: 0x34fb, + 0x1c30: 0x3432, 0x1c31: 0x3505, 0x1c32: 0x351e, 0x1c33: 0x3525, 0x1c34: 0x352c, 0x1c35: 0x3533, + 0x1c36: 0x3538, 0x1c37: 0x353d, 0x1c38: 0x3542, 0x1c39: 0x3547, 0x1c3a: 0x354c, 0x1c3b: 0x3551, + 0x1c3c: 0x3556, 0x1c3d: 0x355b, 0x1c3e: 0x3560, 0x1c3f: 0x3565, + // Block 0x71, offset 0x1c40 + 0x1c40: 0x356a, 0x1c41: 0x356f, 0x1c42: 0x3574, 0x1c43: 0x3579, 0x1c44: 0x357e, 0x1c45: 0x3583, + 0x1c46: 0x3588, 0x1c47: 0x358d, 0x1c48: 0x3592, 0x1c49: 0x3597, 0x1c4a: 0x359c, 0x1c4b: 0x35a1, + 0x1c4c: 0x3514, 0x1c4d: 0x35a6, 0x1c4e: 0x35ab, 0x1c4f: 0x35b0, 0x1c50: 0x35b5, 0x1c51: 0x3533, + 0x1c52: 0x3538, 0x1c53: 0x353d, 0x1c54: 0x3542, 0x1c55: 0x3547, 0x1c56: 0x354c, 0x1c57: 0x3551, + 0x1c58: 0x3556, 0x1c59: 0x355b, 0x1c5a: 0x3560, 0x1c5b: 0x3565, 0x1c5c: 0x356a, 0x1c5d: 0x356f, + 0x1c5e: 0x3574, 0x1c5f: 0x3579, 0x1c60: 0x357e, 0x1c61: 0x3583, 0x1c62: 0x3588, 0x1c63: 0x358d, + 0x1c64: 0x3592, 0x1c65: 0x3597, 0x1c66: 0x359c, 0x1c67: 0x35a1, 0x1c68: 0x3514, 0x1c69: 0x35a6, + 0x1c6a: 0x35ab, 0x1c6b: 0x35b0, 0x1c6c: 0x35b5, 0x1c6d: 0x3597, 0x1c6e: 0x359c, 0x1c6f: 0x35a1, + 0x1c70: 0x3514, 0x1c71: 0x350f, 0x1c72: 0x3519, 0x1c73: 0x333d, 0x1c74: 0x3306, 0x1c75: 0x330b, + 0x1c76: 0x3310, 0x1c77: 0x3597, 0x1c78: 0x359c, 0x1c79: 0x35a1, 0x1c7a: 0x333d, 0x1c7b: 0x3342, + 0x1c7c: 0x35ba, 0x1c7d: 0x35ba, + // Block 0x72, offset 0x1c80 + 0x1c90: 0x35bf, 0x1c91: 0x35c6, + 0x1c92: 0x35c6, 0x1c93: 0x35cd, 0x1c94: 0x35d4, 0x1c95: 0x35db, 0x1c96: 0x35e2, 0x1c97: 0x35e9, + 0x1c98: 0x35f0, 0x1c99: 0x35f0, 0x1c9a: 0x35f7, 0x1c9b: 0x35fe, 0x1c9c: 0x3605, 0x1c9d: 0x360c, + 0x1c9e: 0x3613, 0x1c9f: 0x361a, 0x1ca0: 0x361a, 0x1ca1: 0x3621, 0x1ca2: 0x3628, 0x1ca3: 0x3628, + 0x1ca4: 0x362f, 0x1ca5: 0x362f, 0x1ca6: 0x3636, 0x1ca7: 0x363d, 0x1ca8: 0x363d, 0x1ca9: 0x3644, + 0x1caa: 0x364b, 0x1cab: 0x364b, 0x1cac: 0x3652, 0x1cad: 0x3652, 0x1cae: 0x3659, 0x1caf: 0x3660, + 0x1cb0: 0x3660, 0x1cb1: 0x3667, 0x1cb2: 0x3667, 0x1cb3: 0x366e, 0x1cb4: 0x3675, 0x1cb5: 0x367c, + 0x1cb6: 0x3683, 0x1cb7: 0x3683, 0x1cb8: 0x368a, 0x1cb9: 0x3691, 0x1cba: 0x3698, 0x1cbb: 0x369f, + 0x1cbc: 0x36a6, 0x1cbd: 0x36a6, 0x1cbe: 0x36ad, 0x1cbf: 0x36b4, + // Block 0x73, offset 0x1cc0 + 0x1cc0: 0x36bb, 0x1cc1: 0x36c2, 0x1cc2: 0x36c9, 0x1cc3: 0x36d0, 0x1cc4: 0x36d0, 0x1cc5: 0x36d7, + 0x1cc6: 0x36d7, 0x1cc7: 0x36de, 0x1cc8: 0x36de, 0x1cc9: 0x36e5, 0x1cca: 0x36ec, 0x1ccb: 0x36f3, + 0x1ccc: 0x36fa, 0x1ccd: 0x3701, 0x1cce: 0x3708, 0x1ccf: 0x370f, + 0x1cd2: 0x3716, 0x1cd3: 0x371d, 0x1cd4: 0x3724, 0x1cd5: 0x372b, 0x1cd6: 0x3732, 0x1cd7: 0x3739, + 0x1cd8: 0x3739, 0x1cd9: 0x3740, 0x1cda: 0x3747, 0x1cdb: 0x374e, 0x1cdc: 0x3755, 0x1cdd: 0x3755, + 0x1cde: 0x375c, 0x1cdf: 0x3763, 0x1ce0: 0x376a, 0x1ce1: 0x3771, 0x1ce2: 0x3778, 0x1ce3: 0x377f, + 0x1ce4: 0x3786, 0x1ce5: 0x378d, 0x1ce6: 0x3794, 0x1ce7: 0x379b, 0x1ce8: 0x37a2, 0x1ce9: 0x37a9, + 0x1cea: 0x37b0, 0x1ceb: 0x37b7, 0x1cec: 0x37be, 0x1ced: 0x37c5, 0x1cee: 0x37cc, 0x1cef: 0x37d3, + 0x1cf0: 0x37da, 0x1cf1: 0x37e1, 0x1cf2: 0x37e8, 0x1cf3: 0x37ef, 0x1cf4: 0x36ad, 0x1cf5: 0x36bb, + 0x1cf6: 0x37f6, 0x1cf7: 0x37fd, 0x1cf8: 0x3804, 0x1cf9: 0x380b, 0x1cfa: 0x3812, 0x1cfb: 0x3819, + 0x1cfc: 0x3812, 0x1cfd: 0x3804, 0x1cfe: 0x3820, 0x1cff: 0x3827, + // Block 0x74, offset 0x1d00 + 0x1d00: 0x382e, 0x1d01: 0x3835, 0x1d02: 0x383c, 0x1d03: 0x3819, 0x1d04: 0x367c, 0x1d05: 0x3636, + 0x1d06: 0x3843, 0x1d07: 0x384a, + 0x1d30: 0x3851, 0x1d31: 0x3858, 0x1d32: 0x385f, 0x1d33: 0x3868, 0x1d34: 0x3871, 0x1d35: 0x387a, + 0x1d36: 0x3883, 0x1d37: 0x388c, 0x1d38: 0x3895, 0x1d39: 0x389e, 0x1d3a: 0x38a5, 0x1d3b: 0x38c7, + 0x1d3c: 0x38d7, + // Block 0x75, offset 0x1d40 + 0x1d50: 0x38e0, 0x1d51: 0x38e2, + 0x1d52: 0x38e6, 0x1d53: 0x38ea, 0x1d54: 0x04e1, 0x1d55: 0x38ec, 0x1d56: 0x38ee, 0x1d57: 0x38f0, + 0x1d58: 0x38f4, 0x1d59: 0x1443, + 0x1d70: 0x1440, 0x1d71: 0x38f8, 0x1d72: 0x38fc, 0x1d73: 0x3900, 0x1d74: 0x3900, 0x1d75: 0x149c, + 0x1d76: 0x149e, 0x1d77: 0x3902, 0x1d78: 0x3904, 0x1d79: 0x3906, 0x1d7a: 0x390a, 0x1d7b: 0x390e, + 0x1d7c: 0x3912, 0x1d7d: 0x3916, 0x1d7e: 0x391a, 0x1d7f: 0x16c3, + // Block 0x76, offset 0x1d80 + 0x1d80: 0x16c7, 0x1d81: 0x391e, 0x1d82: 0x3922, 0x1d83: 0x3926, 0x1d84: 0x392a, + 0x1d87: 0x392e, 0x1d88: 0x3930, 0x1d89: 0x146c, 0x1d8a: 0x146c, 0x1d8b: 0x146c, + 0x1d8c: 0x146c, 0x1d8d: 0x3900, 0x1d8e: 0x3900, 0x1d8f: 0x3900, 0x1d90: 0x38e0, 0x1d91: 0x38e2, + 0x1d92: 0x143e, 0x1d94: 0x04e1, 0x1d95: 0x38ea, 0x1d96: 0x38ee, 0x1d97: 0x38ec, + 0x1d98: 0x38f8, 0x1d99: 0x149c, 0x1d9a: 0x149e, 0x1d9b: 0x3902, 0x1d9c: 0x3904, 0x1d9d: 0x3906, + 0x1d9e: 0x390a, 0x1d9f: 0x3932, 0x1da0: 0x3934, 0x1da1: 0x3936, 0x1da2: 0x1494, 0x1da3: 0x3938, + 0x1da4: 0x393a, 0x1da5: 0x393c, 0x1da6: 0x149a, 0x1da8: 0x393e, 0x1da9: 0x3940, + 0x1daa: 0x3942, 0x1dab: 0x3944, + 0x1db0: 0x3946, 0x1db1: 0x394a, 0x1db2: 0x394f, 0x1db4: 0x3953, + 0x1db6: 0x3957, 0x1db7: 0x395b, 0x1db8: 0x3960, 0x1db9: 0x3964, 0x1dba: 0x3969, 0x1dbb: 0x396d, + 0x1dbc: 0x3972, 0x1dbd: 0x3976, 0x1dbe: 0x397b, 0x1dbf: 0x397f, + // Block 0x77, offset 0x1dc0 + 0x1dc0: 0x3984, 0x1dc1: 0x068d, 0x1dc2: 0x068d, 0x1dc3: 0x0692, 0x1dc4: 0x0692, 0x1dc5: 0x0697, + 0x1dc6: 0x0697, 0x1dc7: 0x069c, 0x1dc8: 0x069c, 0x1dc9: 0x06a1, 0x1dca: 0x06a1, 0x1dcb: 0x06a1, + 0x1dcc: 0x06a1, 0x1dcd: 0x3987, 0x1dce: 0x3987, 0x1dcf: 0x398a, 0x1dd0: 0x398a, 0x1dd1: 0x398a, + 0x1dd2: 0x398a, 0x1dd3: 0x398d, 0x1dd4: 0x398d, 0x1dd5: 0x3990, 0x1dd6: 0x3990, 0x1dd7: 0x3990, + 0x1dd8: 0x3990, 0x1dd9: 0x3993, 0x1dda: 0x3993, 0x1ddb: 0x3993, 0x1ddc: 0x3993, 0x1ddd: 0x3996, + 0x1dde: 0x3996, 0x1ddf: 0x3996, 0x1de0: 0x3996, 0x1de1: 0x3999, 0x1de2: 0x3999, 0x1de3: 0x3999, + 0x1de4: 0x3999, 0x1de5: 0x399c, 0x1de6: 0x399c, 0x1de7: 0x399c, 0x1de8: 0x399c, 0x1de9: 0x399f, + 0x1dea: 0x399f, 0x1deb: 0x39a2, 0x1dec: 0x39a2, 0x1ded: 0x39a5, 0x1dee: 0x39a5, 0x1def: 0x39a8, + 0x1df0: 0x39a8, 0x1df1: 0x39ab, 0x1df2: 0x39ab, 0x1df3: 0x39ab, 0x1df4: 0x39ab, 0x1df5: 0x39ae, + 0x1df6: 0x39ae, 0x1df7: 0x39ae, 0x1df8: 0x39ae, 0x1df9: 0x39b1, 0x1dfa: 0x39b1, 0x1dfb: 0x39b1, + 0x1dfc: 0x39b1, 0x1dfd: 0x39b4, 0x1dfe: 0x39b4, 0x1dff: 0x39b4, + // Block 0x78, offset 0x1e00 + 0x1e00: 0x39b4, 0x1e01: 0x39b7, 0x1e02: 0x39b7, 0x1e03: 0x39b7, 0x1e04: 0x39b7, 0x1e05: 0x39ba, + 0x1e06: 0x39ba, 0x1e07: 0x39ba, 0x1e08: 0x39ba, 0x1e09: 0x39bd, 0x1e0a: 0x39bd, 0x1e0b: 0x39bd, + 0x1e0c: 0x39bd, 0x1e0d: 0x39c0, 0x1e0e: 0x39c0, 0x1e0f: 0x39c0, 0x1e10: 0x39c0, 0x1e11: 0x39c3, + 0x1e12: 0x39c3, 0x1e13: 0x39c3, 0x1e14: 0x39c3, 0x1e15: 0x39c6, 0x1e16: 0x39c6, 0x1e17: 0x39c6, + 0x1e18: 0x39c6, 0x1e19: 0x39c9, 0x1e1a: 0x39c9, 0x1e1b: 0x39c9, 0x1e1c: 0x39c9, 0x1e1d: 0x39cc, + 0x1e1e: 0x39cc, 0x1e1f: 0x39cc, 0x1e20: 0x39cc, 0x1e21: 0x39cf, 0x1e22: 0x39cf, 0x1e23: 0x39cf, + 0x1e24: 0x39cf, 0x1e25: 0x39d2, 0x1e26: 0x39d2, 0x1e27: 0x39d2, 0x1e28: 0x39d2, 0x1e29: 0x39d5, + 0x1e2a: 0x39d5, 0x1e2b: 0x39d5, 0x1e2c: 0x39d5, 0x1e2d: 0x39d8, 0x1e2e: 0x39d8, 0x1e2f: 0x3239, + 0x1e30: 0x3239, 0x1e31: 0x39db, 0x1e32: 0x39db, 0x1e33: 0x39db, 0x1e34: 0x39db, 0x1e35: 0x39de, + 0x1e36: 0x39de, 0x1e37: 0x39e5, 0x1e38: 0x39e5, 0x1e39: 0x39ec, 0x1e3a: 0x39ec, 0x1e3b: 0x39f3, + 0x1e3c: 0x39f3, + // Block 0x79, offset 0x1e40 + 0x1e41: 0x38ec, 0x1e42: 0x39f8, 0x1e43: 0x3932, 0x1e44: 0x3940, 0x1e45: 0x3942, + 0x1e46: 0x3934, 0x1e47: 0x39fa, 0x1e48: 0x149c, 0x1e49: 0x149e, 0x1e4a: 0x3936, 0x1e4b: 0x1494, + 0x1e4c: 0x38e0, 0x1e4d: 0x3938, 0x1e4e: 0x143e, 0x1e4f: 0x39fc, 0x1e50: 0x1486, 0x1e51: 0x001c, + 0x1e52: 0x000d, 0x1e53: 0x000f, 0x1e54: 0x1488, 0x1e55: 0x148a, 0x1e56: 0x148c, 0x1e57: 0x148e, + 0x1e58: 0x1490, 0x1e59: 0x1492, 0x1e5a: 0x38ea, 0x1e5b: 0x04e1, 0x1e5c: 0x393a, 0x1e5d: 0x149a, + 0x1e5e: 0x393c, 0x1e5f: 0x38ee, 0x1e60: 0x3944, 0x1e61: 0x0906, 0x1e62: 0x090b, 0x1e63: 0x14ad, + 0x1e64: 0x090d, 0x1e65: 0x090f, 0x1e66: 0x14d9, 0x1e67: 0x0914, 0x1e68: 0x0916, 0x1e69: 0x0918, + 0x1e6a: 0x091a, 0x1e6b: 0x091c, 0x1e6c: 0x091e, 0x1e6d: 0x0920, 0x1e6e: 0x0922, 0x1e6f: 0x0924, + 0x1e70: 0x0929, 0x1e71: 0x14c8, 0x1e72: 0x092b, 0x1e73: 0x17f6, 0x1e74: 0x092d, 0x1e75: 0x092f, + 0x1e76: 0x155f, 0x1e77: 0x0931, 0x1e78: 0x1570, 0x1e79: 0x17f8, 0x1e7a: 0x14d4, 0x1e7b: 0x392e, + 0x1e7c: 0x393e, 0x1e7d: 0x3930, 0x1e7e: 0x39fe, 0x1e7f: 0x3900, + // Block 0x7a, offset 0x1e80 + 0x1e80: 0x13f7, 0x1e81: 0x0007, 0x1e82: 0x093d, 0x1e83: 0x0984, 0x1e84: 0x093f, 0x1e85: 0x0941, + 0x1e86: 0x098c, 0x1e87: 0x094c, 0x1e88: 0x0494, 0x1e89: 0x097c, 0x1e8a: 0x0499, 0x1e8b: 0x094e, + 0x1e8c: 0x04c5, 0x1e8d: 0x0950, 0x1e8e: 0x14a0, 0x1e8f: 0x001e, 0x1e90: 0x0960, 0x1e91: 0x17fa, + 0x1e92: 0x049b, 0x1e93: 0x02c8, 0x1e94: 0x0962, 0x1e95: 0x0964, 0x1e96: 0x096d, 0x1e97: 0x04a6, + 0x1e98: 0x04c7, 0x1e99: 0x04a8, 0x1e9a: 0x09df, 0x1e9b: 0x3902, 0x1e9c: 0x3a00, 0x1e9d: 0x3904, + 0x1e9e: 0x3a02, 0x1e9f: 0x3a04, 0x1ea0: 0x3a08, 0x1ea1: 0x38e6, 0x1ea2: 0x391e, 0x1ea3: 0x3922, + 0x1ea4: 0x38e2, 0x1ea5: 0x3a0c, 0x1ea6: 0x2321, 0x1ea7: 0x3a10, 0x1ea8: 0x3a14, 0x1ea9: 0x3a18, + 0x1eaa: 0x3a1c, 0x1eab: 0x3a20, 0x1eac: 0x3a24, 0x1ead: 0x3a28, 0x1eae: 0x3a2c, 0x1eaf: 0x3a30, + 0x1eb0: 0x3a34, 0x1eb1: 0x2269, 0x1eb2: 0x226d, 0x1eb3: 0x2271, 0x1eb4: 0x2275, 0x1eb5: 0x2279, + 0x1eb6: 0x227d, 0x1eb7: 0x2281, 0x1eb8: 0x2285, 0x1eb9: 0x2289, 0x1eba: 0x228d, 0x1ebb: 0x2291, + 0x1ebc: 0x2295, 0x1ebd: 0x2299, 0x1ebe: 0x229d, 0x1ebf: 0x22a1, + // Block 0x7b, offset 0x1ec0 + 0x1ec0: 0x22a5, 0x1ec1: 0x22a9, 0x1ec2: 0x22ad, 0x1ec3: 0x22b1, 0x1ec4: 0x22b5, 0x1ec5: 0x22b9, + 0x1ec6: 0x22bd, 0x1ec7: 0x22c1, 0x1ec8: 0x22c5, 0x1ec9: 0x22c9, 0x1eca: 0x22cd, 0x1ecb: 0x22d1, + 0x1ecc: 0x22d5, 0x1ecd: 0x22d9, 0x1ece: 0x22dd, 0x1ecf: 0x22e1, 0x1ed0: 0x22e5, 0x1ed1: 0x22e9, + 0x1ed2: 0x22ed, 0x1ed3: 0x22f1, 0x1ed4: 0x22f5, 0x1ed5: 0x22f9, 0x1ed6: 0x22fd, 0x1ed7: 0x2301, + 0x1ed8: 0x2305, 0x1ed9: 0x2309, 0x1eda: 0x230d, 0x1edb: 0x2311, 0x1edc: 0x2315, 0x1edd: 0x3a38, + 0x1ede: 0x3a3c, 0x1edf: 0x3a40, 0x1ee0: 0x1e04, 0x1ee1: 0x1d38, 0x1ee2: 0x1d3c, 0x1ee3: 0x1d40, + 0x1ee4: 0x1d44, 0x1ee5: 0x1d48, 0x1ee6: 0x1d4c, 0x1ee7: 0x1d50, 0x1ee8: 0x1d54, 0x1ee9: 0x1d58, + 0x1eea: 0x1d5c, 0x1eeb: 0x1d60, 0x1eec: 0x1d64, 0x1eed: 0x1d68, 0x1eee: 0x1d6c, 0x1eef: 0x1d70, + 0x1ef0: 0x1d74, 0x1ef1: 0x1d78, 0x1ef2: 0x1d7c, 0x1ef3: 0x1d80, 0x1ef4: 0x1d84, 0x1ef5: 0x1d88, + 0x1ef6: 0x1d8c, 0x1ef7: 0x1d90, 0x1ef8: 0x1d94, 0x1ef9: 0x1d98, 0x1efa: 0x1d9c, 0x1efb: 0x1da0, + 0x1efc: 0x1da4, 0x1efd: 0x1da8, 0x1efe: 0x1dac, + // Block 0x7c, offset 0x1f00 + 0x1f02: 0x1db0, 0x1f03: 0x1db4, 0x1f04: 0x1db8, 0x1f05: 0x1dbc, + 0x1f06: 0x1dc0, 0x1f07: 0x1dc4, 0x1f0a: 0x1dc8, 0x1f0b: 0x1dcc, + 0x1f0c: 0x1dd0, 0x1f0d: 0x1dd4, 0x1f0e: 0x1dd8, 0x1f0f: 0x1ddc, + 0x1f12: 0x1de0, 0x1f13: 0x1de4, 0x1f14: 0x1de8, 0x1f15: 0x1dec, 0x1f16: 0x1df0, 0x1f17: 0x1df4, + 0x1f1a: 0x1df8, 0x1f1b: 0x1dfc, 0x1f1c: 0x1e00, + 0x1f20: 0x3a44, 0x1f21: 0x3a47, 0x1f22: 0x3a4a, 0x1f23: 0x0009, + 0x1f24: 0x3a4d, 0x1f25: 0x3a50, 0x1f26: 0x3a53, 0x1f28: 0x3a57, 0x1f29: 0x3a5b, + 0x1f2a: 0x3a5f, 0x1f2b: 0x3a63, 0x1f2c: 0x3a67, 0x1f2d: 0x3a6b, 0x1f2e: 0x3a6f, + // Block 0x7d, offset 0x1f40 + 0x1f5a: 0x3a73, 0x1f5c: 0x3a7c, + 0x1f6b: 0x3a85, + // Block 0x7e, offset 0x1f80 + 0x1f9e: 0x3a8e, 0x1f9f: 0x3a97, 0x1fa0: 0x3aa0, 0x1fa1: 0x3aad, 0x1fa2: 0x3aba, 0x1fa3: 0x3ac7, + 0x1fa4: 0x3ad4, + // Block 0x7f, offset 0x1fc0 + 0x1ffb: 0x3ae1, + 0x1ffc: 0x3aea, 0x1ffd: 0x3af3, 0x1ffe: 0x3b00, 0x1fff: 0x3b0d, + // Block 0x80, offset 0x2000 + 0x2000: 0x3b1a, + // Block 0x81, offset 0x2040 + 0x2040: 0x0906, 0x2041: 0x090b, 0x2042: 0x14ad, 0x2043: 0x090d, 0x2044: 0x090f, 0x2045: 0x14d9, + 0x2046: 0x0914, 0x2047: 0x0916, 0x2048: 0x0918, 0x2049: 0x091a, 0x204a: 0x091c, 0x204b: 0x091e, + 0x204c: 0x0920, 0x204d: 0x0922, 0x204e: 0x0924, 0x204f: 0x0929, 0x2050: 0x14c8, 0x2051: 0x092b, + 0x2052: 0x17f6, 0x2053: 0x092d, 0x2054: 0x092f, 0x2055: 0x155f, 0x2056: 0x0931, 0x2057: 0x1570, + 0x2058: 0x17f8, 0x2059: 0x14d4, 0x205a: 0x0007, 0x205b: 0x093d, 0x205c: 0x0984, 0x205d: 0x093f, + 0x205e: 0x0941, 0x205f: 0x098c, 0x2060: 0x094c, 0x2061: 0x0494, 0x2062: 0x097c, 0x2063: 0x0499, + 0x2064: 0x094e, 0x2065: 0x04c5, 0x2066: 0x0950, 0x2067: 0x14a0, 0x2068: 0x001e, 0x2069: 0x0960, + 0x206a: 0x17fa, 0x206b: 0x049b, 0x206c: 0x02c8, 0x206d: 0x0962, 0x206e: 0x0964, 0x206f: 0x096d, + 0x2070: 0x04a6, 0x2071: 0x04c7, 0x2072: 0x04a8, 0x2073: 0x09df, 0x2074: 0x0906, 0x2075: 0x090b, + 0x2076: 0x14ad, 0x2077: 0x090d, 0x2078: 0x090f, 0x2079: 0x14d9, 0x207a: 0x0914, 0x207b: 0x0916, + 0x207c: 0x0918, 0x207d: 0x091a, 0x207e: 0x091c, 0x207f: 0x091e, + // Block 0x82, offset 0x2080 + 0x2080: 0x0920, 0x2081: 0x0922, 0x2082: 0x0924, 0x2083: 0x0929, 0x2084: 0x14c8, 0x2085: 0x092b, + 0x2086: 0x17f6, 0x2087: 0x092d, 0x2088: 0x092f, 0x2089: 0x155f, 0x208a: 0x0931, 0x208b: 0x1570, + 0x208c: 0x17f8, 0x208d: 0x14d4, 0x208e: 0x0007, 0x208f: 0x093d, 0x2090: 0x0984, 0x2091: 0x093f, + 0x2092: 0x0941, 0x2093: 0x098c, 0x2094: 0x094c, 0x2096: 0x097c, 0x2097: 0x0499, + 0x2098: 0x094e, 0x2099: 0x04c5, 0x209a: 0x0950, 0x209b: 0x14a0, 0x209c: 0x001e, 0x209d: 0x0960, + 0x209e: 0x17fa, 0x209f: 0x049b, 0x20a0: 0x02c8, 0x20a1: 0x0962, 0x20a2: 0x0964, 0x20a3: 0x096d, + 0x20a4: 0x04a6, 0x20a5: 0x04c7, 0x20a6: 0x04a8, 0x20a7: 0x09df, 0x20a8: 0x0906, 0x20a9: 0x090b, + 0x20aa: 0x14ad, 0x20ab: 0x090d, 0x20ac: 0x090f, 0x20ad: 0x14d9, 0x20ae: 0x0914, 0x20af: 0x0916, + 0x20b0: 0x0918, 0x20b1: 0x091a, 0x20b2: 0x091c, 0x20b3: 0x091e, 0x20b4: 0x0920, 0x20b5: 0x0922, + 0x20b6: 0x0924, 0x20b7: 0x0929, 0x20b8: 0x14c8, 0x20b9: 0x092b, 0x20ba: 0x17f6, 0x20bb: 0x092d, + 0x20bc: 0x092f, 0x20bd: 0x155f, 0x20be: 0x0931, 0x20bf: 0x1570, + // Block 0x83, offset 0x20c0 + 0x20c0: 0x17f8, 0x20c1: 0x14d4, 0x20c2: 0x0007, 0x20c3: 0x093d, 0x20c4: 0x0984, 0x20c5: 0x093f, + 0x20c6: 0x0941, 0x20c7: 0x098c, 0x20c8: 0x094c, 0x20c9: 0x0494, 0x20ca: 0x097c, 0x20cb: 0x0499, + 0x20cc: 0x094e, 0x20cd: 0x04c5, 0x20ce: 0x0950, 0x20cf: 0x14a0, 0x20d0: 0x001e, 0x20d1: 0x0960, + 0x20d2: 0x17fa, 0x20d3: 0x049b, 0x20d4: 0x02c8, 0x20d5: 0x0962, 0x20d6: 0x0964, 0x20d7: 0x096d, + 0x20d8: 0x04a6, 0x20d9: 0x04c7, 0x20da: 0x04a8, 0x20db: 0x09df, 0x20dc: 0x0906, + 0x20de: 0x14ad, 0x20df: 0x090d, 0x20e2: 0x0914, + 0x20e5: 0x091a, 0x20e6: 0x091c, 0x20e9: 0x0922, + 0x20ea: 0x0924, 0x20eb: 0x0929, 0x20ec: 0x14c8, 0x20ee: 0x17f6, 0x20ef: 0x092d, + 0x20f0: 0x092f, 0x20f1: 0x155f, 0x20f2: 0x0931, 0x20f3: 0x1570, 0x20f4: 0x17f8, 0x20f5: 0x14d4, + 0x20f6: 0x0007, 0x20f7: 0x093d, 0x20f8: 0x0984, 0x20f9: 0x093f, 0x20fb: 0x098c, + 0x20fd: 0x0494, 0x20fe: 0x097c, 0x20ff: 0x0499, + // Block 0x84, offset 0x2100 + 0x2100: 0x094e, 0x2101: 0x04c5, 0x2102: 0x0950, 0x2103: 0x14a0, 0x2105: 0x0960, + 0x2106: 0x17fa, 0x2107: 0x049b, 0x2108: 0x02c8, 0x2109: 0x0962, 0x210a: 0x0964, 0x210b: 0x096d, + 0x210c: 0x04a6, 0x210d: 0x04c7, 0x210e: 0x04a8, 0x210f: 0x09df, 0x2110: 0x0906, 0x2111: 0x090b, + 0x2112: 0x14ad, 0x2113: 0x090d, 0x2114: 0x090f, 0x2115: 0x14d9, 0x2116: 0x0914, 0x2117: 0x0916, + 0x2118: 0x0918, 0x2119: 0x091a, 0x211a: 0x091c, 0x211b: 0x091e, 0x211c: 0x0920, 0x211d: 0x0922, + 0x211e: 0x0924, 0x211f: 0x0929, 0x2120: 0x14c8, 0x2121: 0x092b, 0x2122: 0x17f6, 0x2123: 0x092d, + 0x2124: 0x092f, 0x2125: 0x155f, 0x2126: 0x0931, 0x2127: 0x1570, 0x2128: 0x17f8, 0x2129: 0x14d4, + 0x212a: 0x0007, 0x212b: 0x093d, 0x212c: 0x0984, 0x212d: 0x093f, 0x212e: 0x0941, 0x212f: 0x098c, + 0x2130: 0x094c, 0x2131: 0x0494, 0x2132: 0x097c, 0x2133: 0x0499, 0x2134: 0x094e, 0x2135: 0x04c5, + 0x2136: 0x0950, 0x2137: 0x14a0, 0x2138: 0x001e, 0x2139: 0x0960, 0x213a: 0x17fa, 0x213b: 0x049b, + 0x213c: 0x02c8, 0x213d: 0x0962, 0x213e: 0x0964, 0x213f: 0x096d, + // Block 0x85, offset 0x2140 + 0x2140: 0x04a6, 0x2141: 0x04c7, 0x2142: 0x04a8, 0x2143: 0x09df, 0x2144: 0x0906, 0x2145: 0x090b, + 0x2147: 0x090d, 0x2148: 0x090f, 0x2149: 0x14d9, 0x214a: 0x0914, + 0x214d: 0x091a, 0x214e: 0x091c, 0x214f: 0x091e, 0x2150: 0x0920, 0x2151: 0x0922, + 0x2152: 0x0924, 0x2153: 0x0929, 0x2154: 0x14c8, 0x2156: 0x17f6, 0x2157: 0x092d, + 0x2158: 0x092f, 0x2159: 0x155f, 0x215a: 0x0931, 0x215b: 0x1570, 0x215c: 0x17f8, + 0x215e: 0x0007, 0x215f: 0x093d, 0x2160: 0x0984, 0x2161: 0x093f, 0x2162: 0x0941, 0x2163: 0x098c, + 0x2164: 0x094c, 0x2165: 0x0494, 0x2166: 0x097c, 0x2167: 0x0499, 0x2168: 0x094e, 0x2169: 0x04c5, + 0x216a: 0x0950, 0x216b: 0x14a0, 0x216c: 0x001e, 0x216d: 0x0960, 0x216e: 0x17fa, 0x216f: 0x049b, + 0x2170: 0x02c8, 0x2171: 0x0962, 0x2172: 0x0964, 0x2173: 0x096d, 0x2174: 0x04a6, 0x2175: 0x04c7, + 0x2176: 0x04a8, 0x2177: 0x09df, 0x2178: 0x0906, 0x2179: 0x090b, 0x217b: 0x090d, + 0x217c: 0x090f, 0x217d: 0x14d9, 0x217e: 0x0914, + // Block 0x86, offset 0x2180 + 0x2180: 0x0918, 0x2181: 0x091a, 0x2182: 0x091c, 0x2183: 0x091e, 0x2184: 0x0920, + 0x2186: 0x0924, 0x218a: 0x17f6, 0x218b: 0x092d, + 0x218c: 0x092f, 0x218d: 0x155f, 0x218e: 0x0931, 0x218f: 0x1570, 0x2190: 0x17f8, + 0x2192: 0x0007, 0x2193: 0x093d, 0x2194: 0x0984, 0x2195: 0x093f, 0x2196: 0x0941, 0x2197: 0x098c, + 0x2198: 0x094c, 0x2199: 0x0494, 0x219a: 0x097c, 0x219b: 0x0499, 0x219c: 0x094e, 0x219d: 0x04c5, + 0x219e: 0x0950, 0x219f: 0x14a0, 0x21a0: 0x001e, 0x21a1: 0x0960, 0x21a2: 0x17fa, 0x21a3: 0x049b, + 0x21a4: 0x02c8, 0x21a5: 0x0962, 0x21a6: 0x0964, 0x21a7: 0x096d, 0x21a8: 0x04a6, 0x21a9: 0x04c7, + 0x21aa: 0x04a8, 0x21ab: 0x09df, 0x21ac: 0x0906, 0x21ad: 0x090b, 0x21ae: 0x14ad, 0x21af: 0x090d, + 0x21b0: 0x090f, 0x21b1: 0x14d9, 0x21b2: 0x0914, 0x21b3: 0x0916, 0x21b4: 0x0918, 0x21b5: 0x091a, + 0x21b6: 0x091c, 0x21b7: 0x091e, 0x21b8: 0x0920, 0x21b9: 0x0922, 0x21ba: 0x0924, 0x21bb: 0x0929, + 0x21bc: 0x14c8, 0x21bd: 0x092b, 0x21be: 0x17f6, 0x21bf: 0x092d, + // Block 0x87, offset 0x21c0 + 0x21c0: 0x092f, 0x21c1: 0x155f, 0x21c2: 0x0931, 0x21c3: 0x1570, 0x21c4: 0x17f8, 0x21c5: 0x14d4, + 0x21c6: 0x0007, 0x21c7: 0x093d, 0x21c8: 0x0984, 0x21c9: 0x093f, 0x21ca: 0x0941, 0x21cb: 0x098c, + 0x21cc: 0x094c, 0x21cd: 0x0494, 0x21ce: 0x097c, 0x21cf: 0x0499, 0x21d0: 0x094e, 0x21d1: 0x04c5, + 0x21d2: 0x0950, 0x21d3: 0x14a0, 0x21d4: 0x001e, 0x21d5: 0x0960, 0x21d6: 0x17fa, 0x21d7: 0x049b, + 0x21d8: 0x02c8, 0x21d9: 0x0962, 0x21da: 0x0964, 0x21db: 0x096d, 0x21dc: 0x04a6, 0x21dd: 0x04c7, + 0x21de: 0x04a8, 0x21df: 0x09df, 0x21e0: 0x0906, 0x21e1: 0x090b, 0x21e2: 0x14ad, 0x21e3: 0x090d, + 0x21e4: 0x090f, 0x21e5: 0x14d9, 0x21e6: 0x0914, 0x21e7: 0x0916, 0x21e8: 0x0918, 0x21e9: 0x091a, + 0x21ea: 0x091c, 0x21eb: 0x091e, 0x21ec: 0x0920, 0x21ed: 0x0922, 0x21ee: 0x0924, 0x21ef: 0x0929, + 0x21f0: 0x14c8, 0x21f1: 0x092b, 0x21f2: 0x17f6, 0x21f3: 0x092d, 0x21f4: 0x092f, 0x21f5: 0x155f, + 0x21f6: 0x0931, 0x21f7: 0x1570, 0x21f8: 0x17f8, 0x21f9: 0x14d4, 0x21fa: 0x0007, 0x21fb: 0x093d, + 0x21fc: 0x0984, 0x21fd: 0x093f, 0x21fe: 0x0941, 0x21ff: 0x098c, + // Block 0x88, offset 0x2200 + 0x2200: 0x094c, 0x2201: 0x0494, 0x2202: 0x097c, 0x2203: 0x0499, 0x2204: 0x094e, 0x2205: 0x04c5, + 0x2206: 0x0950, 0x2207: 0x14a0, 0x2208: 0x001e, 0x2209: 0x0960, 0x220a: 0x17fa, 0x220b: 0x049b, + 0x220c: 0x02c8, 0x220d: 0x0962, 0x220e: 0x0964, 0x220f: 0x096d, 0x2210: 0x04a6, 0x2211: 0x04c7, + 0x2212: 0x04a8, 0x2213: 0x09df, 0x2214: 0x0906, 0x2215: 0x090b, 0x2216: 0x14ad, 0x2217: 0x090d, + 0x2218: 0x090f, 0x2219: 0x14d9, 0x221a: 0x0914, 0x221b: 0x0916, 0x221c: 0x0918, 0x221d: 0x091a, + 0x221e: 0x091c, 0x221f: 0x091e, 0x2220: 0x0920, 0x2221: 0x0922, 0x2222: 0x0924, 0x2223: 0x0929, + 0x2224: 0x14c8, 0x2225: 0x092b, 0x2226: 0x17f6, 0x2227: 0x092d, 0x2228: 0x092f, 0x2229: 0x155f, + 0x222a: 0x0931, 0x222b: 0x1570, 0x222c: 0x17f8, 0x222d: 0x14d4, 0x222e: 0x0007, 0x222f: 0x093d, + 0x2230: 0x0984, 0x2231: 0x093f, 0x2232: 0x0941, 0x2233: 0x098c, 0x2234: 0x094c, 0x2235: 0x0494, + 0x2236: 0x097c, 0x2237: 0x0499, 0x2238: 0x094e, 0x2239: 0x04c5, 0x223a: 0x0950, 0x223b: 0x14a0, + 0x223c: 0x001e, 0x223d: 0x0960, 0x223e: 0x17fa, 0x223f: 0x049b, + // Block 0x89, offset 0x2240 + 0x2240: 0x02c8, 0x2241: 0x0962, 0x2242: 0x0964, 0x2243: 0x096d, 0x2244: 0x04a6, 0x2245: 0x04c7, + 0x2246: 0x04a8, 0x2247: 0x09df, 0x2248: 0x0906, 0x2249: 0x090b, 0x224a: 0x14ad, 0x224b: 0x090d, + 0x224c: 0x090f, 0x224d: 0x14d9, 0x224e: 0x0914, 0x224f: 0x0916, 0x2250: 0x0918, 0x2251: 0x091a, + 0x2252: 0x091c, 0x2253: 0x091e, 0x2254: 0x0920, 0x2255: 0x0922, 0x2256: 0x0924, 0x2257: 0x0929, + 0x2258: 0x14c8, 0x2259: 0x092b, 0x225a: 0x17f6, 0x225b: 0x092d, 0x225c: 0x092f, 0x225d: 0x155f, + 0x225e: 0x0931, 0x225f: 0x1570, 0x2260: 0x17f8, 0x2261: 0x14d4, 0x2262: 0x0007, 0x2263: 0x093d, + 0x2264: 0x0984, 0x2265: 0x093f, 0x2266: 0x0941, 0x2267: 0x098c, 0x2268: 0x094c, 0x2269: 0x0494, + 0x226a: 0x097c, 0x226b: 0x0499, 0x226c: 0x094e, 0x226d: 0x04c5, 0x226e: 0x0950, 0x226f: 0x14a0, + 0x2270: 0x001e, 0x2271: 0x0960, 0x2272: 0x17fa, 0x2273: 0x049b, 0x2274: 0x02c8, 0x2275: 0x0962, + 0x2276: 0x0964, 0x2277: 0x096d, 0x2278: 0x04a6, 0x2279: 0x04c7, 0x227a: 0x04a8, 0x227b: 0x09df, + 0x227c: 0x0906, 0x227d: 0x090b, 0x227e: 0x14ad, 0x227f: 0x090d, + // Block 0x8a, offset 0x2280 + 0x2280: 0x090f, 0x2281: 0x14d9, 0x2282: 0x0914, 0x2283: 0x0916, 0x2284: 0x0918, 0x2285: 0x091a, + 0x2286: 0x091c, 0x2287: 0x091e, 0x2288: 0x0920, 0x2289: 0x0922, 0x228a: 0x0924, 0x228b: 0x0929, + 0x228c: 0x14c8, 0x228d: 0x092b, 0x228e: 0x17f6, 0x228f: 0x092d, 0x2290: 0x092f, 0x2291: 0x155f, + 0x2292: 0x0931, 0x2293: 0x1570, 0x2294: 0x17f8, 0x2295: 0x14d4, 0x2296: 0x0007, 0x2297: 0x093d, + 0x2298: 0x0984, 0x2299: 0x093f, 0x229a: 0x0941, 0x229b: 0x098c, 0x229c: 0x094c, 0x229d: 0x0494, + 0x229e: 0x097c, 0x229f: 0x0499, 0x22a0: 0x094e, 0x22a1: 0x04c5, 0x22a2: 0x0950, 0x22a3: 0x14a0, + 0x22a4: 0x001e, 0x22a5: 0x0960, 0x22a6: 0x17fa, 0x22a7: 0x049b, 0x22a8: 0x02c8, 0x22a9: 0x0962, + 0x22aa: 0x0964, 0x22ab: 0x096d, 0x22ac: 0x04a6, 0x22ad: 0x04c7, 0x22ae: 0x04a8, 0x22af: 0x09df, + 0x22b0: 0x0906, 0x22b1: 0x090b, 0x22b2: 0x14ad, 0x22b3: 0x090d, 0x22b4: 0x090f, 0x22b5: 0x14d9, + 0x22b6: 0x0914, 0x22b7: 0x0916, 0x22b8: 0x0918, 0x22b9: 0x091a, 0x22ba: 0x091c, 0x22bb: 0x091e, + 0x22bc: 0x0920, 0x22bd: 0x0922, 0x22be: 0x0924, 0x22bf: 0x0929, + // Block 0x8b, offset 0x22c0 + 0x22c0: 0x14c8, 0x22c1: 0x092b, 0x22c2: 0x17f6, 0x22c3: 0x092d, 0x22c4: 0x092f, 0x22c5: 0x155f, + 0x22c6: 0x0931, 0x22c7: 0x1570, 0x22c8: 0x17f8, 0x22c9: 0x14d4, 0x22ca: 0x0007, 0x22cb: 0x093d, + 0x22cc: 0x0984, 0x22cd: 0x093f, 0x22ce: 0x0941, 0x22cf: 0x098c, 0x22d0: 0x094c, 0x22d1: 0x0494, + 0x22d2: 0x097c, 0x22d3: 0x0499, 0x22d4: 0x094e, 0x22d5: 0x04c5, 0x22d6: 0x0950, 0x22d7: 0x14a0, + 0x22d8: 0x001e, 0x22d9: 0x0960, 0x22da: 0x17fa, 0x22db: 0x049b, 0x22dc: 0x02c8, 0x22dd: 0x0962, + 0x22de: 0x0964, 0x22df: 0x096d, 0x22e0: 0x04a6, 0x22e1: 0x04c7, 0x22e2: 0x04a8, 0x22e3: 0x09df, + 0x22e4: 0x3b27, 0x22e5: 0x3b2a, 0x22e8: 0x3b2d, 0x22e9: 0x3b30, + 0x22ea: 0x14eb, 0x22eb: 0x3b33, 0x22ec: 0x3b36, 0x22ed: 0x3b39, 0x22ee: 0x3b3c, 0x22ef: 0x057b, + 0x22f0: 0x3b3f, 0x22f1: 0x3b42, 0x22f2: 0x3b45, 0x22f3: 0x3b48, 0x22f4: 0x3b4b, 0x22f5: 0x3b4e, + 0x22f6: 0x3b51, 0x22f7: 0x14ee, 0x22f8: 0x3b54, 0x22f9: 0x057b, 0x22fa: 0x0581, 0x22fb: 0x3b57, + 0x22fc: 0x055f, 0x22fd: 0x3b5a, 0x22fe: 0x3b5d, 0x22ff: 0x3b60, + // Block 0x8c, offset 0x2300 + 0x2300: 0x14d6, 0x2301: 0x3b63, 0x2302: 0x3b67, 0x2303: 0x0559, 0x2304: 0x0973, 0x2305: 0x0976, + 0x2306: 0x057e, 0x2307: 0x3b6a, 0x2308: 0x3b6d, 0x2309: 0x055c, 0x230a: 0x12fd, 0x230b: 0x0572, + 0x230c: 0x3b70, 0x230d: 0x0015, 0x230e: 0x3b73, 0x230f: 0x3b76, 0x2310: 0x3b79, 0x2311: 0x056f, + 0x2312: 0x0575, 0x2313: 0x0578, 0x2314: 0x3b7c, 0x2315: 0x3b7f, 0x2316: 0x3b82, 0x2317: 0x056c, + 0x2318: 0x0979, 0x2319: 0x3b85, 0x231a: 0x3b88, 0x231b: 0x3b8b, 0x231c: 0x057e, 0x231d: 0x055c, + 0x231e: 0x0572, 0x231f: 0x056c, 0x2320: 0x0575, 0x2321: 0x056f, 0x2322: 0x3b2d, 0x2323: 0x3b30, + 0x2324: 0x14eb, 0x2325: 0x3b33, 0x2326: 0x3b36, 0x2327: 0x3b39, 0x2328: 0x3b3c, 0x2329: 0x057b, + 0x232a: 0x3b3f, 0x232b: 0x3b42, 0x232c: 0x3b45, 0x232d: 0x3b48, 0x232e: 0x3b4b, 0x232f: 0x3b4e, + 0x2330: 0x3b51, 0x2331: 0x14ee, 0x2332: 0x3b54, 0x2333: 0x057b, 0x2334: 0x0581, 0x2335: 0x3b57, + 0x2336: 0x055f, 0x2337: 0x3b5a, 0x2338: 0x3b5d, 0x2339: 0x3b60, 0x233a: 0x14d6, 0x233b: 0x3b63, + 0x233c: 0x3b67, 0x233d: 0x0559, 0x233e: 0x0973, 0x233f: 0x0976, + // Block 0x8d, offset 0x2340 + 0x2340: 0x057e, 0x2341: 0x3b6a, 0x2342: 0x3b6d, 0x2343: 0x055c, 0x2344: 0x12fd, 0x2345: 0x0572, + 0x2346: 0x3b70, 0x2347: 0x0015, 0x2348: 0x3b73, 0x2349: 0x3b76, 0x234a: 0x3b79, 0x234b: 0x056f, + 0x234c: 0x0575, 0x234d: 0x0578, 0x234e: 0x3b7c, 0x234f: 0x3b7f, 0x2350: 0x3b82, 0x2351: 0x056c, + 0x2352: 0x0979, 0x2353: 0x3b85, 0x2354: 0x3b88, 0x2355: 0x3b8b, 0x2356: 0x057e, 0x2357: 0x055c, + 0x2358: 0x0572, 0x2359: 0x056c, 0x235a: 0x0575, 0x235b: 0x056f, 0x235c: 0x3b2d, 0x235d: 0x3b30, + 0x235e: 0x14eb, 0x235f: 0x3b33, 0x2360: 0x3b36, 0x2361: 0x3b39, 0x2362: 0x3b3c, 0x2363: 0x057b, + 0x2364: 0x3b3f, 0x2365: 0x3b42, 0x2366: 0x3b45, 0x2367: 0x3b48, 0x2368: 0x3b4b, 0x2369: 0x3b4e, + 0x236a: 0x3b51, 0x236b: 0x14ee, 0x236c: 0x3b54, 0x236d: 0x057b, 0x236e: 0x0581, 0x236f: 0x3b57, + 0x2370: 0x055f, 0x2371: 0x3b5a, 0x2372: 0x3b5d, 0x2373: 0x3b60, 0x2374: 0x14d6, 0x2375: 0x3b63, + 0x2376: 0x3b67, 0x2377: 0x0559, 0x2378: 0x0973, 0x2379: 0x0976, 0x237a: 0x057e, 0x237b: 0x3b6a, + 0x237c: 0x3b6d, 0x237d: 0x055c, 0x237e: 0x12fd, 0x237f: 0x0572, + // Block 0x8e, offset 0x2380 + 0x2380: 0x3b70, 0x2381: 0x0015, 0x2382: 0x3b73, 0x2383: 0x3b76, 0x2384: 0x3b79, 0x2385: 0x056f, + 0x2386: 0x0575, 0x2387: 0x0578, 0x2388: 0x3b7c, 0x2389: 0x3b7f, 0x238a: 0x3b82, 0x238b: 0x056c, + 0x238c: 0x0979, 0x238d: 0x3b85, 0x238e: 0x3b88, 0x238f: 0x3b8b, 0x2390: 0x057e, 0x2391: 0x055c, + 0x2392: 0x0572, 0x2393: 0x056c, 0x2394: 0x0575, 0x2395: 0x056f, 0x2396: 0x3b2d, 0x2397: 0x3b30, + 0x2398: 0x14eb, 0x2399: 0x3b33, 0x239a: 0x3b36, 0x239b: 0x3b39, 0x239c: 0x3b3c, 0x239d: 0x057b, + 0x239e: 0x3b3f, 0x239f: 0x3b42, 0x23a0: 0x3b45, 0x23a1: 0x3b48, 0x23a2: 0x3b4b, 0x23a3: 0x3b4e, + 0x23a4: 0x3b51, 0x23a5: 0x14ee, 0x23a6: 0x3b54, 0x23a7: 0x057b, 0x23a8: 0x0581, 0x23a9: 0x3b57, + 0x23aa: 0x055f, 0x23ab: 0x3b5a, 0x23ac: 0x3b5d, 0x23ad: 0x3b60, 0x23ae: 0x14d6, 0x23af: 0x3b63, + 0x23b0: 0x3b67, 0x23b1: 0x0559, 0x23b2: 0x0973, 0x23b3: 0x0976, 0x23b4: 0x057e, 0x23b5: 0x3b6a, + 0x23b6: 0x3b6d, 0x23b7: 0x055c, 0x23b8: 0x12fd, 0x23b9: 0x0572, 0x23ba: 0x3b70, 0x23bb: 0x0015, + 0x23bc: 0x3b73, 0x23bd: 0x3b76, 0x23be: 0x3b79, 0x23bf: 0x056f, + // Block 0x8f, offset 0x23c0 + 0x23c0: 0x0575, 0x23c1: 0x0578, 0x23c2: 0x3b7c, 0x23c3: 0x3b7f, 0x23c4: 0x3b82, 0x23c5: 0x056c, + 0x23c6: 0x0979, 0x23c7: 0x3b85, 0x23c8: 0x3b88, 0x23c9: 0x3b8b, 0x23ca: 0x057e, 0x23cb: 0x055c, + 0x23cc: 0x0572, 0x23cd: 0x056c, 0x23ce: 0x0575, 0x23cf: 0x056f, 0x23d0: 0x3b2d, 0x23d1: 0x3b30, + 0x23d2: 0x14eb, 0x23d3: 0x3b33, 0x23d4: 0x3b36, 0x23d5: 0x3b39, 0x23d6: 0x3b3c, 0x23d7: 0x057b, + 0x23d8: 0x3b3f, 0x23d9: 0x3b42, 0x23da: 0x3b45, 0x23db: 0x3b48, 0x23dc: 0x3b4b, 0x23dd: 0x3b4e, + 0x23de: 0x3b51, 0x23df: 0x14ee, 0x23e0: 0x3b54, 0x23e1: 0x057b, 0x23e2: 0x0581, 0x23e3: 0x3b57, + 0x23e4: 0x055f, 0x23e5: 0x3b5a, 0x23e6: 0x3b5d, 0x23e7: 0x3b60, 0x23e8: 0x14d6, 0x23e9: 0x3b63, + 0x23ea: 0x3b67, 0x23eb: 0x0559, 0x23ec: 0x0973, 0x23ed: 0x0976, 0x23ee: 0x057e, 0x23ef: 0x3b6a, + 0x23f0: 0x3b6d, 0x23f1: 0x055c, 0x23f2: 0x12fd, 0x23f3: 0x0572, 0x23f4: 0x3b70, 0x23f5: 0x0015, + 0x23f6: 0x3b73, 0x23f7: 0x3b76, 0x23f8: 0x3b79, 0x23f9: 0x056f, 0x23fa: 0x0575, 0x23fb: 0x0578, + 0x23fc: 0x3b7c, 0x23fd: 0x3b7f, 0x23fe: 0x3b82, 0x23ff: 0x056c, + // Block 0x90, offset 0x2400 + 0x2400: 0x0979, 0x2401: 0x3b85, 0x2402: 0x3b88, 0x2403: 0x3b8b, 0x2404: 0x057e, 0x2405: 0x055c, + 0x2406: 0x0572, 0x2407: 0x056c, 0x2408: 0x0575, 0x2409: 0x056f, 0x240a: 0x3b8f, 0x240b: 0x3b92, + 0x240e: 0x1486, 0x240f: 0x001c, 0x2410: 0x000d, 0x2411: 0x000f, + 0x2412: 0x1488, 0x2413: 0x148a, 0x2414: 0x148c, 0x2415: 0x148e, 0x2416: 0x1490, 0x2417: 0x1492, + 0x2418: 0x1486, 0x2419: 0x001c, 0x241a: 0x000d, 0x241b: 0x000f, 0x241c: 0x1488, 0x241d: 0x148a, + 0x241e: 0x148c, 0x241f: 0x148e, 0x2420: 0x1490, 0x2421: 0x1492, 0x2422: 0x1486, 0x2423: 0x001c, + 0x2424: 0x000d, 0x2425: 0x000f, 0x2426: 0x1488, 0x2427: 0x148a, 0x2428: 0x148c, 0x2429: 0x148e, + 0x242a: 0x1490, 0x242b: 0x1492, 0x242c: 0x1486, 0x242d: 0x001c, 0x242e: 0x000d, 0x242f: 0x000f, + 0x2430: 0x1488, 0x2431: 0x148a, 0x2432: 0x148c, 0x2433: 0x148e, 0x2434: 0x1490, 0x2435: 0x1492, + 0x2436: 0x1486, 0x2437: 0x001c, 0x2438: 0x000d, 0x2439: 0x000f, 0x243a: 0x1488, 0x243b: 0x148a, + 0x243c: 0x148c, 0x243d: 0x148e, 0x243e: 0x1490, 0x243f: 0x1492, + // Block 0x91, offset 0x2440 + 0x2440: 0x3b95, 0x2441: 0x3b98, 0x2442: 0x3b9b, 0x2443: 0x3b9e, 0x2444: 0x3ba1, 0x2445: 0x3ba4, + 0x2446: 0x3ba7, 0x2447: 0x3baa, 0x2448: 0x3bad, 0x2449: 0x3bb0, 0x244a: 0x3bb3, + 0x2450: 0x3bb6, 0x2451: 0x3bba, + 0x2452: 0x3bbe, 0x2453: 0x3bc2, 0x2454: 0x3bc6, 0x2455: 0x3bca, 0x2456: 0x3bce, 0x2457: 0x3bd2, + 0x2458: 0x3bd6, 0x2459: 0x3bda, 0x245a: 0x3bde, 0x245b: 0x3be2, 0x245c: 0x3be6, 0x245d: 0x3bea, + 0x245e: 0x3bee, 0x245f: 0x3bf2, 0x2460: 0x3bf6, 0x2461: 0x3bfa, 0x2462: 0x3bfe, 0x2463: 0x3c02, + 0x2464: 0x3c06, 0x2465: 0x3c0a, 0x2466: 0x3c0e, 0x2467: 0x3c12, 0x2468: 0x3c16, 0x2469: 0x3c1a, + 0x246a: 0x3c1e, 0x246b: 0x14ad, 0x246c: 0x092b, 0x246d: 0x3c26, 0x246e: 0x3c29, + 0x2470: 0x0906, 0x2471: 0x090b, 0x2472: 0x14ad, 0x2473: 0x090d, 0x2474: 0x090f, 0x2475: 0x14d9, + 0x2476: 0x0914, 0x2477: 0x0916, 0x2478: 0x0918, 0x2479: 0x091a, 0x247a: 0x091c, 0x247b: 0x091e, + 0x247c: 0x0920, 0x247d: 0x0922, 0x247e: 0x0924, 0x247f: 0x0929, + // Block 0x92, offset 0x2480 + 0x2480: 0x14c8, 0x2481: 0x092b, 0x2482: 0x17f6, 0x2483: 0x092d, 0x2484: 0x092f, 0x2485: 0x155f, + 0x2486: 0x0931, 0x2487: 0x1570, 0x2488: 0x17f8, 0x2489: 0x14d4, 0x248a: 0x3c2c, 0x248b: 0x293d, + 0x248c: 0x3c2f, 0x248d: 0x3c32, 0x248e: 0x3c35, 0x248f: 0x3c39, + // Block 0x93, offset 0x24c0 + 0x24d0: 0x3c3c, + // Block 0x94, offset 0x2500 + 0x2500: 0x3c3f, 0x2501: 0x3c46, 0x2502: 0x2291, + 0x2510: 0x1922, 0x2511: 0x3c4d, + 0x2512: 0x3c51, 0x2513: 0x1cb3, 0x2514: 0x183e, 0x2515: 0x3c55, 0x2516: 0x3c59, 0x2517: 0x1ed0, + 0x2518: 0x3c5d, 0x2519: 0x3c61, 0x251a: 0x3c65, 0x251b: 0x2d49, 0x251c: 0x3c69, 0x251d: 0x3c6d, + 0x251e: 0x3c71, 0x251f: 0x3c75, 0x2520: 0x3c79, 0x2521: 0x3c7d, 0x2522: 0x19b2, 0x2523: 0x3c81, + 0x2524: 0x3c85, 0x2525: 0x3c89, 0x2526: 0x3c8d, 0x2527: 0x3c91, 0x2528: 0x3c95, 0x2529: 0x1826, + 0x252a: 0x1eb0, 0x252b: 0x3c99, 0x252c: 0x21c7, 0x252d: 0x1ebc, 0x252e: 0x21cb, 0x252f: 0x3c9d, + 0x2530: 0x1a92, 0x2531: 0x3ca1, 0x2532: 0x3ca5, 0x2533: 0x3ca9, 0x2534: 0x3cad, 0x2535: 0x3cb1, + 0x2536: 0x2183, 0x2537: 0x194a, 0x2538: 0x3cb5, 0x2539: 0x3cb9, 0x253a: 0x3cbd, + // Block 0x95, offset 0x2540 + 0x2540: 0x3cc1, 0x2541: 0x3ccb, 0x2542: 0x3cd5, 0x2543: 0x3cdf, 0x2544: 0x3ce9, 0x2545: 0x3cf3, + 0x2546: 0x3cfd, 0x2547: 0x3d07, 0x2548: 0x3d11, + 0x2550: 0x3d1b, 0x2551: 0x3d1f, + // Block 0x96, offset 0x2580 + 0x2580: 0x3d23, 0x2581: 0x3d27, 0x2582: 0x3d2b, 0x2583: 0x3d2f, 0x2584: 0x3d34, 0x2585: 0x2eb5, + 0x2586: 0x3d38, 0x2587: 0x3d3c, 0x2588: 0x3d40, 0x2589: 0x3d44, 0x258a: 0x2eb9, 0x258b: 0x3d48, + 0x258c: 0x3d4c, 0x258d: 0x3d50, 0x258e: 0x2ebd, 0x258f: 0x3d55, 0x2590: 0x3d59, 0x2591: 0x3d5d, + 0x2592: 0x3d61, 0x2593: 0x3d66, 0x2594: 0x3d6a, 0x2595: 0x3c71, 0x2596: 0x3d6e, 0x2597: 0x3d73, + 0x2598: 0x3d77, 0x2599: 0x3d7b, 0x259a: 0x3d7f, 0x259b: 0x2f9a, 0x259c: 0x3d83, 0x259d: 0x1866, + 0x259e: 0x3d88, 0x259f: 0x3d8c, 0x25a0: 0x3d90, 0x25a1: 0x3d94, 0x25a2: 0x3cb9, 0x25a3: 0x3d98, + 0x25a4: 0x3d9c, 0x25a5: 0x2fae, 0x25a6: 0x2ec1, 0x25a7: 0x2ec5, 0x25a8: 0x2fb2, 0x25a9: 0x3da0, + 0x25aa: 0x3da4, 0x25ab: 0x2bf1, 0x25ac: 0x3da8, 0x25ad: 0x2ec9, 0x25ae: 0x3dac, 0x25af: 0x3db0, + 0x25b0: 0x3db4, 0x25b1: 0x3db8, 0x25b2: 0x3db8, 0x25b3: 0x3db8, 0x25b4: 0x3dbc, 0x25b5: 0x3dc1, + 0x25b6: 0x3dc5, 0x25b7: 0x3dc9, 0x25b8: 0x3dcd, 0x25b9: 0x3dd2, 0x25ba: 0x3dd6, 0x25bb: 0x3dda, + 0x25bc: 0x3dde, 0x25bd: 0x3de2, 0x25be: 0x3de6, 0x25bf: 0x3dea, + // Block 0x97, offset 0x25c0 + 0x25c0: 0x3dee, 0x25c1: 0x3df2, 0x25c2: 0x3df6, 0x25c3: 0x3dfa, 0x25c4: 0x3dfe, 0x25c5: 0x3e02, + 0x25c6: 0x3e02, 0x25c7: 0x2fba, 0x25c8: 0x3e06, 0x25c9: 0x3e0a, 0x25ca: 0x3e0e, 0x25cb: 0x3e12, + 0x25cc: 0x2ed1, 0x25cd: 0x3e16, 0x25ce: 0x3e1a, 0x25cf: 0x3e1e, 0x25d0: 0x2e39, 0x25d1: 0x3e22, + 0x25d2: 0x3e26, 0x25d3: 0x3e2a, 0x25d4: 0x3e2e, 0x25d5: 0x3e32, 0x25d6: 0x3e36, 0x25d7: 0x3e3a, + 0x25d8: 0x3e3e, 0x25d9: 0x3e42, 0x25da: 0x3e47, 0x25db: 0x3e4b, 0x25dc: 0x3e4f, 0x25dd: 0x3c55, + 0x25de: 0x3e53, 0x25df: 0x3e57, 0x25e0: 0x3e5b, 0x25e1: 0x3e60, 0x25e2: 0x3e65, 0x25e3: 0x3e69, + 0x25e4: 0x3e6d, 0x25e5: 0x3e71, 0x25e6: 0x3e75, 0x25e7: 0x3e79, 0x25e8: 0x3e7d, 0x25e9: 0x3e81, + 0x25ea: 0x3e85, 0x25eb: 0x3e85, 0x25ec: 0x3e89, 0x25ed: 0x3e8e, 0x25ee: 0x3e92, 0x25ef: 0x2be1, + 0x25f0: 0x3e96, 0x25f1: 0x3e9a, 0x25f2: 0x3e9f, 0x25f3: 0x3ea3, 0x25f4: 0x3ea7, 0x25f5: 0x18ce, + 0x25f6: 0x3eab, 0x25f7: 0x3eaf, 0x25f8: 0x18d6, 0x25f9: 0x3eb3, 0x25fa: 0x3eb7, 0x25fb: 0x3ebb, + 0x25fc: 0x3ec0, 0x25fd: 0x3ec4, 0x25fe: 0x3ec9, 0x25ff: 0x3ecd, + // Block 0x98, offset 0x2600 + 0x2600: 0x3ed1, 0x2601: 0x3ed5, 0x2602: 0x3ed9, 0x2603: 0x3edd, 0x2604: 0x3ee1, 0x2605: 0x3ee5, + 0x2606: 0x3ee9, 0x2607: 0x3eed, 0x2608: 0x3ef1, 0x2609: 0x3ef5, 0x260a: 0x3efa, 0x260b: 0x3efe, + 0x260c: 0x3f02, 0x260d: 0x3f06, 0x260e: 0x2b11, 0x260f: 0x3f0a, 0x2610: 0x18fe, 0x2611: 0x3f0f, + 0x2612: 0x3f0f, 0x2613: 0x3f14, 0x2614: 0x3f18, 0x2615: 0x3f18, 0x2616: 0x3f1c, 0x2617: 0x3f20, + 0x2618: 0x3f25, 0x2619: 0x3f2a, 0x261a: 0x3f2e, 0x261b: 0x3f32, 0x261c: 0x3f36, 0x261d: 0x3f3a, + 0x261e: 0x3f3e, 0x261f: 0x3f42, 0x2620: 0x3f46, 0x2621: 0x3f4a, 0x2622: 0x3f4e, 0x2623: 0x2ee5, + 0x2624: 0x3f52, 0x2625: 0x3f57, 0x2626: 0x3f5b, 0x2627: 0x3f5f, 0x2628: 0x2fea, 0x2629: 0x3f5f, + 0x262a: 0x3f63, 0x262b: 0x2eed, 0x262c: 0x3f67, 0x262d: 0x3f6b, 0x262e: 0x3f6f, 0x262f: 0x3f73, + 0x2630: 0x2ef1, 0x2631: 0x2aa5, 0x2632: 0x3f77, 0x2633: 0x3f7b, 0x2634: 0x3f7f, 0x2635: 0x3f83, + 0x2636: 0x3f87, 0x2637: 0x3f8b, 0x2638: 0x3f8f, 0x2639: 0x3f94, 0x263a: 0x3f98, 0x263b: 0x3f9c, + 0x263c: 0x3fa0, 0x263d: 0x3fa4, 0x263e: 0x3fa8, 0x263f: 0x3fad, + // Block 0x99, offset 0x2640 + 0x2640: 0x3fb1, 0x2641: 0x3fb5, 0x2642: 0x3fb9, 0x2643: 0x3fbd, 0x2644: 0x3fc1, 0x2645: 0x3fc5, + 0x2646: 0x3fc9, 0x2647: 0x3fcd, 0x2648: 0x2ef5, 0x2649: 0x3fd1, 0x264a: 0x3fd5, 0x264b: 0x3fda, + 0x264c: 0x3fde, 0x264d: 0x3fe2, 0x264e: 0x3fe6, 0x264f: 0x2efd, 0x2650: 0x3fea, 0x2651: 0x3fee, + 0x2652: 0x3ff2, 0x2653: 0x3ff6, 0x2654: 0x3ffa, 0x2655: 0x3ffe, 0x2656: 0x4002, 0x2657: 0x4006, + 0x2658: 0x2b15, 0x2659: 0x300a, 0x265a: 0x400a, 0x265b: 0x400e, 0x265c: 0x4012, 0x265d: 0x4016, + 0x265e: 0x401b, 0x265f: 0x401f, 0x2660: 0x4023, 0x2661: 0x4027, 0x2662: 0x2f01, 0x2663: 0x402b, + 0x2664: 0x4030, 0x2665: 0x4034, 0x2666: 0x4038, 0x2667: 0x30b5, 0x2668: 0x403c, 0x2669: 0x4040, + 0x266a: 0x4044, 0x266b: 0x4048, 0x266c: 0x404c, 0x266d: 0x4051, 0x266e: 0x4055, 0x266f: 0x4059, + 0x2670: 0x405d, 0x2671: 0x4062, 0x2672: 0x4066, 0x2673: 0x406a, 0x2674: 0x406e, 0x2675: 0x2c25, + 0x2676: 0x4072, 0x2677: 0x4076, 0x2678: 0x407b, 0x2679: 0x4080, 0x267a: 0x4085, 0x267b: 0x4089, + 0x267c: 0x408e, 0x267d: 0x4092, 0x267e: 0x4096, 0x267f: 0x409a, + // Block 0x9a, offset 0x2680 + 0x2680: 0x409e, 0x2681: 0x2f05, 0x2682: 0x2d71, 0x2683: 0x40a2, 0x2684: 0x40a6, 0x2685: 0x40aa, + 0x2686: 0x40ae, 0x2687: 0x40b3, 0x2688: 0x40b7, 0x2689: 0x40bb, 0x268a: 0x40bf, 0x268b: 0x3016, + 0x268c: 0x40c3, 0x268d: 0x40c7, 0x268e: 0x40cc, 0x268f: 0x40d0, 0x2690: 0x40d4, 0x2691: 0x40d9, + 0x2692: 0x40de, 0x2693: 0x40e2, 0x2694: 0x301a, 0x2695: 0x40e6, 0x2696: 0x40ea, 0x2697: 0x40ee, + 0x2698: 0x40f2, 0x2699: 0x40f6, 0x269a: 0x40fa, 0x269b: 0x40fe, 0x269c: 0x4103, 0x269d: 0x4107, + 0x269e: 0x410c, 0x269f: 0x4110, 0x26a0: 0x4115, 0x26a1: 0x3022, 0x26a2: 0x4119, 0x26a3: 0x411d, + 0x26a4: 0x4122, 0x26a5: 0x4126, 0x26a6: 0x412a, 0x26a7: 0x412f, 0x26a8: 0x4134, 0x26a9: 0x4138, + 0x26aa: 0x413c, 0x26ab: 0x4140, 0x26ac: 0x4144, 0x26ad: 0x4144, 0x26ae: 0x4148, 0x26af: 0x414c, + 0x26b0: 0x302a, 0x26b1: 0x4150, 0x26b2: 0x4154, 0x26b3: 0x4158, 0x26b4: 0x415c, 0x26b5: 0x4160, + 0x26b6: 0x4165, 0x26b7: 0x4169, 0x26b8: 0x2bed, 0x26b9: 0x416e, 0x26ba: 0x4173, 0x26bb: 0x4177, + 0x26bc: 0x417c, 0x26bd: 0x4181, 0x26be: 0x4186, 0x26bf: 0x418a, + // Block 0x9b, offset 0x26c0 + 0x26c0: 0x3042, 0x26c1: 0x418e, 0x26c2: 0x4193, 0x26c3: 0x4198, 0x26c4: 0x419d, 0x26c5: 0x41a2, + 0x26c6: 0x41a6, 0x26c7: 0x41a6, 0x26c8: 0x3046, 0x26c9: 0x30bd, 0x26ca: 0x41aa, 0x26cb: 0x41ae, + 0x26cc: 0x41b2, 0x26cd: 0x41b6, 0x26ce: 0x41bb, 0x26cf: 0x2b59, 0x26d0: 0x304e, 0x26d1: 0x41bf, + 0x26d2: 0x41c3, 0x26d3: 0x2f2d, 0x26d4: 0x41c8, 0x26d5: 0x41cd, 0x26d6: 0x2e89, 0x26d7: 0x41d2, + 0x26d8: 0x41d6, 0x26d9: 0x2f39, 0x26da: 0x41da, 0x26db: 0x41de, 0x26dc: 0x41e2, 0x26dd: 0x41e7, + 0x26de: 0x41e7, 0x26df: 0x41ec, 0x26e0: 0x41f0, 0x26e1: 0x41f4, 0x26e2: 0x41f9, 0x26e3: 0x41fd, + 0x26e4: 0x4201, 0x26e5: 0x4205, 0x26e6: 0x420a, 0x26e7: 0x420e, 0x26e8: 0x4212, 0x26e9: 0x4216, + 0x26ea: 0x421a, 0x26eb: 0x421e, 0x26ec: 0x4223, 0x26ed: 0x4227, 0x26ee: 0x422b, 0x26ef: 0x422f, + 0x26f0: 0x4233, 0x26f1: 0x4237, 0x26f2: 0x423b, 0x26f3: 0x4240, 0x26f4: 0x4245, 0x26f5: 0x4249, + 0x26f6: 0x424e, 0x26f7: 0x4252, 0x26f8: 0x4257, 0x26f9: 0x425b, 0x26fa: 0x2f51, 0x26fb: 0x425f, + 0x26fc: 0x4264, 0x26fd: 0x4269, 0x26fe: 0x426d, 0x26ff: 0x4272, + // Block 0x9c, offset 0x2700 + 0x2700: 0x4276, 0x2701: 0x427b, 0x2702: 0x427f, 0x2703: 0x4283, 0x2704: 0x4287, 0x2705: 0x428b, + 0x2706: 0x428f, 0x2707: 0x4293, 0x2708: 0x4298, 0x2709: 0x429d, 0x270a: 0x42a2, 0x270b: 0x3f14, + 0x270c: 0x42a7, 0x270d: 0x42ab, 0x270e: 0x42af, 0x270f: 0x42b3, 0x2710: 0x42b7, 0x2711: 0x42bb, + 0x2712: 0x42bf, 0x2713: 0x42c3, 0x2714: 0x42c7, 0x2715: 0x42cb, 0x2716: 0x42cf, 0x2717: 0x42d3, + 0x2718: 0x2c31, 0x2719: 0x42d8, 0x271a: 0x42dc, 0x271b: 0x42e0, 0x271c: 0x42e4, 0x271d: 0x42e8, + 0x271e: 0x42ec, 0x271f: 0x2f5d, 0x2720: 0x42f0, 0x2721: 0x42f4, 0x2722: 0x42f8, 0x2723: 0x42fc, + 0x2724: 0x4300, 0x2725: 0x4305, 0x2726: 0x430a, 0x2727: 0x430f, 0x2728: 0x4313, 0x2729: 0x4317, + 0x272a: 0x431b, 0x272b: 0x431f, 0x272c: 0x4324, 0x272d: 0x4328, 0x272e: 0x432d, 0x272f: 0x4331, + 0x2730: 0x4335, 0x2731: 0x433a, 0x2732: 0x433f, 0x2733: 0x4343, 0x2734: 0x2b45, 0x2735: 0x4347, + 0x2736: 0x434b, 0x2737: 0x434f, 0x2738: 0x4353, 0x2739: 0x4357, 0x273a: 0x435b, 0x273b: 0x306a, + 0x273c: 0x435f, 0x273d: 0x4363, 0x273e: 0x4367, 0x273f: 0x436b, + // Block 0x9d, offset 0x2740 + 0x2740: 0x436f, 0x2741: 0x4373, 0x2742: 0x4377, 0x2743: 0x437b, 0x2744: 0x1a66, 0x2745: 0x437f, + 0x2746: 0x4384, 0x2747: 0x4388, 0x2748: 0x438c, 0x2749: 0x4390, 0x274a: 0x4394, 0x274b: 0x4398, + 0x274c: 0x439d, 0x274d: 0x43a2, 0x274e: 0x43a6, 0x274f: 0x43aa, 0x2750: 0x307e, 0x2751: 0x3082, + 0x2752: 0x1a82, 0x2753: 0x43ae, 0x2754: 0x43b3, 0x2755: 0x43b7, 0x2756: 0x43bb, 0x2757: 0x43bf, + 0x2758: 0x43c3, 0x2759: 0x43c8, 0x275a: 0x43cd, 0x275b: 0x43d1, 0x275c: 0x43d5, 0x275d: 0x43d9, + 0x275e: 0x43de, 0x275f: 0x3086, 0x2760: 0x43e2, 0x2761: 0x43e7, 0x2762: 0x43ec, 0x2763: 0x43f0, + 0x2764: 0x43f4, 0x2765: 0x43f8, 0x2766: 0x43fd, 0x2767: 0x4401, 0x2768: 0x4405, 0x2769: 0x4409, + 0x276a: 0x440d, 0x276b: 0x4411, 0x276c: 0x4415, 0x276d: 0x4419, 0x276e: 0x441e, 0x276f: 0x4422, + 0x2770: 0x4426, 0x2771: 0x442a, 0x2772: 0x442f, 0x2773: 0x4433, 0x2774: 0x4437, 0x2775: 0x443b, + 0x2776: 0x443f, 0x2777: 0x4444, 0x2778: 0x4449, 0x2779: 0x444d, 0x277a: 0x4451, 0x277b: 0x4455, + 0x277c: 0x445a, 0x277d: 0x445e, 0x277e: 0x309e, 0x277f: 0x309e, + // Block 0x9e, offset 0x2780 + 0x2780: 0x4463, 0x2781: 0x4467, 0x2782: 0x446c, 0x2783: 0x4470, 0x2784: 0x4474, 0x2785: 0x4478, + 0x2786: 0x447c, 0x2787: 0x4480, 0x2788: 0x4484, 0x2789: 0x4488, 0x278a: 0x30a2, 0x278b: 0x448d, + 0x278c: 0x4491, 0x278d: 0x4495, 0x278e: 0x4499, 0x278f: 0x449d, 0x2790: 0x44a1, 0x2791: 0x44a6, + 0x2792: 0x44aa, 0x2793: 0x44af, 0x2794: 0x44b4, 0x2795: 0x1b42, 0x2796: 0x44b9, 0x2797: 0x1b52, + 0x2798: 0x44bd, 0x2799: 0x44c1, 0x279a: 0x44c5, 0x279b: 0x44c9, 0x279c: 0x1b66, 0x279d: 0x44cd, } // nfkcDecompLookup: 960 bytes // Block 0 is the null block. -var nfkcDecompLookup = [...]uint8{ - // Block 0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 2 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 3 - 0x00, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x00, 0x0A, 0x0B, 0x00, 0x0C, 0x0D, 0x0E, - 0x0F, 0x10, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, - 0x13, 0x14, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 4 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x16, 0x17, 0x00, 0x18, - 0x19, 0x1A, 0x00, 0x00, 0x00, 0x1B, 0x1C, 0x1D, - 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x20, 0x00, 0x21, - 0x22, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x00, - // Block 5 - 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2A, 0x2B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2C, 0x2D, 0x2E, 0x00, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - // Block 6 - 0x37, 0x38, 0x39, 0x00, 0x3A, 0x3B, 0x3C, 0x3D, - 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x00, 0x00, 0x00, - 0x00, 0x43, 0x44, 0x45, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x47, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, - 0x00, 0x00, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, - // Block 7 - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x00, - 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 8 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 9 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, - 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, - // Block A - 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block B - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7F, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block C - 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x00, - 0x94, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block D - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, - 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block E - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x0C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +var nfkcDecompLookup = [960]uint8{ + // Block 0x0, offset 0x0 + // Block 0x1, offset 0x40 + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x0c2: 0x03, 0x0c3: 0x04, 0x0c4: 0x05, 0x0c5: 0x06, 0x0c6: 0x07, 0x0c7: 0x08, + 0x0c8: 0x09, 0x0ca: 0x0a, 0x0cb: 0x0b, 0x0cd: 0x0c, 0x0ce: 0x0d, 0x0cf: 0x0e, + 0x0d0: 0x0f, 0x0d1: 0x10, 0x0d3: 0x11, 0x0d6: 0x12, + 0x0d8: 0x13, 0x0d9: 0x14, 0x0db: 0x15, + 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07, + 0x0ea: 0x08, 0x0ef: 0x09, + 0x0f0: 0x0e, + // Block 0x4, offset 0x100 + 0x124: 0x16, 0x125: 0x17, 0x127: 0x18, + 0x128: 0x19, 0x129: 0x1a, 0x12d: 0x1b, 0x12e: 0x1c, 0x12f: 0x1d, + 0x131: 0x1e, 0x133: 0x1f, 0x135: 0x20, 0x137: 0x21, + 0x138: 0x22, 0x13a: 0x23, 0x13b: 0x24, 0x13c: 0x25, 0x13d: 0x26, 0x13e: 0x27, + // Block 0x5, offset 0x140 + 0x140: 0x28, 0x143: 0x29, + 0x16c: 0x2a, 0x16d: 0x2b, + 0x174: 0x2c, 0x175: 0x2d, 0x176: 0x2e, + 0x178: 0x2f, 0x179: 0x30, 0x17a: 0x31, 0x17b: 0x32, 0x17c: 0x33, 0x17d: 0x34, 0x17e: 0x35, 0x17f: 0x36, + // Block 0x6, offset 0x180 + 0x180: 0x37, 0x181: 0x38, 0x182: 0x39, 0x184: 0x3a, 0x185: 0x3b, 0x186: 0x3c, 0x187: 0x3d, + 0x188: 0x3e, 0x189: 0x3f, 0x18a: 0x40, 0x18b: 0x41, 0x18c: 0x42, + 0x191: 0x43, 0x192: 0x44, 0x193: 0x45, + 0x1a8: 0x46, 0x1a9: 0x47, 0x1ab: 0x48, + 0x1b1: 0x49, 0x1b5: 0x4a, + 0x1ba: 0x4b, 0x1bb: 0x4c, 0x1bc: 0x4d, 0x1bd: 0x4e, 0x1be: 0x4f, 0x1bf: 0x50, + // Block 0x7, offset 0x1c0 + 0x1c0: 0x51, 0x1c1: 0x52, 0x1c2: 0x53, 0x1c3: 0x54, 0x1c4: 0x55, 0x1c5: 0x56, 0x1c6: 0x57, + 0x1c8: 0x58, 0x1c9: 0x59, 0x1ca: 0x5a, 0x1cb: 0x5b, 0x1cc: 0x5c, 0x1cd: 0x5d, 0x1ce: 0x5e, 0x1cf: 0x5f, + // Block 0x8, offset 0x200 + 0x21d: 0x60, + // Block 0x9, offset 0x240 + 0x264: 0x61, 0x265: 0x62, 0x266: 0x63, 0x267: 0x64, + 0x268: 0x65, 0x269: 0x66, 0x26a: 0x67, 0x26b: 0x68, 0x26c: 0x69, 0x26d: 0x6a, 0x26e: 0x6b, 0x26f: 0x6c, + 0x270: 0x6d, 0x271: 0x6e, 0x272: 0x6f, 0x273: 0x70, 0x274: 0x71, 0x275: 0x72, 0x276: 0x73, 0x277: 0x74, + 0x278: 0x75, 0x279: 0x76, 0x27a: 0x77, 0x27b: 0x78, 0x27c: 0x79, 0x27d: 0x7a, 0x27e: 0x7b, 0x27f: 0x7c, + // Block 0xa, offset 0x280 + 0x282: 0x7d, + // Block 0xb, offset 0x2c0 + 0x2c5: 0x7e, 0x2c6: 0x7f, 0x2c7: 0x80, + 0x2d0: 0x81, 0x2d1: 0x82, 0x2d2: 0x83, 0x2d3: 0x84, 0x2d4: 0x85, 0x2d5: 0x86, 0x2d6: 0x87, 0x2d7: 0x88, + 0x2d8: 0x89, 0x2d9: 0x8a, 0x2da: 0x8b, 0x2db: 0x8c, 0x2dc: 0x8d, 0x2dd: 0x8e, 0x2de: 0x8f, 0x2df: 0x90, + // Block 0xc, offset 0x300 + 0x304: 0x91, 0x305: 0x92, 0x306: 0x93, + 0x308: 0x94, 0x309: 0x95, + // Block 0xd, offset 0x340 + 0x360: 0x96, 0x361: 0x97, 0x362: 0x98, 0x363: 0x99, 0x364: 0x9a, 0x365: 0x9b, 0x366: 0x9c, 0x367: 0x9d, + 0x368: 0x9e, + // Block 0xe, offset 0x380 + 0x391: 0x0a, + 0x39d: 0x0b, 0x39f: 0x0c, + 0x3af: 0x0d, } +var nfkcDecompTrie = trie{nfkcDecompLookup[:], nfkcDecompValues[:]} + // recompMap: 7448 bytes (entries only) var recompMap = map[uint32]uint32{ 0x00410300: 0x00C0, @@ -5832,1713 +5358,1223 @@ var recompMap = map[uint32]uint32{ // charInfoValues: 10944 entries, 21888 bytes // Block 2 is the null block. -var charInfoValues = [...]uint16{ - // Block 0 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x0000, - // Block 1 - 0x0000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, - 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, - 0x8800, 0x0000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, - 0x8800, 0x8800, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, - 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, - 0x8800, 0x0000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, - 0x8800, 0x8800, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3800, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x0000, - // Block 4 - 0x1100, 0x1100, 0x9900, 0x1100, 0x9900, 0x9900, 0x8800, 0x9900, - 0x1100, 0x1100, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x9900, - 0x0000, 0x1100, 0x1100, 0x1100, 0x9900, 0x9900, 0x9900, 0x0000, - 0x8800, 0x1100, 0x1100, 0x1100, 0x9900, 0x1100, 0x0000, 0x0000, - 0x1100, 0x1100, 0x9900, 0x1100, 0x9900, 0x9900, 0x8800, 0x9900, - 0x1100, 0x1100, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x9900, - 0x0000, 0x1100, 0x1100, 0x1100, 0x9900, 0x9900, 0x9900, 0x0000, - 0x8800, 0x1100, 0x1100, 0x1100, 0x9900, 0x1100, 0x0000, 0x1100, - // Block 5 - 0x1100, 0x1100, 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x0000, 0x0000, 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x0000, 0x3000, 0x3000, 0x1100, 0x1100, 0x1100, 0x1100, - 0x0000, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x3000, - // Block 6 - 0x3000, 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x3000, 0x0000, 0x0000, 0x9900, 0x9900, 0x1100, 0x1100, - 0x1100, 0x1100, 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x9900, 0x9900, 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x3800, - // Block 7 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9900, 0x9900, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9900, - 0x9900, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 8 - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, 0x1100, 0x1100, - 0x1100, 0x1100, 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x3000, 0x3000, 0x3000, 0x1100, 0x1100, 0x0000, 0x0000, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - // Block 9 - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, 0x1100, 0x1100, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9900, 0x9900, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x9900, 0x9900, - 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block C - 0x66E6, 0x66E6, 0x66E6, 0x66E6, 0x66E6, 0x00E6, 0x66E6, 0x66E6, - 0x66E6, 0x66E6, 0x66E6, 0x66E6, 0x66E6, 0x00E6, 0x00E6, 0x66E6, - 0x00E6, 0x66E6, 0x00E6, 0x66E6, 0x66E6, 0x00E8, 0x00DC, 0x00DC, - 0x00DC, 0x00DC, 0x00E8, 0x66D8, 0x00DC, 0x00DC, 0x00DC, 0x00DC, - 0x00DC, 0x00CA, 0x00CA, 0x66DC, 0x66DC, 0x66DC, 0x66DC, 0x66CA, - 0x66CA, 0x00DC, 0x00DC, 0x00DC, 0x00DC, 0x66DC, 0x66DC, 0x00DC, - 0x66DC, 0x66DC, 0x00DC, 0x00DC, 0x0001, 0x0001, 0x0001, 0x0001, - 0x6601, 0x00DC, 0x00DC, 0x00DC, 0x00DC, 0x00E6, 0x00E6, 0x00E6, - // Block D - 0x33E6, 0x33E6, 0x66E6, 0x33E6, 0x33E6, 0x66F0, 0x00E6, 0x00DC, - 0x00DC, 0x00DC, 0x00E6, 0x00E6, 0x00E6, 0x00DC, 0x00DC, 0x0000, - 0x00E6, 0x00E6, 0x00E6, 0x00DC, 0x00DC, 0x00DC, 0x00DC, 0x00E6, - 0x00E8, 0x00DC, 0x00DC, 0x00E6, 0x00E9, 0x00EA, 0x00EA, 0x00E9, - 0x00EA, 0x00EA, 0x00E9, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, - // Block E - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3100, 0x1100, 0x3300, - 0x1100, 0x1100, 0x1100, 0x0000, 0x1100, 0x0000, 0x1100, 0x1100, - 0x1100, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x8800, - 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, - 0x0000, 0x8800, 0x1100, 0x1100, 0x9900, 0x1100, 0x9900, 0x1100, - 0x1100, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x8800, - 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - // Block F - 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, - 0x0000, 0x8800, 0x9900, 0x9900, 0x1100, 0x1100, 0x9900, 0x0000, - 0x3000, 0x3000, 0x3800, 0x3100, 0x3100, 0x3000, 0x3000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x0000, 0x0000, - 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 10 - 0x1100, 0x1100, 0x0000, 0x1100, 0x0000, 0x0000, 0x8800, 0x1100, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x0000, - 0x8800, 0x0000, 0x0000, 0x8800, 0x0000, 0x8800, 0x8800, 0x8800, - 0x8800, 0x1100, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, - 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, - 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x8800, 0x0000, 0x0000, - 0x8800, 0x0000, 0x0000, 0x8800, 0x0000, 0x8800, 0x8800, 0x8800, - 0x8800, 0x1100, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, - // Block 11 - 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x8800, - 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x8800, 0x0000, 0x0000, - 0x1100, 0x1100, 0x0000, 0x1100, 0x0000, 0x0000, 0x8800, 0x1100, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x8800, 0x1100, 0x1100, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 12 - 0x0000, 0x0000, 0x0000, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 13 - 0x0000, 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, 0x1100, 0x1100, - 0x8800, 0x8800, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x8800, 0x8800, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 14 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x00DC, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00DC, 0x00E6, - 0x00E6, 0x00E6, 0x00DE, 0x00DC, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00DC, 0x00DC, 0x00DC, 0x00DC, 0x00DC, 0x00DC, - 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x00DE, 0x00E4, 0x00E6, - 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, - 0x0012, 0x0013, 0x0013, 0x0014, 0x0015, 0x0016, 0x0000, 0x0017, - // Block 15 - 0x0000, 0x0018, 0x0019, 0x0000, 0x00E6, 0x00DC, 0x0000, 0x0012, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 16 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x001E, 0x001F, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x8800, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 17 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x8800, 0x0000, 0x8800, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x66E6, 0x66E6, 0x66DC, 0x00DC, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x00DC, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0023, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 18 - 0x1100, 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x8800, 0x1100, 0x0000, 0x8800, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x0000, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x0000, 0x0000, 0x00E6, - 0x00E6, 0x0000, 0x00DC, 0x00E6, 0x00E6, 0x00DC, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 19 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0024, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x00DC, - 0x00DC, 0x00DC, 0x00E6, 0x00DC, 0x00DC, 0x00E6, 0x00DC, 0x00E6, - // Block 1A - 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x00DC, 0x00E6, 0x00DC, 0x00E6, - 0x00DC, 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x0000, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x00E6, 0x00E6, 0x00E6, - 0x0000, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x00DC, 0x00DC, 0x00DC, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 1E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x8800, 0x1100, 0x0000, 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x6607, 0x0000, 0x0000, 0x0000, - // Block 1F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, - 0x0000, 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 20 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, 0x6600, 0x0000, - // Block 21 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - 0x0000, 0x0000, 0x0000, 0x1100, 0x1100, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x3300, 0x0000, 0x3300, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 22 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x3300, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, 0x0000, 0x0000, - // Block 23 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, 0x3300, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 24 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, 0x0000, 0x0000, - // Block 25 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 26 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - 0x1100, 0x0000, 0x0000, 0x1100, 0x1100, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, 0x6600, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x3300, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 27 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x8800, 0x0000, 0x1100, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, 0x0000, - // Block 28 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x8800, - 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 29 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, - 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0054, 0x665B, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, 0x0000, 0x8800, - // Block 2B - 0x1100, 0x0000, 0x6600, 0x0000, 0x0000, 0x0000, 0x8800, 0x1100, - 0x1100, 0x0000, 0x9900, 0x1100, 0x0000, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, 0x6600, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, 0x0000, - // Block 2D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x6609, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x8800, 0x1100, 0x0000, 0x9900, 0x1100, 0x1100, 0x6600, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0067, 0x0067, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 2F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x006B, 0x006B, 0x006B, 0x006B, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 30 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0076, 0x0076, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 31 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x007A, 0x007A, 0x007A, 0x007A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 32 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00DC, 0x00DC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00DC, 0x0000, 0x00DC, - 0x0000, 0x00D8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 33 - 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, - 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0081, 0x0082, 0x3300, 0x0084, 0x3300, 0x3300, 0x3000, - 0x3300, 0x3000, 0x0082, 0x0082, 0x0082, 0x0082, 0x0000, 0x0000, - // Block 34 - 0x0082, 0x3300, 0x00E6, 0x00E6, 0x0009, 0x0000, 0x00E6, 0x00E6, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, - 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 35 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00DC, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 36 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x1100, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6600, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, - 0x0000, 0x0009, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 37 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00DC, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 38 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, - // Block 39 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, - 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, - 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, - 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, - 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, 0x6600, - // Block 3B - 0x6600, 0x6600, 0x6600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, 0x00E6, 0x00E6, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 3F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x00E4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 40 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x00DE, 0x00E6, 0x00DC, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 41 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, - 0x00DC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 42 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x0000, 0x00DC, - // Block 43 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x1100, 0x8800, - 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x0000, - 0x0000, 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x6600, 0x0000, 0x0000, - 0x0000, 0x0000, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, 0x8800, - // Block 44 - 0x1100, 0x1100, 0x8800, 0x1100, 0x0009, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 45 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 46 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0009, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 47 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 48 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x0001, 0x00DC, 0x00DC, 0x00DC, - 0x00DC, 0x00DC, 0x00E6, 0x00E6, 0x00DC, 0x00DC, 0x00DC, 0x00DC, - 0x00E6, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x00DC, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 49 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 4A - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 4B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 4C - 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00DC, 0x00E6, 0x00E6, 0x00EA, 0x00D6, 0x00DC, - 0x00CA, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x00E9, 0x00DC, 0x00E6, 0x00DC, - // Block 4D - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x9900, 0x9900, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - // Block 4E - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - // Block 4F - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x3000, 0x3100, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - // Block 50 - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x9900, 0x9900, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 51 - 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, - 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, - 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - // Block 52 - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x9900, 0x9900, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x0000, 0x9900, 0x0000, 0x1100, 0x0000, 0x1100, 0x0000, 0x1100, - 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, - 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, - 0x9900, 0x3300, 0x1100, 0x3300, 0x9900, 0x3300, 0x1100, 0x3300, - 0x1100, 0x3300, 0x1100, 0x3300, 0x9900, 0x3300, 0x0000, 0x0000, - // Block 53 - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x9900, 0x1100, - 0x1100, 0x1100, 0x1100, 0x3300, 0x1100, 0x3000, 0x3300, 0x3800, - // Block 54 - 0x3000, 0x3100, 0x1100, 0x1100, 0x1100, 0x0000, 0x9900, 0x1100, - 0x1100, 0x3300, 0x1100, 0x3300, 0x1100, 0x3100, 0x3100, 0x3100, - 0x1100, 0x1100, 0x1100, 0x3300, 0x0000, 0x0000, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x3300, 0x0000, 0x3100, 0x3100, 0x3100, - 0x1100, 0x1100, 0x1100, 0x3300, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x3300, 0x1100, 0x3100, 0x3300, 0x3300, - 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x0000, 0x9900, 0x1100, - 0x1100, 0x3300, 0x1100, 0x3300, 0x1100, 0x3300, 0x3800, 0x0000, - // Block 55 - 0x3300, 0x3300, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, 0x3000, 0x0000, - // Block 56 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 57 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 58 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00E6, 0x0001, 0x0001, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x0001, 0x0001, 0x0001, 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, - 0x0000, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x00E6, - 0x00DC, 0x00E6, 0x0001, 0x0001, 0x00DC, 0x00DC, 0x00DC, 0x00DC, - 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 59 - 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x0000, - 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x0000, 0x3300, 0x0000, - 0x3000, 0x0000, 0x3300, 0x3300, 0x3000, 0x3000, 0x0000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 5A - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 5B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x8800, 0x0000, 0x8800, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1100, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 5C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, - 0x8800, 0x0000, 0x8800, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 5D - 0x0000, 0x0000, 0x0000, 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, - 0x8800, 0x1100, 0x0000, 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x8800, 0x1100, 0x8800, 0x1100, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, 0x3000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, - // Block 5E - 0x0000, 0x1100, 0x0000, 0x8800, 0x1100, 0x8800, 0x0000, 0x1100, - 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1100, 0x8800, 0x1100, 0x0000, 0x8800, 0x8800, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x8800, 0x8800, 0x1100, 0x1100, 0x8800, 0x8800, - 0x1100, 0x1100, 0x8800, 0x8800, 0x8800, 0x8800, 0x0000, 0x0000, - // Block 5F - 0x1100, 0x1100, 0x8800, 0x8800, 0x1100, 0x1100, 0x8800, 0x8800, - 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x8800, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x8800, 0x8800, 0x0000, 0x8800, 0x1100, 0x1100, 0x1100, 0x1100, - 0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x8800, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 60 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 61 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 62 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 63 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 64 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 65 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 66 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 67 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 68 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, 0x0000, - // Block 69 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, - 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 6A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, - // Block 6B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - // Block 6C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 6D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 6E - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 6F - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x00DA, 0x00E4, 0x00E8, 0x00DE, 0x00E0, 0x00E0, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 70 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, - 0x0000, 0x0000, 0x0000, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, - 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, - 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, - 0x1100, 0x8800, 0x1100, 0x0000, 0x8800, 0x1100, 0x8800, 0x1100, - 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - 0x1100, 0x1100, 0x8800, 0x1100, 0x1100, 0x8800, 0x1100, 0x1100, - 0x8800, 0x1100, 0x1100, 0x8800, 0x1100, 0x1100, 0x0000, 0x0000, - // Block 71 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1100, 0x0000, 0x0000, 0x0000, - 0x0000, 0x6608, 0x6608, 0x3000, 0x3000, 0x8800, 0x1100, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, - 0x0000, 0x0000, 0x0000, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, - 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, - 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, 0x1100, 0x8800, - // Block 72 - 0x1100, 0x8800, 0x1100, 0x0000, 0x8800, 0x1100, 0x8800, 0x1100, - 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - 0x1100, 0x1100, 0x8800, 0x1100, 0x1100, 0x8800, 0x1100, 0x1100, - 0x8800, 0x1100, 0x1100, 0x8800, 0x1100, 0x1100, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, - 0x8800, 0x8800, 0x8800, 0x0000, 0x1100, 0x0000, 0x0000, 0x1100, - 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, 0x8800, 0x1100, 0x3000, - // Block 73 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 74 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 75 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 76 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - // Block 77 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - // Block 78 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, 0x00E6, 0x0000, 0x0000, - // Block 79 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7B - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7C - 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00DC, 0x00DC, 0x00DC, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7E - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 7F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 80 - 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 81 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x0000, 0x00E6, 0x00E6, 0x00DC, 0x0000, 0x0000, 0x00E6, - 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E6, 0x00E6, - // Block 82 - 0x0000, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 83 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 84 - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - // Block 85 - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, - 0x1100, 0x1100, 0x1100, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 86 - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - // Block 87 - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, - 0x3300, 0x0000, 0x3300, 0x0000, 0x0000, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, - 0x3300, 0x0000, 0x3300, 0x0000, 0x0000, 0x3300, 0x3300, 0x0000, - 0x0000, 0x0000, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - // Block 88 - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - // Block 89 - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 8A - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x001A, 0x3300, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x3300, 0x0000, - // Block 8B - 0x3300, 0x3300, 0x0000, 0x3300, 0x3300, 0x0000, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 8C - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 8D - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 8E - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, - // Block 8F - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 90 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 91 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, - // Block 92 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 93 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x0000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 94 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, - // Block 95 - 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 96 - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 97 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00DC, 0x0000, 0x0000, - // Block 98 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00DC, 0x0000, 0x00E6, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00E6, 0x0001, 0x00DC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, - // Block 99 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x8800, 0x1100, 0x8800, 0x1100, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8800, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x1100, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0009, 0x6607, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 9A - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x00D8, 0x00D8, 0x0001, - 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x00E2, 0x00D8, 0x00D8, - 0x00D8, 0x00D8, 0x00D8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00DC, 0x00DC, 0x00DC, 0x00DC, 0x00DC, - // Block 9B - 0x00DC, 0x00DC, 0x00DC, 0x0000, 0x0000, 0x00E6, 0x00E6, 0x00E6, - 0x00E6, 0x00E6, 0x00DC, 0x00DC, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x00E6, 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - // Block 9C - 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 9D - 0x0000, 0x0000, 0x00E6, 0x00E6, 0x00E6, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block 9E - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block 9F - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, - 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, - // Block A0 - 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block A1 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - // Block A2 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x3000, 0x0000, - 0x0000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x0000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block A3 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block A4 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block A5 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - // Block A6 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block A7 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block A8 - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block A9 - 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, - 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - // Block AA - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, - 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +var charInfoValues = [10944]uint16{ + // Block 0x0, offset 0x0 + 0x003c: 0x8800, 0x003d: 0x8800, 0x003e: 0x8800, + // Block 0x1, offset 0x40 + 0x0041: 0x8800, 0x0042: 0x8800, 0x0043: 0x8800, 0x0044: 0x8800, 0x0045: 0x8800, + 0x0046: 0x8800, 0x0047: 0x8800, 0x0048: 0x8800, 0x0049: 0x8800, 0x004a: 0x8800, 0x004b: 0x8800, + 0x004c: 0x8800, 0x004d: 0x8800, 0x004e: 0x8800, 0x004f: 0x8800, 0x0050: 0x8800, + 0x0052: 0x8800, 0x0053: 0x8800, 0x0054: 0x8800, 0x0055: 0x8800, 0x0056: 0x8800, 0x0057: 0x8800, + 0x0058: 0x8800, 0x0059: 0x8800, 0x005a: 0x8800, + 0x0061: 0x8800, 0x0062: 0x8800, 0x0063: 0x8800, + 0x0064: 0x8800, 0x0065: 0x8800, 0x0066: 0x8800, 0x0067: 0x8800, 0x0068: 0x8800, 0x0069: 0x8800, + 0x006a: 0x8800, 0x006b: 0x8800, 0x006c: 0x8800, 0x006d: 0x8800, 0x006e: 0x8800, 0x006f: 0x8800, + 0x0070: 0x8800, 0x0072: 0x8800, 0x0073: 0x8800, 0x0074: 0x8800, 0x0075: 0x8800, + 0x0076: 0x8800, 0x0077: 0x8800, 0x0078: 0x8800, 0x0079: 0x8800, 0x007a: 0x8800, + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x00e0: 0x3000, + 0x00e8: 0x3800, + 0x00ea: 0x3000, 0x00ef: 0x3000, + 0x00f2: 0x3000, 0x00f3: 0x3000, 0x00f4: 0x3000, 0x00f5: 0x3000, + 0x00f8: 0x3000, 0x00f9: 0x3000, 0x00fa: 0x3000, + 0x00fc: 0x3000, 0x00fd: 0x3000, 0x00fe: 0x3000, + // Block 0x4, offset 0x100 + 0x0100: 0x1100, 0x0101: 0x1100, 0x0102: 0x9900, 0x0103: 0x1100, 0x0104: 0x9900, 0x0105: 0x9900, + 0x0106: 0x8800, 0x0107: 0x9900, 0x0108: 0x1100, 0x0109: 0x1100, 0x010a: 0x9900, 0x010b: 0x1100, + 0x010c: 0x1100, 0x010d: 0x1100, 0x010e: 0x1100, 0x010f: 0x9900, 0x0111: 0x1100, + 0x0112: 0x1100, 0x0113: 0x1100, 0x0114: 0x9900, 0x0115: 0x9900, 0x0116: 0x9900, + 0x0118: 0x8800, 0x0119: 0x1100, 0x011a: 0x1100, 0x011b: 0x1100, 0x011c: 0x9900, 0x011d: 0x1100, + 0x0120: 0x1100, 0x0121: 0x1100, 0x0122: 0x9900, 0x0123: 0x1100, + 0x0124: 0x9900, 0x0125: 0x9900, 0x0126: 0x8800, 0x0127: 0x9900, 0x0128: 0x1100, 0x0129: 0x1100, + 0x012a: 0x9900, 0x012b: 0x1100, 0x012c: 0x1100, 0x012d: 0x1100, 0x012e: 0x1100, 0x012f: 0x9900, + 0x0131: 0x1100, 0x0132: 0x1100, 0x0133: 0x1100, 0x0134: 0x9900, 0x0135: 0x9900, + 0x0136: 0x9900, 0x0138: 0x8800, 0x0139: 0x1100, 0x013a: 0x1100, 0x013b: 0x1100, + 0x013c: 0x9900, 0x013d: 0x1100, 0x013f: 0x1100, + // Block 0x5, offset 0x140 + 0x0140: 0x1100, 0x0141: 0x1100, 0x0142: 0x9900, 0x0143: 0x9900, 0x0144: 0x1100, 0x0145: 0x1100, + 0x0146: 0x1100, 0x0147: 0x1100, 0x0148: 0x1100, 0x0149: 0x1100, 0x014a: 0x1100, 0x014b: 0x1100, + 0x014c: 0x1100, 0x014d: 0x1100, 0x014e: 0x1100, 0x014f: 0x1100, + 0x0152: 0x9900, 0x0153: 0x9900, 0x0154: 0x1100, 0x0155: 0x1100, 0x0156: 0x1100, 0x0157: 0x1100, + 0x0158: 0x1100, 0x0159: 0x1100, 0x015a: 0x1100, 0x015b: 0x1100, 0x015c: 0x1100, 0x015d: 0x1100, + 0x015e: 0x1100, 0x015f: 0x1100, 0x0160: 0x1100, 0x0161: 0x1100, 0x0162: 0x1100, 0x0163: 0x1100, + 0x0164: 0x1100, 0x0165: 0x1100, 0x0168: 0x1100, 0x0169: 0x1100, + 0x016a: 0x1100, 0x016b: 0x1100, 0x016c: 0x1100, 0x016d: 0x1100, 0x016e: 0x1100, 0x016f: 0x1100, + 0x0170: 0x1100, 0x0172: 0x3000, 0x0173: 0x3000, 0x0174: 0x1100, 0x0175: 0x1100, + 0x0176: 0x1100, 0x0177: 0x1100, 0x0179: 0x1100, 0x017a: 0x1100, 0x017b: 0x1100, + 0x017c: 0x1100, 0x017d: 0x1100, 0x017e: 0x1100, 0x017f: 0x3000, + // Block 0x6, offset 0x180 + 0x0180: 0x3000, 0x0183: 0x1100, 0x0184: 0x1100, 0x0185: 0x1100, + 0x0186: 0x1100, 0x0187: 0x1100, 0x0188: 0x1100, 0x0189: 0x3000, + 0x018c: 0x9900, 0x018d: 0x9900, 0x018e: 0x1100, 0x018f: 0x1100, 0x0190: 0x1100, 0x0191: 0x1100, + 0x0194: 0x1100, 0x0195: 0x1100, 0x0196: 0x1100, 0x0197: 0x1100, + 0x0198: 0x1100, 0x0199: 0x1100, 0x019a: 0x9900, 0x019b: 0x9900, 0x019c: 0x1100, 0x019d: 0x1100, + 0x019e: 0x1100, 0x019f: 0x1100, 0x01a0: 0x9900, 0x01a1: 0x9900, 0x01a2: 0x1100, 0x01a3: 0x1100, + 0x01a4: 0x1100, 0x01a5: 0x1100, 0x01a8: 0x9900, 0x01a9: 0x9900, + 0x01aa: 0x9900, 0x01ab: 0x9900, 0x01ac: 0x1100, 0x01ad: 0x1100, 0x01ae: 0x1100, 0x01af: 0x1100, + 0x01b0: 0x1100, 0x01b1: 0x1100, 0x01b2: 0x1100, 0x01b3: 0x1100, 0x01b4: 0x1100, 0x01b5: 0x1100, + 0x01b6: 0x1100, 0x01b7: 0x1100, 0x01b8: 0x1100, 0x01b9: 0x1100, 0x01ba: 0x1100, 0x01bb: 0x1100, + 0x01bc: 0x1100, 0x01bd: 0x1100, 0x01be: 0x1100, 0x01bf: 0x3800, + // Block 0x7, offset 0x1c0 + 0x01e0: 0x9900, 0x01e1: 0x9900, + 0x01ef: 0x9900, + 0x01f0: 0x9900, + 0x01f7: 0x8800, + // Block 0x8, offset 0x200 + 0x0204: 0x3000, 0x0205: 0x3000, + 0x0206: 0x3000, 0x0207: 0x3000, 0x0208: 0x3000, 0x0209: 0x3000, 0x020a: 0x3000, 0x020b: 0x3000, + 0x020c: 0x3000, 0x020d: 0x1100, 0x020e: 0x1100, 0x020f: 0x1100, 0x0210: 0x1100, 0x0211: 0x1100, + 0x0212: 0x1100, 0x0213: 0x1100, 0x0214: 0x1100, 0x0215: 0x1100, 0x0216: 0x1100, 0x0217: 0x1100, + 0x0218: 0x1100, 0x0219: 0x1100, 0x021a: 0x1100, 0x021b: 0x1100, 0x021c: 0x1100, + 0x021e: 0x1100, 0x021f: 0x1100, 0x0220: 0x1100, 0x0221: 0x1100, 0x0222: 0x1100, 0x0223: 0x1100, + 0x0226: 0x1100, 0x0227: 0x1100, 0x0228: 0x1100, 0x0229: 0x1100, + 0x022a: 0x9900, 0x022b: 0x9900, 0x022c: 0x1100, 0x022d: 0x1100, 0x022e: 0x1100, 0x022f: 0x1100, + 0x0230: 0x1100, 0x0231: 0x3000, 0x0232: 0x3000, 0x0233: 0x3000, 0x0234: 0x1100, 0x0235: 0x1100, + 0x0238: 0x1100, 0x0239: 0x1100, 0x023a: 0x1100, 0x023b: 0x1100, + 0x023c: 0x1100, 0x023d: 0x1100, 0x023e: 0x1100, 0x023f: 0x1100, + // Block 0x9, offset 0x240 + 0x0240: 0x1100, 0x0241: 0x1100, 0x0242: 0x1100, 0x0243: 0x1100, 0x0244: 0x1100, 0x0245: 0x1100, + 0x0246: 0x1100, 0x0247: 0x1100, 0x0248: 0x1100, 0x0249: 0x1100, 0x024a: 0x1100, 0x024b: 0x1100, + 0x024c: 0x1100, 0x024d: 0x1100, 0x024e: 0x1100, 0x024f: 0x1100, 0x0250: 0x1100, 0x0251: 0x1100, + 0x0252: 0x1100, 0x0253: 0x1100, 0x0254: 0x1100, 0x0255: 0x1100, 0x0256: 0x1100, 0x0257: 0x1100, + 0x0258: 0x1100, 0x0259: 0x1100, 0x025a: 0x1100, 0x025b: 0x1100, + 0x025e: 0x1100, 0x025f: 0x1100, + 0x0266: 0x9900, 0x0267: 0x9900, 0x0268: 0x9900, 0x0269: 0x9900, + 0x026a: 0x1100, 0x026b: 0x1100, 0x026c: 0x1100, 0x026d: 0x1100, 0x026e: 0x9900, 0x026f: 0x9900, + 0x0270: 0x1100, 0x0271: 0x1100, 0x0272: 0x1100, 0x0273: 0x1100, + // Block 0xa, offset 0x280 + 0x0292: 0x8800, + 0x02b0: 0x3000, 0x02b1: 0x3000, 0x02b2: 0x3000, 0x02b3: 0x3000, 0x02b4: 0x3000, 0x02b5: 0x3000, + 0x02b6: 0x3000, 0x02b7: 0x3000, 0x02b8: 0x3000, + // Block 0xb, offset 0x2c0 + 0x02d8: 0x3000, 0x02d9: 0x3000, 0x02da: 0x3000, 0x02db: 0x3000, 0x02dc: 0x3000, 0x02dd: 0x3000, + 0x02e0: 0x3000, 0x02e1: 0x3000, 0x02e2: 0x3000, 0x02e3: 0x3000, + 0x02e4: 0x3000, + // Block 0xc, offset 0x300 + 0x0300: 0x66e6, 0x0301: 0x66e6, 0x0302: 0x66e6, 0x0303: 0x66e6, 0x0304: 0x66e6, 0x0305: 0x00e6, + 0x0306: 0x66e6, 0x0307: 0x66e6, 0x0308: 0x66e6, 0x0309: 0x66e6, 0x030a: 0x66e6, 0x030b: 0x66e6, + 0x030c: 0x66e6, 0x030d: 0x00e6, 0x030e: 0x00e6, 0x030f: 0x66e6, 0x0310: 0x00e6, 0x0311: 0x66e6, + 0x0312: 0x00e6, 0x0313: 0x66e6, 0x0314: 0x66e6, 0x0315: 0x00e8, 0x0316: 0x00dc, 0x0317: 0x00dc, + 0x0318: 0x00dc, 0x0319: 0x00dc, 0x031a: 0x00e8, 0x031b: 0x66d8, 0x031c: 0x00dc, 0x031d: 0x00dc, + 0x031e: 0x00dc, 0x031f: 0x00dc, 0x0320: 0x00dc, 0x0321: 0x00ca, 0x0322: 0x00ca, 0x0323: 0x66dc, + 0x0324: 0x66dc, 0x0325: 0x66dc, 0x0326: 0x66dc, 0x0327: 0x66ca, 0x0328: 0x66ca, 0x0329: 0x00dc, + 0x032a: 0x00dc, 0x032b: 0x00dc, 0x032c: 0x00dc, 0x032d: 0x66dc, 0x032e: 0x66dc, 0x032f: 0x00dc, + 0x0330: 0x66dc, 0x0331: 0x66dc, 0x0332: 0x00dc, 0x0333: 0x00dc, 0x0334: 0x0001, 0x0335: 0x0001, + 0x0336: 0x0001, 0x0337: 0x0001, 0x0338: 0x6601, 0x0339: 0x00dc, 0x033a: 0x00dc, 0x033b: 0x00dc, + 0x033c: 0x00dc, 0x033d: 0x00e6, 0x033e: 0x00e6, 0x033f: 0x00e6, + // Block 0xd, offset 0x340 + 0x0340: 0x33e6, 0x0341: 0x33e6, 0x0342: 0x66e6, 0x0343: 0x33e6, 0x0344: 0x33e6, 0x0345: 0x66f0, + 0x0346: 0x00e6, 0x0347: 0x00dc, 0x0348: 0x00dc, 0x0349: 0x00dc, 0x034a: 0x00e6, 0x034b: 0x00e6, + 0x034c: 0x00e6, 0x034d: 0x00dc, 0x034e: 0x00dc, 0x0350: 0x00e6, 0x0351: 0x00e6, + 0x0352: 0x00e6, 0x0353: 0x00dc, 0x0354: 0x00dc, 0x0355: 0x00dc, 0x0356: 0x00dc, 0x0357: 0x00e6, + 0x0358: 0x00e8, 0x0359: 0x00dc, 0x035a: 0x00dc, 0x035b: 0x00e6, 0x035c: 0x00e9, 0x035d: 0x00ea, + 0x035e: 0x00ea, 0x035f: 0x00e9, 0x0360: 0x00ea, 0x0361: 0x00ea, 0x0362: 0x00e9, 0x0363: 0x00e6, + 0x0364: 0x00e6, 0x0365: 0x00e6, 0x0366: 0x00e6, 0x0367: 0x00e6, 0x0368: 0x00e6, 0x0369: 0x00e6, + 0x036a: 0x00e6, 0x036b: 0x00e6, 0x036c: 0x00e6, 0x036d: 0x00e6, 0x036e: 0x00e6, 0x036f: 0x00e6, + 0x0374: 0x3300, + 0x037a: 0x3000, + 0x037e: 0x3300, + // Block 0xe, offset 0x380 + 0x0384: 0x3000, 0x0385: 0x3100, + 0x0386: 0x1100, 0x0387: 0x3300, 0x0388: 0x1100, 0x0389: 0x1100, 0x038a: 0x1100, + 0x038c: 0x1100, 0x038e: 0x1100, 0x038f: 0x1100, 0x0390: 0x1100, 0x0391: 0x8800, + 0x0395: 0x8800, 0x0397: 0x8800, + 0x0399: 0x8800, + 0x039f: 0x8800, 0x03a1: 0x8800, + 0x03a5: 0x8800, 0x03a9: 0x8800, + 0x03aa: 0x1100, 0x03ab: 0x1100, 0x03ac: 0x9900, 0x03ad: 0x1100, 0x03ae: 0x9900, 0x03af: 0x1100, + 0x03b0: 0x1100, 0x03b1: 0x8800, 0x03b5: 0x8800, + 0x03b7: 0x8800, 0x03b9: 0x8800, + 0x03bf: 0x8800, + // Block 0xf, offset 0x3c0 + 0x03c1: 0x8800, 0x03c5: 0x8800, + 0x03c9: 0x8800, 0x03ca: 0x9900, 0x03cb: 0x9900, + 0x03cc: 0x1100, 0x03cd: 0x1100, 0x03ce: 0x9900, 0x03d0: 0x3000, 0x03d1: 0x3000, + 0x03d2: 0x3800, 0x03d3: 0x3100, 0x03d4: 0x3100, 0x03d5: 0x3000, 0x03d6: 0x3000, + 0x03f0: 0x3000, 0x03f1: 0x3000, 0x03f2: 0x3000, 0x03f4: 0x3000, 0x03f5: 0x3000, + 0x03f9: 0x3000, + // Block 0x10, offset 0x400 + 0x0400: 0x1100, 0x0401: 0x1100, 0x0403: 0x1100, + 0x0406: 0x8800, 0x0407: 0x1100, + 0x040c: 0x1100, 0x040d: 0x1100, 0x040e: 0x1100, 0x0410: 0x8800, + 0x0413: 0x8800, 0x0415: 0x8800, 0x0416: 0x8800, 0x0417: 0x8800, + 0x0418: 0x8800, 0x0419: 0x1100, 0x041a: 0x8800, + 0x041e: 0x8800, 0x0423: 0x8800, + 0x0427: 0x8800, + 0x042b: 0x8800, 0x042d: 0x8800, + 0x0430: 0x8800, 0x0433: 0x8800, 0x0435: 0x8800, + 0x0436: 0x8800, 0x0437: 0x8800, 0x0438: 0x8800, 0x0439: 0x1100, 0x043a: 0x8800, + 0x043e: 0x8800, + // Block 0x11, offset 0x440 + 0x0443: 0x8800, + 0x0447: 0x8800, 0x044b: 0x8800, + 0x044d: 0x8800, 0x0450: 0x1100, 0x0451: 0x1100, + 0x0453: 0x1100, 0x0456: 0x8800, 0x0457: 0x1100, + 0x045c: 0x1100, 0x045d: 0x1100, + 0x045e: 0x1100, + 0x0474: 0x8800, 0x0475: 0x8800, + 0x0476: 0x1100, 0x0477: 0x1100, + // Block 0x12, offset 0x480 + 0x0483: 0x00e6, 0x0484: 0x00e6, 0x0485: 0x00e6, + 0x0486: 0x00e6, 0x0487: 0x00e6, + // Block 0x13, offset 0x4c0 + 0x04c1: 0x1100, 0x04c2: 0x1100, + 0x04d0: 0x1100, 0x04d1: 0x1100, + 0x04d2: 0x1100, 0x04d3: 0x1100, 0x04d6: 0x1100, 0x04d7: 0x1100, + 0x04d8: 0x8800, 0x04d9: 0x8800, 0x04da: 0x1100, 0x04db: 0x1100, 0x04dc: 0x1100, 0x04dd: 0x1100, + 0x04de: 0x1100, 0x04df: 0x1100, 0x04e2: 0x1100, 0x04e3: 0x1100, + 0x04e4: 0x1100, 0x04e5: 0x1100, 0x04e6: 0x1100, 0x04e7: 0x1100, 0x04e8: 0x8800, 0x04e9: 0x8800, + 0x04ea: 0x1100, 0x04eb: 0x1100, 0x04ec: 0x1100, 0x04ed: 0x1100, 0x04ee: 0x1100, 0x04ef: 0x1100, + 0x04f0: 0x1100, 0x04f1: 0x1100, 0x04f2: 0x1100, 0x04f3: 0x1100, 0x04f4: 0x1100, 0x04f5: 0x1100, + 0x04f8: 0x1100, 0x04f9: 0x1100, + // Block 0x14, offset 0x500 + 0x0507: 0x3000, + 0x0511: 0x00dc, + 0x0512: 0x00e6, 0x0513: 0x00e6, 0x0514: 0x00e6, 0x0515: 0x00e6, 0x0516: 0x00dc, 0x0517: 0x00e6, + 0x0518: 0x00e6, 0x0519: 0x00e6, 0x051a: 0x00de, 0x051b: 0x00dc, 0x051c: 0x00e6, 0x051d: 0x00e6, + 0x051e: 0x00e6, 0x051f: 0x00e6, 0x0520: 0x00e6, 0x0521: 0x00e6, 0x0522: 0x00dc, 0x0523: 0x00dc, + 0x0524: 0x00dc, 0x0525: 0x00dc, 0x0526: 0x00dc, 0x0527: 0x00dc, 0x0528: 0x00e6, 0x0529: 0x00e6, + 0x052a: 0x00dc, 0x052b: 0x00e6, 0x052c: 0x00e6, 0x052d: 0x00de, 0x052e: 0x00e4, 0x052f: 0x00e6, + 0x0530: 0x000a, 0x0531: 0x000b, 0x0532: 0x000c, 0x0533: 0x000d, 0x0534: 0x000e, 0x0535: 0x000f, + 0x0536: 0x0010, 0x0537: 0x0011, 0x0538: 0x0012, 0x0539: 0x0013, 0x053a: 0x0013, 0x053b: 0x0014, + 0x053c: 0x0015, 0x053d: 0x0016, 0x053f: 0x0017, + // Block 0x15, offset 0x540 + 0x0541: 0x0018, 0x0542: 0x0019, 0x0544: 0x00e6, 0x0545: 0x00dc, + 0x0547: 0x0012, + // Block 0x16, offset 0x580 + 0x0590: 0x00e6, 0x0591: 0x00e6, + 0x0592: 0x00e6, 0x0593: 0x00e6, 0x0594: 0x00e6, 0x0595: 0x00e6, 0x0596: 0x00e6, 0x0597: 0x00e6, + 0x0598: 0x001e, 0x0599: 0x001f, 0x059a: 0x0020, + 0x05a2: 0x1100, 0x05a3: 0x1100, + 0x05a4: 0x1100, 0x05a5: 0x1100, 0x05a6: 0x1100, 0x05a7: 0x8800, + // Block 0x17, offset 0x5c0 + 0x05c8: 0x8800, 0x05ca: 0x8800, 0x05cb: 0x001b, + 0x05cc: 0x001c, 0x05cd: 0x001d, 0x05ce: 0x001e, 0x05cf: 0x001f, 0x05d0: 0x0020, 0x05d1: 0x0021, + 0x05d2: 0x0022, 0x05d3: 0x66e6, 0x05d4: 0x66e6, 0x05d5: 0x66dc, 0x05d6: 0x00dc, 0x05d7: 0x00e6, + 0x05d8: 0x00e6, 0x05d9: 0x00e6, 0x05da: 0x00e6, 0x05db: 0x00e6, 0x05dc: 0x00dc, 0x05dd: 0x00e6, + 0x05de: 0x00e6, 0x05df: 0x00dc, + 0x05f0: 0x0023, 0x05f5: 0x3000, + 0x05f6: 0x3000, 0x05f7: 0x3000, 0x05f8: 0x3000, + // Block 0x18, offset 0x600 + 0x0600: 0x1100, 0x0601: 0x8800, 0x0602: 0x1100, + 0x0612: 0x8800, 0x0613: 0x1100, 0x0615: 0x8800, 0x0616: 0x00e6, 0x0617: 0x00e6, + 0x0618: 0x00e6, 0x0619: 0x00e6, 0x061a: 0x00e6, 0x061b: 0x00e6, 0x061c: 0x00e6, + 0x061f: 0x00e6, 0x0620: 0x00e6, 0x0621: 0x00e6, 0x0622: 0x00e6, 0x0623: 0x00dc, + 0x0624: 0x00e6, 0x0627: 0x00e6, 0x0628: 0x00e6, + 0x062a: 0x00dc, 0x062b: 0x00e6, 0x062c: 0x00e6, 0x062d: 0x00dc, + // Block 0x19, offset 0x640 + 0x0651: 0x0024, + 0x0670: 0x00e6, 0x0671: 0x00dc, 0x0672: 0x00e6, 0x0673: 0x00e6, 0x0674: 0x00dc, 0x0675: 0x00e6, + 0x0676: 0x00e6, 0x0677: 0x00dc, 0x0678: 0x00dc, 0x0679: 0x00dc, 0x067a: 0x00e6, 0x067b: 0x00dc, + 0x067c: 0x00dc, 0x067d: 0x00e6, 0x067e: 0x00dc, 0x067f: 0x00e6, + // Block 0x1a, offset 0x680 + 0x0680: 0x00e6, 0x0681: 0x00e6, 0x0682: 0x00dc, 0x0683: 0x00e6, 0x0684: 0x00dc, 0x0685: 0x00e6, + 0x0686: 0x00dc, 0x0687: 0x00e6, 0x0688: 0x00dc, 0x0689: 0x00e6, 0x068a: 0x00e6, + // Block 0x1b, offset 0x6c0 + 0x06eb: 0x00e6, 0x06ec: 0x00e6, 0x06ed: 0x00e6, 0x06ee: 0x00e6, 0x06ef: 0x00e6, + 0x06f0: 0x00e6, 0x06f1: 0x00e6, 0x06f2: 0x00dc, 0x06f3: 0x00e6, + // Block 0x1c, offset 0x700 + 0x0716: 0x00e6, 0x0717: 0x00e6, + 0x0718: 0x00e6, 0x0719: 0x00e6, 0x071b: 0x00e6, 0x071c: 0x00e6, 0x071d: 0x00e6, + 0x071e: 0x00e6, 0x071f: 0x00e6, 0x0720: 0x00e6, 0x0721: 0x00e6, 0x0722: 0x00e6, 0x0723: 0x00e6, + 0x0725: 0x00e6, 0x0726: 0x00e6, 0x0727: 0x00e6, 0x0729: 0x00e6, + 0x072a: 0x00e6, 0x072b: 0x00e6, 0x072c: 0x00e6, 0x072d: 0x00e6, + // Block 0x1d, offset 0x740 + 0x0759: 0x00dc, 0x075a: 0x00dc, 0x075b: 0x00dc, + // Block 0x1e, offset 0x780 + 0x07a8: 0x8800, 0x07a9: 0x1100, + 0x07b0: 0x8800, 0x07b1: 0x1100, 0x07b3: 0x8800, 0x07b4: 0x1100, + 0x07bc: 0x6607, + // Block 0x1f, offset 0x7c0 + 0x07cd: 0x0009, 0x07d1: 0x00e6, + 0x07d2: 0x00dc, 0x07d3: 0x00e6, 0x07d4: 0x00e6, + 0x07d8: 0x3300, 0x07d9: 0x3300, 0x07da: 0x3300, 0x07db: 0x3300, 0x07dc: 0x3300, 0x07dd: 0x3300, + 0x07de: 0x3300, 0x07df: 0x3300, + // Block 0x20, offset 0x800 + 0x083c: 0x0007, 0x083e: 0x6600, + // Block 0x21, offset 0x840 + 0x0847: 0x8800, 0x084b: 0x1100, + 0x084c: 0x1100, 0x084d: 0x0009, + 0x0857: 0x6600, + 0x085c: 0x3300, 0x085d: 0x3300, + 0x085f: 0x3300, + // Block 0x22, offset 0x880 + 0x08b3: 0x3300, + 0x08b6: 0x3300, + 0x08bc: 0x0007, + // Block 0x23, offset 0x8c0 + 0x08cd: 0x0009, + 0x08d9: 0x3300, 0x08da: 0x3300, 0x08db: 0x3300, + 0x08de: 0x3300, + // Block 0x24, offset 0x900 + 0x093c: 0x0007, + // Block 0x25, offset 0x940 + 0x094d: 0x0009, + // Block 0x26, offset 0x980 + 0x0987: 0x8800, 0x0988: 0x1100, 0x098b: 0x1100, + 0x098c: 0x1100, 0x098d: 0x0009, + 0x0996: 0x6600, 0x0997: 0x6600, + 0x099c: 0x3300, 0x099d: 0x3300, + // Block 0x27, offset 0x9c0 + 0x09d2: 0x8800, 0x09d4: 0x1100, + 0x09fe: 0x6600, + // Block 0x28, offset 0xa00 + 0x0a06: 0x8800, 0x0a07: 0x8800, 0x0a0a: 0x1100, 0x0a0b: 0x1100, + 0x0a0c: 0x1100, 0x0a0d: 0x0009, + 0x0a17: 0x6600, + // Block 0x29, offset 0xa40 + 0x0a46: 0x8800, 0x0a48: 0x1100, + 0x0a4d: 0x0009, + 0x0a55: 0x0054, 0x0a56: 0x665b, + // Block 0x2a, offset 0xa80 + 0x0abc: 0x0007, 0x0abf: 0x8800, + // Block 0x2b, offset 0xac0 + 0x0ac0: 0x1100, 0x0ac2: 0x6600, + 0x0ac6: 0x8800, 0x0ac7: 0x1100, 0x0ac8: 0x1100, 0x0aca: 0x9900, 0x0acb: 0x1100, + 0x0acd: 0x0009, + 0x0ad5: 0x6600, 0x0ad6: 0x6600, + // Block 0x2c, offset 0xb00 + 0x0b3e: 0x6600, + // Block 0x2d, offset 0xb40 + 0x0b4a: 0x6609, + 0x0b4f: 0x6600, + 0x0b59: 0x8800, 0x0b5a: 0x1100, 0x0b5c: 0x9900, 0x0b5d: 0x1100, + 0x0b5e: 0x1100, 0x0b5f: 0x6600, + // Block 0x2e, offset 0xb80 + 0x0bb3: 0x3000, + 0x0bb8: 0x0067, 0x0bb9: 0x0067, 0x0bba: 0x0009, + // Block 0x2f, offset 0xbc0 + 0x0bc8: 0x006b, 0x0bc9: 0x006b, 0x0bca: 0x006b, 0x0bcb: 0x006b, + // Block 0x30, offset 0xc00 + 0x0c33: 0x3000, + 0x0c38: 0x0076, 0x0c39: 0x0076, + // Block 0x31, offset 0xc40 + 0x0c48: 0x007a, 0x0c49: 0x007a, 0x0c4a: 0x007a, 0x0c4b: 0x007a, + 0x0c5c: 0x3000, 0x0c5d: 0x3000, + // Block 0x32, offset 0xc80 + 0x0c8c: 0x3000, + 0x0c98: 0x00dc, 0x0c99: 0x00dc, + 0x0cb5: 0x00dc, + 0x0cb7: 0x00dc, 0x0cb9: 0x00d8, + // Block 0x33, offset 0xcc0 + 0x0cc3: 0x3300, + 0x0ccd: 0x3300, + 0x0cd2: 0x3300, 0x0cd7: 0x3300, + 0x0cdc: 0x3300, + 0x0ce9: 0x3300, + 0x0cf1: 0x0081, 0x0cf2: 0x0082, 0x0cf3: 0x3300, 0x0cf4: 0x0084, 0x0cf5: 0x3300, + 0x0cf6: 0x3300, 0x0cf7: 0x3000, 0x0cf8: 0x3300, 0x0cf9: 0x3000, 0x0cfa: 0x0082, 0x0cfb: 0x0082, + 0x0cfc: 0x0082, 0x0cfd: 0x0082, + // Block 0x34, offset 0xd00 + 0x0d00: 0x0082, 0x0d01: 0x3300, 0x0d02: 0x00e6, 0x0d03: 0x00e6, 0x0d04: 0x0009, + 0x0d06: 0x00e6, 0x0d07: 0x00e6, + 0x0d13: 0x3300, + 0x0d1d: 0x3300, + 0x0d22: 0x3300, + 0x0d27: 0x3300, + 0x0d2c: 0x3300, + 0x0d39: 0x3300, + // Block 0x35, offset 0xd40 + 0x0d46: 0x00dc, + // Block 0x36, offset 0xd80 + 0x0da5: 0x8800, 0x0da6: 0x1100, + 0x0dae: 0x6600, + 0x0db7: 0x0007, 0x0db9: 0x0009, 0x0dba: 0x0009, + // Block 0x37, offset 0xdc0 + 0x0dcd: 0x00dc, + // Block 0x38, offset 0xe00 + 0x0e3c: 0x3000, + // Block 0x39, offset 0xe40 + 0x0e61: 0x6600, 0x0e62: 0x6600, 0x0e63: 0x6600, + 0x0e64: 0x6600, 0x0e65: 0x6600, 0x0e66: 0x6600, 0x0e67: 0x6600, 0x0e68: 0x6600, 0x0e69: 0x6600, + 0x0e6a: 0x6600, 0x0e6b: 0x6600, 0x0e6c: 0x6600, 0x0e6d: 0x6600, 0x0e6e: 0x6600, 0x0e6f: 0x6600, + 0x0e70: 0x6600, 0x0e71: 0x6600, 0x0e72: 0x6600, 0x0e73: 0x6600, 0x0e74: 0x6600, 0x0e75: 0x6600, + // Block 0x3a, offset 0xe80 + 0x0ea8: 0x6600, 0x0ea9: 0x6600, + 0x0eaa: 0x6600, 0x0eab: 0x6600, 0x0eac: 0x6600, 0x0ead: 0x6600, 0x0eae: 0x6600, 0x0eaf: 0x6600, + 0x0eb0: 0x6600, 0x0eb1: 0x6600, 0x0eb2: 0x6600, 0x0eb3: 0x6600, 0x0eb4: 0x6600, 0x0eb5: 0x6600, + 0x0eb6: 0x6600, 0x0eb7: 0x6600, 0x0eb8: 0x6600, 0x0eb9: 0x6600, 0x0eba: 0x6600, 0x0ebb: 0x6600, + 0x0ebc: 0x6600, 0x0ebd: 0x6600, 0x0ebe: 0x6600, 0x0ebf: 0x6600, + // Block 0x3b, offset 0xec0 + 0x0ec0: 0x6600, 0x0ec1: 0x6600, 0x0ec2: 0x6600, + // Block 0x3c, offset 0xf00 + 0x0f1d: 0x00e6, + 0x0f1e: 0x00e6, 0x0f1f: 0x00e6, + // Block 0x3d, offset 0xf40 + 0x0f54: 0x0009, + 0x0f74: 0x0009, + // Block 0x3e, offset 0xf80 + 0x0f92: 0x0009, + 0x0f9d: 0x00e6, + // Block 0x3f, offset 0xfc0 + 0x0fe9: 0x00e4, + // Block 0x40, offset 0x1000 + 0x1039: 0x00de, 0x103a: 0x00e6, 0x103b: 0x00dc, + // Block 0x41, offset 0x1040 + 0x1057: 0x00e6, + 0x1058: 0x00dc, + // Block 0x42, offset 0x1080 + 0x10a0: 0x0009, + 0x10b5: 0x00e6, + 0x10b6: 0x00e6, 0x10b7: 0x00e6, 0x10b8: 0x00e6, 0x10b9: 0x00e6, 0x10ba: 0x00e6, 0x10bb: 0x00e6, + 0x10bc: 0x00e6, 0x10bf: 0x00dc, + // Block 0x43, offset 0x10c0 + 0x10c5: 0x8800, + 0x10c6: 0x1100, 0x10c7: 0x8800, 0x10c8: 0x1100, 0x10c9: 0x8800, 0x10ca: 0x1100, 0x10cb: 0x8800, + 0x10cc: 0x1100, 0x10cd: 0x8800, 0x10ce: 0x1100, 0x10d1: 0x8800, + 0x10d2: 0x1100, + 0x10f4: 0x0007, 0x10f5: 0x6600, + 0x10fa: 0x8800, 0x10fb: 0x1100, + 0x10fc: 0x8800, 0x10fd: 0x1100, 0x10fe: 0x8800, 0x10ff: 0x8800, + // Block 0x44, offset 0x1100 + 0x1100: 0x1100, 0x1101: 0x1100, 0x1102: 0x8800, 0x1103: 0x1100, 0x1104: 0x0009, + 0x112b: 0x00e6, 0x112c: 0x00dc, 0x112d: 0x00e6, 0x112e: 0x00e6, 0x112f: 0x00e6, + 0x1130: 0x00e6, 0x1131: 0x00e6, 0x1132: 0x00e6, 0x1133: 0x00e6, + // Block 0x45, offset 0x1140 + 0x116a: 0x0009, + // Block 0x46, offset 0x1180 + 0x11a6: 0x0007, + 0x11b2: 0x0009, 0x11b3: 0x0009, + // Block 0x47, offset 0x11c0 + 0x11f7: 0x0007, + // Block 0x48, offset 0x1200 + 0x1210: 0x00e6, 0x1211: 0x00e6, + 0x1212: 0x00e6, 0x1214: 0x0001, 0x1215: 0x00dc, 0x1216: 0x00dc, 0x1217: 0x00dc, + 0x1218: 0x00dc, 0x1219: 0x00dc, 0x121a: 0x00e6, 0x121b: 0x00e6, 0x121c: 0x00dc, 0x121d: 0x00dc, + 0x121e: 0x00dc, 0x121f: 0x00dc, 0x1220: 0x00e6, 0x1222: 0x0001, 0x1223: 0x0001, + 0x1224: 0x0001, 0x1225: 0x0001, 0x1226: 0x0001, 0x1227: 0x0001, 0x1228: 0x0001, + 0x122d: 0x00dc, + // Block 0x49, offset 0x1240 + 0x126c: 0x3000, 0x126d: 0x3000, 0x126e: 0x3000, + 0x1270: 0x3000, 0x1271: 0x3000, 0x1272: 0x3000, 0x1273: 0x3000, 0x1274: 0x3000, 0x1275: 0x3000, + 0x1276: 0x3000, 0x1277: 0x3000, 0x1278: 0x3000, 0x1279: 0x3000, 0x127a: 0x3000, + 0x127c: 0x3000, 0x127d: 0x3000, 0x127e: 0x3000, 0x127f: 0x3000, + // Block 0x4a, offset 0x1280 + 0x1280: 0x3000, 0x1281: 0x3000, 0x1282: 0x3000, 0x1283: 0x3000, 0x1284: 0x3000, 0x1285: 0x3000, + 0x1286: 0x3000, 0x1287: 0x3000, 0x1288: 0x3000, 0x1289: 0x3000, 0x128a: 0x3000, 0x128b: 0x3000, + 0x128c: 0x3000, 0x128d: 0x3000, 0x128f: 0x3000, 0x1290: 0x3000, 0x1291: 0x3000, + 0x1292: 0x3000, 0x1293: 0x3000, 0x1294: 0x3000, 0x1295: 0x3000, 0x1296: 0x3000, 0x1297: 0x3000, + 0x1298: 0x3000, 0x1299: 0x3000, 0x129a: 0x3000, 0x129b: 0x3000, 0x129c: 0x3000, 0x129d: 0x3000, + 0x129e: 0x3000, 0x129f: 0x3000, 0x12a0: 0x3000, 0x12a1: 0x3000, 0x12a2: 0x3000, 0x12a3: 0x3000, + 0x12a4: 0x3000, 0x12a5: 0x3000, 0x12a6: 0x3000, 0x12a7: 0x3000, 0x12a8: 0x3000, 0x12a9: 0x3000, + 0x12aa: 0x3000, + 0x12b8: 0x3000, + // Block 0x4b, offset 0x12c0 + 0x12db: 0x3000, 0x12dc: 0x3000, 0x12dd: 0x3000, + 0x12de: 0x3000, 0x12df: 0x3000, 0x12e0: 0x3000, 0x12e1: 0x3000, 0x12e2: 0x3000, 0x12e3: 0x3000, + 0x12e4: 0x3000, 0x12e5: 0x3000, 0x12e6: 0x3000, 0x12e7: 0x3000, 0x12e8: 0x3000, 0x12e9: 0x3000, + 0x12ea: 0x3000, 0x12eb: 0x3000, 0x12ec: 0x3000, 0x12ed: 0x3000, 0x12ee: 0x3000, 0x12ef: 0x3000, + 0x12f0: 0x3000, 0x12f1: 0x3000, 0x12f2: 0x3000, 0x12f3: 0x3000, 0x12f4: 0x3000, 0x12f5: 0x3000, + 0x12f6: 0x3000, 0x12f7: 0x3000, 0x12f8: 0x3000, 0x12f9: 0x3000, 0x12fa: 0x3000, 0x12fb: 0x3000, + 0x12fc: 0x3000, 0x12fd: 0x3000, 0x12fe: 0x3000, 0x12ff: 0x3000, + // Block 0x4c, offset 0x1300 + 0x1300: 0x00e6, 0x1301: 0x00e6, 0x1302: 0x00dc, 0x1303: 0x00e6, 0x1304: 0x00e6, 0x1305: 0x00e6, + 0x1306: 0x00e6, 0x1307: 0x00e6, 0x1308: 0x00e6, 0x1309: 0x00e6, 0x130a: 0x00dc, 0x130b: 0x00e6, + 0x130c: 0x00e6, 0x130d: 0x00ea, 0x130e: 0x00d6, 0x130f: 0x00dc, 0x1310: 0x00ca, 0x1311: 0x00e6, + 0x1312: 0x00e6, 0x1313: 0x00e6, 0x1314: 0x00e6, 0x1315: 0x00e6, 0x1316: 0x00e6, 0x1317: 0x00e6, + 0x1318: 0x00e6, 0x1319: 0x00e6, 0x131a: 0x00e6, 0x131b: 0x00e6, 0x131c: 0x00e6, 0x131d: 0x00e6, + 0x131e: 0x00e6, 0x131f: 0x00e6, 0x1320: 0x00e6, 0x1321: 0x00e6, 0x1322: 0x00e6, 0x1323: 0x00e6, + 0x1324: 0x00e6, 0x1325: 0x00e6, 0x1326: 0x00e6, + 0x133c: 0x00e9, 0x133d: 0x00dc, 0x133e: 0x00e6, 0x133f: 0x00dc, + // Block 0x4d, offset 0x1340 + 0x1340: 0x1100, 0x1341: 0x1100, 0x1342: 0x1100, 0x1343: 0x1100, 0x1344: 0x1100, 0x1345: 0x1100, + 0x1346: 0x1100, 0x1347: 0x1100, 0x1348: 0x1100, 0x1349: 0x1100, 0x134a: 0x1100, 0x134b: 0x1100, + 0x134c: 0x1100, 0x134d: 0x1100, 0x134e: 0x1100, 0x134f: 0x1100, 0x1350: 0x1100, 0x1351: 0x1100, + 0x1352: 0x1100, 0x1353: 0x1100, 0x1354: 0x1100, 0x1355: 0x1100, 0x1356: 0x1100, 0x1357: 0x1100, + 0x1358: 0x1100, 0x1359: 0x1100, 0x135a: 0x1100, 0x135b: 0x1100, 0x135c: 0x1100, 0x135d: 0x1100, + 0x135e: 0x1100, 0x135f: 0x1100, 0x1360: 0x1100, 0x1361: 0x1100, 0x1362: 0x1100, 0x1363: 0x1100, + 0x1364: 0x1100, 0x1365: 0x1100, 0x1366: 0x1100, 0x1367: 0x1100, 0x1368: 0x1100, 0x1369: 0x1100, + 0x136a: 0x1100, 0x136b: 0x1100, 0x136c: 0x1100, 0x136d: 0x1100, 0x136e: 0x1100, 0x136f: 0x1100, + 0x1370: 0x1100, 0x1371: 0x1100, 0x1372: 0x1100, 0x1373: 0x1100, 0x1374: 0x1100, 0x1375: 0x1100, + 0x1376: 0x9900, 0x1377: 0x9900, 0x1378: 0x1100, 0x1379: 0x1100, 0x137a: 0x1100, 0x137b: 0x1100, + 0x137c: 0x1100, 0x137d: 0x1100, 0x137e: 0x1100, 0x137f: 0x1100, + // Block 0x4e, offset 0x1380 + 0x1380: 0x1100, 0x1381: 0x1100, 0x1382: 0x1100, 0x1383: 0x1100, 0x1384: 0x1100, 0x1385: 0x1100, + 0x1386: 0x1100, 0x1387: 0x1100, 0x1388: 0x1100, 0x1389: 0x1100, 0x138a: 0x1100, 0x138b: 0x1100, + 0x138c: 0x1100, 0x138d: 0x1100, 0x138e: 0x1100, 0x138f: 0x1100, 0x1390: 0x1100, 0x1391: 0x1100, + 0x1392: 0x1100, 0x1393: 0x1100, 0x1394: 0x1100, 0x1395: 0x1100, 0x1396: 0x1100, 0x1397: 0x1100, + 0x1398: 0x1100, 0x1399: 0x1100, 0x139a: 0x9900, 0x139b: 0x9900, 0x139c: 0x1100, 0x139d: 0x1100, + 0x139e: 0x1100, 0x139f: 0x1100, 0x13a0: 0x1100, 0x13a1: 0x1100, 0x13a2: 0x9900, 0x13a3: 0x9900, + 0x13a4: 0x1100, 0x13a5: 0x1100, 0x13a6: 0x1100, 0x13a7: 0x1100, 0x13a8: 0x1100, 0x13a9: 0x1100, + 0x13aa: 0x1100, 0x13ab: 0x1100, 0x13ac: 0x1100, 0x13ad: 0x1100, 0x13ae: 0x1100, 0x13af: 0x1100, + 0x13b0: 0x1100, 0x13b1: 0x1100, 0x13b2: 0x1100, 0x13b3: 0x1100, 0x13b4: 0x1100, 0x13b5: 0x1100, + 0x13b6: 0x1100, 0x13b7: 0x1100, 0x13b8: 0x1100, 0x13b9: 0x1100, 0x13ba: 0x1100, 0x13bb: 0x1100, + 0x13bc: 0x1100, 0x13bd: 0x1100, 0x13be: 0x1100, 0x13bf: 0x1100, + // Block 0x4f, offset 0x13c0 + 0x13c0: 0x1100, 0x13c1: 0x1100, 0x13c2: 0x1100, 0x13c3: 0x1100, 0x13c4: 0x1100, 0x13c5: 0x1100, + 0x13c6: 0x1100, 0x13c7: 0x1100, 0x13c8: 0x1100, 0x13c9: 0x1100, 0x13ca: 0x1100, 0x13cb: 0x1100, + 0x13cc: 0x1100, 0x13cd: 0x1100, 0x13ce: 0x1100, 0x13cf: 0x1100, 0x13d0: 0x1100, 0x13d1: 0x1100, + 0x13d2: 0x1100, 0x13d3: 0x1100, 0x13d4: 0x1100, 0x13d5: 0x1100, 0x13d6: 0x1100, 0x13d7: 0x1100, + 0x13d8: 0x1100, 0x13d9: 0x1100, 0x13da: 0x3000, 0x13db: 0x3100, + 0x13e0: 0x9900, 0x13e1: 0x9900, 0x13e2: 0x1100, 0x13e3: 0x1100, + 0x13e4: 0x1100, 0x13e5: 0x1100, 0x13e6: 0x1100, 0x13e7: 0x1100, 0x13e8: 0x1100, 0x13e9: 0x1100, + 0x13ea: 0x1100, 0x13eb: 0x1100, 0x13ec: 0x1100, 0x13ed: 0x1100, 0x13ee: 0x1100, 0x13ef: 0x1100, + 0x13f0: 0x1100, 0x13f1: 0x1100, 0x13f2: 0x1100, 0x13f3: 0x1100, 0x13f4: 0x1100, 0x13f5: 0x1100, + 0x13f6: 0x1100, 0x13f7: 0x1100, 0x13f8: 0x9900, 0x13f9: 0x9900, 0x13fa: 0x1100, 0x13fb: 0x1100, + 0x13fc: 0x1100, 0x13fd: 0x1100, 0x13fe: 0x1100, 0x13ff: 0x1100, + // Block 0x50, offset 0x1400 + 0x1400: 0x1100, 0x1401: 0x1100, 0x1402: 0x1100, 0x1403: 0x1100, 0x1404: 0x1100, 0x1405: 0x1100, + 0x1406: 0x1100, 0x1407: 0x1100, 0x1408: 0x1100, 0x1409: 0x1100, 0x140a: 0x1100, 0x140b: 0x1100, + 0x140c: 0x9900, 0x140d: 0x9900, 0x140e: 0x1100, 0x140f: 0x1100, 0x1410: 0x1100, 0x1411: 0x1100, + 0x1412: 0x1100, 0x1413: 0x1100, 0x1414: 0x1100, 0x1415: 0x1100, 0x1416: 0x1100, 0x1417: 0x1100, + 0x1418: 0x1100, 0x1419: 0x1100, 0x141a: 0x1100, 0x141b: 0x1100, 0x141c: 0x1100, 0x141d: 0x1100, + 0x141e: 0x1100, 0x141f: 0x1100, 0x1420: 0x1100, 0x1421: 0x1100, 0x1422: 0x1100, 0x1423: 0x1100, + 0x1424: 0x1100, 0x1425: 0x1100, 0x1426: 0x1100, 0x1427: 0x1100, 0x1428: 0x1100, 0x1429: 0x1100, + 0x142a: 0x1100, 0x142b: 0x1100, 0x142c: 0x1100, 0x142d: 0x1100, 0x142e: 0x1100, 0x142f: 0x1100, + 0x1430: 0x1100, 0x1431: 0x1100, 0x1432: 0x1100, 0x1433: 0x1100, 0x1434: 0x1100, 0x1435: 0x1100, + 0x1436: 0x1100, 0x1437: 0x1100, 0x1438: 0x1100, 0x1439: 0x1100, + // Block 0x51, offset 0x1440 + 0x1440: 0x9900, 0x1441: 0x9900, 0x1442: 0x9900, 0x1443: 0x9900, 0x1444: 0x9900, 0x1445: 0x9900, + 0x1446: 0x9900, 0x1447: 0x9900, 0x1448: 0x9900, 0x1449: 0x9900, 0x144a: 0x9900, 0x144b: 0x9900, + 0x144c: 0x9900, 0x144d: 0x9900, 0x144e: 0x9900, 0x144f: 0x9900, 0x1450: 0x9900, 0x1451: 0x9900, + 0x1452: 0x1100, 0x1453: 0x1100, 0x1454: 0x1100, 0x1455: 0x1100, + 0x1458: 0x9900, 0x1459: 0x9900, 0x145a: 0x1100, 0x145b: 0x1100, 0x145c: 0x1100, 0x145d: 0x1100, + 0x1460: 0x9900, 0x1461: 0x9900, 0x1462: 0x9900, 0x1463: 0x9900, + 0x1464: 0x9900, 0x1465: 0x9900, 0x1466: 0x9900, 0x1467: 0x9900, 0x1468: 0x9900, 0x1469: 0x9900, + 0x146a: 0x9900, 0x146b: 0x9900, 0x146c: 0x9900, 0x146d: 0x9900, 0x146e: 0x9900, 0x146f: 0x9900, + 0x1470: 0x9900, 0x1471: 0x9900, 0x1472: 0x1100, 0x1473: 0x1100, 0x1474: 0x1100, 0x1475: 0x1100, + 0x1476: 0x1100, 0x1477: 0x1100, 0x1478: 0x9900, 0x1479: 0x9900, 0x147a: 0x1100, 0x147b: 0x1100, + 0x147c: 0x1100, 0x147d: 0x1100, 0x147e: 0x1100, 0x147f: 0x1100, + // Block 0x52, offset 0x1480 + 0x1480: 0x9900, 0x1481: 0x9900, 0x1482: 0x1100, 0x1483: 0x1100, 0x1484: 0x1100, 0x1485: 0x1100, + 0x1488: 0x9900, 0x1489: 0x9900, 0x148a: 0x1100, 0x148b: 0x1100, + 0x148c: 0x1100, 0x148d: 0x1100, 0x1490: 0x9900, 0x1491: 0x9900, + 0x1492: 0x1100, 0x1493: 0x1100, 0x1494: 0x1100, 0x1495: 0x1100, 0x1496: 0x1100, 0x1497: 0x1100, + 0x1499: 0x9900, 0x149b: 0x1100, 0x149d: 0x1100, + 0x149f: 0x1100, 0x14a0: 0x9900, 0x14a1: 0x9900, 0x14a2: 0x9900, 0x14a3: 0x9900, + 0x14a4: 0x9900, 0x14a5: 0x9900, 0x14a6: 0x9900, 0x14a7: 0x9900, 0x14a8: 0x9900, 0x14a9: 0x9900, + 0x14aa: 0x9900, 0x14ab: 0x9900, 0x14ac: 0x9900, 0x14ad: 0x9900, 0x14ae: 0x9900, 0x14af: 0x9900, + 0x14b0: 0x9900, 0x14b1: 0x3300, 0x14b2: 0x1100, 0x14b3: 0x3300, 0x14b4: 0x9900, 0x14b5: 0x3300, + 0x14b6: 0x1100, 0x14b7: 0x3300, 0x14b8: 0x1100, 0x14b9: 0x3300, 0x14ba: 0x1100, 0x14bb: 0x3300, + 0x14bc: 0x9900, 0x14bd: 0x3300, + // Block 0x53, offset 0x14c0 + 0x14c0: 0x1100, 0x14c1: 0x1100, 0x14c2: 0x1100, 0x14c3: 0x1100, 0x14c4: 0x1100, 0x14c5: 0x1100, + 0x14c6: 0x1100, 0x14c7: 0x1100, 0x14c8: 0x1100, 0x14c9: 0x1100, 0x14ca: 0x1100, 0x14cb: 0x1100, + 0x14cc: 0x1100, 0x14cd: 0x1100, 0x14ce: 0x1100, 0x14cf: 0x1100, 0x14d0: 0x1100, 0x14d1: 0x1100, + 0x14d2: 0x1100, 0x14d3: 0x1100, 0x14d4: 0x1100, 0x14d5: 0x1100, 0x14d6: 0x1100, 0x14d7: 0x1100, + 0x14d8: 0x1100, 0x14d9: 0x1100, 0x14da: 0x1100, 0x14db: 0x1100, 0x14dc: 0x1100, 0x14dd: 0x1100, + 0x14de: 0x1100, 0x14df: 0x1100, 0x14e0: 0x1100, 0x14e1: 0x1100, 0x14e2: 0x1100, 0x14e3: 0x1100, + 0x14e4: 0x1100, 0x14e5: 0x1100, 0x14e6: 0x1100, 0x14e7: 0x1100, 0x14e8: 0x1100, 0x14e9: 0x1100, + 0x14ea: 0x1100, 0x14eb: 0x1100, 0x14ec: 0x1100, 0x14ed: 0x1100, 0x14ee: 0x1100, 0x14ef: 0x1100, + 0x14f0: 0x1100, 0x14f1: 0x1100, 0x14f2: 0x1100, 0x14f3: 0x1100, 0x14f4: 0x1100, + 0x14f6: 0x9900, 0x14f7: 0x1100, 0x14f8: 0x1100, 0x14f9: 0x1100, 0x14fa: 0x1100, 0x14fb: 0x3300, + 0x14fc: 0x1100, 0x14fd: 0x3000, 0x14fe: 0x3300, 0x14ff: 0x3800, + // Block 0x54, offset 0x1500 + 0x1500: 0x3000, 0x1501: 0x3100, 0x1502: 0x1100, 0x1503: 0x1100, 0x1504: 0x1100, + 0x1506: 0x9900, 0x1507: 0x1100, 0x1508: 0x1100, 0x1509: 0x3300, 0x150a: 0x1100, 0x150b: 0x3300, + 0x150c: 0x1100, 0x150d: 0x3100, 0x150e: 0x3100, 0x150f: 0x3100, 0x1510: 0x1100, 0x1511: 0x1100, + 0x1512: 0x1100, 0x1513: 0x3300, 0x1516: 0x1100, 0x1517: 0x1100, + 0x1518: 0x1100, 0x1519: 0x1100, 0x151a: 0x1100, 0x151b: 0x3300, 0x151d: 0x3100, + 0x151e: 0x3100, 0x151f: 0x3100, 0x1520: 0x1100, 0x1521: 0x1100, 0x1522: 0x1100, 0x1523: 0x3300, + 0x1524: 0x1100, 0x1525: 0x1100, 0x1526: 0x1100, 0x1527: 0x1100, 0x1528: 0x1100, 0x1529: 0x1100, + 0x152a: 0x1100, 0x152b: 0x3300, 0x152c: 0x1100, 0x152d: 0x3100, 0x152e: 0x3300, 0x152f: 0x3300, + 0x1532: 0x1100, 0x1533: 0x1100, 0x1534: 0x1100, + 0x1536: 0x9900, 0x1537: 0x1100, 0x1538: 0x1100, 0x1539: 0x3300, 0x153a: 0x1100, 0x153b: 0x3300, + 0x153c: 0x1100, 0x153d: 0x3300, 0x153e: 0x3800, + // Block 0x55, offset 0x1540 + 0x1540: 0x3300, 0x1541: 0x3300, 0x1542: 0x3000, 0x1543: 0x3000, 0x1544: 0x3000, 0x1545: 0x3000, + 0x1546: 0x3000, 0x1547: 0x3000, 0x1548: 0x3000, 0x1549: 0x3000, 0x154a: 0x3000, + 0x1551: 0x3000, + 0x1557: 0x3000, + 0x1564: 0x3000, 0x1565: 0x3000, 0x1566: 0x3000, + 0x156f: 0x3000, + 0x1573: 0x3000, 0x1574: 0x3000, + 0x1576: 0x3000, 0x1577: 0x3000, + 0x157c: 0x3000, 0x157e: 0x3000, + // Block 0x56, offset 0x1580 + 0x1587: 0x3000, 0x1588: 0x3000, 0x1589: 0x3000, + 0x1597: 0x3000, + 0x159f: 0x3000, + 0x15b0: 0x3000, 0x15b1: 0x3000, 0x15b4: 0x3000, 0x15b5: 0x3000, + 0x15b6: 0x3000, 0x15b7: 0x3000, 0x15b8: 0x3000, 0x15b9: 0x3000, 0x15ba: 0x3000, 0x15bb: 0x3000, + 0x15bc: 0x3000, 0x15bd: 0x3000, 0x15be: 0x3000, 0x15bf: 0x3000, + // Block 0x57, offset 0x15c0 + 0x15c0: 0x3000, 0x15c1: 0x3000, 0x15c2: 0x3000, 0x15c3: 0x3000, 0x15c4: 0x3000, 0x15c5: 0x3000, + 0x15c6: 0x3000, 0x15c7: 0x3000, 0x15c8: 0x3000, 0x15c9: 0x3000, 0x15ca: 0x3000, 0x15cb: 0x3000, + 0x15cc: 0x3000, 0x15cd: 0x3000, 0x15ce: 0x3000, 0x15d0: 0x3000, 0x15d1: 0x3000, + 0x15d2: 0x3000, 0x15d3: 0x3000, 0x15d4: 0x3000, 0x15d5: 0x3000, 0x15d6: 0x3000, 0x15d7: 0x3000, + 0x15d8: 0x3000, 0x15d9: 0x3000, 0x15da: 0x3000, 0x15db: 0x3000, 0x15dc: 0x3000, + 0x15e8: 0x3000, + // Block 0x58, offset 0x1600 + 0x1610: 0x00e6, 0x1611: 0x00e6, + 0x1612: 0x0001, 0x1613: 0x0001, 0x1614: 0x00e6, 0x1615: 0x00e6, 0x1616: 0x00e6, 0x1617: 0x00e6, + 0x1618: 0x0001, 0x1619: 0x0001, 0x161a: 0x0001, 0x161b: 0x00e6, 0x161c: 0x00e6, + 0x1621: 0x00e6, + 0x1625: 0x0001, 0x1626: 0x0001, 0x1627: 0x00e6, 0x1628: 0x00dc, 0x1629: 0x00e6, + 0x162a: 0x0001, 0x162b: 0x0001, 0x162c: 0x00dc, 0x162d: 0x00dc, 0x162e: 0x00dc, 0x162f: 0x00dc, + 0x1630: 0x00e6, + // Block 0x59, offset 0x1640 + 0x1640: 0x3000, 0x1641: 0x3000, 0x1642: 0x3000, 0x1643: 0x3000, 0x1645: 0x3000, + 0x1646: 0x3000, 0x1647: 0x3000, 0x1649: 0x3000, 0x164a: 0x3000, 0x164b: 0x3000, + 0x164c: 0x3000, 0x164d: 0x3000, 0x164e: 0x3000, 0x164f: 0x3000, 0x1650: 0x3000, 0x1651: 0x3000, + 0x1652: 0x3000, 0x1653: 0x3000, 0x1655: 0x3000, 0x1656: 0x3000, + 0x1659: 0x3000, 0x165a: 0x3000, 0x165b: 0x3000, 0x165c: 0x3000, 0x165d: 0x3000, + 0x1660: 0x3000, 0x1661: 0x3000, 0x1662: 0x3000, + 0x1664: 0x3000, 0x1666: 0x3300, 0x1668: 0x3000, + 0x166a: 0x3300, 0x166b: 0x3300, 0x166c: 0x3000, 0x166d: 0x3000, 0x166f: 0x3000, + 0x1670: 0x3000, 0x1671: 0x3000, 0x1673: 0x3000, 0x1674: 0x3000, 0x1675: 0x3000, + 0x1676: 0x3000, 0x1677: 0x3000, 0x1678: 0x3000, 0x1679: 0x3000, 0x167b: 0x3000, + 0x167c: 0x3000, 0x167d: 0x3000, 0x167e: 0x3000, 0x167f: 0x3000, + // Block 0x5a, offset 0x1680 + 0x1680: 0x3000, 0x1685: 0x3000, + 0x1686: 0x3000, 0x1687: 0x3000, 0x1688: 0x3000, 0x1689: 0x3000, + 0x1690: 0x3000, 0x1691: 0x3000, + 0x1692: 0x3000, 0x1693: 0x3000, 0x1694: 0x3000, 0x1695: 0x3000, 0x1696: 0x3000, 0x1697: 0x3000, + 0x1698: 0x3000, 0x1699: 0x3000, 0x169a: 0x3000, 0x169b: 0x3000, 0x169c: 0x3000, 0x169d: 0x3000, + 0x169e: 0x3000, 0x169f: 0x3000, 0x16a0: 0x3000, 0x16a1: 0x3000, 0x16a2: 0x3000, 0x16a3: 0x3000, + 0x16a4: 0x3000, 0x16a5: 0x3000, 0x16a6: 0x3000, 0x16a7: 0x3000, 0x16a8: 0x3000, 0x16a9: 0x3000, + 0x16aa: 0x3000, 0x16ab: 0x3000, 0x16ac: 0x3000, 0x16ad: 0x3000, 0x16ae: 0x3000, 0x16af: 0x3000, + 0x16b0: 0x3000, 0x16b1: 0x3000, 0x16b2: 0x3000, 0x16b3: 0x3000, 0x16b4: 0x3000, 0x16b5: 0x3000, + 0x16b6: 0x3000, 0x16b7: 0x3000, 0x16b8: 0x3000, 0x16b9: 0x3000, 0x16ba: 0x3000, 0x16bb: 0x3000, + 0x16bc: 0x3000, 0x16bd: 0x3000, 0x16be: 0x3000, 0x16bf: 0x3000, + // Block 0x5b, offset 0x16c0 + 0x16c9: 0x3000, + 0x16d0: 0x8800, + 0x16d2: 0x8800, 0x16d4: 0x8800, + 0x16da: 0x1100, 0x16db: 0x1100, + 0x16ee: 0x1100, + // Block 0x5c, offset 0x1700 + 0x170d: 0x1100, 0x170e: 0x1100, 0x170f: 0x1100, 0x1710: 0x8800, + 0x1712: 0x8800, 0x1714: 0x8800, + // Block 0x5d, offset 0x1740 + 0x1743: 0x8800, 0x1744: 0x1100, + 0x1748: 0x8800, 0x1749: 0x1100, 0x174b: 0x8800, + 0x174c: 0x1100, + 0x1763: 0x8800, + 0x1764: 0x1100, 0x1765: 0x8800, 0x1766: 0x1100, + 0x176c: 0x3000, 0x176d: 0x3000, 0x176f: 0x3000, + 0x1770: 0x3000, + 0x177c: 0x8800, + // Block 0x5e, offset 0x1780 + 0x1781: 0x1100, 0x1783: 0x8800, 0x1784: 0x1100, 0x1785: 0x8800, + 0x1787: 0x1100, 0x1788: 0x8800, 0x1789: 0x1100, + 0x178d: 0x8800, + 0x17a0: 0x1100, 0x17a1: 0x8800, 0x17a2: 0x1100, + 0x17a4: 0x8800, 0x17a5: 0x8800, + 0x17ad: 0x1100, 0x17ae: 0x1100, 0x17af: 0x1100, + 0x17b0: 0x1100, 0x17b1: 0x1100, 0x17b2: 0x8800, 0x17b3: 0x8800, 0x17b4: 0x1100, 0x17b5: 0x1100, + 0x17b6: 0x8800, 0x17b7: 0x8800, 0x17b8: 0x1100, 0x17b9: 0x1100, 0x17ba: 0x8800, 0x17bb: 0x8800, + 0x17bc: 0x8800, 0x17bd: 0x8800, + // Block 0x5f, offset 0x17c0 + 0x17c0: 0x1100, 0x17c1: 0x1100, 0x17c2: 0x8800, 0x17c3: 0x8800, 0x17c4: 0x1100, 0x17c5: 0x1100, + 0x17c6: 0x8800, 0x17c7: 0x8800, 0x17c8: 0x1100, 0x17c9: 0x1100, + 0x17d1: 0x8800, + 0x17d2: 0x8800, + 0x17e2: 0x8800, + 0x17e8: 0x8800, 0x17e9: 0x8800, + 0x17eb: 0x8800, 0x17ec: 0x1100, 0x17ed: 0x1100, 0x17ee: 0x1100, 0x17ef: 0x1100, + 0x17f2: 0x8800, 0x17f3: 0x8800, 0x17f4: 0x8800, 0x17f5: 0x8800, + // Block 0x60, offset 0x1800 + 0x1820: 0x1100, 0x1821: 0x1100, 0x1822: 0x1100, 0x1823: 0x1100, + 0x182a: 0x1100, 0x182b: 0x1100, 0x182c: 0x1100, 0x182d: 0x1100, + // Block 0x61, offset 0x1840 + 0x1869: 0x3300, + 0x186a: 0x3300, + // Block 0x62, offset 0x1880 + 0x18a0: 0x3000, 0x18a1: 0x3000, 0x18a2: 0x3000, 0x18a3: 0x3000, + 0x18a4: 0x3000, 0x18a5: 0x3000, 0x18a6: 0x3000, 0x18a7: 0x3000, 0x18a8: 0x3000, 0x18a9: 0x3000, + 0x18aa: 0x3000, 0x18ab: 0x3000, 0x18ac: 0x3000, 0x18ad: 0x3000, 0x18ae: 0x3000, 0x18af: 0x3000, + 0x18b0: 0x3000, 0x18b1: 0x3000, 0x18b2: 0x3000, 0x18b3: 0x3000, 0x18b4: 0x3000, 0x18b5: 0x3000, + 0x18b6: 0x3000, 0x18b7: 0x3000, 0x18b8: 0x3000, 0x18b9: 0x3000, 0x18ba: 0x3000, 0x18bb: 0x3000, + 0x18bc: 0x3000, 0x18bd: 0x3000, 0x18be: 0x3000, 0x18bf: 0x3000, + // Block 0x63, offset 0x18c0 + 0x18c0: 0x3000, 0x18c1: 0x3000, 0x18c2: 0x3000, 0x18c3: 0x3000, 0x18c4: 0x3000, 0x18c5: 0x3000, + 0x18c6: 0x3000, 0x18c7: 0x3000, 0x18c8: 0x3000, 0x18c9: 0x3000, 0x18ca: 0x3000, 0x18cb: 0x3000, + 0x18cc: 0x3000, 0x18cd: 0x3000, 0x18ce: 0x3000, 0x18cf: 0x3000, 0x18d0: 0x3000, 0x18d1: 0x3000, + 0x18d2: 0x3000, 0x18d3: 0x3000, 0x18d4: 0x3000, 0x18d5: 0x3000, 0x18d6: 0x3000, 0x18d7: 0x3000, + 0x18d8: 0x3000, 0x18d9: 0x3000, 0x18da: 0x3000, 0x18db: 0x3000, 0x18dc: 0x3000, 0x18dd: 0x3000, + 0x18de: 0x3000, 0x18df: 0x3000, 0x18e0: 0x3000, 0x18e1: 0x3000, 0x18e2: 0x3000, 0x18e3: 0x3000, + 0x18e4: 0x3000, 0x18e5: 0x3000, 0x18e6: 0x3000, 0x18e7: 0x3000, 0x18e8: 0x3000, 0x18e9: 0x3000, + 0x18ea: 0x3000, 0x18eb: 0x3000, 0x18ec: 0x3000, 0x18ed: 0x3000, 0x18ee: 0x3000, 0x18ef: 0x3000, + 0x18f0: 0x3000, 0x18f1: 0x3000, 0x18f2: 0x3000, 0x18f3: 0x3000, 0x18f4: 0x3000, 0x18f5: 0x3000, + 0x18f6: 0x3000, 0x18f7: 0x3000, 0x18f8: 0x3000, 0x18f9: 0x3000, 0x18fa: 0x3000, 0x18fb: 0x3000, + 0x18fc: 0x3000, 0x18fd: 0x3000, 0x18fe: 0x3000, 0x18ff: 0x3000, + // Block 0x64, offset 0x1900 + 0x1900: 0x3000, 0x1901: 0x3000, 0x1902: 0x3000, 0x1903: 0x3000, 0x1904: 0x3000, 0x1905: 0x3000, + 0x1906: 0x3000, 0x1907: 0x3000, 0x1908: 0x3000, 0x1909: 0x3000, 0x190a: 0x3000, 0x190b: 0x3000, + 0x190c: 0x3000, 0x190d: 0x3000, 0x190e: 0x3000, 0x190f: 0x3000, 0x1910: 0x3000, 0x1911: 0x3000, + 0x1912: 0x3000, 0x1913: 0x3000, 0x1914: 0x3000, 0x1915: 0x3000, 0x1916: 0x3000, 0x1917: 0x3000, + 0x1918: 0x3000, 0x1919: 0x3000, 0x191a: 0x3000, 0x191b: 0x3000, 0x191c: 0x3000, 0x191d: 0x3000, + 0x191e: 0x3000, 0x191f: 0x3000, 0x1920: 0x3000, 0x1921: 0x3000, 0x1922: 0x3000, 0x1923: 0x3000, + 0x1924: 0x3000, 0x1925: 0x3000, 0x1926: 0x3000, 0x1927: 0x3000, 0x1928: 0x3000, 0x1929: 0x3000, + 0x192a: 0x3000, + // Block 0x65, offset 0x1940 + 0x194c: 0x3000, + // Block 0x66, offset 0x1980 + 0x19b4: 0x3000, 0x19b5: 0x3000, + 0x19b6: 0x3000, + // Block 0x67, offset 0x19c0 + 0x19dc: 0x3300, + // Block 0x68, offset 0x1a00 + 0x1a3c: 0x3000, 0x1a3d: 0x3000, + // Block 0x69, offset 0x1a40 + 0x1a6f: 0x00e6, + 0x1a70: 0x00e6, 0x1a71: 0x00e6, + // Block 0x6a, offset 0x1a80 + 0x1aaf: 0x3000, + 0x1abf: 0x0009, + // Block 0x6b, offset 0x1ac0 + 0x1ae0: 0x00e6, 0x1ae1: 0x00e6, 0x1ae2: 0x00e6, 0x1ae3: 0x00e6, + 0x1ae4: 0x00e6, 0x1ae5: 0x00e6, 0x1ae6: 0x00e6, 0x1ae7: 0x00e6, 0x1ae8: 0x00e6, 0x1ae9: 0x00e6, + 0x1aea: 0x00e6, 0x1aeb: 0x00e6, 0x1aec: 0x00e6, 0x1aed: 0x00e6, 0x1aee: 0x00e6, 0x1aef: 0x00e6, + 0x1af0: 0x00e6, 0x1af1: 0x00e6, 0x1af2: 0x00e6, 0x1af3: 0x00e6, 0x1af4: 0x00e6, 0x1af5: 0x00e6, + 0x1af6: 0x00e6, 0x1af7: 0x00e6, 0x1af8: 0x00e6, 0x1af9: 0x00e6, 0x1afa: 0x00e6, 0x1afb: 0x00e6, + 0x1afc: 0x00e6, 0x1afd: 0x00e6, 0x1afe: 0x00e6, 0x1aff: 0x00e6, + // Block 0x6c, offset 0x1b00 + 0x1b1f: 0x3000, + // Block 0x6d, offset 0x1b40 + 0x1b73: 0x3000, + // Block 0x6e, offset 0x1b80 + 0x1b80: 0x3000, 0x1b81: 0x3000, 0x1b82: 0x3000, 0x1b83: 0x3000, 0x1b84: 0x3000, 0x1b85: 0x3000, + 0x1b86: 0x3000, 0x1b87: 0x3000, 0x1b88: 0x3000, 0x1b89: 0x3000, 0x1b8a: 0x3000, 0x1b8b: 0x3000, + 0x1b8c: 0x3000, 0x1b8d: 0x3000, 0x1b8e: 0x3000, 0x1b8f: 0x3000, 0x1b90: 0x3000, 0x1b91: 0x3000, + 0x1b92: 0x3000, 0x1b93: 0x3000, 0x1b94: 0x3000, 0x1b95: 0x3000, + // Block 0x6f, offset 0x1bc0 + 0x1bc0: 0x3000, + 0x1bea: 0x00da, 0x1beb: 0x00e4, 0x1bec: 0x00e8, 0x1bed: 0x00de, 0x1bee: 0x00e0, 0x1bef: 0x00e0, + 0x1bf6: 0x3000, 0x1bf8: 0x3000, 0x1bf9: 0x3000, 0x1bfa: 0x3000, + // Block 0x70, offset 0x1c00 + 0x1c06: 0x8800, 0x1c0b: 0x8800, + 0x1c0c: 0x1100, 0x1c0d: 0x8800, 0x1c0e: 0x1100, 0x1c0f: 0x8800, 0x1c10: 0x1100, 0x1c11: 0x8800, + 0x1c12: 0x1100, 0x1c13: 0x8800, 0x1c14: 0x1100, 0x1c15: 0x8800, 0x1c16: 0x1100, 0x1c17: 0x8800, + 0x1c18: 0x1100, 0x1c19: 0x8800, 0x1c1a: 0x1100, 0x1c1b: 0x8800, 0x1c1c: 0x1100, 0x1c1d: 0x8800, + 0x1c1e: 0x1100, 0x1c1f: 0x8800, 0x1c20: 0x1100, 0x1c21: 0x8800, 0x1c22: 0x1100, + 0x1c24: 0x8800, 0x1c25: 0x1100, 0x1c26: 0x8800, 0x1c27: 0x1100, 0x1c28: 0x8800, 0x1c29: 0x1100, + 0x1c2f: 0x8800, + 0x1c30: 0x1100, 0x1c31: 0x1100, 0x1c32: 0x8800, 0x1c33: 0x1100, 0x1c34: 0x1100, 0x1c35: 0x8800, + 0x1c36: 0x1100, 0x1c37: 0x1100, 0x1c38: 0x8800, 0x1c39: 0x1100, 0x1c3a: 0x1100, 0x1c3b: 0x8800, + 0x1c3c: 0x1100, 0x1c3d: 0x1100, + // Block 0x71, offset 0x1c40 + 0x1c54: 0x1100, + 0x1c59: 0x6608, 0x1c5a: 0x6608, 0x1c5b: 0x3000, 0x1c5c: 0x3000, 0x1c5d: 0x8800, + 0x1c5e: 0x1100, 0x1c5f: 0x3000, + 0x1c66: 0x8800, + 0x1c6b: 0x8800, 0x1c6c: 0x1100, 0x1c6d: 0x8800, 0x1c6e: 0x1100, 0x1c6f: 0x8800, + 0x1c70: 0x1100, 0x1c71: 0x8800, 0x1c72: 0x1100, 0x1c73: 0x8800, 0x1c74: 0x1100, 0x1c75: 0x8800, + 0x1c76: 0x1100, 0x1c77: 0x8800, 0x1c78: 0x1100, 0x1c79: 0x8800, 0x1c7a: 0x1100, 0x1c7b: 0x8800, + 0x1c7c: 0x1100, 0x1c7d: 0x8800, 0x1c7e: 0x1100, 0x1c7f: 0x8800, + // Block 0x72, offset 0x1c80 + 0x1c80: 0x1100, 0x1c81: 0x8800, 0x1c82: 0x1100, 0x1c84: 0x8800, 0x1c85: 0x1100, + 0x1c86: 0x8800, 0x1c87: 0x1100, 0x1c88: 0x8800, 0x1c89: 0x1100, + 0x1c8f: 0x8800, 0x1c90: 0x1100, 0x1c91: 0x1100, + 0x1c92: 0x8800, 0x1c93: 0x1100, 0x1c94: 0x1100, 0x1c95: 0x8800, 0x1c96: 0x1100, 0x1c97: 0x1100, + 0x1c98: 0x8800, 0x1c99: 0x1100, 0x1c9a: 0x1100, 0x1c9b: 0x8800, 0x1c9c: 0x1100, 0x1c9d: 0x1100, + 0x1caf: 0x8800, + 0x1cb0: 0x8800, 0x1cb1: 0x8800, 0x1cb2: 0x8800, 0x1cb4: 0x1100, + 0x1cb7: 0x1100, 0x1cb8: 0x1100, 0x1cb9: 0x1100, 0x1cba: 0x1100, + 0x1cbd: 0x8800, 0x1cbe: 0x1100, 0x1cbf: 0x3000, + // Block 0x73, offset 0x1cc0 + 0x1cf1: 0x3000, 0x1cf2: 0x3000, 0x1cf3: 0x3000, 0x1cf4: 0x3000, 0x1cf5: 0x3000, + 0x1cf6: 0x3000, 0x1cf7: 0x3000, 0x1cf8: 0x3000, 0x1cf9: 0x3000, 0x1cfa: 0x3000, 0x1cfb: 0x3000, + 0x1cfc: 0x3000, 0x1cfd: 0x3000, 0x1cfe: 0x3000, 0x1cff: 0x3000, + // Block 0x74, offset 0x1d00 + 0x1d00: 0x3000, 0x1d01: 0x3000, 0x1d02: 0x3000, 0x1d03: 0x3000, 0x1d04: 0x3000, 0x1d05: 0x3000, + 0x1d06: 0x3000, 0x1d07: 0x3000, 0x1d08: 0x3000, 0x1d09: 0x3000, 0x1d0a: 0x3000, 0x1d0b: 0x3000, + 0x1d0c: 0x3000, 0x1d0d: 0x3000, 0x1d0e: 0x3000, + 0x1d12: 0x3000, 0x1d13: 0x3000, 0x1d14: 0x3000, 0x1d15: 0x3000, 0x1d16: 0x3000, 0x1d17: 0x3000, + 0x1d18: 0x3000, 0x1d19: 0x3000, 0x1d1a: 0x3000, 0x1d1b: 0x3000, 0x1d1c: 0x3000, 0x1d1d: 0x3000, + 0x1d1e: 0x3000, 0x1d1f: 0x3000, + // Block 0x75, offset 0x1d40 + 0x1d40: 0x3000, 0x1d41: 0x3000, 0x1d42: 0x3000, 0x1d43: 0x3000, 0x1d44: 0x3000, 0x1d45: 0x3000, + 0x1d46: 0x3000, 0x1d47: 0x3000, 0x1d48: 0x3000, 0x1d49: 0x3000, 0x1d4a: 0x3000, 0x1d4b: 0x3000, + 0x1d4c: 0x3000, 0x1d4d: 0x3000, 0x1d4e: 0x3000, 0x1d4f: 0x3000, 0x1d50: 0x3000, 0x1d51: 0x3000, + 0x1d52: 0x3000, 0x1d53: 0x3000, 0x1d54: 0x3000, 0x1d55: 0x3000, 0x1d56: 0x3000, 0x1d57: 0x3000, + 0x1d58: 0x3000, 0x1d59: 0x3000, 0x1d5a: 0x3000, 0x1d5b: 0x3000, 0x1d5c: 0x3000, 0x1d5d: 0x3000, + 0x1d5e: 0x3000, 0x1d60: 0x3000, 0x1d61: 0x3000, 0x1d62: 0x3000, 0x1d63: 0x3000, + 0x1d64: 0x3000, 0x1d65: 0x3000, 0x1d66: 0x3000, 0x1d67: 0x3000, 0x1d68: 0x3000, 0x1d69: 0x3000, + 0x1d6a: 0x3000, 0x1d6b: 0x3000, 0x1d6c: 0x3000, 0x1d6d: 0x3000, 0x1d6e: 0x3000, 0x1d6f: 0x3000, + 0x1d70: 0x3000, 0x1d71: 0x3000, 0x1d72: 0x3000, 0x1d73: 0x3000, 0x1d74: 0x3000, 0x1d75: 0x3000, + 0x1d76: 0x3000, 0x1d77: 0x3000, 0x1d78: 0x3000, 0x1d79: 0x3000, 0x1d7a: 0x3000, 0x1d7b: 0x3000, + 0x1d7c: 0x3000, 0x1d7d: 0x3000, 0x1d7e: 0x3000, 0x1d7f: 0x3000, + // Block 0x76, offset 0x1d80 + 0x1d80: 0x3000, 0x1d81: 0x3000, 0x1d82: 0x3000, 0x1d83: 0x3000, 0x1d84: 0x3000, 0x1d85: 0x3000, + 0x1d86: 0x3000, 0x1d87: 0x3000, + 0x1d90: 0x3000, 0x1d91: 0x3000, + 0x1d92: 0x3000, 0x1d93: 0x3000, 0x1d94: 0x3000, 0x1d95: 0x3000, 0x1d96: 0x3000, 0x1d97: 0x3000, + 0x1d98: 0x3000, 0x1d99: 0x3000, 0x1d9a: 0x3000, 0x1d9b: 0x3000, 0x1d9c: 0x3000, 0x1d9d: 0x3000, + 0x1d9e: 0x3000, 0x1d9f: 0x3000, 0x1da0: 0x3000, 0x1da1: 0x3000, 0x1da2: 0x3000, 0x1da3: 0x3000, + 0x1da4: 0x3000, 0x1da5: 0x3000, 0x1da6: 0x3000, 0x1da7: 0x3000, 0x1da8: 0x3000, 0x1da9: 0x3000, + 0x1daa: 0x3000, 0x1dab: 0x3000, 0x1dac: 0x3000, 0x1dad: 0x3000, 0x1dae: 0x3000, 0x1daf: 0x3000, + 0x1db0: 0x3000, 0x1db1: 0x3000, 0x1db2: 0x3000, 0x1db3: 0x3000, 0x1db4: 0x3000, 0x1db5: 0x3000, + 0x1db6: 0x3000, 0x1db7: 0x3000, 0x1db8: 0x3000, 0x1db9: 0x3000, 0x1dba: 0x3000, 0x1dbb: 0x3000, + 0x1dbc: 0x3000, 0x1dbd: 0x3000, 0x1dbe: 0x3000, + // Block 0x77, offset 0x1dc0 + 0x1dc0: 0x3000, 0x1dc1: 0x3000, 0x1dc2: 0x3000, 0x1dc3: 0x3000, 0x1dc4: 0x3000, 0x1dc5: 0x3000, + 0x1dc6: 0x3000, 0x1dc7: 0x3000, 0x1dc8: 0x3000, 0x1dc9: 0x3000, 0x1dca: 0x3000, 0x1dcb: 0x3000, + 0x1dcc: 0x3000, 0x1dcd: 0x3000, 0x1dce: 0x3000, 0x1dcf: 0x3000, 0x1dd0: 0x3000, 0x1dd1: 0x3000, + 0x1dd2: 0x3000, 0x1dd3: 0x3000, 0x1dd4: 0x3000, 0x1dd5: 0x3000, 0x1dd6: 0x3000, 0x1dd7: 0x3000, + 0x1dd8: 0x3000, 0x1dd9: 0x3000, 0x1dda: 0x3000, 0x1ddb: 0x3000, 0x1ddc: 0x3000, 0x1ddd: 0x3000, + 0x1dde: 0x3000, 0x1ddf: 0x3000, 0x1de0: 0x3000, 0x1de1: 0x3000, 0x1de2: 0x3000, 0x1de3: 0x3000, + 0x1de4: 0x3000, 0x1de5: 0x3000, 0x1de6: 0x3000, 0x1de7: 0x3000, 0x1de8: 0x3000, 0x1de9: 0x3000, + 0x1dea: 0x3000, 0x1deb: 0x3000, 0x1dec: 0x3000, 0x1ded: 0x3000, 0x1dee: 0x3000, 0x1def: 0x3000, + 0x1df0: 0x3000, 0x1df1: 0x3000, 0x1df2: 0x3000, 0x1df3: 0x3000, 0x1df4: 0x3000, 0x1df5: 0x3000, + 0x1df6: 0x3000, 0x1df7: 0x3000, 0x1df8: 0x3000, 0x1df9: 0x3000, 0x1dfa: 0x3000, 0x1dfb: 0x3000, + 0x1dfc: 0x3000, 0x1dfd: 0x3000, 0x1dfe: 0x3000, + // Block 0x78, offset 0x1e00 + 0x1e2f: 0x00e6, + 0x1e3c: 0x00e6, 0x1e3d: 0x00e6, + // Block 0x79, offset 0x1e40 + 0x1e70: 0x00e6, 0x1e71: 0x00e6, + // Block 0x7a, offset 0x1e80 + 0x1eb0: 0x3000, + // Block 0x7b, offset 0x1ec0 + 0x1ec6: 0x0009, + // Block 0x7c, offset 0x1f00 + 0x1f04: 0x0009, + 0x1f20: 0x00e6, 0x1f21: 0x00e6, 0x1f22: 0x00e6, 0x1f23: 0x00e6, + 0x1f24: 0x00e6, 0x1f25: 0x00e6, 0x1f26: 0x00e6, 0x1f27: 0x00e6, 0x1f28: 0x00e6, 0x1f29: 0x00e6, + 0x1f2a: 0x00e6, 0x1f2b: 0x00e6, 0x1f2c: 0x00e6, 0x1f2d: 0x00e6, 0x1f2e: 0x00e6, 0x1f2f: 0x00e6, + 0x1f30: 0x00e6, 0x1f31: 0x00e6, + // Block 0x7d, offset 0x1f40 + 0x1f6b: 0x00dc, 0x1f6c: 0x00dc, 0x1f6d: 0x00dc, + // Block 0x7e, offset 0x1f80 + 0x1f93: 0x0009, + // Block 0x7f, offset 0x1fc0 + 0x1ff3: 0x0007, + // Block 0x80, offset 0x2000 + 0x2000: 0x0009, + // Block 0x81, offset 0x2040 + 0x2070: 0x00e6, 0x2072: 0x00e6, 0x2073: 0x00e6, 0x2074: 0x00dc, + 0x2077: 0x00e6, 0x2078: 0x00e6, + 0x207e: 0x00e6, 0x207f: 0x00e6, + // Block 0x82, offset 0x2080 + 0x2081: 0x00e6, + // Block 0x83, offset 0x20c0 + 0x20ed: 0x0009, + // Block 0x84, offset 0x2100 + 0x2100: 0x1100, 0x2101: 0x1100, 0x2102: 0x1100, 0x2103: 0x1100, 0x2104: 0x1100, 0x2105: 0x1100, + 0x2106: 0x1100, 0x2107: 0x1100, 0x2108: 0x1100, 0x2109: 0x1100, 0x210a: 0x1100, 0x210b: 0x1100, + 0x210c: 0x1100, 0x210d: 0x1100, 0x210e: 0x1100, 0x210f: 0x1100, 0x2110: 0x1100, 0x2111: 0x1100, + 0x2112: 0x1100, 0x2113: 0x1100, 0x2114: 0x1100, 0x2115: 0x1100, 0x2116: 0x1100, 0x2117: 0x1100, + 0x2118: 0x1100, 0x2119: 0x1100, 0x211a: 0x1100, 0x211b: 0x1100, 0x211c: 0x1100, 0x211d: 0x1100, + 0x211e: 0x1100, 0x211f: 0x1100, 0x2120: 0x1100, 0x2121: 0x1100, 0x2122: 0x1100, 0x2123: 0x1100, + 0x2124: 0x1100, 0x2125: 0x1100, 0x2126: 0x1100, 0x2127: 0x1100, 0x2128: 0x1100, 0x2129: 0x1100, + 0x212a: 0x1100, 0x212b: 0x1100, 0x212c: 0x1100, 0x212d: 0x1100, 0x212e: 0x1100, 0x212f: 0x1100, + 0x2130: 0x1100, 0x2131: 0x1100, 0x2132: 0x1100, 0x2133: 0x1100, 0x2134: 0x1100, 0x2135: 0x1100, + 0x2136: 0x1100, 0x2137: 0x1100, 0x2138: 0x1100, 0x2139: 0x1100, 0x213a: 0x1100, 0x213b: 0x1100, + 0x213c: 0x1100, 0x213d: 0x1100, 0x213e: 0x1100, 0x213f: 0x1100, + // Block 0x85, offset 0x2140 + 0x2140: 0x1100, 0x2141: 0x1100, 0x2142: 0x1100, 0x2143: 0x1100, 0x2144: 0x1100, 0x2145: 0x1100, + 0x2146: 0x1100, 0x2147: 0x1100, 0x2148: 0x1100, 0x2149: 0x1100, 0x214a: 0x1100, 0x214b: 0x1100, + 0x214c: 0x1100, 0x214d: 0x1100, 0x214e: 0x1100, 0x214f: 0x1100, 0x2150: 0x1100, 0x2151: 0x1100, + 0x2152: 0x1100, 0x2153: 0x1100, 0x2154: 0x1100, 0x2155: 0x1100, 0x2156: 0x1100, 0x2157: 0x1100, + 0x2158: 0x1100, 0x2159: 0x1100, 0x215a: 0x1100, 0x215b: 0x1100, 0x215c: 0x1100, 0x215d: 0x1100, + 0x215e: 0x1100, 0x215f: 0x1100, 0x2160: 0x1100, 0x2161: 0x1100, 0x2162: 0x1100, 0x2163: 0x1100, + // Block 0x86, offset 0x2180 + 0x2180: 0x3300, 0x2181: 0x3300, 0x2182: 0x3300, 0x2183: 0x3300, 0x2184: 0x3300, 0x2185: 0x3300, + 0x2186: 0x3300, 0x2187: 0x3300, 0x2188: 0x3300, 0x2189: 0x3300, 0x218a: 0x3300, 0x218b: 0x3300, + 0x218c: 0x3300, 0x218d: 0x3300, 0x218e: 0x3300, 0x218f: 0x3300, 0x2190: 0x3300, 0x2191: 0x3300, + 0x2192: 0x3300, 0x2193: 0x3300, 0x2194: 0x3300, 0x2195: 0x3300, 0x2196: 0x3300, 0x2197: 0x3300, + 0x2198: 0x3300, 0x2199: 0x3300, 0x219a: 0x3300, 0x219b: 0x3300, 0x219c: 0x3300, 0x219d: 0x3300, + 0x219e: 0x3300, 0x219f: 0x3300, 0x21a0: 0x3300, 0x21a1: 0x3300, 0x21a2: 0x3300, 0x21a3: 0x3300, + 0x21a4: 0x3300, 0x21a5: 0x3300, 0x21a6: 0x3300, 0x21a7: 0x3300, 0x21a8: 0x3300, 0x21a9: 0x3300, + 0x21aa: 0x3300, 0x21ab: 0x3300, 0x21ac: 0x3300, 0x21ad: 0x3300, 0x21ae: 0x3300, 0x21af: 0x3300, + 0x21b0: 0x3300, 0x21b1: 0x3300, 0x21b2: 0x3300, 0x21b3: 0x3300, 0x21b4: 0x3300, 0x21b5: 0x3300, + 0x21b6: 0x3300, 0x21b7: 0x3300, 0x21b8: 0x3300, 0x21b9: 0x3300, 0x21ba: 0x3300, 0x21bb: 0x3300, + 0x21bc: 0x3300, 0x21bd: 0x3300, 0x21be: 0x3300, 0x21bf: 0x3300, + // Block 0x87, offset 0x21c0 + 0x21c0: 0x3300, 0x21c1: 0x3300, 0x21c2: 0x3300, 0x21c3: 0x3300, 0x21c4: 0x3300, 0x21c5: 0x3300, + 0x21c6: 0x3300, 0x21c7: 0x3300, 0x21c8: 0x3300, 0x21c9: 0x3300, 0x21ca: 0x3300, 0x21cb: 0x3300, + 0x21cc: 0x3300, 0x21cd: 0x3300, 0x21d0: 0x3300, + 0x21d2: 0x3300, 0x21d5: 0x3300, 0x21d6: 0x3300, 0x21d7: 0x3300, + 0x21d8: 0x3300, 0x21d9: 0x3300, 0x21da: 0x3300, 0x21db: 0x3300, 0x21dc: 0x3300, 0x21dd: 0x3300, + 0x21de: 0x3300, 0x21e0: 0x3300, 0x21e2: 0x3300, + 0x21e5: 0x3300, 0x21e6: 0x3300, + 0x21ea: 0x3300, 0x21eb: 0x3300, 0x21ec: 0x3300, 0x21ed: 0x3300, + 0x21f0: 0x3300, 0x21f1: 0x3300, 0x21f2: 0x3300, 0x21f3: 0x3300, 0x21f4: 0x3300, 0x21f5: 0x3300, + 0x21f6: 0x3300, 0x21f7: 0x3300, 0x21f8: 0x3300, 0x21f9: 0x3300, 0x21fa: 0x3300, 0x21fb: 0x3300, + 0x21fc: 0x3300, 0x21fd: 0x3300, 0x21fe: 0x3300, 0x21ff: 0x3300, + // Block 0x88, offset 0x2200 + 0x2200: 0x3300, 0x2201: 0x3300, 0x2202: 0x3300, 0x2203: 0x3300, 0x2204: 0x3300, 0x2205: 0x3300, + 0x2206: 0x3300, 0x2207: 0x3300, 0x2208: 0x3300, 0x2209: 0x3300, 0x220a: 0x3300, 0x220b: 0x3300, + 0x220c: 0x3300, 0x220d: 0x3300, 0x220e: 0x3300, 0x220f: 0x3300, 0x2210: 0x3300, 0x2211: 0x3300, + 0x2212: 0x3300, 0x2213: 0x3300, 0x2214: 0x3300, 0x2215: 0x3300, 0x2216: 0x3300, 0x2217: 0x3300, + 0x2218: 0x3300, 0x2219: 0x3300, 0x221a: 0x3300, 0x221b: 0x3300, 0x221c: 0x3300, 0x221d: 0x3300, + 0x221e: 0x3300, 0x221f: 0x3300, 0x2220: 0x3300, 0x2221: 0x3300, 0x2222: 0x3300, 0x2223: 0x3300, + 0x2224: 0x3300, 0x2225: 0x3300, 0x2226: 0x3300, 0x2227: 0x3300, 0x2228: 0x3300, 0x2229: 0x3300, + 0x222a: 0x3300, 0x222b: 0x3300, 0x222c: 0x3300, 0x222d: 0x3300, + 0x2230: 0x3300, 0x2231: 0x3300, 0x2232: 0x3300, 0x2233: 0x3300, 0x2234: 0x3300, 0x2235: 0x3300, + 0x2236: 0x3300, 0x2237: 0x3300, 0x2238: 0x3300, 0x2239: 0x3300, 0x223a: 0x3300, 0x223b: 0x3300, + 0x223c: 0x3300, 0x223d: 0x3300, 0x223e: 0x3300, 0x223f: 0x3300, + // Block 0x89, offset 0x2240 + 0x2240: 0x3300, 0x2241: 0x3300, 0x2242: 0x3300, 0x2243: 0x3300, 0x2244: 0x3300, 0x2245: 0x3300, + 0x2246: 0x3300, 0x2247: 0x3300, 0x2248: 0x3300, 0x2249: 0x3300, 0x224a: 0x3300, 0x224b: 0x3300, + 0x224c: 0x3300, 0x224d: 0x3300, 0x224e: 0x3300, 0x224f: 0x3300, 0x2250: 0x3300, 0x2251: 0x3300, + 0x2252: 0x3300, 0x2253: 0x3300, 0x2254: 0x3300, 0x2255: 0x3300, 0x2256: 0x3300, 0x2257: 0x3300, + 0x2258: 0x3300, 0x2259: 0x3300, + // Block 0x8a, offset 0x2280 + 0x2280: 0x3000, 0x2281: 0x3000, 0x2282: 0x3000, 0x2283: 0x3000, 0x2284: 0x3000, 0x2285: 0x3000, + 0x2286: 0x3000, + 0x2293: 0x3000, 0x2294: 0x3000, 0x2295: 0x3000, 0x2296: 0x3000, 0x2297: 0x3000, + 0x229d: 0x3300, + 0x229e: 0x001a, 0x229f: 0x3300, 0x22a0: 0x3000, 0x22a1: 0x3000, 0x22a2: 0x3000, 0x22a3: 0x3000, + 0x22a4: 0x3000, 0x22a5: 0x3000, 0x22a6: 0x3000, 0x22a7: 0x3000, 0x22a8: 0x3000, 0x22a9: 0x3000, + 0x22aa: 0x3300, 0x22ab: 0x3300, 0x22ac: 0x3300, 0x22ad: 0x3300, 0x22ae: 0x3300, 0x22af: 0x3300, + 0x22b0: 0x3300, 0x22b1: 0x3300, 0x22b2: 0x3300, 0x22b3: 0x3300, 0x22b4: 0x3300, 0x22b5: 0x3300, + 0x22b6: 0x3300, 0x22b8: 0x3300, 0x22b9: 0x3300, 0x22ba: 0x3300, 0x22bb: 0x3300, + 0x22bc: 0x3300, 0x22be: 0x3300, + // Block 0x8b, offset 0x22c0 + 0x22c0: 0x3300, 0x22c1: 0x3300, 0x22c3: 0x3300, 0x22c4: 0x3300, + 0x22c6: 0x3300, 0x22c7: 0x3300, 0x22c8: 0x3300, 0x22c9: 0x3300, 0x22ca: 0x3300, 0x22cb: 0x3300, + 0x22cc: 0x3300, 0x22cd: 0x3300, 0x22ce: 0x3300, 0x22cf: 0x3000, 0x22d0: 0x3000, 0x22d1: 0x3000, + 0x22d2: 0x3000, 0x22d3: 0x3000, 0x22d4: 0x3000, 0x22d5: 0x3000, 0x22d6: 0x3000, 0x22d7: 0x3000, + 0x22d8: 0x3000, 0x22d9: 0x3000, 0x22da: 0x3000, 0x22db: 0x3000, 0x22dc: 0x3000, 0x22dd: 0x3000, + 0x22de: 0x3000, 0x22df: 0x3000, 0x22e0: 0x3000, 0x22e1: 0x3000, 0x22e2: 0x3000, 0x22e3: 0x3000, + 0x22e4: 0x3000, 0x22e5: 0x3000, 0x22e6: 0x3000, 0x22e7: 0x3000, 0x22e8: 0x3000, 0x22e9: 0x3000, + 0x22ea: 0x3000, 0x22eb: 0x3000, 0x22ec: 0x3000, 0x22ed: 0x3000, 0x22ee: 0x3000, 0x22ef: 0x3000, + 0x22f0: 0x3000, 0x22f1: 0x3000, 0x22f2: 0x3000, 0x22f3: 0x3000, 0x22f4: 0x3000, 0x22f5: 0x3000, + 0x22f6: 0x3000, 0x22f7: 0x3000, 0x22f8: 0x3000, 0x22f9: 0x3000, 0x22fa: 0x3000, 0x22fb: 0x3000, + 0x22fc: 0x3000, 0x22fd: 0x3000, 0x22fe: 0x3000, 0x22ff: 0x3000, + // Block 0x8c, offset 0x2300 + 0x2300: 0x3000, 0x2301: 0x3000, 0x2302: 0x3000, 0x2303: 0x3000, 0x2304: 0x3000, 0x2305: 0x3000, + 0x2306: 0x3000, 0x2307: 0x3000, 0x2308: 0x3000, 0x2309: 0x3000, 0x230a: 0x3000, 0x230b: 0x3000, + 0x230c: 0x3000, 0x230d: 0x3000, 0x230e: 0x3000, 0x230f: 0x3000, 0x2310: 0x3000, 0x2311: 0x3000, + 0x2312: 0x3000, 0x2313: 0x3000, 0x2314: 0x3000, 0x2315: 0x3000, 0x2316: 0x3000, 0x2317: 0x3000, + 0x2318: 0x3000, 0x2319: 0x3000, 0x231a: 0x3000, 0x231b: 0x3000, 0x231c: 0x3000, 0x231d: 0x3000, + 0x231e: 0x3000, 0x231f: 0x3000, 0x2320: 0x3000, 0x2321: 0x3000, 0x2322: 0x3000, 0x2323: 0x3000, + 0x2324: 0x3000, 0x2325: 0x3000, 0x2326: 0x3000, 0x2327: 0x3000, 0x2328: 0x3000, 0x2329: 0x3000, + 0x232a: 0x3000, 0x232b: 0x3000, 0x232c: 0x3000, 0x232d: 0x3000, 0x232e: 0x3000, 0x232f: 0x3000, + 0x2330: 0x3000, 0x2331: 0x3000, + // Block 0x8d, offset 0x2340 + 0x2353: 0x3000, 0x2354: 0x3000, 0x2355: 0x3000, 0x2356: 0x3000, 0x2357: 0x3000, + 0x2358: 0x3000, 0x2359: 0x3000, 0x235a: 0x3000, 0x235b: 0x3000, 0x235c: 0x3000, 0x235d: 0x3000, + 0x235e: 0x3000, 0x235f: 0x3000, 0x2360: 0x3000, 0x2361: 0x3000, 0x2362: 0x3000, 0x2363: 0x3000, + 0x2364: 0x3000, 0x2365: 0x3000, 0x2366: 0x3000, 0x2367: 0x3000, 0x2368: 0x3000, 0x2369: 0x3000, + 0x236a: 0x3000, 0x236b: 0x3000, 0x236c: 0x3000, 0x236d: 0x3000, 0x236e: 0x3000, 0x236f: 0x3000, + 0x2370: 0x3000, 0x2371: 0x3000, 0x2372: 0x3000, 0x2373: 0x3000, 0x2374: 0x3000, 0x2375: 0x3000, + 0x2376: 0x3000, 0x2377: 0x3000, 0x2378: 0x3000, 0x2379: 0x3000, 0x237a: 0x3000, 0x237b: 0x3000, + 0x237c: 0x3000, 0x237d: 0x3000, 0x237e: 0x3000, 0x237f: 0x3000, + // Block 0x8e, offset 0x2380 + 0x2380: 0x3000, 0x2381: 0x3000, 0x2382: 0x3000, 0x2383: 0x3000, 0x2384: 0x3000, 0x2385: 0x3000, + 0x2386: 0x3000, 0x2387: 0x3000, 0x2388: 0x3000, 0x2389: 0x3000, 0x238a: 0x3000, 0x238b: 0x3000, + 0x238c: 0x3000, 0x238d: 0x3000, 0x238e: 0x3000, 0x238f: 0x3000, 0x2390: 0x3000, 0x2391: 0x3000, + 0x2392: 0x3000, 0x2393: 0x3000, 0x2394: 0x3000, 0x2395: 0x3000, 0x2396: 0x3000, 0x2397: 0x3000, + 0x2398: 0x3000, 0x2399: 0x3000, 0x239a: 0x3000, 0x239b: 0x3000, 0x239c: 0x3000, 0x239d: 0x3000, + 0x239e: 0x3000, 0x239f: 0x3000, 0x23a0: 0x3000, 0x23a1: 0x3000, 0x23a2: 0x3000, 0x23a3: 0x3000, + 0x23a4: 0x3000, 0x23a5: 0x3000, 0x23a6: 0x3000, 0x23a7: 0x3000, 0x23a8: 0x3000, 0x23a9: 0x3000, + 0x23aa: 0x3000, 0x23ab: 0x3000, 0x23ac: 0x3000, 0x23ad: 0x3000, 0x23ae: 0x3000, 0x23af: 0x3000, + 0x23b0: 0x3000, 0x23b1: 0x3000, 0x23b2: 0x3000, 0x23b3: 0x3000, 0x23b4: 0x3000, 0x23b5: 0x3000, + 0x23b6: 0x3000, 0x23b7: 0x3000, 0x23b8: 0x3000, 0x23b9: 0x3000, 0x23ba: 0x3000, 0x23bb: 0x3000, + 0x23bc: 0x3000, 0x23bd: 0x3000, + // Block 0x8f, offset 0x23c0 + 0x23d0: 0x3000, 0x23d1: 0x3000, + 0x23d2: 0x3000, 0x23d3: 0x3000, 0x23d4: 0x3000, 0x23d5: 0x3000, 0x23d6: 0x3000, 0x23d7: 0x3000, + 0x23d8: 0x3000, 0x23d9: 0x3000, 0x23da: 0x3000, 0x23db: 0x3000, 0x23dc: 0x3000, 0x23dd: 0x3000, + 0x23de: 0x3000, 0x23df: 0x3000, 0x23e0: 0x3000, 0x23e1: 0x3000, 0x23e2: 0x3000, 0x23e3: 0x3000, + 0x23e4: 0x3000, 0x23e5: 0x3000, 0x23e6: 0x3000, 0x23e7: 0x3000, 0x23e8: 0x3000, 0x23e9: 0x3000, + 0x23ea: 0x3000, 0x23eb: 0x3000, 0x23ec: 0x3000, 0x23ed: 0x3000, 0x23ee: 0x3000, 0x23ef: 0x3000, + 0x23f0: 0x3000, 0x23f1: 0x3000, 0x23f2: 0x3000, 0x23f3: 0x3000, 0x23f4: 0x3000, 0x23f5: 0x3000, + 0x23f6: 0x3000, 0x23f7: 0x3000, 0x23f8: 0x3000, 0x23f9: 0x3000, 0x23fa: 0x3000, 0x23fb: 0x3000, + 0x23fc: 0x3000, 0x23fd: 0x3000, 0x23fe: 0x3000, 0x23ff: 0x3000, + // Block 0x90, offset 0x2400 + 0x2400: 0x3000, 0x2401: 0x3000, 0x2402: 0x3000, 0x2403: 0x3000, 0x2404: 0x3000, 0x2405: 0x3000, + 0x2406: 0x3000, 0x2407: 0x3000, 0x2408: 0x3000, 0x2409: 0x3000, 0x240a: 0x3000, 0x240b: 0x3000, + 0x240c: 0x3000, 0x240d: 0x3000, 0x240e: 0x3000, 0x240f: 0x3000, + 0x2412: 0x3000, 0x2413: 0x3000, 0x2414: 0x3000, 0x2415: 0x3000, 0x2416: 0x3000, 0x2417: 0x3000, + 0x2418: 0x3000, 0x2419: 0x3000, 0x241a: 0x3000, 0x241b: 0x3000, 0x241c: 0x3000, 0x241d: 0x3000, + 0x241e: 0x3000, 0x241f: 0x3000, 0x2420: 0x3000, 0x2421: 0x3000, 0x2422: 0x3000, 0x2423: 0x3000, + 0x2424: 0x3000, 0x2425: 0x3000, 0x2426: 0x3000, 0x2427: 0x3000, 0x2428: 0x3000, 0x2429: 0x3000, + 0x242a: 0x3000, 0x242b: 0x3000, 0x242c: 0x3000, 0x242d: 0x3000, 0x242e: 0x3000, 0x242f: 0x3000, + 0x2430: 0x3000, 0x2431: 0x3000, 0x2432: 0x3000, 0x2433: 0x3000, 0x2434: 0x3000, 0x2435: 0x3000, + 0x2436: 0x3000, 0x2437: 0x3000, 0x2438: 0x3000, 0x2439: 0x3000, 0x243a: 0x3000, 0x243b: 0x3000, + 0x243c: 0x3000, 0x243d: 0x3000, 0x243e: 0x3000, 0x243f: 0x3000, + // Block 0x91, offset 0x2440 + 0x2440: 0x3000, 0x2441: 0x3000, 0x2442: 0x3000, 0x2443: 0x3000, 0x2444: 0x3000, 0x2445: 0x3000, + 0x2446: 0x3000, 0x2447: 0x3000, + 0x2470: 0x3000, 0x2471: 0x3000, 0x2472: 0x3000, 0x2473: 0x3000, 0x2474: 0x3000, 0x2475: 0x3000, + 0x2476: 0x3000, 0x2477: 0x3000, 0x2478: 0x3000, 0x2479: 0x3000, 0x247a: 0x3000, 0x247b: 0x3000, + 0x247c: 0x3000, + // Block 0x92, offset 0x2480 + 0x2490: 0x3000, 0x2491: 0x3000, + 0x2492: 0x3000, 0x2493: 0x3000, 0x2494: 0x3000, 0x2495: 0x3000, 0x2496: 0x3000, 0x2497: 0x3000, + 0x2498: 0x3000, 0x2499: 0x3000, + 0x24a0: 0x00e6, 0x24a1: 0x00e6, 0x24a2: 0x00e6, 0x24a3: 0x00e6, + 0x24a4: 0x00e6, 0x24a5: 0x00e6, 0x24a6: 0x00e6, + 0x24b0: 0x3000, 0x24b1: 0x3000, 0x24b2: 0x3000, 0x24b3: 0x3000, 0x24b4: 0x3000, 0x24b5: 0x3000, + 0x24b6: 0x3000, 0x24b7: 0x3000, 0x24b8: 0x3000, 0x24b9: 0x3000, 0x24ba: 0x3000, 0x24bb: 0x3000, + 0x24bc: 0x3000, 0x24bd: 0x3000, 0x24be: 0x3000, 0x24bf: 0x3000, + // Block 0x93, offset 0x24c0 + 0x24c0: 0x3000, 0x24c1: 0x3000, 0x24c2: 0x3000, 0x24c3: 0x3000, 0x24c4: 0x3000, + 0x24c7: 0x3000, 0x24c8: 0x3000, 0x24c9: 0x3000, 0x24ca: 0x3000, 0x24cb: 0x3000, + 0x24cc: 0x3000, 0x24cd: 0x3000, 0x24ce: 0x3000, 0x24cf: 0x3000, 0x24d0: 0x3000, 0x24d1: 0x3000, + 0x24d2: 0x3000, 0x24d4: 0x3000, 0x24d5: 0x3000, 0x24d6: 0x3000, 0x24d7: 0x3000, + 0x24d8: 0x3000, 0x24d9: 0x3000, 0x24da: 0x3000, 0x24db: 0x3000, 0x24dc: 0x3000, 0x24dd: 0x3000, + 0x24de: 0x3000, 0x24df: 0x3000, 0x24e0: 0x3000, 0x24e1: 0x3000, 0x24e2: 0x3000, 0x24e3: 0x3000, + 0x24e4: 0x3000, 0x24e5: 0x3000, 0x24e6: 0x3000, 0x24e8: 0x3000, 0x24e9: 0x3000, + 0x24ea: 0x3000, 0x24eb: 0x3000, + 0x24f0: 0x3000, 0x24f1: 0x3000, 0x24f2: 0x3000, 0x24f4: 0x3000, + 0x24f6: 0x3000, 0x24f7: 0x3000, 0x24f8: 0x3000, 0x24f9: 0x3000, 0x24fa: 0x3000, 0x24fb: 0x3000, + 0x24fc: 0x3000, 0x24fd: 0x3000, 0x24fe: 0x3000, 0x24ff: 0x3000, + // Block 0x94, offset 0x2500 + 0x2500: 0x3000, 0x2501: 0x3000, 0x2502: 0x3000, 0x2503: 0x3000, 0x2504: 0x3000, 0x2505: 0x3000, + 0x2506: 0x3000, 0x2507: 0x3000, 0x2508: 0x3000, 0x2509: 0x3000, 0x250a: 0x3000, 0x250b: 0x3000, + 0x250c: 0x3000, 0x250d: 0x3000, 0x250e: 0x3000, 0x250f: 0x3000, 0x2510: 0x3000, 0x2511: 0x3000, + 0x2512: 0x3000, 0x2513: 0x3000, 0x2514: 0x3000, 0x2515: 0x3000, 0x2516: 0x3000, 0x2517: 0x3000, + 0x2518: 0x3000, 0x2519: 0x3000, 0x251a: 0x3000, 0x251b: 0x3000, 0x251c: 0x3000, 0x251d: 0x3000, + 0x251e: 0x3000, 0x251f: 0x3000, 0x2520: 0x3000, 0x2521: 0x3000, 0x2522: 0x3000, 0x2523: 0x3000, + 0x2524: 0x3000, 0x2525: 0x3000, 0x2526: 0x3000, 0x2527: 0x3000, 0x2528: 0x3000, 0x2529: 0x3000, + 0x252a: 0x3000, 0x252b: 0x3000, 0x252c: 0x3000, 0x252d: 0x3000, 0x252e: 0x3000, 0x252f: 0x3000, + 0x2530: 0x3000, 0x2531: 0x3000, 0x2532: 0x3000, 0x2533: 0x3000, 0x2534: 0x3000, 0x2535: 0x3000, + 0x2536: 0x3000, 0x2537: 0x3000, 0x2538: 0x3000, 0x2539: 0x3000, 0x253a: 0x3000, 0x253b: 0x3000, + 0x253c: 0x3000, + // Block 0x95, offset 0x2540 + 0x2541: 0x3000, 0x2542: 0x3000, 0x2543: 0x3000, 0x2544: 0x3000, 0x2545: 0x3000, + 0x2546: 0x3000, 0x2547: 0x3000, 0x2548: 0x3000, 0x2549: 0x3000, 0x254a: 0x3000, 0x254b: 0x3000, + 0x254c: 0x3000, 0x254d: 0x3000, 0x254e: 0x3000, 0x254f: 0x3000, 0x2550: 0x3000, 0x2551: 0x3000, + 0x2552: 0x3000, 0x2553: 0x3000, 0x2554: 0x3000, 0x2555: 0x3000, 0x2556: 0x3000, 0x2557: 0x3000, + 0x2558: 0x3000, 0x2559: 0x3000, 0x255a: 0x3000, 0x255b: 0x3000, 0x255c: 0x3000, 0x255d: 0x3000, + 0x255e: 0x3000, 0x255f: 0x3000, 0x2560: 0x3000, 0x2561: 0x3000, 0x2562: 0x3000, 0x2563: 0x3000, + 0x2564: 0x3000, 0x2565: 0x3000, 0x2566: 0x3000, 0x2567: 0x3000, 0x2568: 0x3000, 0x2569: 0x3000, + 0x256a: 0x3000, 0x256b: 0x3000, 0x256c: 0x3000, 0x256d: 0x3000, 0x256e: 0x3000, 0x256f: 0x3000, + 0x2570: 0x3000, 0x2571: 0x3000, 0x2572: 0x3000, 0x2573: 0x3000, 0x2574: 0x3000, 0x2575: 0x3000, + 0x2576: 0x3000, 0x2577: 0x3000, 0x2578: 0x3000, 0x2579: 0x3000, 0x257a: 0x3000, 0x257b: 0x3000, + 0x257c: 0x3000, 0x257d: 0x3000, 0x257e: 0x3000, 0x257f: 0x3000, + // Block 0x96, offset 0x2580 + 0x2582: 0x3000, 0x2583: 0x3000, 0x2584: 0x3000, 0x2585: 0x3000, + 0x2586: 0x3000, 0x2587: 0x3000, 0x258a: 0x3000, 0x258b: 0x3000, + 0x258c: 0x3000, 0x258d: 0x3000, 0x258e: 0x3000, 0x258f: 0x3000, + 0x2592: 0x3000, 0x2593: 0x3000, 0x2594: 0x3000, 0x2595: 0x3000, 0x2596: 0x3000, 0x2597: 0x3000, + 0x259a: 0x3000, 0x259b: 0x3000, 0x259c: 0x3000, + 0x25a0: 0x3000, 0x25a1: 0x3000, 0x25a2: 0x3000, 0x25a3: 0x3000, + 0x25a4: 0x3000, 0x25a5: 0x3000, 0x25a6: 0x3000, 0x25a8: 0x3000, 0x25a9: 0x3000, + 0x25aa: 0x3000, 0x25ab: 0x3000, 0x25ac: 0x3000, 0x25ad: 0x3000, 0x25ae: 0x3000, + // Block 0x97, offset 0x25c0 + 0x25fd: 0x00dc, + // Block 0x98, offset 0x2600 + 0x260d: 0x00dc, 0x260f: 0x00e6, + 0x2638: 0x00e6, 0x2639: 0x0001, 0x263a: 0x00dc, + 0x263f: 0x0009, + // Block 0x99, offset 0x2640 + 0x2659: 0x8800, 0x265a: 0x1100, 0x265b: 0x8800, 0x265c: 0x1100, + 0x2665: 0x8800, + 0x266b: 0x1100, + 0x2679: 0x0009, 0x267a: 0x6607, + // Block 0x9a, offset 0x2680 + 0x269e: 0x3300, 0x269f: 0x3300, 0x26a0: 0x3300, 0x26a1: 0x3300, 0x26a2: 0x3300, 0x26a3: 0x3300, + 0x26a4: 0x3300, 0x26a5: 0x00d8, 0x26a6: 0x00d8, 0x26a7: 0x0001, 0x26a8: 0x0001, 0x26a9: 0x0001, + 0x26ad: 0x00e2, 0x26ae: 0x00d8, 0x26af: 0x00d8, + 0x26b0: 0x00d8, 0x26b1: 0x00d8, 0x26b2: 0x00d8, + 0x26bb: 0x00dc, + 0x26bc: 0x00dc, 0x26bd: 0x00dc, 0x26be: 0x00dc, 0x26bf: 0x00dc, + // Block 0x9b, offset 0x26c0 + 0x26c0: 0x00dc, 0x26c1: 0x00dc, 0x26c2: 0x00dc, 0x26c5: 0x00e6, + 0x26c6: 0x00e6, 0x26c7: 0x00e6, 0x26c8: 0x00e6, 0x26c9: 0x00e6, 0x26ca: 0x00dc, 0x26cb: 0x00dc, + 0x26ea: 0x00e6, 0x26eb: 0x00e6, 0x26ec: 0x00e6, 0x26ed: 0x00e6, + 0x26fb: 0x3300, + 0x26fc: 0x3300, 0x26fd: 0x3300, 0x26fe: 0x3300, 0x26ff: 0x3300, + // Block 0x9c, offset 0x2700 + 0x2700: 0x3300, + // Block 0x9d, offset 0x2740 + 0x2742: 0x00e6, 0x2743: 0x00e6, 0x2744: 0x00e6, + // Block 0x9e, offset 0x2780 + 0x2780: 0x3000, 0x2781: 0x3000, 0x2782: 0x3000, 0x2783: 0x3000, 0x2784: 0x3000, 0x2785: 0x3000, + 0x2786: 0x3000, 0x2787: 0x3000, 0x2788: 0x3000, 0x2789: 0x3000, 0x278a: 0x3000, 0x278b: 0x3000, + 0x278c: 0x3000, 0x278d: 0x3000, 0x278e: 0x3000, 0x278f: 0x3000, 0x2790: 0x3000, 0x2791: 0x3000, + 0x2792: 0x3000, 0x2793: 0x3000, 0x2794: 0x3000, 0x2796: 0x3000, 0x2797: 0x3000, + 0x2798: 0x3000, 0x2799: 0x3000, 0x279a: 0x3000, 0x279b: 0x3000, 0x279c: 0x3000, 0x279d: 0x3000, + 0x279e: 0x3000, 0x279f: 0x3000, 0x27a0: 0x3000, 0x27a1: 0x3000, 0x27a2: 0x3000, 0x27a3: 0x3000, + 0x27a4: 0x3000, 0x27a5: 0x3000, 0x27a6: 0x3000, 0x27a7: 0x3000, 0x27a8: 0x3000, 0x27a9: 0x3000, + 0x27aa: 0x3000, 0x27ab: 0x3000, 0x27ac: 0x3000, 0x27ad: 0x3000, 0x27ae: 0x3000, 0x27af: 0x3000, + 0x27b0: 0x3000, 0x27b1: 0x3000, 0x27b2: 0x3000, 0x27b3: 0x3000, 0x27b4: 0x3000, 0x27b5: 0x3000, + 0x27b6: 0x3000, 0x27b7: 0x3000, 0x27b8: 0x3000, 0x27b9: 0x3000, 0x27ba: 0x3000, 0x27bb: 0x3000, + 0x27bc: 0x3000, 0x27bd: 0x3000, 0x27be: 0x3000, 0x27bf: 0x3000, + // Block 0x9f, offset 0x27c0 + 0x27c0: 0x3000, 0x27c1: 0x3000, 0x27c2: 0x3000, 0x27c3: 0x3000, 0x27c4: 0x3000, 0x27c5: 0x3000, + 0x27c6: 0x3000, 0x27c7: 0x3000, 0x27c8: 0x3000, 0x27c9: 0x3000, 0x27ca: 0x3000, 0x27cb: 0x3000, + 0x27cc: 0x3000, 0x27cd: 0x3000, 0x27ce: 0x3000, 0x27cf: 0x3000, 0x27d0: 0x3000, 0x27d1: 0x3000, + 0x27d2: 0x3000, 0x27d3: 0x3000, 0x27d4: 0x3000, 0x27d5: 0x3000, 0x27d6: 0x3000, 0x27d7: 0x3000, + 0x27d8: 0x3000, 0x27d9: 0x3000, 0x27da: 0x3000, 0x27db: 0x3000, 0x27dc: 0x3000, + 0x27de: 0x3000, 0x27df: 0x3000, 0x27e2: 0x3000, + 0x27e5: 0x3000, 0x27e6: 0x3000, 0x27e9: 0x3000, + 0x27ea: 0x3000, 0x27eb: 0x3000, 0x27ec: 0x3000, 0x27ee: 0x3000, 0x27ef: 0x3000, + 0x27f0: 0x3000, 0x27f1: 0x3000, 0x27f2: 0x3000, 0x27f3: 0x3000, 0x27f4: 0x3000, 0x27f5: 0x3000, + 0x27f6: 0x3000, 0x27f7: 0x3000, 0x27f8: 0x3000, 0x27f9: 0x3000, 0x27fb: 0x3000, + 0x27fd: 0x3000, 0x27fe: 0x3000, 0x27ff: 0x3000, + // Block 0xa0, offset 0x2800 + 0x2800: 0x3000, 0x2801: 0x3000, 0x2802: 0x3000, 0x2803: 0x3000, 0x2805: 0x3000, + 0x2806: 0x3000, 0x2807: 0x3000, 0x2808: 0x3000, 0x2809: 0x3000, 0x280a: 0x3000, 0x280b: 0x3000, + 0x280c: 0x3000, 0x280d: 0x3000, 0x280e: 0x3000, 0x280f: 0x3000, 0x2810: 0x3000, 0x2811: 0x3000, + 0x2812: 0x3000, 0x2813: 0x3000, 0x2814: 0x3000, 0x2815: 0x3000, 0x2816: 0x3000, 0x2817: 0x3000, + 0x2818: 0x3000, 0x2819: 0x3000, 0x281a: 0x3000, 0x281b: 0x3000, 0x281c: 0x3000, 0x281d: 0x3000, + 0x281e: 0x3000, 0x281f: 0x3000, 0x2820: 0x3000, 0x2821: 0x3000, 0x2822: 0x3000, 0x2823: 0x3000, + 0x2824: 0x3000, 0x2825: 0x3000, 0x2826: 0x3000, 0x2827: 0x3000, 0x2828: 0x3000, 0x2829: 0x3000, + 0x282a: 0x3000, 0x282b: 0x3000, 0x282c: 0x3000, 0x282d: 0x3000, 0x282e: 0x3000, 0x282f: 0x3000, + 0x2830: 0x3000, 0x2831: 0x3000, 0x2832: 0x3000, 0x2833: 0x3000, 0x2834: 0x3000, 0x2835: 0x3000, + 0x2836: 0x3000, 0x2837: 0x3000, 0x2838: 0x3000, 0x2839: 0x3000, 0x283a: 0x3000, 0x283b: 0x3000, + 0x283c: 0x3000, 0x283d: 0x3000, 0x283e: 0x3000, 0x283f: 0x3000, + // Block 0xa1, offset 0x2840 + 0x2840: 0x3000, 0x2841: 0x3000, 0x2842: 0x3000, 0x2843: 0x3000, 0x2844: 0x3000, 0x2845: 0x3000, + 0x2847: 0x3000, 0x2848: 0x3000, 0x2849: 0x3000, 0x284a: 0x3000, + 0x284d: 0x3000, 0x284e: 0x3000, 0x284f: 0x3000, 0x2850: 0x3000, 0x2851: 0x3000, + 0x2852: 0x3000, 0x2853: 0x3000, 0x2854: 0x3000, 0x2856: 0x3000, 0x2857: 0x3000, + 0x2858: 0x3000, 0x2859: 0x3000, 0x285a: 0x3000, 0x285b: 0x3000, 0x285c: 0x3000, + 0x285e: 0x3000, 0x285f: 0x3000, 0x2860: 0x3000, 0x2861: 0x3000, 0x2862: 0x3000, 0x2863: 0x3000, + 0x2864: 0x3000, 0x2865: 0x3000, 0x2866: 0x3000, 0x2867: 0x3000, 0x2868: 0x3000, 0x2869: 0x3000, + 0x286a: 0x3000, 0x286b: 0x3000, 0x286c: 0x3000, 0x286d: 0x3000, 0x286e: 0x3000, 0x286f: 0x3000, + 0x2870: 0x3000, 0x2871: 0x3000, 0x2872: 0x3000, 0x2873: 0x3000, 0x2874: 0x3000, 0x2875: 0x3000, + 0x2876: 0x3000, 0x2877: 0x3000, 0x2878: 0x3000, 0x2879: 0x3000, 0x287b: 0x3000, + 0x287c: 0x3000, 0x287d: 0x3000, 0x287e: 0x3000, + // Block 0xa2, offset 0x2880 + 0x2880: 0x3000, 0x2881: 0x3000, 0x2882: 0x3000, 0x2883: 0x3000, 0x2884: 0x3000, + 0x2886: 0x3000, 0x288a: 0x3000, 0x288b: 0x3000, + 0x288c: 0x3000, 0x288d: 0x3000, 0x288e: 0x3000, 0x288f: 0x3000, 0x2890: 0x3000, + 0x2892: 0x3000, 0x2893: 0x3000, 0x2894: 0x3000, 0x2895: 0x3000, 0x2896: 0x3000, 0x2897: 0x3000, + 0x2898: 0x3000, 0x2899: 0x3000, 0x289a: 0x3000, 0x289b: 0x3000, 0x289c: 0x3000, 0x289d: 0x3000, + 0x289e: 0x3000, 0x289f: 0x3000, 0x28a0: 0x3000, 0x28a1: 0x3000, 0x28a2: 0x3000, 0x28a3: 0x3000, + 0x28a4: 0x3000, 0x28a5: 0x3000, 0x28a6: 0x3000, 0x28a7: 0x3000, 0x28a8: 0x3000, 0x28a9: 0x3000, + 0x28aa: 0x3000, 0x28ab: 0x3000, 0x28ac: 0x3000, 0x28ad: 0x3000, 0x28ae: 0x3000, 0x28af: 0x3000, + 0x28b0: 0x3000, 0x28b1: 0x3000, 0x28b2: 0x3000, 0x28b3: 0x3000, 0x28b4: 0x3000, 0x28b5: 0x3000, + 0x28b6: 0x3000, 0x28b7: 0x3000, 0x28b8: 0x3000, 0x28b9: 0x3000, 0x28ba: 0x3000, 0x28bb: 0x3000, + 0x28bc: 0x3000, 0x28bd: 0x3000, 0x28be: 0x3000, 0x28bf: 0x3000, + // Block 0xa3, offset 0x28c0 + 0x28c0: 0x3000, 0x28c1: 0x3000, 0x28c2: 0x3000, 0x28c3: 0x3000, 0x28c4: 0x3000, 0x28c5: 0x3000, + 0x28c6: 0x3000, 0x28c7: 0x3000, 0x28c8: 0x3000, 0x28c9: 0x3000, 0x28ca: 0x3000, 0x28cb: 0x3000, + 0x28cc: 0x3000, 0x28cd: 0x3000, 0x28ce: 0x3000, 0x28cf: 0x3000, 0x28d0: 0x3000, 0x28d1: 0x3000, + 0x28d2: 0x3000, 0x28d3: 0x3000, 0x28d4: 0x3000, 0x28d5: 0x3000, 0x28d6: 0x3000, 0x28d7: 0x3000, + 0x28d8: 0x3000, 0x28d9: 0x3000, 0x28da: 0x3000, 0x28db: 0x3000, 0x28dc: 0x3000, 0x28dd: 0x3000, + 0x28de: 0x3000, 0x28df: 0x3000, 0x28e0: 0x3000, 0x28e1: 0x3000, 0x28e2: 0x3000, 0x28e3: 0x3000, + 0x28e4: 0x3000, 0x28e5: 0x3000, 0x28e8: 0x3000, 0x28e9: 0x3000, + 0x28ea: 0x3000, 0x28eb: 0x3000, 0x28ec: 0x3000, 0x28ed: 0x3000, 0x28ee: 0x3000, 0x28ef: 0x3000, + 0x28f0: 0x3000, 0x28f1: 0x3000, 0x28f2: 0x3000, 0x28f3: 0x3000, 0x28f4: 0x3000, 0x28f5: 0x3000, + 0x28f6: 0x3000, 0x28f7: 0x3000, 0x28f8: 0x3000, 0x28f9: 0x3000, 0x28fa: 0x3000, 0x28fb: 0x3000, + 0x28fc: 0x3000, 0x28fd: 0x3000, 0x28fe: 0x3000, 0x28ff: 0x3000, + // Block 0xa4, offset 0x2900 + 0x2900: 0x3000, 0x2901: 0x3000, 0x2902: 0x3000, 0x2903: 0x3000, 0x2904: 0x3000, 0x2905: 0x3000, + 0x2906: 0x3000, 0x2907: 0x3000, 0x2908: 0x3000, 0x2909: 0x3000, 0x290a: 0x3000, 0x290b: 0x3000, + 0x290e: 0x3000, 0x290f: 0x3000, 0x2910: 0x3000, 0x2911: 0x3000, + 0x2912: 0x3000, 0x2913: 0x3000, 0x2914: 0x3000, 0x2915: 0x3000, 0x2916: 0x3000, 0x2917: 0x3000, + 0x2918: 0x3000, 0x2919: 0x3000, 0x291a: 0x3000, 0x291b: 0x3000, 0x291c: 0x3000, 0x291d: 0x3000, + 0x291e: 0x3000, 0x291f: 0x3000, 0x2920: 0x3000, 0x2921: 0x3000, 0x2922: 0x3000, 0x2923: 0x3000, + 0x2924: 0x3000, 0x2925: 0x3000, 0x2926: 0x3000, 0x2927: 0x3000, 0x2928: 0x3000, 0x2929: 0x3000, + 0x292a: 0x3000, 0x292b: 0x3000, 0x292c: 0x3000, 0x292d: 0x3000, 0x292e: 0x3000, 0x292f: 0x3000, + 0x2930: 0x3000, 0x2931: 0x3000, 0x2932: 0x3000, 0x2933: 0x3000, 0x2934: 0x3000, 0x2935: 0x3000, + 0x2936: 0x3000, 0x2937: 0x3000, 0x2938: 0x3000, 0x2939: 0x3000, 0x293a: 0x3000, 0x293b: 0x3000, + 0x293c: 0x3000, 0x293d: 0x3000, 0x293e: 0x3000, 0x293f: 0x3000, + // Block 0xa5, offset 0x2940 + 0x2940: 0x3000, 0x2941: 0x3000, 0x2942: 0x3000, 0x2943: 0x3000, 0x2944: 0x3000, 0x2945: 0x3000, + 0x2946: 0x3000, 0x2947: 0x3000, 0x2948: 0x3000, 0x2949: 0x3000, 0x294a: 0x3000, + 0x2950: 0x3000, 0x2951: 0x3000, + 0x2952: 0x3000, 0x2953: 0x3000, 0x2954: 0x3000, 0x2955: 0x3000, 0x2956: 0x3000, 0x2957: 0x3000, + 0x2958: 0x3000, 0x2959: 0x3000, 0x295a: 0x3000, 0x295b: 0x3000, 0x295c: 0x3000, 0x295d: 0x3000, + 0x295e: 0x3000, 0x295f: 0x3000, 0x2960: 0x3000, 0x2961: 0x3000, 0x2962: 0x3000, 0x2963: 0x3000, + 0x2964: 0x3000, 0x2965: 0x3000, 0x2966: 0x3000, 0x2967: 0x3000, 0x2968: 0x3000, 0x2969: 0x3000, + 0x296a: 0x3000, 0x296b: 0x3000, 0x296c: 0x3000, 0x296d: 0x3000, 0x296e: 0x3000, + 0x2970: 0x3000, 0x2971: 0x3000, 0x2972: 0x3000, 0x2973: 0x3000, 0x2974: 0x3000, 0x2975: 0x3000, + 0x2976: 0x3000, 0x2977: 0x3000, 0x2978: 0x3000, 0x2979: 0x3000, 0x297a: 0x3000, 0x297b: 0x3000, + 0x297c: 0x3000, 0x297d: 0x3000, 0x297e: 0x3000, 0x297f: 0x3000, + // Block 0xa6, offset 0x2980 + 0x2980: 0x3000, 0x2981: 0x3000, 0x2982: 0x3000, 0x2983: 0x3000, 0x2984: 0x3000, 0x2985: 0x3000, + 0x2986: 0x3000, 0x2987: 0x3000, 0x2988: 0x3000, 0x2989: 0x3000, 0x298a: 0x3000, 0x298b: 0x3000, + 0x298c: 0x3000, 0x298d: 0x3000, 0x298e: 0x3000, 0x298f: 0x3000, + // Block 0xa7, offset 0x29c0 + 0x29d0: 0x3000, + // Block 0xa8, offset 0x2a00 + 0x2a00: 0x3000, 0x2a01: 0x3000, 0x2a02: 0x3000, + 0x2a10: 0x3000, 0x2a11: 0x3000, + 0x2a12: 0x3000, 0x2a13: 0x3000, 0x2a14: 0x3000, 0x2a15: 0x3000, 0x2a16: 0x3000, 0x2a17: 0x3000, + 0x2a18: 0x3000, 0x2a19: 0x3000, 0x2a1a: 0x3000, 0x2a1b: 0x3000, 0x2a1c: 0x3000, 0x2a1d: 0x3000, + 0x2a1e: 0x3000, 0x2a1f: 0x3000, 0x2a20: 0x3000, 0x2a21: 0x3000, 0x2a22: 0x3000, 0x2a23: 0x3000, + 0x2a24: 0x3000, 0x2a25: 0x3000, 0x2a26: 0x3000, 0x2a27: 0x3000, 0x2a28: 0x3000, 0x2a29: 0x3000, + 0x2a2a: 0x3000, 0x2a2b: 0x3000, 0x2a2c: 0x3000, 0x2a2d: 0x3000, 0x2a2e: 0x3000, 0x2a2f: 0x3000, + 0x2a30: 0x3000, 0x2a31: 0x3000, 0x2a32: 0x3000, 0x2a33: 0x3000, 0x2a34: 0x3000, 0x2a35: 0x3000, + 0x2a36: 0x3000, 0x2a37: 0x3000, 0x2a38: 0x3000, 0x2a39: 0x3000, 0x2a3a: 0x3000, + // Block 0xa9, offset 0x2a40 + 0x2a40: 0x3000, 0x2a41: 0x3000, 0x2a42: 0x3000, 0x2a43: 0x3000, 0x2a44: 0x3000, 0x2a45: 0x3000, + 0x2a46: 0x3000, 0x2a47: 0x3000, 0x2a48: 0x3000, + 0x2a50: 0x3000, 0x2a51: 0x3000, + // Block 0xaa, offset 0x2a80 + 0x2a80: 0x3300, 0x2a81: 0x3300, 0x2a82: 0x3300, 0x2a83: 0x3300, 0x2a84: 0x3300, 0x2a85: 0x3300, + 0x2a86: 0x3300, 0x2a87: 0x3300, 0x2a88: 0x3300, 0x2a89: 0x3300, 0x2a8a: 0x3300, 0x2a8b: 0x3300, + 0x2a8c: 0x3300, 0x2a8d: 0x3300, 0x2a8e: 0x3300, 0x2a8f: 0x3300, 0x2a90: 0x3300, 0x2a91: 0x3300, + 0x2a92: 0x3300, 0x2a93: 0x3300, 0x2a94: 0x3300, 0x2a95: 0x3300, 0x2a96: 0x3300, 0x2a97: 0x3300, + 0x2a98: 0x3300, 0x2a99: 0x3300, 0x2a9a: 0x3300, 0x2a9b: 0x3300, 0x2a9c: 0x3300, 0x2a9d: 0x3300, } // charInfoLookup: 1152 bytes // Block 0 is the null block. -var charInfoLookup = [...]uint8{ - // Block 0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 2 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 3 - 0x00, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x00, 0x00, 0x14, 0x15, - 0x16, 0x17, 0x00, 0x18, 0x19, 0x1A, 0x00, 0x1B, - 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x09, 0x09, 0x0A, 0x00, 0x0B, - 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 4 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1C, 0x1D, 0x00, 0x00, 0x1E, 0x1F, 0x20, 0x21, - 0x22, 0x23, 0x24, 0x25, 0x20, 0x26, 0x27, 0x28, - 0x00, 0x29, 0x2A, 0x2B, 0x2C, 0x28, 0x00, 0x2D, - 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, - // Block 5 - 0x36, 0x00, 0x37, 0x38, 0x00, 0x39, 0x3A, 0x3B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x3E, - 0x00, 0x00, 0x3F, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x41, 0x42, 0x00, 0x00, 0x43, 0x44, 0x45, 0x46, - 0x47, 0x00, 0x00, 0x48, 0x49, 0x4A, 0x4B, 0x4C, - 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, - // Block 6 - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, - 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x00, 0x00, 0x00, - 0x00, 0x62, 0x63, 0x64, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x65, 0x66, 0x00, 0x67, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x68, 0x00, 0x69, 0x00, 0x6A, 0x00, 0x6B, - 0x00, 0x00, 0x6C, 0x6D, 0x63, 0x63, 0x63, 0x6E, - // Block 7 - 0x6F, 0x70, 0x71, 0x72, 0x73, 0x63, 0x74, 0x00, - 0x75, 0x76, 0x63, 0x77, 0x63, 0x63, 0x63, 0x63, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 8 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x79, 0x00, 0x7A, 0x00, 0x00, - 0x7B, 0x00, 0x00, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, - 0x00, 0x00, 0x81, 0x82, 0x00, 0x00, 0x00, 0x83, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - // Block 9 - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - // Block A - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x85, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block B - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x86, 0x86, 0x86, 0x86, - 0x87, 0x88, 0x86, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, - 0x63, 0x63, 0x63, 0x63, 0x8E, 0x8F, 0x90, 0x91, - 0x92, 0x93, 0x63, 0x94, 0x95, 0x63, 0x77, 0x96, - // Block C - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block D - 0x00, 0x7B, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block E - 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x9B, 0x9C, - 0x00, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x63, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0x63, 0x63, - 0x63, 0x63, 0xA3, 0x63, 0x63, 0x63, 0x63, 0xA4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block F - 0x00, 0x00, 0x00, 0x00, 0xA5, 0xA6, 0xA7, 0x00, - 0xA8, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 10 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Block 11 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +var charInfoLookup = [1152]uint8{ + // Block 0x0, offset 0x0 + // Block 0x1, offset 0x40 + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x0c2: 0x03, 0x0c3: 0x04, 0x0c4: 0x05, 0x0c5: 0x06, 0x0c6: 0x07, 0x0c7: 0x08, + 0x0c8: 0x09, 0x0ca: 0x0a, 0x0cb: 0x0b, 0x0cc: 0x0c, 0x0cd: 0x0d, 0x0ce: 0x0e, 0x0cf: 0x0f, + 0x0d0: 0x10, 0x0d1: 0x11, 0x0d2: 0x12, 0x0d3: 0x13, 0x0d6: 0x14, 0x0d7: 0x15, + 0x0d8: 0x16, 0x0d9: 0x17, 0x0db: 0x18, 0x0dc: 0x19, 0x0dd: 0x1a, 0x0df: 0x1b, + 0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07, + 0x0ea: 0x08, 0x0eb: 0x09, 0x0ec: 0x09, 0x0ed: 0x0a, 0x0ef: 0x0b, + 0x0f0: 0x11, + // Block 0x4, offset 0x100 + 0x120: 0x1c, 0x121: 0x1d, 0x124: 0x1e, 0x125: 0x1f, 0x126: 0x20, 0x127: 0x21, + 0x128: 0x22, 0x129: 0x23, 0x12a: 0x24, 0x12b: 0x25, 0x12c: 0x20, 0x12d: 0x26, 0x12e: 0x27, 0x12f: 0x28, + 0x131: 0x29, 0x132: 0x2a, 0x133: 0x2b, 0x134: 0x2c, 0x135: 0x28, 0x137: 0x2d, + 0x138: 0x2e, 0x139: 0x2f, 0x13a: 0x30, 0x13b: 0x31, 0x13c: 0x32, 0x13d: 0x33, 0x13e: 0x34, 0x13f: 0x35, + // Block 0x5, offset 0x140 + 0x140: 0x36, 0x142: 0x37, 0x143: 0x38, 0x145: 0x39, 0x146: 0x3a, 0x147: 0x3b, + 0x14d: 0x3c, + 0x15c: 0x3d, 0x15f: 0x3e, + 0x162: 0x3f, 0x164: 0x40, + 0x168: 0x41, 0x169: 0x42, 0x16c: 0x43, 0x16d: 0x44, 0x16e: 0x45, 0x16f: 0x46, + 0x170: 0x47, 0x173: 0x48, 0x174: 0x49, 0x175: 0x4a, 0x176: 0x4b, 0x177: 0x4c, + 0x178: 0x4d, 0x179: 0x4e, 0x17a: 0x4f, 0x17b: 0x50, 0x17c: 0x51, 0x17d: 0x52, 0x17e: 0x53, 0x17f: 0x54, + // Block 0x6, offset 0x180 + 0x180: 0x55, 0x181: 0x56, 0x182: 0x57, 0x183: 0x58, 0x184: 0x59, 0x185: 0x5a, 0x186: 0x5b, 0x187: 0x5c, + 0x188: 0x5d, 0x189: 0x5e, 0x18a: 0x5f, 0x18b: 0x60, 0x18c: 0x61, + 0x191: 0x62, 0x192: 0x63, 0x193: 0x64, + 0x1a8: 0x65, 0x1a9: 0x66, 0x1ab: 0x67, + 0x1b1: 0x68, 0x1b3: 0x69, 0x1b5: 0x6a, 0x1b7: 0x6b, + 0x1ba: 0x6c, 0x1bb: 0x6d, 0x1bc: 0x63, 0x1bd: 0x63, 0x1be: 0x63, 0x1bf: 0x6e, + // Block 0x7, offset 0x1c0 + 0x1c0: 0x6f, 0x1c1: 0x70, 0x1c2: 0x71, 0x1c3: 0x72, 0x1c4: 0x73, 0x1c5: 0x63, 0x1c6: 0x74, + 0x1c8: 0x75, 0x1c9: 0x76, 0x1ca: 0x63, 0x1cb: 0x77, 0x1cc: 0x63, 0x1cd: 0x63, 0x1ce: 0x63, 0x1cf: 0x63, + // Block 0x8, offset 0x200 + 0x219: 0x78, 0x21b: 0x79, 0x21d: 0x7a, + 0x220: 0x7b, 0x223: 0x7c, 0x224: 0x7d, 0x225: 0x7e, 0x226: 0x7f, 0x227: 0x80, + 0x22a: 0x81, 0x22b: 0x82, 0x22f: 0x83, + 0x230: 0x84, 0x231: 0x84, 0x232: 0x84, 0x233: 0x84, 0x234: 0x84, 0x235: 0x84, 0x236: 0x84, 0x237: 0x84, + 0x238: 0x84, 0x239: 0x84, 0x23a: 0x84, 0x23b: 0x84, 0x23c: 0x84, 0x23d: 0x84, 0x23e: 0x84, 0x23f: 0x84, + // Block 0x9, offset 0x240 + 0x240: 0x84, 0x241: 0x84, 0x242: 0x84, 0x243: 0x84, 0x244: 0x84, 0x245: 0x84, 0x246: 0x84, 0x247: 0x84, + 0x248: 0x84, 0x249: 0x84, 0x24a: 0x84, 0x24b: 0x84, 0x24c: 0x84, 0x24d: 0x84, 0x24e: 0x84, 0x24f: 0x84, + 0x250: 0x84, 0x251: 0x84, 0x252: 0x84, 0x253: 0x84, 0x254: 0x84, 0x255: 0x84, 0x256: 0x84, 0x257: 0x84, + 0x258: 0x84, 0x259: 0x84, 0x25a: 0x84, 0x25b: 0x84, 0x25c: 0x84, 0x25d: 0x84, 0x25e: 0x84, 0x25f: 0x84, + 0x260: 0x84, 0x261: 0x84, 0x262: 0x84, 0x263: 0x84, 0x264: 0x84, 0x265: 0x84, 0x266: 0x84, 0x267: 0x84, + 0x268: 0x84, 0x269: 0x84, 0x26a: 0x84, 0x26b: 0x84, 0x26c: 0x84, 0x26d: 0x84, 0x26e: 0x84, 0x26f: 0x84, + 0x270: 0x84, 0x271: 0x84, 0x272: 0x84, 0x273: 0x84, 0x274: 0x84, 0x275: 0x84, 0x276: 0x84, 0x277: 0x84, + 0x278: 0x84, 0x279: 0x84, 0x27a: 0x84, 0x27b: 0x84, 0x27c: 0x84, 0x27d: 0x84, 0x27e: 0x84, 0x27f: 0x84, + // Block 0xa, offset 0x280 + 0x280: 0x84, 0x281: 0x84, 0x282: 0x84, 0x283: 0x84, 0x284: 0x84, 0x285: 0x84, 0x286: 0x84, 0x287: 0x84, + 0x288: 0x84, 0x289: 0x84, 0x28a: 0x84, 0x28b: 0x84, 0x28c: 0x84, 0x28d: 0x84, 0x28e: 0x84, 0x28f: 0x84, + 0x290: 0x84, 0x291: 0x84, 0x292: 0x84, 0x293: 0x84, 0x294: 0x84, 0x295: 0x84, 0x296: 0x84, 0x297: 0x84, + 0x298: 0x84, 0x299: 0x84, 0x29a: 0x84, 0x29b: 0x84, 0x29c: 0x84, 0x29d: 0x84, 0x29e: 0x85, + // Block 0xb, offset 0x2c0 + 0x2e4: 0x86, 0x2e5: 0x86, 0x2e6: 0x86, 0x2e7: 0x86, + 0x2e8: 0x87, 0x2e9: 0x88, 0x2ea: 0x86, 0x2eb: 0x89, 0x2ec: 0x8a, 0x2ed: 0x8b, 0x2ee: 0x8c, 0x2ef: 0x8d, + 0x2f0: 0x63, 0x2f1: 0x63, 0x2f2: 0x63, 0x2f3: 0x63, 0x2f4: 0x8e, 0x2f5: 0x8f, 0x2f6: 0x90, 0x2f7: 0x91, + 0x2f8: 0x92, 0x2f9: 0x93, 0x2fa: 0x63, 0x2fb: 0x94, 0x2fc: 0x95, 0x2fd: 0x63, 0x2fe: 0x77, 0x2ff: 0x96, + // Block 0xc, offset 0x300 + 0x307: 0x97, + 0x328: 0x98, + // Block 0xd, offset 0x340 + 0x341: 0x7b, 0x342: 0x99, + // Block 0xe, offset 0x380 + 0x385: 0x9a, 0x386: 0x9b, 0x387: 0x9c, + 0x389: 0x9d, + 0x390: 0x63, 0x391: 0x9e, 0x392: 0x9f, 0x393: 0xa0, 0x394: 0xa1, 0x395: 0xa2, 0x396: 0x63, 0x397: 0x63, + 0x398: 0x63, 0x399: 0x63, 0x39a: 0xa3, 0x39b: 0x63, 0x39c: 0x63, 0x39d: 0x63, 0x39e: 0x63, 0x39f: 0xa4, + // Block 0xf, offset 0x3c0 + 0x3c4: 0xa5, 0x3c5: 0xa6, 0x3c6: 0xa7, + 0x3c8: 0xa8, 0x3c9: 0xa9, + // Block 0x10, offset 0x400 + 0x420: 0x86, 0x421: 0x86, 0x422: 0x86, 0x423: 0x86, 0x424: 0x86, 0x425: 0x86, 0x426: 0x86, 0x427: 0x86, + 0x428: 0xaa, + // Block 0x11, offset 0x440 + 0x450: 0x0c, 0x451: 0x0d, + 0x45d: 0x0e, 0x45f: 0x0f, + 0x46f: 0x10, } +var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:]} + // Total size of tables: 78KB (80234 bytes) diff --git a/src/pkg/exp/norm/trie.go b/src/pkg/exp/norm/trie.go new file mode 100644 index 000000000..6b6540187 --- /dev/null +++ b/src/pkg/exp/norm/trie.go @@ -0,0 +1,234 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package norm + +type trie struct { + index []uint8 + values []uint16 +} + +const ( + t1 = 0x00 // 0000 0000 + tx = 0x80 // 1000 0000 + t2 = 0xC0 // 1100 0000 + t3 = 0xE0 // 1110 0000 + t4 = 0xF0 // 1111 0000 + t5 = 0xF8 // 1111 1000 + t6 = 0xFC // 1111 1100 + te = 0xFE // 1111 1110 + + maskx = 0x3F // 0011 1111 + mask2 = 0x1F // 0001 1111 + mask3 = 0x0F // 0000 1111 + mask4 = 0x07 // 0000 0111 +) + +// lookup returns the trie value for the first UTF-8 encoding in s and +// the width in bytes of this encoding. The size will be 0 if s does not +// hold enough bytes to complete the encoding. len(s) must be greater than 0. +func (t *trie) lookup(s []byte) (v uint16, sz int) { + c0 := s[0] + switch { + case c0 < tx: + return t.values[c0], 1 + case c0 < t2: + return 0, 1 + case c0 < t3: + if len(s) < 2 { + return 0, 0 + } + i := t.index[c0] + c1 := s[1] + if c1 < tx || t2 <= c1 { + return 0, 1 + } + o := uint16(i)<<6 + uint16(c1)&maskx + return t.values[o], 2 + case c0 < t4: + if len(s) < 3 { + return 0, 0 + } + i := t.index[c0] + c1 := s[1] + if c1 < tx || t2 <= c1 { + return 0, 1 + } + o := uint16(i)<<6 + uint16(c1)&maskx + i = t.index[o] + c2 := s[2] + if c2 < tx || t2 <= c2 { + return 0, 2 + } + o = uint16(i)<<6 + uint16(c2)&maskx + return t.values[o], 3 + case c0 < t5: + if len(s) < 4 { + return 0, 0 + } + i := t.index[c0] + c1 := s[1] + if c1 < tx || t2 <= c1 { + return 0, 1 + } + o := uint16(i)<<6 + uint16(c1)&maskx + i = t.index[o] + c2 := s[2] + if c2 < tx || t2 <= c2 { + return 0, 2 + } + o = uint16(i)<<6 + uint16(c2)&maskx + i = t.index[o] + c3 := s[3] + if c3 < tx || t2 <= c3 { + return 0, 3 + } + o = uint16(i)<<6 + uint16(c3)&maskx + return t.values[o], 4 + case c0 < t6: + if len(s) < 5 { + return 0, 0 + } + return 0, 5 + case c0 < te: + if len(s) < 6 { + return 0, 0 + } + return 0, 6 + } + // Illegal rune + return 0, 1 +} + +// lookupString returns the trie value for the first UTF-8 encoding in s and +// the width in bytes of this encoding. The size will be 0 if s does not +// hold enough bytes to complete the encoding. len(s) must be greater than 0. +func (t *trie) lookupString(s string) (v uint16, sz int) { + c0 := s[0] + switch { + case c0 < tx: + return t.values[c0], 1 + case c0 < t2: + return 0, 1 + case c0 < t3: + if len(s) < 2 { + return 0, 0 + } + i := t.index[c0] + c1 := s[1] + if c1 < tx || t2 <= c1 { + return 0, 1 + } + o := uint16(i)<<6 + uint16(c1)&maskx + return t.values[o], 2 + case c0 < t4: + if len(s) < 3 { + return 0, 0 + } + i := t.index[c0] + c1 := s[1] + if c1 < tx || t2 <= c1 { + return 0, 1 + } + o := uint16(i)<<6 + uint16(c1)&maskx + i = t.index[o] + c2 := s[2] + if c2 < tx || t2 <= c2 { + return 0, 2 + } + o = uint16(i)<<6 + uint16(c2)&maskx + return t.values[o], 3 + case c0 < t5: + if len(s) < 4 { + return 0, 0 + } + i := t.index[c0] + c1 := s[1] + if c1 < tx || t2 <= c1 { + return 0, 1 + } + o := uint16(i)<<6 + uint16(c1)&maskx + i = t.index[o] + c2 := s[2] + if c2 < tx || t2 <= c2 { + return 0, 2 + } + o = uint16(i)<<6 + uint16(c2)&maskx + i = t.index[o] + c3 := s[3] + if c3 < tx || t2 <= c3 { + return 0, 3 + } + o = uint16(i)<<6 + uint16(c3)&maskx + return t.values[o], 4 + case c0 < t6: + if len(s) < 5 { + return 0, 0 + } + return 0, 5 + case c0 < te: + if len(s) < 6 { + return 0, 0 + } + return 0, 6 + } + // Illegal rune + return 0, 1 +} + +// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. +// s must hold a full encoding. +func (t *trie) lookupUnsafe(s []byte) uint16 { + c0 := s[0] + if c0 < tx { + return t.values[c0] + } + if c0 < t2 { + return 0 + } + i := t.index[c0] + o := uint16(i)<<6 + uint16(s[1])&maskx + if c0 < t3 { + return t.values[o] + } + i = t.index[o] + o = uint16(i)<<6 + uint16(s[2])&maskx + if c0 < t4 { + return t.values[o] + } + i = t.index[o] + o = uint16(i)<<6 + uint16(s[3])&maskx + if c0 < t5 { + return t.values[o] + } + return 0 +} + +// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. +// s must hold a full encoding. +func (t *trie) lookupStringUnsafe(s string) uint16 { + c0 := s[0] + if c0 < tx { + return t.values[c0] + } + if c0 < t2 { + return 0 + } + i := t.index[c0] + o := uint16(i)<<6 + uint16(s[1])&maskx + if c0 < t3 { + return t.values[o] + } + i = t.index[o] + o = uint16(i)<<6 + uint16(s[2])&maskx + if c0 < t4 { + return t.values[o] + } + i = t.index[o] + o = uint16(i)<<6 + uint16(s[3])&maskx + if c0 < t5 { + return t.values[o] + } + return 0 +} diff --git a/src/pkg/exp/norm/trie_test.go b/src/pkg/exp/norm/trie_test.go new file mode 100644 index 000000000..ad87d972b --- /dev/null +++ b/src/pkg/exp/norm/trie_test.go @@ -0,0 +1,107 @@ +package norm + +import ( + "testing" + "utf8" +) + +// Test data is located in triedata_test.go; generated by maketesttables. +var testdata = testdataTrie + +// Test cases for illegal runes. +type trietest struct { + size int + bytes []byte +} + +var tests = []trietest{ + // illegal runes + {1, []byte{0x80}}, + {1, []byte{0xFF}}, + {1, []byte{t2, tx - 1}}, + {1, []byte{t2, t2}}, + {2, []byte{t3, tx, tx - 1}}, + {2, []byte{t3, tx, t2}}, + {1, []byte{t3, tx - 1, tx}}, + {3, []byte{t4, tx, tx, tx - 1}}, + {3, []byte{t4, tx, tx, t2}}, + {1, []byte{t4, t2, tx, tx - 1}}, + {2, []byte{t4, tx, t2, tx - 1}}, + + // short runes + {0, []byte{t2}}, + {0, []byte{t3, tx}}, + {0, []byte{t4, tx, tx}}, + {0, []byte{t5, tx, tx, tx}}, + {0, []byte{t6, tx, tx, tx, tx}}, +} + +func mkUtf8(rune int) ([]byte, int) { + var b [utf8.UTFMax]byte + sz := utf8.EncodeRune(b[:], rune) + return b[:sz], sz +} + +func TestLookup(t *testing.T) { + for i, tt := range testRunes { + b, szg := mkUtf8(tt) + v, szt := testdata.lookup(b) + if int(v) != i { + t.Errorf("lookup(%U): found value %#x, expected %#x", i, v, i) + } + if szt != szg { + t.Errorf("lookup(%U): found size %d, expected %d", i, szt, szg) + } + } + for i, tt := range tests { + v, sz := testdata.lookup(tt.bytes) + if int(v) != 0 { + t.Errorf("lookup of illegal rune, case %d: found value %#x, expected 0", i, v) + } + if sz != tt.size { + t.Errorf("lookup of illegal rune, case %d: found size %d, expected %d", i, sz, tt.size) + } + } +} + +func TestLookupUnsafe(t *testing.T) { + for i, tt := range testRunes { + b, _ := mkUtf8(tt) + v := testdata.lookupUnsafe(b) + if int(v) != i { + t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i) + } + } +} + +func TestLookupString(t *testing.T) { + for i, tt := range testRunes { + b, szg := mkUtf8(tt) + v, szt := testdata.lookupString(string(b)) + if int(v) != i { + t.Errorf("lookup(%U): found value %#x, expected %#x", i, v, i) + } + if szt != szg { + t.Errorf("lookup(%U): found size %d, expected %d", i, szt, szg) + } + } + for i, tt := range tests { + v, sz := testdata.lookupString(string(tt.bytes)) + if int(v) != 0 { + t.Errorf("lookup of illegal rune, case %d: found value %#x, expected 0", i, v) + } + if sz != tt.size { + t.Errorf("lookup of illegal rune, case %d: found size %d, expected %d", i, sz, tt.size) + } + } +} + +func TestLookupStringUnsafe(t *testing.T) { + for i, tt := range testRunes { + b, _ := mkUtf8(tt) + v := testdata.lookupStringUnsafe(string(b)) + if int(v) != i { + t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i) + } + } +} diff --git a/src/pkg/exp/norm/triedata_test.go b/src/pkg/exp/norm/triedata_test.go new file mode 100644 index 000000000..f886e6004 --- /dev/null +++ b/src/pkg/exp/norm/triedata_test.go @@ -0,0 +1,63 @@ +// Generated by running +// maketesttables +// DO NOT EDIT + +package norm + +var testRunes = []int{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111} + +// testdataValues: 768 entries, 1536 bytes +// Block 2 is the null block. +var testdataValues = [768]uint16{ + // Block 0x0, offset 0x0 + 0x000c: 0x0001, + // Block 0x1, offset 0x40 + 0x007f: 0x0002, + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x00c0: 0x0003, + // Block 0x4, offset 0x100 + 0x0100: 0x0004, + // Block 0x5, offset 0x140 + 0x017f: 0x0005, + // Block 0x6, offset 0x180 + 0x0180: 0x0006, + // Block 0x7, offset 0x1c0 + 0x01d9: 0x0007, + // Block 0x8, offset 0x200 + 0x023f: 0x0008, + // Block 0x9, offset 0x240 + 0x0240: 0x0009, + // Block 0xa, offset 0x280 + 0x0281: 0x000a, + // Block 0xb, offset 0x2c0 + 0x02ff: 0x000b, +} + +// testdataLookup: 640 bytes +// Block 0 is the null block. +var testdataLookup = [640]uint8{ + // Block 0x0, offset 0x0 + // Block 0x1, offset 0x40 + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0x0c2: 0x03, 0x0c4: 0x04, + 0x0df: 0x05, + 0x0e0: 0x04, + 0x0ef: 0x05, + 0x0f0: 0x07, 0x0f4: 0x09, + // Block 0x4, offset 0x100 + 0x120: 0x06, 0x126: 0x07, + // Block 0x5, offset 0x140 + 0x17f: 0x08, + // Block 0x6, offset 0x180 + 0x180: 0x09, 0x184: 0x0a, + // Block 0x7, offset 0x1c0 + 0x1d0: 0x06, + // Block 0x8, offset 0x200 + 0x23f: 0x0b, + // Block 0x9, offset 0x240 + 0x24f: 0x08, +} + +var testdataTrie = trie{testdataLookup[:], testdataValues[:]} diff --git a/src/pkg/exp/norm/triegen.go b/src/pkg/exp/norm/triegen.go new file mode 100644 index 000000000..2b7eeee17 --- /dev/null +++ b/src/pkg/exp/norm/triegen.go @@ -0,0 +1,211 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Trie table generator. +// Used by make*tables tools to generate a go file with trie data structures +// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte +// sequence are used to lookup offsets in the index table to be used for the +// next byte. The last byte is used to index into a table with 16-bit values. + +package main + +import ( + "fmt" + "hash/crc32" + "log" + "utf8" +) + +// Intermediate trie structure +type trieNode struct { + table [256]*trieNode + value uint16 + b byte + leaf bool +} + +func newNode() *trieNode { + return new(trieNode) +} + +func (n trieNode) String() string { + s := fmt.Sprint("trieNode{table: { non-nil at index: ") + for i, v := range n.table { + if v != nil { + s += fmt.Sprintf("%d, ", i) + } + } + s += fmt.Sprintf("}, value:%#x, b:%#x leaf:%v}", n.value, n.b, n.leaf) + return s +} + +func (n trieNode) isInternal() bool { + internal := true + for i := 0; i < 256; i++ { + if nn := n.table[i]; nn != nil { + if !internal && !nn.leaf { + log.Fatalf("triegen: isInternal: node contains both leaf and non-leaf children (%v)", n) + } + internal = internal && !nn.leaf + } + } + return internal +} + +func (n *trieNode) insert(rune int, value uint16) { + var p [utf8.UTFMax]byte + sz := utf8.EncodeRune(p[:], rune) + + for i := 0; i < sz; i++ { + if n.leaf { + log.Fatalf("triegen: insert: node (%#v) should not be a leaf", n) + } + nn := n.table[p[i]] + if nn == nil { + nn = newNode() + nn.b = p[i] + n.table[p[i]] = nn + } + n = nn + } + n.value = value + n.leaf = true +} + +type nodeIndex struct { + lookupBlocks []*trieNode + valueBlocks []*trieNode + + lookupBlockIdx map[uint32]uint16 + valueBlockIdx map[uint32]uint16 +} + +func newIndex() *nodeIndex { + index := &nodeIndex{} + index.lookupBlocks = make([]*trieNode, 0) + index.valueBlocks = make([]*trieNode, 0) + index.lookupBlockIdx = make(map[uint32]uint16) + index.valueBlockIdx = make(map[uint32]uint16) + return index +} + +func computeOffsets(index *nodeIndex, n *trieNode) uint16 { + if n.leaf { + return n.value + } + hasher := crc32.New(crc32.MakeTable(crc32.IEEE)) + // We only index continuation bytes. + for i := 0; i < 64; i++ { + var v uint16 = 0 + if nn := n.table[0x80+i]; nn != nil { + v = computeOffsets(index, nn) + } + hasher.Write([]byte{uint8(v >> 8), uint8(v)}) + } + h := hasher.Sum32() + if n.isInternal() { + v, ok := index.lookupBlockIdx[h] + if !ok { + v = uint16(len(index.lookupBlocks)) + index.lookupBlocks = append(index.lookupBlocks, n) + index.lookupBlockIdx[h] = v + } + n.value = v + } else { + v, ok := index.valueBlockIdx[h] + if !ok { + v = uint16(len(index.valueBlocks)) + index.valueBlocks = append(index.valueBlocks, n) + index.valueBlockIdx[h] = v + } + n.value = v + } + return n.value +} + +func printValueBlock(nr int, n *trieNode, offset int) { + boff := nr * 64 + fmt.Printf("\n// Block %#x, offset %#x", nr, boff) + var printnewline bool + for i := 0; i < 64; i++ { + if i%6 == 0 { + printnewline = true + } + v := uint16(0) + if nn := n.table[i+offset]; nn != nil { + v = nn.value + } + if v != 0 { + if printnewline { + fmt.Printf("\n") + printnewline = false + } + fmt.Printf("%#04x:%#04x, ", nr*64+i, v) + } + } +} + +func printLookupBlock(nr int, n *trieNode, offset int) { + boff := nr * 64 + fmt.Printf("\n// Block %#x, offset %#x", nr, boff) + var printnewline bool + for i := 0; i < 64; i++ { + if i%8 == 0 { + printnewline = true + } + v := uint16(0) + if nn := n.table[i+offset]; nn != nil { + v = nn.value + } + if v != 0 { + if printnewline { + fmt.Printf("\n") + printnewline = false + } + fmt.Printf("%#03x:%#02x, ", boff+i, v) + } + } +} + +// printTables returns the size in bytes of the generated tables. +func (t *trieNode) printTables(name string) int { + index := newIndex() + // Values for 7-bit ASCII are stored in first two block, followed by nil block. + index.valueBlocks = append(index.valueBlocks, nil, nil, nil) + // First byte of multi-byte UTF-8 codepoints are indexed in 4th block. + index.lookupBlocks = append(index.lookupBlocks, nil, nil, nil, nil) + // Index starter bytes of multi-byte UTF-8. + for i := 0xC0; i < 0x100; i++ { + if t.table[i] != nil { + computeOffsets(index, t.table[i]) + } + } + + nv := len(index.valueBlocks) * 64 + fmt.Printf("// %sValues: %d entries, %d bytes\n", name, nv, nv*2) + fmt.Printf("// Block 2 is the null block.\n") + fmt.Printf("var %sValues = [%d]uint16 {", name, nv) + printValueBlock(0, t, 0) + printValueBlock(1, t, 64) + printValueBlock(2, newNode(), 0) + for i := 3; i < len(index.valueBlocks); i++ { + printValueBlock(i, index.valueBlocks[i], 0x80) + } + fmt.Print("\n}\n\n") + + ni := len(index.lookupBlocks) * 64 + fmt.Printf("// %sLookup: %d bytes\n", name, ni) + fmt.Printf("// Block 0 is the null block.\n") + fmt.Printf("var %sLookup = [%d]uint8 {", name, ni) + printLookupBlock(0, newNode(), 0) + printLookupBlock(1, newNode(), 0) + printLookupBlock(2, newNode(), 0) + printLookupBlock(3, t, 0xC0) + for i := 4; i < len(index.lookupBlocks); i++ { + printLookupBlock(i, index.lookupBlocks[i], 0x80) + } + fmt.Print("\n}\n\n") + fmt.Printf("var %sTrie = trie{ %sLookup[:], %sValues[:] }\n\n", name, name, name) + return nv*2 + ni +} diff --git a/src/pkg/exp/template/doc.go b/src/pkg/exp/template/doc.go deleted file mode 100644 index ef9e1563b..000000000 --- a/src/pkg/exp/template/doc.go +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package template implements data-driven templates for generating textual output -such as HTML. - -Templates are executed by applying them to a data structure. Annotations in the -template refer to elements of the data structure (typically a field of a struct -or a key in a map) to control execution and derive values to be displayed. -Execution of the template walks the structure and sets the cursor, represented -by a period '.' and called "dot", to the value at the current location in the -structure as execution proceeds. - -The input text for a template is UTF-8-encoded text in any format. -"Actions"--data evaluations or control structures--are delimited by -"{{" and "}}"; all text outside actions is copied to the output unchanged. -Actions may not span newlines, although comments can. - -Once constructed, templates and template sets can be executed safely in -parallel. - -Actions - -Here is the list of actions. "Arguments" and "pipelines" are evaluations of -data, defined in detail below. - -*/ -// {{/* a comment */}} -// A comment; discarded. May contain newlines. -// Comments do not nest. -/* - - {{pipeline}} - The default textual representation of the value of the pipeline - is copied to the output. - - {{if pipeline}} T1 {{end}} - If the value of the pipeline is empty, no output is generated; - otherwise, T1 is executed. The empty values are false, 0, any - nil pointer or interface value, and any array, slice, map, or - string of length zero. - Dot is unaffected. - - {{if pipeline}} T1 {{else}} T0 {{end}} - If the value of the pipeline is empty, T0 is executed; - otherwise, T1 is executed. Dot is unaffected. - - {{range pipeline}} T1 {{end}} - The value of the pipeline must be an array, slice, or map. If - the value of the pipeline has length zero, nothing is output; - otherwise, dot is set to the successive elements of the array, - slice, or map and T1 is executed. - - {{range pipeline}} T1 {{else}} T0 {{end}} - The value of the pipeline must be an array, slice, or map. If - the value of the pipeline has length zero, dot is unaffected and - T0 is executed; otherwise, dot is set to the successive elements - of the array, slice, or map and T1 is executed. - - {{template "name"}} - The template with the specified name is executed with nil data. - - {{template "name" pipeline}} - The template with the specified name is executed with dot set - to the value of the pipeline. - - {{with pipeline}} T1 {{end}} - If the value of the pipeline is empty, no output is generated; - otherwise, dot is set to the value of the pipeline and T1 is - executed. - - {{with pipeline}} T1 {{else}} T0 {{end}} - If the value of the pipeline is empty, dot is unaffected and T0 - is executed; otherwise, dot is set to the value of the pipeline - and T1 is executed. - -Arguments - -An argument is a simple value, denoted by one of the following. - - - A boolean, string, character, integer, floating-point, imaginary - or complex constant in Go syntax. These behave like Go's untyped - constants, although raw strings may not span newlines. - - The character '.' (period): - . - The result is the value of dot. - - A variable name, which is a (possibly empty) alphanumeric string - preceded by a dollar sign, such as - $piOver2 - or - $ - The result is the value of the variable. - Variables are described below. - - The name of a field of the data, which must be a struct, preceded - by a period, such as - .Field - The result is the value of the field. Field invocations may be - chained: - .Field1.Field2 - Fields can also be evaluated on variables, including chaining: - $x.Field1.Field2 - - The name of a niladic method of the data, preceded by a period, - such as - .Method - The result is the value of invoking the method with dot as the - receiver, dot.Method(). Such a method must have one return value (of - any type) or two return values, the second of which is an os.Error. - If it has two and the returned error is non-nil, execution terminates - and an error is returned to the caller as the value of Execute. - Method invocations may be chained and combined with fields - to any depth: - .Field1.Method1.Field2.Method2 - Methods can also be evaluated on variables, including chaining: - $x.Method1.Field - - The name of a niladic function, such as - fun - The result is the value of invoking the function, fun(). The return - types and values behave as in methods. Functions and function - names are described below. - -Arguments may evaluate to any type; if they are pointers the implementation -automatically indirects to the base type when required. - -A pipeline is a possibly chained sequence of "commands". A command is a simple -value (argument) or a function or method call, possibly with multiple arguments: - - Argument - The result is the value of evaluating the argument. - .Method [Argument...] - The method can be alone or the last element of a chain but, - unlike methods in the middle of a chain, it can take arguments. - The result is the value of calling the method with the - arguments: - dot.Method(Argument1, etc.) - functionName [Argument...] - The result is the value of calling the function associated - with the name: - function(Argument1, etc.) - Functions and function names are described below. - -Pipelines - -A pipeline may be "chained" by separating a sequence of commands with pipeline -characters '|'. In a chained pipeline, the result of the each command is -passed as the last argument of the following command. The output of the final -command in the pipeline is the value of the pipeline. - -The output of a command will be either one value or two values, the second of -which has type os.Error. If that second value is present and evaluates to -non-nil, execution terminates and the error is returned to the caller of -Execute. - -Variables - -A pipeline inside an action may initialize a variable to capture the result. -The initialization has syntax - - $variable := pipeline - -where $variable is the name of the variable. An action that declares a -variable produces no output. - -If a "range" action initializes a variable, the variable is set to the -successive elements of the iteration. Also, a "range" may declare two -variables, separated by a comma: - - $index, $element := pipeline - -in which case $index and $element are set to the successive values of the -array/slice index or map key and element, respectively. Note that if there is -only one variable, it is assigned the element; this is opposite to the -convention in Go range clauses. - -A variable's scope extends to the "end" action of the control structure ("if", -"with", or "range") in which it is declared, or to the end of the template if -there is no such control structure. A template invocation does not inherit -variables from the point of its invocation. - -When execution begins, $ is set to the data argument passed to Execute, that is, -to the starting value of dot. - -Examples - -Here are some example one-line templates demonstrating pipelines and variables. -All produce the quoted word "output": - - {{"\"output\""}} - A string constant. - {{`"output"`}} - A raw string constant. - {{printf "%q" "output"}} - A function call. - {{"output" | printf "%q"}} - A function call whose final argument comes from the previous - command. - {{"put" | printf "%s%s" "out" | printf "%q"}} - A more elaborate call. - {{"output" | printf "%s" | printf "%q"}} - A longer chain. - {{with "output"}}{{printf "%q" .}}{{end}} - A with action using dot. - {{with $x := "output" | printf "%q"}}{{$x}}{{end}} - A with action that creates and uses a variable. - {{with $x := "output"}}{{printf "%q" $x}}{{end}} - A with action that uses the variable in another action. - {{with $x := "output"}}{{$x | printf "%q"}}{{end}} - The same, but pipelined. - -Functions - -During execution functions are found in three function maps: first in the -template, then in the "template set" (described below), and finally in the -global function map. By default, no functions are defined in the template or -the set but the Funcs methods can be used to add them. - -Predefined global functions are named as follows. - - and - Returns the boolean AND of its arguments by returning the - first empty argument or the last argument, that is, - "and x y" behaves as "if x then y else x". All the - arguments are evaluated. - html - Returns the escaped HTML equivalent of the textual - representation of its arguments. - index - Returns the result of indexing its first argument by the - following arguments. Thus "index x 1 2 3" is, in Go syntax, - x[1][2][3]. Each indexed item must be a map, slice, or array. - js - Returns the escaped JavaScript equivalent of the textual - representation of its arguments. - not - Returns the boolean negation of its single argument. - or - Returns the boolean OR of its arguments by returning the - first non-empty argument or the last argument, that is, - "or x y" behaves as "if x then x else y". All the - arguments are evaluated. - print - An alias for fmt.Sprint - printf - An alias for fmt.Sprintf - println - An alias for fmt.Sprintln - url - Returns the escaped value of the textual representation of - its arguments in a form suitable for embedding in a URL. - -The boolean functions take any zero value to be false and a non-zero value to -be true. - -Template sets - -Each template is named by a string specified when it is created. A template may -use a template invocation to instantiate another template directly or by its -name; see the explanation of the template action above. The name is looked up -in the template set associated with the template. - -If no template invocation actions occur in the template, the issue of template -sets can be ignored. If it does contain invocations, though, the template -containing the invocations must be part of a template set in which to look up -the names. - -There are two ways to construct template sets. - -The first is to use a Set's Parse method to create a set of named templates from -a single input defining multiple templates. The syntax of the definitions is to -surround each template declaration with a define and end action. - -The define action names the template being created by providing a string -constant. Here is a simple example of input to Set.Parse: - - `{{define "T1"}} definition of template T1 {{end}} - {{define "T2"}} definition of template T2 {{end}} - {{define "T3"}} {{template "T1"}} {{template "T2"}} {{end}}` - -This defines two templates, T1 and T2, and a third T3 that invokes the other two -when it is executed. - -The second way to build a template set is to use Set's Add method to add a -parsed template to a set. A template may be bound at most one set. If it's -necessary to have a template in multiple sets, the template definition must be -parsed multiple times to create distinct *Template values. - -Set.Parse may be called multiple times on different inputs to construct the set. -Two sets may therefore be constructed with a common base set of templates plus, -through a second Parse call each, specializations for some elements. - -A template may be executed directly or through Set.Execute, which executes a -named template from the set. To invoke our example above, we might write, - - err := set.Execute(os.Stdout, "T3", "no data needed") - if err != nil { - log.Fatalf("execution failed: %s", err) - } -*/ -package template diff --git a/src/pkg/exp/template/parse/Makefile b/src/pkg/exp/template/html/Makefile index 5483a0cf9..2f107da11 100644 --- a/src/pkg/exp/template/parse/Makefile +++ b/src/pkg/exp/template/html/Makefile @@ -4,11 +4,8 @@ include ../../../../Make.inc -TARG=exp/template/parse +TARG=exp/template/html GOFILES=\ - lex.go\ - node.go\ - parse.go\ - set.go\ + escape.go include ../../../../Make.pkg diff --git a/src/pkg/exp/template/html/context.go b/src/pkg/exp/template/html/context.go new file mode 100644 index 000000000..411006883 --- /dev/null +++ b/src/pkg/exp/template/html/context.go @@ -0,0 +1,98 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package html + +import ( + "fmt" +) + +// context describes the state an HTML parser must be in when it reaches the +// portion of HTML produced by evaluating a particular template node. +// +// The zero value of type context is the start context for a template that +// produces an HTML fragment as defined at +// http://www.w3.org/TR/html5/the-end.html#parsing-html-fragments +// where the context element is null. +type context struct { + state state + delim delim +} + +func (c context) String() string { + return fmt.Sprintf("context{state: %s, delim: %s", c.state, c.delim) +} + +// eq is true if the two contexts are identical field-wise. +func (c context) eq(d context) bool { + return c.state == d.state && c.delim == d.delim +} + +// state describes a high-level HTML parser state. +// +// It bounds the top of the element stack, and by extension the HTML +// insertion mode, but also contains state that does not correspond to +// anything in the HTML5 parsing algorithm because a single token +// production in the HTML grammar may contain embedded actions in a template. +// For instance, the quoted HTML attribute produced by +// <div title="Hello {{.World}}"> +// is a single token in HTML's grammar but in a template spans several nodes. +type state uint8 + +const ( + // statePCDATA is parsed character data. An HTML parser is in + // this state when its parse position is outside an HTML tag, + // directive, comment, and special element body. + statePCDATA state = iota + // stateTag occurs before an HTML attribute or the end of a tag. + stateTag + // stateURI occurs inside an HTML attribute whose content is a URI. + stateURI + // stateError is an infectious error state outside any valid + // HTML/CSS/JS construct. + stateError +) + +var stateNames = [...]string{ + statePCDATA: "statePCDATA", + stateTag: "stateTag", + stateURI: "stateURI", + stateError: "stateError", +} + +func (s state) String() string { + if uint(s) < uint(len(stateNames)) { + return stateNames[s] + } + return fmt.Sprintf("illegal state %d", uint(s)) +} + +// delim is the delimiter that will end the current HTML attribute. +type delim uint8 + +const ( + // delimNone occurs outside any attribute. + delimNone delim = iota + // delimDoubleQuote occurs when a double quote (") closes the attribute. + delimDoubleQuote + // delimSingleQuote occurs when a single quote (') closes the attribute. + delimSingleQuote + // delimSpaceOrTagEnd occurs when a space or right angle bracket (>) + // closes the attribute. + delimSpaceOrTagEnd +) + +var delimNames = [...]string{ + delimNone: "delimNone", + delimDoubleQuote: "delimDoubleQuote", + delimSingleQuote: "delimSingleQuote", + delimSpaceOrTagEnd: "delimSpaceOrTagEnd", +} + +func (d delim) String() string { + if uint(d) < uint(len(delimNames)) { + return delimNames[d] + } + return fmt.Sprintf("illegal delim %d", uint(d)) +} diff --git a/src/pkg/exp/template/html/escape.go b/src/pkg/exp/template/html/escape.go new file mode 100644 index 000000000..e0e87b98d --- /dev/null +++ b/src/pkg/exp/template/html/escape.go @@ -0,0 +1,105 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package html is a specialization of exp/template that automates the +// construction of safe HTML output. +// At the moment, the escaping is naive. All dynamic content is assumed to be +// plain text interpolated in an HTML PCDATA context. +package html + +import ( + "template" + "template/parse" +) + +// Escape rewrites each action in the template to guarantee the output is +// HTML-escaped. +func Escape(t *template.Template) { + // If the parser shares trees based on common-subexpression + // joining then we will need to avoid multiply escaping the same action. + escapeListNode(t.Tree.Root) +} + +// escapeNode dispatches to escape<NodeType> helpers by type. +func escapeNode(node parse.Node) { + switch n := node.(type) { + case *parse.ListNode: + escapeListNode(n) + case *parse.TextNode: + // Nothing to do. + case *parse.ActionNode: + escapeActionNode(n) + case *parse.IfNode: + escapeIfNode(n) + case *parse.RangeNode: + escapeRangeNode(n) + case *parse.TemplateNode: + // Nothing to do. + case *parse.WithNode: + escapeWithNode(n) + default: + panic("handling for " + node.String() + " not implemented") + // TODO: Handle other inner node types. + } +} + +// escapeListNode recursively escapes its input's children. +func escapeListNode(node *parse.ListNode) { + if node == nil { + return + } + children := node.Nodes + for _, child := range children { + escapeNode(child) + } +} + +// escapeActionNode adds a pipeline call to the end that escapes the result +// of the expression before it is interpolated into the template output. +func escapeActionNode(node *parse.ActionNode) { + pipe := node.Pipe + + cmds := pipe.Cmds + nCmds := len(cmds) + + // If it already has an escaping command, do not interfere. + if nCmds != 0 { + if lastCmd := cmds[nCmds-1]; len(lastCmd.Args) != 0 { + // TODO: Recognize url and js as escaping functions once + // we have enough context to know whether additional + // escaping is necessary. + if arg, ok := lastCmd.Args[0].(*parse.IdentifierNode); ok && arg.Ident == "html" { + return + } + } + } + + htmlEscapeCommand := parse.CommandNode{ + NodeType: parse.NodeCommand, + Args: []parse.Node{parse.NewIdentifier("html")}, + } + + node.Pipe.Cmds = append(node.Pipe.Cmds, &htmlEscapeCommand) +} + +// escapeIfNode recursively escapes the if and then clauses but leaves the +// condition unchanged. +func escapeIfNode(node *parse.IfNode) { + escapeListNode(node.List) + escapeListNode(node.ElseList) +} + +// escapeRangeNode recursively escapes the loop body and else clause but +// leaves the series unchanged. +func escapeRangeNode(node *parse.RangeNode) { + escapeListNode(node.List) + escapeListNode(node.ElseList) +} + +// escapeWithNode recursively escapes the scope body and else clause but +// leaves the pipeline unchanged. +func escapeWithNode(node *parse.WithNode) { + escapeListNode(node.List) + escapeListNode(node.ElseList) +} diff --git a/src/pkg/exp/template/html/escape_test.go b/src/pkg/exp/template/html/escape_test.go new file mode 100644 index 000000000..345a752a8 --- /dev/null +++ b/src/pkg/exp/template/html/escape_test.go @@ -0,0 +1,75 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package html + +import ( + "bytes" + "template" + "testing" +) + +type data struct { + F, T bool + C, G, H string + A, E []string +} + +var testData = data{ + F: false, + T: true, + C: "<Cincinatti>", + G: "<Goodbye>", + H: "<Hello>", + A: []string{"<a>", "<b>"}, + E: []string{}, +} + +type testCase struct { + name string + input string + output string +} + +var testCases = []testCase{ + {"if", "{{if .T}}Hello{{end}}, {{.C}}!", "Hello, <Cincinatti>!"}, + {"else", "{{if .F}}{{.H}}{{else}}{{.G}}{{end}}!", "<Goodbye>!"}, + {"overescaping", "Hello, {{.C | html}}!", "Hello, <Cincinatti>!"}, + {"assignment", "{{if $x := .H}}{{$x}}{{end}}", "<Hello>"}, + {"withBody", "{{with .H}}{{.}}{{end}}", "<Hello>"}, + {"withElse", "{{with .E}}{{.}}{{else}}{{.H}}{{end}}", "<Hello>"}, + {"rangeBody", "{{range .A}}{{.}}{{end}}", "<a><b>"}, + {"rangeElse", "{{range .E}}{{.}}{{else}}{{.H}}{{end}}", "<Hello>"}, + {"nonStringValue", "{{.T}}", "true"}, + {"constant", `<a href="{{"'str'"}}">`, `<a href="'str'">`}, +} + +func TestAutoesc(t *testing.T) { + for _, testCase := range testCases { + name := testCase.name + tmpl := template.New(name) + tmpl, err := tmpl.Parse(testCase.input) + if err != nil { + t.Errorf("%s: failed to parse template: %s", name, err) + continue + } + + Escape(tmpl) + + buffer := new(bytes.Buffer) + + err = tmpl.Execute(buffer, testData) + if err != nil { + t.Errorf("%s: template execution failed: %s", name, err) + continue + } + + output := testCase.output + actual := buffer.String() + if output != actual { + t.Errorf("%s: escaped output: %q != %q", + name, output, actual) + } + } +} diff --git a/src/pkg/exp/template/parse.go b/src/pkg/exp/template/parse.go deleted file mode 100644 index 6db00c1c1..000000000 --- a/src/pkg/exp/template/parse.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package template - -import ( - "exp/template/parse" - "os" - "reflect" -) - -// Template is the representation of a parsed template. -type Template struct { - name string - *parse.Tree - // We use two maps, one for parsing and one for execution. - // This separation makes the API cleaner since it doesn't - // expose reflection to the client. - parseFuncs FuncMap - execFuncs map[string]reflect.Value - set *Set // can be nil. -} - -// Name returns the name of the template. -func (t *Template) Name() string { - return t.Tree.Name -} - -// Parsing. - -// New allocates a new template with the given name. -func New(name string) *Template { - return &Template{ - name: name, - parseFuncs: make(FuncMap), - execFuncs: make(map[string]reflect.Value), - } -} - -// Funcs adds the elements of the argument map to the template's function -// map. It panics if a value in the map is not a function with appropriate -// return type. -// The return value is the template, so calls can be chained. -func (t *Template) Funcs(funcMap FuncMap) *Template { - addValueFuncs(t.execFuncs, funcMap) - addFuncs(t.parseFuncs, funcMap) - return t -} - -// Parse parses the template definition string to construct an internal -// representation of the template for execution. -func (t *Template) Parse(s string) (tmpl *Template, err os.Error) { - t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, builtins) - if err != nil { - return nil, err - } - return t, nil -} - -// ParseInSet parses the template definition string to construct an internal -// representation of the template for execution. It also adds the template -// to the set. -// Function bindings are checked against those in the set. -func (t *Template) ParseInSet(s string, set *Set) (tmpl *Template, err os.Error) { - var setFuncs FuncMap - if set != nil { - setFuncs = set.parseFuncs - } - t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, setFuncs, builtins) - if err != nil { - return nil, err - } - t.addToSet(set) - return t, nil -} - -// addToSet adds the template to the set, verifying it's not being double-assigned. -func (t *Template) addToSet(set *Set) { - if set == nil || t.set == set { - return - } - // If double-assigned, Add will panic and we will turn that into an error. - set.Add(t) -} diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go index 2a24b1455..e1989226b 100644 --- a/src/pkg/go/doc/comment.go +++ b/src/pkg/go/doc/comment.go @@ -11,7 +11,7 @@ import ( "io" "regexp" "strings" - "template" // for htmlEscape + "template" // for HTMLEscape ) func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' } diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index 618a15076..9c14d1667 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -420,10 +420,10 @@ func (p *parser) parseExprList(lhs bool) (list []ast.Expr) { defer un(trace(p, "ExpressionList")) } - list = append(list, p.parseExpr(lhs)) + list = append(list, p.checkExpr(p.parseExpr(lhs))) for p.tok == token.COMMA { p.next() - list = append(list, p.parseExpr(lhs)) + list = append(list, p.checkExpr(p.parseExpr(lhs))) } return @@ -973,7 +973,7 @@ func (p *parser) parseOperand(lhs bool) ast.Expr { lparen := p.pos p.next() p.exprLev++ - x := p.parseRhs() + x := p.parseRhsOrType() // types may be parenthesized: (some type) p.exprLev-- rparen := p.expect(token.RPAREN) return &ast.ParenExpr{lparen, x, rparen} @@ -1062,7 +1062,7 @@ func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr { var list []ast.Expr var ellipsis token.Pos for p.tok != token.RPAREN && p.tok != token.EOF && !ellipsis.IsValid() { - list = append(list, p.parseRhs()) + list = append(list, p.parseRhsOrType()) // builtins may expect a type: make(some type, ...) if p.tok == token.ELLIPSIS { ellipsis = p.pos p.next() @@ -1087,7 +1087,7 @@ func (p *parser) parseElement(keyOk bool) ast.Expr { return p.parseLiteralValue(nil) } - x := p.parseExpr(keyOk) // don't resolve if map key + x := p.checkExpr(p.parseExpr(keyOk)) // don't resolve if map key if keyOk { if p.tok == token.COLON { colon := p.pos @@ -1146,19 +1146,14 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { case *ast.IndexExpr: case *ast.SliceExpr: case *ast.TypeAssertExpr: - if t.Type == nil { - // the form X.(type) is only allowed in type switch expressions - p.errorExpected(x.Pos(), "expression") - x = &ast.BadExpr{x.Pos(), x.End()} - } + // If t.Type == nil we have a type assertion of the form + // y.(type), which is only allowed in type switch expressions. + // It's hard to exclude those but for the case where we are in + // a type switch. Instead be lenient and test this in the type + // checker. case *ast.CallExpr: case *ast.StarExpr: case *ast.UnaryExpr: - if t.Op == token.RANGE { - // the range operator is only allowed at the top of a for statement - p.errorExpected(x.Pos(), "expression") - x = &ast.BadExpr{x.Pos(), x.End()} - } case *ast.BinaryExpr: default: // all other nodes are not proper expressions @@ -1223,11 +1218,6 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr { case *ast.ParenExpr: panic("unreachable") case *ast.UnaryExpr: - if t.Op == token.RANGE { - // the range operator is only allowed at the top of a for statement - p.errorExpected(x.Pos(), "expression") - x = &ast.BadExpr{x.Pos(), x.End()} - } case *ast.ArrayType: if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis { p.error(len.Pos(), "expected array length, found '...'") @@ -1300,7 +1290,7 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr { } switch p.tok { - case token.ADD, token.SUB, token.NOT, token.XOR, token.AND, token.RANGE: + case token.ADD, token.SUB, token.NOT, token.XOR, token.AND: pos, op := p.pos, p.tok p.next() x := p.parseUnaryExpr(false) @@ -1354,8 +1344,9 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr { } // If lhs is set and the result is an identifier, it is not resolved. -// TODO(gri): parseExpr may return a type or even a raw type ([..]int) - -// should reject when a type/raw type is obviously not allowed +// The result may be a type or even a raw type ([...]int). Callers must +// check the result (using checkExpr or checkExprOrType), depending on +// context. func (p *parser) parseExpr(lhs bool) ast.Expr { if p.trace { defer un(trace(p, "Expression")) @@ -1365,13 +1356,28 @@ func (p *parser) parseExpr(lhs bool) ast.Expr { } func (p *parser) parseRhs() ast.Expr { - return p.parseExpr(false) + return p.checkExpr(p.parseExpr(false)) +} + +func (p *parser) parseRhsOrType() ast.Expr { + return p.checkExprOrType(p.parseExpr(false)) } // ---------------------------------------------------------------------------- // Statements -func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt { +// Parsing modes for parseSimpleStmt. +const ( + basic = iota + labelOk + rangeOk +) + +// parseSimpleStmt returns true as 2nd result if it parsed the assignment +// of a range clause (with mode == rangeOk). The returned statement is an +// assignment with a right-hand side that is a single unary expression of +// the form "range x". No guarantees are given for the left-hand side. +func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) { if p.trace { defer un(trace(p, "SimpleStmt")) } @@ -1384,11 +1390,20 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt { token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN: - // assignment statement + // assignment statement, possibly part of a range clause pos, tok := p.pos, p.tok p.next() - y := p.parseRhsList() - return &ast.AssignStmt{x, pos, tok, y} + var y []ast.Expr + isRange := false + if mode == rangeOk && p.tok == token.RANGE && (tok == token.DEFINE || tok == token.ASSIGN) { + pos := p.pos + p.next() + y = []ast.Expr{&ast.UnaryExpr{pos, token.RANGE, p.parseRhs()}} + isRange = true + } else { + y = p.parseRhsList() + } + return &ast.AssignStmt{x, pos, tok, y}, isRange } if len(x) > 1 { @@ -1401,13 +1416,13 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt { // labeled statement colon := p.pos p.next() - if label, isIdent := x[0].(*ast.Ident); labelOk && isIdent { + if label, isIdent := x[0].(*ast.Ident); mode == labelOk && isIdent { // Go spec: The scope of a label is the body of the function // in which it is declared and excludes the body of any nested // function. stmt := &ast.LabeledStmt{label, colon, p.parseStmt()} p.declare(stmt, nil, p.labelScope, ast.Lbl, label) - return stmt + return stmt, false } // The label declaration typically starts at x[0].Pos(), but the label // declaration may be erroneous due to a token after that position (and @@ -1416,28 +1431,28 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt { // before the ':' that caused the problem. Thus, use the (latest) colon // position for error reporting. p.error(colon, "illegal label declaration") - return &ast.BadStmt{x[0].Pos(), colon + 1} + return &ast.BadStmt{x[0].Pos(), colon + 1}, false case token.ARROW: // send statement arrow := p.pos p.next() // consume "<-" y := p.parseRhs() - return &ast.SendStmt{x[0], arrow, y} + return &ast.SendStmt{x[0], arrow, y}, false case token.INC, token.DEC: // increment or decrement s := &ast.IncDecStmt{x[0], p.pos, p.tok} p.next() // consume "++" or "--" - return s + return s, false } // expression - return &ast.ExprStmt{x[0]} + return &ast.ExprStmt{x[0]}, false } func (p *parser) parseCallExpr() *ast.CallExpr { - x := p.parseRhs() + x := p.parseRhsOrType() // could be a conversion: (some type)(x) if call, isCall := x.(*ast.CallExpr); isCall { return call } @@ -1538,7 +1553,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt { p.next() x = p.parseRhs() } else { - s = p.parseSimpleStmt(false) + s, _ = p.parseSimpleStmt(basic) if p.tok == token.SEMICOLON { p.next() x = p.parseRhs() @@ -1629,14 +1644,14 @@ func (p *parser) parseSwitchStmt() ast.Stmt { prevLev := p.exprLev p.exprLev = -1 if p.tok != token.SEMICOLON { - s2 = p.parseSimpleStmt(false) + s2, _ = p.parseSimpleStmt(basic) } if p.tok == token.SEMICOLON { p.next() s1 = s2 s2 = nil if p.tok != token.LBRACE { - s2 = p.parseSimpleStmt(false) + s2, _ = p.parseSimpleStmt(basic) } } p.exprLev = prevLev @@ -1749,22 +1764,23 @@ func (p *parser) parseForStmt() ast.Stmt { defer p.closeScope() var s1, s2, s3 ast.Stmt + var isRange bool if p.tok != token.LBRACE { prevLev := p.exprLev p.exprLev = -1 if p.tok != token.SEMICOLON { - s2 = p.parseSimpleStmt(false) + s2, isRange = p.parseSimpleStmt(rangeOk) } - if p.tok == token.SEMICOLON { + if !isRange && p.tok == token.SEMICOLON { p.next() s1 = s2 s2 = nil if p.tok != token.SEMICOLON { - s2 = p.parseSimpleStmt(false) + s2, _ = p.parseSimpleStmt(basic) } p.expectSemi() if p.tok != token.LBRACE { - s3 = p.parseSimpleStmt(false) + s3, _ = p.parseSimpleStmt(basic) } } p.exprLev = prevLev @@ -1773,12 +1789,8 @@ func (p *parser) parseForStmt() ast.Stmt { body := p.parseBlockStmt() p.expectSemi() - if as, isAssign := s2.(*ast.AssignStmt); isAssign { - // possibly a for statement with a range clause; check assignment operator - if as.Tok != token.ASSIGN && as.Tok != token.DEFINE { - p.errorExpected(as.TokPos, "'=' or ':='") - return &ast.BadStmt{pos, body.End()} - } + if isRange { + as := s2.(*ast.AssignStmt) // check lhs var key, value ast.Expr switch len(as.Lhs) { @@ -1790,18 +1802,10 @@ func (p *parser) parseForStmt() ast.Stmt { p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions") return &ast.BadStmt{pos, body.End()} } - // check rhs - if len(as.Rhs) != 1 { - p.errorExpected(as.Rhs[0].Pos(), "1 expression") - return &ast.BadStmt{pos, body.End()} - } - if rhs, isUnary := as.Rhs[0].(*ast.UnaryExpr); isUnary && rhs.Op == token.RANGE { - // rhs is range expression - // (any short variable declaration was handled by parseSimpleStat above) - return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body} - } - p.errorExpected(s2.Pos(), "range clause") - return &ast.BadStmt{pos, body.End()} + // parseSimpleStmt returned a right-hand side that + // is a single unary expression of the form "range x" + x := as.Rhs[0].(*ast.UnaryExpr).X + return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, x, body} } // regular for statement @@ -1821,7 +1825,7 @@ func (p *parser) parseStmt() (s ast.Stmt) { token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operand token.LBRACK, token.STRUCT, // composite type token.MUL, token.AND, token.ARROW, token.ADD, token.SUB, token.XOR: // unary operators - s = p.parseSimpleStmt(true) + s, _ = p.parseSimpleStmt(labelOk) // because of the required look-ahead, labeled statements are // parsed by parseSimpleStmt - don't expect a semicolon after // them @@ -2153,6 +2157,5 @@ func (p *parser) parseFile() *ast.File { } } - // TODO(gri): store p.imports in AST return &ast.File{doc, pos, ident, decls, p.pkgScope, p.imports, p.unresolved[0:i], p.comments} } diff --git a/src/pkg/go/parser/parser_test.go b/src/pkg/go/parser/parser_test.go index 8269db839..39a78e515 100644 --- a/src/pkg/go/parser/parser_test.go +++ b/src/pkg/go/parser/parser_test.go @@ -21,6 +21,24 @@ var illegalInputs = []interface{}{ `package p; func f() { if ; /* should have condition */ {} };`, `package p; func f() { if f(); /* should have condition */ {} };`, `package p; const c; /* should have constant value */`, + `package p; func f() { if _ = range x; true {} };`, + `package p; func f() { switch _ = range x; true {} };`, + `package p; func f() { for _ = range x ; ; {} };`, + `package p; func f() { for ; ; _ = range x {} };`, + `package p; func f() { for ; _ = range x ; {} };`, + `package p; var a = [1]int; /* illegal expression */`, + `package p; var a = [...]int; /* illegal expression */`, + `package p; var a = struct{} /* illegal expression */`, + `package p; var a = func(); /* illegal expression */`, + `package p; var a = interface{} /* illegal expression */`, + `package p; var a = []int /* illegal expression */`, + `package p; var a = map[int]int /* illegal expression */`, + `package p; var a = chan int; /* illegal expression */`, + `package p; var a = []int{[]int}; /* illegal expression */`, + `package p; var a = ([]int); /* illegal expression */`, + `package p; var a = a[[]int:[]int]; /* illegal expression */`, + `package p; var a = <- chan int; /* illegal expression */`, + `package p; func f() { select { case _ <- chan int: } };`, } func TestParseIllegalInputs(t *testing.T) { @@ -51,6 +69,7 @@ var validPrograms = []interface{}{ `package p; func f() { select { case x := (<-c): } };`, `package p; func f() { if ; true {} };`, `package p; func f() { switch ; {} };`, + `package p; func f() { for _ = range "foo" + "bar" {} };`, } func TestParseValidPrograms(t *testing.T) { diff --git a/src/pkg/html/token.go b/src/pkg/html/token.go index fddc922d6..d266b3a30 100644 --- a/src/pkg/html/token.go +++ b/src/pkg/html/token.go @@ -429,7 +429,7 @@ loop: for ; i < z.p1; i++ { c := z.buf[i] switch c { - case '<', '>', '"', '\'', '/', '=': + case '>', '/', '=': break loop } switch { diff --git a/src/pkg/html/token_test.go b/src/pkg/html/token_test.go index 1330f3247..0a0beb201 100644 --- a/src/pkg/html/token_test.go +++ b/src/pkg/html/token_test.go @@ -49,14 +49,24 @@ var tokenTests = []tokenTest{ }, { "malformed tag #1", + `<p </p>`, + `<p <="" p="">`, + }, + { + "malformed tag #2", `<p id=0</p>`, `<p id="0</p">`, }, { - "malformed tag #2", + "malformed tag #3", `<p id="0</p>`, `<p id="0</p>">`, }, + { + "malformed tag #4", + `<p id="0"</p>`, + `<p id="0" <="" p="">`, + }, // Comments. { "comment0", diff --git a/src/pkg/http/Makefile b/src/pkg/http/Makefile index b8bc093d4..df4ab9510 100644 --- a/src/pkg/http/Makefile +++ b/src/pkg/http/Makefile @@ -22,6 +22,5 @@ GOFILES=\ status.go\ transfer.go\ transport.go\ - url.go\ include ../../Make.pkg diff --git a/src/pkg/http/cgi/child.go b/src/pkg/http/cgi/child.go index 8b74d7054..8d0eca8d5 100644 --- a/src/pkg/http/cgi/child.go +++ b/src/pkg/http/cgi/child.go @@ -18,6 +18,7 @@ import ( "os" "strconv" "strings" + "url" ) // Request returns the HTTP request as represented in the current @@ -93,7 +94,7 @@ func RequestFromMap(params map[string]string) (*http.Request, os.Error) { // Hostname is provided, so we can reasonably construct a URL, // even if we have to assume 'http' for the scheme. r.RawURL = "http://" + r.Host + params["REQUEST_URI"] - url, err := http.ParseURL(r.RawURL) + url, err := url.Parse(r.RawURL) if err != nil { return nil, os.NewError("cgi: failed to parse host and REQUEST_URI into a URL: " + r.RawURL) } @@ -103,7 +104,7 @@ func RequestFromMap(params map[string]string) (*http.Request, os.Error) { // failed to parse if r.URL == nil { r.RawURL = params["REQUEST_URI"] - url, err := http.ParseURL(r.RawURL) + url, err := url.Parse(r.RawURL) if err != nil { return nil, os.NewError("cgi: failed to parse REQUEST_URI into a URL: " + r.RawURL) } diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go index 93825b391..f7de89f99 100644 --- a/src/pkg/http/cgi/host.go +++ b/src/pkg/http/cgi/host.go @@ -276,7 +276,7 @@ func (h *Handler) printf(format string, v ...interface{}) { } func (h *Handler) handleInternalRedirect(rw http.ResponseWriter, req *http.Request, path string) { - url, err := req.URL.ParseURL(path) + url, err := req.URL.Parse(path) if err != nil { rw.WriteHeader(http.StatusInternalServerError) h.printf("cgi: error resolving local URI path %q: %v", path, err) diff --git a/src/pkg/http/client.go b/src/pkg/http/client.go index 6ea7dee03..44b3443fc 100644 --- a/src/pkg/http/client.go +++ b/src/pkg/http/client.go @@ -12,6 +12,7 @@ import ( "io" "os" "strings" + "url" ) // A Client is an HTTP client. Its zero value (DefaultClient) is a usable client @@ -158,7 +159,7 @@ func (c *Client) Get(url string) (r *Response, err os.Error) { func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err os.Error) { // TODO: if/when we add cookie support, the redirected request shouldn't // necessarily supply the same cookies as the original. - var base *URL + var base *url.URL redirectChecker := c.CheckRedirect if redirectChecker == nil { redirectChecker = defaultCheckRedirect @@ -166,13 +167,13 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err os.Error) var via []*Request req := ireq - url := "" // next relative or absolute URL to fetch (after first request) + urlStr := "" // next relative or absolute URL to fetch (after first request) for redirect := 0; ; redirect++ { if redirect != 0 { req = new(Request) req.Method = ireq.Method req.Header = make(Header) - req.URL, err = base.ParseURL(url) + req.URL, err = base.Parse(urlStr) if err != nil { break } @@ -190,13 +191,13 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err os.Error) } } - url = req.URL.String() + urlStr = req.URL.String() if r, err = send(req, c.Transport); err != nil { break } if shouldRedirect(r.StatusCode) { r.Body.Close() - if url = r.Header.Get("Location"); url == "" { + if urlStr = r.Header.Get("Location"); urlStr == "" { err = os.NewError(fmt.Sprintf("%d response missing Location header", r.StatusCode)) break } @@ -208,7 +209,7 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err os.Error) } method := ireq.Method - err = &URLError{method[0:1] + strings.ToLower(method[1:]), url, err} + err = &url.Error{method[0:1] + strings.ToLower(method[1:]), urlStr, err} return } @@ -246,7 +247,7 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, // Caller should close r.Body when done reading from it. // // PostForm is a wrapper around DefaultClient.PostForm -func PostForm(url string, data Values) (r *Response, err os.Error) { +func PostForm(url string, data url.Values) (r *Response, err os.Error) { return DefaultClient.PostForm(url, data) } @@ -254,7 +255,7 @@ func PostForm(url string, data Values) (r *Response, err os.Error) { // with data's keys and values urlencoded as the request body. // // Caller should close r.Body when done reading from it. -func (c *Client) PostForm(url string, data Values) (r *Response, err os.Error) { +func (c *Client) PostForm(url string, data url.Values) (r *Response, err os.Error) { return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) } diff --git a/src/pkg/http/client_test.go b/src/pkg/http/client_test.go index 3b8558535..f22cce50b 100644 --- a/src/pkg/http/client_test.go +++ b/src/pkg/http/client_test.go @@ -17,6 +17,7 @@ import ( "strconv" "strings" "testing" + "url" ) var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) { @@ -109,18 +110,18 @@ func TestPostFormRequestFormat(t *testing.T) { tr := &recordingTransport{} client := &Client{Transport: tr} - url := "http://dummy.faketld/" - form := make(Values) + urlStr := "http://dummy.faketld/" + form := make(url.Values) form.Set("foo", "bar") form.Add("foo", "bar2") form.Set("bar", "baz") - client.PostForm(url, form) // Note: doesn't hit network + client.PostForm(urlStr, form) // Note: doesn't hit network if tr.req.Method != "POST" { t.Errorf("got method %q, want %q", tr.req.Method, "POST") } - if tr.req.URL.String() != url { - t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) + if tr.req.URL.String() != urlStr { + t.Errorf("got URL %q, want %q", tr.req.URL.String(), urlStr) } if tr.req.Header == nil { t.Fatalf("expected non-nil request Header") @@ -281,7 +282,7 @@ func TestClientWrites(t *testing.T) { } writes = 0 - _, err = c.PostForm(ts.URL, Values{"foo": {"bar"}}) + _, err = c.PostForm(ts.URL, url.Values{"foo": {"bar"}}) if err != nil { t.Fatal(err) } diff --git a/src/pkg/http/fs_test.go b/src/pkg/http/fs_test.go index 823770ec4..bb6d0158b 100644 --- a/src/pkg/http/fs_test.go +++ b/src/pkg/http/fs_test.go @@ -13,6 +13,7 @@ import ( "path/filepath" "strings" "testing" + "url" ) const ( @@ -49,7 +50,7 @@ func TestServeFile(t *testing.T) { // set up the Request (re-used for all tests) var req Request req.Header = make(Header) - if req.URL, err = ParseURL(ts.URL); err != nil { + if req.URL, err = url.Parse(ts.URL); err != nil { t.Fatal("ParseURL:", err) } req.Method = "GET" diff --git a/src/pkg/http/readrequest_test.go b/src/pkg/http/readrequest_test.go index 79f8de70d..f6dc99e2e 100644 --- a/src/pkg/http/readrequest_test.go +++ b/src/pkg/http/readrequest_test.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "testing" + "url" ) type reqTest struct { @@ -40,7 +41,7 @@ var reqTests = []reqTest{ &Request{ Method: "GET", RawURL: "http://www.techcrunch.com/", - URL: &URL{ + URL: &url.URL{ Raw: "http://www.techcrunch.com/", Scheme: "http", RawPath: "/", @@ -67,7 +68,7 @@ var reqTests = []reqTest{ Close: false, ContentLength: 7, Host: "www.techcrunch.com", - Form: Values{}, + Form: url.Values{}, }, "abcdef\n", @@ -83,7 +84,7 @@ var reqTests = []reqTest{ &Request{ Method: "GET", RawURL: "/", - URL: &URL{ + URL: &url.URL{ Raw: "/", Path: "/", RawPath: "/", @@ -94,7 +95,7 @@ var reqTests = []reqTest{ Close: false, ContentLength: 0, Host: "foo.com", - Form: Values{}, + Form: url.Values{}, }, noBody, @@ -110,7 +111,7 @@ var reqTests = []reqTest{ &Request{ Method: "GET", RawURL: "//user@host/is/actually/a/path/", - URL: &URL{ + URL: &url.URL{ Raw: "//user@host/is/actually/a/path/", Scheme: "", RawPath: "//user@host/is/actually/a/path/", @@ -128,7 +129,7 @@ var reqTests = []reqTest{ Close: false, ContentLength: 0, Host: "test", - Form: Values{}, + Form: url.Values{}, }, noBody, diff --git a/src/pkg/http/request.go b/src/pkg/http/request.go index a1c98a1f8..ed41fa45c 100644 --- a/src/pkg/http/request.go +++ b/src/pkg/http/request.go @@ -22,6 +22,7 @@ import ( "os" "strconv" "strings" + "url" ) const ( @@ -72,9 +73,9 @@ var reqWriteExcludeHeader = map[string]bool{ // A Request represents a parsed HTTP request header. type Request struct { - Method string // GET, POST, PUT, etc. - RawURL string // The raw URL given in the request. - URL *URL // Parsed URL. + Method string // GET, POST, PUT, etc. + RawURL string // The raw URL given in the request. + URL *url.URL // Parsed URL. // The protocol version for incoming requests. // Outgoing requests always use HTTP/1.1. @@ -124,7 +125,7 @@ type Request struct { Host string // The parsed form. Only available after ParseForm is called. - Form Values + Form url.Values // The parsed multipart form, including file uploads. // Only available after ParseMultipartForm is called. @@ -289,22 +290,22 @@ func (req *Request) write(w io.Writer, usingProxy bool) os.Error { host = req.URL.Host } - uri := req.RawURL - if uri == "" { - uri = valueOrDefault(urlEscape(req.URL.Path, encodePath), "/") + urlStr := req.RawURL + if urlStr == "" { + urlStr = valueOrDefault(req.URL.EncodedPath(), "/") if req.URL.RawQuery != "" { - uri += "?" + req.URL.RawQuery + urlStr += "?" + req.URL.RawQuery } if usingProxy { - if uri == "" || uri[0] != '/' { - uri = "/" + uri + if urlStr == "" || urlStr[0] != '/' { + urlStr = "/" + urlStr } - uri = req.URL.Scheme + "://" + host + uri + urlStr = req.URL.Scheme + "://" + host + urlStr } } bw := bufio.NewWriter(w) - fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), uri) + fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), urlStr) // Header lines fmt.Fprintf(bw, "Host: %s\r\n", host) @@ -481,8 +482,8 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err os.Error) { } // NewRequest returns a new Request given a method, URL, and optional body. -func NewRequest(method, url string, body io.Reader) (*Request, os.Error) { - u, err := ParseURL(url) +func NewRequest(method, urlStr string, body io.Reader) (*Request, os.Error) { + u, err := url.Parse(urlStr) if err != nil { return nil, err } @@ -547,7 +548,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) { return nil, &badStringError{"malformed HTTP version", req.Proto} } - if req.URL, err = ParseRequestURL(req.RawURL); err != nil { + if req.URL, err = url.ParseRequest(req.RawURL); err != nil { return nil, err } @@ -607,77 +608,6 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) { return req, nil } -// Values maps a string key to a list of values. -// It is typically used for query parameters and form values. -// Unlike in the Header map, the keys in a Values map -// are case-sensitive. -type Values map[string][]string - -// Get gets the first value associated with the given key. -// If there are no values associated with the key, Get returns -// the empty string. To access multiple values, use the map -// directly. -func (v Values) Get(key string) string { - if v == nil { - return "" - } - vs, ok := v[key] - if !ok || len(vs) == 0 { - return "" - } - return vs[0] -} - -// Set sets the key to value. It replaces any existing -// values. -func (v Values) Set(key, value string) { - v[key] = []string{value} -} - -// Add adds the key to value. It appends to any existing -// values associated with key. -func (v Values) Add(key, value string) { - v[key] = append(v[key], value) -} - -// Del deletes the values associated with key. -func (v Values) Del(key string) { - v[key] = nil, false -} - -// ParseQuery parses the URL-encoded query string and returns -// a map listing the values specified for each key. -// ParseQuery always returns a non-nil map containing all the -// valid query parameters found; err describes the first decoding error -// encountered, if any. -func ParseQuery(query string) (m Values, err os.Error) { - m = make(Values) - err = parseQuery(m, query) - return -} - -func parseQuery(m Values, query string) (err os.Error) { - for _, kv := range strings.Split(query, "&") { - if len(kv) == 0 { - continue - } - kvPair := strings.SplitN(kv, "=", 2) - - var key, value string - var e os.Error - key, e = URLUnescape(kvPair[0]) - if e == nil && len(kvPair) > 1 { - value, e = URLUnescape(kvPair[1]) - } - if e != nil { - err = e - continue - } - m[key] = append(m[key], value) - } - return err -} - // ParseForm parses the raw query. // For POST requests, it also parses the request body as a form. // ParseMultipartForm calls ParseForm automatically. @@ -687,9 +617,8 @@ func (r *Request) ParseForm() (err os.Error) { return } - r.Form = make(Values) if r.URL != nil { - err = parseQuery(r.Form, r.URL.RawQuery) + r.Form, err = url.ParseQuery(r.URL.RawQuery) } if r.Method == "POST" { if r.Body == nil { @@ -709,10 +638,20 @@ func (r *Request) ParseForm() (err os.Error) { if int64(len(b)) > maxFormSize { return os.NewError("http: POST too large") } - e = parseQuery(r.Form, string(b)) + var newValues url.Values + newValues, e = url.ParseQuery(string(b)) if err == nil { err = e } + if r.Form == nil { + r.Form = make(url.Values) + } + // Copy values into r.Form. TODO: make this smoother. + for k, vs := range newValues { + for _, value := range vs { + r.Form.Add(k, value) + } + } case "multipart/form-data": // handled by ParseMultipartForm default: @@ -729,6 +668,9 @@ func (r *Request) ParseForm() (err os.Error) { // ParseMultipartForm calls ParseForm if necessary. // After one call to ParseMultipartForm, subsequent calls have no effect. func (r *Request) ParseMultipartForm(maxMemory int64) os.Error { + if r.MultipartForm == multipartByReader { + return os.NewError("http: multipart handled by MultipartReader") + } if r.Form == nil { err := r.ParseForm() if err != nil { @@ -738,9 +680,6 @@ func (r *Request) ParseMultipartForm(maxMemory int64) os.Error { if r.MultipartForm != nil { return nil } - if r.MultipartForm == multipartByReader { - return os.NewError("http: multipart handled by MultipartReader") - } mr, err := r.multipartReader() if err == ErrNotMultipart { diff --git a/src/pkg/http/request_test.go b/src/pkg/http/request_test.go index e03ed3b05..869cd57b6 100644 --- a/src/pkg/http/request_test.go +++ b/src/pkg/http/request_test.go @@ -17,6 +17,7 @@ import ( "regexp" "strings" "testing" + "url" ) type stringMultimap map[string][]string @@ -43,7 +44,7 @@ var parseTests = []parseTest{ func TestParseForm(t *testing.T) { for i, test := range parseTests { - form, err := ParseQuery(test.query) + form, err := url.ParseQuery(test.query) if err != nil { t.Errorf("test %d: Unexpected error: %v", i, err) continue @@ -72,7 +73,7 @@ func TestParseForm(t *testing.T) { func TestQuery(t *testing.T) { req := &Request{Method: "GET"} - req.URL, _ = ParseURL("http://www.google.com/search?q=foo&q=bar") + req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar") if q := req.FormValue("q"); q != "foo" { t.Errorf(`req.FormValue("q") = %q, want "foo"`, q) } @@ -80,7 +81,7 @@ func TestQuery(t *testing.T) { func TestPostQuery(t *testing.T) { req := &Request{Method: "POST"} - req.URL, _ = ParseURL("http://www.google.com/search?q=foo&q=bar&both=x") + req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar&both=x") req.Header = Header{ "Content-Type": {"application/x-www-form-urlencoded; boo!"}, } @@ -219,6 +220,18 @@ func TestEmptyMultipartRequest(t *testing.T) { testMissingFile(t, req) } +func TestRequestMultipartCallOrder(t *testing.T) { + req := newTestMultipartRequest(t) + _, err := req.MultipartReader() + if err != nil { + t.Fatalf("MultipartReader: %v", err) + } + err = req.ParseMultipartForm(1024) + if err == nil { + t.Errorf("expected an error from ParseMultipartForm after call to MultipartReader") + } +} + func testMissingFile(t *testing.T, req *Request) { f, fh, err := req.FormFile("missing") if f != nil { diff --git a/src/pkg/http/requestwrite_test.go b/src/pkg/http/requestwrite_test.go index 0052c0cfc..458f0bd7f 100644 --- a/src/pkg/http/requestwrite_test.go +++ b/src/pkg/http/requestwrite_test.go @@ -12,6 +12,7 @@ import ( "os" "strings" "testing" + "url" ) type reqWriteTest struct { @@ -27,7 +28,7 @@ var reqWriteTests = []reqWriteTest{ Request{ Method: "GET", RawURL: "http://www.techcrunch.com/", - URL: &URL{ + URL: &url.URL{ Raw: "http://www.techcrunch.com/", Scheme: "http", RawPath: "http://www.techcrunch.com/", @@ -82,7 +83,7 @@ var reqWriteTests = []reqWriteTest{ { Request{ Method: "GET", - URL: &URL{ + URL: &url.URL{ Scheme: "http", Host: "www.google.com", Path: "/search", @@ -111,7 +112,7 @@ var reqWriteTests = []reqWriteTest{ { Request{ Method: "POST", - URL: &URL{ + URL: &url.URL{ Scheme: "http", Host: "www.google.com", Path: "/search", @@ -144,7 +145,7 @@ var reqWriteTests = []reqWriteTest{ { Request{ Method: "POST", - URL: &URL{ + URL: &url.URL{ Scheme: "http", Host: "www.google.com", Path: "/search", diff --git a/src/pkg/http/reverseproxy.go b/src/pkg/http/reverseproxy.go index 015f87f24..3f8bfdc80 100644 --- a/src/pkg/http/reverseproxy.go +++ b/src/pkg/http/reverseproxy.go @@ -14,6 +14,7 @@ import ( "strings" "sync" "time" + "url" ) // ReverseProxy is an HTTP Handler that takes an incoming request and @@ -53,7 +54,7 @@ func singleJoiningSlash(a, b string) string { // URLs to the scheme, host, and base path provided in target. If the // target's path is "/base" and the incoming request was for "/dir", // the target request will be for /base/dir. -func NewSingleHostReverseProxy(target *URL) *ReverseProxy { +func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy { director := func(req *Request) { req.URL.Scheme = target.Scheme req.URL.Host = target.Host diff --git a/src/pkg/http/reverseproxy_test.go b/src/pkg/http/reverseproxy_test.go index b2dd24633..8078c8d10 100644 --- a/src/pkg/http/reverseproxy_test.go +++ b/src/pkg/http/reverseproxy_test.go @@ -11,6 +11,7 @@ import ( "http/httptest" "io/ioutil" "testing" + "url" ) func TestReverseProxy(t *testing.T) { @@ -32,7 +33,7 @@ func TestReverseProxy(t *testing.T) { w.Write([]byte(backendResponse)) })) defer backend.Close() - backendURL, err := ParseURL(backend.URL) + backendURL, err := url.Parse(backend.URL) if err != nil { t.Fatal(err) } diff --git a/src/pkg/http/serve_test.go b/src/pkg/http/serve_test.go index 2725c3b42..ac0403345 100644 --- a/src/pkg/http/serve_test.go +++ b/src/pkg/http/serve_test.go @@ -22,6 +22,7 @@ import ( "syscall" "testing" "time" + "url" ) type dummyAddr string @@ -183,7 +184,7 @@ func TestHostHandlers(t *testing.T) { for _, vt := range vtests { var r *Response var req Request - if req.URL, err = ParseURL(vt.url); err != nil { + if req.URL, err = url.Parse(vt.url); err != nil { t.Errorf("cannot parse url: %v", err) continue } diff --git a/src/pkg/http/server.go b/src/pkg/http/server.go index 1955b67e6..b634e27d6 100644 --- a/src/pkg/http/server.go +++ b/src/pkg/http/server.go @@ -25,6 +25,7 @@ import ( "strings" "sync" "time" + "url" ) // Errors introduced by the HTTP server. @@ -716,8 +717,8 @@ func StripPrefix(prefix string, h Handler) Handler { // Redirect replies to the request with a redirect to url, // which may be a path relative to the request path. -func Redirect(w ResponseWriter, r *Request, url string, code int) { - if u, err := ParseURL(url); err == nil { +func Redirect(w ResponseWriter, r *Request, urlStr string, code int) { + if u, err := url.Parse(urlStr); err == nil { // If url was relative, make absolute by // combining with request path. // The browser would probably do this for us, @@ -740,35 +741,35 @@ func Redirect(w ResponseWriter, r *Request, url string, code int) { } if u.Scheme == "" { // no leading http://server - if url == "" || url[0] != '/' { + if urlStr == "" || urlStr[0] != '/' { // make relative path absolute olddir, _ := path.Split(oldpath) - url = olddir + url + urlStr = olddir + urlStr } var query string - if i := strings.Index(url, "?"); i != -1 { - url, query = url[:i], url[i:] + if i := strings.Index(urlStr, "?"); i != -1 { + urlStr, query = urlStr[:i], urlStr[i:] } // clean up but preserve trailing slash - trailing := url[len(url)-1] == '/' - url = path.Clean(url) - if trailing && url[len(url)-1] != '/' { - url += "/" + trailing := urlStr[len(urlStr)-1] == '/' + urlStr = path.Clean(urlStr) + if trailing && urlStr[len(urlStr)-1] != '/' { + urlStr += "/" } - url += query + urlStr += query } } - w.Header().Set("Location", url) + w.Header().Set("Location", urlStr) w.WriteHeader(code) // RFC2616 recommends that a short note "SHOULD" be included in the // response because older user agents may not understand 301/307. // Shouldn't send the response for POST or HEAD; that leaves GET. if r.Method == "GET" { - note := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n" + note := "<a href=\"" + htmlEscape(urlStr) + "\">" + statusText[code] + "</a>.\n" fmt.Fprintln(w, note) } } diff --git a/src/pkg/http/transport.go b/src/pkg/http/transport.go index 3c16c880d..4302ffab1 100644 --- a/src/pkg/http/transport.go +++ b/src/pkg/http/transport.go @@ -17,6 +17,7 @@ import ( "os" "strings" "sync" + "url" ) // DefaultTransport is the default implementation of Transport and is @@ -46,7 +47,7 @@ type Transport struct { // Request. If the function returns a non-nil error, the // request is aborted with the provided error. // If Proxy is nil or returns a nil *URL, no proxy is used. - Proxy func(*Request) (*URL, os.Error) + Proxy func(*Request) (*url.URL, os.Error) // Dial specifies the dial function for creating TCP // connections. @@ -66,7 +67,7 @@ type Transport struct { // given request, as indicated by the environment variables // $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy). // Either URL or an error is returned. -func ProxyFromEnvironment(req *Request) (*URL, os.Error) { +func ProxyFromEnvironment(req *Request) (*url.URL, os.Error) { proxy := getenvEitherCase("HTTP_PROXY") if proxy == "" { return nil, nil @@ -74,12 +75,12 @@ func ProxyFromEnvironment(req *Request) (*URL, os.Error) { if !useProxy(canonicalAddr(req.URL)) { return nil, nil } - proxyURL, err := ParseRequestURL(proxy) + proxyURL, err := url.ParseRequest(proxy) if err != nil { return nil, os.NewError("invalid proxy address") } if proxyURL.Host == "" { - proxyURL, err = ParseRequestURL("http://" + proxy) + proxyURL, err = url.ParseRequest("http://" + proxy) if err != nil { return nil, os.NewError("invalid proxy address") } @@ -89,16 +90,16 @@ func ProxyFromEnvironment(req *Request) (*URL, os.Error) { // ProxyURL returns a proxy function (for use in a Transport) // that always returns the same URL. -func ProxyURL(url *URL) func(*Request) (*URL, os.Error) { - return func(*Request) (*URL, os.Error) { - return url, nil +func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, os.Error) { + return func(*Request) (*url.URL, os.Error) { + return fixedURL, nil } } // RoundTrip implements the RoundTripper interface. func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) { if req.URL == nil { - if req.URL, err = ParseURL(req.RawURL); err != nil { + if req.URL, err = url.Parse(req.RawURL); err != nil { return } } @@ -413,9 +414,9 @@ func useProxy(addr string) bool { // Note: no support to https to the proxy yet. // type connectMethod struct { - proxyURL *URL // "" for no proxy, else full proxy URL - targetScheme string // "http" or "https" - targetAddr string // Not used if proxy + http targetScheme (4th example in table) + proxyURL *url.URL // nil for no proxy, else full proxy URL + targetScheme string // "http" or "https" + targetAddr string // Not used if proxy + http targetScheme (4th example in table) } func (ck *connectMethod) String() string { @@ -511,6 +512,9 @@ func (pc *persistConn) readLoop() { if err != nil || resp.ContentLength == 0 { return resp, err } + if rc.addedGzip { + forReq.Header.Del("Accept-Encoding") + } if rc.addedGzip && resp.Header.Get("Content-Encoding") == "gzip" { resp.Header.Del("Content-Encoding") resp.Header.Del("Content-Length") @@ -639,7 +643,7 @@ var portMap = map[string]string{ } // canonicalAddr returns url.Host but always with a ":port" suffix -func canonicalAddr(url *URL) string { +func canonicalAddr(url *url.URL) string { addr := url.Host if !hasPort(addr) { return addr + ":" + portMap[url.Scheme] diff --git a/src/pkg/http/transport_test.go b/src/pkg/http/transport_test.go index 76e97640e..eafde7f89 100644 --- a/src/pkg/http/transport_test.go +++ b/src/pkg/http/transport_test.go @@ -20,6 +20,7 @@ import ( "strings" "testing" "time" + "url" ) // TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close @@ -77,7 +78,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) { fetch := func(n int) string { req := new(Request) var err os.Error - req.URL, err = ParseURL(ts.URL + fmt.Sprintf("?close=%v", connectionClose)) + req.URL, err = url.Parse(ts.URL + fmt.Sprintf("?close=%v", connectionClose)) if err != nil { t.Fatalf("URL parse error: %v", err) } @@ -119,7 +120,7 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) { fetch := func(n int) string { req := new(Request) var err os.Error - req.URL, err = ParseURL(ts.URL) + req.URL, err = url.Parse(ts.URL) if err != nil { t.Fatalf("URL parse error: %v", err) } @@ -387,6 +388,68 @@ func TestTransportNilURL(t *testing.T) { } } +var roundTripTests = []struct { + accept string + expectAccept string + compressed bool +}{ + // Requests with no accept-encoding header use transparent compression + {"", "gzip", false}, + // Requests with other accept-encoding should pass through unmodified + {"foo", "foo", false}, + // Requests with accept-encoding == gzip should be passed through + {"gzip", "gzip", true}} + +// Test that the modification made to the Request by the RoundTripper is cleaned up +func TestRoundTripGzip(t *testing.T) { + const responseBody = "test response body" + ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { + accept := req.Header.Get("Accept-Encoding") + if expect := req.FormValue("expect_accept"); accept != expect { + t.Errorf("Accept-Encoding = %q, want %q", accept, expect) + } + if accept == "gzip" { + rw.Header().Set("Content-Encoding", "gzip") + gz, _ := gzip.NewWriter(rw) + gz.Write([]byte(responseBody)) + gz.Close() + } else { + rw.Header().Set("Content-Encoding", accept) + rw.Write([]byte(responseBody)) + } + })) + defer ts.Close() + + for i, test := range roundTripTests { + // Test basic request (no accept-encoding) + req, _ := NewRequest("GET", ts.URL+"?expect_accept="+test.expectAccept, nil) + req.Header.Set("Accept-Encoding", test.accept) + res, err := DefaultTransport.RoundTrip(req) + var body []byte + if test.compressed { + gzip, _ := gzip.NewReader(res.Body) + body, err = ioutil.ReadAll(gzip) + res.Body.Close() + } else { + body, err = ioutil.ReadAll(res.Body) + } + if err != nil { + t.Errorf("%d. Error: %q", i, err) + } else { + if g, e := string(body), responseBody; g != e { + t.Errorf("%d. body = %q; want %q", i, g, e) + } + if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e { + t.Errorf("%d. Accept-Encoding = %q; want %q", i, g, e) + } + if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e { + t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e) + } + } + } + +} + func TestTransportGzip(t *testing.T) { const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" const nRandBytes = 1024 * 1024 @@ -490,7 +553,7 @@ func TestTransportProxy(t *testing.T) { })) defer proxy.Close() - pu, err := ParseURL(proxy.URL) + pu, err := url.Parse(proxy.URL) if err != nil { t.Fatal(err) } diff --git a/src/pkg/json/decode.go b/src/pkg/json/decode.go index 7d474fa7b..4f6562bd5 100644 --- a/src/pkg/json/decode.go +++ b/src/pkg/json/decode.go @@ -251,6 +251,12 @@ func (d *decodeState) value(v reflect.Value) { // if it encounters an Unmarshaler, indirect stops and returns that. // if wantptr is true, indirect stops at the last pointer. func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, reflect.Value) { + // If v is a named type and is addressable, + // start with its address, so that if the type has pointer methods, + // we find them. + if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + v = v.Addr() + } for { var isUnmarshaler bool if v.Type().NumMethod() > 0 { diff --git a/src/pkg/json/decode_test.go b/src/pkg/json/decode_test.go index c0ef5bc3a..a855d6048 100644 --- a/src/pkg/json/decode_test.go +++ b/src/pkg/json/decode_test.go @@ -34,10 +34,17 @@ func (u *unmarshaler) UnmarshalJSON(b []byte) os.Error { return nil } +type ustruct struct { + M unmarshaler +} + var ( um0, um1 unmarshaler // target2 of unmarshaling ump = &um1 umtrue = unmarshaler{true} + umslice = []unmarshaler{unmarshaler{true}} + umslicep = new([]unmarshaler) + umstruct = ustruct{unmarshaler{true}} ) type unmarshalTest struct { @@ -77,6 +84,9 @@ var unmarshalTests = []unmarshalTest{ // unmarshal interface test {`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called {`{"T":false}`, &ump, &umtrue, nil}, + {`[{"T":false}]`, &umslice, umslice, nil}, + {`[{"T":false}]`, &umslicep, &umslice, nil}, + {`{"M":{"T":false}}`, &umstruct, umstruct, nil}, } func TestMarshal(t *testing.T) { @@ -140,7 +150,6 @@ func TestUnmarshal(t *testing.T) { println(string(data)) data, _ = Marshal(tt.out) println(string(data)) - return continue } } diff --git a/src/pkg/net/Makefile b/src/pkg/net/Makefile index 6b3d0b328..eba9e26d9 100644 --- a/src/pkg/net/Makefile +++ b/src/pkg/net/Makefile @@ -9,16 +9,14 @@ GOFILES=\ dial.go\ dnsclient.go\ dnsmsg.go\ - fd_$(GOOS).go\ hosts.go\ interface.go\ ip.go\ - ipsock.go\ iprawsock.go\ + ipsock.go\ net.go\ parse.go\ pipe.go\ - sock.go\ tcpsock.go\ udpsock.go\ unixsock.go\ @@ -27,80 +25,129 @@ GOFILES_freebsd=\ dnsclient_unix.go\ dnsconfig.go\ fd.go\ + fd_$(GOOS).go\ file.go\ interface_bsd.go\ interface_freebsd.go\ + iprawsock_posix.go\ + ipsock_posix.go\ lookup_unix.go\ newpollserver.go\ port.go\ sendfile_stub.go\ + sock.go\ sock_bsd.go\ + tcpsock_posix.go\ + udpsock_posix.go\ + unixsock_posix.go\ +ifeq ($(CGO_ENABLED),1) CGOFILES_freebsd=\ cgo_bsd.go\ - cgo_unix.go\ + cgo_unix.go +else +GOFILES_freebsd+=cgo_stub.go +endif GOFILES_darwin=\ dnsclient_unix.go\ dnsconfig.go\ fd.go\ + fd_$(GOOS).go\ file.go\ interface_bsd.go\ interface_darwin.go\ + iprawsock_posix.go\ + ipsock_posix.go\ lookup_unix.go\ newpollserver.go\ port.go\ sendfile_stub.go\ + sock.go\ sock_bsd.go\ + tcpsock_posix.go\ + udpsock_posix.go\ + unixsock_posix.go\ +ifeq ($(CGO_ENABLED),1) CGOFILES_darwin=\ cgo_bsd.go\ - cgo_unix.go\ + cgo_unix.go +else +GOFILES_darwin+=cgo_stub.go +endif GOFILES_linux=\ dnsclient_unix.go\ dnsconfig.go\ fd.go\ + fd_$(GOOS).go\ file.go\ interface_linux.go\ + iprawsock_posix.go\ + ipsock_posix.go\ lookup_unix.go\ newpollserver.go\ port.go\ sendfile_linux.go\ + sock.go\ sock_linux.go\ + tcpsock_posix.go\ + udpsock_posix.go\ + unixsock_posix.go\ + +ifeq ($(CGO_ENABLED),1) +CGOFILES_linux=\ + cgo_linux.go\ + cgo_unix.go +else +GOFILES_linux+=cgo_stub.go +endif GOFILES_openbsd=\ - dnsclient.go\ + dnsclient_unix.go\ dnsconfig.go\ fd.go\ + fd_$(GOOS).go\ file.go\ interface_bsd.go\ + interface_openbsd.go\ + iprawsock_posix.go\ + ipsock_posix.go\ + lookup_unix.go\ newpollserver.go\ port.go\ sendfile_stub.go\ + sock.go\ sock_bsd.go\ + tcpsock_posix.go\ + udpsock_posix.go\ + unixsock_posix.go\ cgo_stub.go\ GOFILES_plan9=\ + file_plan9.go\ interface_stub.go\ - lookup_unix.go\ - sendfile_stub.go\ - -ifeq ($(GOARCH),arm) -# ARM has no cgo, so use the stubs. -GOFILES_linux+=cgo_stub.go -else -CGOFILES_linux=\ - cgo_linux.go\ - cgo_unix.go -endif + iprawsock_plan9.go\ + ipsock_plan9.go\ + lookup_plan9.go\ + tcpsock_plan9.go\ + udpsock_plan9.go\ + unixsock_plan9.go\ GOFILES_windows=\ + fd_$(GOOS).go\ file_windows.go\ interface_windows.go\ + iprawsock_posix.go\ + ipsock_posix.go\ lookup_windows.go\ sendfile_windows.go\ + sock.go\ sock_windows.go\ + tcpsock_posix.go\ + udpsock_posix.go\ + unixsock_posix.go\ GOFILES+=$(GOFILES_$(GOOS)) ifneq ($(CGOFILES_$(GOOS)),) diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go index cd1a21dc3..707dccaa4 100644 --- a/src/pkg/net/fd.go +++ b/src/pkg/net/fd.go @@ -585,20 +585,25 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os. fd.incref() defer fd.decref() + if fd.rdeadline_delta > 0 { + fd.rdeadline = pollserver.Now() + fd.rdeadline_delta + } else { + fd.rdeadline = 0 + } // See ../syscall/exec.go for description of ForkLock. // It is okay to hold the lock across syscall.Accept // because we have put fd.sysfd into non-blocking mode. syscall.ForkLock.RLock() var s, e int - var sa syscall.Sockaddr + var rsa syscall.Sockaddr for { if fd.closing { syscall.ForkLock.RUnlock() return nil, os.EINVAL } - s, sa, e = syscall.Accept(fd.sysfd) - if e != syscall.EAGAIN { + s, rsa, e = syscall.Accept(fd.sysfd) + if e != syscall.EAGAIN || fd.rdeadline < 0 { break } syscall.ForkLock.RUnlock() @@ -616,7 +621,8 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os. syscall.Close(s) return nil, err } - nfd.setAddr(fd.laddr, toAddr(sa)) + lsa, _ := syscall.Getsockname(nfd.sysfd) + nfd.setAddr(toAddr(lsa), toAddr(rsa)) return nfd, nil } diff --git a/src/pkg/net/file_plan9.go b/src/pkg/net/file_plan9.go new file mode 100644 index 000000000..a07e74331 --- /dev/null +++ b/src/pkg/net/file_plan9.go @@ -0,0 +1,33 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package net + +import ( + "os" +) + +// FileConn returns a copy of the network connection corresponding to +// the open file f. It is the caller's responsibility to close f when +// finished. Closing c does not affect f, and closing f does not +// affect c. +func FileConn(f *os.File) (c Conn, err os.Error) { + return nil, os.EPLAN9 +} + +// FileListener returns a copy of the network listener corresponding +// to the open file f. It is the caller's responsibility to close l +// when finished. Closing c does not affect l, and closing l does not +// affect c. +func FileListener(f *os.File) (l Listener, err os.Error) { + return nil, os.EPLAN9 +} + +// FilePacketConn returns a copy of the packet network connection +// corresponding to the open file f. It is the caller's +// responsibility to close f when finished. Closing c does not affect +// f, and closing f does not affect c. +func FilePacketConn(f *os.File) (c PacketConn, err os.Error) { + return nil, os.EPLAN9 +} diff --git a/src/pkg/net/file_test.go b/src/pkg/net/file_test.go index bd1e2c9d7..9a8c2dcbc 100644 --- a/src/pkg/net/file_test.go +++ b/src/pkg/net/file_test.go @@ -57,7 +57,7 @@ func testFileListener(t *testing.T, net, laddr string) { } func TestFileListener(t *testing.T) { - if runtime.GOOS == "windows" { + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { return } testFileListener(t, "tcp", "127.0.0.1") @@ -116,7 +116,7 @@ func testFilePacketConnDial(t *testing.T, net, raddr string) { } func TestFilePacketConn(t *testing.T) { - if runtime.GOOS == "windows" { + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { return } testFilePacketConnListen(t, "udp", "127.0.0.1:0") diff --git a/src/pkg/net/interface_bsd.go b/src/pkg/net/interface_bsd.go index 130820d4a..2675f94b9 100644 --- a/src/pkg/net/interface_bsd.go +++ b/src/pkg/net/interface_bsd.go @@ -169,34 +169,3 @@ func newAddr(m *syscall.InterfaceAddrMessage) ([]Addr, os.Error) { return ifat, nil } - -func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, os.Error) { - var ifmat []Addr - - sas, e := syscall.ParseRoutingSockaddr(m) - if e != 0 { - return nil, os.NewSyscallError("route sockaddr", e) - } - - for _, s := range sas { - switch v := s.(type) { - case *syscall.SockaddrInet4: - ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])} - ifmat = append(ifmat, ifma.toAddr()) - case *syscall.SockaddrInet6: - ifma := &IPAddr{IP: make(IP, IPv6len)} - copy(ifma.IP, v.Addr[:]) - // NOTE: KAME based IPv6 protcol stack usually embeds - // the interface index in the interface-local or link- - // local address as the kernel-internal form. - if ifma.IP.IsInterfaceLocalMulticast() || - ifma.IP.IsLinkLocalMulticast() { - // remove embedded scope zone ID - ifma.IP[2], ifma.IP[3] = 0, 0 - } - ifmat = append(ifmat, ifma.toAddr()) - } - } - - return ifmat, nil -} diff --git a/src/pkg/net/interface_darwin.go b/src/pkg/net/interface_darwin.go index 6fbcd3723..a7b68ad7f 100644 --- a/src/pkg/net/interface_darwin.go +++ b/src/pkg/net/interface_darwin.go @@ -47,3 +47,34 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) { return ifmat, nil } + +func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, os.Error) { + var ifmat []Addr + + sas, e := syscall.ParseRoutingSockaddr(m) + if e != 0 { + return nil, os.NewSyscallError("route sockaddr", e) + } + + for _, s := range sas { + switch v := s.(type) { + case *syscall.SockaddrInet4: + ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])} + ifmat = append(ifmat, ifma.toAddr()) + case *syscall.SockaddrInet6: + ifma := &IPAddr{IP: make(IP, IPv6len)} + copy(ifma.IP, v.Addr[:]) + // NOTE: KAME based IPv6 protcol stack usually embeds + // the interface index in the interface-local or link- + // local address as the kernel-internal form. + if ifma.IP.IsInterfaceLocalMulticast() || + ifma.IP.IsLinkLocalMulticast() { + // remove embedded scope zone ID + ifma.IP[2], ifma.IP[3] = 0, 0 + } + ifmat = append(ifmat, ifma.toAddr()) + } + } + + return ifmat, nil +} diff --git a/src/pkg/net/interface_freebsd.go b/src/pkg/net/interface_freebsd.go index e0ff6caf0..20f506b08 100644 --- a/src/pkg/net/interface_freebsd.go +++ b/src/pkg/net/interface_freebsd.go @@ -47,3 +47,34 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) { return ifmat, nil } + +func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, os.Error) { + var ifmat []Addr + + sas, e := syscall.ParseRoutingSockaddr(m) + if e != 0 { + return nil, os.NewSyscallError("route sockaddr", e) + } + + for _, s := range sas { + switch v := s.(type) { + case *syscall.SockaddrInet4: + ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])} + ifmat = append(ifmat, ifma.toAddr()) + case *syscall.SockaddrInet6: + ifma := &IPAddr{IP: make(IP, IPv6len)} + copy(ifma.IP, v.Addr[:]) + // NOTE: KAME based IPv6 protcol stack usually embeds + // the interface index in the interface-local or link- + // local address as the kernel-internal form. + if ifma.IP.IsInterfaceLocalMulticast() || + ifma.IP.IsLinkLocalMulticast() { + // remove embedded scope zone ID + ifma.IP[2], ifma.IP[3] = 0, 0 + } + ifmat = append(ifmat, ifma.toAddr()) + } + } + + return ifmat, nil +} diff --git a/src/pkg/net/interface_openbsd.go b/src/pkg/net/interface_openbsd.go new file mode 100644 index 000000000..f18149393 --- /dev/null +++ b/src/pkg/net/interface_openbsd.go @@ -0,0 +1,16 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Network interface identification for OpenBSD + +package net + +import "os" + +// If the ifindex is zero, interfaceMulticastAddrTable returns +// addresses for all network interfaces. Otherwise it returns +// addresses for a specific interface. +func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) { + return nil, nil +} diff --git a/src/pkg/net/iprawsock.go b/src/pkg/net/iprawsock.go index 43047a78e..662b9f57b 100644 --- a/src/pkg/net/iprawsock.go +++ b/src/pkg/net/iprawsock.go @@ -8,22 +8,8 @@ package net import ( "os" - "sync" - "syscall" ) -var onceReadProtocols sync.Once - -func sockaddrToIP(sa syscall.Sockaddr) Addr { - switch sa := sa.(type) { - case *syscall.SockaddrInet4: - return &IPAddr{sa.Addr[0:]} - case *syscall.SockaddrInet6: - return &IPAddr{sa.Addr[0:]} - } - return nil -} - // IPAddr represents the address of a IP end point. type IPAddr struct { IP IP @@ -39,27 +25,6 @@ func (a *IPAddr) String() string { return a.IP.String() } -func (a *IPAddr) family() int { - if a == nil || len(a.IP) <= 4 { - return syscall.AF_INET - } - if a.IP.To4() != nil { - return syscall.AF_INET - } - return syscall.AF_INET6 -} - -func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) { - return ipToSockaddr(family, a.IP, 0) -} - -func (a *IPAddr) toAddr() sockaddr { - if a == nil { // nil *IPAddr - return nil // nil interface - } - return a -} - // ResolveIPAddr parses addr as a IP address and resolves domain // names to numeric addresses on the network net, which must be // "ip", "ip4" or "ip6". A literal IPv6 host address must be @@ -72,168 +37,6 @@ func ResolveIPAddr(net, addr string) (*IPAddr, os.Error) { return &IPAddr{ip}, nil } -// IPConn is the implementation of the Conn and PacketConn -// interfaces for IP network connections. -type IPConn struct { - fd *netFD -} - -func newIPConn(fd *netFD) *IPConn { return &IPConn{fd} } - -func (c *IPConn) ok() bool { return c != nil && c.fd != nil } - -// Implementation of the Conn interface - see Conn for documentation. - -// Read implements the net.Conn Read method. -func (c *IPConn) Read(b []byte) (n int, err os.Error) { - n, _, err = c.ReadFrom(b) - return -} - -// Write implements the net.Conn Write method. -func (c *IPConn) Write(b []byte) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - return c.fd.Write(b) -} - -// Close closes the IP connection. -func (c *IPConn) Close() os.Error { - if !c.ok() { - return os.EINVAL - } - err := c.fd.Close() - c.fd = nil - return err -} - -// LocalAddr returns the local network address. -func (c *IPConn) LocalAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.laddr -} - -// RemoteAddr returns the remote network address, a *IPAddr. -func (c *IPConn) RemoteAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.raddr -} - -// SetTimeout implements the net.Conn SetTimeout method. -func (c *IPConn) SetTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setTimeout(c.fd, nsec) -} - -// SetReadTimeout implements the net.Conn SetReadTimeout method. -func (c *IPConn) SetReadTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadTimeout(c.fd, nsec) -} - -// SetWriteTimeout implements the net.Conn SetWriteTimeout method. -func (c *IPConn) SetWriteTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteTimeout(c.fd, nsec) -} - -// SetReadBuffer sets the size of the operating system's -// receive buffer associated with the connection. -func (c *IPConn) SetReadBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadBuffer(c.fd, bytes) -} - -// SetWriteBuffer sets the size of the operating system's -// transmit buffer associated with the connection. -func (c *IPConn) SetWriteBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteBuffer(c.fd, bytes) -} - -// IP-specific methods. - -// ReadFromIP reads a IP packet from c, copying the payload into b. -// It returns the number of bytes copied into b and the return address -// that was on the packet. -// -// ReadFromIP can be made to time out and return an error with -// Timeout() == true after a fixed time limit; see SetTimeout and -// SetReadTimeout. -func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err os.Error) { - if !c.ok() { - return 0, nil, os.EINVAL - } - // TODO(cw,rsc): consider using readv if we know the family - // type to avoid the header trim/copy - n, sa, err := c.fd.ReadFrom(b) - switch sa := sa.(type) { - case *syscall.SockaddrInet4: - addr = &IPAddr{sa.Addr[0:]} - if len(b) >= 4 { // discard ipv4 header - hsize := (int(b[0]) & 0xf) * 4 - copy(b, b[hsize:]) - n -= hsize - } - case *syscall.SockaddrInet6: - addr = &IPAddr{sa.Addr[0:]} - } - return -} - -// ReadFrom implements the net.PacketConn ReadFrom method. -func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { - if !c.ok() { - return 0, nil, os.EINVAL - } - n, uaddr, err := c.ReadFromIP(b) - return n, uaddr.toAddr(), err -} - -// WriteToIP writes a IP packet to addr via c, copying the payload from b. -// -// WriteToIP can be made to time out and return -// an error with Timeout() == true after a fixed time limit; -// see SetTimeout and SetWriteTimeout. -// On packet-oriented connections, write timeouts are rare. -func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - sa, err1 := addr.sockaddr(c.fd.family) - if err1 != nil { - return 0, &OpError{Op: "write", Net: "ip", Addr: addr, Error: err1} - } - return c.fd.WriteTo(b, sa) -} - -// WriteTo implements the net.PacketConn WriteTo method. -func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - a, ok := addr.(*IPAddr) - if !ok { - return 0, &OpError{"writeto", "ip", addr, os.EINVAL} - } - return c.WriteToIP(b, a) -} - // Convert "host" into IP address. func hostToIP(net, host string) (ip IP, err os.Error) { var addr IP @@ -264,100 +67,3 @@ func hostToIP(net, host string) (ip IP, err os.Error) { Error: return nil, err } - -var protocols map[string]int - -func readProtocols() { - protocols = make(map[string]int) - if file, err := open("/etc/protocols"); err == nil { - for line, ok := file.readLine(); ok; line, ok = file.readLine() { - // tcp 6 TCP # transmission control protocol - if i := byteIndex(line, '#'); i >= 0 { - line = line[0:i] - } - f := getFields(line) - if len(f) < 2 { - continue - } - if proto, _, ok := dtoi(f[1], 0); ok { - protocols[f[0]] = proto - for _, alias := range f[2:] { - protocols[alias] = proto - } - } - } - file.close() - } -} - -func splitNetProto(netProto string) (net string, proto int, err os.Error) { - onceReadProtocols.Do(readProtocols) - i := last(netProto, ':') - if i < 0 { // no colon - return "", 0, os.NewError("no IP protocol specified") - } - net = netProto[0:i] - protostr := netProto[i+1:] - proto, i, ok := dtoi(protostr, 0) - if !ok || i != len(protostr) { - // lookup by name - proto, ok = protocols[protostr] - if ok { - return - } - } - return -} - -// DialIP connects to the remote address raddr on the network net, -// which must be "ip", "ip4", or "ip6". -func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) { - net, proto, err := splitNetProto(netProto) - if err != nil { - return - } - switch net { - case "ip", "ip4", "ip6": - default: - return nil, UnknownNetworkError(net) - } - if raddr == nil { - return nil, &OpError{"dial", "ip", nil, errMissingAddress} - } - fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP) - if e != nil { - return nil, e - } - return newIPConn(fd), nil -} - -// ListenIP listens for incoming IP packets addressed to the -// local address laddr. The returned connection c's ReadFrom -// and WriteTo methods can be used to receive and send IP -// packets with per-packet addressing. -func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err os.Error) { - net, proto, err := splitNetProto(netProto) - if err != nil { - return - } - switch net { - case "ip", "ip4", "ip6": - default: - return nil, UnknownNetworkError(net) - } - fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "dial", sockaddrToIP) - if e != nil { - return nil, e - } - return newIPConn(fd), nil -} - -// BindToDevice binds an IPConn to a network interface. -func (c *IPConn) BindToDevice(device string) os.Error { - if !c.ok() { - return os.EINVAL - } - c.fd.incref() - defer c.fd.decref() - return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device)) -} diff --git a/src/pkg/net/iprawsock_plan9.go b/src/pkg/net/iprawsock_plan9.go new file mode 100644 index 000000000..808e17974 --- /dev/null +++ b/src/pkg/net/iprawsock_plan9.go @@ -0,0 +1,99 @@ +// Copyright 2010 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. + +// (Raw) IP sockets stubs for Plan 9 + +package net + +import ( + "os" +) + +// IPConn is the implementation of the Conn and PacketConn +// interfaces for IP network connections. +type IPConn bool + +// Implementation of the Conn interface - see Conn for documentation. + +// Read implements the net.Conn Read method. +func (c *IPConn) Read(b []byte) (n int, err os.Error) { + return 0, os.EPLAN9 +} + +// Write implements the net.Conn Write method. +func (c *IPConn) Write(b []byte) (n int, err os.Error) { + return 0, os.EPLAN9 +} + +// Close closes the IP connection. +func (c *IPConn) Close() os.Error { + return os.EPLAN9 +} + +// LocalAddr returns the local network address. +func (c *IPConn) LocalAddr() Addr { + return nil +} + +// RemoteAddr returns the remote network address, a *IPAddr. +func (c *IPConn) RemoteAddr() Addr { + return nil +} + +// SetTimeout implements the net.Conn SetTimeout method. +func (c *IPConn) SetTimeout(nsec int64) os.Error { + return os.EPLAN9 +} + +// SetReadTimeout implements the net.Conn SetReadTimeout method. +func (c *IPConn) SetReadTimeout(nsec int64) os.Error { + return os.EPLAN9 +} + +// SetWriteTimeout implements the net.Conn SetWriteTimeout method. +func (c *IPConn) SetWriteTimeout(nsec int64) os.Error { + return os.EPLAN9 +} + +// IP-specific methods. + +// ReadFrom implements the net.PacketConn ReadFrom method. +func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { + err = os.EPLAN9 + return +} + +// WriteToIP writes a IP packet to addr via c, copying the payload from b. +// +// WriteToIP can be made to time out and return +// an error with Timeout() == true after a fixed time limit; +// see SetTimeout and SetWriteTimeout. +// On packet-oriented connections, write timeouts are rare. +func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err os.Error) { + return 0, os.EPLAN9 +} + +// WriteTo implements the net.PacketConn WriteTo method. +func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { + return 0, os.EPLAN9 +} + +func splitNetProto(netProto string) (net string, proto int, err os.Error) { + err = os.EPLAN9 + return +} + +// DialIP connects to the remote address raddr on the network net, +// which must be "ip", "ip4", or "ip6". +func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) { + return nil, os.EPLAN9 +} + +// ListenIP listens for incoming IP packets addressed to the +// local address laddr. The returned connection c's ReadFrom +// and WriteTo methods can be used to receive and send IP +// packets with per-packet addressing. +func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err os.Error) { + return nil, os.EPLAN9 +} diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go new file mode 100644 index 000000000..4e1151800 --- /dev/null +++ b/src/pkg/net/iprawsock_posix.go @@ -0,0 +1,305 @@ +// Copyright 2010 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. + +// (Raw) IP sockets + +package net + +import ( + "os" + "sync" + "syscall" +) + +var onceReadProtocols sync.Once + +func sockaddrToIP(sa syscall.Sockaddr) Addr { + switch sa := sa.(type) { + case *syscall.SockaddrInet4: + return &IPAddr{sa.Addr[0:]} + case *syscall.SockaddrInet6: + return &IPAddr{sa.Addr[0:]} + } + return nil +} + +func (a *IPAddr) family() int { + if a == nil || len(a.IP) <= 4 { + return syscall.AF_INET + } + if a.IP.To4() != nil { + return syscall.AF_INET + } + return syscall.AF_INET6 +} + +func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) { + return ipToSockaddr(family, a.IP, 0) +} + +func (a *IPAddr) toAddr() sockaddr { + if a == nil { // nil *IPAddr + return nil // nil interface + } + return a +} + +// IPConn is the implementation of the Conn and PacketConn +// interfaces for IP network connections. +type IPConn struct { + fd *netFD +} + +func newIPConn(fd *netFD) *IPConn { return &IPConn{fd} } + +func (c *IPConn) ok() bool { return c != nil && c.fd != nil } + +// Implementation of the Conn interface - see Conn for documentation. + +// Read implements the net.Conn Read method. +func (c *IPConn) Read(b []byte) (n int, err os.Error) { + n, _, err = c.ReadFrom(b) + return +} + +// Write implements the net.Conn Write method. +func (c *IPConn) Write(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + return c.fd.Write(b) +} + +// Close closes the IP connection. +func (c *IPConn) Close() os.Error { + if !c.ok() { + return os.EINVAL + } + err := c.fd.Close() + c.fd = nil + return err +} + +// LocalAddr returns the local network address. +func (c *IPConn) LocalAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.laddr +} + +// RemoteAddr returns the remote network address, a *IPAddr. +func (c *IPConn) RemoteAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.raddr +} + +// SetTimeout implements the net.Conn SetTimeout method. +func (c *IPConn) SetTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setTimeout(c.fd, nsec) +} + +// SetReadTimeout implements the net.Conn SetReadTimeout method. +func (c *IPConn) SetReadTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadTimeout(c.fd, nsec) +} + +// SetWriteTimeout implements the net.Conn SetWriteTimeout method. +func (c *IPConn) SetWriteTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteTimeout(c.fd, nsec) +} + +// SetReadBuffer sets the size of the operating system's +// receive buffer associated with the connection. +func (c *IPConn) SetReadBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadBuffer(c.fd, bytes) +} + +// SetWriteBuffer sets the size of the operating system's +// transmit buffer associated with the connection. +func (c *IPConn) SetWriteBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteBuffer(c.fd, bytes) +} + +// IP-specific methods. + +// ReadFromIP reads a IP packet from c, copying the payload into b. +// It returns the number of bytes copied into b and the return address +// that was on the packet. +// +// ReadFromIP can be made to time out and return an error with +// Timeout() == true after a fixed time limit; see SetTimeout and +// SetReadTimeout. +func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + // TODO(cw,rsc): consider using readv if we know the family + // type to avoid the header trim/copy + n, sa, err := c.fd.ReadFrom(b) + switch sa := sa.(type) { + case *syscall.SockaddrInet4: + addr = &IPAddr{sa.Addr[0:]} + if len(b) >= 4 { // discard ipv4 header + hsize := (int(b[0]) & 0xf) * 4 + copy(b, b[hsize:]) + n -= hsize + } + case *syscall.SockaddrInet6: + addr = &IPAddr{sa.Addr[0:]} + } + return +} + +// ReadFrom implements the net.PacketConn ReadFrom method. +func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + n, uaddr, err := c.ReadFromIP(b) + return n, uaddr.toAddr(), err +} + +// WriteToIP writes a IP packet to addr via c, copying the payload from b. +// +// WriteToIP can be made to time out and return +// an error with Timeout() == true after a fixed time limit; +// see SetTimeout and SetWriteTimeout. +// On packet-oriented connections, write timeouts are rare. +func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + sa, err1 := addr.sockaddr(c.fd.family) + if err1 != nil { + return 0, &OpError{Op: "write", Net: "ip", Addr: addr, Error: err1} + } + return c.fd.WriteTo(b, sa) +} + +// WriteTo implements the net.PacketConn WriteTo method. +func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + a, ok := addr.(*IPAddr) + if !ok { + return 0, &OpError{"writeto", "ip", addr, os.EINVAL} + } + return c.WriteToIP(b, a) +} + +var protocols map[string]int + +func readProtocols() { + protocols = make(map[string]int) + if file, err := open("/etc/protocols"); err == nil { + for line, ok := file.readLine(); ok; line, ok = file.readLine() { + // tcp 6 TCP # transmission control protocol + if i := byteIndex(line, '#'); i >= 0 { + line = line[0:i] + } + f := getFields(line) + if len(f) < 2 { + continue + } + if proto, _, ok := dtoi(f[1], 0); ok { + protocols[f[0]] = proto + for _, alias := range f[2:] { + protocols[alias] = proto + } + } + } + file.close() + } +} + +func splitNetProto(netProto string) (net string, proto int, err os.Error) { + onceReadProtocols.Do(readProtocols) + i := last(netProto, ':') + if i < 0 { // no colon + return "", 0, os.NewError("no IP protocol specified") + } + net = netProto[0:i] + protostr := netProto[i+1:] + proto, i, ok := dtoi(protostr, 0) + if !ok || i != len(protostr) { + // lookup by name + proto, ok = protocols[protostr] + if ok { + return + } + } + return +} + +// DialIP connects to the remote address raddr on the network net, +// which must be "ip", "ip4", or "ip6". +func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) { + net, proto, err := splitNetProto(netProto) + if err != nil { + return + } + switch net { + case "ip", "ip4", "ip6": + default: + return nil, UnknownNetworkError(net) + } + if raddr == nil { + return nil, &OpError{"dial", "ip", nil, errMissingAddress} + } + fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP) + if e != nil { + return nil, e + } + return newIPConn(fd), nil +} + +// ListenIP listens for incoming IP packets addressed to the +// local address laddr. The returned connection c's ReadFrom +// and WriteTo methods can be used to receive and send IP +// packets with per-packet addressing. +func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err os.Error) { + net, proto, err := splitNetProto(netProto) + if err != nil { + return + } + switch net { + case "ip", "ip4", "ip6": + default: + return nil, UnknownNetworkError(net) + } + fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "dial", sockaddrToIP) + if e != nil { + return nil, e + } + return newIPConn(fd), nil +} + +// BindToDevice binds an IPConn to a network interface. +func (c *IPConn) BindToDevice(device string) os.Error { + if !c.ok() { + return os.EINVAL + } + c.fd.incref() + defer c.fd.decref() + return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device)) +} diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go index e831d9afc..4e2a5622b 100644 --- a/src/pkg/net/ipsock.go +++ b/src/pkg/net/ipsock.go @@ -8,94 +8,10 @@ package net import ( "os" - "syscall" ) -// Should we try to use the IPv4 socket interface if we're -// only dealing with IPv4 sockets? As long as the host system -// understands IPv6, it's okay to pass IPv4 addresses to the IPv6 -// interface. That simplifies our code and is most general. -// Unfortunately, we need to run on kernels built without IPv6 -// support too. So probe the kernel to figure it out. -// -// probeIPv6Stack probes both basic IPv6 capability and IPv6 IPv4- -// mapping capability which is controlled by IPV6_V6ONLY socket -// option and/or kernel state "net.inet6.ip6.v6only". -// It returns two boolean values. If the first boolean value is -// true, kernel supports basic IPv6 functionality. If the second -// boolean value is true, kernel supports IPv6 IPv4-mapping. -func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { - var probes = []struct { - la TCPAddr - ok bool - }{ - // IPv6 communication capability - {TCPAddr{IP: ParseIP("::1")}, false}, - // IPv6 IPv4-mapped address communication capability - {TCPAddr{IP: IPv4(127, 0, 0, 1)}, false}, - } - - for i := range probes { - s, errno := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) - if errno != 0 { - continue - } - defer closesocket(s) - sa, err := probes[i].la.toAddr().sockaddr(syscall.AF_INET6) - if err != nil { - continue - } - errno = syscall.Bind(s, sa) - if errno != 0 { - continue - } - probes[i].ok = true - } - - return probes[0].ok, probes[1].ok -} - var supportsIPv6, supportsIPv4map = probeIPv6Stack() -// favoriteAddrFamily returns the appropriate address family to -// the given net, raddr, laddr and mode. At first it figures -// address family out from the net. If mode indicates "listen" -// and laddr.(type).IP is nil, it assumes that the user wants to -// make a passive connection with wildcard address family, both -// INET and INET6, and wildcard address. Otherwise guess: if the -// addresses are IPv4 then returns INET, or else returns INET6. -func favoriteAddrFamily(net string, raddr, laddr sockaddr, mode string) int { - switch net[len(net)-1] { - case '4': - return syscall.AF_INET - case '6': - return syscall.AF_INET6 - } - - if mode == "listen" { - switch a := laddr.(type) { - case *TCPAddr: - if a.IP == nil && supportsIPv6 { - return syscall.AF_INET6 - } - case *UDPAddr: - if a.IP == nil && supportsIPv6 { - return syscall.AF_INET6 - } - case *IPAddr: - if a.IP == nil && supportsIPv6 { - return syscall.AF_INET6 - } - } - } - - if (laddr == nil || laddr.family() == syscall.AF_INET) && - (raddr == nil || raddr.family() == syscall.AF_INET) { - return syscall.AF_INET - } - return syscall.AF_INET6 -} - func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) { if filter == anyaddr { // We'll take any IP address, but since the dialing code @@ -143,93 +59,12 @@ func ipv6only(x IP) IP { return nil } -// TODO(rsc): if syscall.OS == "linux", we're supposed to read -// /proc/sys/net/core/somaxconn, -// to take advantage of kernels that have raised the limit. -func listenBacklog() int { return syscall.SOMAXCONN } - -// Internet sockets (TCP, UDP) - -// A sockaddr represents a TCP or UDP network address that can -// be converted into a syscall.Sockaddr. -type sockaddr interface { - Addr - sockaddr(family int) (syscall.Sockaddr, os.Error) - family() int -} - -func internetSocket(net string, laddr, raddr sockaddr, socktype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) { - var oserr os.Error - var la, ra syscall.Sockaddr - family := favoriteAddrFamily(net, raddr, laddr, mode) - if laddr != nil { - if la, oserr = laddr.sockaddr(family); oserr != nil { - goto Error - } - } - if raddr != nil { - if ra, oserr = raddr.sockaddr(family); oserr != nil { - goto Error - } - } - fd, oserr = socket(net, family, socktype, proto, la, ra, toAddr) - if oserr != nil { - goto Error - } - return fd, nil - -Error: - addr := raddr - if mode == "listen" { - addr = laddr - } - return nil, &OpError{mode, net, addr, oserr} -} - type InvalidAddrError string func (e InvalidAddrError) String() string { return string(e) } func (e InvalidAddrError) Timeout() bool { return false } func (e InvalidAddrError) Temporary() bool { return false } -func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, os.Error) { - switch family { - case syscall.AF_INET: - if len(ip) == 0 { - ip = IPv4zero - } - if ip = ip.To4(); ip == nil { - return nil, InvalidAddrError("non-IPv4 address") - } - s := new(syscall.SockaddrInet4) - for i := 0; i < IPv4len; i++ { - s.Addr[i] = ip[i] - } - s.Port = port - return s, nil - case syscall.AF_INET6: - if len(ip) == 0 { - ip = IPv6zero - } - // IPv4 callers use 0.0.0.0 to mean "announce on any available address". - // In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0", - // which it refuses to do. Rewrite to the IPv6 all zeros. - if ip.Equal(IPv4zero) { - ip = IPv6zero - } - if ip = ip.To16(); ip == nil { - return nil, InvalidAddrError("non-IPv6 address") - } - s := new(syscall.SockaddrInet6) - for i := 0; i < IPv6len; i++ { - s.Addr[i] = ip[i] - } - s.Port = port - return s, nil - } - return nil, InvalidAddrError("unexpected socket family") -} - // SplitHostPort splits a network address of the form // "host:port" or "[host]:port" into host and port. // The latter form must be used when host contains a colon. diff --git a/src/pkg/net/ipsock_plan9.go b/src/pkg/net/ipsock_plan9.go new file mode 100644 index 000000000..9e5da6d38 --- /dev/null +++ b/src/pkg/net/ipsock_plan9.go @@ -0,0 +1,305 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// IP sockets stubs for Plan 9 + +package net + +import ( + "os" +) + +// probeIPv6Stack returns two boolean values. If the first boolean value is +// true, kernel supports basic IPv6 functionality. If the second +// boolean value is true, kernel supports IPv6 IPv4-mapping. +func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { + return false, false +} + +// parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80). +func parsePlan9Addr(s string) (ip IP, iport int, err os.Error) { + var ( + addr IP + p, i int + ok bool + ) + addr = IPv4zero // address contains port only + i = byteIndex(s, '!') + if i >= 0 { + addr = ParseIP(s[:i]) + if addr == nil { + err = os.NewError("net: parsing IP failed") + goto Error + } + } + p, _, ok = dtoi(s[i+1:], 0) + if !ok { + err = os.NewError("net: parsing port failed") + goto Error + } + if p < 0 || p > 0xFFFF { + err = &AddrError{"invalid port", string(p)} + goto Error + } + return addr, p, nil + +Error: + return nil, 0, err +} + +func readPlan9Addr(proto, filename string) (addr Addr, err os.Error) { + var buf [128]byte + + f, err := os.Open(filename) + if err != nil { + return + } + n, err := f.Read(buf[:]) + if err != nil { + return + } + ip, port, err := parsePlan9Addr(string(buf[:n])) + if err != nil { + return + } + switch proto { + case "tcp": + addr = &TCPAddr{ip, port} + case "udp": + addr = &UDPAddr{ip, port} + default: + return nil, os.NewError("unknown protocol " + proto) + } + return addr, nil +} + +type plan9Conn struct { + proto, name, dir string + ctl, data *os.File + laddr, raddr Addr +} + +func newPlan9Conn(proto, name string, ctl *os.File, laddr, raddr Addr) *plan9Conn { + return &plan9Conn{proto, name, "/net/" + proto + "/" + name, ctl, nil, laddr, raddr} +} + +func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil } + +// Implementation of the Conn interface - see Conn for documentation. + +// Read implements the net.Conn Read method. +func (c *plan9Conn) Read(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + if c.data == nil { + c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) + if err != nil { + return 0, err + } + } + n, err = c.data.Read(b) + if c.proto == "udp" && err == os.EOF { + n = 0 + err = nil + } + return +} + +// Write implements the net.Conn Write method. +func (c *plan9Conn) Write(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + if c.data == nil { + c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) + if err != nil { + return 0, err + } + } + return c.data.Write(b) +} + +// Close closes the connection. +func (c *plan9Conn) Close() os.Error { + if !c.ok() { + return os.EINVAL + } + err := c.ctl.Close() + if err != nil { + return err + } + if c.data != nil { + err = c.data.Close() + } + c.ctl = nil + c.data = nil + return err +} + +// LocalAddr returns the local network address. +func (c *plan9Conn) LocalAddr() Addr { + if !c.ok() { + return nil + } + return c.laddr +} + +// RemoteAddr returns the remote network address. +func (c *plan9Conn) RemoteAddr() Addr { + if !c.ok() { + return nil + } + return c.raddr +} + +// SetTimeout implements the net.Conn SetTimeout method. +func (c *plan9Conn) SetTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return os.EPLAN9 +} + +// SetReadTimeout implements the net.Conn SetReadTimeout method. +func (c *plan9Conn) SetReadTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return os.EPLAN9 +} + +// SetWriteTimeout implements the net.Conn SetWriteTimeout method. +func (c *plan9Conn) SetWriteTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return os.EPLAN9 +} + +func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err os.Error) { + var ( + ip IP + port int + ) + switch a := addr.(type) { + case *TCPAddr: + proto = "tcp" + ip = a.IP + port = a.Port + case *UDPAddr: + proto = "udp" + ip = a.IP + port = a.Port + default: + err = UnknownNetworkError(net) + return + } + + clone, dest, err := queryCS1(proto, ip, port) + if err != nil { + return + } + f, err := os.OpenFile(clone, os.O_RDWR, 0) + if err != nil { + return + } + var buf [16]byte + n, err := f.Read(buf[:]) + if err != nil { + return + } + return f, dest, proto, string(buf[:n]), nil +} + +func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err os.Error) { + f, dest, proto, name, err := startPlan9(net, raddr) + if err != nil { + return + } + _, err = f.WriteString("connect " + dest) + if err != nil { + return + } + laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") + if err != nil { + return + } + raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote") + if err != nil { + return + } + return newPlan9Conn(proto, name, f, laddr, raddr), nil +} + +type plan9Listener struct { + proto, name, dir string + ctl *os.File + laddr Addr +} + +func listenPlan9(net string, laddr Addr) (l *plan9Listener, err os.Error) { + f, dest, proto, name, err := startPlan9(net, laddr) + if err != nil { + return + } + _, err = f.WriteString("announce " + dest) + if err != nil { + return + } + laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") + if err != nil { + return + } + l = new(plan9Listener) + l.proto = proto + l.name = name + l.dir = "/net/" + proto + "/" + name + l.ctl = f + l.laddr = laddr + return l, nil +} + +func (l *plan9Listener) plan9Conn() *plan9Conn { + return newPlan9Conn(l.proto, l.name, l.ctl, l.laddr, nil) +} + +func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err os.Error) { + f, err := os.Open(l.dir + "/listen") + if err != nil { + return + } + var buf [16]byte + n, err := f.Read(buf[:]) + if err != nil { + return + } + name := string(buf[:n]) + laddr, err := readPlan9Addr(l.proto, l.dir+"/local") + if err != nil { + return + } + raddr, err := readPlan9Addr(l.proto, l.dir+"/remote") + if err != nil { + return + } + return newPlan9Conn(l.proto, name, f, laddr, raddr), nil +} + +func (l *plan9Listener) Accept() (c Conn, err os.Error) { + c1, err := l.acceptPlan9() + if err != nil { + return + } + return c1, nil +} + +func (l *plan9Listener) Close() os.Error { + if l == nil || l.ctl == nil { + return os.EINVAL + } + return l.ctl.Close() +} + +func (l *plan9Listener) Addr() Addr { return l.laddr } diff --git a/src/pkg/net/ipsock_posix.go b/src/pkg/net/ipsock_posix.go new file mode 100644 index 000000000..0c522fb7f --- /dev/null +++ b/src/pkg/net/ipsock_posix.go @@ -0,0 +1,174 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package net + +import ( + "os" + "syscall" +) + +// Should we try to use the IPv4 socket interface if we're +// only dealing with IPv4 sockets? As long as the host system +// understands IPv6, it's okay to pass IPv4 addresses to the IPv6 +// interface. That simplifies our code and is most general. +// Unfortunately, we need to run on kernels built without IPv6 +// support too. So probe the kernel to figure it out. +// +// probeIPv6Stack probes both basic IPv6 capability and IPv6 IPv4- +// mapping capability which is controlled by IPV6_V6ONLY socket +// option and/or kernel state "net.inet6.ip6.v6only". +// It returns two boolean values. If the first boolean value is +// true, kernel supports basic IPv6 functionality. If the second +// boolean value is true, kernel supports IPv6 IPv4-mapping. +func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { + var probes = []struct { + la TCPAddr + ok bool + }{ + // IPv6 communication capability + {TCPAddr{IP: ParseIP("::1")}, false}, + // IPv6 IPv4-mapped address communication capability + {TCPAddr{IP: IPv4(127, 0, 0, 1)}, false}, + } + + for i := range probes { + s, errno := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) + if errno != 0 { + continue + } + defer closesocket(s) + sa, err := probes[i].la.toAddr().sockaddr(syscall.AF_INET6) + if err != nil { + continue + } + errno = syscall.Bind(s, sa) + if errno != 0 { + continue + } + probes[i].ok = true + } + + return probes[0].ok, probes[1].ok +} + +// favoriteAddrFamily returns the appropriate address family to +// the given net, raddr, laddr and mode. At first it figures +// address family out from the net. If mode indicates "listen" +// and laddr.(type).IP is nil, it assumes that the user wants to +// make a passive connection with wildcard address family, both +// INET and INET6, and wildcard address. Otherwise guess: if the +// addresses are IPv4 then returns INET, or else returns INET6. +func favoriteAddrFamily(net string, raddr, laddr sockaddr, mode string) int { + switch net[len(net)-1] { + case '4': + return syscall.AF_INET + case '6': + return syscall.AF_INET6 + } + + if mode == "listen" { + switch a := laddr.(type) { + case *TCPAddr: + if a.IP == nil && supportsIPv6 { + return syscall.AF_INET6 + } + case *UDPAddr: + if a.IP == nil && supportsIPv6 { + return syscall.AF_INET6 + } + case *IPAddr: + if a.IP == nil && supportsIPv6 { + return syscall.AF_INET6 + } + } + } + + if (laddr == nil || laddr.family() == syscall.AF_INET) && + (raddr == nil || raddr.family() == syscall.AF_INET) { + return syscall.AF_INET + } + return syscall.AF_INET6 +} + +// TODO(rsc): if syscall.OS == "linux", we're supposed to read +// /proc/sys/net/core/somaxconn, +// to take advantage of kernels that have raised the limit. +func listenBacklog() int { return syscall.SOMAXCONN } + +// Internet sockets (TCP, UDP) + +// A sockaddr represents a TCP or UDP network address that can +// be converted into a syscall.Sockaddr. +type sockaddr interface { + Addr + sockaddr(family int) (syscall.Sockaddr, os.Error) + family() int +} + +func internetSocket(net string, laddr, raddr sockaddr, socktype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) { + var oserr os.Error + var la, ra syscall.Sockaddr + family := favoriteAddrFamily(net, raddr, laddr, mode) + if laddr != nil { + if la, oserr = laddr.sockaddr(family); oserr != nil { + goto Error + } + } + if raddr != nil { + if ra, oserr = raddr.sockaddr(family); oserr != nil { + goto Error + } + } + fd, oserr = socket(net, family, socktype, proto, la, ra, toAddr) + if oserr != nil { + goto Error + } + return fd, nil + +Error: + addr := raddr + if mode == "listen" { + addr = laddr + } + return nil, &OpError{mode, net, addr, oserr} +} + +func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, os.Error) { + switch family { + case syscall.AF_INET: + if len(ip) == 0 { + ip = IPv4zero + } + if ip = ip.To4(); ip == nil { + return nil, InvalidAddrError("non-IPv4 address") + } + s := new(syscall.SockaddrInet4) + for i := 0; i < IPv4len; i++ { + s.Addr[i] = ip[i] + } + s.Port = port + return s, nil + case syscall.AF_INET6: + if len(ip) == 0 { + ip = IPv6zero + } + // IPv4 callers use 0.0.0.0 to mean "announce on any available address". + // In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0", + // which it refuses to do. Rewrite to the IPv6 all zeros. + if ip.Equal(IPv4zero) { + ip = IPv6zero + } + if ip = ip.To16(); ip == nil { + return nil, InvalidAddrError("non-IPv6 address") + } + s := new(syscall.SockaddrInet6) + for i := 0; i < IPv6len; i++ { + s.Addr[i] = ip[i] + } + s.Port = port + return s, nil + } + return nil, InvalidAddrError("unexpected socket family") +} diff --git a/src/pkg/net/lookup_plan9.go b/src/pkg/net/lookup_plan9.go new file mode 100644 index 000000000..37d6b8e31 --- /dev/null +++ b/src/pkg/net/lookup_plan9.go @@ -0,0 +1,226 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package net + +import ( + "os" +) + +func query(filename, query string, bufSize int) (res []string, err os.Error) { + file, err := os.OpenFile(filename, os.O_RDWR, 0) + if err != nil { + return + } + defer file.Close() + + _, err = file.WriteString(query) + if err != nil { + return + } + _, err = file.Seek(0, 0) + if err != nil { + return + } + buf := make([]byte, bufSize) + for { + n, _ := file.Read(buf) + if n <= 0 { + break + } + res = append(res, string(buf[:n])) + } + return +} + +func queryCS(net, host, service string) (res []string, err os.Error) { + switch net { + case "tcp4", "tcp6": + net = "tcp" + case "udp4", "udp6": + net = "udp" + } + if host == "" { + host = "*" + } + return query("/net/cs", net+"!"+host+"!"+service, 128) +} + +func queryCS1(net string, ip IP, port int) (clone, dest string, err os.Error) { + ips := "*" + if !ip.IsUnspecified() { + ips = ip.String() + } + lines, err := queryCS(net, ips, itoa(port)) + if err != nil { + return + } + f := getFields(lines[0]) + if len(f) < 2 { + return "", "", os.NewError("net: bad response from ndb/cs") + } + clone, dest = f[0], f[1] + return +} + +func queryDNS(addr string, typ string) (res []string, err os.Error) { + return query("/net/dns", addr+" "+typ, 1024) +} + +// LookupHost looks up the given host using the local resolver. +// It returns an array of that host's addresses. +func LookupHost(host string) (addrs []string, err os.Error) { + // Use /net/cs insead of /net/dns because cs knows about + // host names in local network (e.g. from /lib/ndb/local) + lines, err := queryCS("tcp", host, "1") + if err != nil { + return + } + for _, line := range lines { + f := getFields(line) + if len(f) < 2 { + continue + } + addr := f[1] + if i := byteIndex(addr, '!'); i >= 0 { + addr = addr[:i] // remove port + } + if ParseIP(addr) == nil { + continue + } + addrs = append(addrs, addr) + } + return +} + +// LookupIP looks up host using the local resolver. +// It returns an array of that host's IPv4 and IPv6 addresses. +func LookupIP(host string) (ips []IP, err os.Error) { + addrs, err := LookupHost(host) + if err != nil { + return + } + for _, addr := range addrs { + if ip := ParseIP(addr); ip != nil { + ips = append(ips, ip) + } + } + return +} + +// LookupPort looks up the port for the given network and service. +func LookupPort(network, service string) (port int, err os.Error) { + switch network { + case "tcp4", "tcp6": + network = "tcp" + case "udp4", "udp6": + network = "udp" + } + lines, err := queryCS(network, "127.0.0.1", service) + if err != nil { + return + } + unknownPortError := &AddrError{"unknown port", network + "/" + service} + if len(lines) == 0 { + return 0, unknownPortError + } + f := getFields(lines[0]) + if len(f) < 2 { + return 0, unknownPortError + } + s := f[1] + if i := byteIndex(s, '!'); i >= 0 { + s = s[i+1:] // remove address + } + if n, _, ok := dtoi(s, 0); ok { + return n, nil + } + return 0, unknownPortError +} + +// LookupCNAME returns the canonical DNS host for the given name. +// Callers that do not care about the canonical name can call +// LookupHost or LookupIP directly; both take care of resolving +// the canonical name as part of the lookup. +func LookupCNAME(name string) (cname string, err os.Error) { + lines, err := queryDNS(name, "cname") + if err != nil { + return + } + if len(lines) > 0 { + if f := getFields(lines[0]); len(f) >= 3 { + return f[2] + ".", nil + } + } + return "", os.NewError("net: bad response from ndb/dns") +} + +// LookupSRV tries to resolve an SRV query of the given service, +// protocol, and domain name, as specified in RFC 2782. In most cases +// the proto argument can be the same as the corresponding +// Addr.Network(). The returned records are sorted by priority +// and randomized by weight within a priority. +func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) { + target := "_" + service + "._" + proto + "." + name + lines, err := queryDNS(target, "srv") + if err != nil { + return + } + for _, line := range lines { + f := getFields(line) + if len(f) < 6 { + continue + } + port, _, portOk := dtoi(f[2], 0) + priority, _, priorityOk := dtoi(f[3], 0) + weight, _, weightOk := dtoi(f[4], 0) + if !(portOk && priorityOk && weightOk) { + continue + } + addrs = append(addrs, &SRV{f[5], uint16(port), uint16(priority), uint16(weight)}) + cname = f[0] + } + byPriorityWeight(addrs).sort() + return +} + +// LookupMX returns the DNS MX records for the given domain name sorted by preference. +func LookupMX(name string) (mx []*MX, err os.Error) { + lines, err := queryDNS(name, "mx") + if err != nil { + return + } + for _, line := range lines { + f := getFields(line) + if len(f) < 4 { + continue + } + if pref, _, ok := dtoi(f[2], 0); ok { + mx = append(mx, &MX{f[3], uint16(pref)}) + } + } + byPref(mx).sort() + return +} + +// LookupAddr performs a reverse lookup for the given address, returning a list +// of names mapping to that address. +func LookupAddr(addr string) (name []string, err os.Error) { + arpa, err := reverseaddr(addr) + if err != nil { + return + } + lines, err := queryDNS(arpa, "ptr") + if err != nil { + return + } + for _, line := range lines { + f := getFields(line) + if len(f) < 3 { + continue + } + name = append(name, f[2]) + } + return +} diff --git a/src/pkg/net/parse_test.go b/src/pkg/net/parse_test.go index 226f354d3..8d51eba18 100644 --- a/src/pkg/net/parse_test.go +++ b/src/pkg/net/parse_test.go @@ -12,8 +12,8 @@ import ( ) func TestReadLine(t *testing.T) { - // /etc/services file does not exist on windows. - if runtime.GOOS == "windows" { + // /etc/services file does not exist on windows and Plan 9. + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { return } filename := "/etc/services" // a nice big file diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go index 36780d789..7d7f7fc01 100644 --- a/src/pkg/net/server_test.go +++ b/src/pkg/net/server_test.go @@ -146,8 +146,8 @@ func TestTCPServer(t *testing.T) { } func TestUnixServer(t *testing.T) { - // "unix" sockets are not supported on windows. - if runtime.GOOS == "windows" { + // "unix" sockets are not supported on windows and Plan 9. + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { return } os.Remove("/tmp/gotest.net") @@ -225,8 +225,8 @@ func TestUDPServer(t *testing.T) { } func TestUnixDatagramServer(t *testing.T) { - // "unix" sockets are not supported on windows. - if runtime.GOOS == "windows" { + // "unix" sockets are not supported on windows and Plan 9. + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { return } for _, isEmpty := range []bool{false} { diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go index 9ee6c14f7..f5c0a2781 100644 --- a/src/pkg/net/tcpsock.go +++ b/src/pkg/net/tcpsock.go @@ -7,21 +7,9 @@ package net import ( - "io" "os" - "syscall" ) -func sockaddrToTCP(sa syscall.Sockaddr) Addr { - switch sa := sa.(type) { - case *syscall.SockaddrInet4: - return &TCPAddr{sa.Addr[0:], sa.Port} - case *syscall.SockaddrInet6: - return &TCPAddr{sa.Addr[0:], sa.Port} - } - return nil -} - // TCPAddr represents the address of a TCP end point. type TCPAddr struct { IP IP @@ -38,27 +26,6 @@ func (a *TCPAddr) String() string { return JoinHostPort(a.IP.String(), itoa(a.Port)) } -func (a *TCPAddr) family() int { - if a == nil || len(a.IP) <= 4 { - return syscall.AF_INET - } - if a.IP.To4() != nil { - return syscall.AF_INET - } - return syscall.AF_INET6 -} - -func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) { - return ipToSockaddr(family, a.IP, a.Port) -} - -func (a *TCPAddr) toAddr() sockaddr { - if a == nil { // nil *TCPAddr - return nil // nil interface - } - return a -} - // ResolveTCPAddr parses addr as a TCP address of the form // host:port and resolves domain names or port names to // numeric addresses on the network net, which must be "tcp", @@ -71,234 +38,3 @@ func ResolveTCPAddr(net, addr string) (*TCPAddr, os.Error) { } return &TCPAddr{ip, port}, nil } - -// TCPConn is an implementation of the Conn interface -// for TCP network connections. -type TCPConn struct { - fd *netFD -} - -func newTCPConn(fd *netFD) *TCPConn { - c := &TCPConn{fd} - c.SetNoDelay(true) - return c -} - -func (c *TCPConn) ok() bool { return c != nil && c.fd != nil } - -// Implementation of the Conn interface - see Conn for documentation. - -// Read implements the net.Conn Read method. -func (c *TCPConn) Read(b []byte) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - return c.fd.Read(b) -} - -// ReadFrom implements the io.ReaderFrom ReadFrom method. -func (c *TCPConn) ReadFrom(r io.Reader) (int64, os.Error) { - if n, err, handled := sendFile(c.fd, r); handled { - return n, err - } - return genericReadFrom(c, r) -} - -// Write implements the net.Conn Write method. -func (c *TCPConn) Write(b []byte) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - return c.fd.Write(b) -} - -// Close closes the TCP connection. -func (c *TCPConn) Close() os.Error { - if !c.ok() { - return os.EINVAL - } - err := c.fd.Close() - c.fd = nil - return err -} - -// LocalAddr returns the local network address, a *TCPAddr. -func (c *TCPConn) LocalAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.laddr -} - -// RemoteAddr returns the remote network address, a *TCPAddr. -func (c *TCPConn) RemoteAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.raddr -} - -// SetTimeout implements the net.Conn SetTimeout method. -func (c *TCPConn) SetTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setTimeout(c.fd, nsec) -} - -// SetReadTimeout implements the net.Conn SetReadTimeout method. -func (c *TCPConn) SetReadTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadTimeout(c.fd, nsec) -} - -// SetWriteTimeout implements the net.Conn SetWriteTimeout method. -func (c *TCPConn) SetWriteTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteTimeout(c.fd, nsec) -} - -// SetReadBuffer sets the size of the operating system's -// receive buffer associated with the connection. -func (c *TCPConn) SetReadBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadBuffer(c.fd, bytes) -} - -// SetWriteBuffer sets the size of the operating system's -// transmit buffer associated with the connection. -func (c *TCPConn) SetWriteBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteBuffer(c.fd, bytes) -} - -// SetLinger sets the behavior of Close() on a connection -// which still has data waiting to be sent or to be acknowledged. -// -// If sec < 0 (the default), Close returns immediately and -// the operating system finishes sending the data in the background. -// -// If sec == 0, Close returns immediately and the operating system -// discards any unsent or unacknowledged data. -// -// If sec > 0, Close blocks for at most sec seconds waiting for -// data to be sent and acknowledged. -func (c *TCPConn) SetLinger(sec int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setLinger(c.fd, sec) -} - -// SetKeepAlive sets whether the operating system should send -// keepalive messages on the connection. -func (c *TCPConn) SetKeepAlive(keepalive bool) os.Error { - if !c.ok() { - return os.EINVAL - } - return setKeepAlive(c.fd, keepalive) -} - -// SetNoDelay controls whether the operating system should delay -// packet transmission in hopes of sending fewer packets -// (Nagle's algorithm). The default is true (no delay), meaning -// that data is sent as soon as possible after a Write. -func (c *TCPConn) SetNoDelay(noDelay bool) os.Error { - if !c.ok() { - return os.EINVAL - } - return setNoDelay(c.fd, noDelay) -} - -// File returns a copy of the underlying os.File, set to blocking mode. -// It is the caller's responsibility to close f when finished. -// Closing c does not affect f, and closing f does not affect c. -func (c *TCPConn) File() (f *os.File, err os.Error) { return c.fd.dup() } - -// DialTCP connects to the remote address raddr on the network net, -// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used -// as the local address for the connection. -func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error) { - if raddr == nil { - return nil, &OpError{"dial", "tcp", nil, errMissingAddress} - } - fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) - if e != nil { - return nil, e - } - return newTCPConn(fd), nil -} - -// TCPListener is a TCP network listener. -// Clients should typically use variables of type Listener -// instead of assuming TCP. -type TCPListener struct { - fd *netFD -} - -// ListenTCP announces on the TCP address laddr and returns a TCP listener. -// Net must be "tcp", "tcp4", or "tcp6". -// If laddr has a port of 0, it means to listen on some available port. -// The caller can use l.Addr() to retrieve the chosen address. -func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) { - fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP) - if err != nil { - return nil, err - } - errno := syscall.Listen(fd.sysfd, listenBacklog()) - if errno != 0 { - closesocket(fd.sysfd) - return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)} - } - l = new(TCPListener) - l.fd = fd - return l, nil -} - -// AcceptTCP accepts the next incoming call and returns the new connection -// and the remote address. -func (l *TCPListener) AcceptTCP() (c *TCPConn, err os.Error) { - if l == nil || l.fd == nil || l.fd.sysfd < 0 { - return nil, os.EINVAL - } - fd, err := l.fd.accept(sockaddrToTCP) - if err != nil { - return nil, err - } - return newTCPConn(fd), nil -} - -// Accept implements the Accept method in the Listener interface; -// it waits for the next call and returns a generic Conn. -func (l *TCPListener) Accept() (c Conn, err os.Error) { - c1, err := l.AcceptTCP() - if err != nil { - return nil, err - } - return c1, nil -} - -// Close stops listening on the TCP address. -// Already Accepted connections are not closed. -func (l *TCPListener) Close() os.Error { - if l == nil || l.fd == nil { - return os.EINVAL - } - return l.fd.Close() -} - -// Addr returns the listener's network address, a *TCPAddr. -func (l *TCPListener) Addr() Addr { return l.fd.laddr } - -// File returns a copy of the underlying os.File, set to blocking mode. -// It is the caller's responsibility to close f when finished. -// Closing c does not affect f, and closing f does not affect c. -func (l *TCPListener) File() (f *os.File, err os.Error) { return l.fd.dup() } diff --git a/src/pkg/net/tcpsock_plan9.go b/src/pkg/net/tcpsock_plan9.go new file mode 100644 index 000000000..f4f6e9fee --- /dev/null +++ b/src/pkg/net/tcpsock_plan9.go @@ -0,0 +1,63 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TCP for Plan 9 + +package net + +import ( + "os" +) + +// TCPConn is an implementation of the Conn interface +// for TCP network connections. +type TCPConn struct { + plan9Conn +} + +// DialTCP connects to the remote address raddr on the network net, +// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used +// as the local address for the connection. +func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error) { + switch net { + case "tcp", "tcp4", "tcp6": + default: + return nil, UnknownNetworkError(net) + } + if raddr == nil { + return nil, &OpError{"dial", "tcp", nil, errMissingAddress} + } + c1, err := dialPlan9(net, laddr, raddr) + if err != nil { + return + } + return &TCPConn{*c1}, nil +} + +// TCPListener is a TCP network listener. +// Clients should typically use variables of type Listener +// instead of assuming TCP. +type TCPListener struct { + plan9Listener +} + +// ListenTCP announces on the TCP address laddr and returns a TCP listener. +// Net must be "tcp", "tcp4", or "tcp6". +// If laddr has a port of 0, it means to listen on some available port. +// The caller can use l.Addr() to retrieve the chosen address. +func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) { + switch net { + case "tcp", "tcp4", "tcp6": + default: + return nil, UnknownNetworkError(net) + } + if laddr == nil { + return nil, &OpError{"listen", "tcp", nil, errMissingAddress} + } + l1, err := listenPlan9(net, laddr) + if err != nil { + return + } + return &TCPListener{*l1}, nil +} diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go new file mode 100644 index 000000000..5560301b4 --- /dev/null +++ b/src/pkg/net/tcpsock_posix.go @@ -0,0 +1,283 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TCP sockets + +package net + +import ( + "io" + "os" + "syscall" +) + +func sockaddrToTCP(sa syscall.Sockaddr) Addr { + switch sa := sa.(type) { + case *syscall.SockaddrInet4: + return &TCPAddr{sa.Addr[0:], sa.Port} + case *syscall.SockaddrInet6: + return &TCPAddr{sa.Addr[0:], sa.Port} + } + return nil +} + +func (a *TCPAddr) family() int { + if a == nil || len(a.IP) <= 4 { + return syscall.AF_INET + } + if a.IP.To4() != nil { + return syscall.AF_INET + } + return syscall.AF_INET6 +} + +func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) { + return ipToSockaddr(family, a.IP, a.Port) +} + +func (a *TCPAddr) toAddr() sockaddr { + if a == nil { // nil *TCPAddr + return nil // nil interface + } + return a +} + +// TCPConn is an implementation of the Conn interface +// for TCP network connections. +type TCPConn struct { + fd *netFD +} + +func newTCPConn(fd *netFD) *TCPConn { + c := &TCPConn{fd} + c.SetNoDelay(true) + return c +} + +func (c *TCPConn) ok() bool { return c != nil && c.fd != nil } + +// Implementation of the Conn interface - see Conn for documentation. + +// Read implements the net.Conn Read method. +func (c *TCPConn) Read(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + return c.fd.Read(b) +} + +// ReadFrom implements the io.ReaderFrom ReadFrom method. +func (c *TCPConn) ReadFrom(r io.Reader) (int64, os.Error) { + if n, err, handled := sendFile(c.fd, r); handled { + return n, err + } + return genericReadFrom(c, r) +} + +// Write implements the net.Conn Write method. +func (c *TCPConn) Write(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + return c.fd.Write(b) +} + +// Close closes the TCP connection. +func (c *TCPConn) Close() os.Error { + if !c.ok() { + return os.EINVAL + } + err := c.fd.Close() + c.fd = nil + return err +} + +// LocalAddr returns the local network address, a *TCPAddr. +func (c *TCPConn) LocalAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.laddr +} + +// RemoteAddr returns the remote network address, a *TCPAddr. +func (c *TCPConn) RemoteAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.raddr +} + +// SetTimeout implements the net.Conn SetTimeout method. +func (c *TCPConn) SetTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setTimeout(c.fd, nsec) +} + +// SetReadTimeout implements the net.Conn SetReadTimeout method. +func (c *TCPConn) SetReadTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadTimeout(c.fd, nsec) +} + +// SetWriteTimeout implements the net.Conn SetWriteTimeout method. +func (c *TCPConn) SetWriteTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteTimeout(c.fd, nsec) +} + +// SetReadBuffer sets the size of the operating system's +// receive buffer associated with the connection. +func (c *TCPConn) SetReadBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadBuffer(c.fd, bytes) +} + +// SetWriteBuffer sets the size of the operating system's +// transmit buffer associated with the connection. +func (c *TCPConn) SetWriteBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteBuffer(c.fd, bytes) +} + +// SetLinger sets the behavior of Close() on a connection +// which still has data waiting to be sent or to be acknowledged. +// +// If sec < 0 (the default), Close returns immediately and +// the operating system finishes sending the data in the background. +// +// If sec == 0, Close returns immediately and the operating system +// discards any unsent or unacknowledged data. +// +// If sec > 0, Close blocks for at most sec seconds waiting for +// data to be sent and acknowledged. +func (c *TCPConn) SetLinger(sec int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setLinger(c.fd, sec) +} + +// SetKeepAlive sets whether the operating system should send +// keepalive messages on the connection. +func (c *TCPConn) SetKeepAlive(keepalive bool) os.Error { + if !c.ok() { + return os.EINVAL + } + return setKeepAlive(c.fd, keepalive) +} + +// SetNoDelay controls whether the operating system should delay +// packet transmission in hopes of sending fewer packets +// (Nagle's algorithm). The default is true (no delay), meaning +// that data is sent as soon as possible after a Write. +func (c *TCPConn) SetNoDelay(noDelay bool) os.Error { + if !c.ok() { + return os.EINVAL + } + return setNoDelay(c.fd, noDelay) +} + +// File returns a copy of the underlying os.File, set to blocking mode. +// It is the caller's responsibility to close f when finished. +// Closing c does not affect f, and closing f does not affect c. +func (c *TCPConn) File() (f *os.File, err os.Error) { return c.fd.dup() } + +// DialTCP connects to the remote address raddr on the network net, +// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used +// as the local address for the connection. +func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error) { + if raddr == nil { + return nil, &OpError{"dial", "tcp", nil, errMissingAddress} + } + fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) + if e != nil { + return nil, e + } + return newTCPConn(fd), nil +} + +// TCPListener is a TCP network listener. +// Clients should typically use variables of type Listener +// instead of assuming TCP. +type TCPListener struct { + fd *netFD +} + +// ListenTCP announces on the TCP address laddr and returns a TCP listener. +// Net must be "tcp", "tcp4", or "tcp6". +// If laddr has a port of 0, it means to listen on some available port. +// The caller can use l.Addr() to retrieve the chosen address. +func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) { + fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP) + if err != nil { + return nil, err + } + errno := syscall.Listen(fd.sysfd, listenBacklog()) + if errno != 0 { + closesocket(fd.sysfd) + return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)} + } + l = new(TCPListener) + l.fd = fd + return l, nil +} + +// AcceptTCP accepts the next incoming call and returns the new connection +// and the remote address. +func (l *TCPListener) AcceptTCP() (c *TCPConn, err os.Error) { + if l == nil || l.fd == nil || l.fd.sysfd < 0 { + return nil, os.EINVAL + } + fd, err := l.fd.accept(sockaddrToTCP) + if err != nil { + return nil, err + } + return newTCPConn(fd), nil +} + +// Accept implements the Accept method in the Listener interface; +// it waits for the next call and returns a generic Conn. +func (l *TCPListener) Accept() (c Conn, err os.Error) { + c1, err := l.AcceptTCP() + if err != nil { + return nil, err + } + return c1, nil +} + +// Close stops listening on the TCP address. +// Already Accepted connections are not closed. +func (l *TCPListener) Close() os.Error { + if l == nil || l.fd == nil { + return os.EINVAL + } + return l.fd.Close() +} + +// Addr returns the listener's network address, a *TCPAddr. +func (l *TCPListener) Addr() Addr { return l.fd.laddr } + +// SetTimeout sets the deadline associated with the listener +func (l *TCPListener) SetTimeout(nsec int64) os.Error { + if l == nil || l.fd == nil { + return os.EINVAL + } + return setTimeout(l.fd, nsec) +} + +// File returns a copy of the underlying os.File, set to blocking mode. +// It is the caller's responsibility to close f when finished. +// Closing c does not affect f, and closing f does not affect c. +func (l *TCPListener) File() (f *os.File, err os.Error) { return l.fd.dup() } diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go index 94e249d62..3dfa71675 100644 --- a/src/pkg/net/udpsock.go +++ b/src/pkg/net/udpsock.go @@ -8,19 +8,8 @@ package net import ( "os" - "syscall" ) -func sockaddrToUDP(sa syscall.Sockaddr) Addr { - switch sa := sa.(type) { - case *syscall.SockaddrInet4: - return &UDPAddr{sa.Addr[0:], sa.Port} - case *syscall.SockaddrInet6: - return &UDPAddr{sa.Addr[0:], sa.Port} - } - return nil -} - // UDPAddr represents the address of a UDP end point. type UDPAddr struct { IP IP @@ -37,27 +26,6 @@ func (a *UDPAddr) String() string { return JoinHostPort(a.IP.String(), itoa(a.Port)) } -func (a *UDPAddr) family() int { - if a == nil || len(a.IP) <= 4 { - return syscall.AF_INET - } - if a.IP.To4() != nil { - return syscall.AF_INET - } - return syscall.AF_INET6 -} - -func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) { - return ipToSockaddr(family, a.IP, a.Port) -} - -func (a *UDPAddr) toAddr() sockaddr { - if a == nil { // nil *UDPAddr - return nil // nil interface - } - return a -} - // ResolveUDPAddr parses addr as a UDP address of the form // host:port and resolves domain names or port names to // numeric addresses on the network net, which must be "udp", @@ -70,254 +38,3 @@ func ResolveUDPAddr(net, addr string) (*UDPAddr, os.Error) { } return &UDPAddr{ip, port}, nil } - -// UDPConn is the implementation of the Conn and PacketConn -// interfaces for UDP network connections. -type UDPConn struct { - fd *netFD -} - -func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{fd} } - -func (c *UDPConn) ok() bool { return c != nil && c.fd != nil } - -// Implementation of the Conn interface - see Conn for documentation. - -// Read implements the net.Conn Read method. -func (c *UDPConn) Read(b []byte) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - return c.fd.Read(b) -} - -// Write implements the net.Conn Write method. -func (c *UDPConn) Write(b []byte) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - return c.fd.Write(b) -} - -// Close closes the UDP connection. -func (c *UDPConn) Close() os.Error { - if !c.ok() { - return os.EINVAL - } - err := c.fd.Close() - c.fd = nil - return err -} - -// LocalAddr returns the local network address. -func (c *UDPConn) LocalAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.laddr -} - -// RemoteAddr returns the remote network address, a *UDPAddr. -func (c *UDPConn) RemoteAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.raddr -} - -// SetTimeout implements the net.Conn SetTimeout method. -func (c *UDPConn) SetTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setTimeout(c.fd, nsec) -} - -// SetReadTimeout implements the net.Conn SetReadTimeout method. -func (c *UDPConn) SetReadTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadTimeout(c.fd, nsec) -} - -// SetWriteTimeout implements the net.Conn SetWriteTimeout method. -func (c *UDPConn) SetWriteTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteTimeout(c.fd, nsec) -} - -// SetReadBuffer sets the size of the operating system's -// receive buffer associated with the connection. -func (c *UDPConn) SetReadBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadBuffer(c.fd, bytes) -} - -// SetWriteBuffer sets the size of the operating system's -// transmit buffer associated with the connection. -func (c *UDPConn) SetWriteBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteBuffer(c.fd, bytes) -} - -// UDP-specific methods. - -// ReadFromUDP reads a UDP packet from c, copying the payload into b. -// It returns the number of bytes copied into b and the return address -// that was on the packet. -// -// ReadFromUDP can be made to time out and return an error with Timeout() == true -// after a fixed time limit; see SetTimeout and SetReadTimeout. -func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) { - if !c.ok() { - return 0, nil, os.EINVAL - } - n, sa, err := c.fd.ReadFrom(b) - switch sa := sa.(type) { - case *syscall.SockaddrInet4: - addr = &UDPAddr{sa.Addr[0:], sa.Port} - case *syscall.SockaddrInet6: - addr = &UDPAddr{sa.Addr[0:], sa.Port} - } - return -} - -// ReadFrom implements the net.PacketConn ReadFrom method. -func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { - if !c.ok() { - return 0, nil, os.EINVAL - } - n, uaddr, err := c.ReadFromUDP(b) - return n, uaddr.toAddr(), err -} - -// WriteToUDP writes a UDP packet to addr via c, copying the payload from b. -// -// WriteToUDP can be made to time out and return -// an error with Timeout() == true after a fixed time limit; -// see SetTimeout and SetWriteTimeout. -// On packet-oriented connections, write timeouts are rare. -func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - sa, err1 := addr.sockaddr(c.fd.family) - if err1 != nil { - return 0, &OpError{Op: "write", Net: "udp", Addr: addr, Error: err1} - } - return c.fd.WriteTo(b, sa) -} - -// WriteTo implements the net.PacketConn WriteTo method. -func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - a, ok := addr.(*UDPAddr) - if !ok { - return 0, &OpError{"writeto", "udp", addr, os.EINVAL} - } - return c.WriteToUDP(b, a) -} - -// DialUDP connects to the remote address raddr on the network net, -// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used -// as the local address for the connection. -func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error) { - switch net { - case "udp", "udp4", "udp6": - default: - return nil, UnknownNetworkError(net) - } - if raddr == nil { - return nil, &OpError{"dial", "udp", nil, errMissingAddress} - } - fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP) - if e != nil { - return nil, e - } - return newUDPConn(fd), nil -} - -// ListenUDP listens for incoming UDP packets addressed to the -// local address laddr. The returned connection c's ReadFrom -// and WriteTo methods can be used to receive and send UDP -// packets with per-packet addressing. -func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) { - switch net { - case "udp", "udp4", "udp6": - default: - return nil, UnknownNetworkError(net) - } - if laddr == nil { - return nil, &OpError{"listen", "udp", nil, errMissingAddress} - } - fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP) - if e != nil { - return nil, e - } - return newUDPConn(fd), nil -} - -// BindToDevice binds a UDPConn to a network interface. -func (c *UDPConn) BindToDevice(device string) os.Error { - if !c.ok() { - return os.EINVAL - } - c.fd.incref() - defer c.fd.decref() - return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device)) -} - -// File returns a copy of the underlying os.File, set to blocking mode. -// It is the caller's responsibility to close f when finished. -// Closing c does not affect f, and closing f does not affect c. -func (c *UDPConn) File() (f *os.File, err os.Error) { return c.fd.dup() } - -var errInvalidMulticast = os.NewError("invalid IPv4 multicast address") - -// JoinGroup joins the IPv4 multicast group named by addr. -// The UDPConn must use the "udp4" network. -func (c *UDPConn) JoinGroup(addr IP) os.Error { - if !c.ok() { - return os.EINVAL - } - ip := addr.To4() - if ip == nil { - return &OpError{"joingroup", "udp", &IPAddr{ip}, errInvalidMulticast} - } - mreq := &syscall.IPMreq{ - Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}, - } - err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)) - if err != nil { - return &OpError{"joingroup", "udp", &IPAddr{ip}, err} - } - return nil -} - -// LeaveGroup exits the IPv4 multicast group named by addr. -func (c *UDPConn) LeaveGroup(addr IP) os.Error { - if !c.ok() { - return os.EINVAL - } - ip := addr.To4() - if ip == nil { - return &OpError{"leavegroup", "udp", &IPAddr{ip}, errInvalidMulticast} - } - mreq := &syscall.IPMreq{ - Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}, - } - err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)) - if err != nil { - return &OpError{"leavegroup", "udp", &IPAddr{ip}, err} - } - return nil -} diff --git a/src/pkg/net/udpsock_plan9.go b/src/pkg/net/udpsock_plan9.go new file mode 100644 index 000000000..bb7196041 --- /dev/null +++ b/src/pkg/net/udpsock_plan9.go @@ -0,0 +1,187 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// UDP for Plan 9 + +package net + +import ( + "os" +) + +// UDPConn is the implementation of the Conn and PacketConn +// interfaces for UDP network connections. +type UDPConn struct { + plan9Conn +} + +// UDP-specific methods. + +// ReadFromUDP reads a UDP packet from c, copying the payload into b. +// It returns the number of bytes copied into b and the return address +// that was on the packet. +// +// ReadFromUDP can be made to time out and return an error with Timeout() == true +// after a fixed time limit; see SetTimeout and SetReadTimeout. +func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + if c.data == nil { + c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) + if err != nil { + return 0, nil, err + } + } + buf := make([]byte, udpHeaderSize+len(b)) + m, err := c.data.Read(buf) + if err != nil { + return + } + if m < udpHeaderSize { + return 0, nil, os.NewError("short read reading UDP header") + } + buf = buf[:m] + + h, buf := unmarshalUDPHeader(buf) + n = copy(b, buf) + return n, &UDPAddr{h.raddr, int(h.rport)}, nil +} + +// ReadFrom implements the net.PacketConn ReadFrom method. +func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + return c.ReadFromUDP(b) +} + +// WriteToUDP writes a UDP packet to addr via c, copying the payload from b. +// +// WriteToUDP can be made to time out and return +// an error with Timeout() == true after a fixed time limit; +// see SetTimeout and SetWriteTimeout. +// On packet-oriented connections, write timeouts are rare. +func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + if c.data == nil { + c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) + if err != nil { + return 0, err + } + } + h := new(udpHeader) + h.raddr = addr.IP.To16() + h.laddr = c.laddr.(*UDPAddr).IP.To16() + h.ifcaddr = IPv6zero // ignored (receive only) + h.rport = uint16(addr.Port) + h.lport = uint16(c.laddr.(*UDPAddr).Port) + + buf := make([]byte, udpHeaderSize+len(b)) + i := copy(buf, h.Bytes()) + copy(buf[i:], b) + return c.data.Write(buf) +} + +// WriteTo implements the net.PacketConn WriteTo method. +func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + a, ok := addr.(*UDPAddr) + if !ok { + return 0, &OpError{"writeto", "udp", addr, os.EINVAL} + } + return c.WriteToUDP(b, a) +} + +// DialUDP connects to the remote address raddr on the network net, +// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used +// as the local address for the connection. +func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error) { + switch net { + case "udp", "udp4", "udp6": + default: + return nil, UnknownNetworkError(net) + } + if raddr == nil { + return nil, &OpError{"dial", "udp", nil, errMissingAddress} + } + c1, err := dialPlan9(net, laddr, raddr) + if err != nil { + return + } + return &UDPConn{*c1}, nil +} + +const udpHeaderSize = 16*3 + 2*2 + +type udpHeader struct { + raddr, laddr, ifcaddr IP + rport, lport uint16 +} + +func (h *udpHeader) Bytes() []byte { + b := make([]byte, udpHeaderSize) + i := 0 + i += copy(b[i:i+16], h.raddr) + i += copy(b[i:i+16], h.laddr) + i += copy(b[i:i+16], h.ifcaddr) + b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2 + b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2 + return b +} + +func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) { + h := new(udpHeader) + h.raddr, b = IP(b[:16]), b[16:] + h.laddr, b = IP(b[:16]), b[16:] + h.ifcaddr, b = IP(b[:16]), b[16:] + h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:] + h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:] + return h, b +} + +// ListenUDP listens for incoming UDP packets addressed to the +// local address laddr. The returned connection c's ReadFrom +// and WriteTo methods can be used to receive and send UDP +// packets with per-packet addressing. +func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) { + switch net { + case "udp", "udp4", "udp6": + default: + return nil, UnknownNetworkError(net) + } + if laddr == nil { + return nil, &OpError{"listen", "udp", nil, errMissingAddress} + } + l, err := listenPlan9(net, laddr) + if err != nil { + return + } + _, err = l.ctl.WriteString("headers") + if err != nil { + return + } + return &UDPConn{*l.plan9Conn()}, nil +} + +// JoinGroup joins the IPv4 multicast group named by addr. +// The UDPConn must use the "udp4" network. +func (c *UDPConn) JoinGroup(addr IP) os.Error { + if !c.ok() { + return os.EINVAL + } + return os.EPLAN9 +} + +// LeaveGroup exits the IPv4 multicast group named by addr. +func (c *UDPConn) LeaveGroup(addr IP) os.Error { + if !c.ok() { + return os.EINVAL + } + return os.EPLAN9 +} diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go new file mode 100644 index 000000000..d4ea056f3 --- /dev/null +++ b/src/pkg/net/udpsock_posix.go @@ -0,0 +1,294 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// UDP sockets + +package net + +import ( + "os" + "syscall" +) + +func sockaddrToUDP(sa syscall.Sockaddr) Addr { + switch sa := sa.(type) { + case *syscall.SockaddrInet4: + return &UDPAddr{sa.Addr[0:], sa.Port} + case *syscall.SockaddrInet6: + return &UDPAddr{sa.Addr[0:], sa.Port} + } + return nil +} + +func (a *UDPAddr) family() int { + if a == nil || len(a.IP) <= 4 { + return syscall.AF_INET + } + if a.IP.To4() != nil { + return syscall.AF_INET + } + return syscall.AF_INET6 +} + +func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) { + return ipToSockaddr(family, a.IP, a.Port) +} + +func (a *UDPAddr) toAddr() sockaddr { + if a == nil { // nil *UDPAddr + return nil // nil interface + } + return a +} + +// UDPConn is the implementation of the Conn and PacketConn +// interfaces for UDP network connections. +type UDPConn struct { + fd *netFD +} + +func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{fd} } + +func (c *UDPConn) ok() bool { return c != nil && c.fd != nil } + +// Implementation of the Conn interface - see Conn for documentation. + +// Read implements the net.Conn Read method. +func (c *UDPConn) Read(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + return c.fd.Read(b) +} + +// Write implements the net.Conn Write method. +func (c *UDPConn) Write(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + return c.fd.Write(b) +} + +// Close closes the UDP connection. +func (c *UDPConn) Close() os.Error { + if !c.ok() { + return os.EINVAL + } + err := c.fd.Close() + c.fd = nil + return err +} + +// LocalAddr returns the local network address. +func (c *UDPConn) LocalAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.laddr +} + +// RemoteAddr returns the remote network address, a *UDPAddr. +func (c *UDPConn) RemoteAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.raddr +} + +// SetTimeout implements the net.Conn SetTimeout method. +func (c *UDPConn) SetTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setTimeout(c.fd, nsec) +} + +// SetReadTimeout implements the net.Conn SetReadTimeout method. +func (c *UDPConn) SetReadTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadTimeout(c.fd, nsec) +} + +// SetWriteTimeout implements the net.Conn SetWriteTimeout method. +func (c *UDPConn) SetWriteTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteTimeout(c.fd, nsec) +} + +// SetReadBuffer sets the size of the operating system's +// receive buffer associated with the connection. +func (c *UDPConn) SetReadBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadBuffer(c.fd, bytes) +} + +// SetWriteBuffer sets the size of the operating system's +// transmit buffer associated with the connection. +func (c *UDPConn) SetWriteBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteBuffer(c.fd, bytes) +} + +// UDP-specific methods. + +// ReadFromUDP reads a UDP packet from c, copying the payload into b. +// It returns the number of bytes copied into b and the return address +// that was on the packet. +// +// ReadFromUDP can be made to time out and return an error with Timeout() == true +// after a fixed time limit; see SetTimeout and SetReadTimeout. +func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + n, sa, err := c.fd.ReadFrom(b) + switch sa := sa.(type) { + case *syscall.SockaddrInet4: + addr = &UDPAddr{sa.Addr[0:], sa.Port} + case *syscall.SockaddrInet6: + addr = &UDPAddr{sa.Addr[0:], sa.Port} + } + return +} + +// ReadFrom implements the net.PacketConn ReadFrom method. +func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + n, uaddr, err := c.ReadFromUDP(b) + return n, uaddr.toAddr(), err +} + +// WriteToUDP writes a UDP packet to addr via c, copying the payload from b. +// +// WriteToUDP can be made to time out and return +// an error with Timeout() == true after a fixed time limit; +// see SetTimeout and SetWriteTimeout. +// On packet-oriented connections, write timeouts are rare. +func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + sa, err1 := addr.sockaddr(c.fd.family) + if err1 != nil { + return 0, &OpError{Op: "write", Net: "udp", Addr: addr, Error: err1} + } + return c.fd.WriteTo(b, sa) +} + +// WriteTo implements the net.PacketConn WriteTo method. +func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + a, ok := addr.(*UDPAddr) + if !ok { + return 0, &OpError{"writeto", "udp", addr, os.EINVAL} + } + return c.WriteToUDP(b, a) +} + +// DialUDP connects to the remote address raddr on the network net, +// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used +// as the local address for the connection. +func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error) { + switch net { + case "udp", "udp4", "udp6": + default: + return nil, UnknownNetworkError(net) + } + if raddr == nil { + return nil, &OpError{"dial", "udp", nil, errMissingAddress} + } + fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP) + if e != nil { + return nil, e + } + return newUDPConn(fd), nil +} + +// ListenUDP listens for incoming UDP packets addressed to the +// local address laddr. The returned connection c's ReadFrom +// and WriteTo methods can be used to receive and send UDP +// packets with per-packet addressing. +func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) { + switch net { + case "udp", "udp4", "udp6": + default: + return nil, UnknownNetworkError(net) + } + if laddr == nil { + return nil, &OpError{"listen", "udp", nil, errMissingAddress} + } + fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP) + if e != nil { + return nil, e + } + return newUDPConn(fd), nil +} + +// BindToDevice binds a UDPConn to a network interface. +func (c *UDPConn) BindToDevice(device string) os.Error { + if !c.ok() { + return os.EINVAL + } + c.fd.incref() + defer c.fd.decref() + return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device)) +} + +// File returns a copy of the underlying os.File, set to blocking mode. +// It is the caller's responsibility to close f when finished. +// Closing c does not affect f, and closing f does not affect c. +func (c *UDPConn) File() (f *os.File, err os.Error) { return c.fd.dup() } + +var errInvalidMulticast = os.NewError("invalid IPv4 multicast address") + +// JoinGroup joins the IPv4 multicast group named by addr. +// The UDPConn must use the "udp4" network. +func (c *UDPConn) JoinGroup(addr IP) os.Error { + if !c.ok() { + return os.EINVAL + } + ip := addr.To4() + if ip == nil { + return &OpError{"joingroup", "udp", &IPAddr{ip}, errInvalidMulticast} + } + mreq := &syscall.IPMreq{ + Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}, + } + err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)) + if err != nil { + return &OpError{"joingroup", "udp", &IPAddr{ip}, err} + } + return nil +} + +// LeaveGroup exits the IPv4 multicast group named by addr. +func (c *UDPConn) LeaveGroup(addr IP) os.Error { + if !c.ok() { + return os.EINVAL + } + ip := addr.To4() + if ip == nil { + return &OpError{"leavegroup", "udp", &IPAddr{ip}, errInvalidMulticast} + } + mreq := &syscall.IPMreq{ + Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}, + } + err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)) + if err != nil { + return &OpError{"leavegroup", "udp", &IPAddr{ip}, err} + } + return nil +} diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go index 8c26a7baf..d5040f9a2 100644 --- a/src/pkg/net/unixsock.go +++ b/src/pkg/net/unixsock.go @@ -8,109 +8,14 @@ package net import ( "os" - "syscall" ) -func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err os.Error) { - var proto int - switch net { - default: - return nil, UnknownNetworkError(net) - case "unix": - proto = syscall.SOCK_STREAM - case "unixgram": - proto = syscall.SOCK_DGRAM - case "unixpacket": - proto = syscall.SOCK_SEQPACKET - } - - var la, ra syscall.Sockaddr - switch mode { - default: - panic("unixSocket mode " + mode) - - case "dial": - if laddr != nil { - la = &syscall.SockaddrUnix{Name: laddr.Name} - } - if raddr != nil { - ra = &syscall.SockaddrUnix{Name: raddr.Name} - } else if proto != syscall.SOCK_DGRAM || laddr == nil { - return nil, &OpError{Op: mode, Net: net, Error: errMissingAddress} - } - - case "listen": - if laddr == nil { - return nil, &OpError{mode, net, nil, errMissingAddress} - } - la = &syscall.SockaddrUnix{Name: laddr.Name} - if raddr != nil { - return nil, &OpError{Op: mode, Net: net, Addr: raddr, Error: &AddrError{Error: "unexpected remote address", Addr: raddr.String()}} - } - } - - f := sockaddrToUnix - if proto == syscall.SOCK_DGRAM { - f = sockaddrToUnixgram - } else if proto == syscall.SOCK_SEQPACKET { - f = sockaddrToUnixpacket - } - - fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f) - if oserr != nil { - goto Error - } - return fd, nil - -Error: - addr := raddr - if mode == "listen" { - addr = laddr - } - return nil, &OpError{Op: mode, Net: net, Addr: addr, Error: oserr} -} - // UnixAddr represents the address of a Unix domain socket end point. type UnixAddr struct { Name string Net string } -func sockaddrToUnix(sa syscall.Sockaddr) Addr { - if s, ok := sa.(*syscall.SockaddrUnix); ok { - return &UnixAddr{s.Name, "unix"} - } - return nil -} - -func sockaddrToUnixgram(sa syscall.Sockaddr) Addr { - if s, ok := sa.(*syscall.SockaddrUnix); ok { - return &UnixAddr{s.Name, "unixgram"} - } - return nil -} - -func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr { - if s, ok := sa.(*syscall.SockaddrUnix); ok { - return &UnixAddr{s.Name, "unixpacket"} - } - return nil -} - -func protoToNet(proto int) string { - switch proto { - case syscall.SOCK_STREAM: - return "unix" - case syscall.SOCK_SEQPACKET: - return "unixpacket" - case syscall.SOCK_DGRAM: - return "unixgram" - default: - panic("protoToNet unknown protocol") - } - return "" -} - // Network returns the address's network name, "unix" or "unixgram". func (a *UnixAddr) Network() string { return a.Net @@ -143,307 +48,3 @@ func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) { } return &UnixAddr{addr, net}, nil } - -// UnixConn is an implementation of the Conn interface -// for connections to Unix domain sockets. -type UnixConn struct { - fd *netFD -} - -func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{fd} } - -func (c *UnixConn) ok() bool { return c != nil && c.fd != nil } - -// Implementation of the Conn interface - see Conn for documentation. - -// Read implements the net.Conn Read method. -func (c *UnixConn) Read(b []byte) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - return c.fd.Read(b) -} - -// Write implements the net.Conn Write method. -func (c *UnixConn) Write(b []byte) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - return c.fd.Write(b) -} - -// Close closes the Unix domain connection. -func (c *UnixConn) Close() os.Error { - if !c.ok() { - return os.EINVAL - } - err := c.fd.Close() - c.fd = nil - return err -} - -// LocalAddr returns the local network address, a *UnixAddr. -// Unlike in other protocols, LocalAddr is usually nil for dialed connections. -func (c *UnixConn) LocalAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.laddr -} - -// RemoteAddr returns the remote network address, a *UnixAddr. -// Unlike in other protocols, RemoteAddr is usually nil for connections -// accepted by a listener. -func (c *UnixConn) RemoteAddr() Addr { - if !c.ok() { - return nil - } - return c.fd.raddr -} - -// SetTimeout implements the net.Conn SetTimeout method. -func (c *UnixConn) SetTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setTimeout(c.fd, nsec) -} - -// SetReadTimeout implements the net.Conn SetReadTimeout method. -func (c *UnixConn) SetReadTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadTimeout(c.fd, nsec) -} - -// SetWriteTimeout implements the net.Conn SetWriteTimeout method. -func (c *UnixConn) SetWriteTimeout(nsec int64) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteTimeout(c.fd, nsec) -} - -// SetReadBuffer sets the size of the operating system's -// receive buffer associated with the connection. -func (c *UnixConn) SetReadBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setReadBuffer(c.fd, bytes) -} - -// SetWriteBuffer sets the size of the operating system's -// transmit buffer associated with the connection. -func (c *UnixConn) SetWriteBuffer(bytes int) os.Error { - if !c.ok() { - return os.EINVAL - } - return setWriteBuffer(c.fd, bytes) -} - -// ReadFromUnix reads a packet from c, copying the payload into b. -// It returns the number of bytes copied into b and the return address -// that was on the packet. -// -// ReadFromUnix can be made to time out and return -// an error with Timeout() == true after a fixed time limit; -// see SetTimeout and SetReadTimeout. -func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error) { - if !c.ok() { - return 0, nil, os.EINVAL - } - n, sa, err := c.fd.ReadFrom(b) - switch sa := sa.(type) { - case *syscall.SockaddrUnix: - addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)} - } - return -} - -// ReadFrom implements the net.PacketConn ReadFrom method. -func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { - if !c.ok() { - return 0, nil, os.EINVAL - } - n, uaddr, err := c.ReadFromUnix(b) - return n, uaddr.toAddr(), err -} - -// WriteToUnix writes a packet to addr via c, copying the payload from b. -// -// WriteToUnix can be made to time out and return -// an error with Timeout() == true after a fixed time limit; -// see SetTimeout and SetWriteTimeout. -// On packet-oriented connections, write timeouts are rare. -func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - if addr.Net != protoToNet(c.fd.proto) { - return 0, os.EAFNOSUPPORT - } - sa := &syscall.SockaddrUnix{Name: addr.Name} - return c.fd.WriteTo(b, sa) -} - -// WriteTo implements the net.PacketConn WriteTo method. -func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { - if !c.ok() { - return 0, os.EINVAL - } - a, ok := addr.(*UnixAddr) - if !ok { - return 0, &OpError{"writeto", "unix", addr, os.EINVAL} - } - return c.WriteToUnix(b, a) -} - -func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err os.Error) { - if !c.ok() { - return 0, 0, 0, nil, os.EINVAL - } - n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob) - switch sa := sa.(type) { - case *syscall.SockaddrUnix: - addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)} - } - return -} - -func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) { - if !c.ok() { - return 0, 0, os.EINVAL - } - if addr != nil { - if addr.Net != protoToNet(c.fd.proto) { - return 0, 0, os.EAFNOSUPPORT - } - sa := &syscall.SockaddrUnix{Name: addr.Name} - return c.fd.WriteMsg(b, oob, sa) - } - return c.fd.WriteMsg(b, oob, nil) -} - -// File returns a copy of the underlying os.File, set to blocking mode. -// It is the caller's responsibility to close f when finished. -// Closing c does not affect f, and closing f does not affect c. -func (c *UnixConn) File() (f *os.File, err os.Error) { return c.fd.dup() } - -// DialUnix connects to the remote address raddr on the network net, -// which must be "unix" or "unixgram". If laddr is not nil, it is used -// as the local address for the connection. -func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err os.Error) { - fd, e := unixSocket(net, laddr, raddr, "dial") - if e != nil { - return nil, e - } - return newUnixConn(fd), nil -} - -// UnixListener is a Unix domain socket listener. -// Clients should typically use variables of type Listener -// instead of assuming Unix domain sockets. -type UnixListener struct { - fd *netFD - path string -} - -// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener. -// Net must be "unix" (stream sockets). -func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) { - if net != "unix" && net != "unixgram" && net != "unixpacket" { - return nil, UnknownNetworkError(net) - } - if laddr != nil { - laddr = &UnixAddr{laddr.Name, net} // make our own copy - } - fd, err := unixSocket(net, laddr, nil, "listen") - if err != nil { - return nil, err - } - e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog()); - if e1 != 0 { - closesocket(fd.sysfd) - return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Error: os.Errno(e1)} - } - return &UnixListener{fd, laddr.Name}, nil -} - -// AcceptUnix accepts the next incoming call and returns the new connection -// and the remote address. -func (l *UnixListener) AcceptUnix() (c *UnixConn, err os.Error) { - if l == nil || l.fd == nil { - return nil, os.EINVAL - } - fd, e := l.fd.accept(sockaddrToUnix) - if e != nil { - return nil, e - } - c = newUnixConn(fd) - return c, nil -} - -// Accept implements the Accept method in the Listener interface; -// it waits for the next call and returns a generic Conn. -func (l *UnixListener) Accept() (c Conn, err os.Error) { - c1, err := l.AcceptUnix() - if err != nil { - return nil, err - } - return c1, nil -} - -// Close stops listening on the Unix address. -// Already accepted connections are not closed. -func (l *UnixListener) Close() os.Error { - if l == nil || l.fd == nil { - return os.EINVAL - } - - // The operating system doesn't clean up - // the file that announcing created, so - // we have to clean it up ourselves. - // There's a race here--we can't know for - // sure whether someone else has come along - // and replaced our socket name already-- - // but this sequence (remove then close) - // is at least compatible with the auto-remove - // sequence in ListenUnix. It's only non-Go - // programs that can mess us up. - if l.path[0] != '@' { - syscall.Unlink(l.path) - } - err := l.fd.Close() - l.fd = nil - return err -} - -// Addr returns the listener's network address. -func (l *UnixListener) Addr() Addr { return l.fd.laddr } - -// File returns a copy of the underlying os.File, set to blocking mode. -// It is the caller's responsibility to close f when finished. -// Closing c does not affect f, and closing f does not affect c. -func (l *UnixListener) File() (f *os.File, err os.Error) { return l.fd.dup() } - -// ListenUnixgram listens for incoming Unix datagram packets addressed to the -// local address laddr. The returned connection c's ReadFrom -// and WriteTo methods can be used to receive and send UDP -// packets with per-packet addressing. The network net must be "unixgram". -func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err os.Error) { - switch net { - case "unixgram": - default: - return nil, UnknownNetworkError(net) - } - if laddr == nil { - return nil, &OpError{"listen", "unixgram", nil, errMissingAddress} - } - fd, e := unixSocket(net, laddr, nil, "listen") - if e != nil { - return nil, e - } - return newUDPConn(fd), nil -} diff --git a/src/pkg/net/unixsock_plan9.go b/src/pkg/net/unixsock_plan9.go new file mode 100644 index 000000000..7e212df8a --- /dev/null +++ b/src/pkg/net/unixsock_plan9.go @@ -0,0 +1,105 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Unix domain sockets stubs for Plan 9 + +package net + +import ( + "os" +) + +// UnixConn is an implementation of the Conn interface +// for connections to Unix domain sockets. +type UnixConn bool + +// Implementation of the Conn interface - see Conn for documentation. + +// Read implements the net.Conn Read method. +func (c *UnixConn) Read(b []byte) (n int, err os.Error) { + return 0, os.EPLAN9 +} + +// Write implements the net.Conn Write method. +func (c *UnixConn) Write(b []byte) (n int, err os.Error) { + return 0, os.EPLAN9 +} + +// Close closes the Unix domain connection. +func (c *UnixConn) Close() os.Error { + return os.EPLAN9 +} + +// LocalAddr returns the local network address, a *UnixAddr. +// Unlike in other protocols, LocalAddr is usually nil for dialed connections. +func (c *UnixConn) LocalAddr() Addr { + return nil +} + +// RemoteAddr returns the remote network address, a *UnixAddr. +// Unlike in other protocols, RemoteAddr is usually nil for connections +// accepted by a listener. +func (c *UnixConn) RemoteAddr() Addr { + return nil +} + +// SetTimeout implements the net.Conn SetTimeout method. +func (c *UnixConn) SetTimeout(nsec int64) os.Error { + return os.EPLAN9 +} + +// SetReadTimeout implements the net.Conn SetReadTimeout method. +func (c *UnixConn) SetReadTimeout(nsec int64) os.Error { + return os.EPLAN9 +} + +// SetWriteTimeout implements the net.Conn SetWriteTimeout method. +func (c *UnixConn) SetWriteTimeout(nsec int64) os.Error { + return os.EPLAN9 +} + +// ReadFrom implements the net.PacketConn ReadFrom method. +func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { + err = os.EPLAN9 + return +} + +// WriteTo implements the net.PacketConn WriteTo method. +func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { + err = os.EPLAN9 + return +} + +// DialUnix connects to the remote address raddr on the network net, +// which must be "unix" or "unixgram". If laddr is not nil, it is used +// as the local address for the connection. +func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err os.Error) { + return nil, os.EPLAN9 +} + +// UnixListener is a Unix domain socket listener. +// Clients should typically use variables of type Listener +// instead of assuming Unix domain sockets. +type UnixListener bool + +// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener. +// Net must be "unix" (stream sockets). +func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) { + return nil, os.EPLAN9 +} + +// Accept implements the Accept method in the Listener interface; +// it waits for the next call and returns a generic Conn. +func (l *UnixListener) Accept() (c Conn, err os.Error) { + return nil, os.EPLAN9 +} + +// Close stops listening on the Unix address. +// Already accepted connections are not closed. +func (l *UnixListener) Close() os.Error { + return os.EPLAN9 +} + +// Addr returns the listener's network address. +func (l *UnixListener) Addr() Addr { return nil } diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go new file mode 100644 index 000000000..38c6fe9eb --- /dev/null +++ b/src/pkg/net/unixsock_posix.go @@ -0,0 +1,418 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Unix domain sockets + +package net + +import ( + "os" + "syscall" +) + +func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err os.Error) { + var proto int + switch net { + default: + return nil, UnknownNetworkError(net) + case "unix": + proto = syscall.SOCK_STREAM + case "unixgram": + proto = syscall.SOCK_DGRAM + case "unixpacket": + proto = syscall.SOCK_SEQPACKET + } + + var la, ra syscall.Sockaddr + switch mode { + default: + panic("unixSocket mode " + mode) + + case "dial": + if laddr != nil { + la = &syscall.SockaddrUnix{Name: laddr.Name} + } + if raddr != nil { + ra = &syscall.SockaddrUnix{Name: raddr.Name} + } else if proto != syscall.SOCK_DGRAM || laddr == nil { + return nil, &OpError{Op: mode, Net: net, Error: errMissingAddress} + } + + case "listen": + if laddr == nil { + return nil, &OpError{mode, net, nil, errMissingAddress} + } + la = &syscall.SockaddrUnix{Name: laddr.Name} + if raddr != nil { + return nil, &OpError{Op: mode, Net: net, Addr: raddr, Error: &AddrError{Error: "unexpected remote address", Addr: raddr.String()}} + } + } + + f := sockaddrToUnix + if proto == syscall.SOCK_DGRAM { + f = sockaddrToUnixgram + } else if proto == syscall.SOCK_SEQPACKET { + f = sockaddrToUnixpacket + } + + fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f) + if oserr != nil { + goto Error + } + return fd, nil + +Error: + addr := raddr + if mode == "listen" { + addr = laddr + } + return nil, &OpError{Op: mode, Net: net, Addr: addr, Error: oserr} +} + +func sockaddrToUnix(sa syscall.Sockaddr) Addr { + if s, ok := sa.(*syscall.SockaddrUnix); ok { + return &UnixAddr{s.Name, "unix"} + } + return nil +} + +func sockaddrToUnixgram(sa syscall.Sockaddr) Addr { + if s, ok := sa.(*syscall.SockaddrUnix); ok { + return &UnixAddr{s.Name, "unixgram"} + } + return nil +} + +func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr { + if s, ok := sa.(*syscall.SockaddrUnix); ok { + return &UnixAddr{s.Name, "unixpacket"} + } + return nil +} + +func protoToNet(proto int) string { + switch proto { + case syscall.SOCK_STREAM: + return "unix" + case syscall.SOCK_SEQPACKET: + return "unixpacket" + case syscall.SOCK_DGRAM: + return "unixgram" + default: + panic("protoToNet unknown protocol") + } + return "" +} + +// UnixConn is an implementation of the Conn interface +// for connections to Unix domain sockets. +type UnixConn struct { + fd *netFD +} + +func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{fd} } + +func (c *UnixConn) ok() bool { return c != nil && c.fd != nil } + +// Implementation of the Conn interface - see Conn for documentation. + +// Read implements the net.Conn Read method. +func (c *UnixConn) Read(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + return c.fd.Read(b) +} + +// Write implements the net.Conn Write method. +func (c *UnixConn) Write(b []byte) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + return c.fd.Write(b) +} + +// Close closes the Unix domain connection. +func (c *UnixConn) Close() os.Error { + if !c.ok() { + return os.EINVAL + } + err := c.fd.Close() + c.fd = nil + return err +} + +// LocalAddr returns the local network address, a *UnixAddr. +// Unlike in other protocols, LocalAddr is usually nil for dialed connections. +func (c *UnixConn) LocalAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.laddr +} + +// RemoteAddr returns the remote network address, a *UnixAddr. +// Unlike in other protocols, RemoteAddr is usually nil for connections +// accepted by a listener. +func (c *UnixConn) RemoteAddr() Addr { + if !c.ok() { + return nil + } + return c.fd.raddr +} + +// SetTimeout implements the net.Conn SetTimeout method. +func (c *UnixConn) SetTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setTimeout(c.fd, nsec) +} + +// SetReadTimeout implements the net.Conn SetReadTimeout method. +func (c *UnixConn) SetReadTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadTimeout(c.fd, nsec) +} + +// SetWriteTimeout implements the net.Conn SetWriteTimeout method. +func (c *UnixConn) SetWriteTimeout(nsec int64) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteTimeout(c.fd, nsec) +} + +// SetReadBuffer sets the size of the operating system's +// receive buffer associated with the connection. +func (c *UnixConn) SetReadBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setReadBuffer(c.fd, bytes) +} + +// SetWriteBuffer sets the size of the operating system's +// transmit buffer associated with the connection. +func (c *UnixConn) SetWriteBuffer(bytes int) os.Error { + if !c.ok() { + return os.EINVAL + } + return setWriteBuffer(c.fd, bytes) +} + +// ReadFromUnix reads a packet from c, copying the payload into b. +// It returns the number of bytes copied into b and the return address +// that was on the packet. +// +// ReadFromUnix can be made to time out and return +// an error with Timeout() == true after a fixed time limit; +// see SetTimeout and SetReadTimeout. +func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + n, sa, err := c.fd.ReadFrom(b) + switch sa := sa.(type) { + case *syscall.SockaddrUnix: + addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)} + } + return +} + +// ReadFrom implements the net.PacketConn ReadFrom method. +func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) { + if !c.ok() { + return 0, nil, os.EINVAL + } + n, uaddr, err := c.ReadFromUnix(b) + return n, uaddr.toAddr(), err +} + +// WriteToUnix writes a packet to addr via c, copying the payload from b. +// +// WriteToUnix can be made to time out and return +// an error with Timeout() == true after a fixed time limit; +// see SetTimeout and SetWriteTimeout. +// On packet-oriented connections, write timeouts are rare. +func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + if addr.Net != protoToNet(c.fd.proto) { + return 0, os.EAFNOSUPPORT + } + sa := &syscall.SockaddrUnix{Name: addr.Name} + return c.fd.WriteTo(b, sa) +} + +// WriteTo implements the net.PacketConn WriteTo method. +func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) { + if !c.ok() { + return 0, os.EINVAL + } + a, ok := addr.(*UnixAddr) + if !ok { + return 0, &OpError{"writeto", "unix", addr, os.EINVAL} + } + return c.WriteToUnix(b, a) +} + +func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err os.Error) { + if !c.ok() { + return 0, 0, 0, nil, os.EINVAL + } + n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob) + switch sa := sa.(type) { + case *syscall.SockaddrUnix: + addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)} + } + return +} + +func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) { + if !c.ok() { + return 0, 0, os.EINVAL + } + if addr != nil { + if addr.Net != protoToNet(c.fd.proto) { + return 0, 0, os.EAFNOSUPPORT + } + sa := &syscall.SockaddrUnix{Name: addr.Name} + return c.fd.WriteMsg(b, oob, sa) + } + return c.fd.WriteMsg(b, oob, nil) +} + +// File returns a copy of the underlying os.File, set to blocking mode. +// It is the caller's responsibility to close f when finished. +// Closing c does not affect f, and closing f does not affect c. +func (c *UnixConn) File() (f *os.File, err os.Error) { return c.fd.dup() } + +// DialUnix connects to the remote address raddr on the network net, +// which must be "unix" or "unixgram". If laddr is not nil, it is used +// as the local address for the connection. +func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err os.Error) { + fd, e := unixSocket(net, laddr, raddr, "dial") + if e != nil { + return nil, e + } + return newUnixConn(fd), nil +} + +// UnixListener is a Unix domain socket listener. +// Clients should typically use variables of type Listener +// instead of assuming Unix domain sockets. +type UnixListener struct { + fd *netFD + path string +} + +// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener. +// Net must be "unix" (stream sockets). +func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) { + if net != "unix" && net != "unixgram" && net != "unixpacket" { + return nil, UnknownNetworkError(net) + } + if laddr != nil { + laddr = &UnixAddr{laddr.Name, net} // make our own copy + } + fd, err := unixSocket(net, laddr, nil, "listen") + if err != nil { + return nil, err + } + e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog()); + if e1 != 0 { + closesocket(fd.sysfd) + return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Error: os.Errno(e1)} + } + return &UnixListener{fd, laddr.Name}, nil +} + +// AcceptUnix accepts the next incoming call and returns the new connection +// and the remote address. +func (l *UnixListener) AcceptUnix() (c *UnixConn, err os.Error) { + if l == nil || l.fd == nil { + return nil, os.EINVAL + } + fd, e := l.fd.accept(sockaddrToUnix) + if e != nil { + return nil, e + } + c = newUnixConn(fd) + return c, nil +} + +// Accept implements the Accept method in the Listener interface; +// it waits for the next call and returns a generic Conn. +func (l *UnixListener) Accept() (c Conn, err os.Error) { + c1, err := l.AcceptUnix() + if err != nil { + return nil, err + } + return c1, nil +} + +// Close stops listening on the Unix address. +// Already accepted connections are not closed. +func (l *UnixListener) Close() os.Error { + if l == nil || l.fd == nil { + return os.EINVAL + } + + // The operating system doesn't clean up + // the file that announcing created, so + // we have to clean it up ourselves. + // There's a race here--we can't know for + // sure whether someone else has come along + // and replaced our socket name already-- + // but this sequence (remove then close) + // is at least compatible with the auto-remove + // sequence in ListenUnix. It's only non-Go + // programs that can mess us up. + if l.path[0] != '@' { + syscall.Unlink(l.path) + } + err := l.fd.Close() + l.fd = nil + return err +} + +// Addr returns the listener's network address. +func (l *UnixListener) Addr() Addr { return l.fd.laddr } + +// SetTimeout sets the deadline associated wuth the listener +func (l *UnixListener) SetTimeout(nsec int64) (err os.Error) { + if l == nil || l.fd == nil { + return os.EINVAL + } + return setTimeout(l.fd, nsec) +} + +// File returns a copy of the underlying os.File, set to blocking mode. +// It is the caller's responsibility to close f when finished. +// Closing c does not affect f, and closing f does not affect c. +func (l *UnixListener) File() (f *os.File, err os.Error) { return l.fd.dup() } + +// ListenUnixgram listens for incoming Unix datagram packets addressed to the +// local address laddr. The returned connection c's ReadFrom +// and WriteTo methods can be used to receive and send UDP +// packets with per-packet addressing. The network net must be "unixgram". +func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err os.Error) { + switch net { + case "unixgram": + default: + return nil, UnknownNetworkError(net) + } + if laddr == nil { + return nil, &OpError{"listen", "unixgram", nil, errMissingAddress} + } + fd, e := unixSocket(net, laddr, nil, "listen") + if e != nil { + return nil, e + } + return newUDPConn(fd), nil +} diff --git a/src/pkg/old/template/Makefile b/src/pkg/old/template/Makefile new file mode 100644 index 000000000..5772cb4aa --- /dev/null +++ b/src/pkg/old/template/Makefile @@ -0,0 +1,14 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include ../../../Make.inc + +TARG=old/template +GOFILES=\ + doc.go\ + execute.go\ + format.go\ + parse.go\ + +include ../../../Make.pkg diff --git a/src/pkg/old/template/doc.go b/src/pkg/old/template/doc.go new file mode 100644 index 000000000..e778d801d --- /dev/null +++ b/src/pkg/old/template/doc.go @@ -0,0 +1,91 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + Package template implements data-driven templates for generating textual + output such as HTML. + + Templates are executed by applying them to a data structure. + Annotations in the template refer to elements of the data + structure (typically a field of a struct or a key in a map) + to control execution and derive values to be displayed. + The template walks the structure as it executes and the + "cursor" @ represents the value at the current location + in the structure. + + Data items may be values or pointers; the interface hides the + indirection. + + In the following, 'Field' is one of several things, according to the data. + + - The name of a field of a struct (result = data.Field), + - The value stored in a map under that key (result = data["Field"]), or + - The result of invoking a niladic single-valued method with that name + (result = data.Field()) + + If Field is a struct field or method name, it must be an exported + (capitalized) name. + + Major constructs ({} are the default delimiters for template actions; + [] are the notation in this comment for optional elements): + + {# comment } + + A one-line comment. + + {.section field} XXX [ {.or} YYY ] {.end} + + Set @ to the value of the field. It may be an explicit @ + to stay at the same point in the data. If the field is nil + or empty, execute YYY; otherwise execute XXX. + + {.repeated section field} XXX [ {.alternates with} ZZZ ] [ {.or} YYY ] {.end} + + Like .section, but field must be an array or slice. XXX + is executed for each element. If the array is nil or empty, + YYY is executed instead. If the {.alternates with} marker + is present, ZZZ is executed between iterations of XXX. + + {field} + {field1 field2 ...} + {field|formatter} + {field1 field2...|formatter} + {field|formatter1|formatter2} + + Insert the value of the fields into the output. Each field is + first looked for in the cursor, as in .section and .repeated. + If it is not found, the search continues in outer sections + until the top level is reached. + + If the field value is a pointer, leading asterisks indicate + that the value to be inserted should be evaluated through the + pointer. For example, if x.p is of type *int, {x.p} will + insert the value of the pointer but {*x.p} will insert the + value of the underlying integer. If the value is nil or not a + pointer, asterisks have no effect. + + If a formatter is specified, it must be named in the formatter + map passed to the template set up routines or in the default + set ("html","str","") and is used to process the data for + output. The formatter function has signature + func(wr io.Writer, formatter string, data ...interface{}) + where wr is the destination for output, data holds the field + values at the instantiation, and formatter is its name at + the invocation site. The default formatter just concatenates + the string representations of the fields. + + Multiple formatters separated by the pipeline character | are + executed sequentially, with each formatter receiving the bytes + emitted by the one to its left. + + As well as field names, one may use literals with Go syntax. + Integer, floating-point, and string literals are supported. + Raw strings may not span newlines. + + The delimiter strings get their default value, "{" and "}", from + JSON-template. They may be set to any non-empty, space-free + string using the SetDelims method. Their value can be printed + in the output using {.meta-left} and {.meta-right}. +*/ +package template diff --git a/src/pkg/template/execute.go b/src/pkg/old/template/execute.go index 464b620c9..464b620c9 100644 --- a/src/pkg/template/execute.go +++ b/src/pkg/old/template/execute.go diff --git a/src/pkg/template/format.go b/src/pkg/old/template/format.go index 9156b0808..9156b0808 100644 --- a/src/pkg/template/format.go +++ b/src/pkg/old/template/format.go diff --git a/src/pkg/old/template/parse.go b/src/pkg/old/template/parse.go new file mode 100644 index 000000000..dedf9ad8e --- /dev/null +++ b/src/pkg/old/template/parse.go @@ -0,0 +1,743 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code to parse a template. + +package template + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "reflect" + "strconv" + "strings" + "unicode" + "utf8" +) + +// Errors returned during parsing and execution. Users may extract the information and reformat +// if they desire. +type Error struct { + Line int + Msg string +} + +func (e *Error) String() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) } + +// checkError is a deferred function to turn a panic with type *Error into a plain error return. +// Other panics are unexpected and so are re-enabled. +func checkError(error *os.Error) { + if v := recover(); v != nil { + if e, ok := v.(*Error); ok { + *error = e + } else { + // runtime errors should crash + panic(v) + } + } +} + +// Most of the literals are aces. +var lbrace = []byte{'{'} +var rbrace = []byte{'}'} +var space = []byte{' '} +var tab = []byte{'\t'} + +// The various types of "tokens", which are plain text or (usually) brace-delimited descriptors +const ( + tokAlternates = iota + tokComment + tokEnd + tokLiteral + tokOr + tokRepeated + tokSection + tokText + tokVariable +) + +// FormatterMap is the type describing the mapping from formatter +// names to the functions that implement them. +type FormatterMap map[string]func(io.Writer, string, ...interface{}) + +// Built-in formatters. +var builtins = FormatterMap{ + "html": HTMLFormatter, + "str": StringFormatter, + "": StringFormatter, +} + +// The parsed state of a template is a vector of xxxElement structs. +// Sections have line numbers so errors can be reported better during execution. + +// Plain text. +type textElement struct { + text []byte +} + +// A literal such as .meta-left or .meta-right +type literalElement struct { + text []byte +} + +// A variable invocation to be evaluated +type variableElement struct { + linenum int + args []interface{} // The fields and literals in the invocation. + fmts []string // Names of formatters to apply. len(fmts) > 0 +} + +// A variableElement arg to be evaluated as a field name +type fieldName string + +// A .section block, possibly with a .or +type sectionElement struct { + linenum int // of .section itself + field string // cursor field for this block + start int // first element + or int // first element of .or block + end int // one beyond last element +} + +// A .repeated block, possibly with a .or and a .alternates +type repeatedElement struct { + sectionElement // It has the same structure... + altstart int // ... except for alternates + altend int +} + +// Template is the type that represents a template definition. +// It is unchanged after parsing. +type Template struct { + fmap FormatterMap // formatters for variables + // Used during parsing: + ldelim, rdelim []byte // delimiters; default {} + buf []byte // input text to process + p int // position in buf + linenum int // position in input + // Parsed results: + elems []interface{} +} + +// New creates a new template with the specified formatter map (which +// may be nil) to define auxiliary functions for formatting variables. +func New(fmap FormatterMap) *Template { + t := new(Template) + t.fmap = fmap + t.ldelim = lbrace + t.rdelim = rbrace + t.elems = make([]interface{}, 0, 16) + return t +} + +// Report error and stop executing. The line number must be provided explicitly. +func (t *Template) execError(st *state, line int, err string, args ...interface{}) { + panic(&Error{line, fmt.Sprintf(err, args...)}) +} + +// Report error, panic to terminate parsing. +// The line number comes from the template state. +func (t *Template) parseError(err string, args ...interface{}) { + panic(&Error{t.linenum, fmt.Sprintf(err, args...)}) +} + +// Is this an exported - upper case - name? +func isExported(name string) bool { + rune, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(rune) +} + +// -- Lexical analysis + +// Is c a space character? +func isSpace(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } + +// Safely, does s[n:n+len(t)] == t? +func equal(s []byte, n int, t []byte) bool { + b := s[n:] + if len(t) > len(b) { // not enough space left for a match. + return false + } + for i, c := range t { + if c != b[i] { + return false + } + } + return true +} + +// isQuote returns true if c is a string- or character-delimiting quote character. +func isQuote(c byte) bool { + return c == '"' || c == '`' || c == '\'' +} + +// endQuote returns the end quote index for the quoted string that +// starts at n, or -1 if no matching end quote is found before the end +// of the line. +func endQuote(s []byte, n int) int { + quote := s[n] + for n++; n < len(s); n++ { + switch s[n] { + case '\\': + if quote == '"' || quote == '\'' { + n++ + } + case '\n': + return -1 + case quote: + return n + } + } + return -1 +} + +// nextItem returns the next item from the input buffer. If the returned +// item is empty, we are at EOF. The item will be either a +// delimited string or a non-empty string between delimited +// strings. Tokens stop at (but include, if plain text) a newline. +// Action tokens on a line by themselves drop any space on +// either side, up to and including the newline. +func (t *Template) nextItem() []byte { + startOfLine := t.p == 0 || t.buf[t.p-1] == '\n' + start := t.p + var i int + newline := func() { + t.linenum++ + i++ + } + // Leading space up to but not including newline + for i = start; i < len(t.buf); i++ { + if t.buf[i] == '\n' || !isSpace(t.buf[i]) { + break + } + } + leadingSpace := i > start + // What's left is nothing, newline, delimited string, or plain text + switch { + case i == len(t.buf): + // EOF; nothing to do + case t.buf[i] == '\n': + newline() + case equal(t.buf, i, t.ldelim): + left := i // Start of left delimiter. + right := -1 // Will be (immediately after) right delimiter. + haveText := false // Delimiters contain text. + i += len(t.ldelim) + // Find the end of the action. + for ; i < len(t.buf); i++ { + if t.buf[i] == '\n' { + break + } + if isQuote(t.buf[i]) { + i = endQuote(t.buf, i) + if i == -1 { + t.parseError("unmatched quote") + return nil + } + continue + } + if equal(t.buf, i, t.rdelim) { + i += len(t.rdelim) + right = i + break + } + haveText = true + } + if right < 0 { + t.parseError("unmatched opening delimiter") + return nil + } + // Is this a special action (starts with '.' or '#') and the only thing on the line? + if startOfLine && haveText { + firstChar := t.buf[left+len(t.ldelim)] + if firstChar == '.' || firstChar == '#' { + // It's special and the first thing on the line. Is it the last? + for j := right; j < len(t.buf) && isSpace(t.buf[j]); j++ { + if t.buf[j] == '\n' { + // Yes it is. Drop the surrounding space and return the {.foo} + t.linenum++ + t.p = j + 1 + return t.buf[left:right] + } + } + } + } + // No it's not. If there's leading space, return that. + if leadingSpace { + // not trimming space: return leading space if there is some. + t.p = left + return t.buf[start:left] + } + // Return the word, leave the trailing space. + start = left + break + default: + for ; i < len(t.buf); i++ { + if t.buf[i] == '\n' { + newline() + break + } + if equal(t.buf, i, t.ldelim) { + break + } + } + } + item := t.buf[start:i] + t.p = i + return item +} + +// Turn a byte array into a space-split array of strings, +// taking into account quoted strings. +func words(buf []byte) []string { + s := make([]string, 0, 5) + for i := 0; i < len(buf); { + // One word per loop + for i < len(buf) && isSpace(buf[i]) { + i++ + } + if i == len(buf) { + break + } + // Got a word + start := i + if isQuote(buf[i]) { + i = endQuote(buf, i) + if i < 0 { + i = len(buf) + } else { + i++ + } + } + // Even with quotes, break on space only. This handles input + // such as {""|} and catches quoting mistakes. + for i < len(buf) && !isSpace(buf[i]) { + i++ + } + s = append(s, string(buf[start:i])) + } + return s +} + +// Analyze an item and return its token type and, if it's an action item, an array of +// its constituent words. +func (t *Template) analyze(item []byte) (tok int, w []string) { + // item is known to be non-empty + if !equal(item, 0, t.ldelim) { // doesn't start with left delimiter + tok = tokText + return + } + if !equal(item, len(item)-len(t.rdelim), t.rdelim) { // doesn't end with right delimiter + t.parseError("internal error: unmatched opening delimiter") // lexing should prevent this + return + } + if len(item) <= len(t.ldelim)+len(t.rdelim) { // no contents + t.parseError("empty directive") + return + } + // Comment + if item[len(t.ldelim)] == '#' { + tok = tokComment + return + } + // Split into words + w = words(item[len(t.ldelim) : len(item)-len(t.rdelim)]) // drop final delimiter + if len(w) == 0 { + t.parseError("empty directive") + return + } + first := w[0] + if first[0] != '.' { + tok = tokVariable + return + } + if len(first) > 1 && first[1] >= '0' && first[1] <= '9' { + // Must be a float. + tok = tokVariable + return + } + switch first { + case ".meta-left", ".meta-right", ".space", ".tab": + tok = tokLiteral + return + case ".or": + tok = tokOr + return + case ".end": + tok = tokEnd + return + case ".section": + if len(w) != 2 { + t.parseError("incorrect fields for .section: %s", item) + return + } + tok = tokSection + return + case ".repeated": + if len(w) != 3 || w[1] != "section" { + t.parseError("incorrect fields for .repeated: %s", item) + return + } + tok = tokRepeated + return + case ".alternates": + if len(w) != 2 || w[1] != "with" { + t.parseError("incorrect fields for .alternates: %s", item) + return + } + tok = tokAlternates + return + } + t.parseError("bad directive: %s", item) + return +} + +// formatter returns the Formatter with the given name in the Template, or nil if none exists. +func (t *Template) formatter(name string) func(io.Writer, string, ...interface{}) { + if t.fmap != nil { + if fn := t.fmap[name]; fn != nil { + return fn + } + } + return builtins[name] +} + +// -- Parsing + +// newVariable allocates a new variable-evaluation element. +func (t *Template) newVariable(words []string) *variableElement { + formatters := extractFormatters(words) + args := make([]interface{}, len(words)) + + // Build argument list, processing any literals + for i, word := range words { + var lerr os.Error + switch word[0] { + case '"', '`', '\'': + v, err := strconv.Unquote(word) + if err == nil && word[0] == '\'' { + args[i] = []int(v)[0] + } else { + args[i], lerr = v, err + } + + case '.', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + v, err := strconv.Btoi64(word, 0) + if err == nil { + args[i] = v + } else { + v, err := strconv.Atof64(word) + args[i], lerr = v, err + } + + default: + args[i] = fieldName(word) + } + if lerr != nil { + t.parseError("invalid literal: %q: %s", word, lerr) + } + } + + // We could remember the function address here and avoid the lookup later, + // but it's more dynamic to let the user change the map contents underfoot. + // We do require the name to be present, though. + + // Is it in user-supplied map? + for _, f := range formatters { + if t.formatter(f) == nil { + t.parseError("unknown formatter: %q", f) + } + } + + return &variableElement{t.linenum, args, formatters} +} + +// extractFormatters extracts a list of formatters from words. +// After the final space-separated argument in a variable, formatters may be +// specified separated by pipe symbols. For example: {a b c|d|e} +// The words parameter still has the formatters joined by '|' in the last word. +// extractFormatters splits formatters, replaces the last word with the content +// found before the first '|' within it, and returns the formatters obtained. +// If no formatters are found in words, the default formatter is returned. +func extractFormatters(words []string) (formatters []string) { + // "" is the default formatter. + formatters = []string{""} + if len(words) == 0 { + return + } + var bar int + lastWord := words[len(words)-1] + if isQuote(lastWord[0]) { + end := endQuote([]byte(lastWord), 0) + if end < 0 || end+1 == len(lastWord) || lastWord[end+1] != '|' { + return + } + bar = end + 1 + } else { + bar = strings.IndexRune(lastWord, '|') + if bar < 0 { + return + } + } + words[len(words)-1] = lastWord[0:bar] + formatters = strings.Split(lastWord[bar+1:], "|") + return +} + +// Grab the next item. If it's simple, just append it to the template. +// Otherwise return its details. +func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) { + tok, w = t.analyze(item) + done = true // assume for simplicity + switch tok { + case tokComment: + return + case tokText: + t.elems = append(t.elems, &textElement{item}) + return + case tokLiteral: + switch w[0] { + case ".meta-left": + t.elems = append(t.elems, &literalElement{t.ldelim}) + case ".meta-right": + t.elems = append(t.elems, &literalElement{t.rdelim}) + case ".space": + t.elems = append(t.elems, &literalElement{space}) + case ".tab": + t.elems = append(t.elems, &literalElement{tab}) + default: + t.parseError("internal error: unknown literal: %s", w[0]) + } + return + case tokVariable: + t.elems = append(t.elems, t.newVariable(w)) + return + } + return false, tok, w +} + +// parseRepeated and parseSection are mutually recursive + +func (t *Template) parseRepeated(words []string) *repeatedElement { + r := new(repeatedElement) + t.elems = append(t.elems, r) + r.linenum = t.linenum + r.field = words[2] + // Scan section, collecting true and false (.or) blocks. + r.start = len(t.elems) + r.or = -1 + r.altstart = -1 + r.altend = -1 +Loop: + for { + item := t.nextItem() + if len(item) == 0 { + t.parseError("missing .end for .repeated section") + break + } + done, tok, w := t.parseSimple(item) + if done { + continue + } + switch tok { + case tokEnd: + break Loop + case tokOr: + if r.or >= 0 { + t.parseError("extra .or in .repeated section") + break Loop + } + r.altend = len(t.elems) + r.or = len(t.elems) + case tokSection: + t.parseSection(w) + case tokRepeated: + t.parseRepeated(w) + case tokAlternates: + if r.altstart >= 0 { + t.parseError("extra .alternates in .repeated section") + break Loop + } + if r.or >= 0 { + t.parseError(".alternates inside .or block in .repeated section") + break Loop + } + r.altstart = len(t.elems) + default: + t.parseError("internal error: unknown repeated section item: %s", item) + break Loop + } + } + if r.altend < 0 { + r.altend = len(t.elems) + } + r.end = len(t.elems) + return r +} + +func (t *Template) parseSection(words []string) *sectionElement { + s := new(sectionElement) + t.elems = append(t.elems, s) + s.linenum = t.linenum + s.field = words[1] + // Scan section, collecting true and false (.or) blocks. + s.start = len(t.elems) + s.or = -1 +Loop: + for { + item := t.nextItem() + if len(item) == 0 { + t.parseError("missing .end for .section") + break + } + done, tok, w := t.parseSimple(item) + if done { + continue + } + switch tok { + case tokEnd: + break Loop + case tokOr: + if s.or >= 0 { + t.parseError("extra .or in .section") + break Loop + } + s.or = len(t.elems) + case tokSection: + t.parseSection(w) + case tokRepeated: + t.parseRepeated(w) + case tokAlternates: + t.parseError(".alternates not in .repeated") + default: + t.parseError("internal error: unknown section item: %s", item) + } + } + s.end = len(t.elems) + return s +} + +func (t *Template) parse() { + for { + item := t.nextItem() + if len(item) == 0 { + break + } + done, tok, w := t.parseSimple(item) + if done { + continue + } + switch tok { + case tokOr, tokEnd, tokAlternates: + t.parseError("unexpected %s", w[0]) + case tokSection: + t.parseSection(w) + case tokRepeated: + t.parseRepeated(w) + default: + t.parseError("internal error: bad directive in parse: %s", item) + } + } +} + +// -- Execution + +// -- Public interface + +// Parse initializes a Template by parsing its definition. The string +// s contains the template text. If any errors occur, Parse returns +// the error. +func (t *Template) Parse(s string) (err os.Error) { + if t.elems == nil { + return &Error{1, "template not allocated with New"} + } + if !validDelim(t.ldelim) || !validDelim(t.rdelim) { + return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)} + } + defer checkError(&err) + t.buf = []byte(s) + t.p = 0 + t.linenum = 1 + t.parse() + return nil +} + +// ParseFile is like Parse but reads the template definition from the +// named file. +func (t *Template) ParseFile(filename string) (err os.Error) { + b, err := ioutil.ReadFile(filename) + if err != nil { + return err + } + return t.Parse(string(b)) +} + +// Execute applies a parsed template to the specified data object, +// generating output to wr. +func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) { + // Extract the driver data. + val := reflect.ValueOf(data) + defer checkError(&err) + t.p = 0 + t.execute(0, len(t.elems), &state{parent: nil, data: val, wr: wr}) + return nil +} + +// SetDelims sets the left and right delimiters for operations in the +// template. They are validated during parsing. They could be +// validated here but it's better to keep the routine simple. The +// delimiters are very rarely invalid and Parse has the necessary +// error-handling interface already. +func (t *Template) SetDelims(left, right string) { + t.ldelim = []byte(left) + t.rdelim = []byte(right) +} + +// Parse creates a Template with default parameters (such as {} for +// metacharacters). The string s contains the template text while +// the formatter map fmap, which may be nil, defines auxiliary functions +// for formatting variables. The template is returned. If any errors +// occur, err will be non-nil. +func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) { + t = New(fmap) + err = t.Parse(s) + if err != nil { + t = nil + } + return +} + +// ParseFile is a wrapper function that creates a Template with default +// parameters (such as {} for metacharacters). The filename identifies +// a file containing the template text, while the formatter map fmap, which +// may be nil, defines auxiliary functions for formatting variables. +// The template is returned. If any errors occur, err will be non-nil. +func ParseFile(filename string, fmap FormatterMap) (t *Template, err os.Error) { + b, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + return Parse(string(b), fmap) +} + +// MustParse is like Parse but panics if the template cannot be parsed. +func MustParse(s string, fmap FormatterMap) *Template { + t, err := Parse(s, fmap) + if err != nil { + panic("template.MustParse error: " + err.String()) + } + return t +} + +// MustParseFile is like ParseFile but panics if the file cannot be read +// or the template cannot be parsed. +func MustParseFile(filename string, fmap FormatterMap) *Template { + b, err := ioutil.ReadFile(filename) + if err != nil { + panic("template.MustParseFile error: " + err.String()) + } + return MustParse(string(b), fmap) +} diff --git a/src/pkg/template/template_test.go b/src/pkg/old/template/template_test.go index eae8011eb..eae8011eb 100644 --- a/src/pkg/template/template_test.go +++ b/src/pkg/old/template/template_test.go diff --git a/src/pkg/os/user/Makefile b/src/pkg/os/user/Makefile index 731f7999a..aabb54995 100644 --- a/src/pkg/os/user/Makefile +++ b/src/pkg/os/user/Makefile @@ -8,7 +8,7 @@ TARG=os/user GOFILES=\ user.go\ -ifneq ($(GOARCH),arm) +ifeq ($(CGO_ENABLED),1) CGOFILES_linux=\ lookup_unix.go CGOFILES_freebsd=\ diff --git a/src/pkg/os/user/lookup_unix.go b/src/pkg/os/user/lookup_unix.go index 678de802b..1b2c9e8c9 100644 --- a/src/pkg/os/user/lookup_unix.go +++ b/src/pkg/os/user/lookup_unix.go @@ -25,6 +25,10 @@ static int mygetpwuid_r(int uid, struct passwd *pwd, */ import "C" +func init() { + implemented = true +} + // Lookup looks up a user by username. If the user cannot be found, // the returned error is of type UnknownUserError. func Lookup(username string) (*User, os.Error) { diff --git a/src/pkg/os/user/user.go b/src/pkg/os/user/user.go index dd009211d..f71e11d8b 100644 --- a/src/pkg/os/user/user.go +++ b/src/pkg/os/user/user.go @@ -9,6 +9,8 @@ import ( "strconv" ) +var implemented = false // set to true by lookup_unix.go's init + // User represents a user account. type User struct { Uid int // user id diff --git a/src/pkg/os/user/user_test.go b/src/pkg/os/user/user_test.go index ee917b57a..59f15e4c6 100644 --- a/src/pkg/os/user/user_test.go +++ b/src/pkg/os/user/user_test.go @@ -13,8 +13,8 @@ import ( ) func skip(t *testing.T) bool { - if runtime.GOARCH == "arm" { - t.Logf("user: cgo not implemented on arm; skipping tests") + if !implemented { + t.Logf("user: not implemented; skipping tests") return true } diff --git a/src/pkg/path/filepath/Makefile b/src/pkg/path/filepath/Makefile index bc26a7d6a..af250ab33 100644 --- a/src/pkg/path/filepath/Makefile +++ b/src/pkg/path/filepath/Makefile @@ -18,6 +18,9 @@ GOFILES_darwin=\ GOFILES_linux=\ path_unix.go +GOFILES_openbsd=\ + path_unix.go + GOFILES_plan9=\ path_plan9.go diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go index 82985c575..d3c510ac2 100644 --- a/src/pkg/reflect/value.go +++ b/src/pkg/reflect/value.go @@ -860,6 +860,9 @@ func (v Value) Interface() interface{} { } func (iv internalValue) Interface() interface{} { + if iv.kind == 0 { + panic(&ValueError{"reflect.Value.Interface", iv.kind}) + } if iv.method { panic("reflect.Value.Interface: cannot create interface value for method with bound receiver") } @@ -974,7 +977,7 @@ func (v Value) MapIndex(key Value) Value { flag := (iv.flag | ikey.flag) & flagRO elemType := typ.Elem() - elemWord, ok := mapaccess(iv.word, ikey.word) + elemWord, ok := mapaccess(typ.runtimeType(), iv.word, ikey.word) if !ok { return Value{} } @@ -996,7 +999,7 @@ func (v Value) MapKeys() []Value { if m != 0 { mlen = maplen(m) } - it := mapiterinit(m) + it := mapiterinit(iv.typ.runtimeType(), m) a := make([]Value, mlen) var i int for i = 0; i < len(a); i++ { @@ -1159,7 +1162,7 @@ func (iv internalValue) recv(nb bool) (val Value, ok bool) { if ch == 0 { panic("recv on nil channel") } - valWord, selected, ok := chanrecv(ch, nb) + valWord, selected, ok := chanrecv(iv.typ.runtimeType(), ch, nb) if selected { val = valueFromIword(0, t.Elem(), valWord) } @@ -1189,7 +1192,7 @@ func (iv internalValue) send(x Value, nb bool) (selected bool) { if ch == 0 { panic("send on nil channel") } - return chansend(ch, ix.word, nb) + return chansend(iv.typ.runtimeType(), ch, ix.word, nb) } // Set assigns x to the value v. @@ -1306,7 +1309,7 @@ func (v Value) SetMapIndex(key, val Value) { ival = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Elem(), ival) } - mapassign(iv.word, ikey.word, ival.word, ival.kind != Invalid) + mapassign(iv.typ.runtimeType(), iv.word, ikey.word, ival.word, ival.kind != Invalid) } // SetUint sets v's underlying value to x. @@ -1717,14 +1720,14 @@ func convertForAssignment(what string, addr unsafe.Pointer, dst Type, iv interna func chancap(ch iword) int32 func chanclose(ch iword) func chanlen(ch iword) int32 -func chanrecv(ch iword, nb bool) (val iword, selected, received bool) -func chansend(ch iword, val iword, nb bool) bool +func chanrecv(t *runtime.Type, ch iword, nb bool) (val iword, selected, received bool) +func chansend(t *runtime.Type, ch iword, val iword, nb bool) bool func makechan(typ *runtime.Type, size uint32) (ch iword) func makemap(t *runtime.Type) iword -func mapaccess(m iword, key iword) (val iword, ok bool) -func mapassign(m iword, key, val iword, ok bool) -func mapiterinit(m iword) *byte +func mapaccess(t *runtime.Type, m iword, key iword) (val iword, ok bool) +func mapassign(t *runtime.Type, m iword, key, val iword, ok bool) +func mapiterinit(t *runtime.Type, m iword) *byte func mapiterkey(it *byte) (key iword, ok bool) func mapiternext(it *byte) func maplen(m iword) int32 diff --git a/src/pkg/rpc/debug.go b/src/pkg/rpc/debug.go index ae76a4586..7e3e6f6e5 100644 --- a/src/pkg/rpc/debug.go +++ b/src/pkg/rpc/debug.go @@ -10,10 +10,10 @@ package rpc */ import ( - "exp/template" "fmt" "http" "sort" + "template" ) const debugText = `<html> @@ -70,7 +70,7 @@ func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) { // Build a sorted version of the data. var services = make(serviceArray, len(server.serviceMap)) i := 0 - server.Lock() + server.mu.Lock() for sname, service := range server.serviceMap { services[i] = debugService{service, sname, make(methodArray, len(service.method))} j := 0 @@ -81,7 +81,7 @@ func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) { sort.Sort(services[i].Method) i++ } - server.Unlock() + server.mu.Unlock() sort.Sort(services) err := debug.Execute(w, services) if err != nil { diff --git a/src/pkg/rpc/server.go b/src/pkg/rpc/server.go index 86767abea..745074428 100644 --- a/src/pkg/rpc/server.go +++ b/src/pkg/rpc/server.go @@ -174,7 +174,7 @@ type Response struct { // Server represents an RPC Server. type Server struct { - sync.Mutex // protects the serviceMap + mu sync.Mutex // protects the serviceMap serviceMap map[string]*service reqLock sync.Mutex // protects freeReq freeReq *Request @@ -226,8 +226,8 @@ func (server *Server) RegisterName(name string, rcvr interface{}) os.Error { } func (server *Server) register(rcvr interface{}, name string, useName bool) os.Error { - server.Lock() - defer server.Unlock() + server.mu.Lock() + defer server.mu.Unlock() if server.serviceMap == nil { server.serviceMap = make(map[string]*service) } @@ -394,7 +394,7 @@ func (server *Server) ServeConn(conn io.ReadWriteCloser) { func (server *Server) ServeCodec(codec ServerCodec) { sending := new(sync.Mutex) for { - req, service, mtype, err := server.readRequest(codec) + service, mtype, req, argv, replyv, err := server.readRequest(codec) if err != nil { if err != os.EOF { log.Println("rpc:", err) @@ -402,9 +402,6 @@ func (server *Server) ServeCodec(codec ServerCodec) { if err == os.EOF || err == io.ErrUnexpectedEOF { break } - // discard body - codec.ReadRequestBody(nil) - // send a response if we actually managed to read a header. if req != nil { server.sendResponse(sending, req, invalidRequest, codec, err.String()) @@ -412,35 +409,29 @@ func (server *Server) ServeCodec(codec ServerCodec) { } continue } + go service.call(server, sending, mtype, req, argv, replyv, codec) + } + codec.Close() +} - // Decode the argument value. - var argv reflect.Value - argIsValue := false // if true, need to indirect before calling. - if mtype.ArgType.Kind() == reflect.Ptr { - argv = reflect.New(mtype.ArgType.Elem()) - } else { - argv = reflect.New(mtype.ArgType) - argIsValue = true - } - // argv guaranteed to be a pointer now. - replyv := reflect.New(mtype.ReplyType.Elem()) - err = codec.ReadRequestBody(argv.Interface()) - if err != nil { - if err == os.EOF || err == io.ErrUnexpectedEOF { - if err == io.ErrUnexpectedEOF { - log.Println("rpc:", err) - } - break - } - server.sendResponse(sending, req, replyv.Interface(), codec, err.String()) - continue +// ServeRequest is like ServeCodec but synchronously serves a single request. +// It does not close the codec upon completion. +func (server *Server) ServeRequest(codec ServerCodec) os.Error { + sending := new(sync.Mutex) + service, mtype, req, argv, replyv, err := server.readRequest(codec) + if err != nil { + if err == os.EOF || err == io.ErrUnexpectedEOF { + return err } - if argIsValue { - argv = argv.Elem() + // send a response if we actually managed to read a header. + if req != nil { + server.sendResponse(sending, req, invalidRequest, codec, err.String()) + server.freeRequest(req) } - go service.call(server, sending, mtype, req, argv, replyv, codec) + return err } - codec.Close() + service.call(server, sending, mtype, req, argv, replyv, codec) + return nil } func (server *Server) getRequest() *Request { @@ -483,7 +474,38 @@ func (server *Server) freeResponse(resp *Response) { server.respLock.Unlock() } -func (server *Server) readRequest(codec ServerCodec) (req *Request, service *service, mtype *methodType, err os.Error) { +func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, err os.Error) { + service, mtype, req, err = server.readRequestHeader(codec) + if err != nil { + if err == os.EOF || err == io.ErrUnexpectedEOF { + return + } + // discard body + codec.ReadRequestBody(nil) + return + } + + // Decode the argument value. + argIsValue := false // if true, need to indirect before calling. + if mtype.ArgType.Kind() == reflect.Ptr { + argv = reflect.New(mtype.ArgType.Elem()) + } else { + argv = reflect.New(mtype.ArgType) + argIsValue = true + } + // argv guaranteed to be a pointer now. + if err = codec.ReadRequestBody(argv.Interface()); err != nil { + return + } + if argIsValue { + argv = argv.Elem() + } + + replyv = reflect.New(mtype.ReplyType.Elem()) + return +} + +func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, err os.Error) { // Grab the request header. req = server.getRequest() err = codec.ReadRequestHeader(req) @@ -502,9 +524,9 @@ func (server *Server) readRequest(codec ServerCodec) (req *Request, service *ser return } // Look up the request. - server.Lock() + server.mu.Lock() service = server.serviceMap[serviceMethod[0]] - server.Unlock() + server.mu.Unlock() if service == nil { err = os.NewError("rpc: can't find service " + req.ServiceMethod) return @@ -568,6 +590,12 @@ func ServeCodec(codec ServerCodec) { DefaultServer.ServeCodec(codec) } +// ServeRequest is like ServeCodec but synchronously serves a single request. +// It does not close the codec upon completion. +func ServeRequest(codec ServerCodec) os.Error { + return DefaultServer.ServeRequest(codec) +} + // Accept accepts connections on the listener and serves requests // to DefaultServer for each incoming connection. // Accept blocks; the caller typically invokes it in a go statement. diff --git a/src/pkg/rpc/server_test.go b/src/pkg/rpc/server_test.go index 459dd59d6..e7bbfbe97 100644 --- a/src/pkg/rpc/server_test.go +++ b/src/pkg/rpc/server_test.go @@ -7,6 +7,7 @@ package rpc import ( "fmt" "http/httptest" + "io" "log" "net" "os" @@ -18,6 +19,7 @@ import ( ) var ( + newServer *Server serverAddr, newServerAddr string httpServerAddr string once, newOnce, httpOnce sync.Once @@ -93,15 +95,15 @@ func startServer() { } func startNewServer() { - s := NewServer() - s.Register(new(Arith)) + newServer = NewServer() + newServer.Register(new(Arith)) var l net.Listener l, newServerAddr = listenTCP() log.Println("NewServer test RPC server listening on", newServerAddr) go Accept(l) - s.HandleHTTP(newHttpPath, "/bar") + newServer.HandleHTTP(newHttpPath, "/bar") httpOnce.Do(startHttpServer) } @@ -264,6 +266,85 @@ func testHTTPRPC(t *testing.T, path string) { } } +// CodecEmulator provides a client-like api and a ServerCodec interface. +// Can be used to test ServeRequest. +type CodecEmulator struct { + server *Server + serviceMethod string + args *Args + reply *Reply + err os.Error +} + +func (codec *CodecEmulator) Call(serviceMethod string, args *Args, reply *Reply) os.Error { + codec.serviceMethod = serviceMethod + codec.args = args + codec.reply = reply + codec.err = nil + var serverError os.Error + if codec.server == nil { + serverError = ServeRequest(codec) + } else { + serverError = codec.server.ServeRequest(codec) + } + if codec.err == nil && serverError != nil { + codec.err = serverError + } + return codec.err +} + +func (codec *CodecEmulator) ReadRequestHeader(req *Request) os.Error { + req.ServiceMethod = codec.serviceMethod + req.Seq = 0 + return nil +} + +func (codec *CodecEmulator) ReadRequestBody(argv interface{}) os.Error { + if codec.args == nil { + return io.ErrUnexpectedEOF + } + *(argv.(*Args)) = *codec.args + return nil +} + +func (codec *CodecEmulator) WriteResponse(resp *Response, reply interface{}) os.Error { + if resp.Error != "" { + codec.err = os.NewError(resp.Error) + } + *codec.reply = *(reply.(*Reply)) + return nil +} + +func (codec *CodecEmulator) Close() os.Error { + return nil +} + +func TestServeRequest(t *testing.T) { + once.Do(startServer) + testServeRequest(t, nil) + newOnce.Do(startNewServer) + testServeRequest(t, newServer) +} + +func testServeRequest(t *testing.T, server *Server) { + client := CodecEmulator{server: server} + + args := &Args{7, 8} + reply := new(Reply) + err := client.Call("Arith.Add", args, reply) + if err != nil { + t.Errorf("Add: expected no error but got string %q", err.String()) + } + if reply.C != args.A+args.B { + t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B) + } + + err = client.Call("Arith.Add", nil, reply) + if err == nil { + t.Errorf("expected error calling Arith.Add with nil arg") + } +} + type ReplyNotPointer int type ArgNotPublic int type ReplyNotPublic int diff --git a/src/pkg/runtime/cgo/Makefile b/src/pkg/runtime/cgo/Makefile index e7a2fa7c6..766794797 100644 --- a/src/pkg/runtime/cgo/Makefile +++ b/src/pkg/runtime/cgo/Makefile @@ -4,29 +4,12 @@ include ../../../Make.inc -ENABLED:=1 - -ifeq ($(GOARCH),arm) -ENABLED:=0 -endif - -ifeq ($(GOOS),plan9) -ENABLED:=0 -endif -ifeq ($(GOOS),openbsd) -ENABLED:=0 -endif - -ifeq ($(DISABLE_CGO),1) -ENABLED:=0 -endif - TARG=runtime/cgo GOFILES=\ cgo.go\ -ifeq ($(ENABLED),1) +ifeq ($(CGO_ENABLED),1) # Unwarranted chumminess with Make.pkg's cgo rules. # Do not try this at home. @@ -59,7 +42,7 @@ endif include ../../../Make.pkg -ifeq ($(ENABLED),1) +ifeq ($(CGO_ENABLED),1) _cgo_defun.c: echo >$@ diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c index 65feacb78..ef5342353 100644 --- a/src/pkg/runtime/chan.c +++ b/src/pkg/runtime/chan.c @@ -81,10 +81,13 @@ static void enqueue(WaitQ*, SudoG*); static void destroychan(Hchan*); Hchan* -runtime·makechan_c(Type *elem, int64 hint) +runtime·makechan_c(ChanType *t, int64 hint) { Hchan *c; int32 n; + Type *elem; + + elem = t->elem; if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size)) runtime·panicstring("makechan: size out of range"); @@ -121,7 +124,7 @@ runtime·makechan_c(Type *elem, int64 hint) void reflect·makechan(ChanType *t, uint32 size, Hchan *c) { - c = runtime·makechan_c(t->elem, size); + c = runtime·makechan_c(t, size); FLUSH(&c); } @@ -132,11 +135,11 @@ destroychan(Hchan *c) } -// makechan(elem *Type, hint int64) (hchan *chan any); +// makechan(t *ChanType, hint int64) (hchan *chan any); void -runtime·makechan(Type *elem, int64 hint, Hchan *ret) +runtime·makechan(ChanType *t, int64 hint, Hchan *ret) { - ret = runtime·makechan_c(elem, hint); + ret = runtime·makechan_c(t, hint); FLUSH(&ret); } @@ -155,14 +158,22 @@ runtime·makechan(Type *elem, int64 hint, Hchan *ret) * the operation; we'll see that it's now closed. */ void -runtime·chansend(Hchan *c, byte *ep, bool *pres) +runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres) { SudoG *sg; SudoG mysg; G* gp; - if(c == nil) - runtime·panicstring("send to nil channel"); + if(c == nil) { + USED(t); + if(pres != nil) { + *pres = false; + return; + } + g->status = Gwaiting; + runtime·gosched(); + return; // not reached + } if(runtime·gcwaiting) runtime·gosched(); @@ -263,21 +274,29 @@ closed: void -runtime·chanrecv(Hchan* c, byte *ep, bool *selected, bool *received) +runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received) { SudoG *sg; SudoG mysg; G *gp; - if(c == nil) - runtime·panicstring("receive from nil channel"); - if(runtime·gcwaiting) runtime·gosched(); if(debug) runtime·printf("chanrecv: chan=%p\n", c); + if(c == nil) { + USED(t); + if(selected != nil) { + *selected = false; + return; + } + g->status = Gwaiting; + runtime·gosched(); + return; // not reached + } + runtime·lock(c); if(c->dataqsiz > 0) goto asynch; @@ -385,50 +404,29 @@ closed: // chansend1(hchan *chan any, elem any); #pragma textflag 7 void -runtime·chansend1(Hchan* c, ...) +runtime·chansend1(ChanType *t, Hchan* c, ...) { - int32 o; - byte *ae; - - if(c == nil) - runtime·panicstring("send to nil channel"); - - o = runtime·rnd(sizeof(c), c->elemalign); - ae = (byte*)&c + o; - runtime·chansend(c, ae, nil); + runtime·chansend(t, c, (byte*)(&c+1), nil); } // chanrecv1(hchan *chan any) (elem any); #pragma textflag 7 void -runtime·chanrecv1(Hchan* c, ...) +runtime·chanrecv1(ChanType *t, Hchan* c, ...) { - int32 o; - byte *ae; - - o = runtime·rnd(sizeof(c), Structrnd); - ae = (byte*)&c + o; - - runtime·chanrecv(c, ae, nil, nil); + runtime·chanrecv(t, c, (byte*)(&c+1), nil, nil); } // chanrecv2(hchan *chan any) (elem any, received bool); #pragma textflag 7 void -runtime·chanrecv2(Hchan* c, ...) +runtime·chanrecv2(ChanType *t, Hchan* c, ...) { - int32 o; - byte *ae, *ac; - - if(c == nil) - runtime·panicstring("receive from nil channel"); - - o = runtime·rnd(sizeof(c), Structrnd); - ae = (byte*)&c + o; - o += c->elemsize; - ac = (byte*)&c + o; + byte *ae, *ap; - runtime·chanrecv(c, ae, nil, ac); + ae = (byte*)(&c+1); + ap = ae + t->elem->size; + runtime·chanrecv(t, c, ae, nil, ap); } // func selectnbsend(c chan any, elem any) bool @@ -444,7 +442,7 @@ runtime·chanrecv2(Hchan* c, ...) // // as // -// if c != nil && selectnbsend(c, v) { +// if selectnbsend(c, v) { // ... foo // } else { // ... bar @@ -452,17 +450,13 @@ runtime·chanrecv2(Hchan* c, ...) // #pragma textflag 7 void -runtime·selectnbsend(Hchan *c, ...) +runtime·selectnbsend(ChanType *t, Hchan *c, ...) { - int32 o; byte *ae, *ap; - o = runtime·rnd(sizeof(c), c->elemalign); - ae = (byte*)&c + o; - o = runtime·rnd(o+c->elemsize, Structrnd); - ap = (byte*)&c + o; - - runtime·chansend(c, ae, ap); + ae = (byte*)(&c + 1); + ap = ae + runtime·rnd(t->elem->size, Structrnd); + runtime·chansend(t, c, ae, ap); } // func selectnbrecv(elem *any, c chan any) bool @@ -478,7 +472,7 @@ runtime·selectnbsend(Hchan *c, ...) // // as // -// if c != nil && selectnbrecv(&v, c) { +// if selectnbrecv(&v, c) { // ... foo // } else { // ... bar @@ -486,9 +480,9 @@ runtime·selectnbsend(Hchan *c, ...) // #pragma textflag 7 void -runtime·selectnbrecv(byte *v, Hchan *c, bool selected) +runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected) { - runtime·chanrecv(c, v, &selected, nil); + runtime·chanrecv(t, c, v, &selected, nil); } // func selectnbrecv2(elem *any, ok *bool, c chan any) bool @@ -512,9 +506,9 @@ runtime·selectnbrecv(byte *v, Hchan *c, bool selected) // #pragma textflag 7 void -runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected) +runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected) { - runtime·chanrecv(c, v, &selected, received); + runtime·chanrecv(t, c, v, &selected, received); } // For reflect: @@ -525,14 +519,11 @@ runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected) // The "uintptr selected" is really "bool selected" but saying // uintptr gets us the right alignment for the output parameter block. void -reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected) +reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected) { bool *sp; byte *vp; - if(c == nil) - runtime·panicstring("send to nil channel"); - if(nb) { selected = false; sp = (bool*)&selected; @@ -541,11 +532,11 @@ reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected) FLUSH(&selected); sp = nil; } - if(c->elemsize <= sizeof(val)) + if(t->elem->size <= sizeof(val)) vp = (byte*)&val; else vp = (byte*)val; - runtime·chansend(c, vp, sp); + runtime·chansend(t, c, vp, sp); } // For reflect: @@ -553,13 +544,10 @@ reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected) // where an iword is the same word an interface value would use: // the actual data if it fits, or else a pointer to the data. void -reflect·chanrecv(Hchan *c, bool nb, uintptr val, bool selected, bool received) +reflect·chanrecv(ChanType *t, Hchan *c, bool nb, uintptr val, bool selected, bool received) { byte *vp; bool *sp; - - if(c == nil) - runtime·panicstring("receive from nil channel"); if(nb) { selected = false; @@ -571,15 +559,15 @@ reflect·chanrecv(Hchan *c, bool nb, uintptr val, bool selected, bool received) } received = false; FLUSH(&received); - if(c->elemsize <= sizeof(val)) { + if(t->elem->size <= sizeof(val)) { val = 0; vp = (byte*)&val; } else { - vp = runtime·mal(c->elemsize); + vp = runtime·mal(t->elem->size); val = (uintptr)vp; FLUSH(&val); } - runtime·chanrecv(c, vp, sp, &received); + runtime·chanrecv(t, c, vp, sp, &received); } static void newselect(int32, Select**); @@ -904,7 +892,8 @@ loop: // pass 2 - enqueue on all chans for(i=0; i<sel->ncase; i++) { - cas = &sel->scase[i]; + o = sel->pollorder[i]; + cas = &sel->scase[o]; c = cas->chan; sg = &cas->sg; sg->g = g; diff --git a/src/pkg/runtime/chan_test.go b/src/pkg/runtime/chan_test.go index 71c9e2fd7..46ddfd7e8 100644 --- a/src/pkg/runtime/chan_test.go +++ b/src/pkg/runtime/chan_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "runtime" + "sync" "sync/atomic" "testing" ) @@ -26,6 +27,38 @@ func TestChanSendInterface(t *testing.T) { } } +func TestPseudoRandomSend(t *testing.T) { + n := 100 + c := make(chan int) + l := make([]int, n) + var m sync.Mutex + m.Lock() + go func() { + for i := 0; i < n; i++ { + runtime.Gosched() + l[i] = <-c + } + m.Unlock() + }() + for i := 0; i < n; i++ { + select { + case c <- 0: + case c <- 1: + } + } + m.Lock() // wait + n0 := 0 + n1 := 0 + for _, i := range l { + n0 += (i + 1) % 2 + n1 += i + if n0 > n/10 && n1 > n/10 { + return + } + } + t.Errorf("Want pseudo random, got %d zeros and %d ones", n0, n1) +} + func BenchmarkSelectUncontended(b *testing.B) { const CallsPerSched = 1000 procs := runtime.GOMAXPROCS(-1) diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c index 179a56375..0c0e3e4a2 100644 --- a/src/pkg/runtime/hashmap.c +++ b/src/pkg/runtime/hashmap.c @@ -690,13 +690,17 @@ hash_indirect(Hmap *h, void *p) static int32 debug = 0; -// makemap(key, val *Type, hint uint32) (hmap *map[any]any); +// makemap(typ *Type, hint uint32) (hmap *map[any]any); Hmap* -runtime·makemap_c(Type *key, Type *val, int64 hint) +runtime·makemap_c(MapType *typ, int64 hint) { Hmap *h; int32 keyalg, valalg, keysize, valsize, valsize_in_hash; void (*data_del)(uint32, void*, void*); + Type *key, *val; + + key = typ->key; + val = typ->elem; if(hint < 0 || (int32)hint != hint) runtime·panicstring("makemap: size out of range"); @@ -770,9 +774,9 @@ runtime·makemap_c(Type *key, Type *val, int64 hint) // makemap(key, val *Type, hint int64) (hmap *map[any]any); void -runtime·makemap(Type *key, Type *val, int64 hint, Hmap *ret) +runtime·makemap(MapType *typ, int64 hint, Hmap *ret) { - ret = runtime·makemap_c(key, val, hint); + ret = runtime·makemap_c(typ, hint); FLUSH(&ret); } @@ -781,17 +785,22 @@ runtime·makemap(Type *key, Type *val, int64 hint, Hmap *ret) void reflect·makemap(MapType *t, Hmap *ret) { - ret = runtime·makemap_c(t->key, t->elem, 0); + ret = runtime·makemap_c(t, 0); FLUSH(&ret); } void -runtime·mapaccess(Hmap *h, byte *ak, byte *av, bool *pres) +runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres) { byte *res; + Type *elem; - if(h == nil) - runtime·panicstring("lookup in nil map"); + if(h == nil) { + elem = t->elem; + runtime·algarray[elem->alg].copy(elem->size, av, nil); + *pres = false; + return; + } if(runtime·gcwaiting) runtime·gosched(); @@ -809,18 +818,20 @@ runtime·mapaccess(Hmap *h, byte *ak, byte *av, bool *pres) // mapaccess1(hmap *map[any]any, key any) (val any); #pragma textflag 7 void -runtime·mapaccess1(Hmap *h, ...) +runtime·mapaccess1(MapType *t, Hmap *h, ...) { byte *ak, *av; bool pres; - if(h == nil) - runtime·panicstring("lookup in nil map"); - - ak = (byte*)&h + h->ko1; - av = (byte*)&h + h->vo1; + if(h == nil) { + ak = (byte*)(&h + 1); + av = ak + runtime·rnd(t->key->size, Structrnd); + } else { + ak = (byte*)&h + h->ko1; + av = (byte*)&h + h->vo1; + } - runtime·mapaccess(h, ak, av, &pres); + runtime·mapaccess(t, h, ak, av, &pres); if(debug) { runtime·prints("runtime.mapaccess1: map="); @@ -838,18 +849,21 @@ runtime·mapaccess1(Hmap *h, ...) // mapaccess2(hmap *map[any]any, key any) (val any, pres bool); #pragma textflag 7 void -runtime·mapaccess2(Hmap *h, ...) +runtime·mapaccess2(MapType *t, Hmap *h, ...) { byte *ak, *av, *ap; - if(h == nil) - runtime·panicstring("lookup in nil map"); - - ak = (byte*)&h + h->ko1; - av = (byte*)&h + h->vo1; - ap = (byte*)&h + h->po1; + if(h == nil) { + ak = (byte*)(&h + 1); + av = ak + runtime·rnd(t->key->size, Structrnd); + ap = av + t->elem->size; + } else { + ak = (byte*)&h + h->ko1; + av = (byte*)&h + h->vo1; + ap = (byte*)&h + h->po1; + } - runtime·mapaccess(h, ak, av, ap); + runtime·mapaccess(t, h, ak, av, ap); if(debug) { runtime·prints("runtime.mapaccess2: map="); @@ -865,39 +879,39 @@ runtime·mapaccess2(Hmap *h, ...) } // For reflect: -// func mapaccess(h map, key iword) (val iword, pres bool) +// func mapaccess(t type, h map, key iword) (val iword, pres bool) // where an iword is the same word an interface value would use: // the actual data if it fits, or else a pointer to the data. void -reflect·mapaccess(Hmap *h, uintptr key, uintptr val, bool pres) +reflect·mapaccess(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres) { byte *ak, *av; - if(h == nil) - runtime·panicstring("lookup in nil map"); - if(h->keysize <= sizeof(key)) + if(t->key->size <= sizeof(key)) ak = (byte*)&key; else ak = (byte*)key; val = 0; pres = false; - if(h->valsize <= sizeof(val)) + if(t->elem->size <= sizeof(val)) av = (byte*)&val; else { - av = runtime·mal(h->valsize); + av = runtime·mal(t->elem->size); val = (uintptr)av; } - runtime·mapaccess(h, ak, av, &pres); + runtime·mapaccess(t, h, ak, av, &pres); FLUSH(&val); FLUSH(&pres); } void -runtime·mapassign(Hmap *h, byte *ak, byte *av) +runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av) { byte *res; int32 hit; + USED(t); + if(h == nil) runtime·panicstring("assignment to entry in nil map"); @@ -931,10 +945,10 @@ runtime·mapassign(Hmap *h, byte *ak, byte *av) } } -// mapassign1(hmap *map[any]any, key any, val any); +// mapassign1(mapType *type, hmap *map[any]any, key any, val any); #pragma textflag 7 void -runtime·mapassign1(Hmap *h, ...) +runtime·mapassign1(MapType *t, Hmap *h, ...) { byte *ak, *av; @@ -944,13 +958,13 @@ runtime·mapassign1(Hmap *h, ...) ak = (byte*)&h + h->ko2; av = (byte*)&h + h->vo2; - runtime·mapassign(h, ak, av); + runtime·mapassign(t, h, ak, av); } -// mapassign2(hmap *map[any]any, key any, val any, pres bool); +// mapassign2(mapType *type, hmap *map[any]any, key any, val any, pres bool); #pragma textflag 7 void -runtime·mapassign2(Hmap *h, ...) +runtime·mapassign2(MapType *t, Hmap *h, ...) { byte *ak, *av, *ap; @@ -964,7 +978,7 @@ runtime·mapassign2(Hmap *h, ...) if(*ap == false) av = nil; // delete - runtime·mapassign(h, ak, av); + runtime·mapassign(t, h, ak, av); if(debug) { runtime·prints("mapassign2: map="); @@ -976,16 +990,16 @@ runtime·mapassign2(Hmap *h, ...) } // For reflect: -// func mapassign(h map, key, val iword, pres bool) +// func mapassign(t type h map, key, val iword, pres bool) // where an iword is the same word an interface value would use: // the actual data if it fits, or else a pointer to the data. void -reflect·mapassign(Hmap *h, uintptr key, uintptr val, bool pres) +reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres) { byte *ak, *av; if(h == nil) - runtime·panicstring("lookup in nil map"); + runtime·panicstring("assignment to entry in nil map"); if(h->keysize <= sizeof(key)) ak = (byte*)&key; else @@ -996,12 +1010,12 @@ reflect·mapassign(Hmap *h, uintptr key, uintptr val, bool pres) av = (byte*)val; if(!pres) av = nil; - runtime·mapassign(h, ak, av); + runtime·mapassign(t, h, ak, av); } -// mapiterinit(hmap *map[any]any, hiter *any); +// mapiterinit(mapType *type, hmap *map[any]any, hiter *any); void -runtime·mapiterinit(Hmap *h, struct hash_iter *it) +runtime·mapiterinit(MapType*, Hmap *h, struct hash_iter *it) { if(h == nil) { it->data = nil; @@ -1023,11 +1037,11 @@ runtime·mapiterinit(Hmap *h, struct hash_iter *it) // For reflect: // func mapiterinit(h map) (it iter) void -reflect·mapiterinit(Hmap *h, struct hash_iter *it) +reflect·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it) { it = runtime·mal(sizeof *it); FLUSH(&it); - runtime·mapiterinit(h, it); + runtime·mapiterinit(t, h, it); } // mapiternext(hiter *any); diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 6325aadc6..78ea2aa2b 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -737,11 +737,11 @@ runtime·markallocated(void *v, uintptr n, bool noptr) bits = (obits & ~(bitMask<<shift)) | (bitAllocated<<shift); if(noptr) bits |= bitNoPointers<<shift; - if(runtime·gomaxprocs == 1) { + if(runtime·singleproc) { *b = bits; break; } else { - // gomaxprocs > 1: use atomic op + // more than one goroutine is potentially running: use atomic op if(runtime·casp((void**)b, (void*)obits, (void*)bits)) break; } @@ -767,11 +767,11 @@ runtime·markfreed(void *v, uintptr n) for(;;) { obits = *b; bits = (obits & ~(bitMask<<shift)) | (bitBlockBoundary<<shift); - if(runtime·gomaxprocs == 1) { + if(runtime·singleproc) { *b = bits; break; } else { - // gomaxprocs > 1: use atomic op + // more than one goroutine is potentially running: use atomic op if(runtime·casp((void**)b, (void*)obits, (void*)bits)) break; } @@ -878,11 +878,11 @@ runtime·setblockspecial(void *v) for(;;) { obits = *b; bits = obits | (bitSpecial<<shift); - if(runtime·gomaxprocs == 1) { + if(runtime·singleproc) { *b = bits; break; } else { - // gomaxprocs > 1: use atomic op + // more than one goroutine is potentially running: use atomic op if(runtime·casp((void**)b, (void*)obits, (void*)bits)) break; } diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index 7a8159100..5f396b49f 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -126,6 +126,7 @@ enum { Sched runtime·sched; int32 runtime·gomaxprocs; +bool runtime·singleproc; // An m that is waiting for notewakeup(&m->havenextg). This may be // only be accessed while the scheduler lock is held. This is used to @@ -199,6 +200,7 @@ runtime·schedinit(void) runtime·gomaxprocs = n; } setmcpumax(runtime·gomaxprocs); + runtime·singleproc = runtime·gomaxprocs == 1; runtime·sched.predawn = 1; m->nomemprof--; @@ -585,6 +587,7 @@ runtime·stoptheworld(void) runtime·notesleep(&runtime·sched.stopped); schedlock(); } + runtime·singleproc = runtime·gomaxprocs == 1; schedunlock(); } @@ -1416,6 +1419,8 @@ runtime·gomaxprocsfunc(int32 n) if(n > maxgomaxprocs) n = maxgomaxprocs; runtime·gomaxprocs = n; + if(runtime·gomaxprocs > 1) + runtime·singleproc = false; if(runtime·gcwaiting != 0) { if(atomic_mcpumax(runtime·sched.atomic) != 1) runtime·throw("invalid mcpumax during gc"); diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index 8c5403f44..526a320ea 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -62,6 +62,8 @@ typedef struct Iface Iface; typedef struct Itab Itab; typedef struct Eface Eface; typedef struct Type Type; +typedef struct ChanType ChanType; +typedef struct MapType MapType; typedef struct Defer Defer; typedef struct Panic Panic; typedef struct Hmap Hmap; @@ -248,12 +250,9 @@ struct M uint32 freghi[16]; // D[i] msb and F[i+16] uint32 fflag; // floating point compare flags #ifdef __WINDOWS__ - void* sehframe; - #ifdef _64BIT void* gostack; #endif - #endif }; @@ -386,6 +385,7 @@ extern String runtime·emptystring; G* runtime·allg; M* runtime·allm; extern int32 runtime·gomaxprocs; +extern bool runtime·singleproc; extern uint32 runtime·panicking; extern int32 runtime·gcwaiting; // gc is waiting to run int8* runtime·goos; @@ -618,16 +618,16 @@ int32 runtime·gomaxprocsfunc(int32 n); void runtime·procyield(uint32); void runtime·osyield(void); -void runtime·mapassign(Hmap*, byte*, byte*); -void runtime·mapaccess(Hmap*, byte*, byte*, bool*); +void runtime·mapassign(MapType*, Hmap*, byte*, byte*); +void runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*); void runtime·mapiternext(struct hash_iter*); bool runtime·mapiterkey(struct hash_iter*, void*); void runtime·mapiterkeyvalue(struct hash_iter*, void*, void*); -Hmap* runtime·makemap_c(Type*, Type*, int64); +Hmap* runtime·makemap_c(MapType*, int64); -Hchan* runtime·makechan_c(Type*, int64); -void runtime·chansend(Hchan*, void*, bool*); -void runtime·chanrecv(Hchan*, void*, bool*, bool*); +Hchan* runtime·makechan_c(ChanType*, int64); +void runtime·chansend(ChanType*, Hchan*, void*, bool*); +void runtime·chanrecv(ChanType*, Hchan*, void*, bool*, bool*); int32 runtime·chanlen(Hchan*); int32 runtime·chancap(Hchan*); diff --git a/src/pkg/runtime/type.h b/src/pkg/runtime/type.h index 1adb6dc2e..8c80c62d3 100644 --- a/src/pkg/runtime/type.h +++ b/src/pkg/runtime/type.h @@ -16,8 +16,6 @@ typedef struct UncommonType UncommonType; typedef struct InterfaceType InterfaceType; typedef struct Method Method; typedef struct IMethod IMethod; -typedef struct MapType MapType; -typedef struct ChanType ChanType; typedef struct SliceType SliceType; typedef struct FuncType FuncType; diff --git a/src/pkg/runtime/windows/386/sys.s b/src/pkg/runtime/windows/386/sys.s index d38405075..703f77d55 100644 --- a/src/pkg/runtime/windows/386/sys.s +++ b/src/pkg/runtime/windows/386/sys.s @@ -14,8 +14,6 @@ TEXT runtime·stdcall_raw(SB),7,$0 // Switch to m->g0 if needed. get_tls(DI) MOVL m(DI), DX - MOVL 0(FS), SI - MOVL SI, m_sehframe(DX) MOVL m_g0(DX), SI CMPL g(DI), SI MOVL SP, BX @@ -116,7 +114,7 @@ TEXT runtime·ctrlhandler(SB),7,$0 MOVL SP, BX // setup dummy m, g - SUBL $(m_sehframe+4), SP // at least space for m_sehframe + SUBL $(m_fflag+4), SP // at least space for m_fflag LEAL m_tls(SP), CX MOVL CX, 0x2c(FS) MOVL SP, m(CX) @@ -159,33 +157,39 @@ TEXT runtime·callbackasm+0(SB),7,$0 ADDL $4, DX // extend argsize by size of return value // save registers as required for windows callback - PUSHL 0(FS) PUSHL DI PUSHL SI PUSHL BP PUSHL BX + + // set up SEH frame again + PUSHL $runtime·sigtramp(SB) + PUSHL 0(FS) + MOVL SP, 0(FS) + + // callback parameters PUSHL DX PUSHL CX PUSHL AX - // reinstall our SEH handler - get_tls(CX) - MOVL m(CX), CX - MOVL m_sehframe(CX), CX - MOVL CX, 0(FS) CLD CALL runtime·cgocallback(SB) - // restore registers as required for windows callback POPL AX POPL CX POPL DX + + // pop SEH frame + POPL 0(FS) + POPL BX + + // restore registers as required for windows callback POPL BX POPL BP POPL SI POPL DI - POPL 0(FS) + CLD MOVL -4(CX)(DX*1), AX diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c index 4ab043e88..e08d1b6f0 100644 --- a/src/pkg/runtime/windows/thread.c +++ b/src/pkg/runtime/windows/thread.c @@ -347,16 +347,26 @@ static Callbacks cbs; byte * runtime·compilecallback(Eface fn, bool cleanstack) { - Func *f; - int32 argsize, n; + FuncType *ft; + Type *t; + int32 argsize, i, n; byte *p; Callback *c; - if(fn.type->kind != KindFunc) - runtime·panicstring("not a function"); - if((f = runtime·findfunc((uintptr)fn.data)) == nil) - runtime·throw("cannot find function"); - argsize = (f->args-2) * 4; + if(fn.type == nil || fn.type->kind != KindFunc) + runtime·panicstring("compilecallback: not a function"); + ft = (FuncType*)fn.type; + if(ft->out.len != 1) + runtime·panicstring("compilecallback: function must have one output parameter"); + if(((Type**)ft->out.array)[0]->size != sizeof(uintptr)) + runtime·panicstring("compilecallback: output parameter size is wrong"); + argsize = 0; + for(i=0; i<ft->in.len; i++) { + t = ((Type**)ft->in.array)[i]; + if(t->size != sizeof(uintptr)) + runtime·panicstring("compilecallback: input parameter size is wrong"); + argsize += t->size; + } // compute size of new fn. // must match code laid out below. diff --git a/src/pkg/syscall/route_bsd.go b/src/pkg/syscall/route_bsd.go index e41667c14..93e345d71 100644 --- a/src/pkg/syscall/route_bsd.go +++ b/src/pkg/syscall/route_bsd.go @@ -131,35 +131,6 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) { return sas } -const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA - -func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) { - if m.Header.Addrs&rtaIfmaMask == 0 { - return nil - } - - buf := m.Data[:] - for i := uint(0); i < RTAX_MAX; i++ { - if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 { - continue - } - rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) - switch i { - case RTAX_IFA: - sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) - if e != 0 { - return nil - } - sas = append(sas, sa) - case RTAX_GATEWAY, RTAX_IFP: - // nothing to do - } - buf = buf[rsaAlignOf(int(rsa.Len)):] - } - - return sas -} - // ParseRoutingMessage parses buf as routing messages and returns // the slice containing the RoutingMessage interfaces. func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) { diff --git a/src/pkg/syscall/route_darwin.go b/src/pkg/syscall/route_darwin.go index 8f79b708d..9d3a701da 100644 --- a/src/pkg/syscall/route_darwin.go +++ b/src/pkg/syscall/route_darwin.go @@ -46,3 +46,32 @@ type InterfaceMulticastAddrMessage struct { Header IfmaMsghdr2 Data []byte } + +const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA + +func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) { + if m.Header.Addrs&rtaIfmaMask == 0 { + return nil + } + + buf := m.Data[:] + for i := uint(0); i < RTAX_MAX; i++ { + if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 { + continue + } + rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) + switch i { + case RTAX_IFA: + sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) + if e != 0 { + return nil + } + sas = append(sas, sa) + case RTAX_GATEWAY, RTAX_IFP: + // nothing to do + } + buf = buf[rsaAlignOf(int(rsa.Len)):] + } + + return sas +} diff --git a/src/pkg/syscall/route_freebsd.go b/src/pkg/syscall/route_freebsd.go index 128e93cf9..0d61d08b0 100644 --- a/src/pkg/syscall/route_freebsd.go +++ b/src/pkg/syscall/route_freebsd.go @@ -46,3 +46,32 @@ type InterfaceMulticastAddrMessage struct { Header IfmaMsghdr Data []byte } + +const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA + +func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) { + if m.Header.Addrs&rtaIfmaMask == 0 { + return nil + } + + buf := m.Data[:] + for i := uint(0); i < RTAX_MAX; i++ { + if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 { + continue + } + rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) + switch i { + case RTAX_IFA: + sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) + if e != 0 { + return nil + } + sas = append(sas, sa) + case RTAX_GATEWAY, RTAX_IFP: + // nothing to do + } + buf = buf[rsaAlignOf(int(rsa.Len)):] + } + + return sas +} diff --git a/src/pkg/syscall/syscall_plan9.go b/src/pkg/syscall/syscall_plan9.go index a158b9516..eacdd93c9 100644 --- a/src/pkg/syscall/syscall_plan9.go +++ b/src/pkg/syscall/syscall_plan9.go @@ -35,9 +35,14 @@ var ( Stdout = 1 Stderr = 2 - EISDIR = NewError("file is a directory") + EAFNOSUPPORT = NewError("address family not supported by protocol") + EISDIR = NewError("file is a directory") ) +// For testing: clients can set this flag to force +// creation of IPv6 sockets to return EAFNOSUPPORT. +var SocketDisableIPv6 bool + func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err string) func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err string) func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go index 05887da82..19c6587f5 100644 --- a/src/pkg/syscall/syscall_windows.go +++ b/src/pkg/syscall/syscall_windows.go @@ -90,7 +90,7 @@ func getprocaddress(handle uintptr, procname uintptr) (proc uintptr) // call to its Handle method or to one of its // LazyProc's Addr method. type LazyDLL struct { - sync.Mutex + mu sync.Mutex Name string h uintptr // module handle once dll is loaded } @@ -98,8 +98,8 @@ type LazyDLL struct { // Handle returns d's module handle. func (d *LazyDLL) Handle() uintptr { if d.h == 0 { - d.Lock() - defer d.Unlock() + d.mu.Lock() + defer d.mu.Unlock() if d.h == 0 { d.h = loadlibraryex(uintptr(unsafe.Pointer(StringBytePtr(d.Name)))) if d.h == 0 { @@ -123,7 +123,7 @@ func NewLazyDLL(name string) *LazyDLL { // A LazyProc implements access to a procedure inside a LazyDLL. // It delays the lookup until the Addr method is called. type LazyProc struct { - sync.Mutex + mu sync.Mutex Name string dll *LazyDLL addr uintptr @@ -133,8 +133,8 @@ type LazyProc struct { // The return value can be passed to Syscall to run the procedure. func (s *LazyProc) Addr() uintptr { if s.addr == 0 { - s.Lock() - defer s.Unlock() + s.mu.Lock() + defer s.mu.Unlock() if s.addr == 0 { s.addr = getprocaddress(s.dll.Handle(), uintptr(unsafe.Pointer(StringBytePtr(s.Name)))) if s.addr == 0 { diff --git a/src/pkg/template/Makefile b/src/pkg/template/Makefile index 4f1e06527..3ed3b0330 100644 --- a/src/pkg/template/Makefile +++ b/src/pkg/template/Makefile @@ -1,4 +1,4 @@ -# Copyright 2009 The Go Authors. All rights reserved. +# Copyright 2011 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. @@ -6,9 +6,10 @@ include ../../Make.inc TARG=template GOFILES=\ - doc.go\ - execute.go\ - format.go\ + exec.go\ + funcs.go\ + helper.go\ parse.go\ + set.go\ include ../../Make.pkg diff --git a/src/pkg/template/doc.go b/src/pkg/template/doc.go index e778d801d..f65946aed 100644 --- a/src/pkg/template/doc.go +++ b/src/pkg/template/doc.go @@ -1,91 +1,313 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. /* - Package template implements data-driven templates for generating textual - output such as HTML. - - Templates are executed by applying them to a data structure. - Annotations in the template refer to elements of the data - structure (typically a field of a struct or a key in a map) - to control execution and derive values to be displayed. - The template walks the structure as it executes and the - "cursor" @ represents the value at the current location - in the structure. - - Data items may be values or pointers; the interface hides the - indirection. - - In the following, 'Field' is one of several things, according to the data. - - - The name of a field of a struct (result = data.Field), - - The value stored in a map under that key (result = data["Field"]), or - - The result of invoking a niladic single-valued method with that name - (result = data.Field()) - - If Field is a struct field or method name, it must be an exported - (capitalized) name. - - Major constructs ({} are the default delimiters for template actions; - [] are the notation in this comment for optional elements): - - {# comment } - - A one-line comment. - - {.section field} XXX [ {.or} YYY ] {.end} - - Set @ to the value of the field. It may be an explicit @ - to stay at the same point in the data. If the field is nil - or empty, execute YYY; otherwise execute XXX. - - {.repeated section field} XXX [ {.alternates with} ZZZ ] [ {.or} YYY ] {.end} - - Like .section, but field must be an array or slice. XXX - is executed for each element. If the array is nil or empty, - YYY is executed instead. If the {.alternates with} marker - is present, ZZZ is executed between iterations of XXX. - - {field} - {field1 field2 ...} - {field|formatter} - {field1 field2...|formatter} - {field|formatter1|formatter2} - - Insert the value of the fields into the output. Each field is - first looked for in the cursor, as in .section and .repeated. - If it is not found, the search continues in outer sections - until the top level is reached. - - If the field value is a pointer, leading asterisks indicate - that the value to be inserted should be evaluated through the - pointer. For example, if x.p is of type *int, {x.p} will - insert the value of the pointer but {*x.p} will insert the - value of the underlying integer. If the value is nil or not a - pointer, asterisks have no effect. - - If a formatter is specified, it must be named in the formatter - map passed to the template set up routines or in the default - set ("html","str","") and is used to process the data for - output. The formatter function has signature - func(wr io.Writer, formatter string, data ...interface{}) - where wr is the destination for output, data holds the field - values at the instantiation, and formatter is its name at - the invocation site. The default formatter just concatenates - the string representations of the fields. - - Multiple formatters separated by the pipeline character | are - executed sequentially, with each formatter receiving the bytes - emitted by the one to its left. - - As well as field names, one may use literals with Go syntax. - Integer, floating-point, and string literals are supported. - Raw strings may not span newlines. - - The delimiter strings get their default value, "{" and "}", from - JSON-template. They may be set to any non-empty, space-free - string using the SetDelims method. Their value can be printed - in the output using {.meta-left} and {.meta-right}. +Package template implements data-driven templates for generating textual output +such as HTML. + +Templates are executed by applying them to a data structure. Annotations in the +template refer to elements of the data structure (typically a field of a struct +or a key in a map) to control execution and derive values to be displayed. +Execution of the template walks the structure and sets the cursor, represented +by a period '.' and called "dot", to the value at the current location in the +structure as execution proceeds. + +The input text for a template is UTF-8-encoded text in any format. +"Actions"--data evaluations or control structures--are delimited by +"{{" and "}}"; all text outside actions is copied to the output unchanged. +Actions may not span newlines, although comments can. + +Once constructed, templates and template sets can be executed safely in +parallel. + +Actions + +Here is the list of actions. "Arguments" and "pipelines" are evaluations of +data, defined in detail below. + +*/ +// {{/* a comment */}} +// A comment; discarded. May contain newlines. +// Comments do not nest. +/* + + {{pipeline}} + The default textual representation of the value of the pipeline + is copied to the output. + + {{if pipeline}} T1 {{end}} + If the value of the pipeline is empty, no output is generated; + otherwise, T1 is executed. The empty values are false, 0, any + nil pointer or interface value, and any array, slice, map, or + string of length zero. + Dot is unaffected. + + {{if pipeline}} T1 {{else}} T0 {{end}} + If the value of the pipeline is empty, T0 is executed; + otherwise, T1 is executed. Dot is unaffected. + + {{range pipeline}} T1 {{end}} + The value of the pipeline must be an array, slice, or map. If + the value of the pipeline has length zero, nothing is output; + otherwise, dot is set to the successive elements of the array, + slice, or map and T1 is executed. + + {{range pipeline}} T1 {{else}} T0 {{end}} + The value of the pipeline must be an array, slice, or map. If + the value of the pipeline has length zero, dot is unaffected and + T0 is executed; otherwise, dot is set to the successive elements + of the array, slice, or map and T1 is executed. + + {{template "name"}} + The template with the specified name is executed with nil data. + + {{template "name" pipeline}} + The template with the specified name is executed with dot set + to the value of the pipeline. + + {{with pipeline}} T1 {{end}} + If the value of the pipeline is empty, no output is generated; + otherwise, dot is set to the value of the pipeline and T1 is + executed. + + {{with pipeline}} T1 {{else}} T0 {{end}} + If the value of the pipeline is empty, dot is unaffected and T0 + is executed; otherwise, dot is set to the value of the pipeline + and T1 is executed. + +Arguments + +An argument is a simple value, denoted by one of the following. + + - A boolean, string, character, integer, floating-point, imaginary + or complex constant in Go syntax. These behave like Go's untyped + constants, although raw strings may not span newlines. + - The character '.' (period): + . + The result is the value of dot. + - A variable name, which is a (possibly empty) alphanumeric string + preceded by a dollar sign, such as + $piOver2 + or + $ + The result is the value of the variable. + Variables are described below. + - The name of a field of the data, which must be a struct, preceded + by a period, such as + .Field + The result is the value of the field. Field invocations may be + chained: + .Field1.Field2 + Fields can also be evaluated on variables, including chaining: + $x.Field1.Field2 + - The name of a key of the data, which must be a map, preceded + by a period, such as + .Key + The result is the map element value indexed by the key. + Key invocations may be chained and combined with fields to any + depth: + .Field1.Key1.Field2.Key2 + Although the key must be an alphanumeric identifier, unlike with + field names they do not need to start with an upper case letter. + Keys can also be evaluated on variables, including chaining: + $x.key1.key2 + - The name of a niladic method of the data, preceded by a period, + such as + .Method + The result is the value of invoking the method with dot as the + receiver, dot.Method(). Such a method must have one return value (of + any type) or two return values, the second of which is an os.Error. + If it has two and the returned error is non-nil, execution terminates + and an error is returned to the caller as the value of Execute. + Method invocations may be chained and combined with fields and keys + to any depth: + .Field1.Key1.Method1.Field2.Key2.Method2 + Methods can also be evaluated on variables, including chaining: + $x.Method1.Field + - The name of a niladic function, such as + fun + The result is the value of invoking the function, fun(). The return + types and values behave as in methods. Functions and function + names are described below. + +Arguments may evaluate to any type; if they are pointers the implementation +automatically indirects to the base type when required. + +A pipeline is a possibly chained sequence of "commands". A command is a simple +value (argument) or a function or method call, possibly with multiple arguments: + + Argument + The result is the value of evaluating the argument. + .Method [Argument...] + The method can be alone or the last element of a chain but, + unlike methods in the middle of a chain, it can take arguments. + The result is the value of calling the method with the + arguments: + dot.Method(Argument1, etc.) + functionName [Argument...] + The result is the value of calling the function associated + with the name: + function(Argument1, etc.) + Functions and function names are described below. + +Pipelines + +A pipeline may be "chained" by separating a sequence of commands with pipeline +characters '|'. In a chained pipeline, the result of the each command is +passed as the last argument of the following command. The output of the final +command in the pipeline is the value of the pipeline. + +The output of a command will be either one value or two values, the second of +which has type os.Error. If that second value is present and evaluates to +non-nil, execution terminates and the error is returned to the caller of +Execute. + +Variables + +A pipeline inside an action may initialize a variable to capture the result. +The initialization has syntax + + $variable := pipeline + +where $variable is the name of the variable. An action that declares a +variable produces no output. + +If a "range" action initializes a variable, the variable is set to the +successive elements of the iteration. Also, a "range" may declare two +variables, separated by a comma: + + $index, $element := pipeline + +in which case $index and $element are set to the successive values of the +array/slice index or map key and element, respectively. Note that if there is +only one variable, it is assigned the element; this is opposite to the +convention in Go range clauses. + +A variable's scope extends to the "end" action of the control structure ("if", +"with", or "range") in which it is declared, or to the end of the template if +there is no such control structure. A template invocation does not inherit +variables from the point of its invocation. + +When execution begins, $ is set to the data argument passed to Execute, that is, +to the starting value of dot. + +Examples + +Here are some example one-line templates demonstrating pipelines and variables. +All produce the quoted word "output": + + {{"\"output\""}} + A string constant. + {{`"output"`}} + A raw string constant. + {{printf "%q" "output"}} + A function call. + {{"output" | printf "%q"}} + A function call whose final argument comes from the previous + command. + {{"put" | printf "%s%s" "out" | printf "%q"}} + A more elaborate call. + {{"output" | printf "%s" | printf "%q"}} + A longer chain. + {{with "output"}}{{printf "%q" .}}{{end}} + A with action using dot. + {{with $x := "output" | printf "%q"}}{{$x}}{{end}} + A with action that creates and uses a variable. + {{with $x := "output"}}{{printf "%q" $x}}{{end}} + A with action that uses the variable in another action. + {{with $x := "output"}}{{$x | printf "%q"}}{{end}} + The same, but pipelined. + +Functions + +During execution functions are found in three function maps: first in the +template, then in the "template set" (described below), and finally in the +global function map. By default, no functions are defined in the template or +the set but the Funcs methods can be used to add them. + +Predefined global functions are named as follows. + + and + Returns the boolean AND of its arguments by returning the + first empty argument or the last argument, that is, + "and x y" behaves as "if x then y else x". All the + arguments are evaluated. + html + Returns the escaped HTML equivalent of the textual + representation of its arguments. + index + Returns the result of indexing its first argument by the + following arguments. Thus "index x 1 2 3" is, in Go syntax, + x[1][2][3]. Each indexed item must be a map, slice, or array. + js + Returns the escaped JavaScript equivalent of the textual + representation of its arguments. + len + Returns the integer length of its argument. + not + Returns the boolean negation of its single argument. + or + Returns the boolean OR of its arguments by returning the + first non-empty argument or the last argument, that is, + "or x y" behaves as "if x then x else y". All the + arguments are evaluated. + print + An alias for fmt.Sprint + printf + An alias for fmt.Sprintf + println + An alias for fmt.Sprintln + urlquery + Returns the escaped value of the textual representation of + its arguments in a form suitable for embedding in a URL query. + +The boolean functions take any zero value to be false and a non-zero value to +be true. + +Template sets + +Each template is named by a string specified when it is created. A template may +use a template invocation to instantiate another template directly or by its +name; see the explanation of the template action above. The name is looked up +in the template set associated with the template. + +If no template invocation actions occur in the template, the issue of template +sets can be ignored. If it does contain invocations, though, the template +containing the invocations must be part of a template set in which to look up +the names. + +There are two ways to construct template sets. + +The first is to use a Set's Parse method to create a set of named templates from +a single input defining multiple templates. The syntax of the definitions is to +surround each template declaration with a define and end action. + +The define action names the template being created by providing a string +constant. Here is a simple example of input to Set.Parse: + + `{{define "T1"}} definition of template T1 {{end}} + {{define "T2"}} definition of template T2 {{end}} + {{define "T3"}} {{template "T1"}} {{template "T2"}} {{end}}` + +This defines two templates, T1 and T2, and a third T3 that invokes the other two +when it is executed. + +The second way to build a template set is to use Set's Add method to add a +parsed template to a set. A template may be bound at most one set. If it's +necessary to have a template in multiple sets, the template definition must be +parsed multiple times to create distinct *Template values. + +Set.Parse may be called multiple times on different inputs to construct the set. +Two sets may therefore be constructed with a common base set of templates plus, +through a second Parse call each, specializations for some elements. + +A template may be executed directly or through Set.Execute, which executes a +named template from the set. To invoke our example above, we might write, + + err := set.Execute(os.Stdout, "T3", "no data needed") + if err != nil { + log.Fatalf("execution failed: %s", err) + } */ package template diff --git a/src/pkg/exp/template/exec.go b/src/pkg/template/exec.go index 7d7a9c732..eaa57ae81 100644 --- a/src/pkg/exp/template/exec.go +++ b/src/pkg/template/exec.go @@ -5,13 +5,13 @@ package template import ( - "exp/template/parse" "fmt" "io" "os" "reflect" "runtime" "strings" + "template/parse" ) // state represents the state of an execution. It's not part of the @@ -148,7 +148,7 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse. val := s.evalPipeline(dot, pipe) truth, ok := isTrue(val) if !ok { - s.errorf("if/with can't use value of type %T", val.Interface()) + s.errorf("if/with can't use %v", val) } if truth { if typ == parse.NodeWith { @@ -164,6 +164,10 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse. // isTrue returns whether the value is 'true', in the sense of not the zero of its type, // and whether the value has a meaningful truth value. func isTrue(val reflect.Value) (truth, ok bool) { + if !val.IsValid() { + // Something like var x interface{}, never set. It's a form of nil. + return false, true + } switch val.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: truth = val.Len() > 0 @@ -171,7 +175,7 @@ func isTrue(val reflect.Value) (truth, ok bool) { truth = val.Bool() case reflect.Complex64, reflect.Complex128: truth = val.Complex() != 0 - case reflect.Chan, reflect.Func, reflect.Ptr: + case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: truth = !val.IsNil() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: truth = val.Int() != 0 @@ -229,8 +233,10 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { s.pop(mark) } return + case reflect.Invalid: + break // An invalid value is likely a nil map, etc. and acts like an empty map. default: - s.errorf("range can't iterate over value of type %T", val.Interface()) + s.errorf("range can't iterate over %v", val) } if r.ElseList != nil { s.walk(dot, r.ElseList) @@ -388,13 +394,14 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node if method, ok := methodByName(ptr, fieldName); ok { return s.evalCall(dot, method, fieldName, args, final) } + hasArgs := len(args) > 1 || final.IsValid() // It's not a method; is it a field of a struct? receiver, isNil := indirect(receiver) if receiver.Kind() == reflect.Struct { tField, ok := receiver.Type().FieldByName(fieldName) if ok { field := receiver.FieldByIndex(tField.Index) - if len(args) > 1 || final.IsValid() { + if hasArgs { s.errorf("%s is not a method but has arguments", fieldName) } if tField.PkgPath == "" { // field is exported @@ -402,6 +409,16 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node } } } + // If it's a map, attempt to use the field name as a key. + if receiver.Kind() == reflect.Map { + nameVal := reflect.ValueOf(fieldName) + if nameVal.Type().AssignableTo(receiver.Type().Key()) { + if hasArgs { + s.errorf("%s is not a method but has arguments", fieldName) + } + return receiver.MapIndex(nameVal) + } + } if isNil { s.errorf("nil pointer evaluating %s.%s", typ, fieldName) } @@ -421,7 +438,8 @@ func methodByName(receiver reflect.Value, name string) (reflect.Value, bool) { } var ( - osErrorType = reflect.TypeOf(new(os.Error)).Elem() + osErrorType = reflect.TypeOf((*os.Error)(nil)).Elem() + fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() ) // evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so @@ -615,19 +633,23 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { // printValue writes the textual representation of the value to the output of // the template. func (s *state) printValue(n parse.Node, v reflect.Value) { + if v.Kind() == reflect.Ptr { + v, _ = indirect(v) // fmt.Fprint handles nil. + } if !v.IsValid() { fmt.Fprint(s.wr, "<no value>") return } - switch v.Kind() { - case reflect.Ptr: - var isNil bool - if v, isNil = indirect(v); isNil { - fmt.Fprint(s.wr, "<nil>") - return + + if !v.Type().Implements(fmtStringerType) { + if v.CanAddr() && reflect.PtrTo(v.Type()).Implements(fmtStringerType) { + v = v.Addr() + } else { + switch v.Kind() { + case reflect.Chan, reflect.Func: + s.errorf("can't print %s of type %s", n, v.Type()) + } } - case reflect.Chan, reflect.Func, reflect.Interface: - s.errorf("can't print %s of type %s", n, v.Type()) } fmt.Fprint(s.wr, v.Interface()) } diff --git a/src/pkg/exp/template/exec_test.go b/src/pkg/template/exec_test.go index b78847440..82f56e13c 100644 --- a/src/pkg/exp/template/exec_test.go +++ b/src/pkg/template/exec_test.go @@ -28,6 +28,9 @@ type T struct { ComplexZero float64 // Nested structs. U *U + // Struct with String method. + V0 V + V1, V2 *V // Slices SI []int SIEmpty []int @@ -36,6 +39,8 @@ type T struct { MSI map[string]int MSIone map[string]int // one element, for deterministic output MSIEmpty map[string]int + MXI map[interface{}]int + MII map[int]int SMSI []map[string]int // Empty interfaces; used to see if we can dig inside one. Empty0 interface{} // nil @@ -45,6 +50,8 @@ type T struct { Empty4 interface{} // Non-empty interface. NonEmptyInterface I + // Stringer. + Str fmt.Stringer // Pointers PI *int PSI *[]int @@ -57,16 +64,31 @@ type U struct { V string } +type V struct { + j int +} + +func (v *V) String() string { + if v == nil { + return "nilV" + } + return fmt.Sprintf("<%d>", v.j) +} + var tVal = &T{ True: true, I: 17, U16: 16, X: "x", U: &U{"v"}, + V0: V{6666}, + V1: &V{7777}, // leave V2 as nil SI: []int{3, 4, 5}, SB: []bool{true, false}, MSI: map[string]int{"one": 1, "two": 2, "three": 3}, MSIone: map[string]int{"one": 1}, + MXI: map[interface{}]int{"one": 1}, + MII: map[int]int{1: 1}, SMSI: []map[string]int{ {"one": 1, "two": 2}, {"eleven": 11, "twelve": 12}, @@ -76,6 +98,7 @@ var tVal = &T{ Empty3: []int{7, 8}, Empty4: &U{"UinEmpty"}, NonEmptyInterface: new(T), + Str: os.NewError("foozle"), PI: newInt(23), PSI: newIntSlice(21, 22, 23), Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X @@ -192,6 +215,14 @@ var execTests = []execTest{ {".X", "-{{.X}}-", "-x-", tVal, true}, {".U.V", "-{{.U.V}}-", "-v-", tVal, true}, + // Fields on maps. + {"map .one", "{{.MSI.one}}", "1", tVal, true}, + {"map .two", "{{.MSI.two}}", "2", tVal, true}, + {"map .NO", "{{.MSI.NO}}", "<no value>", tVal, true}, + {"map .one interface", "{{.MXI.one}}", "1", tVal, true}, + {"map .WRONG args", "{{.MSI.one 1}}", "", tVal, false}, + {"map .WRONG type", "{{.MII.one}}", "", tVal, false}, + // Dots of all kinds to test basic evaluation. {"dot int", "<{{.}}>", "<13>", 13, true}, {"dot uint", "<{{.}}>", "<14>", uint(14), true}, @@ -212,6 +243,11 @@ var execTests = []execTest{ {"$.U.V", "{{$.U.V}}", "v", tVal, true}, {"declare in action", "{{$x := $.U.V}}{{$x}}", "v", tVal, true}, + // Type with String method. + {"V{6666}.String()", "-{{.V0}}-", "-<6666>-", tVal, true}, + {"&V{7777}.String()", "-{{.V1}}-", "-<7777>-", tVal, true}, + {"(*V)(nil).String()", "-{{.V2}}-", "-nilV-", tVal, true}, + // Pointers. {"*int", "{{.PI}}", "23", tVal, true}, {"*[]int", "{{.PSI}}", "[21 22 23]", tVal, true}, @@ -289,8 +325,8 @@ var execTests = []execTest{ // JavaScript. {"js", `{{js .}}`, `It\'d be nice.`, `It'd be nice.`, true}, - // URL. - {"url", `{{"http://www.example.org/"|url}}`, "http%3A%2F%2Fwww.example.org%2F", nil, true}, + // URL query. + {"urlquery", `{{"http://www.example.org/"|urlquery}}`, "http%3A%2F%2Fwww.example.org%2F", nil, true}, // Booleans {"not", "{{not true}} {{not false}}", "false true", nil, true}, @@ -310,6 +346,12 @@ var execTests = []execTest{ {"map[WRONG]", "{{index .MSI 10}}", "", tVal, false}, {"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true}, + // Len. + {"slice", "{{len .SI}}", "3", tVal, true}, + {"map", "{{len .MSI }}", "3", tVal, true}, + {"len of int", "{{len 3}}", "", tVal, false}, + {"len of nothing", "{{len .Empty0}}", "", tVal, false}, + // With. {"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true}, {"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true}, @@ -342,6 +384,7 @@ var execTests = []execTest{ {"range map else", "{{range .MSI | .MSort}}-{{.}}-{{else}}EMPTY{{end}}", "-one--three--two-", tVal, true}, {"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, {"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true}, + {"range empty nil", "{{range .Empty0}}-{{.}}-{{end}}", "", tVal, true}, {"range $x SI", "{{range $x := .SI}}<{{$x}}>{{end}}", "<3><4><5>", tVal, true}, {"range $x $y SI", "{{range $x, $y := .SI}}<{{$x}}={{$y}}>{{end}}", "<0=3><1=4><2=5>", tVal, true}, {"range $x MSIone", "{{range $x := .MSIone}}<{{$x}}>{{end}}", "<1>", tVal, true}, @@ -366,7 +409,11 @@ var execTests = []execTest{ // Was taking address of interface field, so method set was empty. {"bug2", "{{$.NonEmptyInterface.Method0}}", "M0", tVal, true}, // Struct values were not legal in with - mere oversight. - {"bug4", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true}, + {"bug3", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true}, + // Nil interface values in if. + {"bug4", "{{if .Empty0}}non-nil{{else}}nil{{end}}", "nil", tVal, true}, + // Stringer. + {"bug5", "{{.Str}}", "foozle", tVal, true}, } func zeroArgs() string { diff --git a/src/pkg/exp/template/funcs.go b/src/pkg/template/funcs.go index 579c70099..feb1fd82c 100644 --- a/src/pkg/exp/template/funcs.go +++ b/src/pkg/template/funcs.go @@ -7,12 +7,12 @@ package template import ( "bytes" "fmt" - "http" "io" "os" "reflect" "strings" "unicode" + "url" "utf8" ) @@ -23,16 +23,17 @@ import ( type FuncMap map[string]interface{} var builtins = FuncMap{ - "and": and, - "html": HTMLEscaper, - "index": index, - "js": JSEscaper, - "not": not, - "or": or, - "print": fmt.Sprint, - "printf": fmt.Sprintf, - "println": fmt.Sprintln, - "url": URLEscaper, + "and": and, + "html": HTMLEscaper, + "index": index, + "js": JSEscaper, + "len": length, + "not": not, + "or": or, + "print": fmt.Sprint, + "printf": fmt.Sprintf, + "println": fmt.Sprintln, + "urlquery": URLQueryEscaper, } var builtinFuncs = createValueFuncs(builtins) @@ -140,6 +141,21 @@ func index(item interface{}, indices ...interface{}) (interface{}, os.Error) { return v.Interface(), nil } +// Length + +// length returns the length of the item, with an error if it has no defined length. +func length(item interface{}) (int, os.Error) { + v, isNil := indirect(reflect.ValueOf(item)) + if isNil { + return 0, fmt.Errorf("len of nil pointer") + } + switch v.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String: + return v.Len(), nil + } + return 0, fmt.Errorf("len of type %s", v.Type()) +} + // Boolean logic. func truth(a interface{}) bool { @@ -338,9 +354,9 @@ func JSEscaper(args ...interface{}) string { return JSEscapeString(s) } -// URLEscaper returns the escaped value of the textual representation of its -// arguments in a form suitable for embedding in a URL. -func URLEscaper(args ...interface{}) string { +// URLQueryEscaper returns the escaped value of the textual representation of +// its arguments in a form suitable for embedding in a URL query. +func URLQueryEscaper(args ...interface{}) string { s, ok := "", false if len(args) == 1 { s, ok = args[0].(string) @@ -348,5 +364,5 @@ func URLEscaper(args ...interface{}) string { if !ok { s = fmt.Sprint(args...) } - return http.URLEscape(s) + return url.QueryEscape(s) } diff --git a/src/pkg/exp/template/helper.go b/src/pkg/template/helper.go index ae6a057ee..c9b099856 100644 --- a/src/pkg/exp/template/helper.go +++ b/src/pkg/template/helper.go @@ -70,7 +70,7 @@ func (t *Template) parseFileInSet(filename string, set *Set) (*Template, os.Erro // SetMust is a helper that wraps a call to a function returning (*Set, os.Error) // and panics if the error is non-nil. It is intended for use in variable initializations // such as -// var s = template.SetMust(template.ParseSetFile("file")) +// var s = template.SetMust(template.ParseSetFiles("file")) func SetMust(s *Set, err os.Error) *Set { if err != nil { panic(err) @@ -78,10 +78,10 @@ func SetMust(s *Set, err os.Error) *Set { return s } -// ParseFile parses the named files into a set of named templates. +// ParseFiles parses the named files into a set of named templates. // Each file must be parseable by itself. // If an error occurs, parsing stops and the returned set is nil. -func (s *Set) ParseFile(filenames ...string) (*Set, os.Error) { +func (s *Set) ParseFiles(filenames ...string) (*Set, os.Error) { for _, filename := range filenames { b, err := ioutil.ReadFile(filename) if err != nil { @@ -95,9 +95,9 @@ func (s *Set) ParseFile(filenames ...string) (*Set, os.Error) { return s, nil } -// ParseSetFile creates a new Set and parses the set definition from the +// ParseSetFiles creates a new Set and parses the set definition from the // named files. Each file must be individually parseable. -func ParseSetFile(filenames ...string) (*Set, os.Error) { +func ParseSetFiles(filenames ...string) (*Set, os.Error) { s := new(Set) for _, filename := range filenames { b, err := ioutil.ReadFile(filename) @@ -112,11 +112,11 @@ func ParseSetFile(filenames ...string) (*Set, os.Error) { return s, nil } -// ParseFiles parses the set definition from the files identified by the +// ParseGlob parses the set definition from the files identified by the // pattern. The pattern is processed by filepath.Glob and must match at // least one file. // If an error occurs, parsing stops and the returned set is nil. -func (s *Set) ParseFiles(pattern string) (*Set, os.Error) { +func (s *Set) ParseGlob(pattern string) (*Set, os.Error) { filenames, err := filepath.Glob(pattern) if err != nil { return nil, err @@ -124,14 +124,14 @@ func (s *Set) ParseFiles(pattern string) (*Set, os.Error) { if len(filenames) == 0 { return nil, fmt.Errorf("pattern matches no files: %#q", pattern) } - return s.ParseFile(filenames...) + return s.ParseFiles(filenames...) } -// ParseSetFiles creates a new Set and parses the set definition from the +// ParseSetGlob creates a new Set and parses the set definition from the // files identified by the pattern. The pattern is processed by filepath.Glob // and must match at least one file. -func ParseSetFiles(pattern string) (*Set, os.Error) { - set, err := new(Set).ParseFiles(pattern) +func ParseSetGlob(pattern string) (*Set, os.Error) { + set, err := new(Set).ParseGlob(pattern) if err != nil { return nil, err } @@ -140,17 +140,17 @@ func ParseSetFiles(pattern string) (*Set, os.Error) { // Functions and methods to parse stand-alone template files into a set. -// ParseTemplateFile parses the named template files and adds -// them to the set. Each template will named the base name of +// ParseTemplateFiles parses the named template files and adds +// them to the set. Each template will be named the base name of // its file. -// Unlike with ParseFile, each file should be a stand-alone template +// Unlike with ParseFiles, each file should be a stand-alone template // definition suitable for Template.Parse (not Set.Parse); that is, the -// file does not contain {{define}} clauses. ParseTemplateFile is +// file does not contain {{define}} clauses. ParseTemplateFiles is // therefore equivalent to calling the ParseFile function to create // individual templates, which are then added to the set. // Each file must be parseable by itself. // If an error occurs, parsing stops and the returned set is nil. -func (s *Set) ParseTemplateFile(filenames ...string) (*Set, os.Error) { +func (s *Set) ParseTemplateFiles(filenames ...string) (*Set, os.Error) { for _, filename := range filenames { _, err := parseFileInSet(filename, s) if err != nil { @@ -160,17 +160,17 @@ func (s *Set) ParseTemplateFile(filenames ...string) (*Set, os.Error) { return s, nil } -// ParseTemplateFiles parses the template files matched by the -// patern and adds them to the set. Each template will named +// ParseTemplateGlob parses the template files matched by the +// patern and adds them to the set. Each template will be named // the base name of its file. -// Unlike with ParseFiles, each file should be a stand-alone template +// Unlike with ParseGlob, each file should be a stand-alone template // definition suitable for Template.Parse (not Set.Parse); that is, the -// file does not contain {{define}} clauses. ParseTemplateFiles is +// file does not contain {{define}} clauses. ParseTemplateGlob is // therefore equivalent to calling the ParseFile function to create // individual templates, which are then added to the set. // Each file must be parseable by itself. // If an error occurs, parsing stops and the returned set is nil. -func (s *Set) ParseTemplateFiles(pattern string) (*Set, os.Error) { +func (s *Set) ParseTemplateGlob(pattern string) (*Set, os.Error) { filenames, err := filepath.Glob(pattern) if err != nil { return nil, err @@ -184,17 +184,17 @@ func (s *Set) ParseTemplateFiles(pattern string) (*Set, os.Error) { return s, nil } -// ParseTemplateFile creates a set by parsing the named files, -// each of which defines a single template. Each template will +// ParseTemplateFiles creates a set by parsing the named files, +// each of which defines a single template. Each template will be // named the base name of its file. -// Unlike with ParseFile, each file should be a stand-alone template +// Unlike with ParseFiles, each file should be a stand-alone template // definition suitable for Template.Parse (not Set.Parse); that is, the -// file does not contain {{define}} clauses. ParseTemplateFile is +// file does not contain {{define}} clauses. ParseTemplateFiles is // therefore equivalent to calling the ParseFile function to create // individual templates, which are then added to the set. // Each file must be parseable by itself. Parsing stops if an error is // encountered. -func ParseTemplateFile(filenames ...string) (*Set, os.Error) { +func ParseTemplateFiles(filenames ...string) (*Set, os.Error) { set := new(Set) set.init() for _, filename := range filenames { @@ -209,17 +209,17 @@ func ParseTemplateFile(filenames ...string) (*Set, os.Error) { return set, nil } -// ParseTemplateFiles creates a set by parsing the files matched +// ParseTemplateGlob creates a set by parsing the files matched // by the pattern, each of which defines a single template. Each -// template will named the base name of its file. -// Unlike with ParseFiles, each file should be a stand-alone template +// template will be named the base name of its file. +// Unlike with ParseGlob, each file should be a stand-alone template // definition suitable for Template.Parse (not Set.Parse); that is, the -// file does not contain {{define}} clauses. ParseTemplateFiles is +// file does not contain {{define}} clauses. ParseTemplateGlob is // therefore equivalent to calling the ParseFile function to create // individual templates, which are then added to the set. // Each file must be parseable by itself. Parsing stops if an error is // encountered. -func ParseTemplateFiles(pattern string) (*Set, os.Error) { +func ParseTemplateGlob(pattern string) (*Set, os.Error) { set := new(Set) filenames, err := filepath.Glob(pattern) if err != nil { diff --git a/src/pkg/template/parse.go b/src/pkg/template/parse.go index dedf9ad8e..b089c599a 100644 --- a/src/pkg/template/parse.go +++ b/src/pkg/template/parse.go @@ -1,743 +1,85 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code to parse a template. - package template import ( - "fmt" - "io" - "io/ioutil" "os" "reflect" - "strconv" - "strings" - "unicode" - "utf8" -) - -// Errors returned during parsing and execution. Users may extract the information and reformat -// if they desire. -type Error struct { - Line int - Msg string -} - -func (e *Error) String() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) } - -// checkError is a deferred function to turn a panic with type *Error into a plain error return. -// Other panics are unexpected and so are re-enabled. -func checkError(error *os.Error) { - if v := recover(); v != nil { - if e, ok := v.(*Error); ok { - *error = e - } else { - // runtime errors should crash - panic(v) - } - } -} - -// Most of the literals are aces. -var lbrace = []byte{'{'} -var rbrace = []byte{'}'} -var space = []byte{' '} -var tab = []byte{'\t'} - -// The various types of "tokens", which are plain text or (usually) brace-delimited descriptors -const ( - tokAlternates = iota - tokComment - tokEnd - tokLiteral - tokOr - tokRepeated - tokSection - tokText - tokVariable + "template/parse" ) -// FormatterMap is the type describing the mapping from formatter -// names to the functions that implement them. -type FormatterMap map[string]func(io.Writer, string, ...interface{}) - -// Built-in formatters. -var builtins = FormatterMap{ - "html": HTMLFormatter, - "str": StringFormatter, - "": StringFormatter, -} - -// The parsed state of a template is a vector of xxxElement structs. -// Sections have line numbers so errors can be reported better during execution. - -// Plain text. -type textElement struct { - text []byte -} - -// A literal such as .meta-left or .meta-right -type literalElement struct { - text []byte -} - -// A variable invocation to be evaluated -type variableElement struct { - linenum int - args []interface{} // The fields and literals in the invocation. - fmts []string // Names of formatters to apply. len(fmts) > 0 -} - -// A variableElement arg to be evaluated as a field name -type fieldName string - -// A .section block, possibly with a .or -type sectionElement struct { - linenum int // of .section itself - field string // cursor field for this block - start int // first element - or int // first element of .or block - end int // one beyond last element -} - -// A .repeated block, possibly with a .or and a .alternates -type repeatedElement struct { - sectionElement // It has the same structure... - altstart int // ... except for alternates - altend int -} - -// Template is the type that represents a template definition. -// It is unchanged after parsing. +// Template is the representation of a parsed template. type Template struct { - fmap FormatterMap // formatters for variables - // Used during parsing: - ldelim, rdelim []byte // delimiters; default {} - buf []byte // input text to process - p int // position in buf - linenum int // position in input - // Parsed results: - elems []interface{} -} - -// New creates a new template with the specified formatter map (which -// may be nil) to define auxiliary functions for formatting variables. -func New(fmap FormatterMap) *Template { - t := new(Template) - t.fmap = fmap - t.ldelim = lbrace - t.rdelim = rbrace - t.elems = make([]interface{}, 0, 16) - return t -} - -// Report error and stop executing. The line number must be provided explicitly. -func (t *Template) execError(st *state, line int, err string, args ...interface{}) { - panic(&Error{line, fmt.Sprintf(err, args...)}) -} - -// Report error, panic to terminate parsing. -// The line number comes from the template state. -func (t *Template) parseError(err string, args ...interface{}) { - panic(&Error{t.linenum, fmt.Sprintf(err, args...)}) + name string + *parse.Tree + // We use two maps, one for parsing and one for execution. + // This separation makes the API cleaner since it doesn't + // expose reflection to the client. + parseFuncs FuncMap + execFuncs map[string]reflect.Value + set *Set // can be nil. } -// Is this an exported - upper case - name? -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) +// Name returns the name of the template. +func (t *Template) Name() string { + return t.name } -// -- Lexical analysis +// Parsing. -// Is c a space character? -func isSpace(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } - -// Safely, does s[n:n+len(t)] == t? -func equal(s []byte, n int, t []byte) bool { - b := s[n:] - if len(t) > len(b) { // not enough space left for a match. - return false - } - for i, c := range t { - if c != b[i] { - return false - } - } - return true -} - -// isQuote returns true if c is a string- or character-delimiting quote character. -func isQuote(c byte) bool { - return c == '"' || c == '`' || c == '\'' -} - -// endQuote returns the end quote index for the quoted string that -// starts at n, or -1 if no matching end quote is found before the end -// of the line. -func endQuote(s []byte, n int) int { - quote := s[n] - for n++; n < len(s); n++ { - switch s[n] { - case '\\': - if quote == '"' || quote == '\'' { - n++ - } - case '\n': - return -1 - case quote: - return n - } - } - return -1 -} - -// nextItem returns the next item from the input buffer. If the returned -// item is empty, we are at EOF. The item will be either a -// delimited string or a non-empty string between delimited -// strings. Tokens stop at (but include, if plain text) a newline. -// Action tokens on a line by themselves drop any space on -// either side, up to and including the newline. -func (t *Template) nextItem() []byte { - startOfLine := t.p == 0 || t.buf[t.p-1] == '\n' - start := t.p - var i int - newline := func() { - t.linenum++ - i++ - } - // Leading space up to but not including newline - for i = start; i < len(t.buf); i++ { - if t.buf[i] == '\n' || !isSpace(t.buf[i]) { - break - } - } - leadingSpace := i > start - // What's left is nothing, newline, delimited string, or plain text - switch { - case i == len(t.buf): - // EOF; nothing to do - case t.buf[i] == '\n': - newline() - case equal(t.buf, i, t.ldelim): - left := i // Start of left delimiter. - right := -1 // Will be (immediately after) right delimiter. - haveText := false // Delimiters contain text. - i += len(t.ldelim) - // Find the end of the action. - for ; i < len(t.buf); i++ { - if t.buf[i] == '\n' { - break - } - if isQuote(t.buf[i]) { - i = endQuote(t.buf, i) - if i == -1 { - t.parseError("unmatched quote") - return nil - } - continue - } - if equal(t.buf, i, t.rdelim) { - i += len(t.rdelim) - right = i - break - } - haveText = true - } - if right < 0 { - t.parseError("unmatched opening delimiter") - return nil - } - // Is this a special action (starts with '.' or '#') and the only thing on the line? - if startOfLine && haveText { - firstChar := t.buf[left+len(t.ldelim)] - if firstChar == '.' || firstChar == '#' { - // It's special and the first thing on the line. Is it the last? - for j := right; j < len(t.buf) && isSpace(t.buf[j]); j++ { - if t.buf[j] == '\n' { - // Yes it is. Drop the surrounding space and return the {.foo} - t.linenum++ - t.p = j + 1 - return t.buf[left:right] - } - } - } - } - // No it's not. If there's leading space, return that. - if leadingSpace { - // not trimming space: return leading space if there is some. - t.p = left - return t.buf[start:left] - } - // Return the word, leave the trailing space. - start = left - break - default: - for ; i < len(t.buf); i++ { - if t.buf[i] == '\n' { - newline() - break - } - if equal(t.buf, i, t.ldelim) { - break - } - } +// New allocates a new template with the given name. +func New(name string) *Template { + return &Template{ + name: name, + parseFuncs: make(FuncMap), + execFuncs: make(map[string]reflect.Value), } - item := t.buf[start:i] - t.p = i - return item } -// Turn a byte array into a space-split array of strings, -// taking into account quoted strings. -func words(buf []byte) []string { - s := make([]string, 0, 5) - for i := 0; i < len(buf); { - // One word per loop - for i < len(buf) && isSpace(buf[i]) { - i++ - } - if i == len(buf) { - break - } - // Got a word - start := i - if isQuote(buf[i]) { - i = endQuote(buf, i) - if i < 0 { - i = len(buf) - } else { - i++ - } - } - // Even with quotes, break on space only. This handles input - // such as {""|} and catches quoting mistakes. - for i < len(buf) && !isSpace(buf[i]) { - i++ - } - s = append(s, string(buf[start:i])) - } - return s -} - -// Analyze an item and return its token type and, if it's an action item, an array of -// its constituent words. -func (t *Template) analyze(item []byte) (tok int, w []string) { - // item is known to be non-empty - if !equal(item, 0, t.ldelim) { // doesn't start with left delimiter - tok = tokText - return - } - if !equal(item, len(item)-len(t.rdelim), t.rdelim) { // doesn't end with right delimiter - t.parseError("internal error: unmatched opening delimiter") // lexing should prevent this - return - } - if len(item) <= len(t.ldelim)+len(t.rdelim) { // no contents - t.parseError("empty directive") - return - } - // Comment - if item[len(t.ldelim)] == '#' { - tok = tokComment - return - } - // Split into words - w = words(item[len(t.ldelim) : len(item)-len(t.rdelim)]) // drop final delimiter - if len(w) == 0 { - t.parseError("empty directive") - return - } - first := w[0] - if first[0] != '.' { - tok = tokVariable - return - } - if len(first) > 1 && first[1] >= '0' && first[1] <= '9' { - // Must be a float. - tok = tokVariable - return - } - switch first { - case ".meta-left", ".meta-right", ".space", ".tab": - tok = tokLiteral - return - case ".or": - tok = tokOr - return - case ".end": - tok = tokEnd - return - case ".section": - if len(w) != 2 { - t.parseError("incorrect fields for .section: %s", item) - return - } - tok = tokSection - return - case ".repeated": - if len(w) != 3 || w[1] != "section" { - t.parseError("incorrect fields for .repeated: %s", item) - return - } - tok = tokRepeated - return - case ".alternates": - if len(w) != 2 || w[1] != "with" { - t.parseError("incorrect fields for .alternates: %s", item) - return - } - tok = tokAlternates - return - } - t.parseError("bad directive: %s", item) - return -} - -// formatter returns the Formatter with the given name in the Template, or nil if none exists. -func (t *Template) formatter(name string) func(io.Writer, string, ...interface{}) { - if t.fmap != nil { - if fn := t.fmap[name]; fn != nil { - return fn - } - } - return builtins[name] -} - -// -- Parsing - -// newVariable allocates a new variable-evaluation element. -func (t *Template) newVariable(words []string) *variableElement { - formatters := extractFormatters(words) - args := make([]interface{}, len(words)) - - // Build argument list, processing any literals - for i, word := range words { - var lerr os.Error - switch word[0] { - case '"', '`', '\'': - v, err := strconv.Unquote(word) - if err == nil && word[0] == '\'' { - args[i] = []int(v)[0] - } else { - args[i], lerr = v, err - } - - case '.', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - v, err := strconv.Btoi64(word, 0) - if err == nil { - args[i] = v - } else { - v, err := strconv.Atof64(word) - args[i], lerr = v, err - } - - default: - args[i] = fieldName(word) - } - if lerr != nil { - t.parseError("invalid literal: %q: %s", word, lerr) - } - } - - // We could remember the function address here and avoid the lookup later, - // but it's more dynamic to let the user change the map contents underfoot. - // We do require the name to be present, though. - - // Is it in user-supplied map? - for _, f := range formatters { - if t.formatter(f) == nil { - t.parseError("unknown formatter: %q", f) - } - } - - return &variableElement{t.linenum, args, formatters} -} - -// extractFormatters extracts a list of formatters from words. -// After the final space-separated argument in a variable, formatters may be -// specified separated by pipe symbols. For example: {a b c|d|e} -// The words parameter still has the formatters joined by '|' in the last word. -// extractFormatters splits formatters, replaces the last word with the content -// found before the first '|' within it, and returns the formatters obtained. -// If no formatters are found in words, the default formatter is returned. -func extractFormatters(words []string) (formatters []string) { - // "" is the default formatter. - formatters = []string{""} - if len(words) == 0 { - return - } - var bar int - lastWord := words[len(words)-1] - if isQuote(lastWord[0]) { - end := endQuote([]byte(lastWord), 0) - if end < 0 || end+1 == len(lastWord) || lastWord[end+1] != '|' { - return - } - bar = end + 1 - } else { - bar = strings.IndexRune(lastWord, '|') - if bar < 0 { - return - } - } - words[len(words)-1] = lastWord[0:bar] - formatters = strings.Split(lastWord[bar+1:], "|") - return -} - -// Grab the next item. If it's simple, just append it to the template. -// Otherwise return its details. -func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) { - tok, w = t.analyze(item) - done = true // assume for simplicity - switch tok { - case tokComment: - return - case tokText: - t.elems = append(t.elems, &textElement{item}) - return - case tokLiteral: - switch w[0] { - case ".meta-left": - t.elems = append(t.elems, &literalElement{t.ldelim}) - case ".meta-right": - t.elems = append(t.elems, &literalElement{t.rdelim}) - case ".space": - t.elems = append(t.elems, &literalElement{space}) - case ".tab": - t.elems = append(t.elems, &literalElement{tab}) - default: - t.parseError("internal error: unknown literal: %s", w[0]) - } - return - case tokVariable: - t.elems = append(t.elems, t.newVariable(w)) - return - } - return false, tok, w -} - -// parseRepeated and parseSection are mutually recursive - -func (t *Template) parseRepeated(words []string) *repeatedElement { - r := new(repeatedElement) - t.elems = append(t.elems, r) - r.linenum = t.linenum - r.field = words[2] - // Scan section, collecting true and false (.or) blocks. - r.start = len(t.elems) - r.or = -1 - r.altstart = -1 - r.altend = -1 -Loop: - for { - item := t.nextItem() - if len(item) == 0 { - t.parseError("missing .end for .repeated section") - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokEnd: - break Loop - case tokOr: - if r.or >= 0 { - t.parseError("extra .or in .repeated section") - break Loop - } - r.altend = len(t.elems) - r.or = len(t.elems) - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - case tokAlternates: - if r.altstart >= 0 { - t.parseError("extra .alternates in .repeated section") - break Loop - } - if r.or >= 0 { - t.parseError(".alternates inside .or block in .repeated section") - break Loop - } - r.altstart = len(t.elems) - default: - t.parseError("internal error: unknown repeated section item: %s", item) - break Loop - } - } - if r.altend < 0 { - r.altend = len(t.elems) - } - r.end = len(t.elems) - return r -} - -func (t *Template) parseSection(words []string) *sectionElement { - s := new(sectionElement) - t.elems = append(t.elems, s) - s.linenum = t.linenum - s.field = words[1] - // Scan section, collecting true and false (.or) blocks. - s.start = len(t.elems) - s.or = -1 -Loop: - for { - item := t.nextItem() - if len(item) == 0 { - t.parseError("missing .end for .section") - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokEnd: - break Loop - case tokOr: - if s.or >= 0 { - t.parseError("extra .or in .section") - break Loop - } - s.or = len(t.elems) - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - case tokAlternates: - t.parseError(".alternates not in .repeated") - default: - t.parseError("internal error: unknown section item: %s", item) - } - } - s.end = len(t.elems) - return s -} - -func (t *Template) parse() { - for { - item := t.nextItem() - if len(item) == 0 { - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokOr, tokEnd, tokAlternates: - t.parseError("unexpected %s", w[0]) - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - default: - t.parseError("internal error: bad directive in parse: %s", item) - } - } -} - -// -- Execution - -// -- Public interface - -// Parse initializes a Template by parsing its definition. The string -// s contains the template text. If any errors occur, Parse returns -// the error. -func (t *Template) Parse(s string) (err os.Error) { - if t.elems == nil { - return &Error{1, "template not allocated with New"} - } - if !validDelim(t.ldelim) || !validDelim(t.rdelim) { - return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)} - } - defer checkError(&err) - t.buf = []byte(s) - t.p = 0 - t.linenum = 1 - t.parse() - return nil +// Funcs adds the elements of the argument map to the template's function +// map. It panics if a value in the map is not a function with appropriate +// return type. +// The return value is the template, so calls can be chained. +func (t *Template) Funcs(funcMap FuncMap) *Template { + addValueFuncs(t.execFuncs, funcMap) + addFuncs(t.parseFuncs, funcMap) + return t } -// ParseFile is like Parse but reads the template definition from the -// named file. -func (t *Template) ParseFile(filename string) (err os.Error) { - b, err := ioutil.ReadFile(filename) +// Parse parses the template definition string to construct an internal +// representation of the template for execution. +func (t *Template) Parse(s string) (tmpl *Template, err os.Error) { + t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, builtins) if err != nil { - return err + return nil, err } - return t.Parse(string(b)) -} - -// Execute applies a parsed template to the specified data object, -// generating output to wr. -func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) { - // Extract the driver data. - val := reflect.ValueOf(data) - defer checkError(&err) - t.p = 0 - t.execute(0, len(t.elems), &state{parent: nil, data: val, wr: wr}) - return nil -} - -// SetDelims sets the left and right delimiters for operations in the -// template. They are validated during parsing. They could be -// validated here but it's better to keep the routine simple. The -// delimiters are very rarely invalid and Parse has the necessary -// error-handling interface already. -func (t *Template) SetDelims(left, right string) { - t.ldelim = []byte(left) - t.rdelim = []byte(right) + return t, nil } -// Parse creates a Template with default parameters (such as {} for -// metacharacters). The string s contains the template text while -// the formatter map fmap, which may be nil, defines auxiliary functions -// for formatting variables. The template is returned. If any errors -// occur, err will be non-nil. -func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) { - t = New(fmap) - err = t.Parse(s) - if err != nil { - t = nil +// ParseInSet parses the template definition string to construct an internal +// representation of the template for execution. It also adds the template +// to the set. +// Function bindings are checked against those in the set. +func (t *Template) ParseInSet(s string, set *Set) (tmpl *Template, err os.Error) { + var setFuncs FuncMap + if set != nil { + setFuncs = set.parseFuncs } - return -} - -// ParseFile is a wrapper function that creates a Template with default -// parameters (such as {} for metacharacters). The filename identifies -// a file containing the template text, while the formatter map fmap, which -// may be nil, defines auxiliary functions for formatting variables. -// The template is returned. If any errors occur, err will be non-nil. -func ParseFile(filename string, fmap FormatterMap) (t *Template, err os.Error) { - b, err := ioutil.ReadFile(filename) + t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, setFuncs, builtins) if err != nil { return nil, err } - return Parse(string(b), fmap) + t.addToSet(set) + return t, nil } -// MustParse is like Parse but panics if the template cannot be parsed. -func MustParse(s string, fmap FormatterMap) *Template { - t, err := Parse(s, fmap) - if err != nil { - panic("template.MustParse error: " + err.String()) - } - return t -} - -// MustParseFile is like ParseFile but panics if the file cannot be read -// or the template cannot be parsed. -func MustParseFile(filename string, fmap FormatterMap) *Template { - b, err := ioutil.ReadFile(filename) - if err != nil { - panic("template.MustParseFile error: " + err.String()) +// addToSet adds the template to the set, verifying it's not being double-assigned. +func (t *Template) addToSet(set *Set) { + if set == nil || t.set == set { + return } - return MustParse(string(b), fmap) + // If double-assigned, Add will panic and we will turn that into an error. + set.Add(t) } diff --git a/src/pkg/exp/template/Makefile b/src/pkg/template/parse/Makefile index 06df9b659..fe6585809 100644 --- a/src/pkg/exp/template/Makefile +++ b/src/pkg/template/parse/Makefile @@ -4,11 +4,10 @@ include ../../../Make.inc -TARG=exp/template +TARG=template/parse GOFILES=\ - exec.go\ - funcs.go\ - helper.go\ + lex.go\ + node.go\ parse.go\ set.go\ diff --git a/src/pkg/exp/template/parse/lex.go b/src/pkg/template/parse/lex.go index 7ec4e920b..7ec4e920b 100644 --- a/src/pkg/exp/template/parse/lex.go +++ b/src/pkg/template/parse/lex.go diff --git a/src/pkg/exp/template/parse/lex_test.go b/src/pkg/template/parse/lex_test.go index 2ad91d5fa..2ad91d5fa 100644 --- a/src/pkg/exp/template/parse/lex_test.go +++ b/src/pkg/template/parse/lex_test.go diff --git a/src/pkg/exp/template/parse/node.go b/src/pkg/template/parse/node.go index 0f77ad850..a917418dc 100644 --- a/src/pkg/exp/template/parse/node.go +++ b/src/pkg/template/parse/node.go @@ -31,14 +31,14 @@ func (t NodeType) Type() NodeType { const ( NodeText NodeType = iota // Plain text. - NodeAction // An simple action such as field evaluation. + NodeAction // A simple action such as field evaluation. NodeBool // A boolean constant. NodeCommand // An element of a pipeline. NodeDot // The cursor, dot. NodeElse // An else action. NodeEnd // An end action. NodeField // A field or method name. - NodeIdentifier // A identifier; always a function name. + NodeIdentifier // An identifier; always a function name. NodeIf // An if action. NodeList // A list of Nodes. NodeNumber // A numerical constant. @@ -154,7 +154,8 @@ type IdentifierNode struct { Ident string // The identifier's name. } -func newIdentifier(ident string) *IdentifierNode { +// NewIdentifier returns a new IdentifierNode with the given identifier name. +func NewIdentifier(ident string) *IdentifierNode { return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident} } diff --git a/src/pkg/exp/template/parse/parse.go b/src/pkg/template/parse/parse.go index f8f9023e5..9a411a3f3 100644 --- a/src/pkg/exp/template/parse/parse.go +++ b/src/pkg/template/parse/parse.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package parse builds parse trees for templates. The grammar is defined -// in the documents for the exp/template package. +// in the documents for the template package. package parse import ( @@ -373,7 +373,7 @@ Loop: if !t.hasFunction(token.val) { t.errorf("function %q not defined", token.val) } - cmd.append(newIdentifier(token.val)) + cmd.append(NewIdentifier(token.val)) case itemDot: cmd.append(newDot()) case itemVariable: diff --git a/src/pkg/exp/template/parse/parse_test.go b/src/pkg/template/parse/parse_test.go index 1928c319d..1928c319d 100644 --- a/src/pkg/exp/template/parse/parse_test.go +++ b/src/pkg/template/parse/parse_test.go diff --git a/src/pkg/exp/template/parse/set.go b/src/pkg/template/parse/set.go index 4820da925..4820da925 100644 --- a/src/pkg/exp/template/parse/set.go +++ b/src/pkg/template/parse/set.go diff --git a/src/pkg/exp/template/set.go b/src/pkg/template/set.go index 7f2813c04..f778fd169 100644 --- a/src/pkg/exp/template/set.go +++ b/src/pkg/template/set.go @@ -5,11 +5,11 @@ package template import ( - "exp/template/parse" "fmt" "io" "os" "reflect" + "template/parse" ) // Set holds a set of related templates that can refer to one another by name. diff --git a/src/pkg/exp/template/set_test.go b/src/pkg/template/set_test.go index 6fa29063b..f437bc779 100644 --- a/src/pkg/exp/template/set_test.go +++ b/src/pkg/template/set_test.go @@ -120,58 +120,58 @@ func TestSetExecute(t *testing.T) { testExecute(setExecTests, set, t) } -func TestSetParseFile(t *testing.T) { +func TestSetParseFiles(t *testing.T) { set := new(Set) - _, err := set.ParseFile("DOES NOT EXIST") + _, err := set.ParseFiles("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - _, err = set.ParseFile("testdata/file1.tmpl", "testdata/file2.tmpl") + _, err = set.ParseFiles("testdata/file1.tmpl", "testdata/file2.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } testExecute(setExecTests, set, t) } -func TestParseSetFile(t *testing.T) { +func TestParseSetFiles(t *testing.T) { set := new(Set) - _, err := ParseSetFile("DOES NOT EXIST") + _, err := ParseSetFiles("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - set, err = ParseSetFile("testdata/file1.tmpl", "testdata/file2.tmpl") + set, err = ParseSetFiles("testdata/file1.tmpl", "testdata/file2.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } testExecute(setExecTests, set, t) } -func TestSetParseFiles(t *testing.T) { - _, err := new(Set).ParseFiles("DOES NOT EXIST") +func TestSetParseGlob(t *testing.T) { + _, err := new(Set).ParseGlob("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - _, err = new(Set).ParseFiles("[x") + _, err = new(Set).ParseGlob("[x") if err == nil { t.Error("expected error for bad pattern; got none") } - set, err := new(Set).ParseFiles("testdata/file*.tmpl") + set, err := new(Set).ParseGlob("testdata/file*.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } testExecute(setExecTests, set, t) } -func TestParseSetFiles(t *testing.T) { - _, err := ParseSetFiles("DOES NOT EXIST") +func TestParseSetGlob(t *testing.T) { + _, err := ParseSetGlob("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - _, err = ParseSetFiles("[x") + _, err = ParseSetGlob("[x") if err == nil { t.Error("expected error for bad pattern; got none") } - set, err := ParseSetFiles("testdata/file*.tmpl") + set, err := ParseSetGlob("testdata/file*.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } @@ -182,56 +182,56 @@ var templateFileExecTests = []execTest{ {"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\ntemplate2\n", 0, true}, } -func TestSetParseTemplateFile(t *testing.T) { - _, err := ParseTemplateFile("DOES NOT EXIST") +func TestSetParseTemplateFiles(t *testing.T) { + _, err := ParseTemplateFiles("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - set, err := new(Set).ParseTemplateFile("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") + set, err := new(Set).ParseTemplateFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } testExecute(templateFileExecTests, set, t) } -func TestParseTemplateFile(t *testing.T) { - _, err := ParseTemplateFile("DOES NOT EXIST") +func TestParseTemplateFiles(t *testing.T) { + _, err := ParseTemplateFiles("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - set, err := new(Set).ParseTemplateFile("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") + set, err := new(Set).ParseTemplateFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } testExecute(templateFileExecTests, set, t) } -func TestSetParseTemplateFiles(t *testing.T) { - _, err := ParseTemplateFiles("DOES NOT EXIST") +func TestSetParseTemplateGlob(t *testing.T) { + _, err := ParseTemplateGlob("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - _, err = new(Set).ParseTemplateFiles("[x") + _, err = new(Set).ParseTemplateGlob("[x") if err == nil { t.Error("expected error for bad pattern; got none") } - set, err := new(Set).ParseTemplateFiles("testdata/tmpl*.tmpl") + set, err := new(Set).ParseTemplateGlob("testdata/tmpl*.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } testExecute(templateFileExecTests, set, t) } -func TestParseTemplateFiles(t *testing.T) { - _, err := ParseTemplateFiles("DOES NOT EXIST") +func TestParseTemplateGlob(t *testing.T) { + _, err := ParseTemplateGlob("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - _, err = ParseTemplateFiles("[x") + _, err = ParseTemplateGlob("[x") if err == nil { t.Error("expected error for bad pattern; got none") } - set, err := ParseTemplateFiles("testdata/tmpl*.tmpl") + set, err := ParseTemplateGlob("testdata/tmpl*.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } diff --git a/src/pkg/exp/template/testdata/file1.tmpl b/src/pkg/template/testdata/file1.tmpl index febf9d9f8..febf9d9f8 100644 --- a/src/pkg/exp/template/testdata/file1.tmpl +++ b/src/pkg/template/testdata/file1.tmpl diff --git a/src/pkg/exp/template/testdata/file2.tmpl b/src/pkg/template/testdata/file2.tmpl index 39bf6fb9e..39bf6fb9e 100644 --- a/src/pkg/exp/template/testdata/file2.tmpl +++ b/src/pkg/template/testdata/file2.tmpl diff --git a/src/pkg/exp/template/testdata/tmpl1.tmpl b/src/pkg/template/testdata/tmpl1.tmpl index 3d15b8173..3d15b8173 100644 --- a/src/pkg/exp/template/testdata/tmpl1.tmpl +++ b/src/pkg/template/testdata/tmpl1.tmpl diff --git a/src/pkg/exp/template/testdata/tmpl2.tmpl b/src/pkg/template/testdata/tmpl2.tmpl index a374d2fe7..a374d2fe7 100644 --- a/src/pkg/exp/template/testdata/tmpl2.tmpl +++ b/src/pkg/template/testdata/tmpl2.tmpl diff --git a/src/pkg/time/Makefile b/src/pkg/time/Makefile index 023e8775e..a6fce3fa1 100644 --- a/src/pkg/time/Makefile +++ b/src/pkg/time/Makefile @@ -27,6 +27,11 @@ GOFILES_linux=\ zoneinfo_posix.go\ zoneinfo_unix.go\ +GOFILES_openbsd=\ + sys_posix.go\ + zoneinfo_posix.go\ + zoneinfo_unix.go\ + GOFILES_windows=\ sys_posix.go\ zoneinfo_windows.go\ diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go index 3c42f0c2d..5ddd54812 100644 --- a/src/pkg/time/format.go +++ b/src/pkg/time/format.go @@ -26,8 +26,11 @@ const ( // replaced by a digit if the following number (a day) has two digits; for // compatibility with fixed-width Unix time formats. // -// A decimal point followed by one or more zeros represents a -// fractional second. +// A decimal point followed by one or more zeros represents a fractional +// second. When parsing (only), the input may contain a fractional second +// field immediately after the seconds field, even if the layout does not +// signify its presence. In that case a decimal point followed by a maximal +// series of digits is parsed as a fractional second. // // Numeric time zone offsets format as follows: // -0700 ±hhmm @@ -169,7 +172,7 @@ func nextStdChunk(layout string) (prefix, std, suffix string) { numZeros++ } // String of digits must end here - only fractional second is all zeros. - if numZeros > 0 && (j >= len(layout) || layout[j] < '0' || '9' < layout[j]) { + if numZeros > 0 && !isDigit(layout, j) { return layout[0:i], layout[i : i+1+numZeros], layout[i+1+numZeros:] } } @@ -416,14 +419,24 @@ func (e *ParseError) String() string { strconv.Quote(e.Value) + e.Message } +// isDigit returns true if s[i] is a decimal digit, false if not or +// if s[i] is out of range. +func isDigit(s string, i int) bool { + if len(s) <= i { + return false + } + c := s[i] + return '0' <= c && c <= '9' +} + // getnum parses s[0:1] or s[0:2] (fixed forces the latter) // as a decimal integer and returns the integer and the // remainder of the string. func getnum(s string, fixed bool) (int, string, os.Error) { - if len(s) == 0 || s[0] < '0' || s[0] > '9' { + if !isDigit(s, 0) { return 0, s, errBad } - if len(s) == 1 || s[1] < '0' || s[1] > '9' { + if !isDigit(s, 1) { if fixed { return 0, s, errBad } @@ -509,7 +522,7 @@ func Parse(alayout, avalue string) (*Time, os.Error) { t.Year += 2000 } case stdLongYear: - if len(value) < 4 || value[0] < '0' || value[0] > '9' { + if len(value) < 4 || !isDigit(value, 0) { err = errBad break } @@ -557,6 +570,21 @@ func Parse(alayout, avalue string) (*Time, os.Error) { if t.Second < 0 || 60 <= t.Second { rangeErrString = "second" } + // Special case: do we have a fractional second but no + // fractional second in the format? + if len(value) > 2 && value[0] == '.' && isDigit(value, 1) { + _, std, _ := nextStdChunk(layout) + if len(std) > 0 && std[0] == '.' && isDigit(std, 1) { + // Fractional second in the layout; proceed normally + break + } + // No fractional second in the layout but we have one in the input. + n := 2 + for ; n < len(value) && isDigit(value, n); n++ { + } + rangeErrString, err = t.parseNanoseconds(value, n) + value = value[n:] + } case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ: if std[0] == 'Z' && len(value) >= 1 && value[0] == 'Z' { value = value[1:] @@ -663,26 +691,8 @@ func Parse(alayout, avalue string) (*Time, os.Error) { break } if len(std) >= 2 && std[0:2] == ".0" { - if value[0] != '.' { - err = errBad - break - } - t.Nanosecond, err = strconv.Atoi(value[1:len(std)]) - if err != nil { - break - } - if t.Nanosecond < 0 || t.Nanosecond >= 1e9 { - rangeErrString = "fractional second" - break - } + rangeErrString, err = t.parseNanoseconds(value, len(std)) value = value[len(std):] - // We need nanoseconds, which means scaling by the number - // of missing digits in the format, maximum length 10. If it's - // longer than 10, we won't scale. - scaleDigits := 10 - len(std) - for i := 0; i < scaleDigits; i++ { - t.Nanosecond *= 10 - } } } if rangeErrString != "" { @@ -699,3 +709,26 @@ func Parse(alayout, avalue string) (*Time, os.Error) { } return &t, nil } + +func (t *Time) parseNanoseconds(value string, nbytes int) (rangErrString string, err os.Error) { + if value[0] != '.' { + return "", errBad + } + var ns int + ns, err = strconv.Atoi(value[1:nbytes]) + if err != nil { + return "", err + } + if ns < 0 || 1e9 <= ns { + return "fractional second", nil + } + // We need nanoseconds, which means scaling by the number + // of missing digits in the format, maximum length 10. If it's + // longer than 10, we won't scale. + scaleDigits := 10 - nbytes + for i := 0; i < scaleDigits; i++ { + ns *= 10 + } + t.Nanosecond = ns + return +} diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go index 4999f4536..dceed491a 100644 --- a/src/pkg/time/time_test.go +++ b/src/pkg/time/time_test.go @@ -250,6 +250,13 @@ var parseTests = []ParseTest{ {"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true, 1, 0}, {"RFC3339", RFC3339, "2010-02-04T21:00:57-08:00", true, false, 1, 0}, {"custom: \"2006-01-02 15:04:05-07\"", "2006-01-02 15:04:05-07", "2010-02-04 21:00:57-08", true, false, 1, 0}, + // Optional fractional seconds. + {"ANSIC", ANSIC, "Thu Feb 4 21:00:57.0 2010", false, true, 1, 1}, + {"UnixDate", UnixDate, "Thu Feb 4 21:00:57.01 PST 2010", true, true, 1, 2}, + {"RubyDate", RubyDate, "Thu Feb 04 21:00:57.012 -0800 2010", true, true, 1, 3}, + {"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57.0123 PST", true, true, 1, 4}, + {"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57.01234 PST", true, true, 1, 5}, + {"RFC3339", RFC3339, "2010-02-04T21:00:57.012345678-08:00", true, false, 1, 9}, // Amount of white space should not matter. {"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0}, {"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0}, diff --git a/src/pkg/url/Makefile b/src/pkg/url/Makefile new file mode 100644 index 000000000..b9267bd08 --- /dev/null +++ b/src/pkg/url/Makefile @@ -0,0 +1,11 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include ../../Make.inc + +TARG=url +GOFILES=\ + url.go\ + +include ../../Make.pkg diff --git a/src/pkg/http/url.go b/src/pkg/url/url.go index b38585ac2..d07b01611 100644 --- a/src/pkg/http/url.go +++ b/src/pkg/url/url.go @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Parse URLs (actually URIs, but that seems overly pedantic). -// RFC 3986 - -package http +// Package URL parses URLs and implements query escaping. +// See RFC 3986. +package url import ( "os" @@ -13,14 +12,14 @@ import ( "strings" ) -// URLError reports an error and the operation and URL that caused it. -type URLError struct { +// Error reports an error and the operation and URL that caused it. +type Error struct { Op string URL string Error os.Error } -func (e *URLError) String() string { return e.Op + " " + e.URL + ": " + e.Error.String() } +func (e *Error) String() string { return e.Op + " " + e.URL + ": " + e.Error.String() } func ishex(c byte) bool { switch { @@ -56,9 +55,9 @@ const ( encodeOpaque ) -type URLEscapeError string +type EscapeError string -func (e URLEscapeError) String() string { +func (e EscapeError) String() string { return "invalid URL escape " + strconv.Quote(string(e)) } @@ -113,19 +112,16 @@ func shouldEscape(c byte, mode encoding) bool { return true } -// URLUnescape unescapes a string in ``URL encoded'' form, -// converting %AB into the byte 0xAB and '+' into ' ' (space). -// It returns an error if any % is not followed -// by two hexadecimal digits. -// Despite the name, this encoding applies only to individual -// components of the query portion of the URL. -func URLUnescape(s string) (string, os.Error) { - return urlUnescape(s, encodeQueryComponent) +// QueryUnescape does the inverse transformation of QueryEscape, converting +// %AB into the byte 0xAB and '+' into ' ' (space). It returns an error if +// any % is not followed by two hexadecimal digits. +func QueryUnescape(s string) (string, os.Error) { + return unescape(s, encodeQueryComponent) } -// urlUnescape is like URLUnescape but mode specifies -// which section of the URL is being unescaped. -func urlUnescape(s string, mode encoding) (string, os.Error) { +// unescape unescapes a string; the mode specifies +// which section of the URL string is being unescaped. +func unescape(s string, mode encoding) (string, os.Error) { // Count %, check that they're well-formed. n := 0 hasPlus := false @@ -138,7 +134,7 @@ func urlUnescape(s string, mode encoding) (string, os.Error) { if len(s) > 3 { s = s[0:3] } - return "", URLEscapeError(s) + return "", EscapeError(s) } i += 3 case '+': @@ -178,14 +174,13 @@ func urlUnescape(s string, mode encoding) (string, os.Error) { return string(t), nil } -// URLEscape converts a string into ``URL encoded'' form. -// Despite the name, this encoding applies only to individual -// components of the query portion of the URL. -func URLEscape(s string) string { - return urlEscape(s, encodeQueryComponent) +// QueryEscape escapes the string so it can be safely placed +// inside a URL query. +func QueryEscape(s string) string { + return escape(s, encodeQueryComponent) } -func urlEscape(s string, mode encoding) string { +func escape(s string, mode encoding) string { spaceCount, hexCount := 0, 0 for i := 0; i < len(s); i++ { c := s[i] @@ -233,10 +228,10 @@ func urlEscape(s string, mode encoding) string { // security risk in almost every case where it has been used.'' func UnescapeUserinfo(rawUserinfo string) (user, password string, err os.Error) { u, p := split(rawUserinfo, ':', true) - if user, err = urlUnescape(u, encodeUserPassword); err != nil { + if user, err = unescape(u, encodeUserPassword); err != nil { return "", "", err } - if password, err = urlUnescape(p, encodeUserPassword); err != nil { + if password, err = unescape(p, encodeUserPassword); err != nil { return "", "", err } return @@ -252,9 +247,9 @@ func UnescapeUserinfo(rawUserinfo string) (user, password string, err os.Error) // information in clear text (such as URI) has proven to be a // security risk in almost every case where it has been used.'' func EscapeUserinfo(user, password string) string { - raw := urlEscape(user, encodeUserPassword) + raw := escape(user, encodeUserPassword) if password != "" { - raw += ":" + urlEscape(password, encodeUserPassword) + raw += ":" + escape(password, encodeUserPassword) } return raw } @@ -324,28 +319,28 @@ func split(s string, c byte, cutc bool) (string, string) { return s, "" } -// ParseURL parses rawurl into a URL structure. +// Parse parses rawurl into a URL structure. // The string rawurl is assumed not to have a #fragment suffix. // (Web browsers strip #fragment before sending the URL to a web server.) // The rawurl may be relative or absolute. -func ParseURL(rawurl string) (url *URL, err os.Error) { - return parseURL(rawurl, false) +func Parse(rawurl string) (url *URL, err os.Error) { + return parse(rawurl, false) } -// ParseRequestURL parses rawurl into a URL structure. It assumes that +// ParseRequest parses rawurl into a URL structure. It assumes that // rawurl was received from an HTTP request, so the rawurl is interpreted // only as an absolute URI or an absolute path. // The string rawurl is assumed not to have a #fragment suffix. // (Web browsers strip #fragment before sending the URL to a web server.) -func ParseRequestURL(rawurl string) (url *URL, err os.Error) { - return parseURL(rawurl, true) +func ParseRequest(rawurl string) (url *URL, err os.Error) { + return parse(rawurl, true) } -// parseURL parses a URL from a string in one of two contexts. If +// parse parses a URL from a string in one of two contexts. If // viaRequest is true, the URL is assumed to have arrived via an HTTP request, // in which case only absolute URLs or path-absolute relative URLs are allowed. // If viaRequest is false, all forms of relative URLs are allowed. -func parseURL(rawurl string, viaRequest bool) (url *URL, err os.Error) { +func parse(rawurl string, viaRequest bool) (url *URL, err os.Error) { var ( leadingSlash bool path string @@ -372,7 +367,7 @@ func parseURL(rawurl string, viaRequest bool) (url *URL, err os.Error) { // This is the case that handles mailto:name@example.com. url.RawPath = path - if url.Path, err = urlUnescape(path, encodeOpaque); err != nil { + if url.Path, err = unescape(path, encodeOpaque); err != nil { goto Error } url.OpaquePath = true @@ -417,30 +412,30 @@ func parseURL(rawurl string, viaRequest bool) (url *URL, err os.Error) { } url.Host = rawHost - if url.Path, err = urlUnescape(path, encodePath); err != nil { + if url.Path, err = unescape(path, encodePath); err != nil { goto Error } } return url, nil Error: - return nil, &URLError{"parse", rawurl, err} + return nil, &Error{"parse", rawurl, err} } -// ParseURLReference is like ParseURL but allows a trailing #fragment. -func ParseURLReference(rawurlref string) (url *URL, err os.Error) { +// ParseWithReference is like Parse but allows a trailing #fragment. +func ParseWithReference(rawurlref string) (url *URL, err os.Error) { // Cut off #frag. rawurl, frag := split(rawurlref, '#', false) - if url, err = ParseURL(rawurl); err != nil { + if url, err = Parse(rawurl); err != nil { return nil, err } url.Raw += frag url.RawPath += frag if len(frag) > 1 { frag = frag[1:] - if url.Fragment, err = urlUnescape(frag, encodeFragment); err != nil { - return nil, &URLError{"parse", rawurl, err} + if url.Fragment, err = unescape(frag, encodeFragment); err != nil { + return nil, &Error{"parse", rawurl, err} } } return url, nil @@ -474,19 +469,90 @@ func (url *URL) String() string { result += "%2f" path = path[1:] } - result += urlEscape(path, encodeOpaque) + result += escape(path, encodeOpaque) } else { - result += urlEscape(url.Path, encodePath) + result += escape(url.Path, encodePath) } if url.RawQuery != "" { result += "?" + url.RawQuery } if url.Fragment != "" { - result += "#" + urlEscape(url.Fragment, encodeFragment) + result += "#" + escape(url.Fragment, encodeFragment) } return result } +// Values maps a string key to a list of values. +// It is typically used for query parameters and form values. +// Unlike in the http.Header map, the keys in a Values map +// are case-sensitive. +type Values map[string][]string + +// Get gets the first value associated with the given key. +// If there are no values associated with the key, Get returns +// the empty string. To access multiple values, use the map +// directly. +func (v Values) Get(key string) string { + if v == nil { + return "" + } + vs, ok := v[key] + if !ok || len(vs) == 0 { + return "" + } + return vs[0] +} + +// Set sets the key to value. It replaces any existing +// values. +func (v Values) Set(key, value string) { + v[key] = []string{value} +} + +// Add adds the key to value. It appends to any existing +// values associated with key. +func (v Values) Add(key, value string) { + v[key] = append(v[key], value) +} + +// Del deletes the values associated with key. +func (v Values) Del(key string) { + v[key] = nil, false +} + +// ParseQuery parses the URL-encoded query string and returns +// a map listing the values specified for each key. +// ParseQuery always returns a non-nil map containing all the +// valid query parameters found; err describes the first decoding error +// encountered, if any. +func ParseQuery(query string) (m Values, err os.Error) { + m = make(Values) + err = parseQuery(m, query) + return +} + +func parseQuery(m Values, query string) (err os.Error) { + for _, kv := range strings.Split(query, "&") { + if len(kv) == 0 { + continue + } + kvPair := strings.SplitN(kv, "=", 2) + + var key, value string + var e os.Error + key, e = QueryUnescape(kvPair[0]) + if e == nil && len(kvPair) > 1 { + value, e = QueryUnescape(kvPair[1]) + } + if e != nil { + err = e + continue + } + m[key] = append(m[key], value) + } + return err +} + // Encode encodes the values into ``URL encoded'' form. // e.g. "foo=bar&bar=baz" func (v Values) Encode() string { @@ -495,9 +561,9 @@ func (v Values) Encode() string { } parts := make([]string, 0, len(v)) // will be large enough for most uses for k, vs := range v { - prefix := URLEscape(k) + "=" + prefix := QueryEscape(k) + "=" for _, v := range vs { - parts = append(parts, prefix+URLEscape(v)) + parts = append(parts, prefix+QueryEscape(v)) } } return strings.Join(parts, "&") @@ -538,11 +604,11 @@ func (url *URL) IsAbs() bool { return url.Scheme != "" } -// ParseURL parses a URL in the context of a base URL. The URL in ref -// may be relative or absolute. ParseURL returns nil, err on parse +// Parse parses a URL in the context of a base URL. The URL in ref +// may be relative or absolute. Parse returns nil, err on parse // failure, otherwise its return value is the same as ResolveReference. -func (base *URL) ParseURL(ref string) (*URL, os.Error) { - refurl, err := ParseURL(ref) +func (base *URL) Parse(ref string) (*URL, os.Error) { + refurl, err := Parse(ref) if err != nil { return nil, err } @@ -604,3 +670,8 @@ func (u *URL) Query() Values { v, _ := ParseQuery(u.RawQuery) return v } + +// EncodedPath returns the URL's path in "URL path encoded" form. +func (u *URL) EncodedPath() string { + return escape(u.Path, encodePath) +} diff --git a/src/pkg/http/url_test.go b/src/pkg/url/url_test.go index eaec5872a..af394d4fb 100644 --- a/src/pkg/http/url_test.go +++ b/src/pkg/url/url_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package http +package url import ( "fmt" @@ -12,9 +12,9 @@ import ( ) // TODO(rsc): -// test URLUnescape -// test URLEscape -// test ParseURL +// test Unescape +// test Escape +// test Parse type URLTest struct { in string @@ -218,7 +218,7 @@ var urltests = []URLTest{ }, // Three leading slashes isn't an authority, but doesn't return an error. // (We can't return an error, as this code is also used via - // ServeHTTP -> ReadRequest -> ParseURL, which is arguably a + // ServeHTTP -> ReadRequest -> Parse, which is arguably a // different URL parsing context, but currently shares the // same codepath) { @@ -325,14 +325,14 @@ func DoTest(t *testing.T, parse func(string) (*URL, os.Error), name string, test } } -func TestParseURL(t *testing.T) { - DoTest(t, ParseURL, "ParseURL", urltests) - DoTest(t, ParseURL, "ParseURL", urlnofragtests) +func TestParse(t *testing.T) { + DoTest(t, Parse, "Parse", urltests) + DoTest(t, Parse, "Parse", urlnofragtests) } -func TestParseURLReference(t *testing.T) { - DoTest(t, ParseURLReference, "ParseURLReference", urltests) - DoTest(t, ParseURLReference, "ParseURLReference", urlfragtests) +func TestParseWithReference(t *testing.T) { + DoTest(t, ParseWithReference, "ParseWithReference", urltests) + DoTest(t, ParseWithReference, "ParseWithReference", urlfragtests) } const pathThatLooksSchemeRelative = "//not.a.user@not.a.host/just/a/path" @@ -351,16 +351,16 @@ var parseRequestUrlTests = []struct { {"../dir/", false}, } -func TestParseRequestURL(t *testing.T) { +func TestParseRequest(t *testing.T) { for _, test := range parseRequestUrlTests { - _, err := ParseRequestURL(test.url) + _, err := ParseRequest(test.url) valid := err == nil if valid != test.expectedValid { t.Errorf("Expected valid=%v for %q; got %v", test.expectedValid, test.url, valid) } } - url, err := ParseRequestURL(pathThatLooksSchemeRelative) + url, err := ParseRequest(pathThatLooksSchemeRelative) if err != nil { t.Fatalf("Unexpected error %v", err) } @@ -388,19 +388,19 @@ func DoTestString(t *testing.T, parse func(string) (*URL, os.Error), name string } func TestURLString(t *testing.T) { - DoTestString(t, ParseURL, "ParseURL", urltests) - DoTestString(t, ParseURL, "ParseURL", urlnofragtests) - DoTestString(t, ParseURLReference, "ParseURLReference", urltests) - DoTestString(t, ParseURLReference, "ParseURLReference", urlfragtests) + DoTestString(t, Parse, "Parse", urltests) + DoTestString(t, Parse, "Parse", urlnofragtests) + DoTestString(t, ParseWithReference, "ParseWithReference", urltests) + DoTestString(t, ParseWithReference, "ParseWithReference", urlfragtests) } -type URLEscapeTest struct { +type EscapeTest struct { in string out string err os.Error } -var unescapeTests = []URLEscapeTest{ +var unescapeTests = []EscapeTest{ { "", "", @@ -434,40 +434,40 @@ var unescapeTests = []URLEscapeTest{ { "%", // not enough characters after % "", - URLEscapeError("%"), + EscapeError("%"), }, { "%a", // not enough characters after % "", - URLEscapeError("%a"), + EscapeError("%a"), }, { "%1", // not enough characters after % "", - URLEscapeError("%1"), + EscapeError("%1"), }, { "123%45%6", // not enough characters after % "", - URLEscapeError("%6"), + EscapeError("%6"), }, { "%zzzzz", // invalid hex digits "", - URLEscapeError("%zz"), + EscapeError("%zz"), }, } -func TestURLUnescape(t *testing.T) { +func TestUnescape(t *testing.T) { for _, tt := range unescapeTests { - actual, err := URLUnescape(tt.in) + actual, err := QueryUnescape(tt.in) if actual != tt.out || (err != nil) != (tt.err != nil) { - t.Errorf("URLUnescape(%q) = %q, %s; want %q, %s", tt.in, actual, err, tt.out, tt.err) + t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", tt.in, actual, err, tt.out, tt.err) } } } -var escapeTests = []URLEscapeTest{ +var escapeTests = []EscapeTest{ { "", "", @@ -495,17 +495,17 @@ var escapeTests = []URLEscapeTest{ }, } -func TestURLEscape(t *testing.T) { +func TestEscape(t *testing.T) { for _, tt := range escapeTests { - actual := URLEscape(tt.in) + actual := QueryEscape(tt.in) if tt.out != actual { - t.Errorf("URLEscape(%q) = %q, want %q", tt.in, actual, tt.out) + t.Errorf("QueryEscape(%q) = %q, want %q", tt.in, actual, tt.out) } // for bonus points, verify that escape:unescape is an identity. - roundtrip, err := URLUnescape(actual) + roundtrip, err := QueryUnescape(actual) if roundtrip != tt.in || err != nil { - t.Errorf("URLUnescape(%q) = %q, %s; want %q, %s", actual, roundtrip, err, tt.in, "[no error]") + t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", actual, roundtrip, err, tt.in, "[no error]") } } } @@ -629,16 +629,16 @@ var resolveReferenceTests = []struct { } func TestResolveReference(t *testing.T) { - mustParseURL := func(url string) *URL { - u, err := ParseURLReference(url) + mustParse := func(url string) *URL { + u, err := ParseWithReference(url) if err != nil { t.Fatalf("Expected URL to parse: %q, got error: %v", url, err) } return u } for _, test := range resolveReferenceTests { - base := mustParseURL(test.base) - rel := mustParseURL(test.rel) + base := mustParse(test.base) + rel := mustParse(test.rel) url := base.ResolveReference(rel) urlStr := url.String() if urlStr != test.expected { @@ -647,33 +647,33 @@ func TestResolveReference(t *testing.T) { } // Test that new instances are returned. - base := mustParseURL("http://foo.com/") - abs := base.ResolveReference(mustParseURL(".")) + base := mustParse("http://foo.com/") + abs := base.ResolveReference(mustParse(".")) if base == abs { t.Errorf("Expected no-op reference to return new URL instance.") } - barRef := mustParseURL("http://bar.com/") + barRef := mustParse("http://bar.com/") abs = base.ResolveReference(barRef) if abs == barRef { t.Errorf("Expected resolution of absolute reference to return new URL instance.") } // Test the convenience wrapper too - base = mustParseURL("http://foo.com/path/one/") - abs, _ = base.ParseURL("../two") + base = mustParse("http://foo.com/path/one/") + abs, _ = base.Parse("../two") expected := "http://foo.com/path/two" if abs.String() != expected { - t.Errorf("ParseURL wrapper got %q; expected %q", abs.String(), expected) + t.Errorf("Parse wrapper got %q; expected %q", abs.String(), expected) } - _, err := base.ParseURL("") + _, err := base.Parse("") if err == nil { - t.Errorf("Expected an error from ParseURL wrapper parsing an empty string.") + t.Errorf("Expected an error from Parse wrapper parsing an empty string.") } } func TestQueryValues(t *testing.T) { - u, _ := ParseURL("http://x.com?foo=bar&bar=1&bar=2") + u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2") v := u.Query() if len(v) != 2 { t.Errorf("got %d keys in Query values, want 2", len(v)) diff --git a/src/pkg/utf8/utf8.go b/src/pkg/utf8/utf8.go index f542358d6..8910e17d7 100644 --- a/src/pkg/utf8/utf8.go +++ b/src/pkg/utf8/utf8.go @@ -16,22 +16,22 @@ const ( ) const ( - _T1 = 0x00 // 0000 0000 - _Tx = 0x80 // 1000 0000 - _T2 = 0xC0 // 1100 0000 - _T3 = 0xE0 // 1110 0000 - _T4 = 0xF0 // 1111 0000 - _T5 = 0xF8 // 1111 1000 - - _Maskx = 0x3F // 0011 1111 - _Mask2 = 0x1F // 0001 1111 - _Mask3 = 0x0F // 0000 1111 - _Mask4 = 0x07 // 0000 0111 - - _Rune1Max = 1<<7 - 1 - _Rune2Max = 1<<11 - 1 - _Rune3Max = 1<<16 - 1 - _Rune4Max = 1<<21 - 1 + t1 = 0x00 // 0000 0000 + tx = 0x80 // 1000 0000 + t2 = 0xC0 // 1100 0000 + t3 = 0xE0 // 1110 0000 + t4 = 0xF0 // 1111 0000 + t5 = 0xF8 // 1111 1000 + + maskx = 0x3F // 0011 1111 + mask2 = 0x1F // 0001 1111 + mask3 = 0x0F // 0000 1111 + mask4 = 0x07 // 0000 0111 + + rune1Max = 1<<7 - 1 + rune2Max = 1<<11 - 1 + rune3Max = 1<<16 - 1 + rune4Max = 1<<21 - 1 ) func decodeRuneInternal(p []byte) (rune, size int, short bool) { @@ -42,12 +42,12 @@ func decodeRuneInternal(p []byte) (rune, size int, short bool) { c0 := p[0] // 1-byte, 7-bit sequence? - if c0 < _Tx { + if c0 < tx { return int(c0), 1, false } // unexpected continuation byte? - if c0 < _T2 { + if c0 < t2 { return RuneError, 1, false } @@ -56,14 +56,14 @@ func decodeRuneInternal(p []byte) (rune, size int, short bool) { return RuneError, 1, true } c1 := p[1] - if c1 < _Tx || _T2 <= c1 { + if c1 < tx || t2 <= c1 { return RuneError, 1, false } // 2-byte, 11-bit sequence? - if c0 < _T3 { - rune = int(c0&_Mask2)<<6 | int(c1&_Maskx) - if rune <= _Rune1Max { + if c0 < t3 { + rune = int(c0&mask2)<<6 | int(c1&maskx) + if rune <= rune1Max { return RuneError, 1, false } return rune, 2, false @@ -74,14 +74,14 @@ func decodeRuneInternal(p []byte) (rune, size int, short bool) { return RuneError, 1, true } c2 := p[2] - if c2 < _Tx || _T2 <= c2 { + if c2 < tx || t2 <= c2 { return RuneError, 1, false } // 3-byte, 16-bit sequence? - if c0 < _T4 { - rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx) - if rune <= _Rune2Max { + if c0 < t4 { + rune = int(c0&mask3)<<12 | int(c1&maskx)<<6 | int(c2&maskx) + if rune <= rune2Max { return RuneError, 1, false } return rune, 3, false @@ -92,14 +92,14 @@ func decodeRuneInternal(p []byte) (rune, size int, short bool) { return RuneError, 1, true } c3 := p[3] - if c3 < _Tx || _T2 <= c3 { + if c3 < tx || t2 <= c3 { return RuneError, 1, false } // 4-byte, 21-bit sequence? - if c0 < _T5 { - rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx) - if rune <= _Rune3Max { + if c0 < t5 { + rune = int(c0&mask4)<<18 | int(c1&maskx)<<12 | int(c2&maskx)<<6 | int(c3&maskx) + if rune <= rune3Max { return RuneError, 1, false } return rune, 4, false @@ -117,12 +117,12 @@ func decodeRuneInStringInternal(s string) (rune, size int, short bool) { c0 := s[0] // 1-byte, 7-bit sequence? - if c0 < _Tx { + if c0 < tx { return int(c0), 1, false } // unexpected continuation byte? - if c0 < _T2 { + if c0 < t2 { return RuneError, 1, false } @@ -131,14 +131,14 @@ func decodeRuneInStringInternal(s string) (rune, size int, short bool) { return RuneError, 1, true } c1 := s[1] - if c1 < _Tx || _T2 <= c1 { + if c1 < tx || t2 <= c1 { return RuneError, 1, false } // 2-byte, 11-bit sequence? - if c0 < _T3 { - rune = int(c0&_Mask2)<<6 | int(c1&_Maskx) - if rune <= _Rune1Max { + if c0 < t3 { + rune = int(c0&mask2)<<6 | int(c1&maskx) + if rune <= rune1Max { return RuneError, 1, false } return rune, 2, false @@ -149,14 +149,14 @@ func decodeRuneInStringInternal(s string) (rune, size int, short bool) { return RuneError, 1, true } c2 := s[2] - if c2 < _Tx || _T2 <= c2 { + if c2 < tx || t2 <= c2 { return RuneError, 1, false } // 3-byte, 16-bit sequence? - if c0 < _T4 { - rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx) - if rune <= _Rune2Max { + if c0 < t4 { + rune = int(c0&mask3)<<12 | int(c1&maskx)<<6 | int(c2&maskx) + if rune <= rune2Max { return RuneError, 1, false } return rune, 3, false @@ -167,14 +167,14 @@ func decodeRuneInStringInternal(s string) (rune, size int, short bool) { return RuneError, 1, true } c3 := s[3] - if c3 < _Tx || _T2 <= c3 { + if c3 < tx || t2 <= c3 { return RuneError, 1, false } // 4-byte, 21-bit sequence? - if c0 < _T5 { - rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx) - if rune <= _Rune3Max { + if c0 < t5 { + rune = int(c0&mask4)<<18 | int(c1&maskx)<<12 | int(c2&maskx)<<6 | int(c3&maskx) + if rune <= rune3Max { return RuneError, 1, false } return rune, 4, false @@ -279,13 +279,13 @@ func DecodeLastRuneInString(s string) (rune, size int) { // RuneLen returns the number of bytes required to encode the rune. func RuneLen(rune int) int { switch { - case rune <= _Rune1Max: + case rune <= rune1Max: return 1 - case rune <= _Rune2Max: + case rune <= rune2Max: return 2 - case rune <= _Rune3Max: + case rune <= rune3Max: return 3 - case rune <= _Rune4Max: + case rune <= rune4Max: return 4 } return -1 @@ -297,14 +297,14 @@ func EncodeRune(p []byte, rune int) int { // Negative values are erroneous. Making it unsigned addresses the problem. r := uint(rune) - if r <= _Rune1Max { + if r <= rune1Max { p[0] = byte(r) return 1 } - if r <= _Rune2Max { - p[0] = _T2 | byte(r>>6) - p[1] = _Tx | byte(r)&_Maskx + if r <= rune2Max { + p[0] = t2 | byte(r>>6) + p[1] = tx | byte(r)&maskx return 2 } @@ -312,17 +312,17 @@ func EncodeRune(p []byte, rune int) int { r = RuneError } - if r <= _Rune3Max { - p[0] = _T3 | byte(r>>12) - p[1] = _Tx | byte(r>>6)&_Maskx - p[2] = _Tx | byte(r)&_Maskx + if r <= rune3Max { + p[0] = t3 | byte(r>>12) + p[1] = tx | byte(r>>6)&maskx + p[2] = tx | byte(r)&maskx return 3 } - p[0] = _T4 | byte(r>>18) - p[1] = _Tx | byte(r>>12)&_Maskx - p[2] = _Tx | byte(r>>6)&_Maskx - p[3] = _Tx | byte(r)&_Maskx + p[0] = t4 | byte(r>>18) + p[1] = tx | byte(r>>12)&maskx + p[2] = tx | byte(r>>6)&maskx + p[3] = tx | byte(r)&maskx return 4 } diff --git a/src/pkg/websocket/client.go b/src/pkg/websocket/client.go index f24c46360..74bede424 100644 --- a/src/pkg/websocket/client.go +++ b/src/pkg/websocket/client.go @@ -15,6 +15,7 @@ import ( "os" "rand" "strings" + "url" ) type ProtocolError struct { @@ -99,10 +100,10 @@ A trivial example client: // use msg[0:n] } */ -func Dial(url, protocol, origin string) (ws *Conn, err os.Error) { +func Dial(url_, protocol, origin string) (ws *Conn, err os.Error) { var client net.Conn - parsedUrl, err := http.ParseURL(url) + parsedUrl, err := url.Parse(url_) if err != nil { goto Error } @@ -121,14 +122,14 @@ func Dial(url, protocol, origin string) (ws *Conn, err os.Error) { goto Error } - ws, err = newClient(parsedUrl.RawPath, parsedUrl.Host, origin, url, protocol, client, handshake) + ws, err = newClient(parsedUrl.RawPath, parsedUrl.Host, origin, url_, protocol, client, handshake) if err != nil { goto Error } return Error: - return nil, &DialError{url, protocol, origin, err} + return nil, &DialError{url_, protocol, origin, err} } /* diff --git a/src/pkg/websocket/websocket_test.go b/src/pkg/websocket/websocket_test.go index 84788b416..71c3c8514 100644 --- a/src/pkg/websocket/websocket_test.go +++ b/src/pkg/websocket/websocket_test.go @@ -15,6 +15,7 @@ import ( "net" "sync" "testing" + "url" ) var serverAddr string @@ -155,9 +156,9 @@ func TestHTTP(t *testing.T) { t.Error("Get: unexpected success") return } - urlerr, ok := err.(*http.URLError) + urlerr, ok := err.(*url.Error) if !ok { - t.Errorf("Get: not URLError %#v", err) + t.Errorf("Get: not url.Error %#v", err) return } if urlerr.Error != io.ErrUnexpectedEOF { diff --git a/src/pkg/xml/marshal.go b/src/pkg/xml/marshal.go index f6e5bf5cd..ea421c1b1 100644 --- a/src/pkg/xml/marshal.go +++ b/src/pkg/xml/marshal.go @@ -177,7 +177,7 @@ func (p *printer) marshalValue(val reflect.Value, name string) os.Error { case "": case "chardata": if tk := f.Type.Kind(); tk == reflect.String { - p.Write([]byte(val.Field(i).String())) + Escape(p, []byte(val.Field(i).String())) } else if tk == reflect.Slice { if elem, ok := val.Field(i).Interface().([]byte); ok { Escape(p, elem) diff --git a/src/pkg/xml/marshal_test.go b/src/pkg/xml/marshal_test.go index 77b2e726d..5b972fafe 100644 --- a/src/pkg/xml/marshal_test.go +++ b/src/pkg/xml/marshal_test.go @@ -57,6 +57,11 @@ type Domain struct { Name []byte `xml:"chardata"` } +type Book struct { + XMLName Name `xml:"book"` + Title string `xml:"chardata"` +} + type SecretAgent struct { XMLName Name `xml:"agent"` Handle string `xml:"attr"` @@ -113,6 +118,7 @@ var marshalTests = []struct { {Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`}, {Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="<unix>"></port>`}, {Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&friends</domain>`}, + {Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride & Prejudice</book>`}, {Value: atomValue, ExpectXML: atomXml}, { Value: &Ship{ diff --git a/src/run.bash b/src/run.bash index ae79a0cec..a9689bf15 100755 --- a/src/run.bash +++ b/src/run.bash @@ -49,20 +49,20 @@ GOMAXPROCS=10 gomake testshort time gomake test ) || exit $? -[ "$GOARCH" == arm ] || +[ "$CGO_ENABLED" != 1 ] || [ "$GOHOSTOS" == windows ] || (xcd ../misc/cgo/stdio gomake clean ./test.bash ) || exit $? -[ "$GOARCH" == arm ] || +[ "$CGO_ENABLED" != 1 ] || (xcd ../misc/cgo/life gomake clean ./test.bash ) || exit $? -[ "$GOARCH" == arm ] || +[ "$CGO_ENABLED" != 1 ] || [ "$GOHOSTOS" == windows ] || (xcd ../misc/cgo/test gomake clean diff --git a/src/version.bash b/src/version.bash index ce5a9969a..fc899e2e3 100755 --- a/src/version.bash +++ b/src/version.bash @@ -3,9 +3,18 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -# Check that we can use 'hg' -if ! hg version > /dev/null 2>&1; then - echo 'hg not installed' 1>&2 +GOROOT=$(dirname $0)/.. + +# If a version file created by -save is available, use it +if [ -f "$GOROOT/VERSION" ]; then + cat $GOROOT/VERSION + exit 0 +fi + +# Otherwise, if hg doesn't work for whatever reason, fail +if [ ! -d "$GOROOT/.hg" ] || ! hg version > /dev/null 2>&1; then + echo 'Unable to report version: hg and VERSION file missing' 1>&2 + echo 'Generate VERSION with `src/version.bash -save` while hg is usable' 1>&2 exit 2 fi @@ -34,5 +43,8 @@ if [ "$TAG" != "" ]; then VERSION="$TAG $VERSION" fi -echo $VERSION - +if [ "$1" = "-save" ]; then + echo $VERSION > $GOROOT/VERSION +else + echo $VERSION +fi diff --git a/test/chan/select3.go b/test/chan/select3.go index b4e8f8e4b..d919de3e0 100644 --- a/test/chan/select3.go +++ b/test/chan/select3.go @@ -58,15 +58,15 @@ func main() { closedch := make(chan int) close(closedch) - // sending/receiving from a nil channel outside a select panics - testPanic(always, func() { + // sending/receiving from a nil channel blocks + testBlock(always, func() { nilch <- 7 }) - testPanic(always, func() { + testBlock(always, func() { <-nilch }) - // sending/receiving from a nil channel inside a select never panics + // sending/receiving from a nil channel inside a select is never selected testPanic(never, func() { select { case nilch <- 7: diff --git a/test/chan/select5.go b/test/chan/select5.go index e7ca9e015..607182167 100644 --- a/test/chan/select5.go +++ b/test/chan/select5.go @@ -37,7 +37,7 @@ func main() { } fmt.Fprintln(out, `}`) } - + do(recv) do(send) do(recvOrder) @@ -54,8 +54,8 @@ func run(t *template.Template, a interface{}, out io.Writer) { } } -type arg struct{ - def bool +type arg struct { + def bool nreset int } @@ -135,181 +135,180 @@ func main() { } ` -func parse(s string) *template.Template { - t := template.New(nil) - t.SetDelims("〈", "〉") - if err := t.Parse(s); err != nil { - panic(s) +func parse(name, s string) *template.Template { + t, err := template.New(name).Parse(s) + if err != nil { + panic(fmt.Sprintf("%q: %s", name, err)) } return t } -var recv = parse(` - 〈# Send n, receive it one way or another into x, check that they match.〉 +var recv = parse("recv", ` + {{/* Send n, receive it one way or another into x, check that they match. */}} c <- n - 〈.section Maybe〉 + {{if .Maybe}} x = <-c - 〈.or〉 + {{else}} select { - 〈# Blocking or non-blocking, before the receive.〉 - 〈# The compiler implements two-case select where one is default with custom code,〉 - 〈# so test the default branch both before and after the send.〉 - 〈.section MaybeDefault〉 + {{/* Blocking or non-blocking, before the receive. */}} + {{/* The compiler implements two-case select where one is default with custom code, */}} + {{/* so test the default branch both before and after the send. */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Receive from c. Different cases are direct, indirect, :=, interface, and map assignment.〉 - 〈.section Maybe〉 + {{end}} + {{/* Receive from c. Different cases are direct, indirect, :=, interface, and map assignment. */}} + {{if .Maybe}} case x = <-c: - 〈.or〉〈.section Maybe〉 + {{else}}{{if .Maybe}} case *f(&x) = <-c: - 〈.or〉〈.section Maybe〉 + {{else}}{{if .Maybe}} case y := <-c: x = y - 〈.or〉〈.section Maybe〉 + {{else}}{{if .Maybe}} case i = <-c: x = i.(int) - 〈.or〉 + {{else}} case m[13] = <-c: x = m[13] - 〈.end〉〈.end〉〈.end〉〈.end〉 - 〈# Blocking or non-blocking again, after the receive.〉 - 〈.section MaybeDefault〉 + {{end}}{{end}}{{end}}{{end}} + {{/* Blocking or non-blocking again, after the receive. */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Dummy send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case dummy <- 1: panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-dummy: panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Nil channel send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case nilch <- 1: panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-nilch: panic("nilch recv") - 〈.end〉 + {{end}} } - 〈.end〉 + {{end}} if x != n { die(x) } n++ `) -var recvOrder = parse(` - 〈# Send n, receive it one way or another into x, check that they match.〉 - 〈# Check order of operations along the way by calling functions that check〉 - 〈# that the argument sequence is strictly increasing.〉 +var recvOrder = parse("recvOrder", ` + {{/* Send n, receive it one way or another into x, check that they match. */}} + {{/* Check order of operations along the way by calling functions that check */}} + {{/* that the argument sequence is strictly increasing. */}} order = 0 c <- n - 〈.section Maybe〉 - 〈# Outside of select, left-to-right rule applies.〉 - 〈# (Inside select, assignment waits until case is chosen,〉 - 〈# so right hand side happens before anything on left hand side.〉 + {{if .Maybe}} + {{/* Outside of select, left-to-right rule applies. */}} + {{/* (Inside select, assignment waits until case is chosen, */}} + {{/* so right hand side happens before anything on left hand side. */}} *fp(&x, 1) = <-fc(c, 2) - 〈.or〉〈.section Maybe〉 + {{else}}{{if .Maybe}} m[fn(13, 1)] = <-fc(c, 2) x = m[13] - 〈.or〉 + {{else}} select { - 〈# Blocking or non-blocking, before the receive.〉 - 〈# The compiler implements two-case select where one is default with custom code,〉 - 〈# so test the default branch both before and after the send.〉 - 〈.section MaybeDefault〉 + {{/* Blocking or non-blocking, before the receive. */}} + {{/* The compiler implements two-case select where one is default with custom code, */}} + {{/* so test the default branch both before and after the send. */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Receive from c. Different cases are direct, indirect, :=, interface, and map assignment.〉 - 〈.section Maybe〉 + {{end}} + {{/* Receive from c. Different cases are direct, indirect, :=, interface, and map assignment. */}} + {{if .Maybe}} case *fp(&x, 100) = <-fc(c, 1): - 〈.or〉〈.section Maybe〉 + {{else}}{{if .Maybe}} case y := <-fc(c, 1): x = y - 〈.or〉〈.section Maybe〉 + {{else}}{{if .Maybe}} case i = <-fc(c, 1): x = i.(int) - 〈.or〉 + {{else}} case m[fn(13, 100)] = <-fc(c, 1): x = m[13] - 〈.end〉〈.end〉〈.end〉 - 〈# Blocking or non-blocking again, after the receive.〉 - 〈.section MaybeDefault〉 + {{end}}{{end}}{{end}} + {{/* Blocking or non-blocking again, after the receive. */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Dummy send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case fc(dummy, 2) <- fn(1, 3): panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-fc(dummy, 4): panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Nil channel send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case fc(nilch, 5) <- fn(1, 6): panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-fc(nilch, 7): panic("nilch recv") - 〈.end〉 + {{end}} } - 〈.end〉〈.end〉 + {{end}}{{end}} if x != n { die(x) } n++ `) -var send = parse(` - 〈# Send n one way or another, receive it into x, check that they match.〉 - 〈.section Maybe〉 +var send = parse("send", ` + {{/* Send n one way or another, receive it into x, check that they match. */}} + {{if .Maybe}} c <- n - 〈.or〉 + {{else}} select { - 〈# Blocking or non-blocking, before the receive (same reason as in recv).〉 - 〈.section MaybeDefault〉 + {{/* Blocking or non-blocking, before the receive (same reason as in recv). */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Send c <- n. No real special cases here, because no values come back〉 - 〈# from the send operation.〉 + {{end}} + {{/* Send c <- n. No real special cases here, because no values come back */}} + {{/* from the send operation. */}} case c <- n: - 〈# Blocking or non-blocking.〉 - 〈.section MaybeDefault〉 + {{/* Blocking or non-blocking. */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Dummy send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case dummy <- 1: panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-dummy: panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Nil channel send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case nilch <- 1: panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-nilch: panic("nilch recv") - 〈.end〉 + {{end}} } - 〈.end〉 + {{end}} x = <-c if x != n { die(x) @@ -317,48 +316,48 @@ var send = parse(` n++ `) -var sendOrder = parse(` - 〈# Send n one way or another, receive it into x, check that they match.〉 - 〈# Check order of operations along the way by calling functions that check〉 - 〈# that the argument sequence is strictly increasing.〉 +var sendOrder = parse("sendOrder", ` + {{/* Send n one way or another, receive it into x, check that they match. */}} + {{/* Check order of operations along the way by calling functions that check */}} + {{/* that the argument sequence is strictly increasing. */}} order = 0 - 〈.section Maybe〉 + {{if .Maybe}} fc(c, 1) <- fn(n, 2) - 〈.or〉 + {{else}} select { - 〈# Blocking or non-blocking, before the receive (same reason as in recv).〉 - 〈.section MaybeDefault〉 + {{/* Blocking or non-blocking, before the receive (same reason as in recv). */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Send c <- n. No real special cases here, because no values come back〉 - 〈# from the send operation.〉 + {{end}} + {{/* Send c <- n. No real special cases here, because no values come back */}} + {{/* from the send operation. */}} case fc(c, 1) <- fn(n, 2): - 〈# Blocking or non-blocking.〉 - 〈.section MaybeDefault〉 + {{/* Blocking or non-blocking. */}} + {{if .MaybeDefault}} default: panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Dummy send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case fc(dummy, 3) <- fn(1, 4): panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-fc(dummy, 5): panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 + {{end}} + {{/* Nil channel send, receive to keep compiler from optimizing select. */}} + {{if .Maybe}} case fc(nilch, 6) <- fn(1, 7): panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-fc(nilch, 8): panic("nilch recv") - 〈.end〉 + {{end}} } - 〈.end〉 + {{end}} x = <-c if x != n { die(x) @@ -366,49 +365,49 @@ var sendOrder = parse(` n++ `) -var nonblock = parse(` +var nonblock = parse("nonblock", ` x = n - 〈# Test various combinations of non-blocking operations.〉 - 〈# Receive assignments must not edit or even attempt to compute the address of the lhs.〉 + {{/* Test various combinations of non-blocking operations. */}} + {{/* Receive assignments must not edit or even attempt to compute the address of the lhs. */}} select { - 〈.section MaybeDefault〉 + {{if .MaybeDefault}} default: - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case dummy <- 1: panic("dummy <- 1") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case nilch <- 1: panic("nilch <- 1") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-dummy: panic("<-dummy") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case x = <-dummy: panic("<-dummy x") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case **(**int)(nil) = <-dummy: panic("<-dummy (and didn't crash saving result!)") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case <-nilch: panic("<-nilch") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case x = <-nilch: panic("<-nilch x") - 〈.end〉 - 〈.section Maybe〉 + {{end}} + {{if .Maybe}} case **(**int)(nil) = <-nilch: panic("<-nilch (and didn't crash saving result!)") - 〈.end〉 - 〈.section MustDefault〉 + {{end}} + {{if .MustDefault}} default: - 〈.end〉 + {{end}} } if x != n { die(x) @@ -466,7 +465,7 @@ func next() bool { } // increment last choice sequence - cp = len(choices)-1 + cp = len(choices) - 1 for cp >= 0 && choices[cp].i == choices[cp].n-1 { cp-- } @@ -479,4 +478,3 @@ func next() bool { cp = 0 return true } - diff --git a/test/declbad.go b/test/declbad.go index 5e5e14501..09f1dfb57 100644 --- a/test/declbad.go +++ b/test/declbad.go @@ -40,7 +40,7 @@ func main() { { // single redeclaration i, f, s := f3() - i := f1() // ERROR "redeclared|no new|incompatible" + i := 1 // ERROR "redeclared|no new|incompatible" _, _, _ = i, f, s } // double redeclaration diff --git a/test/errchk b/test/errchk index 8fdf77a30..6b00570bd 100755 --- a/test/errchk +++ b/test/errchk @@ -88,41 +88,46 @@ sub chk { $line++; next if $src =~ m|////|; # double comment disables ERROR next unless $src =~ m|// (GC_)?ERROR (.*)|; - $regexp = $2; - if($regexp !~ /^"([^"]*)"/) { + my $all = $2; + if($all !~ /^"([^"]*)"/) { print STDERR "$file:$line: malformed regexp\n"; next; } - $regexp = $1; - - # Turn relative line number in message into absolute line number. - if($regexp =~ /LINE(([+-])([0-9]+))?/) { - my $n = $line; - if(defined($1)) { - if($2 eq "+") { - $n += int($3); - } else { - $n -= int($3); - } - } - $regexp = "$`$file:$n$'"; - } - @errmsg = grep { /$file:$line[:[]/ } @out; @out = grep { !/$file:$line[:[]/ } @out; if(@errmsg == 0) { bug(); - print STDERR "errchk: $file:$line: missing expected error: '$regexp'\n"; + print STDERR "errchk: $file:$line: missing expected error: '$all'\n"; next; } - @match = grep { /$regexp/ } @errmsg; - if(@match == 0) { + foreach my $regexp ($all =~ /"([^"]*)"/g) { + # Turn relative line number in message into absolute line number. + if($regexp =~ /LINE(([+-])([0-9]+))?/) { + my $n = $line; + if(defined($1)) { + if($2 eq "+") { + $n += int($3); + } else { + $n -= int($3); + } + } + $regexp = "$`$file:$n$'"; + } + + @match = grep { /$regexp/ } @errmsg; + if(@match == 0) { + bug(); + print STDERR "errchk: $file:$line: error messages do not match '$regexp'\n"; + next; + } + @errmsg = grep { !/$regexp/ } @errmsg; + } + if(@errmsg != 0) { bug(); - print STDERR "errchk: $file:$line: error message does not match '$regexp'\n"; + print STDERR "errchk: $file:$line: unmatched error messages:\n"; foreach my $l (@errmsg) { print STDERR "> $l"; } - next; } } } diff --git a/test/fixedbugs/bug205.go b/test/fixedbugs/bug205.go index 4262ec10d..e12be72f9 100644 --- a/test/fixedbugs/bug205.go +++ b/test/fixedbugs/bug205.go @@ -12,7 +12,7 @@ var m map[string]int; func main() { println(t["hi"]); // ERROR "integer" - println(s["hi"]); // ERROR "integer" + println(s["hi"]); // ERROR "integer" "to type uint" println(m[0]); // ERROR "map index" } diff --git a/test/fixedbugs/bug228.go b/test/fixedbugs/bug228.go index 81bc90856..da335dbc0 100644 --- a/test/fixedbugs/bug228.go +++ b/test/fixedbugs/bug228.go @@ -8,7 +8,7 @@ package main func f(x int, y ...int) // ok -func g(x int, y float) (...) // ERROR "[.][.][.]" +func g(x int, y float) (...) // ERROR "[.][.][.]" "final argument" func h(x, y ...int) // ERROR "[.][.][.]" diff --git a/test/fixedbugs/bug229.go b/test/fixedbugs/bug229.go index fe0f0d8c7..6c9de9ba9 100644 --- a/test/fixedbugs/bug229.go +++ b/test/fixedbugs/bug229.go @@ -16,5 +16,5 @@ func main() { t.ch = nil // ERROR "unexported" - println(testing.anyLowercaseName("asdf")) // ERROR "unexported" + println(testing.anyLowercaseName("asdf")) // ERROR "unexported" "undefined: testing.anyLowercaseName" } diff --git a/test/fixedbugs/bug231.go b/test/fixedbugs/bug231.go index 91996d313..9500e582b 100644 --- a/test/fixedbugs/bug231.go +++ b/test/fixedbugs/bug231.go @@ -17,6 +17,6 @@ func main() { var i I i = m - i = t // ERROR "not a method|has no methods" + i = t // ERROR "not a method|has no methods" "does not implement I" _ = i } diff --git a/test/fixedbugs/bug297.go b/test/fixedbugs/bug297.go index ba029427f..8767cdfea 100644 --- a/test/fixedbugs/bug297.go +++ b/test/fixedbugs/bug297.go @@ -11,5 +11,5 @@ package main type ByteSize float64 const ( _ = iota; // ignore first value by assigning to blank identifier - KB ByteSize = 1<<(10*X) // ERROR "undefined" + KB ByteSize = 1<<(10*X) // ERROR "undefined" "as type ByteSize" ) diff --git a/test/fixedbugs/bug351.go b/test/fixedbugs/bug351.go index c33e28271..2f631bbbb 100644 --- a/test/fixedbugs/bug351.go +++ b/test/fixedbugs/bug351.go @@ -6,6 +6,8 @@ package main +var x int + func main() { (x) := 0 // ERROR "non-name [(]x[)]" } diff --git a/test/fixedbugs/bug359.go b/test/fixedbugs/bug359.go index 6ced608bc..7f34672f1 100644 --- a/test/fixedbugs/bug359.go +++ b/test/fixedbugs/bug359.go @@ -16,7 +16,7 @@ type Painting struct { } func (p Painting) Foo() { - for e := p.fragments; e.Front() != nil; e = e.Next() { // ERROR "unexported field" + for e := p.fragments; e.Front() != nil; { // ERROR "unexported field" } } diff --git a/test/import1.go b/test/import1.go index 8bb2a94a2..ebd704ef9 100644 --- a/test/import1.go +++ b/test/import1.go @@ -9,9 +9,9 @@ package main import "bufio" // GCCGO_ERROR "previous|not used" -import bufio "os" // ERROR "redeclared|redefinition|incompatible" +import bufio "os" // ERROR "redeclared|redefinition|incompatible" "imported and not used" import ( "fmt" // GCCGO_ERROR "previous|not used" - fmt "math" // ERROR "redeclared|redefinition|incompatible" + fmt "math" // ERROR "redeclared|redefinition|incompatible" "imported and not used" ) diff --git a/test/initializerr.go b/test/initializerr.go index 37f8a602d..e7f8b0e92 100644 --- a/test/initializerr.go +++ b/test/initializerr.go @@ -17,7 +17,7 @@ type T struct { var x = 1 var a1 = S { 0, X: 1 } // ERROR "mixture|undefined" var a2 = S { Y: 3, Z: 2, Y: 3 } // ERROR "duplicate" -var a3 = T { 1, 2, 3, 4, 5, 6 } // ERROR "convert|too many" +var a3 = T { S{}, 2, 3, 4, 5, 6 } // ERROR "convert|too many" var a4 = [5]byte{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } // ERROR "index|too many" var a5 = []byte { x: 2 } // ERROR "index" diff --git a/test/interface/explicit.go b/test/interface/explicit.go index b6a582fff..daae59b36 100644 --- a/test/interface/explicit.go +++ b/test/interface/explicit.go @@ -48,7 +48,7 @@ func main() { i2 = I2(i) // ERROR "invalid|missing N method" e = E(t) // ok - t = T(e) // ERROR "need explicit|need type assertion|incompatible" + t = T(e) // ERROR "need explicit|need type assertion|incompatible" "as type [*]T" } type M interface { diff --git a/test/interface/pointer.go b/test/interface/pointer.go index 076469c8d..fe4d8e3ef 100644 --- a/test/interface/pointer.go +++ b/test/interface/pointer.go @@ -33,5 +33,5 @@ func main() { print("call addinst\n") var x Inst = AddInst(new(Start)) // ERROR "pointer to interface" print("return from addinst\n") - var x *Inst = new(Start) // ERROR "pointer to interface" + var y *Inst = new(Start) // ERROR "pointer to interface" } diff --git a/test/nil.go b/test/nil.go index 4f4c75527..30cc2705b 100644 --- a/test/nil.go +++ b/test/nil.go @@ -6,6 +6,11 @@ package main +import ( + "fmt" + "time" +) + type T struct { i int } @@ -33,4 +38,141 @@ func main() { ta[0] = nil _, _, _, _, _, _, _, _ = i, f, s, m, c, t, in, ta + + arraytest() + chantest() + maptest() + slicetest() +} + +func shouldPanic(f func()) { + defer func() { + if recover() == nil { + panic("not panicking") + } + }() + f() +} + +func shouldBlock(f func()) { + go func() { + f() + panic("did not block") + }() + time.Sleep(1e7) +} + +// nil array pointer + +func arraytest() { + var p *[10]int + + // Looping over indices is fine. + s := 0 + for i := range p { + s += i + } + if s != 45 { + panic(s) + } + + s = 0 + for i := 0; i < len(p); i++ { + s += i + } + if s != 45 { + panic(s) + } + + // Looping over values is not. + shouldPanic(func() { + for i, v := range p { + s += i + v + } + }) + + shouldPanic(func() { + for i := 0; i < len(p); i++ { + s += p[i] + } + }) +} + +// nil channel +// select tests already handle select on nil channel + +func chantest() { + var ch chan int + + // nil channel is never ready + shouldBlock(func() { + ch <- 1 + }) + shouldBlock(func() { + <-ch + }) + shouldBlock(func() { + x, ok := <-ch + println(x, ok) + }) + + if len(ch) != 0 { + panic(len(ch)) + } + if cap(ch) != 0 { + panic(cap(ch)) + } +} + +// nil map + +func maptest() { + var m map[int]int + + // nil map appears empty + if len(m) != 0 { + panic(len(m)) + } + if m[1] != 0 { + panic(m[1]) + } + if x, ok := m[1]; x != 0 || ok { + panic(fmt.Sprint(x, ok)) + } + + for k, v := range m { + panic(k) + panic(v) + } + + // but cannot be written to + shouldPanic(func() { + m[2] = 3 + }) + shouldPanic(func() { + m[2] = 0, false + }) +} + +// nil slice + +func slicetest() { + var x []int + + // nil slice is just a 0-element slice. + if len(x) != 0 { + panic(len(x)) + } + if cap(x) != 0 { + panic(cap(x)) + } + + // no 0-element slices can be read from or written to + var s int + shouldPanic(func() { + s += x[1] + }) + shouldPanic(func() { + x[2] = s + }) } diff --git a/test/nul1.go b/test/nul1.go index 9cf51125b..142d4deb1 100644 --- a/test/nul1.go +++ b/test/nul1.go @@ -39,7 +39,7 @@ var y = ` + "`in raw string \x00 foo`" + ` // ERROR "NUL" /* in other comment ` + "\x00" + ` */ // ERROR "NUL" -/* in source code */ ` + "\x00" + `// ERROR "NUL" +/* in source code */ ` + "\x00" + `// ERROR "NUL" "illegal character" var xx = "in string ` + "\xc2\xff" + `" // ERROR "UTF-8" @@ -50,9 +50,9 @@ var yy = ` + "`in raw string \xff foo`" + ` // ERROR "UTF-8" /* in other comment ` + "\xe0\x00\x00" + ` */ // ERROR "UTF-8|NUL" /* in variable name */ -var z` + "\xc1\x81" + ` int // ERROR "UTF-8" +var z` + "\xc1\x81" + ` int // ERROR "UTF-8" "invalid identifier character" -/* in source code */ ` + "\xc2A" + `// ERROR "UTF-8" +/* in source code */ ` + "var \xc2A int" + `// ERROR "UTF-8" "invalid identifier character" `) } diff --git a/test/rename1.go b/test/rename1.go index f23999998..3e78bfca0 100644 --- a/test/rename1.go +++ b/test/rename1.go @@ -10,7 +10,7 @@ func main() { var n byte // ERROR "not a type|expected type" var y = float(0) // ERROR "cannot call|expected function" const ( - a = 1 + iota // ERROR "string|incompatible types" + a = 1 + iota // ERROR "string|incompatible types" "convert iota" ) } diff --git a/test/shift1.go b/test/shift1.go index 8fa48a03c..6a8e26e5e 100644 --- a/test/shift1.go +++ b/test/shift1.go @@ -16,13 +16,13 @@ func h(x float64) int { return 0 } var ( s uint = 33 u = 1.0 << s // ERROR "invalid operation" - v float32 = 1 << s // ERROR "invalid operation" + v float32 = 1 << s // ERROR "invalid operation" "as type float32" ) // non-constant shift expressions var ( - e1 = g(2.0 << s) // ERROR "invalid operation" - f1 = h(2 << s) // ERROR "invalid operation" + e1 = g(2.0 << s) // ERROR "invalid operation" "as type interface" + f1 = h(2 << s) // ERROR "invalid operation" "as type float64" g1 int64 = 1.1 << s // ERROR "truncated" ) |
