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 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} 733