2012-05-30 17:41:39 +08:00
|
|
|
#!/usr/bin/env python
|
2012-01-03 09:02:30 +08:00
|
|
|
|
2012-01-15 16:25:21 +08:00
|
|
|
|
2012-07-09 06:20:39 +08:00
|
|
|
import string, sys, os.path, getopt
|
2012-01-03 09:02:30 +08:00
|
|
|
|
|
|
|
escapes = {}
|
|
|
|
escapes['\a'] = r'\a'
|
|
|
|
escapes['\b'] = r'\b'
|
|
|
|
escapes['\f'] = r'\f'
|
|
|
|
escapes['\n'] = r'\n'
|
|
|
|
escapes['\r'] = r'\r'
|
|
|
|
#escapes['\t'] = r'\t'
|
|
|
|
# Let's replace tabs with four spaces
|
|
|
|
# so the text looks nicely indented in the C source
|
2012-01-15 16:25:21 +08:00
|
|
|
escapes['\t'] = r' '
|
2012-01-03 09:02:30 +08:00
|
|
|
escapes['\v'] = r'\v'
|
|
|
|
# escapes['\''] = r'\''
|
|
|
|
escapes['\"'] = r'\"'
|
|
|
|
escapes['\\'] = r'\\'
|
|
|
|
|
|
|
|
def escape(c):
|
|
|
|
if c in escapes:
|
2012-01-15 16:25:21 +08:00
|
|
|
return (escapes[c], False)
|
2012-01-03 09:02:30 +08:00
|
|
|
elif c not in string.printable:
|
2012-01-15 16:25:21 +08:00
|
|
|
return ("\\x%x" % ord(c), True)
|
2012-01-03 09:02:30 +08:00
|
|
|
else:
|
2012-01-15 16:25:21 +08:00
|
|
|
return (c, False)
|
2012-01-03 09:02:30 +08:00
|
|
|
|
|
|
|
def stringize(line):
|
|
|
|
newline = '"'
|
2012-01-15 16:25:21 +08:00
|
|
|
was_escape = False
|
2012-01-03 09:02:30 +08:00
|
|
|
for c in line:
|
2012-01-15 16:25:21 +08:00
|
|
|
# Avoid an issue where characters after a hexadecimal escape are treated as part of that escape
|
|
|
|
# by adding two quotes
|
|
|
|
if was_escape and c in string.hexdigits:
|
|
|
|
newline += '""'
|
|
|
|
chars, was_escape = escape(c)
|
|
|
|
newline += chars
|
2012-01-03 09:02:30 +08:00
|
|
|
newline += '"'
|
|
|
|
return newline
|
|
|
|
|
|
|
|
class cfunc:
|
2012-01-15 16:25:21 +08:00
|
|
|
def __init__(self, type, name, lines):
|
|
|
|
self.type = type
|
2012-01-03 09:02:30 +08:00
|
|
|
self.name = name
|
|
|
|
self.lines = lines
|
|
|
|
|
|
|
|
def cdef(self):
|
|
|
|
result = ""
|
2012-05-30 17:41:39 +08:00
|
|
|
result += "static const char * const {0} = \n\t".format(self.cfunc_name())
|
2012-01-03 09:02:30 +08:00
|
|
|
result += '\n\t'.join(self.lines)
|
|
|
|
result += ';\n'
|
|
|
|
return result
|
|
|
|
|
|
|
|
def cfunc_name(self):
|
2012-01-15 16:25:21 +08:00
|
|
|
# Translate - and . to underscore
|
2012-05-30 17:41:39 +08:00
|
|
|
try: #Python 2
|
|
|
|
translator = string.maketrans('-.', '__')
|
|
|
|
munged_name = string.translate(self.name, translator)
|
|
|
|
except AttributeError: #Python 3
|
|
|
|
translator = "".maketrans('-.', '__')
|
|
|
|
munged_name = self.name.translate(translator)
|
|
|
|
return "{0}_{1}".format(self.type, munged_name)
|
2012-01-03 09:02:30 +08:00
|
|
|
|
2012-01-15 16:25:21 +08:00
|
|
|
TYPES = ['function', 'completion']
|
|
|
|
type_to_funcs = dict((t, []) for t in TYPES)
|
2012-07-09 06:20:39 +08:00
|
|
|
|
|
|
|
def usage(script_name):
|
|
|
|
print("Usage: {0} [--output output_directory] files...".format(script_name))
|
|
|
|
print("""Command options are:
|
|
|
|
--output directory\t\tThe directory to output the files
|
|
|
|
-h, --help\t\t\tShow this help message
|
|
|
|
""")
|
|
|
|
|
|
|
|
script_name = sys.argv[0]
|
|
|
|
try:
|
|
|
|
opts, file_paths = getopt.gnu_getopt(sys.argv[1:], 'h', ['output=', 'help'])
|
|
|
|
except getopt.GetoptError as err:
|
|
|
|
print(err.msg) # will print something like "option -a not recognized"
|
|
|
|
usage(script_name)
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
output_directory = './'
|
|
|
|
for opt, value in opts:
|
|
|
|
if opt in ('--output',):
|
|
|
|
output_directory = value
|
|
|
|
elif opt in ('-h', '--help'):
|
|
|
|
usage(script_name)
|
|
|
|
sys.exit(0)
|
|
|
|
else:
|
|
|
|
assert False, "unhandled option"
|
|
|
|
|
|
|
|
|
|
|
|
for file in file_paths:
|
2012-01-03 09:02:30 +08:00
|
|
|
fd = open(file, 'r')
|
|
|
|
newlines = []
|
|
|
|
for line in fd:
|
|
|
|
newlines.append(stringize(line))
|
|
|
|
fd.close()
|
2012-01-15 16:25:21 +08:00
|
|
|
dirname = os.path.dirname(file)
|
|
|
|
|
|
|
|
# Try to figure out the file type (completion or function)
|
|
|
|
matches = [dir in dirname for dir in TYPES]
|
|
|
|
if matches.count(True) is not 1:
|
2012-05-30 17:41:39 +08:00
|
|
|
print("Cannot determine the type of the file at path {0}".format(file))
|
2012-01-15 16:25:21 +08:00
|
|
|
sys.exit(-1)
|
|
|
|
type = TYPES[matches.index(True)]
|
|
|
|
|
2012-01-03 09:02:30 +08:00
|
|
|
name = os.path.basename(file)
|
|
|
|
name, ext = os.path.splitext(name)
|
2012-01-15 16:25:21 +08:00
|
|
|
newfunc = cfunc(type, name, newlines)
|
|
|
|
type_to_funcs[type].append(newfunc)
|
2012-01-03 09:02:30 +08:00
|
|
|
|
|
|
|
# Sort our functions by name
|
2012-05-30 17:41:39 +08:00
|
|
|
for funcs in type_to_funcs.values():
|
2012-01-15 16:25:21 +08:00
|
|
|
funcs.sort(key=cfunc.cfunc_name)
|
2012-01-03 09:02:30 +08:00
|
|
|
|
|
|
|
# Output our header
|
2012-07-09 06:20:39 +08:00
|
|
|
fd = open(os.path.join(output_directory, 'builtin_scripts.h'), 'w')
|
2012-01-03 09:02:30 +08:00
|
|
|
fd.write('/* This file is generated by internalize_scripts.py */\n\n')
|
|
|
|
fd.write("""struct builtin_script_t {
|
2012-01-06 03:44:57 +08:00
|
|
|
const wchar_t *name;
|
2012-01-03 09:02:30 +08:00
|
|
|
const char *def;
|
|
|
|
};""")
|
|
|
|
|
|
|
|
fd.write('\n')
|
2012-01-15 16:25:21 +08:00
|
|
|
|
|
|
|
for type in TYPES:
|
|
|
|
funcs = type_to_funcs[type]
|
|
|
|
fd.write('\n')
|
2012-05-30 17:41:39 +08:00
|
|
|
fd.write('extern const struct builtin_script_t internal_{0}_scripts[{1}];'.format(type, len(funcs)))
|
2012-01-15 16:25:21 +08:00
|
|
|
fd.write('\n')
|
2012-01-03 09:02:30 +08:00
|
|
|
fd.close()
|
|
|
|
|
|
|
|
# Output the function definitions
|
2012-07-09 06:20:39 +08:00
|
|
|
fd = open(os.path.join(output_directory, 'builtin_scripts.cpp'), 'w')
|
2012-01-03 09:02:30 +08:00
|
|
|
fd.write('/* This file is generated by internalize_scripts.py */\n\n')
|
|
|
|
fd.write('#include "builtin_scripts.h"\n\n')
|
2012-01-15 16:25:21 +08:00
|
|
|
for type in TYPES:
|
|
|
|
for func in type_to_funcs[type]:
|
|
|
|
fd.write(func.cdef())
|
|
|
|
fd.write('\n')
|
2012-01-03 09:02:30 +08:00
|
|
|
|
|
|
|
# Output the refs
|
2012-01-15 16:25:21 +08:00
|
|
|
for type in TYPES:
|
|
|
|
funcs = type_to_funcs[type]
|
2012-05-30 17:41:39 +08:00
|
|
|
func_refs = ["{0}L{1}, {2}{3}".format("{", stringize(func.name), func.cfunc_name(), "}") for func in funcs]
|
|
|
|
fd.write('const struct builtin_script_t internal_{0}_scripts[{1}] =\n'.format(type, len(funcs)))
|
2012-01-15 16:25:21 +08:00
|
|
|
fd.write('{\n\t')
|
|
|
|
fd.write(',\n\t'.join(func_refs))
|
|
|
|
fd.write('\n};\n')
|
|
|
|
fd.close()
|