1// 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 // The kNIDsIn*Order constants assume each NID fits in a uint16_t. 351 if len(objs.byNID) > 0xffff { 352 return nil, errors.New("too many NIDs allocated") 353 } 354 355 return objs, nil 356} 357 358func writeNumbers(path string, objs *objects) error { 359 out, err := os.Create(path) 360 if err != nil { 361 return err 362 } 363 defer out.Close() 364 365 for nid, obj := range objs.byNID { 366 if len(obj.name) == 0 { 367 continue 368 } 369 if _, err := fmt.Fprintf(out, "%s\t\t%d\n", obj.name, nid); err != nil { 370 return err 371 } 372 } 373 return nil 374} 375 376func clangFormat(input string) (string, error) { 377 var b bytes.Buffer 378 cmd := exec.Command("clang-format") 379 cmd.Stdin = strings.NewReader(input) 380 cmd.Stdout = &b 381 cmd.Stderr = os.Stderr 382 if err := cmd.Run(); err != nil { 383 return "", err 384 } 385 return b.String(), nil 386} 387 388func writeHeader(path string, objs *objects) error { 389 var b bytes.Buffer 390 fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) 391 * All rights reserved. 392 * 393 * This package is an SSL implementation written 394 * by Eric Young (eay@cryptsoft.com). 395 * The implementation was written so as to conform with Netscapes SSL. 396 * 397 * This library is free for commercial and non-commercial use as long as 398 * the following conditions are aheared to. The following conditions 399 * apply to all code found in this distribution, be it the RC4, RSA, 400 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 401 * included with this distribution is covered by the same copyright terms 402 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 403 * 404 * Copyright remains Eric Young's, and as such any Copyright notices in 405 * the code are not to be removed. 406 * If this package is used in a product, Eric Young should be given attribution 407 * as the author of the parts of the library used. 408 * This can be in the form of a textual message at program startup or 409 * in documentation (online or textual) provided with the package. 410 * 411 * Redistribution and use in source and binary forms, with or without 412 * modification, are permitted provided that the following conditions 413 * are met: 414 * 1. Redistributions of source code must retain the copyright 415 * notice, this list of conditions and the following disclaimer. 416 * 2. Redistributions in binary form must reproduce the above copyright 417 * notice, this list of conditions and the following disclaimer in the 418 * documentation and/or other materials provided with the distribution. 419 * 3. All advertising materials mentioning features or use of this software 420 * must display the following acknowledgement: 421 * "This product includes cryptographic software written by 422 * Eric Young (eay@cryptsoft.com)" 423 * The word 'cryptographic' can be left out if the rouines from the library 424 * being used are not cryptographic related :-). 425 * 4. If you include any Windows specific code (or a derivative thereof) from 426 * the apps directory (application code) you must include an acknowledgement: 427 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 428 * 429 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND 430 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 431 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 432 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 433 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 434 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 435 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 436 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 437 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 438 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 439 * SUCH DAMAGE. 440 * 441 * The licence and distribution terms for any publically available version or 442 * derivative of this code cannot be changed. i.e. this code cannot simply be 443 * copied and put under another distribution licence 444 * [including the GNU Public Licence.] */ 445 446/* This file is generated by crypto/obj/objects.go. */ 447 448#ifndef OPENSSL_HEADER_NID_H 449#define OPENSSL_HEADER_NID_H 450 451#include <openssl/base.h> 452 453#if defined(__cplusplus) 454extern "C" { 455#endif 456 457 458/* The nid library provides numbered values for ASN.1 object identifiers and 459 * other symbols. These values are used by other libraries to identify 460 * cryptographic primitives. 461 * 462 * A separate objects library, obj.h, provides functions for converting between 463 * nids and object identifiers. However it depends on large internal tables with 464 * the encodings of every nid defined. Consumers concerned with binary size 465 * should instead embed the encodings of the few consumed OIDs and compare 466 * against those. 467 * 468 * These values should not be used outside of a single process; they are not 469 * stable identifiers. */ 470 471 472`) 473 474 for nid, obj := range objs.byNID { 475 if len(obj.name) == 0 { 476 continue 477 } 478 479 if obj.hasShortName { 480 fmt.Fprintf(&b, "#define SN_%s \"%s\"\n", obj.name, obj.shortName) 481 } 482 if obj.hasLongName { 483 fmt.Fprintf(&b, "#define LN_%s \"%s\"\n", obj.name, obj.longName) 484 } 485 fmt.Fprintf(&b, "#define NID_%s %d\n", obj.name, nid) 486 487 // Although NID_undef does not have an OID, OpenSSL emits 488 // OBJ_undef as if it were zero. 489 oid := obj.oid 490 if nid == 0 { 491 oid = []int{0} 492 } 493 if len(oid) != 0 { 494 var oidStr string 495 for _, val := range oid { 496 if len(oidStr) != 0 { 497 oidStr += "," 498 } 499 oidStr += fmt.Sprintf("%dL", val) 500 } 501 502 fmt.Fprintf(&b, "#define OBJ_%s %s\n", obj.name, oidStr) 503 } 504 505 fmt.Fprintf(&b, "\n") 506 } 507 508 fmt.Fprintf(&b, ` 509#if defined(__cplusplus) 510} /* extern C */ 511#endif 512 513#endif /* OPENSSL_HEADER_NID_H */ 514`) 515 516 formatted, err := clangFormat(b.String()) 517 if err != nil { 518 return err 519 } 520 521 return ioutil.WriteFile(path, []byte(formatted), 0666) 522} 523 524// TODO(davidben): Replace this with sort.Slice once Go 1.8 is sufficiently 525// common. 526type nidSorter struct { 527 nids []int 528 objs *objects 529 cmp func(a, b object) bool 530} 531 532func (a nidSorter) obj(i int) object { return a.objs.byNID[a.nids[i]] } 533func (a nidSorter) Len() int { return len(a.nids) } 534func (a nidSorter) Swap(i, j int) { a.nids[i], a.nids[j] = a.nids[j], a.nids[i] } 535func (a nidSorter) Less(i, j int) bool { return a.cmp(a.obj(i), a.obj(j)) } 536 537func sortNIDs(nids []int, objs *objects, cmp func(a, b object) bool) { 538 sort.Sort(&nidSorter{nids, objs, cmp}) 539} 540 541func writeData(path string, objs *objects) error { 542 var b bytes.Buffer 543 fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) 544 * All rights reserved. 545 * 546 * This package is an SSL implementation written 547 * by Eric Young (eay@cryptsoft.com). 548 * The implementation was written so as to conform with Netscapes SSL. 549 * 550 * This library is free for commercial and non-commercial use as long as 551 * the following conditions are aheared to. The following conditions 552 * apply to all code found in this distribution, be it the RC4, RSA, 553 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 554 * included with this distribution is covered by the same copyright terms 555 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 556 * 557 * Copyright remains Eric Young's, and as such any Copyright notices in 558 * the code are not to be removed. 559 * If this package is used in a product, Eric Young should be given attribution 560 * as the author of the parts of the library used. 561 * This can be in the form of a textual message at program startup or 562 * in documentation (online or textual) provided with the package. 563 * 564 * Redistribution and use in source and binary forms, with or without 565 * modification, are permitted provided that the following conditions 566 * are met: 567 * 1. Redistributions of source code must retain the copyright 568 * notice, this list of conditions and the following disclaimer. 569 * 2. Redistributions in binary form must reproduce the above copyright 570 * notice, this list of conditions and the following disclaimer in the 571 * documentation and/or other materials provided with the distribution. 572 * 3. All advertising materials mentioning features or use of this software 573 * must display the following acknowledgement: 574 * "This product includes cryptographic software written by 575 * Eric Young (eay@cryptsoft.com)" 576 * The word 'cryptographic' can be left out if the rouines from the library 577 * being used are not cryptographic related :-). 578 * 4. If you include any Windows specific code (or a derivative thereof) from 579 * the apps directory (application code) you must include an acknowledgement: 580 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 581 * 582 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND 583 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 584 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 585 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 586 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 587 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 588 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 589 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 590 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 591 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 592 * SUCH DAMAGE. 593 * 594 * The licence and distribution terms for any publically available version or 595 * derivative of this code cannot be changed. i.e. this code cannot simply be 596 * copied and put under another distribution licence 597 * [including the GNU Public Licence.] */ 598 599/* This file is generated by crypto/obj/objects.go. */ 600 601 602`) 603 604 fmt.Fprintf(&b, "#define NUM_NID %d\n", len(objs.byNID)) 605 606 // Emit each object's DER encoding, concatenated, and save the offsets. 607 fmt.Fprintf(&b, "\nstatic const uint8_t kObjectData[] = {\n") 608 offsets := make([]int, len(objs.byNID)) 609 var nextOffset int 610 for nid, obj := range objs.byNID { 611 if len(obj.name) == 0 || len(obj.encoded) == 0 { 612 offsets[nid] = -1 613 continue 614 } 615 616 offsets[nid] = nextOffset 617 nextOffset += len(obj.encoded) 618 fmt.Fprintf(&b, "/* NID_%s */\n", obj.name) 619 for _, val := range obj.encoded { 620 fmt.Fprintf(&b, "0x%02x, ", val) 621 } 622 fmt.Fprintf(&b, "\n") 623 } 624 fmt.Fprintf(&b, "};\n") 625 626 // Emit an ASN1_OBJECT for each object. 627 fmt.Fprintf(&b, "\nstatic const ASN1_OBJECT kObjects[NUM_NID] = {\n") 628 for nid, obj := range objs.byNID { 629 if len(obj.name) == 0 { 630 fmt.Fprintf(&b, "{NULL, NULL, NID_undef, 0, NULL, 0},\n") 631 continue 632 } 633 634 fmt.Fprintf(&b, "{\"%s\", \"%s\", NID_%s, ", obj.shortName, obj.longName, obj.name) 635 if offset := offsets[nid]; offset >= 0 { 636 fmt.Fprintf(&b, "%d, &kObjectData[%d], 0},\n", len(obj.encoded), offset) 637 } else { 638 fmt.Fprintf(&b, "0, NULL, 0},\n") 639 } 640 } 641 fmt.Fprintf(&b, "};\n") 642 643 // Emit a list of NIDs sorted by short name. 644 var nids []int 645 for nid, obj := range objs.byNID { 646 if len(obj.name) == 0 || len(obj.shortName) == 0 { 647 continue 648 } 649 nids = append(nids, nid) 650 } 651 sortNIDs(nids, objs, func(a, b object) bool { return a.shortName < b.shortName }) 652 653 fmt.Fprintf(&b, "\nstatic const uint16_t kNIDsInShortNameOrder[] = {\n") 654 for _, nid := range nids { 655 fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].shortName) 656 } 657 fmt.Fprintf(&b, "};\n") 658 659 // Emit a list of NIDs sorted by long name. 660 nids = nil 661 for nid, obj := range objs.byNID { 662 if len(obj.name) == 0 || len(obj.longName) == 0 { 663 continue 664 } 665 nids = append(nids, nid) 666 } 667 sortNIDs(nids, objs, func(a, b object) bool { return a.longName < b.longName }) 668 669 fmt.Fprintf(&b, "\nstatic const uint16_t kNIDsInLongNameOrder[] = {\n") 670 for _, nid := range nids { 671 fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].longName) 672 } 673 fmt.Fprintf(&b, "};\n") 674 675 // Emit a list of NIDs sorted by OID. 676 nids = nil 677 for nid, obj := range objs.byNID { 678 if len(obj.name) == 0 || len(obj.encoded) == 0 { 679 continue 680 } 681 nids = append(nids, nid) 682 } 683 sortNIDs(nids, objs, func(a, b object) bool { 684 // This comparison must match the definition of |obj_cmp|. 685 if len(a.encoded) < len(b.encoded) { 686 return true 687 } 688 if len(a.encoded) > len(b.encoded) { 689 return false 690 } 691 return bytes.Compare(a.encoded, b.encoded) < 0 692 }) 693 694 fmt.Fprintf(&b, "\nstatic const uint16_t kNIDsInOIDOrder[] = {\n") 695 for _, nid := range nids { 696 obj := objs.byNID[nid] 697 fmt.Fprintf(&b, "%d /* ", nid) 698 for i, c := range obj.oid { 699 if i > 0 { 700 fmt.Fprintf(&b, ".") 701 } 702 fmt.Fprintf(&b, "%d", c) 703 } 704 fmt.Fprintf(&b, " (OBJ_%s) */,\n", obj.name) 705 } 706 fmt.Fprintf(&b, "};\n") 707 708 formatted, err := clangFormat(b.String()) 709 if err != nil { 710 return err 711 } 712 713 return ioutil.WriteFile(path, []byte(formatted), 0666) 714} 715 716func main() { 717 objs, err := readObjects("obj_mac.num", "objects.txt") 718 if err != nil { 719 fmt.Fprintf(os.Stderr, "Error reading objects: %s\n", err) 720 os.Exit(1) 721 } 722 723 if err := writeNumbers("obj_mac.num", objs); err != nil { 724 fmt.Fprintf(os.Stderr, "Error writing numbers: %s\n", err) 725 os.Exit(1) 726 } 727 728 if err := writeHeader("../../include/openssl/nid.h", objs); err != nil { 729 fmt.Fprintf(os.Stderr, "Error writing header: %s\n", err) 730 os.Exit(1) 731 } 732 733 if err := writeData("obj_dat.h", objs); err != nil { 734 fmt.Fprintf(os.Stderr, "Error writing data: %s\n", err) 735 os.Exit(1) 736 } 737} 738