File: mkconstants.py

package info (click to toggle)
cairocffi 1.7.1-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 752 kB
  • sloc: python: 3,020; makefile: 22
file content (101 lines) | stat: -rw-r--r-- 3,029 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import os
import re
import sys
import textwrap

import pycparser.c_generator


def parse_constant(node):
    if isinstance(node, pycparser.c_ast.Constant):
        return node.value
    elif isinstance(node, pycparser.c_ast.UnaryOp) and node.op == '-':
        return '-' + parse_constant(node.expr)
    else:
        raise TypeError(node)


class PrintEnumsVisitor(pycparser.c_ast.NodeVisitor):
    def visit_Decl(self, node):  # noqa: N802
        if node.name and node.name.startswith('CAIRO_'):  # len('CAIRO_') == 6
            if node.init.type == 'string':
                print('%s = b%s' % (node.name[6:], node.init.value))
            else:
                print('%s = %s' % (node.name[6:], node.init.value))
            print('')

    def visit_Enum(self, node):  # noqa: N802
        value = 0
        for enumerator in node.values.enumerators:
            if enumerator.value is not None:
                value_string = parse_constant(enumerator.value)
                value = int(value_string, 0)
            else:
                value_string = str(value)
            assert enumerator.name.startswith('CAIRO_')  # len('CAIRO_') == 6
            print('%s = %s' % (enumerator.name[6:], value_string))
            value += 1
        print('')


def read_cairo_header(cairo_git_dir, suffix):
    filename = os.path.join(cairo_git_dir, 'src', 'cairo%s.h' % suffix)
    source = open(filename, encoding='iso-8859-1').read()
    source = re.sub(
        '/\\*.*?\\*/'
        '|CAIRO_(BEGIN|END)_DECLS'
        '|cairo_public '
        r'|^\s*#.*?[^\\]\n',
        '',
        source,
        flags=re.DOTALL | re.MULTILINE)
    source = re.sub('\n{3,}', '\n\n', source)
    return source


def generate(cairo_git_dir):
    # Remove comments, preprocessor instructions and macros.
    source = read_cairo_header(cairo_git_dir, '')

    source += 'const int CAIRO_PDF_OUTLINE_ROOT = 0;\n'
    source += read_cairo_header(cairo_git_dir, '-pdf')

    source += read_cairo_header(cairo_git_dir, '-ps')

    source += read_cairo_header(cairo_git_dir, '-svg')

    source += '''
        typedef void* HDC;
        typedef void* HFONT;
        typedef void LOGFONTW;
    '''
    source += read_cairo_header(cairo_git_dir, '-win32')

    source += '''
        typedef void* CGContextRef;
        typedef void* CGFontRef;
        typedef void* ATSUFontID;
    '''
    source += read_cairo_header(cairo_git_dir, '-quartz')

    ast = pycparser.CParser().parse(source)

    print(textwrap.dedent('''\
        # *** Do not edit this file ***
        # Generated by utils/mkconstants.py
        # flake8: noqa

        TAG_DEST = b"cairo.dest"
        TAG_LINK = b"Link"\n'''))
    PrintEnumsVisitor().visit(ast)
    print('_CAIRO_HEADERS = r"""%s"""' % source)

    source = read_cairo_header(cairo_git_dir, '-xcb')
    print('_CAIRO_XCB_HEADERS = r"""%s"""' % source)


if __name__ == '__main__':
    if len(sys.argv) >= 2:
        generate(sys.argv[1])
    else:
        print('Usage: %s path/to/cairo_source.git' % sys.argv[0])