|
|
@ -12,8 +12,12 @@ from . import mparser |
|
|
|
from .mesonlib import MesonException |
|
|
|
from .mesonlib import MesonException |
|
|
|
|
|
|
|
|
|
|
|
if T.TYPE_CHECKING: |
|
|
|
if T.TYPE_CHECKING: |
|
|
|
|
|
|
|
from typing_extensions import TypeAlias |
|
|
|
|
|
|
|
|
|
|
|
from .coredata import StrOrBytesPath |
|
|
|
from .coredata import StrOrBytesPath |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SectionT: TypeAlias = T.Union[str, int, bool, T.List[str], T.List['SectionT']] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CmdLineFileParser(configparser.ConfigParser): |
|
|
|
class CmdLineFileParser(configparser.ConfigParser): |
|
|
|
def __init__(self) -> None: |
|
|
|
def __init__(self) -> None: |
|
|
@ -32,8 +36,8 @@ class CmdLineFileParser(configparser.ConfigParser): |
|
|
|
class MachineFileParser(): |
|
|
|
class MachineFileParser(): |
|
|
|
def __init__(self, filenames: T.List[str], sourcedir: str) -> None: |
|
|
|
def __init__(self, filenames: T.List[str], sourcedir: str) -> None: |
|
|
|
self.parser = CmdLineFileParser() |
|
|
|
self.parser = CmdLineFileParser() |
|
|
|
self.constants: T.Dict[str, T.Union[str, bool, int, T.List[str]]] = {'True': True, 'False': False} |
|
|
|
self.constants: T.Dict[str, SectionT] = {'True': True, 'False': False} |
|
|
|
self.sections: T.Dict[str, T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = {} |
|
|
|
self.sections: T.Dict[str, T.Dict[str, SectionT]] = {} |
|
|
|
|
|
|
|
|
|
|
|
for fname in filenames: |
|
|
|
for fname in filenames: |
|
|
|
try: |
|
|
|
try: |
|
|
@ -58,9 +62,9 @@ class MachineFileParser(): |
|
|
|
continue |
|
|
|
continue |
|
|
|
self.sections[s] = self._parse_section(s) |
|
|
|
self.sections[s] = self._parse_section(s) |
|
|
|
|
|
|
|
|
|
|
|
def _parse_section(self, s: str) -> T.Dict[str, T.Union[str, bool, int, T.List[str]]]: |
|
|
|
def _parse_section(self, s: str) -> T.Dict[str, SectionT]: |
|
|
|
self.scope = self.constants.copy() |
|
|
|
self.scope = self.constants.copy() |
|
|
|
section: T.Dict[str, T.Union[str, bool, int, T.List[str]]] = {} |
|
|
|
section: T.Dict[str, SectionT] = {} |
|
|
|
for entry, value in self.parser.items(s): |
|
|
|
for entry, value in self.parser.items(s): |
|
|
|
if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry: |
|
|
|
if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry: |
|
|
|
raise MesonException(f'Malformed variable name {entry!r} in machine file.') |
|
|
|
raise MesonException(f'Malformed variable name {entry!r} in machine file.') |
|
|
@ -79,7 +83,7 @@ class MachineFileParser(): |
|
|
|
self.scope[entry] = res |
|
|
|
self.scope[entry] = res |
|
|
|
return section |
|
|
|
return section |
|
|
|
|
|
|
|
|
|
|
|
def _evaluate_statement(self, node: mparser.BaseNode) -> T.Union[str, bool, int, T.List[str]]: |
|
|
|
def _evaluate_statement(self, node: mparser.BaseNode) -> SectionT: |
|
|
|
if isinstance(node, (mparser.StringNode)): |
|
|
|
if isinstance(node, (mparser.StringNode)): |
|
|
|
return node.value |
|
|
|
return node.value |
|
|
|
elif isinstance(node, mparser.BooleanNode): |
|
|
|
elif isinstance(node, mparser.BooleanNode): |
|
|
@ -89,7 +93,6 @@ class MachineFileParser(): |
|
|
|
elif isinstance(node, mparser.ParenthesizedNode): |
|
|
|
elif isinstance(node, mparser.ParenthesizedNode): |
|
|
|
return self._evaluate_statement(node.inner) |
|
|
|
return self._evaluate_statement(node.inner) |
|
|
|
elif isinstance(node, mparser.ArrayNode): |
|
|
|
elif isinstance(node, mparser.ArrayNode): |
|
|
|
# TODO: This is where recursive types would come in handy |
|
|
|
|
|
|
|
return [self._evaluate_statement(arg) for arg in node.args.arguments] |
|
|
|
return [self._evaluate_statement(arg) for arg in node.args.arguments] |
|
|
|
elif isinstance(node, mparser.IdNode): |
|
|
|
elif isinstance(node, mparser.IdNode): |
|
|
|
return self.scope[node.value] |
|
|
|
return self.scope[node.value] |
|
|
@ -97,20 +100,21 @@ class MachineFileParser(): |
|
|
|
l = self._evaluate_statement(node.left) |
|
|
|
l = self._evaluate_statement(node.left) |
|
|
|
r = self._evaluate_statement(node.right) |
|
|
|
r = self._evaluate_statement(node.right) |
|
|
|
if node.operation == 'add': |
|
|
|
if node.operation == 'add': |
|
|
|
if (isinstance(l, str) and isinstance(r, str)) or \ |
|
|
|
if isinstance(l, str) and isinstance(r, str): |
|
|
|
(isinstance(l, list) and isinstance(r, list)): |
|
|
|
return l + r |
|
|
|
|
|
|
|
if isinstance(l, list) and isinstance(r, list): |
|
|
|
return l + r |
|
|
|
return l + r |
|
|
|
elif node.operation == 'div': |
|
|
|
elif node.operation == 'div': |
|
|
|
if isinstance(l, str) and isinstance(r, str): |
|
|
|
if isinstance(l, str) and isinstance(r, str): |
|
|
|
return os.path.join(l, r) |
|
|
|
return os.path.join(l, r) |
|
|
|
raise MesonException('Unsupported node type') |
|
|
|
raise MesonException('Unsupported node type') |
|
|
|
|
|
|
|
|
|
|
|
def parse_machine_files(filenames: T.List[str], sourcedir: str): |
|
|
|
def parse_machine_files(filenames: T.List[str], sourcedir: str) -> T.Dict[str, T.Dict[str, SectionT]]: |
|
|
|
parser = MachineFileParser(filenames, sourcedir) |
|
|
|
parser = MachineFileParser(filenames, sourcedir) |
|
|
|
return parser.sections |
|
|
|
return parser.sections |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MachineFileStore: |
|
|
|
class MachineFileStore: |
|
|
|
def __init__(self, native_files, cross_files, source_dir): |
|
|
|
def __init__(self, native_files: T.Optional[T.List[str]], cross_files: T.Optional[T.List[str]], source_dir: str): |
|
|
|
self.native = MachineFileParser(native_files if native_files is not None else [], source_dir).sections |
|
|
|
self.native = parse_machine_files(native_files if native_files is not None else [], source_dir) |
|
|
|
self.cross = MachineFileParser(cross_files if cross_files is not None else [], source_dir).sections |
|
|
|
self.cross = parse_machine_files(cross_files if cross_files is not None else [], source_dir) |
|
|
|