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

	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 unsigned 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 unsigned 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 unsigned 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)
	}
}
