Skip to content

Instantly share code, notes, and snippets.

@vivkin
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vivkin/633c321cc6ceeb44559c to your computer and use it in GitHub Desktop.
Save vivkin/633c321cc6ceeb44559c to your computer and use it in GitHub Desktop.
Preprocess #include <...> directive
#!/usr/bin/python
import re
import sys
import os.path
import argparse
parser = argparse.ArgumentParser(description='Preprocess #include <...> directive')
parser.add_argument('-I', dest='paths', action='append',
help='add directory to include search path')
parser.add_argument('-o', '--output', dest='out', type=argparse.FileType('w'), default=sys.stdout,
help='write output to OUT')
parser.add_argument('infile', type=argparse.FileType('r'), default=sys.stdin,
help='input filename', metavar='<file>')
args = parser.parse_args()
pattern = re.compile('\s*#\s*include\s+(<(.*)>|"(.*)")\s*$')
included = []
lines = []
def compile_include(f):
for no, line in enumerate(f):
match = pattern.match(line)
if match:
include_name = match.group(2) or match.group(3)
search_paths = []
if match.group(3):
file_path = os.path.dirname(os.path.relpath(f.name))
search_paths.append(os.path.join(file_path, include_name))
if args.paths:
search_paths.extend(os.path.join(i, include_name) for i in args.paths)
for include_path in search_paths:
if os.path.exists(include_path):
if include_path not in included:
lines.append('#line %d "%s"\n' % (1, include_path))
with open(include_path, 'r') as include_file:
compile_include(include_file)
lines.append('#line %d "%s"\n' % (no + 1, f.name))
included.append(include_path)
break
else:
print '%s:%d: fatal error: %s: file not found' % (f.name, no, include_name)
print ' \n'.join(search_paths)
exit(1)
else:
lines.append(line)
compile_include(args.infile)
args.out.writelines(lines)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment