blob: 28887c0545ae1d26640c9f4793bc93c9d7989a1f [file] [log] [blame]
David Benjamin6cc90382016-04-23 23:28:09 -04001// Copyright (c) 2016, Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15package main
16
17import (
18 "bufio"
19 "bytes"
20 "errors"
21 "fmt"
22 "io/ioutil"
23 "os"
24 "os/exec"
25 "sort"
26 "strconv"
27 "strings"
28)
29
30func sanitizeName(in string) string {
31 in = strings.Replace(in, "-", "_", -1)
32 in = strings.Replace(in, ".", "_", -1)
33 in = strings.Replace(in, " ", "_", -1)
34 return in
35}
36
37type object struct {
38 name string
39 // shortName and longName are the short and long names, respectively. If
40 // one is missing, it takes the value of the other, but the
41 // corresponding SN_foo or LN_foo macro is not defined.
42 shortName, longName string
43 hasShortName, hasLongName bool
44 oid []int
45 encoded []byte
46}
47
48type objects struct {
49 // byNID is the list of all objects, indexed by nid.
50 byNID []object
51 // nameToNID is a map from object name to nid.
52 nameToNID map[string]int
53}
54
55func readNumbers(path string) (nameToNID map[string]int, numNIDs int, err error) {
56 in, err := os.Open(path)
57 if err != nil {
58 return nil, 0, err
59 }
60 defer in.Close()
61
62 nameToNID = make(map[string]int)
63 nidsSeen := make(map[int]struct{})
64
65 // Reserve NID 0 for NID_undef.
66 numNIDs = 1
67 nameToNID["undef"] = 0
68 nidsSeen[0] = struct{}{}
69
70 var lineNo int
71 scanner := bufio.NewScanner(in)
72 for scanner.Scan() {
73 line := scanner.Text()
74 lineNo++
75 withLine := func(err error) error {
76 return fmt.Errorf("%s:%d: %s", path, lineNo, err)
77 }
78
79 fields := strings.Fields(line)
80 if len(fields) == 0 {
81 // Skip blank lines.
82 continue
83 }
84
85 // Each line is a name and a nid, separated by space.
86 if len(fields) != 2 {
87 return nil, 0, withLine(errors.New("syntax error"))
88 }
89 name := fields[0]
90 nid, err := strconv.Atoi(fields[1])
91 if err != nil {
92 return nil, 0, withLine(err)
93 }
94 if nid < 0 {
95 return nil, 0, withLine(errors.New("invalid NID"))
96 }
97
98 // NID_undef is implicitly defined.
99 if name == "undef" && nid == 0 {
100 continue
101 }
102
103 // Forbid duplicates.
104 if _, ok := nameToNID[name]; ok {
105 return nil, 0, withLine(fmt.Errorf("duplicate name %q", name))
106 }
107 if _, ok := nidsSeen[nid]; ok {
108 return nil, 0, withLine(fmt.Errorf("duplicate NID %d", nid))
109 }
110
111 nameToNID[name] = nid
112 nidsSeen[nid] = struct{}{}
113
114 if nid >= numNIDs {
115 numNIDs = nid + 1
116 }
117 }
118 if err := scanner.Err(); err != nil {
119 return nil, 0, fmt.Errorf("error reading %s: %s", path, err)
120 }
121
122 return nameToNID, numNIDs, nil
123}
124
125func parseOID(aliases map[string][]int, in []string) (oid []int, err error) {
126 if len(in) == 0 {
127 return
128 }
129
130 // The first entry may be a reference to a previous alias.
131 if alias, ok := aliases[sanitizeName(in[0])]; ok {
132 in = in[1:]
133 oid = append(oid, alias...)
134 }
135
136 for _, c := range in {
137 val, err := strconv.Atoi(c)
138 if err != nil {
139 return nil, err
140 }
141 if val < 0 {
142 return nil, fmt.Errorf("negative component")
143 }
144 oid = append(oid, val)
145 }
146 return
147}
148
149func appendBase128(dst []byte, value int) []byte {
150 // Zero is encoded with one, not zero bytes.
151 if value == 0 {
152 return append(dst, 0)
153 }
154
155 // Count how many bytes are needed.
156 var l int
157 for n := value; n != 0; n >>= 7 {
158 l++
159 }
160 for ; l > 0; l-- {
161 b := byte(value>>uint(7*(l-1))) & 0x7f
162 if l > 1 {
163 b |= 0x80
164 }
165 dst = append(dst, b)
166 }
167 return dst
168}
169
170func encodeOID(oid []int) []byte {
171 if len(oid) < 2 {
172 return nil
173 }
174
175 var der []byte
176 der = appendBase128(der, 40*oid[0]+oid[1])
177 for _, value := range oid[2:] {
178 der = appendBase128(der, value)
179 }
180 return der
181}
182
183func readObjects(numPath, objectsPath string) (*objects, error) {
184 nameToNID, numNIDs, err := readNumbers(numPath)
185 if err != nil {
186 return nil, err
187 }
188
189 in, err := os.Open(objectsPath)
190 if err != nil {
191 return nil, err
192 }
193 defer in.Close()
194
195 // Implicitly define NID_undef.
196 objs := &objects{
197 byNID: make([]object, numNIDs),
198 nameToNID: make(map[string]int),
199 }
200
201 objs.byNID[0] = object{
202 name: "undef",
203 shortName: "UNDEF",
204 longName: "undefined",
205 hasShortName: true,
206 hasLongName: true,
207 }
208 objs.nameToNID["undef"] = 0
209
210 var module, nextName string
211 var lineNo int
212 longNamesSeen := make(map[string]struct{})
213 shortNamesSeen := make(map[string]struct{})
214 aliases := make(map[string][]int)
215 scanner := bufio.NewScanner(in)
216 for scanner.Scan() {
217 line := scanner.Text()
218 lineNo++
219 withLine := func(err error) error {
220 return fmt.Errorf("%s:%d: %s", objectsPath, lineNo, err)
221 }
222
223 // Remove comments.
224 idx := strings.IndexRune(line, '#')
225 if idx >= 0 {
226 line = line[:idx]
227 }
228
229 // Skip empty lines.
230 line = strings.TrimSpace(line)
231 if len(line) == 0 {
232 continue
233 }
234
235 if line[0] == '!' {
236 args := strings.Fields(line)
237 switch args[0] {
238 case "!module":
239 if len(args) != 2 {
240 return nil, withLine(errors.New("too many arguments"))
241 }
242 module = sanitizeName(args[1]) + "_"
243 case "!global":
244 module = ""
245 case "!Cname":
246 // !Cname directives override the name for the
247 // next object.
248 if len(args) != 2 {
249 return nil, withLine(errors.New("too many arguments"))
250 }
251 nextName = sanitizeName(args[1])
252 case "!Alias":
253 // !Alias directives define an alias for an OID
254 // without emitting an object.
255 if len(nextName) != 0 {
256 return nil, withLine(errors.New("!Cname directives may not modify !Alias directives."))
257 }
258 if len(args) < 3 {
259 return nil, withLine(errors.New("not enough arguments"))
260 }
261 aliasName := module + sanitizeName(args[1])
262 oid, err := parseOID(aliases, args[2:])
263 if err != nil {
264 return nil, withLine(err)
265 }
266 if _, ok := aliases[aliasName]; ok {
267 return nil, withLine(fmt.Errorf("duplicate name '%s'", aliasName))
268 }
269 aliases[aliasName] = oid
270 default:
271 return nil, withLine(fmt.Errorf("unknown directive '%s'", args[0]))
272 }
273 continue
274 }
275
276 fields := strings.Split(line, ":")
277 if len(fields) < 2 || len(fields) > 3 {
278 return nil, withLine(errors.New("invalid field count"))
279 }
280
281 obj := object{name: nextName}
282 nextName = ""
283
284 var err error
285 obj.oid, err = parseOID(aliases, strings.Fields(fields[0]))
286 if err != nil {
287 return nil, withLine(err)
288 }
289 obj.encoded = encodeOID(obj.oid)
290
291 obj.shortName = strings.TrimSpace(fields[1])
292 if len(fields) == 3 {
293 obj.longName = strings.TrimSpace(fields[2])
294 }
295
296 // Long and short names default to each other if missing.
297 if len(obj.shortName) == 0 {
298 obj.shortName = obj.longName
299 } else {
300 obj.hasShortName = true
301 }
302 if len(obj.longName) == 0 {
303 obj.longName = obj.shortName
304 } else {
305 obj.hasLongName = true
306 }
307 if len(obj.shortName) == 0 || len(obj.longName) == 0 {
308 return nil, withLine(errors.New("object with no name"))
309 }
310
311 // If not already specified, prefer the long name if it has no
312 // spaces, otherwise the short name.
313 if len(obj.name) == 0 && strings.IndexRune(obj.longName, ' ') < 0 {
314 obj.name = sanitizeName(obj.longName)
315 }
316 if len(obj.name) == 0 {
317 obj.name = sanitizeName(obj.shortName)
318 }
319 obj.name = module + obj.name
320
321 // Check for duplicate names.
322 if _, ok := aliases[obj.name]; ok {
323 return nil, withLine(fmt.Errorf("duplicate name '%s'", obj.name))
324 }
325 if _, ok := shortNamesSeen[obj.shortName]; ok && len(obj.shortName) > 0 {
326 return nil, withLine(fmt.Errorf("duplicate short name '%s'", obj.shortName))
327 }
328 if _, ok := longNamesSeen[obj.longName]; ok && len(obj.longName) > 0 {
329 return nil, withLine(fmt.Errorf("duplicate long name '%s'", obj.longName))
330 }
331
332 // Allocate a NID.
333 nid, ok := nameToNID[obj.name]
334 if !ok {
335 nid = len(objs.byNID)
336 objs.byNID = append(objs.byNID, object{})
337 }
338
339 objs.byNID[nid] = obj
340 objs.nameToNID[obj.name] = nid
341
342 longNamesSeen[obj.longName] = struct{}{}
343 shortNamesSeen[obj.shortName] = struct{}{}
344 aliases[obj.name] = obj.oid
345 }
346 if err := scanner.Err(); err != nil {
347 return nil, err
348 }
349
350 return objs, nil
351}
352
353func writeNumbers(path string, objs *objects) error {
354 out, err := os.Create(path)
355 if err != nil {
356 return err
357 }
358 defer out.Close()
359
360 for nid, obj := range objs.byNID {
361 if len(obj.name) == 0 {
362 continue
363 }
364 if _, err := fmt.Fprintf(out, "%s\t\t%d\n", obj.name, nid); err != nil {
365 return err
366 }
367 }
368 return nil
369}
370
371func clangFormat(input string) (string, error) {
372 var b bytes.Buffer
373 cmd := exec.Command("clang-format")
374 cmd.Stdin = strings.NewReader(input)
375 cmd.Stdout = &b
376 cmd.Stderr = os.Stderr
377 if err := cmd.Run(); err != nil {
378 return "", err
379 }
380 return b.String(), nil
381}
382
383func writeHeader(path string, objs *objects) error {
384 var b bytes.Buffer
385 fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
386 * All rights reserved.
387 *
388 * This package is an SSL implementation written
389 * by Eric Young (eay@cryptsoft.com).
390 * The implementation was written so as to conform with Netscapes SSL.
391 *
392 * This library is free for commercial and non-commercial use as long as
393 * the following conditions are aheared to. The following conditions
394 * apply to all code found in this distribution, be it the RC4, RSA,
395 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
396 * included with this distribution is covered by the same copyright terms
397 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
398 *
399 * Copyright remains Eric Young's, and as such any Copyright notices in
400 * the code are not to be removed.
401 * If this package is used in a product, Eric Young should be given attribution
402 * as the author of the parts of the library used.
403 * This can be in the form of a textual message at program startup or
404 * in documentation (online or textual) provided with the package.
405 *
406 * Redistribution and use in source and binary forms, with or without
407 * modification, are permitted provided that the following conditions
408 * are met:
409 * 1. Redistributions of source code must retain the copyright
410 * notice, this list of conditions and the following disclaimer.
411 * 2. Redistributions in binary form must reproduce the above copyright
412 * notice, this list of conditions and the following disclaimer in the
413 * documentation and/or other materials provided with the distribution.
414 * 3. All advertising materials mentioning features or use of this software
415 * must display the following acknowledgement:
416 * "This product includes cryptographic software written by
417 * Eric Young (eay@cryptsoft.com)"
418 * The word 'cryptographic' can be left out if the rouines from the library
419 * being used are not cryptographic related :-).
420 * 4. If you include any Windows specific code (or a derivative thereof) from
421 * the apps directory (application code) you must include an acknowledgement:
422 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
423 *
424 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND
425 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
426 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
427 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
428 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
429 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
430 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
431 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
432 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
433 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
434 * SUCH DAMAGE.
435 *
436 * The licence and distribution terms for any publically available version or
437 * derivative of this code cannot be changed. i.e. this code cannot simply be
438 * copied and put under another distribution licence
439 * [including the GNU Public Licence.] */
440
441/* This file is generated by crypto/obj/objects.go. */
442
443#ifndef OPENSSL_HEADER_NID_H
444#define OPENSSL_HEADER_NID_H
445
446#include <openssl/base.h>
447
448#if defined(__cplusplus)
449extern "C" {
450#endif
451
452
453/* The nid library provides numbered values for ASN.1 object identifiers and
454 * other symbols. These values are used by other libraries to identify
455 * cryptographic primitives.
456 *
457 * A separate objects library, obj.h, provides functions for converting between
458 * nids and object identifiers. However it depends on large internal tables with
459 * the encodings of every nid defined. Consumers concerned with binary size
460 * should instead embed the encodings of the few consumed OIDs and compare
461 * against those.
462 *
463 * These values should not be used outside of a single process; they are not
464 * stable identifiers. */
465
466
467`)
468
469 for nid, obj := range objs.byNID {
470 if len(obj.name) == 0 {
471 continue
472 }
473
474 if obj.hasShortName {
475 fmt.Fprintf(&b, "#define SN_%s \"%s\"\n", obj.name, obj.shortName)
476 }
477 if obj.hasLongName {
478 fmt.Fprintf(&b, "#define LN_%s \"%s\"\n", obj.name, obj.longName)
479 }
480 fmt.Fprintf(&b, "#define NID_%s %d\n", obj.name, nid)
481
482 // Although NID_undef does not have an OID, OpenSSL emits
483 // OBJ_undef as if it were zero.
484 oid := obj.oid
485 if nid == 0 {
486 oid = []int{0}
487 }
488 if len(oid) != 0 {
489 var oidStr string
490 for _, val := range oid {
491 if len(oidStr) != 0 {
492 oidStr += ","
493 }
494 oidStr += fmt.Sprintf("%dL", val)
495 }
496
497 fmt.Fprintf(&b, "#define OBJ_%s %s\n", obj.name, oidStr)
498 }
499
500 fmt.Fprintf(&b, "\n")
501 }
502
503 fmt.Fprintf(&b, `
504#if defined(__cplusplus)
505} /* extern C */
506#endif
507
508#endif /* OPENSSL_HEADER_NID_H */
509`)
510
511 formatted, err := clangFormat(b.String())
512 if err != nil {
513 return err
514 }
515
516 return ioutil.WriteFile(path, []byte(formatted), 0666)
517}
518
519// TODO(davidben): Replace this with sort.Slice once Go 1.8 is sufficiently
520// common.
521type nidSorter struct {
522 nids []int
523 objs *objects
524 cmp func(a, b object) bool
525}
526
527func (a nidSorter) obj(i int) object { return a.objs.byNID[a.nids[i]] }
528func (a nidSorter) Len() int { return len(a.nids) }
529func (a nidSorter) Swap(i, j int) { a.nids[i], a.nids[j] = a.nids[j], a.nids[i] }
530func (a nidSorter) Less(i, j int) bool { return a.cmp(a.obj(i), a.obj(j)) }
531
532func sortNIDs(nids []int, objs *objects, cmp func(a, b object) bool) {
533 sort.Sort(&nidSorter{nids, objs, cmp})
534}
535
536func writeData(path string, objs *objects) error {
537 var b bytes.Buffer
538 fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
539 * All rights reserved.
540 *
541 * This package is an SSL implementation written
542 * by Eric Young (eay@cryptsoft.com).
543 * The implementation was written so as to conform with Netscapes SSL.
544 *
545 * This library is free for commercial and non-commercial use as long as
546 * the following conditions are aheared to. The following conditions
547 * apply to all code found in this distribution, be it the RC4, RSA,
548 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
549 * included with this distribution is covered by the same copyright terms
550 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
551 *
552 * Copyright remains Eric Young's, and as such any Copyright notices in
553 * the code are not to be removed.
554 * If this package is used in a product, Eric Young should be given attribution
555 * as the author of the parts of the library used.
556 * This can be in the form of a textual message at program startup or
557 * in documentation (online or textual) provided with the package.
558 *
559 * Redistribution and use in source and binary forms, with or without
560 * modification, are permitted provided that the following conditions
561 * are met:
562 * 1. Redistributions of source code must retain the copyright
563 * notice, this list of conditions and the following disclaimer.
564 * 2. Redistributions in binary form must reproduce the above copyright
565 * notice, this list of conditions and the following disclaimer in the
566 * documentation and/or other materials provided with the distribution.
567 * 3. All advertising materials mentioning features or use of this software
568 * must display the following acknowledgement:
569 * "This product includes cryptographic software written by
570 * Eric Young (eay@cryptsoft.com)"
571 * The word 'cryptographic' can be left out if the rouines from the library
572 * being used are not cryptographic related :-).
573 * 4. If you include any Windows specific code (or a derivative thereof) from
574 * the apps directory (application code) you must include an acknowledgement:
575 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
576 *
577 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND
578 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
579 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
580 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
581 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
582 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
583 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
584 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
585 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
586 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
587 * SUCH DAMAGE.
588 *
589 * The licence and distribution terms for any publically available version or
590 * derivative of this code cannot be changed. i.e. this code cannot simply be
591 * copied and put under another distribution licence
592 * [including the GNU Public Licence.] */
593
594/* This file is generated by crypto/obj/objects.go. */
595
596
597`)
598
599 fmt.Fprintf(&b, "#define NUM_NID %d\n", len(objs.byNID))
600
601 // Emit each object's DER encoding, concatenated, and save the offsets.
602 fmt.Fprintf(&b, "\nstatic const uint8_t kObjectData[] = {\n")
603 offsets := make([]int, len(objs.byNID))
604 var nextOffset int
605 for nid, obj := range objs.byNID {
606 if len(obj.name) == 0 || len(obj.encoded) == 0 {
607 offsets[nid] = -1
608 continue
609 }
610
611 offsets[nid] = nextOffset
612 nextOffset += len(obj.encoded)
613 fmt.Fprintf(&b, "/* NID_%s */\n", obj.name)
614 for _, val := range obj.encoded {
615 fmt.Fprintf(&b, "0x%02x, ", val)
616 }
617 fmt.Fprintf(&b, "\n")
618 }
619 fmt.Fprintf(&b, "};\n")
620
621 // Emit an ASN1_OBJECT for each object.
622 fmt.Fprintf(&b, "\nstatic const ASN1_OBJECT kObjects[NUM_NID] = {\n")
623 for nid, obj := range objs.byNID {
624 if len(obj.name) == 0 {
625 fmt.Fprintf(&b, "{NULL, NULL, NID_undef, 0, NULL, 0},\n")
626 continue
627 }
628
629 fmt.Fprintf(&b, "{\"%s\", \"%s\", NID_%s, ", obj.shortName, obj.longName, obj.name)
630 if offset := offsets[nid]; offset >= 0 {
631 fmt.Fprintf(&b, "%d, &kObjectData[%d], 0},\n", len(obj.encoded), offset)
632 } else {
633 fmt.Fprintf(&b, "0, NULL, 0},\n")
634 }
635 }
636 fmt.Fprintf(&b, "};\n")
637
638 // Emit a list of NIDs sorted by short name.
639 var nids []int
640 for nid, obj := range objs.byNID {
641 if len(obj.name) == 0 || len(obj.shortName) == 0 {
642 continue
643 }
644 nids = append(nids, nid)
645 }
646 sortNIDs(nids, objs, func(a, b object) bool { return a.shortName < b.shortName })
647
648 fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInShortNameOrder[] = {\n")
649 for _, nid := range nids {
650 fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].shortName)
651 }
652 fmt.Fprintf(&b, "};\n")
653
654 // Emit a list of NIDs sorted by long name.
655 nids = nil
656 for nid, obj := range objs.byNID {
657 if len(obj.name) == 0 || len(obj.longName) == 0 {
658 continue
659 }
660 nids = append(nids, nid)
661 }
662 sortNIDs(nids, objs, func(a, b object) bool { return a.longName < b.longName })
663
664 fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInLongNameOrder[] = {\n")
665 for _, nid := range nids {
666 fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].longName)
667 }
668 fmt.Fprintf(&b, "};\n")
669
670 // Emit a list of NIDs sorted by OID.
671 nids = nil
672 for nid, obj := range objs.byNID {
673 if len(obj.name) == 0 || len(obj.encoded) == 0 {
674 continue
675 }
676 nids = append(nids, nid)
677 }
678 sortNIDs(nids, objs, func(a, b object) bool {
679 // This comparison must match the definition of |obj_cmp|.
680 if len(a.encoded) < len(b.encoded) {
681 return true
682 }
683 if len(a.encoded) > len(b.encoded) {
684 return false
685 }
686 return bytes.Compare(a.encoded, b.encoded) < 0
687 })
688
689 fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInOIDOrder[] = {\n")
690 for _, nid := range nids {
691 obj := objs.byNID[nid]
692 fmt.Fprintf(&b, "%d /* ", nid)
693 for i, c := range obj.oid {
694 if i > 0 {
695 fmt.Fprintf(&b, ".")
696 }
697 fmt.Fprintf(&b, "%d", c)
698 }
699 fmt.Fprintf(&b, " (OBJ_%s) */,\n", obj.name)
700 }
701 fmt.Fprintf(&b, "};\n")
702
703 formatted, err := clangFormat(b.String())
704 if err != nil {
705 return err
706 }
707
708 return ioutil.WriteFile(path, []byte(formatted), 0666)
709}
710
711func main() {
712 objs, err := readObjects("obj_mac.num", "objects.txt")
713 if err != nil {
714 fmt.Fprintf(os.Stderr, "Error reading objects: %s\n", err)
715 os.Exit(1)
716 }
717
718 if err := writeNumbers("obj_mac.num", objs); err != nil {
719 fmt.Fprintf(os.Stderr, "Error writing numbers: %s\n", err)
720 os.Exit(1)
721 }
722
723 if err := writeHeader("../../include/openssl/nid.h", objs); err != nil {
724 fmt.Fprintf(os.Stderr, "Error writing header: %s\n", err)
725 os.Exit(1)
726 }
727
728 if err := writeData("obj_dat.h", objs); err != nil {
729 fmt.Fprintf(os.Stderr, "Error writing data: %s\n", err)
730 os.Exit(1)
731 }
732}