pico430prog/test/bin2h.py

113 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import os, re, sys, struct
import textwrap
import traceback
def sanitize_name(name):
# replace special characters with underscores
name = re.sub('[^a-zA-Z0-9_]', '_', name)
# clean up
name = name.strip('_')
# not needed: 'DATA_' prefix
#if name[0] in "0123456789": name = '_' + name
return name
def main():
parser = argparse.ArgumentParser(
description="Convert data files into byte arrays in a C header")
parser.add_argument('input', nargs='*', action='append',
help="Input data file to convert to a header file. If "
+"none are specified, data is read from standard input.")
parser.add_argument('--output', type=str, default=None,
help="Output header file path, standard output if none specified")
args = parser.parse_args()
#print(repr(args), file=sys.stderr)
inputfiles = args.input[0]
datafiles = {}
if len(inputfiles) == 0:
# need to read from stdio
datafiles['data'] = sys.stdin.buffer.read()
else:
for path in inputfiles:
# cannot use os.access, POSIX-only
if not os.path.exists(path) or os.path.isdir(path):
print("ERROR: input path '%s' does not exist, or is not a file" % path)
sys.exit(1)
# get base name of the path (no folder names, no extension)
name = os.path.splitext(os.path.split(path)[1])[0]
# make it usable for C code names
name = sanitize_name(name)
# now read the data
data = None
try:
with open(path, 'rb') as f:
data = f.read()
except IOError:
print("ERROR: input file '%s' not readable" % path)
traceback.print_exc()
sys.exit(1)
data = struct.unpack('<'+('H'*(len(data)//2)), data)
# add it to the list
datafiles[name] = data
#print(repr(datafiles), file=sys.stderr)
outname = "hardcoded_data"
if args.output is not None:
outname = os.path.splitext(os.path.split(args.output)[1])[0]
outname = sanitize_name(outname)
# generate the C source code: one uint8_t array for each data file
# variable name is "DATA_<datafile>"
# (width=84 is the equivalent of 16 bytes/line)
headersrc = '\n\n'.join(
"static uint16_t DATA_%s[%d] = {\n%s\n};" % (name, len(data), \
textwrap.fill(','.join("0x%04x" % b for b in data), width=81,
initial_indent=" ", subsequent_indent=" ")
) for name, data in datafiles.items()
)
# a C header needs include guards
headersrc = """
#ifndef AUTOGEN_{0}_H_
#define AUTOGEN_{0}_H_
{1}
#endif
""".format(outname.upper(), headersrc)
#print(headersrc, file=sys.stderr)
if args.output is None:
# no output specified -> output to stdout
sys.stdout.write(headersrc)
else:
try:
with open(args.output, 'w') as f:
f.write(headersrc)
except IOError:
print("ERROR: output file '%s' not writable" % args.output)
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
main()