<reponame>mmrmartin/pypapi
#!/usr/bin/env python


"""Generates pypapi/events.py from papiStdEventDefs.h

USAGE:
    tools/generate_papi_events.py > pypapi/events.py
"""


import os
import re


_ROOT = os.path.abspath(os.path.dirname(__file__))
_PAPISTDEVENTDEFS_H = os.path.join(_ROOT, "..", "papi", "src", "papiStdEventDefs.h")  # noqa


def _parse_defines(code):
    result = []
    define_regexp = re.compile("^#define\s+([^_][A-Z0-9_]+)\s+([^/]+)\s*(/\*(.+)\*/)?\s*$")  # noqa
    for line in code.split("\n"):
        if define_regexp.match(line):
            name = define_regexp.match(line).group(1)
            value = define_regexp.match(line).group(2)
            comment = define_regexp.match(line).group(4)
            result.append([
                name,
                value.strip(),
                comment.strip() if comment else None
                ])
    return result


def _parse_enum(code):
    result = {}
    count = 0
    is_enum = False
    for line in code.split("\n"):
        if not is_enum:
            if re.match("(^|\s|;)enum(\{|\s|$)", line):
                is_enum = True
            continue
        if re.match("^\s*(PAPI_[A-Z0-9_]+_idx)", line):
            name = re.match("^\s*(PAPI_[A-Z0-9_]+_idx)", line).group(1)
            result[name] = count
            count += 1
    return result


def _resolve_defines(defines, enum):
    evt_regext = re.compile("^\((PAPI_[A-Z0-9_]+_idx)\s*\|\s*(PAPI_[A-Z0-9_]+_MASK)\)$")  # noqa
    mask_int_regexp = re.compile("^\(\s*\(\s*int\s*\)\s*([0-9A-Fa-fxX.-]+)\s*\)$")  # noqa
    for define in defines:
        if evt_regext.match(define[1]):
            idx = evt_regext.match(define[1]).group(1)
            mask = evt_regext.match(define[1]).group(2)
            define[1] = "0x%02X | %s" % (enum[idx], mask)
            continue
        if mask_int_regexp.match(define[1]):
            value = mask_int_regexp.match(define[1]).group(1)
            define[1] = "%s if not %s & 0x80000000 else %s | ~0x7FFFFFFF" % (
                    value, value, value)

    return defines


def _defines_to_python(defines):
    result = ""
    for name, value, doc in defines:
        if doc:
            result += "#: %s\n" % doc
        result += "%s = %s\n\n" % (name, value)
    return result


if __name__ == "__main__":
    code = open(_PAPISTDEVENTDEFS_H, "r").read()
    defines = _parse_defines(code)
    enum = _parse_enum(code)
    _resolve_defines(defines, enum)
    python = _defines_to_python(defines)
    print("# This file is automatically generated by the")
    print("# 'tools/generate_papi_events.py' script.")
    print("# DO NOT EDIT!\n")
    print("\n# flake8: noqa\n\n")
    print(python)
