#! /usr/bin/env python3 """ This script should be called *manually* when we want to upgrade SSLError `library` and `reason` mnemnonics to a more recent OpenSSL version. It takes two arguments: - the path to the OpenSSL include files' directory (e.g. openssl-1.0.1-beta3/include/openssl/) - the path to the C file to be generated (probably Modules/_ssl_data.h) """ import datetime import os import re import sys def parse_error_codes(h_file, prefix): pat = re.compile(r"#define\W+(%s([\w]+))\W+(\d+)\b" % re.escape(prefix)) codes = [] with open(h_file, "r", encoding="latin1") as f: for line in f: match = pat.search(line) if match: code, name, num = match.groups() num = int(num) codes.append((code, name, num)) return codes if __name__ == "__main__": openssl_inc = sys.argv[1] outfile = sys.argv[2] use_stdout = outfile == '-' f = sys.stdout if use_stdout else open(outfile, "w") error_libraries = ( # (library code, mnemonic, error prefix, header file) ('ERR_LIB_PEM', 'PEM', 'PEM_R_', 'pem.h'), ('ERR_LIB_SSL', 'SSL', 'SSL_R_', 'ssl.h'), ('ERR_LIB_X509', 'X509', 'X509_R_', 'x509.h'), ) def w(l): f.write(l + "\n") w("/* File generated by Tools/ssl/make_ssl_data.py */") w("/* Generated on %s */" % datetime.datetime.now().isoformat()) w("") w("static struct py_ssl_library_code library_codes[] = {") for libcode, mnemo, _, _ in error_libraries: w(' {"%s", %s},' % (mnemo, libcode)) w(' { NULL }') w('};') w("") w("static struct py_ssl_error_code error_codes[] = {") for libcode, _, prefix, h_file in error_libraries: codes = parse_error_codes(os.path.join(openssl_inc, h_file), prefix) for code, name, num in sorted(codes): w(' #ifdef %s' % (code)) w(' {"%s", %s, %s},' % (name, libcode, code)) w(' #else') w(' {"%s", %s, %d},' % (name, libcode, num)) w(' #endif') w(' { NULL }') w('};') if not use_stdout: f.close()