diff options
| author | Michele Calgaro <michele.calgaro@yahoo.it> | 2023-12-01 12:38:43 +0900 | 
|---|---|---|
| committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2023-12-01 12:38:43 +0900 | 
| commit | b67b7f2b784c7105e88a5e639d9d84736ae2cbc1 (patch) | |
| tree | 0fd16d439c681c07d57d7f0d544c7582e04c3a31 /debian/uncrustify-trinity/uncrustify-trinity-0.78.1/scripts/update_emscripten_bindings.py | |
| parent | c0a6f1b84c84749908961579b84513fd9f9d9eac (diff) | |
| download | extra-dependencies-b67b7f2b784c7105e88a5e639d9d84736ae2cbc1.tar.gz extra-dependencies-b67b7f2b784c7105e88a5e639d9d84736ae2cbc1.zip | |
uncrustify-trinity: updated based on upstream version 0.78.1
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.78.1/scripts/update_emscripten_bindings.py')
| -rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.78.1/scripts/update_emscripten_bindings.py | 316 | 
1 files changed, 316 insertions, 0 deletions
| diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/scripts/update_emscripten_bindings.py b/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/scripts/update_emscripten_bindings.py new file mode 100644 index 00000000..781311e2 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/scripts/update_emscripten_bindings.py @@ -0,0 +1,316 @@ +#!/bin/python +from __future__ import print_function  # python >= 2.6, chained 'with' >= 2.7 + +from os.path import dirname, abspath +from os import fdopen as os_fdopen, remove as os_remove, name as os_name +from shutil import copy2 +from subprocess import Popen, PIPE +from sys import exit as sys_exit, stderr +from tempfile import mkstemp +from contextlib import contextmanager +from threading import Timer +import re + + +ROOT_DIR = dirname(dirname(abspath(__file__))) + +# ============================================================================== + +FILE_BINDINGS = "%s/src/uncrustify_emscripten.cpp" % ROOT_DIR +FILE_TS = "%s/emscripten/libUncrustify.d.ts" % ROOT_DIR + +REGION_START = "region enum bindings" +REGION_END = "endregion enum bindings" + +''' Enums which values need to be updated in the binding code ''' +ENUMS_INFO = [ +    { +        'name': 'option_type_e', +        'substitute_name': 'OptionType', +        'filepath': '%s/src/option.h' % ROOT_DIR, +        'extra_arg': [], +        'filter_values': [], +        'suffix_chars': 0, +    }, +    { +        'name': 'iarf_e', +        'substitute_name': 'IARF', +        'filepath': '%s/src/option.h' % ROOT_DIR, +        'extra_arg': [], +        'filter_values': ['NOT_DEFINED'], +        'suffix_chars': 0, +    }, +    { +        'name': 'line_end_e', +        'substitute_name': 'LineEnd', +        'filepath': '%s/src/option.h' % ROOT_DIR, +        'extra_arg': [], +        'filter_values': [], +        'suffix_chars': 0, +    }, +    { +        'name': 'token_pos_e', +        'substitute_name': 'TokenPos', +        'filepath': '%s/src/option.h' % ROOT_DIR, +        'extra_arg': [], +        'filter_values': [], +        'suffix_chars': 0, +    }, +    { +        'name': 'log_sev_t', +        'substitute_name': 'LogType', +        'filepath': '%s/src/log_levels.h' % ROOT_DIR, +        'extra_arg': [], +        'filter_values': [], +        'suffix_chars': 1, +    }, +    { +        'name': 'E_Token', +        'substitute_name': 'TokenType', +        'filepath': '%s/src/token_enum.h' % ROOT_DIR, +        'extra_arg': [], +        'filter_values': ['CT_TOKEN_COUNT_'], +        'suffix_chars': 3, +    }, +    { +        'name': 'lang_flag_e', +        'substitute_name': 'Language', +        'filepath': '%s/src/uncrustify_types.h' % ROOT_DIR, +        'extra_arg': ["-extra-arg=-std=c++1z", "-extra-arg=-DEMSCRIPTEN"], +        'filter_values': [ +            'LANG_ALLC', +            'LANG_ALL', +            'FLAG_HDR', +            'FLAG_DIG', +            'FLAG_PP', +        ], +        'suffix_chars': 5, +    }, +] + +# ============================================================================== + +NULL_DEV = "/dev/null" if os_name != "nt" else "nul" + + +@contextmanager +def make_raw_temp_file(*args, **kwargs): +    fd, tmp_file_name = mkstemp(*args, **kwargs) +    try: +        yield (fd, tmp_file_name) +    finally: +        os_remove(tmp_file_name) + + +@contextmanager +def open_fd(*args, **kwargs): +    fp = os_fdopen(*args, **kwargs) +    try: +        yield fp +    finally: +        fp.close() + + +def term_proc(proc, timeout): +    """ +    helper function terminate a process if a timer times out + +    :param proc: the process object that is going to be terminated +    :param timeout: value that will be set to indicate termination +    """ +    timeout["value"] = True +    proc.terminate() + + +def proc_output(args, timeout_sec=10): +    """ +    grabs output from called program +    :param args: string array containing program name and program arguments +    :param timeout_sec: max sec the program can run without being terminated +    :return: utf8 decoded program output in a string +    """ +    proc = Popen(args, stdout=PIPE) + +    timeout = {"value": False} +    if timeout_sec is not None: +        timeout = {"value": False} +        timer = Timer(timeout_sec, term_proc, [proc, timeout]) +        timer.start() + +    output_b, error_txt_b = proc.communicate() + +    if timeout_sec is not None: +        timer.cancel() + +    output = output_b.decode("UTF-8") + +    if timeout["value"]: +        print("proc timeout: %s" % ' '.join(args), file=stderr) + +    return output if not timeout["value"] else None + + +def get_enum_lines(enum_info): +    """ +    extracts enum values from a file via clang-check + +    :param enum_info: dict with: +                        'name' (name of the enum), +                        'filepath' (file containing the enum definition), +                        'extra_arg' (extra arguments passed to clang-check) +    :return: list containing enum values +    """ +    cut_len = len(enum_info['name']) + +    proc_args = ["clang-check", enum_info['filepath'], "-ast-dump", +                 '-ast-dump-filter=%s' % enum_info['name']] +    proc_args += enum_info['extra_arg'] + +    output = proc_output(proc_args) +    if output is None or len(output) == 0: +        print("ScriptError: %s - empty clang-check return" % get_enum_lines.__name__, +              file=stderr) +        return () + +    reg_obj = re.compile("EnumConstantDecl.+col:\d+ (referenced )?(\w+)") + +    lines = [m.group(2) for l in output.splitlines() +             for m in [re.search(reg_obj, l)] if m] +    lines = [line for line in lines if line not in enum_info['filter_values']] + +    if len(lines) == 0: +        print("ScriptError: %s - no enum_info names found" % get_enum_lines.__name__, +              file=stderr) +        return () +    return lines + + +def write_ts(opened_file_obj, enum_info): +    """ +    writes enum values in a specific typescript d.ts file format + +    :param opened_file_obj: opened file file object (with write permissions) +    :param enum_info: dict with: +                        'name' (name of the enum), +                        'substitute_name' (substitute name for the enum), +                        'filepath' (file containing the enum definition), +                        'extra_arg' (extra arguments passed to clang-check) +    :return: False on failure else True +    """ +    lines = get_enum_lines(enum_info) +    if len(lines) == 0: +        return False + +    opened_file_obj.write( +        '    export interface %sValue extends EmscriptenEnumTypeObject {}\n' +        '    export interface %s extends EmscriptenEnumType\n' +        '    {\n' +        % (enum_info['substitute_name'], enum_info['substitute_name']) +    ) +    for line in lines: +        opened_file_obj.write( +            '        %s : %sValue;\n' +            % (line[enum_info['suffix_chars']:], enum_info['substitute_name']) +        ) +    opened_file_obj.write( +        '    }\n\n' +    ) +    return True + + +def write_bindings(opened_file_obj, enum_info): +    """ +    writes enum values in a specific emscripten embind enum bindings format + +    :param opened_file_obj: opened file file object (with write permissions) +    :param enum_info: dict with: +                        'name' (name of the enum), +                        'filepath' (file containing the enum definition), +                        'extra_arg' (extra arguments passed to clang-check) +    :return: False on failure else True +    """ +    lines = get_enum_lines(enum_info) +    if len(lines) == 0: +        return False + +    opened_file_obj.write( +        '   enum_<%s>("%s")' % (enum_info['name'], enum_info['substitute_name']) +    ) +    for line in lines: +        opened_file_obj.write( +            '\n      .value("%s", %s::%s)' +            % (line[enum_info['suffix_chars']:], enum_info['name'], line) +        ) +    opened_file_obj.write( +        ';\n\n' +    ) +    return True + + +def update_file(file_path, writer_func, enums_info): +    """ +    reads in a file and replaces old enum value in a region, which is defined by +    region start and end string, with updated ones + +    :param file_path: file in which the replacement will be made +    :param writer_func: name of the function that will be called to write new +                        content +    :param enums_info:list of dicts each containing: +                    'name' (name of the enum), +                    'substitute_name' (substitute name for the enum), +                    'filepath' (file containing the enum definition), +                    'extra_arg' (extra arguments passed to clang-check) +    :return: False on failure else True +    """ +    in_target_region = False + +    reg_obj_start = re.compile(".*%s$" % REGION_START) +    reg_obj_end = re.compile(".*%s$" % REGION_END) +    reg_obj = reg_obj_start + +    with make_raw_temp_file(suffix='.unc') as (fd, tmp_file_path): +        with open(file_path, 'r') as fr, open_fd(fd, 'w') as fw: +            for line in fr: +                match = None if reg_obj is None else re.search(reg_obj, line) + +                if match is None and not in_target_region: +                    fw.write(line)                # write out of region code + +                elif match is not None and not in_target_region: +                    fw.write(line)                # hit the start region + +                    in_target_region = True +                    reg_obj = reg_obj_end + +                    for enum in enums_info: +                        succes_flag = writer_func(fw, enum) +                        if not succes_flag:       # abort, keep input file clean +                            return False + +                elif match is None and in_target_region: +                    pass                          # ignore old binding code + +                elif match and in_target_region:  # hit the endregion +                    fw.write(line) + +                    in_target_region = False +                    reg_obj = None + +        copy2(tmp_file_path, file_path)           # overwrite input file +        return True + + +def main(): +    flag = update_file(FILE_BINDINGS, write_bindings, ENUMS_INFO) +    if not flag: +        return 1 + +    flag = update_file(FILE_TS, write_ts, ENUMS_INFO) +    if not flag: +        return 1 + +    return 0 + + +if __name__ == "__main__": +    sys_exit(main()) | 
