| // Copyright (c) 2016, 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" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "os/exec" |
| "sort" |
| "strconv" |
| "strings" |
| ) |
| |
| func sanitizeName(in string) string { |
| in = strings.Replace(in, "-", "_", -1) |
| in = strings.Replace(in, ".", "_", -1) |
| in = strings.Replace(in, " ", "_", -1) |
| return in |
| } |
| |
| type object struct { |
| name string |
| // shortName and longName are the short and long names, respectively. If |
| // one is missing, it takes the value of the other, but the |
| // corresponding SN_foo or LN_foo macro is not defined. |
| shortName, longName string |
| hasShortName, hasLongName bool |
| oid []int |
| encoded []byte |
| } |
| |
| type objects struct { |
| // byNID is the list of all objects, indexed by nid. |
| byNID []object |
| // nameToNID is a map from object name to nid. |
| nameToNID map[string]int |
| } |
| |
| func readNumbers(path string) (nameToNID map[string]int, numNIDs int, err error) { |
| in, err := os.Open(path) |
| if err != nil { |
| return nil, 0, err |
| } |
| defer in.Close() |
| |
| nameToNID = make(map[string]int) |
| nidsSeen := make(map[int]struct{}) |
| |
| // Reserve NID 0 for NID_undef. |
| numNIDs = 1 |
| nameToNID["undef"] = 0 |
| nidsSeen[0] = struct{}{} |
| |
| var lineNo int |
| scanner := bufio.NewScanner(in) |
| for scanner.Scan() { |
| line := scanner.Text() |
| lineNo++ |
| withLine := func(err error) error { |
| return fmt.Errorf("%s:%d: %s", path, lineNo, err) |
| } |
| |
| fields := strings.Fields(line) |
| if len(fields) == 0 { |
| // Skip blank lines. |
| continue |
| } |
| |
| // Each line is a name and a nid, separated by space. |
| if len(fields) != 2 { |
| return nil, 0, withLine(errors.New("syntax error")) |
| } |
| name := fields[0] |
| nid, err := strconv.Atoi(fields[1]) |
| if err != nil { |
| return nil, 0, withLine(err) |
| } |
| if nid < 0 { |
| return nil, 0, withLine(errors.New("invalid NID")) |
| } |
| |
| // NID_undef is implicitly defined. |
| if name == "undef" && nid == 0 { |
| continue |
| } |
| |
| // Forbid duplicates. |
| if _, ok := nameToNID[name]; ok { |
| return nil, 0, withLine(fmt.Errorf("duplicate name %q", name)) |
| } |
| if _, ok := nidsSeen[nid]; ok { |
| return nil, 0, withLine(fmt.Errorf("duplicate NID %d", nid)) |
| } |
| |
| nameToNID[name] = nid |
| nidsSeen[nid] = struct{}{} |
| |
| if nid >= numNIDs { |
| numNIDs = nid + 1 |
| } |
| } |
| if err := scanner.Err(); err != nil { |
| return nil, 0, fmt.Errorf("error reading %s: %s", path, err) |
| } |
| |
| return nameToNID, numNIDs, nil |
| } |
| |
| func parseOID(aliases map[string][]int, in []string) (oid []int, err error) { |
| if len(in) == 0 { |
| return |
| } |
| |
| // The first entry may be a reference to a previous alias. |
| if alias, ok := aliases[sanitizeName(in[0])]; ok { |
| in = in[1:] |
| oid = append(oid, alias...) |
| } |
| |
| for _, c := range in { |
| val, err := strconv.Atoi(c) |
| if err != nil { |
| return nil, err |
| } |
| if val < 0 { |
| return nil, fmt.Errorf("negative component") |
| } |
| oid = append(oid, val) |
| } |
| return |
| } |
| |
| func appendBase128(dst []byte, value int) []byte { |
| // Zero is encoded with one, not zero bytes. |
| if value == 0 { |
| return append(dst, 0) |
| } |
| |
| // Count how many bytes are needed. |
| var l int |
| for n := value; n != 0; n >>= 7 { |
| l++ |
| } |
| for ; l > 0; l-- { |
| b := byte(value>>uint(7*(l-1))) & 0x7f |
| if l > 1 { |
| b |= 0x80 |
| } |
| dst = append(dst, b) |
| } |
| return dst |
| } |
| |
| func encodeOID(oid []int) []byte { |
| if len(oid) < 2 { |
| return nil |
| } |
| |
| var der []byte |
| der = appendBase128(der, 40*oid[0]+oid[1]) |
| for _, value := range oid[2:] { |
| der = appendBase128(der, value) |
| } |
| return der |
| } |
| |
| func readObjects(numPath, objectsPath string) (*objects, error) { |
| nameToNID, numNIDs, err := readNumbers(numPath) |
| if err != nil { |
| return nil, err |
| } |
| |
| in, err := os.Open(objectsPath) |
| if err != nil { |
| return nil, err |
| } |
| defer in.Close() |
| |
| // Implicitly define NID_undef. |
| objs := &objects{ |
| byNID: make([]object, numNIDs), |
| nameToNID: make(map[string]int), |
| } |
| |
| objs.byNID[0] = object{ |
| name: "undef", |
| shortName: "UNDEF", |
| longName: "undefined", |
| hasShortName: true, |
| hasLongName: true, |
| } |
| objs.nameToNID["undef"] = 0 |
| |
| var module, nextName string |
| var lineNo int |
| longNamesSeen := make(map[string]struct{}) |
| shortNamesSeen := make(map[string]struct{}) |
| aliases := make(map[string][]int) |
| scanner := bufio.NewScanner(in) |
| for scanner.Scan() { |
| line := scanner.Text() |
| lineNo++ |
| withLine := func(err error) error { |
| return fmt.Errorf("%s:%d: %s", objectsPath, lineNo, err) |
| } |
| |
| // Remove comments. |
| idx := strings.IndexRune(line, '#') |
| if idx >= 0 { |
| line = line[:idx] |
| } |
| |
| // Skip empty lines. |
| line = strings.TrimSpace(line) |
| if len(line) == 0 { |
| continue |
| } |
| |
| if line[0] == '!' { |
| args := strings.Fields(line) |
| switch args[0] { |
| case "!module": |
| if len(args) != 2 { |
| return nil, withLine(errors.New("too many arguments")) |
| } |
| module = sanitizeName(args[1]) + "_" |
| case "!global": |
| module = "" |
| case "!Cname": |
| // !Cname directives override the name for the |
| // next object. |
| if len(args) != 2 { |
| return nil, withLine(errors.New("too many arguments")) |
| } |
| nextName = sanitizeName(args[1]) |
| case "!Alias": |
| // !Alias directives define an alias for an OID |
| // without emitting an object. |
| if len(nextName) != 0 { |
| return nil, withLine(errors.New("!Cname directives may not modify !Alias directives.")) |
| } |
| if len(args) < 3 { |
| return nil, withLine(errors.New("not enough arguments")) |
| } |
| aliasName := module + sanitizeName(args[1]) |
| oid, err := parseOID(aliases, args[2:]) |
| if err != nil { |
| return nil, withLine(err) |
| } |
| if _, ok := aliases[aliasName]; ok { |
| return nil, withLine(fmt.Errorf("duplicate name '%s'", aliasName)) |
| } |
| aliases[aliasName] = oid |
| default: |
| return nil, withLine(fmt.Errorf("unknown directive '%s'", args[0])) |
| } |
| continue |
| } |
| |
| fields := strings.Split(line, ":") |
| if len(fields) < 2 || len(fields) > 3 { |
| return nil, withLine(errors.New("invalid field count")) |
| } |
| |
| obj := object{name: nextName} |
| nextName = "" |
| |
| var err error |
| obj.oid, err = parseOID(aliases, strings.Fields(fields[0])) |
| if err != nil { |
| return nil, withLine(err) |
| } |
| obj.encoded = encodeOID(obj.oid) |
| |
| obj.shortName = strings.TrimSpace(fields[1]) |
| if len(fields) == 3 { |
| obj.longName = strings.TrimSpace(fields[2]) |
| } |
| |
| // Long and short names default to each other if missing. |
| if len(obj.shortName) == 0 { |
| obj.shortName = obj.longName |
| } else { |
| obj.hasShortName = true |
| } |
| if len(obj.longName) == 0 { |
| obj.longName = obj.shortName |
| } else { |
| obj.hasLongName = true |
| } |
| if len(obj.shortName) == 0 || len(obj.longName) == 0 { |
| return nil, withLine(errors.New("object with no name")) |
| } |
| |
| // If not already specified, prefer the long name if it has no |
| // spaces, otherwise the short name. |
| if len(obj.name) == 0 && strings.IndexRune(obj.longName, ' ') < 0 { |
| obj.name = sanitizeName(obj.longName) |
| } |
| if len(obj.name) == 0 { |
| obj.name = sanitizeName(obj.shortName) |
| } |
| obj.name = module + obj.name |
| |
| // Check for duplicate names. |
| if _, ok := aliases[obj.name]; ok { |
| return nil, withLine(fmt.Errorf("duplicate name '%s'", obj.name)) |
| } |
| if _, ok := shortNamesSeen[obj.shortName]; ok && len(obj.shortName) > 0 { |
| return nil, withLine(fmt.Errorf("duplicate short name '%s'", obj.shortName)) |
| } |
| if _, ok := longNamesSeen[obj.longName]; ok && len(obj.longName) > 0 { |
| return nil, withLine(fmt.Errorf("duplicate long name '%s'", obj.longName)) |
| } |
| |
| // Allocate a NID. |
| nid, ok := nameToNID[obj.name] |
| if !ok { |
| nid = len(objs.byNID) |
| objs.byNID = append(objs.byNID, object{}) |
| } |
| |
| objs.byNID[nid] = obj |
| objs.nameToNID[obj.name] = nid |
| |
| longNamesSeen[obj.longName] = struct{}{} |
| shortNamesSeen[obj.shortName] = struct{}{} |
| aliases[obj.name] = obj.oid |
| } |
| if err := scanner.Err(); err != nil { |
| return nil, err |
| } |
| |
| // The kNIDsIn*Order constants assume each NID fits in a uint16_t. |
| if len(objs.byNID) > 0xffff { |
| return nil, errors.New("too many NIDs allocated") |
| } |
| |
| return objs, nil |
| } |
| |
| func writeNumbers(path string, objs *objects) error { |
| out, err := os.Create(path) |
| if err != nil { |
| return err |
| } |
| defer out.Close() |
| |
| for nid, obj := range objs.byNID { |
| if len(obj.name) == 0 { |
| continue |
| } |
| if _, err := fmt.Fprintf(out, "%s\t\t%d\n", obj.name, nid); err != nil { |
| return err |
| } |
| } |
| return nil |
| } |
| |
| func clangFormat(input string) (string, error) { |
| var b bytes.Buffer |
| cmd := exec.Command("clang-format") |
| cmd.Stdin = strings.NewReader(input) |
| cmd.Stdout = &b |
| cmd.Stderr = os.Stderr |
| if err := cmd.Run(); err != nil { |
| return "", err |
| } |
| return b.String(), nil |
| } |
| |
| func writeHeader(path string, objs *objects) error { |
| var b bytes.Buffer |
| fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) |
| * All rights reserved. |
| * |
| * This package is an SSL implementation written |
| * by Eric Young (eay@cryptsoft.com). |
| * The implementation was written so as to conform with Netscapes SSL. |
| * |
| * This library is free for commercial and non-commercial use as long as |
| * the following conditions are aheared to. The following conditions |
| * apply to all code found in this distribution, be it the RC4, RSA, |
| * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
| * included with this distribution is covered by the same copyright terms |
| * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
| * |
| * Copyright remains Eric Young's, and as such any Copyright notices in |
| * the code are not to be removed. |
| * If this package is used in a product, Eric Young should be given attribution |
| * as the author of the parts of the library used. |
| * This can be in the form of a textual message at program startup or |
| * in documentation (online or textual) provided with the package. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. All advertising materials mentioning features or use of this software |
| * must display the following acknowledgement: |
| * "This product includes cryptographic software written by |
| * Eric Young (eay@cryptsoft.com)" |
| * The word 'cryptographic' can be left out if the rouines from the library |
| * being used are not cryptographic related :-). |
| * 4. If you include any Windows specific code (or a derivative thereof) from |
| * the apps directory (application code) you must include an acknowledgement: |
| * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
| * |
| * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * |
| * The licence and distribution terms for any publically available version or |
| * derivative of this code cannot be changed. i.e. this code cannot simply be |
| * copied and put under another distribution licence |
| * [including the GNU Public Licence.] */ |
| |
| /* This file is generated by crypto/obj/objects.go. */ |
| |
| #ifndef OPENSSL_HEADER_NID_H |
| #define OPENSSL_HEADER_NID_H |
| |
| #include <openssl/base.h> |
| |
| #if defined(__cplusplus) |
| extern "C" { |
| #endif |
| |
| |
| /* The nid library provides numbered values for ASN.1 object identifiers and |
| * other symbols. These values are used by other libraries to identify |
| * cryptographic primitives. |
| * |
| * A separate objects library, obj.h, provides functions for converting between |
| * nids and object identifiers. However it depends on large internal tables with |
| * the encodings of every nid defined. Consumers concerned with binary size |
| * should instead embed the encodings of the few consumed OIDs and compare |
| * against those. |
| * |
| * These values should not be used outside of a single process; they are not |
| * stable identifiers. */ |
| |
| |
| `) |
| |
| for nid, obj := range objs.byNID { |
| if len(obj.name) == 0 { |
| continue |
| } |
| |
| if obj.hasShortName { |
| fmt.Fprintf(&b, "#define SN_%s \"%s\"\n", obj.name, obj.shortName) |
| } |
| if obj.hasLongName { |
| fmt.Fprintf(&b, "#define LN_%s \"%s\"\n", obj.name, obj.longName) |
| } |
| fmt.Fprintf(&b, "#define NID_%s %d\n", obj.name, nid) |
| |
| // Although NID_undef does not have an OID, OpenSSL emits |
| // OBJ_undef as if it were zero. |
| oid := obj.oid |
| if nid == 0 { |
| oid = []int{0} |
| } |
| if len(oid) != 0 { |
| var oidStr string |
| for _, val := range oid { |
| if len(oidStr) != 0 { |
| oidStr += "," |
| } |
| oidStr += fmt.Sprintf("%dL", val) |
| } |
| |
| fmt.Fprintf(&b, "#define OBJ_%s %s\n", obj.name, oidStr) |
| } |
| |
| fmt.Fprintf(&b, "\n") |
| } |
| |
| fmt.Fprintf(&b, ` |
| #if defined(__cplusplus) |
| } /* extern C */ |
| #endif |
| |
| #endif /* OPENSSL_HEADER_NID_H */ |
| `) |
| |
| formatted, err := clangFormat(b.String()) |
| if err != nil { |
| return err |
| } |
| |
| return ioutil.WriteFile(path, []byte(formatted), 0666) |
| } |
| |
| // TODO(davidben): Replace this with sort.Slice once Go 1.8 is sufficiently |
| // common. |
| type nidSorter struct { |
| nids []int |
| objs *objects |
| cmp func(a, b object) bool |
| } |
| |
| func (a nidSorter) obj(i int) object { return a.objs.byNID[a.nids[i]] } |
| func (a nidSorter) Len() int { return len(a.nids) } |
| func (a nidSorter) Swap(i, j int) { a.nids[i], a.nids[j] = a.nids[j], a.nids[i] } |
| func (a nidSorter) Less(i, j int) bool { return a.cmp(a.obj(i), a.obj(j)) } |
| |
| func sortNIDs(nids []int, objs *objects, cmp func(a, b object) bool) { |
| sort.Sort(&nidSorter{nids, objs, cmp}) |
| } |
| |
| func writeData(path string, objs *objects) error { |
| var b bytes.Buffer |
| fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) |
| * All rights reserved. |
| * |
| * This package is an SSL implementation written |
| * by Eric Young (eay@cryptsoft.com). |
| * The implementation was written so as to conform with Netscapes SSL. |
| * |
| * This library is free for commercial and non-commercial use as long as |
| * the following conditions are aheared to. The following conditions |
| * apply to all code found in this distribution, be it the RC4, RSA, |
| * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
| * included with this distribution is covered by the same copyright terms |
| * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
| * |
| * Copyright remains Eric Young's, and as such any Copyright notices in |
| * the code are not to be removed. |
| * If this package is used in a product, Eric Young should be given attribution |
| * as the author of the parts of the library used. |
| * This can be in the form of a textual message at program startup or |
| * in documentation (online or textual) provided with the package. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. All advertising materials mentioning features or use of this software |
| * must display the following acknowledgement: |
| * "This product includes cryptographic software written by |
| * Eric Young (eay@cryptsoft.com)" |
| * The word 'cryptographic' can be left out if the rouines from the library |
| * being used are not cryptographic related :-). |
| * 4. If you include any Windows specific code (or a derivative thereof) from |
| * the apps directory (application code) you must include an acknowledgement: |
| * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
| * |
| * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * |
| * The licence and distribution terms for any publically available version or |
| * derivative of this code cannot be changed. i.e. this code cannot simply be |
| * copied and put under another distribution licence |
| * [including the GNU Public Licence.] */ |
| |
| /* This file is generated by crypto/obj/objects.go. */ |
| |
| |
| `) |
| |
| fmt.Fprintf(&b, "#define NUM_NID %d\n", len(objs.byNID)) |
| |
| // Emit each object's DER encoding, concatenated, and save the offsets. |
| fmt.Fprintf(&b, "\nstatic const uint8_t kObjectData[] = {\n") |
| offsets := make([]int, len(objs.byNID)) |
| var nextOffset int |
| for nid, obj := range objs.byNID { |
| if len(obj.name) == 0 || len(obj.encoded) == 0 { |
| offsets[nid] = -1 |
| continue |
| } |
| |
| offsets[nid] = nextOffset |
| nextOffset += len(obj.encoded) |
| fmt.Fprintf(&b, "/* NID_%s */\n", obj.name) |
| for _, val := range obj.encoded { |
| fmt.Fprintf(&b, "0x%02x, ", val) |
| } |
| fmt.Fprintf(&b, "\n") |
| } |
| fmt.Fprintf(&b, "};\n") |
| |
| // Emit an ASN1_OBJECT for each object. |
| fmt.Fprintf(&b, "\nstatic const ASN1_OBJECT kObjects[NUM_NID] = {\n") |
| for nid, obj := range objs.byNID { |
| if len(obj.name) == 0 { |
| fmt.Fprintf(&b, "{NULL, NULL, NID_undef, 0, NULL, 0},\n") |
| continue |
| } |
| |
| fmt.Fprintf(&b, "{\"%s\", \"%s\", NID_%s, ", obj.shortName, obj.longName, obj.name) |
| if offset := offsets[nid]; offset >= 0 { |
| fmt.Fprintf(&b, "%d, &kObjectData[%d], 0},\n", len(obj.encoded), offset) |
| } else { |
| fmt.Fprintf(&b, "0, NULL, 0},\n") |
| } |
| } |
| fmt.Fprintf(&b, "};\n") |
| |
| // Emit a list of NIDs sorted by short name. |
| var nids []int |
| for nid, obj := range objs.byNID { |
| if len(obj.name) == 0 || len(obj.shortName) == 0 { |
| continue |
| } |
| nids = append(nids, nid) |
| } |
| sortNIDs(nids, objs, func(a, b object) bool { return a.shortName < b.shortName }) |
| |
| fmt.Fprintf(&b, "\nstatic const uint16_t kNIDsInShortNameOrder[] = {\n") |
| for _, nid := range nids { |
| fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].shortName) |
| } |
| fmt.Fprintf(&b, "};\n") |
| |
| // Emit a list of NIDs sorted by long name. |
| nids = nil |
| for nid, obj := range objs.byNID { |
| if len(obj.name) == 0 || len(obj.longName) == 0 { |
| continue |
| } |
| nids = append(nids, nid) |
| } |
| sortNIDs(nids, objs, func(a, b object) bool { return a.longName < b.longName }) |
| |
| fmt.Fprintf(&b, "\nstatic const uint16_t kNIDsInLongNameOrder[] = {\n") |
| for _, nid := range nids { |
| fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].longName) |
| } |
| fmt.Fprintf(&b, "};\n") |
| |
| // Emit a list of NIDs sorted by OID. |
| nids = nil |
| for nid, obj := range objs.byNID { |
| if len(obj.name) == 0 || len(obj.encoded) == 0 { |
| continue |
| } |
| nids = append(nids, nid) |
| } |
| sortNIDs(nids, objs, func(a, b object) bool { |
| // This comparison must match the definition of |obj_cmp|. |
| if len(a.encoded) < len(b.encoded) { |
| return true |
| } |
| if len(a.encoded) > len(b.encoded) { |
| return false |
| } |
| return bytes.Compare(a.encoded, b.encoded) < 0 |
| }) |
| |
| fmt.Fprintf(&b, "\nstatic const uint16_t kNIDsInOIDOrder[] = {\n") |
| for _, nid := range nids { |
| obj := objs.byNID[nid] |
| fmt.Fprintf(&b, "%d /* ", nid) |
| for i, c := range obj.oid { |
| if i > 0 { |
| fmt.Fprintf(&b, ".") |
| } |
| fmt.Fprintf(&b, "%d", c) |
| } |
| fmt.Fprintf(&b, " (OBJ_%s) */,\n", obj.name) |
| } |
| fmt.Fprintf(&b, "};\n") |
| |
| formatted, err := clangFormat(b.String()) |
| if err != nil { |
| return err |
| } |
| |
| return ioutil.WriteFile(path, []byte(formatted), 0666) |
| } |
| |
| func main() { |
| objs, err := readObjects("obj_mac.num", "objects.txt") |
| if err != nil { |
| fmt.Fprintf(os.Stderr, "Error reading objects: %s\n", err) |
| os.Exit(1) |
| } |
| |
| if err := writeNumbers("obj_mac.num", objs); err != nil { |
| fmt.Fprintf(os.Stderr, "Error writing numbers: %s\n", err) |
| os.Exit(1) |
| } |
| |
| if err := writeHeader("../../include/openssl/nid.h", objs); err != nil { |
| fmt.Fprintf(os.Stderr, "Error writing header: %s\n", err) |
| os.Exit(1) |
| } |
| |
| if err := writeData("obj_dat.h", objs); err != nil { |
| fmt.Fprintf(os.Stderr, "Error writing data: %s\n", err) |
| os.Exit(1) |
| } |
| } |