/* This file is machine generated by {PROG}. */\
"""
+# Used to update sections of files.
+START_MARKER = 'gennltvals: START'
+END_MARKER = 'gennltvals: END'
-def gentvals(output: TextIO, cpp: str, srctype: str, srcdir: Path,
+
+def extract_syms(cpp: str, srcdir: Path,
+ headers: Iterable[str],
+ pattern: str,
+ filter: str = r'^$') -> dict:
+ """Extract all the symbols from |headers| matching |pattern| using |cpp|."""
+ srcfile = ''.join(f'#include <{x}>\n' for x in headers)
+ syms = set()
+ define_pattern = re.compile(r'^#\s*define\s+(' + pattern + ')')
+ filter_pattern = re.compile(filter)
+ for header in headers:
+ with open(srcdir / header, 'r', encoding='utf-8') as fp:
+ data = fp.read()
+ for line in data.splitlines():
+ m = define_pattern.match(line)
+ if m and not filter_pattern.search(line):
+ syms.add(m.group(1))
+ for sym in syms:
+ srcfile += f'#ifdef {sym}\nDEFVAL "{sym}" {sym}\n#endif\n'
+
+ result = subprocess.run(
+ f'{cpp} -E -I"{srcdir}" -', shell=True, check=True, encoding='utf-8',
+ input=srcfile, capture_output=True)
+ ret = {}
+ for line in result.stdout.splitlines():
+ if line.startswith('DEFVAL '):
+ _, sym, val = line.split()
+ ret[sym.strip('"')] = val
+ return ret
+
+
+def gentvals(output_dir: Path, output: TextIO,
+ cpp: str, srctype: str, srcdir: Path,
headers: Iterable[str],
pattern: str,
+ filter: str = r'^$',
target: str = None):
"""Extract constants from the specified files using a regular expression.
fullpath = srcdir / header
assert fullpath.exists(), f'{fullpath} does not exist'
+ syms = extract_syms(cpp, srcdir, headers, pattern, filter)
+
+ # If we have a map file, use it directly.
+ target_map = output_dir / f'target-newlib-{srctype}.c'
+ if target_map.exists():
+ old_lines = target_map.read_text().splitlines()
+ start_i = end_i = None
+ for i, line in enumerate(old_lines):
+ if START_MARKER in line:
+ start_i = i
+ if END_MARKER in line:
+ end_i = i
+ assert start_i and end_i
+ new_lines = old_lines[0:start_i + 1]
+ new_lines.extend(
+ f'#ifdef {sym}\n'
+ f' {{ "{sym}", {sym}, {val} }},\n'
+ f'#endif' for sym, val in sorted(syms.items()))
+ new_lines.extend(old_lines[end_i:])
+ target_map.write_text('\n'.join(new_lines) + '\n')
+ return
+
+ # Fallback to classic nltvals.def.
if target is not None:
print(f'#ifdef NL_TARGET_{target}', file=output)
print(f'#ifdef {srctype}_defs', file=output)
else:
print(f'/* begin {target} {srctype} target macros */', file=output)
- # Extract all the symbols.
- srcfile = ''.join(f'#include <{x}>\n' for x in headers)
- syms = set()
- define_pattern = re.compile(r'^#\s*define\s+(' + pattern + ')')
- for header in headers:
- with open(srcdir / header, 'r', encoding='utf-8') as fp:
- data = fp.read()
- for line in data.splitlines():
- m = define_pattern.match(line)
- if m:
- syms.add(m.group(1))
- for sym in sorted(syms):
- srcfile += f'#ifdef {sym}\nDEFVAL {{ "{sym}", {sym} }},\n#endif\n'
-
- result = subprocess.run(
- f'{cpp} -E -I"{srcdir}" -', shell=True, check=True, encoding='utf-8',
- input=srcfile, capture_output=True)
- for line in result.stdout.splitlines():
- if line.startswith('DEFVAL '):
- print(line[6:].rstrip(), file=output)
+ for sym, val in sorted(syms.items()):
+ print(f' {{ "{sym}", {val} }},', file=output)
print(f'#undef {srctype}_defs', file=output)
if target is None:
print('#endif', file=output)
-def gen_common(output: TextIO, newlib: Path, cpp: str):
+def gen_common(output_dir: Path, output: TextIO, newlib: Path, cpp: str):
"""Generate the common C library constants.
No arch should override these.
"""
- gentvals(output, cpp, 'errno', newlib / 'newlib/libc/include',
+ gentvals(output_dir, output, cpp, 'errno', newlib / 'newlib/libc/include',
('errno.h', 'sys/errno.h'), 'E[A-Z0-9]*')
- gentvals(output, cpp, 'signal', newlib / 'newlib/libc/include',
- ('signal.h', 'sys/signal.h'), r'SIG[A-Z0-9]*')
+ gentvals(output_dir, output, cpp, 'signal', newlib / 'newlib/libc/include',
+ ('signal.h', 'sys/signal.h'), r'SIG[A-Z0-9]*', filter=r'SIGSTKSZ')
- gentvals(output, cpp, 'open', newlib / 'newlib/libc/include',
+ gentvals(output_dir, output, cpp, 'open', newlib / 'newlib/libc/include',
('fcntl.h', 'sys/fcntl.h', 'sys/_default_fcntl.h'), r'O_[A-Z0-9]*')
-def gen_targets(output: TextIO, newlib: Path, cpp: str):
+def gen_targets(output_dir: Path, output: TextIO, newlib: Path, cpp: str):
"""Generate the target-specific lists."""
for target, subdir in sorted(TARGET_DIRS.items()):
- gentvals(output, cpp, 'sys', newlib / subdir, ('syscall.h',),
- r'SYS_[_a-zA-Z0-9]*', target=target)
+ gentvals(output_dir, output, cpp, 'sys', newlib / subdir,
+ ('syscall.h',), r'SYS_[_a-zA-Z0-9]*', target=target)
# Then output the common syscall targets.
- gentvals(output, cpp, 'sys', newlib / 'libgloss', ('syscall.h',),
- r'SYS_[_a-zA-Z0-9]*')
+ gentvals(output_dir, output, cpp, 'sys', newlib / 'libgloss',
+ ('syscall.h',), r'SYS_[_a-zA-Z0-9]*')
-def gen(output: TextIO, newlib: Path, cpp: str):
+def gen(output_dir: Path, output: TextIO, newlib: Path, cpp: str):
"""Generate all the things!"""
print(FILE_HEADER, file=output)
- gen_common(output, newlib, cpp)
- gen_targets(output, newlib, cpp)
+ gen_common(output_dir, output, newlib, cpp)
+ gen_targets(output_dir, output, newlib, cpp)
def get_parser() -> argparse.ArgumentParser:
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
'-o', '--output', type=Path,
- help='write to the specified file instead of stdout')
+ help='write to the specified directory')
parser.add_argument(
'--cpp', type=str, default='cpp',
help='the preprocessor to use')
parser = get_parser()
opts = parser.parse_args(argv)
+ if opts.output is None:
+ # Default to where the script lives.
+ opts.output = Path(__file__).resolve().parent
+
if opts.srcroot is None:
opts.srcroot = Path(__file__).resolve().parent.parent.parent
+ else:
+ opts.srcroot = opts.srcroot.resolve()
if opts.newlib is None:
# Try to find newlib relative to our source tree.
"""The main entry point for scripts."""
opts = parse_args(argv)
- if opts.output is not None:
- output = open(opts.output, 'w', encoding='utf-8')
- else:
- output = sys.stdout
+ output = (opts.output / 'nltvals.def').open('w', encoding='utf-8')
- gen(output, opts.newlib, opts.cpp)
+ gen(opts.output, output, opts.newlib, opts.cpp)
return 0