| import os.path | |
| from c_analyzer.common import files | |
| from c_analyzer.common.info import UNKNOWN, ID | |
| from c_analyzer.variables import find as _common | |
| from . import SOURCE_DIRS, PYTHON, REPO_ROOT | |
| from .known import ( | |
| from_file as known_from_file, | |
| DATA_FILE as KNOWN_FILE, | |
| ) | |
| from .supported import ( | |
| ignored_from_file, IGNORED_FILE, is_supported, _is_object, | |
| ) | |
| # XXX need tests: | |
| # * vars_from_binary() | |
| # * vars_from_source() | |
| # * supported_vars() | |
| def _handle_id(filename, funcname, name, *, | |
| _relpath=os.path.relpath, | |
| ): | |
| filename = _relpath(filename, REPO_ROOT) | |
| return ID(filename, funcname, name) | |
| def vars_from_binary(*, | |
| known=KNOWN_FILE, | |
| _known_from_file=known_from_file, | |
| _iter_files=files.iter_files_by_suffix, | |
| _iter_vars=_common.vars_from_binary, | |
| ): | |
| """Yield a Variable for each found Symbol. | |
| Details are filled in from the given "known" variables and types. | |
| """ | |
| if isinstance(known, str): | |
| known = _known_from_file(known) | |
| dirnames = SOURCE_DIRS | |
| suffixes = ('.c',) | |
| filenames = _iter_files(dirnames, suffixes) | |
| # XXX For now we only use known variables (no source lookup). | |
| filenames = None | |
| yield from _iter_vars(PYTHON, | |
| known=known, | |
| filenames=filenames, | |
| handle_id=_handle_id, | |
| check_filename=(lambda n: True), | |
| ) | |
| def vars_from_source(*, | |
| preprocessed=None, | |
| known=KNOWN_FILE, | |
| _known_from_file=known_from_file, | |
| _iter_files=files.iter_files_by_suffix, | |
| _iter_vars=_common.vars_from_source, | |
| ): | |
| """Yield a Variable for each declaration in the raw source code. | |
| Details are filled in from the given "known" variables and types. | |
| """ | |
| if isinstance(known, str): | |
| known = _known_from_file(known) | |
| dirnames = SOURCE_DIRS | |
| suffixes = ('.c',) | |
| filenames = _iter_files(dirnames, suffixes) | |
| yield from _iter_vars(filenames, | |
| preprocessed=preprocessed, | |
| known=known, | |
| handle_id=_handle_id, | |
| ) | |
| def supported_vars(*, | |
| known=KNOWN_FILE, | |
| ignored=IGNORED_FILE, | |
| skip_objects=False, | |
| _known_from_file=known_from_file, | |
| _ignored_from_file=ignored_from_file, | |
| _iter_vars=vars_from_binary, | |
| _is_supported=is_supported, | |
| ): | |
| """Yield (var, is supported) for each found variable.""" | |
| if isinstance(known, str): | |
| known = _known_from_file(known) | |
| if isinstance(ignored, str): | |
| ignored = _ignored_from_file(ignored) | |
| for var in _iter_vars(known=known): | |
| if not var.isglobal: | |
| continue | |
| elif var.vartype == UNKNOWN: | |
| yield var, None | |
| # XXX Support proper filters instead. | |
| elif skip_objects and _is_object(found.vartype): | |
| continue | |
| else: | |
| yield var, _is_supported(var, ignored, known) |