Mirror of BoringSSL (grpc依赖)
https://boringssl.googlesource.com/boringssl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
7.0 KiB
285 lines
7.0 KiB
/* Copyright (c) 2015, Google Inc. |
|
* |
|
* Permission to use, copy, modify, and/or distribute this software for any |
|
* purpose with or without fee is hereby granted, provided that the above |
|
* copyright notice and this permission notice appear in all copies. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ |
|
|
|
package main |
|
|
|
import ( |
|
"bufio" |
|
"bytes" |
|
"errors" |
|
"flag" |
|
"fmt" |
|
"io" |
|
"os" |
|
"sort" |
|
"strconv" |
|
"strings" |
|
) |
|
|
|
var verbose = flag.Bool("verbose", false, "If true, prints a status message at the end.") |
|
|
|
// libraryNames must be kept in sync with the enum in err.h. The generated code |
|
// will contain static assertions to enforce this. |
|
var libraryNames = []string{ |
|
"NONE", |
|
"SYS", |
|
"BN", |
|
"RSA", |
|
"DH", |
|
"EVP", |
|
"BUF", |
|
"OBJ", |
|
"PEM", |
|
"DSA", |
|
"X509", |
|
"ASN1", |
|
"CONF", |
|
"CRYPTO", |
|
"EC", |
|
"SSL", |
|
"BIO", |
|
"PKCS7", |
|
"PKCS8", |
|
"X509V3", |
|
"RAND", |
|
"ENGINE", |
|
"OCSP", |
|
"UI", |
|
"COMP", |
|
"ECDSA", |
|
"ECDH", |
|
"HMAC", |
|
"DIGEST", |
|
"CIPHER", |
|
"HKDF", |
|
"TRUST_TOKEN", |
|
"USER", |
|
} |
|
|
|
// stringList is a map from uint32 -> string which can output data for a sorted |
|
// list as C literals. |
|
type stringList struct { |
|
// entries is an array of keys and offsets into |stringData|. The |
|
// offsets are in the bottom 15 bits of each uint32 and the key is the |
|
// top 17 bits. |
|
entries []uint32 |
|
// internedStrings contains the same strings as are in |stringData|, |
|
// but allows for easy deduplication. It maps a string to its offset in |
|
// |stringData|. |
|
internedStrings map[string]uint32 |
|
stringData []byte |
|
} |
|
|
|
func newStringList() *stringList { |
|
return &stringList{ |
|
internedStrings: make(map[string]uint32), |
|
} |
|
} |
|
|
|
// offsetMask is the bottom 15 bits. It's a mask that selects the offset from a |
|
// uint32 in entries. |
|
const offsetMask = 0x7fff |
|
|
|
func (st *stringList) Add(key uint32, value string) error { |
|
if key&offsetMask != 0 { |
|
return errors.New("need bottom 15 bits of the key for the offset") |
|
} |
|
offset, ok := st.internedStrings[value] |
|
if !ok { |
|
offset = uint32(len(st.stringData)) |
|
if offset&offsetMask != offset { |
|
return errors.New("stringList overflow") |
|
} |
|
st.stringData = append(st.stringData, []byte(value)...) |
|
st.stringData = append(st.stringData, 0) |
|
st.internedStrings[value] = offset |
|
} |
|
|
|
for _, existing := range st.entries { |
|
if existing>>15 == key>>15 { |
|
panic("duplicate entry") |
|
} |
|
} |
|
st.entries = append(st.entries, key|offset) |
|
return nil |
|
} |
|
|
|
// keySlice is a type that implements sorting of entries values. |
|
type keySlice []uint32 |
|
|
|
func (ks keySlice) Len() int { |
|
return len(ks) |
|
} |
|
|
|
func (ks keySlice) Less(i, j int) bool { |
|
return (ks[i] >> 15) < (ks[j] >> 15) |
|
} |
|
|
|
func (ks keySlice) Swap(i, j int) { |
|
ks[i], ks[j] = ks[j], ks[i] |
|
} |
|
|
|
func (st *stringList) buildList() []uint32 { |
|
sort.Sort(keySlice(st.entries)) |
|
return st.entries |
|
} |
|
|
|
type stringWriter interface { |
|
io.Writer |
|
WriteString(string) (int, error) |
|
} |
|
|
|
func (st *stringList) WriteTo(out stringWriter, name string) { |
|
list := st.buildList() |
|
if *verbose { |
|
fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData)) |
|
} |
|
|
|
values := "kOpenSSL" + name + "Values" |
|
out.WriteString("const uint32_t " + values + "[] = {\n") |
|
for _, v := range list { |
|
fmt.Fprintf(out, " 0x%x,\n", v) |
|
} |
|
out.WriteString("};\n\n") |
|
out.WriteString("const size_t " + values + "Len = sizeof(" + values + ") / sizeof(" + values + "[0]);\n\n") |
|
|
|
stringData := "kOpenSSL" + name + "StringData" |
|
out.WriteString("const char " + stringData + "[] =\n \"") |
|
for i, c := range st.stringData { |
|
if c == 0 { |
|
out.WriteString("\\0\"\n \"") |
|
continue |
|
} |
|
out.Write(st.stringData[i : i+1]) |
|
} |
|
out.WriteString("\";\n\n") |
|
} |
|
|
|
type errorData struct { |
|
reasons *stringList |
|
libraryMap map[string]uint32 |
|
} |
|
|
|
func (e *errorData) readErrorDataFile(filename string) error { |
|
inFile, err := os.Open(filename) |
|
if err != nil { |
|
return err |
|
} |
|
defer inFile.Close() |
|
|
|
scanner := bufio.NewScanner(inFile) |
|
comma := []byte(",") |
|
|
|
lineNo := 0 |
|
for scanner.Scan() { |
|
lineNo++ |
|
|
|
line := scanner.Bytes() |
|
if len(line) == 0 { |
|
continue |
|
} |
|
parts := bytes.Split(line, comma) |
|
if len(parts) != 3 { |
|
return fmt.Errorf("bad line %d in %s: found %d values but want 3", lineNo, filename, len(parts)) |
|
} |
|
libNum, ok := e.libraryMap[string(parts[0])] |
|
if !ok { |
|
return fmt.Errorf("bad line %d in %s: unknown library", lineNo, filename) |
|
} |
|
if libNum >= 64 { |
|
return fmt.Errorf("bad line %d in %s: library value too large", lineNo, filename) |
|
} |
|
key, err := strconv.ParseUint(string(parts[1]), 10 /* base */, 32 /* bit size */) |
|
if err != nil { |
|
return fmt.Errorf("bad line %d in %s: %s", lineNo, filename, err) |
|
} |
|
if key >= 2048 { |
|
return fmt.Errorf("bad line %d in %s: key too large", lineNo, filename) |
|
} |
|
value := string(parts[2]) |
|
|
|
listKey := libNum<<26 | uint32(key)<<15 |
|
|
|
err = e.reasons.Add(listKey, value) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return scanner.Err() |
|
} |
|
|
|
func main() { |
|
flag.Parse() |
|
|
|
e := &errorData{ |
|
reasons: newStringList(), |
|
libraryMap: make(map[string]uint32), |
|
} |
|
for i, name := range libraryNames { |
|
e.libraryMap[name] = uint32(i) + 1 |
|
} |
|
|
|
cwd, err := os.Open(".") |
|
if err != nil { |
|
panic(err) |
|
} |
|
names, err := cwd.Readdirnames(-1) |
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
sort.Strings(names) |
|
for _, name := range names { |
|
if !strings.HasSuffix(name, ".errordata") { |
|
continue |
|
} |
|
if err := e.readErrorDataFile(name); err != nil { |
|
panic(err) |
|
} |
|
} |
|
|
|
out := os.Stdout |
|
|
|
out.WriteString(`/* Copyright (c) 2015, Google Inc. |
|
* |
|
* Permission to use, copy, modify, and/or distribute this software for any |
|
* purpose with or without fee is hereby granted, provided that the above |
|
* copyright notice and this permission notice appear in all copies. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ |
|
|
|
/* This file was generated by err_data_generate.go. */ |
|
|
|
#include <openssl/base.h> |
|
#include <openssl/err.h> |
|
#include <openssl/type_check.h> |
|
|
|
|
|
`) |
|
|
|
for i, name := range libraryNames { |
|
fmt.Fprintf(out, "OPENSSL_STATIC_ASSERT(ERR_LIB_%s == %d, \"library value changed\");\n", name, i+1) |
|
} |
|
fmt.Fprintf(out, "OPENSSL_STATIC_ASSERT(ERR_NUM_LIBS == %d, \"number of libraries changed\");\n", len(libraryNames)+1) |
|
out.WriteString("\n") |
|
|
|
e.reasons.WriteTo(out, "Reason") |
|
}
|
|
|