17db96d56Sopenharmony_ci""" Unicode Mapping Parser and Codec Generator.
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciThis script parses Unicode mapping files as available from the Unicode
47db96d56Sopenharmony_cisite (ftp://ftp.unicode.org/Public/MAPPINGS/) and creates Python codec
57db96d56Sopenharmony_cimodules from them. The codecs use the standard character mapping codec
67db96d56Sopenharmony_cito actually apply the mapping.
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ciSynopsis: gencodec.py dir codec_prefix
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ciAll files in dir are scanned and those producing non-empty mappings
117db96d56Sopenharmony_ciwill be written to <codec_prefix><mapname>.py with <mapname> being the
127db96d56Sopenharmony_cifirst part of the map's filename ('a' in a.b.c.txt) converted to
137db96d56Sopenharmony_cilowercase with hyphens replaced by underscores.
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ciThe tool also writes marshalled versions of the mapping tables to the
167db96d56Sopenharmony_cisame location (with .mapping extension).
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciWritten by Marc-Andre Lemburg (mal@lemburg.com).
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
217db96d56Sopenharmony_ci(c) Copyright Guido van Rossum, 2000.
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_ciTable generation:
247db96d56Sopenharmony_ci(c) Copyright Marc-Andre Lemburg, 2005.
257db96d56Sopenharmony_ci    Licensed to PSF under a Contributor Agreement.
267db96d56Sopenharmony_ci
277db96d56Sopenharmony_ci"""#"
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ciimport re, os, marshal, codecs
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci# Maximum allowed size of charmap tables
327db96d56Sopenharmony_ciMAX_TABLE_SIZE = 8192
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci# Standard undefined Unicode code point
357db96d56Sopenharmony_ciUNI_UNDEFINED = chr(0xFFFE)
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci# Placeholder for a missing code point
387db96d56Sopenharmony_ciMISSING_CODE = -1
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_cimapRE = re.compile(r'((?:0x[0-9a-fA-F]+\+?)+)'
417db96d56Sopenharmony_ci                   r'\s+'
427db96d56Sopenharmony_ci                   r'((?:(?:0x[0-9a-fA-Z]+|<[A-Za-z]+>)\+?)*)'
437db96d56Sopenharmony_ci                   r'\s*'
447db96d56Sopenharmony_ci                   r'(#.+)?')
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_cidef parsecodes(codes, len=len, range=range):
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ci    """ Converts code combinations to either a single code integer
497db96d56Sopenharmony_ci        or a tuple of integers.
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci        meta-codes (in angular brackets, e.g. <LR> and <RL>) are
527db96d56Sopenharmony_ci        ignored.
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_ci        Empty codes or illegal ones are returned as None.
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci    """
577db96d56Sopenharmony_ci    if not codes:
587db96d56Sopenharmony_ci        return MISSING_CODE
597db96d56Sopenharmony_ci    l = codes.split('+')
607db96d56Sopenharmony_ci    if len(l) == 1:
617db96d56Sopenharmony_ci        return int(l[0],16)
627db96d56Sopenharmony_ci    for i in range(len(l)):
637db96d56Sopenharmony_ci        try:
647db96d56Sopenharmony_ci            l[i] = int(l[i],16)
657db96d56Sopenharmony_ci        except ValueError:
667db96d56Sopenharmony_ci            l[i] = MISSING_CODE
677db96d56Sopenharmony_ci    l = [x for x in l if x != MISSING_CODE]
687db96d56Sopenharmony_ci    if len(l) == 1:
697db96d56Sopenharmony_ci        return l[0]
707db96d56Sopenharmony_ci    else:
717db96d56Sopenharmony_ci        return tuple(l)
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_cidef readmap(filename):
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci    with open(filename) as f:
767db96d56Sopenharmony_ci        lines = f.readlines()
777db96d56Sopenharmony_ci    enc2uni = {}
787db96d56Sopenharmony_ci    identity = []
797db96d56Sopenharmony_ci    unmapped = list(range(256))
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    # UTC mapping tables per convention don't include the identity
827db96d56Sopenharmony_ci    # mappings for code points 0x00 - 0x1F and 0x7F, unless these are
837db96d56Sopenharmony_ci    # explicitly mapped to different characters or undefined
847db96d56Sopenharmony_ci    for i in list(range(32)) + [127]:
857db96d56Sopenharmony_ci        identity.append(i)
867db96d56Sopenharmony_ci        unmapped.remove(i)
877db96d56Sopenharmony_ci        enc2uni[i] = (i, 'CONTROL CHARACTER')
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci    for line in lines:
907db96d56Sopenharmony_ci        line = line.strip()
917db96d56Sopenharmony_ci        if not line or line[0] == '#':
927db96d56Sopenharmony_ci            continue
937db96d56Sopenharmony_ci        m = mapRE.match(line)
947db96d56Sopenharmony_ci        if not m:
957db96d56Sopenharmony_ci            #print '* not matched: %s' % repr(line)
967db96d56Sopenharmony_ci            continue
977db96d56Sopenharmony_ci        enc,uni,comment = m.groups()
987db96d56Sopenharmony_ci        enc = parsecodes(enc)
997db96d56Sopenharmony_ci        uni = parsecodes(uni)
1007db96d56Sopenharmony_ci        if comment is None:
1017db96d56Sopenharmony_ci            comment = ''
1027db96d56Sopenharmony_ci        else:
1037db96d56Sopenharmony_ci            comment = comment[1:].strip()
1047db96d56Sopenharmony_ci        if not isinstance(enc, tuple) and enc < 256:
1057db96d56Sopenharmony_ci            if enc in unmapped:
1067db96d56Sopenharmony_ci                unmapped.remove(enc)
1077db96d56Sopenharmony_ci            if enc == uni:
1087db96d56Sopenharmony_ci                identity.append(enc)
1097db96d56Sopenharmony_ci            enc2uni[enc] = (uni,comment)
1107db96d56Sopenharmony_ci        else:
1117db96d56Sopenharmony_ci            enc2uni[enc] = (uni,comment)
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ci    # If there are more identity-mapped entries than unmapped entries,
1147db96d56Sopenharmony_ci    # it pays to generate an identity dictionary first, and add explicit
1157db96d56Sopenharmony_ci    # mappings to None for the rest
1167db96d56Sopenharmony_ci    if len(identity) >= len(unmapped):
1177db96d56Sopenharmony_ci        for enc in unmapped:
1187db96d56Sopenharmony_ci            enc2uni[enc] = (MISSING_CODE, "")
1197db96d56Sopenharmony_ci        enc2uni['IDENTITY'] = 256
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci    return enc2uni
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_cidef hexrepr(t, precision=4):
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_ci    if t is None:
1267db96d56Sopenharmony_ci        return 'None'
1277db96d56Sopenharmony_ci    try:
1287db96d56Sopenharmony_ci        len(t)
1297db96d56Sopenharmony_ci    except TypeError:
1307db96d56Sopenharmony_ci        return '0x%0*X' % (precision, t)
1317db96d56Sopenharmony_ci    try:
1327db96d56Sopenharmony_ci        return '(' + ', '.join(['0x%0*X' % (precision, item)
1337db96d56Sopenharmony_ci                                for item in t]) + ')'
1347db96d56Sopenharmony_ci    except TypeError as why:
1357db96d56Sopenharmony_ci        print('* failed to convert %r: %s' % (t, why))
1367db96d56Sopenharmony_ci        raise
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_cidef python_mapdef_code(varname, map, comments=1, precisions=(2, 4)):
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci    l = []
1417db96d56Sopenharmony_ci    append = l.append
1427db96d56Sopenharmony_ci    if "IDENTITY" in map:
1437db96d56Sopenharmony_ci        append("%s = codecs.make_identity_dict(range(%d))" %
1447db96d56Sopenharmony_ci               (varname, map["IDENTITY"]))
1457db96d56Sopenharmony_ci        append("%s.update({" % varname)
1467db96d56Sopenharmony_ci        splits = 1
1477db96d56Sopenharmony_ci        del map["IDENTITY"]
1487db96d56Sopenharmony_ci        identity = 1
1497db96d56Sopenharmony_ci    else:
1507db96d56Sopenharmony_ci        append("%s = {" % varname)
1517db96d56Sopenharmony_ci        splits = 0
1527db96d56Sopenharmony_ci        identity = 0
1537db96d56Sopenharmony_ci
1547db96d56Sopenharmony_ci    mappings = sorted(map.items())
1557db96d56Sopenharmony_ci    i = 0
1567db96d56Sopenharmony_ci    key_precision, value_precision = precisions
1577db96d56Sopenharmony_ci    for mapkey, mapvalue in mappings:
1587db96d56Sopenharmony_ci        mapcomment = ''
1597db96d56Sopenharmony_ci        if isinstance(mapkey, tuple):
1607db96d56Sopenharmony_ci            (mapkey, mapcomment) = mapkey
1617db96d56Sopenharmony_ci        if isinstance(mapvalue, tuple):
1627db96d56Sopenharmony_ci            (mapvalue, mapcomment) = mapvalue
1637db96d56Sopenharmony_ci        if mapkey is None:
1647db96d56Sopenharmony_ci            continue
1657db96d56Sopenharmony_ci        if (identity and
1667db96d56Sopenharmony_ci            mapkey == mapvalue and
1677db96d56Sopenharmony_ci            mapkey < 256):
1687db96d56Sopenharmony_ci            # No need to include identity mappings, since these
1697db96d56Sopenharmony_ci            # are already set for the first 256 code points.
1707db96d56Sopenharmony_ci            continue
1717db96d56Sopenharmony_ci        key = hexrepr(mapkey, key_precision)
1727db96d56Sopenharmony_ci        value = hexrepr(mapvalue, value_precision)
1737db96d56Sopenharmony_ci        if mapcomment and comments:
1747db96d56Sopenharmony_ci            append('    %s: %s,\t#  %s' % (key, value, mapcomment))
1757db96d56Sopenharmony_ci        else:
1767db96d56Sopenharmony_ci            append('    %s: %s,' % (key, value))
1777db96d56Sopenharmony_ci        i += 1
1787db96d56Sopenharmony_ci        if i == 4096:
1797db96d56Sopenharmony_ci            # Split the definition into parts to that the Python
1807db96d56Sopenharmony_ci            # parser doesn't dump core
1817db96d56Sopenharmony_ci            if splits == 0:
1827db96d56Sopenharmony_ci                append('}')
1837db96d56Sopenharmony_ci            else:
1847db96d56Sopenharmony_ci                append('})')
1857db96d56Sopenharmony_ci            append('%s.update({' % varname)
1867db96d56Sopenharmony_ci            i = 0
1877db96d56Sopenharmony_ci            splits = splits + 1
1887db96d56Sopenharmony_ci    if splits == 0:
1897db96d56Sopenharmony_ci        append('}')
1907db96d56Sopenharmony_ci    else:
1917db96d56Sopenharmony_ci        append('})')
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci    return l
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_cidef python_tabledef_code(varname, map, comments=1, key_precision=2):
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ci    l = []
1987db96d56Sopenharmony_ci    append = l.append
1997db96d56Sopenharmony_ci    append('%s = (' % varname)
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci    # Analyze map and create table dict
2027db96d56Sopenharmony_ci    mappings = sorted(map.items())
2037db96d56Sopenharmony_ci    table = {}
2047db96d56Sopenharmony_ci    maxkey = 255
2057db96d56Sopenharmony_ci    if 'IDENTITY' in map:
2067db96d56Sopenharmony_ci        for key in range(256):
2077db96d56Sopenharmony_ci            table[key] = (key, '')
2087db96d56Sopenharmony_ci        del map['IDENTITY']
2097db96d56Sopenharmony_ci    for mapkey, mapvalue in mappings:
2107db96d56Sopenharmony_ci        mapcomment = ''
2117db96d56Sopenharmony_ci        if isinstance(mapkey, tuple):
2127db96d56Sopenharmony_ci            (mapkey, mapcomment) = mapkey
2137db96d56Sopenharmony_ci        if isinstance(mapvalue, tuple):
2147db96d56Sopenharmony_ci            (mapvalue, mapcomment) = mapvalue
2157db96d56Sopenharmony_ci        if mapkey == MISSING_CODE:
2167db96d56Sopenharmony_ci            continue
2177db96d56Sopenharmony_ci        table[mapkey] = (mapvalue, mapcomment)
2187db96d56Sopenharmony_ci        if mapkey > maxkey:
2197db96d56Sopenharmony_ci            maxkey = mapkey
2207db96d56Sopenharmony_ci    if maxkey > MAX_TABLE_SIZE:
2217db96d56Sopenharmony_ci        # Table too large
2227db96d56Sopenharmony_ci        return None
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci    # Create table code
2257db96d56Sopenharmony_ci    maxchar = 0
2267db96d56Sopenharmony_ci    for key in range(maxkey + 1):
2277db96d56Sopenharmony_ci        if key not in table:
2287db96d56Sopenharmony_ci            mapvalue = MISSING_CODE
2297db96d56Sopenharmony_ci            mapcomment = 'UNDEFINED'
2307db96d56Sopenharmony_ci        else:
2317db96d56Sopenharmony_ci            mapvalue, mapcomment = table[key]
2327db96d56Sopenharmony_ci        if mapvalue == MISSING_CODE:
2337db96d56Sopenharmony_ci            mapchar = UNI_UNDEFINED
2347db96d56Sopenharmony_ci        else:
2357db96d56Sopenharmony_ci            if isinstance(mapvalue, tuple):
2367db96d56Sopenharmony_ci                # 1-n mappings not supported
2377db96d56Sopenharmony_ci                return None
2387db96d56Sopenharmony_ci            else:
2397db96d56Sopenharmony_ci                mapchar = chr(mapvalue)
2407db96d56Sopenharmony_ci        maxchar = max(maxchar, ord(mapchar))
2417db96d56Sopenharmony_ci        if mapcomment and comments:
2427db96d56Sopenharmony_ci            append('    %a \t#  %s -> %s' % (mapchar,
2437db96d56Sopenharmony_ci                                            hexrepr(key, key_precision),
2447db96d56Sopenharmony_ci                                            mapcomment))
2457db96d56Sopenharmony_ci        else:
2467db96d56Sopenharmony_ci            append('    %a' % mapchar)
2477db96d56Sopenharmony_ci
2487db96d56Sopenharmony_ci    if maxchar < 256:
2497db96d56Sopenharmony_ci        append('    %a \t## Widen to UCS2 for optimization' % UNI_UNDEFINED)
2507db96d56Sopenharmony_ci    append(')')
2517db96d56Sopenharmony_ci    return l
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_cidef codegen(name, map, encodingname, comments=1):
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci    """ Returns Python source for the given map.
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci        Comments are included in the source, if comments is true (default).
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci    """
2607db96d56Sopenharmony_ci    # Generate code
2617db96d56Sopenharmony_ci    decoding_map_code = python_mapdef_code(
2627db96d56Sopenharmony_ci        'decoding_map',
2637db96d56Sopenharmony_ci        map,
2647db96d56Sopenharmony_ci        comments=comments)
2657db96d56Sopenharmony_ci    decoding_table_code = python_tabledef_code(
2667db96d56Sopenharmony_ci        'decoding_table',
2677db96d56Sopenharmony_ci        map,
2687db96d56Sopenharmony_ci        comments=comments)
2697db96d56Sopenharmony_ci    encoding_map_code = python_mapdef_code(
2707db96d56Sopenharmony_ci        'encoding_map',
2717db96d56Sopenharmony_ci        codecs.make_encoding_map(map),
2727db96d56Sopenharmony_ci        comments=comments,
2737db96d56Sopenharmony_ci        precisions=(4, 2))
2747db96d56Sopenharmony_ci
2757db96d56Sopenharmony_ci    if decoding_table_code:
2767db96d56Sopenharmony_ci        suffix = 'table'
2777db96d56Sopenharmony_ci    else:
2787db96d56Sopenharmony_ci        suffix = 'map'
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci    l = [
2817db96d56Sopenharmony_ci        '''\
2827db96d56Sopenharmony_ci""" Python Character Mapping Codec %s generated from '%s' with gencodec.py.
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ci"""#"
2857db96d56Sopenharmony_ci
2867db96d56Sopenharmony_ciimport codecs
2877db96d56Sopenharmony_ci
2887db96d56Sopenharmony_ci### Codec APIs
2897db96d56Sopenharmony_ci
2907db96d56Sopenharmony_ciclass Codec(codecs.Codec):
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci    def encode(self, input, errors='strict'):
2937db96d56Sopenharmony_ci        return codecs.charmap_encode(input, errors, encoding_%s)
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ci    def decode(self, input, errors='strict'):
2967db96d56Sopenharmony_ci        return codecs.charmap_decode(input, errors, decoding_%s)
2977db96d56Sopenharmony_ci''' % (encodingname, name, suffix, suffix)]
2987db96d56Sopenharmony_ci    l.append('''\
2997db96d56Sopenharmony_ciclass IncrementalEncoder(codecs.IncrementalEncoder):
3007db96d56Sopenharmony_ci    def encode(self, input, final=False):
3017db96d56Sopenharmony_ci        return codecs.charmap_encode(input, self.errors, encoding_%s)[0]
3027db96d56Sopenharmony_ci
3037db96d56Sopenharmony_ciclass IncrementalDecoder(codecs.IncrementalDecoder):
3047db96d56Sopenharmony_ci    def decode(self, input, final=False):
3057db96d56Sopenharmony_ci        return codecs.charmap_decode(input, self.errors, decoding_%s)[0]''' %
3067db96d56Sopenharmony_ci        (suffix, suffix))
3077db96d56Sopenharmony_ci
3087db96d56Sopenharmony_ci    l.append('''
3097db96d56Sopenharmony_ciclass StreamWriter(Codec, codecs.StreamWriter):
3107db96d56Sopenharmony_ci    pass
3117db96d56Sopenharmony_ci
3127db96d56Sopenharmony_ciclass StreamReader(Codec, codecs.StreamReader):
3137db96d56Sopenharmony_ci    pass
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ci### encodings module API
3167db96d56Sopenharmony_ci
3177db96d56Sopenharmony_cidef getregentry():
3187db96d56Sopenharmony_ci    return codecs.CodecInfo(
3197db96d56Sopenharmony_ci        name=%r,
3207db96d56Sopenharmony_ci        encode=Codec().encode,
3217db96d56Sopenharmony_ci        decode=Codec().decode,
3227db96d56Sopenharmony_ci        incrementalencoder=IncrementalEncoder,
3237db96d56Sopenharmony_ci        incrementaldecoder=IncrementalDecoder,
3247db96d56Sopenharmony_ci        streamreader=StreamReader,
3257db96d56Sopenharmony_ci        streamwriter=StreamWriter,
3267db96d56Sopenharmony_ci    )
3277db96d56Sopenharmony_ci''' % encodingname.replace('_', '-'))
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci    # Add decoding table or map (with preference to the table)
3307db96d56Sopenharmony_ci    if not decoding_table_code:
3317db96d56Sopenharmony_ci        l.append('''
3327db96d56Sopenharmony_ci### Decoding Map
3337db96d56Sopenharmony_ci''')
3347db96d56Sopenharmony_ci        l.extend(decoding_map_code)
3357db96d56Sopenharmony_ci    else:
3367db96d56Sopenharmony_ci        l.append('''
3377db96d56Sopenharmony_ci### Decoding Table
3387db96d56Sopenharmony_ci''')
3397db96d56Sopenharmony_ci        l.extend(decoding_table_code)
3407db96d56Sopenharmony_ci
3417db96d56Sopenharmony_ci    # Add encoding map
3427db96d56Sopenharmony_ci    if decoding_table_code:
3437db96d56Sopenharmony_ci        l.append('''
3447db96d56Sopenharmony_ci### Encoding table
3457db96d56Sopenharmony_ciencoding_table = codecs.charmap_build(decoding_table)
3467db96d56Sopenharmony_ci''')
3477db96d56Sopenharmony_ci    else:
3487db96d56Sopenharmony_ci        l.append('''
3497db96d56Sopenharmony_ci### Encoding Map
3507db96d56Sopenharmony_ci''')
3517db96d56Sopenharmony_ci        l.extend(encoding_map_code)
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci    # Final new-line
3547db96d56Sopenharmony_ci    l.append('')
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci    return '\n'.join(l).expandtabs()
3577db96d56Sopenharmony_ci
3587db96d56Sopenharmony_cidef pymap(name,map,pyfile,encodingname,comments=1):
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci    code = codegen(name,map,encodingname,comments)
3617db96d56Sopenharmony_ci    with open(pyfile,'w') as f:
3627db96d56Sopenharmony_ci        f.write(code)
3637db96d56Sopenharmony_ci
3647db96d56Sopenharmony_cidef marshalmap(name,map,marshalfile):
3657db96d56Sopenharmony_ci
3667db96d56Sopenharmony_ci    d = {}
3677db96d56Sopenharmony_ci    for e,(u,c) in map.items():
3687db96d56Sopenharmony_ci        d[e] = (u,c)
3697db96d56Sopenharmony_ci    with open(marshalfile,'wb') as f:
3707db96d56Sopenharmony_ci        marshal.dump(d,f)
3717db96d56Sopenharmony_ci
3727db96d56Sopenharmony_cidef convertdir(dir, dirprefix='', nameprefix='', comments=1):
3737db96d56Sopenharmony_ci
3747db96d56Sopenharmony_ci    mapnames = os.listdir(dir)
3757db96d56Sopenharmony_ci    for mapname in mapnames:
3767db96d56Sopenharmony_ci        mappathname = os.path.join(dir, mapname)
3777db96d56Sopenharmony_ci        if not os.path.isfile(mappathname):
3787db96d56Sopenharmony_ci            continue
3797db96d56Sopenharmony_ci        name = os.path.split(mapname)[1]
3807db96d56Sopenharmony_ci        name = name.replace('-','_')
3817db96d56Sopenharmony_ci        name = name.split('.')[0]
3827db96d56Sopenharmony_ci        name = name.lower()
3837db96d56Sopenharmony_ci        name = nameprefix + name
3847db96d56Sopenharmony_ci        codefile = name + '.py'
3857db96d56Sopenharmony_ci        marshalfile = name + '.mapping'
3867db96d56Sopenharmony_ci        print('converting %s to %s and %s' % (mapname,
3877db96d56Sopenharmony_ci                                              dirprefix + codefile,
3887db96d56Sopenharmony_ci                                              dirprefix + marshalfile))
3897db96d56Sopenharmony_ci        try:
3907db96d56Sopenharmony_ci            map = readmap(os.path.join(dir,mapname))
3917db96d56Sopenharmony_ci            if not map:
3927db96d56Sopenharmony_ci                print('* map is empty; skipping')
3937db96d56Sopenharmony_ci            else:
3947db96d56Sopenharmony_ci                pymap(mappathname, map, dirprefix + codefile,name,comments)
3957db96d56Sopenharmony_ci                marshalmap(mappathname, map, dirprefix + marshalfile)
3967db96d56Sopenharmony_ci        except ValueError as why:
3977db96d56Sopenharmony_ci            print('* conversion failed: %s' % why)
3987db96d56Sopenharmony_ci            raise
3997db96d56Sopenharmony_ci
4007db96d56Sopenharmony_cidef rewritepythondir(dir, dirprefix='', comments=1):
4017db96d56Sopenharmony_ci
4027db96d56Sopenharmony_ci    mapnames = os.listdir(dir)
4037db96d56Sopenharmony_ci    for mapname in mapnames:
4047db96d56Sopenharmony_ci        if not mapname.endswith('.mapping'):
4057db96d56Sopenharmony_ci            continue
4067db96d56Sopenharmony_ci        name = mapname[:-len('.mapping')]
4077db96d56Sopenharmony_ci        codefile = name + '.py'
4087db96d56Sopenharmony_ci        print('converting %s to %s' % (mapname,
4097db96d56Sopenharmony_ci                                       dirprefix + codefile))
4107db96d56Sopenharmony_ci        try:
4117db96d56Sopenharmony_ci            with open(os.path.join(dir, mapname), 'rb') as f:
4127db96d56Sopenharmony_ci                map = marshal.load(f)
4137db96d56Sopenharmony_ci            if not map:
4147db96d56Sopenharmony_ci                print('* map is empty; skipping')
4157db96d56Sopenharmony_ci            else:
4167db96d56Sopenharmony_ci                pymap(mapname, map, dirprefix + codefile,name,comments)
4177db96d56Sopenharmony_ci        except ValueError as why:
4187db96d56Sopenharmony_ci            print('* conversion failed: %s' % why)
4197db96d56Sopenharmony_ci
4207db96d56Sopenharmony_ciif __name__ == '__main__':
4217db96d56Sopenharmony_ci
4227db96d56Sopenharmony_ci    import sys
4237db96d56Sopenharmony_ci    if 1:
4247db96d56Sopenharmony_ci        convertdir(*sys.argv[1:])
4257db96d56Sopenharmony_ci    else:
4267db96d56Sopenharmony_ci        rewritepythondir(*sys.argv[1:])
427