docs: def gen_alias(enum, binary, output, ascii_props=False, append=False, prefix=""):
      """Generate alias."""
  
      alias_re = re.compile(r'^#\s+(\w+)\s+\((\w+)\)\s*$')
  
      categories = enum + binary
      alias = {}
      gather = False
      current_category = None
      line_re = None
      alias_header_re = re.compile(r'^#\s+(\w+)\s+Properties\s*$')
      divider_re = re.compile(r'#\s*=+\s*$')
      posix_props = ('alnum', 'blank', 'graph', 'print', 'xdigit')
      toplevel = (
          'catalog', 'enumerated', 'numeric', 'miscellaneous'
      )
  
      with codecs.open(os.path.join(HOME, 'unicodedata', UNIVERSION, 'PropertyAliases.txt'), 'r', 'utf-8') as uf:
          div = False
          capture = False
          name = None
          for line in uf:
              if div:
                  m = alias_header_re.match(line)
                  if m:
                      name = format_name(m.group(1))
                      if name in toplevel:
                          capture = True
                          name = '_'
                      elif name in ('binary',):
                          capture = True
                      else:
                          capture = False
                      continue
                  div = False
              elif divider_re.match(line):
                  div = True
                  continue
              elif line.startswith('#') or not line.strip():
                  continue
              if capture:
                  should_add = False
                  data = [format_name(x) for x in line.split('#')[0].split(';')]
                  index = 0
                  for d in data:
                      if d in categories:
                          should_add = True
                          break
                      index += 1
                  if should_add:
                      data[0], data[index] = data[index], data[0]
                      if name not in alias:
                          alias[name] = {}
                      for d in data[1:]:
                          alias[name][d] = data[0]
  
      with codecs.open(os.path.join(HOME, 'unicodedata', UNIVERSION, 'PropertyValueAliases.txt'), 'r', 'utf-8') as uf:
          for line in uf:
              m = alias_re.match(line)
              if m:
                  original_name = format_name(m.group(1))
                  gather = original_name in categories
                  current_category = format_name(m.group(2))
                  line_re = re.compile(r'%s\s*;' % m.group(2), re.I)
              if gather and line_re.match(line):
                  data = [format_name(x) for x in line.split('#')[0].split(';')]
                  if current_category in ('sc', 'blk', 'dt', 'jg', 'sb', 'wb', 'lb', 'gcb', 'nt', 'inpc', 'inmc', 'insc'):
                      data[1], data[2] = data[2], data[1]
                  elif current_category == 'age' and UNIVERSION_INFO < (6, 1, 0):
                      if data[2] == 'unassigned':
                          data[1] = 'na'
                      else:
                          data[1], data[2] = data[2], 'V' + data[2].replace('.', '_')
                  if len(data) == 5 and data[2] in ('yes', 'no') and data[1] in ('n', 'y'):
                      data = ['binary', original_name, data[0]]
                  else:
                      data[0] = alias['_'].get(data[0], data[0])
                  if data[0] not in alias:
                      alias[data[0]] = {}
                  for a in data[2:]:
                      if a == 'n/a':
                          continue
                      if a not in alias[data[0]] and a != data[1]:
                          alias[data[0]][a] = data[1]
  
      for x in enum:
          if x not in alias:
              alias[x] = {}
  
      for prop in posix_props:
          alias['binary'][prop] = 'posix' + prop
  
      with codecs.open(output, 'a' if append else 'w', 'utf-8') as f:
          if not append:
              f.write(HEADER)
          f.write('%s_alias = {\n' % prefix)
          count = len(alias) - 1
          i = 0
          for k1, v1 in sorted(alias.items()):
              f.write('    "%s": {\n' % k1)
              count2 = len(v1) - 1
              j = 0
              for k2, v2 in sorted(v1.items()):
                  f.write('        "%s": "%s"' % (k2, v2))
                  if j == count2:
                      f.write('\n    }')
                  else:
                      f.write(',\n')
                  j += 1
              if count2 < 0:
                  f.write('    }')
              if i == count:
                  f.write('\n}\n')
              else:
                  f.write(',\n')
              i += 1
  
          cat = set(enum)
          for k in alias['_'].keys():
              cat.add(k)
  
          f.write('enum_names = {\n')
          count = len(cat) - 1
          i = 0
          for name in sorted(cat):
              f.write('    "%s"' % name)
              if i == count:
                  f.write('\n}\n')
              else:
                  f.write(',\n')
              i += 1