2015-07-08 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc.git] / libgo / go / strconv / makeisprint.go
blob588d0a00b53b242010cc50afd051065e1ceb5a91
1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build ignore
7 //
8 // usage:
9 //
10 // go run makeisprint.go -output isprint.go
13 package main
15 import (
16 "bytes"
17 "flag"
18 "fmt"
19 "go/format"
20 "io/ioutil"
21 "log"
22 "unicode"
25 var filename = flag.String("output", "isprint.go", "output file name")
27 var (
28 range16 []uint16
29 except16 []uint16
30 range32 []uint32
31 except32 []uint32
34 // bsearch16 returns the smallest i such that a[i] >= x.
35 // If there is no such i, bsearch16 returns len(a).
36 func bsearch16(a []uint16, x uint16) int {
37 i, j := 0, len(a)
38 for i < j {
39 h := i + (j-i)/2
40 if a[h] < x {
41 i = h + 1
42 } else {
43 j = h
46 return i
49 // bsearch32 returns the smallest i such that a[i] >= x.
50 // If there is no such i, bsearch32 returns len(a).
51 func bsearch32(a []uint32, x uint32) int {
52 i, j := 0, len(a)
53 for i < j {
54 h := i + (j-i)/2
55 if a[h] < x {
56 i = h + 1
57 } else {
58 j = h
61 return i
64 func isPrint(r rune) bool {
65 // Same algorithm, either on uint16 or uint32 value.
66 // First, find first i such that rang[i] >= x.
67 // This is the index of either the start or end of a pair that might span x.
68 // The start is even (rang[i&^1]) and the end is odd (rang[i|1]).
69 // If we find x in a range, make sure x is not in exception list.
71 if 0 <= r && r < 1<<16 {
72 rr, rang, except := uint16(r), range16, except16
73 i := bsearch16(rang, rr)
74 if i >= len(rang) || rr < rang[i&^1] || rang[i|1] < rr {
75 return false
77 j := bsearch16(except, rr)
78 return j >= len(except) || except[j] != rr
81 rr, rang, except := uint32(r), range32, except32
82 i := bsearch32(rang, rr)
83 if i >= len(rang) || rr < rang[i&^1] || rang[i|1] < rr {
84 return false
86 j := bsearch32(except, rr)
87 return j >= len(except) || except[j] != rr
90 func scan(min, max rune) (rang, except []uint32) {
91 lo := rune(-1)
92 for i := min; ; i++ {
93 if (i > max || !unicode.IsPrint(i)) && lo >= 0 {
94 // End range, but avoid flip flop.
95 if i+1 <= max && unicode.IsPrint(i+1) {
96 except = append(except, uint32(i))
97 continue
99 rang = append(rang, uint32(lo), uint32(i-1))
100 lo = -1
102 if i > max {
103 break
105 if lo < 0 && unicode.IsPrint(i) {
106 lo = i
109 return
112 func to16(x []uint32) []uint16 {
113 var y []uint16
114 for _, v := range x {
115 if uint32(uint16(v)) != v {
116 panic("bad 32->16 conversion")
118 y = append(y, uint16(v))
120 return y
123 func main() {
124 flag.Parse()
126 rang, except := scan(0, 0xFFFF)
127 range16 = to16(rang)
128 except16 = to16(except)
129 range32, except32 = scan(0x10000, unicode.MaxRune)
131 for i := rune(0); i <= unicode.MaxRune; i++ {
132 if isPrint(i) != unicode.IsPrint(i) {
133 log.Fatalf("%U: isPrint=%v, want %v\n", i, isPrint(i), unicode.IsPrint(i))
137 var buf bytes.Buffer
139 fmt.Fprintf(&buf, `// Copyright 2013 The Go Authors. All rights reserved.
140 // Use of this source code is governed by a BSD-style
141 // license that can be found in the LICENSE file.`+"\n\n")
142 fmt.Fprintf(&buf, "// DO NOT EDIT. GENERATED BY\n")
143 fmt.Fprintf(&buf, "// go run makeisprint.go -output isprint.go\n\n")
144 fmt.Fprintf(&buf, "package strconv\n\n")
146 fmt.Fprintf(&buf, "// (%d+%d+%d)*2 + (%d)*4 = %d bytes\n\n",
147 len(range16), len(except16), len(except32),
148 len(range32),
149 (len(range16)+len(except16)+len(except32))*2+
150 (len(range32))*4)
152 fmt.Fprintf(&buf, "var isPrint16 = []uint16{\n")
153 for i := 0; i < len(range16); i += 2 {
154 fmt.Fprintf(&buf, "\t%#04x, %#04x,\n", range16[i], range16[i+1])
156 fmt.Fprintf(&buf, "}\n\n")
158 fmt.Fprintf(&buf, "var isNotPrint16 = []uint16{\n")
159 for _, r := range except16 {
160 fmt.Fprintf(&buf, "\t%#04x,\n", r)
162 fmt.Fprintf(&buf, "}\n\n")
164 fmt.Fprintf(&buf, "var isPrint32 = []uint32{\n")
165 for i := 0; i < len(range32); i += 2 {
166 fmt.Fprintf(&buf, "\t%#06x, %#06x,\n", range32[i], range32[i+1])
168 fmt.Fprintf(&buf, "}\n\n")
170 fmt.Fprintf(&buf, "var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n")
171 for _, r := range except32 {
172 if r >= 0x20000 {
173 log.Fatalf("%U too big for isNotPrint32\n", r)
175 fmt.Fprintf(&buf, "\t%#04x,\n", r-0x10000)
177 fmt.Fprintf(&buf, "}\n")
179 data, err := format.Source(buf.Bytes())
180 if err != nil {
181 log.Fatal(err)
183 err = ioutil.WriteFile(*filename, data, 0644)
184 if err != nil {
185 log.Fatal(err)