|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
import fnmatch
|
|
Ivan Mahonin |
b53a5c |
import os.path
|
|
Ivan Mahonin |
b53a5c |
import sys
|
|
Ivan Mahonin |
b53a5c |
import re
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
def print_help():
|
|
Ivan Mahonin |
b53a5c |
print(
|
|
Ivan Mahonin |
b53a5c |
"""usage: python single_header_packer.py --macro <macro> [--intro <files>] --extern <files> --pub <files> --priv1 <files> --priv2 <files> [--outro <files>]
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
where <files> can be a comma-separated list of files. e.g. --priv *.c,inc/*.h
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
The 'extern' files are placed between 'priv1' and 'priv2'.
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
The resulting code is packed as follows:
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/*
|
|
Ivan Mahonin |
b53a5c |
[intro file contents]
|
|
Ivan Mahonin |
b53a5c |
*/
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
#ifndef <macro>_SINGLE_HEADER
|
|
Ivan Mahonin |
b53a5c |
#define <macro>_SINGLE_HEADER
|
|
Ivan Mahonin |
b53a5c |
[public header file contents]
|
|
Ivan Mahonin |
b53a5c |
#endif /* <macro>_SINGLE_HEADER */
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
#ifdef <macro>_IMPLEMENTATION
|
|
Ivan Mahonin |
b53a5c |
[private header and source file contents]
|
|
Ivan Mahonin |
b53a5c |
#endif /* <macro>_IMPLEMENTATION */
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
/*
|
|
Ivan Mahonin |
b53a5c |
[outro file contents]
|
|
Ivan Mahonin |
b53a5c |
*/""")
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
def parse_files(arg):
|
|
Ivan Mahonin |
b53a5c |
files = []
|
|
Ivan Mahonin |
b53a5c |
paths = arg.split(",")
|
|
Ivan Mahonin |
b53a5c |
for path in paths:
|
|
Ivan Mahonin |
b53a5c |
if "*" in path:
|
|
Ivan Mahonin |
b53a5c |
# Wildcard
|
|
Ivan Mahonin |
b53a5c |
d = os.path.dirname(path)
|
|
Ivan Mahonin |
b53a5c |
if d == "": d = "."
|
|
Ivan Mahonin |
b53a5c |
if d == " ": continue
|
|
Ivan Mahonin |
b53a5c |
if not os.path.exists(d):
|
|
Ivan Mahonin |
b53a5c |
print(d + " does not exist.")
|
|
Ivan Mahonin |
b53a5c |
exit()
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
wildcard = os.path.basename(path)
|
|
Ivan Mahonin |
b53a5c |
unsorted = []
|
|
Ivan Mahonin |
b53a5c |
for file in os.listdir(d):
|
|
Ivan Mahonin |
b53a5c |
if fnmatch.fnmatch(file, wildcard):
|
|
Ivan Mahonin |
b53a5c |
unsorted.append(os.path.join(d, file))
|
|
Ivan Mahonin |
b53a5c |
unsorted.sort()
|
|
Ivan Mahonin |
b53a5c |
files.extend(unsorted)
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
else:
|
|
Ivan Mahonin |
b53a5c |
# Regular file
|
|
Ivan Mahonin |
b53a5c |
if not os.path.exists(path):
|
|
Ivan Mahonin |
b53a5c |
print(path + " does not exist.")
|
|
Ivan Mahonin |
b53a5c |
exit()
|
|
Ivan Mahonin |
b53a5c |
elif os.path.isdir(path):
|
|
Ivan Mahonin |
b53a5c |
print(path + " is a directory. Expected a file name.")
|
|
Ivan Mahonin |
b53a5c |
exit()
|
|
Ivan Mahonin |
b53a5c |
else:
|
|
Ivan Mahonin |
b53a5c |
files.append(path)
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
return files;
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
def omit_includes(str, files):
|
|
Ivan Mahonin |
b53a5c |
for file in files:
|
|
Ivan Mahonin |
b53a5c |
fname = os.path.basename(file)
|
|
Ivan Mahonin |
b53a5c |
if ".h" in file:
|
|
Ivan Mahonin |
b53a5c |
str = str.replace("#include \"" + fname + "\"", "");
|
|
Ivan Mahonin |
b53a5c |
str = str.replace("#include <" + fname + ">", "");
|
|
Ivan Mahonin |
b53a5c |
return str
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
def fix_comments(str):
|
|
Ivan Mahonin |
b53a5c |
return re.sub(r"//(.*)(\n|$)", "/* \\1 */\\2", str)
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
# Main start
|
|
Ivan Mahonin |
b53a5c |
# ==========
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if len(sys.argv) < 2:
|
|
Ivan Mahonin |
b53a5c |
print_help()
|
|
Ivan Mahonin |
b53a5c |
exit()
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
intro_files = []
|
|
Ivan Mahonin |
b53a5c |
pub_files = []
|
|
Ivan Mahonin |
b53a5c |
priv_files1 = []
|
|
Ivan Mahonin |
b53a5c |
outro_files2 = []
|
|
Ivan Mahonin |
b53a5c |
extern_files = []
|
|
Ivan Mahonin |
b53a5c |
cur_arg = 1
|
|
Ivan Mahonin |
b53a5c |
macro = ""
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
# Parse args
|
|
Ivan Mahonin |
b53a5c |
# ----------
|
|
Ivan Mahonin |
b53a5c |
while cur_arg < len(sys.argv):
|
|
Ivan Mahonin |
b53a5c |
if sys.argv[cur_arg] == "--help":
|
|
Ivan Mahonin |
b53a5c |
print_help()
|
|
Ivan Mahonin |
b53a5c |
exit()
|
|
Ivan Mahonin |
b53a5c |
elif sys.argv[cur_arg] == "--macro":
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
macro = sys.argv[cur_arg]
|
|
Ivan Mahonin |
b53a5c |
elif sys.argv[cur_arg] == "--intro":
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
intro_files = parse_files(sys.argv[cur_arg])
|
|
Ivan Mahonin |
b53a5c |
elif sys.argv[cur_arg] == "--pub":
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
pub_files = parse_files(sys.argv[cur_arg])
|
|
Ivan Mahonin |
b53a5c |
elif sys.argv[cur_arg] == "--priv1":
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
priv_files1 = parse_files(sys.argv[cur_arg])
|
|
Ivan Mahonin |
b53a5c |
elif sys.argv[cur_arg] == "--priv2":
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
priv_files2 = parse_files(sys.argv[cur_arg])
|
|
Ivan Mahonin |
b53a5c |
elif sys.argv[cur_arg] == "--extern":
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
extern_files = parse_files(sys.argv[cur_arg])
|
|
Ivan Mahonin |
b53a5c |
elif sys.argv[cur_arg] == "--outro":
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
outro_files = parse_files(sys.argv[cur_arg])
|
|
Ivan Mahonin |
b53a5c |
else:
|
|
Ivan Mahonin |
b53a5c |
print("Unknown argument " + sys.argv[cur_arg])
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
cur_arg += 1
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
if macro == "":
|
|
Ivan Mahonin |
b53a5c |
print("Option --macro <macro> is mandatory")
|
|
Ivan Mahonin |
b53a5c |
exit()
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
# Print concatenated output
|
|
Ivan Mahonin |
b53a5c |
# -------------------------
|
|
Ivan Mahonin |
b53a5c |
print("/*")
|
|
Ivan Mahonin |
b53a5c |
for f in intro_files:
|
|
Ivan Mahonin |
b53a5c |
sys.stdout.write(open(f, 'r').read())
|
|
Ivan Mahonin |
b53a5c |
print("*/")
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
# print("\n#ifndef " + macro + "_SINGLE_HEADER");
|
|
Ivan Mahonin |
b53a5c |
# print("#define " + macro + "_SINGLE_HEADER");
|
|
Ivan Mahonin |
b53a5c |
print("#ifndef NK_SINGLE_FILE");
|
|
Ivan Mahonin |
b53a5c |
print(" #define NK_SINGLE_FILE");
|
|
Ivan Mahonin |
b53a5c |
print("#endif");
|
|
Ivan Mahonin |
b53a5c |
print("");
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
for f in pub_files:
|
|
Ivan Mahonin |
b53a5c |
sys.stdout.write(open(f, 'r').read())
|
|
Ivan Mahonin |
b53a5c |
# print("#endif /* " + macro + "_SINGLE_HEADER */");
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
print("\n#ifdef " + macro + "_IMPLEMENTATION");
|
|
Ivan Mahonin |
b53a5c |
print("");
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
for f in priv_files1:
|
|
Ivan Mahonin |
b53a5c |
print(omit_includes(open(f, 'r').read(),
|
|
Ivan Mahonin |
b53a5c |
pub_files + priv_files1 + priv_files2 + extern_files))
|
|
Ivan Mahonin |
b53a5c |
for f in extern_files:
|
|
Ivan Mahonin |
b53a5c |
print(fix_comments(open(f, 'r').read()))
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
for f in priv_files2:
|
|
Ivan Mahonin |
b53a5c |
print(omit_includes(open(f, 'r').read(),
|
|
Ivan Mahonin |
b53a5c |
pub_files + priv_files1 + priv_files2 + extern_files))
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
print("#endif /* " + macro + "_IMPLEMENTATION */");
|
|
Ivan Mahonin |
b53a5c |
|
|
Ivan Mahonin |
b53a5c |
print("\n/*")
|
|
Ivan Mahonin |
b53a5c |
for f in outro_files:
|
|
Ivan Mahonin |
b53a5c |
sys.stdout.write(open(f, 'r').read())
|
|
Ivan Mahonin |
b53a5c |
print("*/\n")
|
|
Ivan Mahonin |
b53a5c |
|