old_contents: #! /usr/bin/env python3
  
  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()
  
new_contents: #! /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()
  
subject: Add a docstring at the top of Tools/ssl/make_ssl_data.py