Skip to content

Instantly share code, notes, and snippets.

@lazka
Created November 3, 2018 09:33
Show Gist options
  • Save lazka/2edd9129ca7c74a3c14edc178c2e2386 to your computer and use it in GitHub Desktop.
Save lazka/2edd9129ca7c74a3c14edc178c2e2386 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import sys
import os
import pycparser
from pycparser import c_parser
def get_symbols():
symbols = set()
class Visitor(pycparser.c_ast.NodeVisitor):
def visit_Decl(self, node):
for _, child in node.children():
if isinstance(child, pycparser.c_ast.FuncDecl):
if node.name.lower().startswith("cairo_"):
symbols.add(node.name)
def visit_ArrayDecl(self, node):
print(node)
def visit_Enumerator(self, node):
if node.name.lower().startswith("cairo_"):
symbols.add(node.name)
include_dir = "/usr/include/cairo"
for entry in os.listdir(include_dir):
header_path = os.path.join(include_dir, entry)
if entry not in ["cairo-xlib.h", "cairo-gobject.h",
"cairo-xlib-xrender.h", "cairo-ft.h"]:
data = pycparser.preprocess_file(header_path, "cpp",
["-I/usr/share/python3-pycparser/fake_libc_include",
"-I/usr/include/freetype2",
"-I" + include_dir,
"-I/usr/include/glib-2.0"])
parser = c_parser.CParser()
ast = parser.parse(data, header_path)
Visitor().visit(ast)
# macros
with open(header_path, "r", encoding="utf-8") as h:
for line in h:
line = line.strip().split()
if len(line) > 1 and line[0].startswith("#define"):
name = line[1]
if name.startswith("CAIRO_") and not \
name.endswith("_H") and not "(" in name:
symbols.add(name)
return sorted(symbols)
def get_missing(symbols):
def strip(s):
if s.lower().startswith("cairo_"):
s = s[len("cairo_"):]
return s
symbols = list(map(strip, symbols))
import cairo
prefixes = [
("scaled_font", cairo.ScaledFont),
("toy_font_face", cairo.ToyFontFace),
("recording_surface", cairo.RecordingSurface),
("font_face", cairo.FontFace),
("font_options", cairo.FontOptions),
("scaled_font", cairo.ScaledFont),
("image_surface", cairo.ImageSurface),
("surface", cairo.Surface),
("svg_surface", cairo.SVGSurface),
("svg", cairo.SVGSurface),
("ps_surface", cairo.PSSurface),
("ps", cairo.PSSurface),
("pdf_surface", cairo.PDFSurface),
("pdf", cairo.PDFSurface),
("pattern", cairo.Gradient),
("pattern", cairo.SolidPattern),
("pattern", cairo.Pattern),
("pattern", cairo.RadialGradient),
("pattern", cairo.SurfacePattern),
("pattern", cairo.LinearGradient),
("raster_source_pattern", cairo.RasterSourcePattern),
("mesh_pattern", cairo.MeshPattern),
("matrix", cairo.Matrix),
("region", cairo.Region),
("xcb_surface", cairo.XCBSurface),
("device", cairo.Device),
("script_surface", cairo.ScriptSurface),
("script", cairo.ScriptDevice),
("format", cairo.Format),
("tee_surface", cairo.TeeSurface),
("", cairo.Context),
("", cairo),
]
bl_attrs = [
"get_reference_count",
"create",
"get_user_data",
"set_user_data",
]
blacklisted = [
"cairo_surface_get_type",
"surface_reference",
"surface_write_to_png_stream",
"surface_get_type",
"cairo_rectangle_list_destroy",
"debug_reset_static_data",
"region_intersect_rectangle",
"region_subtract_rectangle",
"region_union_rectangle",
"region_xor_rectangle",
"path_destroy",
"device_get_type",
"scaled_font_get_type",
"status_to_string",
"pattern_get_type",
"font_face_get_type",
"pattern_get_color_stop_count", # pattern_get_color_stops_rgba
"pattern_get_color_stop_rgba", # pattern_get_color_stops_rgba
"rectangle_list_destroy",
"glyph_allocate",
"glyph_free",
"text_cluster_allocate",
"text_cluster_free",
"raster_source_pattern_get_callback_data",
"raster_source_pattern_set_callback_data",
"raster_source_pattern_get_copy",
"raster_source_pattern_set_copy",
"raster_source_pattern_get_finish",
"raster_source_pattern_set_finish",
"raster_source_pattern_get_snapshot",
"raster_source_pattern_set_snapshot",
"VERSION",
"VERSION_MAJOR",
"VERSION_MICRO",
"VERSION_MINOR",
"VERSION_STRING",
"HAS_FC_FONT",
"HAS_GOBJECT_FUNCTIONS",
"HAS_XCB_SHM_FUNCTIONS",
"HAS_XLIB_XRENDER_SURFACE",
]
found = []
for symbol in symbols:
if symbol.startswith(("SURFACE_TYPE_", "PATTERN_TYPE_", "FONT_TYPE_",
"DEVICE_TYPE_", "GOBJECT_TYPE_")):
blacklisted.append(symbol)
if "surface_observer_" in symbol or symbol == "HAS_OBSERVER_SURFACE":
# not bindable afaics
blacklisted.append(symbol)
if "script_interpreter_" in symbol:
# not bindable
blacklisted.append(symbol)
if "matrix_init" in symbol:
blacklisted.append(symbol)
if "user_font_face" in symbol:
blacklisted.append(symbol)
if symbol.startswith(("xcb_", "device_observer_")):
blacklisted.append(symbol)
for pre, cls in prefixes:
pre = pre + "_" if pre else pre
if symbol.startswith(pre):
attr_name = symbol[len(pre):]
if attr_name in bl_attrs:
blacklisted.append(symbol)
if "_create_" in symbol or symbol.endswith("_create") or \
attr_name in ["status", "reference", "destroy"]:
blacklisted.append(symbol)
if hasattr(cls, attr_name):
found.append(symbol)
if hasattr(cls, "cairo_" + attr_name):
found.append(symbol)
return sorted((set(symbols) - set(found)) - set(blacklisted))
def main(argv):
for symbol in get_missing(get_symbols()):
print(symbol)
if __name__ == "__main__":
sys.exit(main(sys.argv))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment