summaryrefslogtreecommitdiffstats
path: root/Tools/c-analyzer/c_parser/source.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/c-analyzer/c_parser/source.py')
-rw-r--r--Tools/c-analyzer/c_parser/source.py64
1 files changed, 64 insertions, 0 deletions
diff --git a/Tools/c-analyzer/c_parser/source.py b/Tools/c-analyzer/c_parser/source.py
new file mode 100644
index 0000000..30a09ee
--- /dev/null
+++ b/Tools/c-analyzer/c_parser/source.py
@@ -0,0 +1,64 @@
+import contextlib
+import os.path
+
+
+def resolve(source, filename):
+ if _looks_like_filename(source):
+ return _resolve_filename(source, filename)
+
+ if isinstance(source, str):
+ source = source.splitlines()
+
+ # At this point "source" is not a str.
+ if not filename:
+ filename = None
+ elif not isinstance(filename, str):
+ raise TypeError(f'filename should be str (or None), got {filename!r}')
+ else:
+ filename, _ = _resolve_filename(filename)
+ return source, filename
+
+
+@contextlib.contextmanager
+def good_file(filename, alt=None):
+ if not _looks_like_filename(filename):
+ raise ValueError(f'expected a filename, got {filename}')
+ filename, _ = _resolve_filename(filename, alt)
+ try:
+ yield filename
+ except Exception:
+ if not os.path.exists(filename):
+ raise FileNotFoundError(f'file not found: {filename}')
+ raise # re-raise
+
+
+def _looks_like_filename(value):
+ if not isinstance(value, str):
+ return False
+ return value.endswith(('.c', '.h'))
+
+
+def _resolve_filename(filename, alt=None):
+ if os.path.isabs(filename):
+ ...
+# raise NotImplementedError
+ else:
+ filename = os.path.join('.', filename)
+
+ if not alt:
+ alt = filename
+ elif os.path.abspath(filename) == os.path.abspath(alt):
+ alt = filename
+ else:
+ raise ValueError(f'mismatch: {filename} != {alt}')
+ return filename, alt
+
+
+@contextlib.contextmanager
+def opened(source, filename=None):
+ source, filename = resolve(source, filename)
+ if isinstance(source, str):
+ with open(source) as srcfile:
+ yield srcfile, filename
+ else:
+ yield source, filename