#!/usr/bin/env python3 import os import sys import datetime if len(sys.argv) <= 1: print("Expected argument: string list. Strings to be put in PROGMEM, along with an index table.") sys.exit(-1) if len(sys.argv) <= 2: print("Expected argument: destination. The path to be appended with '.h' for the destination file.") sys.exit(-1) stringFile = sys.argv[1] destPath = sys.argv[2] if destPath.endswith(".h"): destPath = destPath.replace(".h", "") if destPath.endswith(".cpp"): destPath = destPath.replace(".cpp", "") destFname = os.path.basename(destPath) print("str2pgmspace: processing '{}' into '{}.[h,c]'".format(stringFile, destPath)) if not os.path.exists( stringFile ): print("File does not exist...") exit(-1) fileDir = os.path.dirname(stringFile) + "/" idtf = None blob = bytearray() indexes = [] with open(stringFile, "r") as flist: lcounter = 1 l = flist.readline() if(l.endswith('\n')): l = l[:-1] while l != "" : tokens = l.split() if len(tokens) == 2: if tokens[0] == "__IDENTIFIER": idtf = tokens[1] l = flist.readline() lcounter += 1 continue if(not l.startswith("#")): indexes.append(len(blob)) idx = 0 while idx < len(l): if(l[idx] == "¬"[0] and idx+2 < len(l)): # char byte in hex incoming hex = "" hex += l[idx+1] hex += l[idx+2] blob += bytes.fromhex(hex) idx += 2 else: blob += bytes([ord(l[idx])]) idx += 1 blob.append(0); # add null terminator to every string l = flist.readline() if(l.endswith('\n')): l = l[:-1] idtf = "_progmem_str" if not idtf else idtf outh = open(destPath+".h", "w") outc = open(destPath+".c", "w") # add initial cruft outh.write("#pragma once\n\n#include \n\n") outh.write("// '{}.h': generated by str2pgmspace from '{}' at {}\n".format(destPath, stringFile, datetime.datetime.now())) outc.write('#include "./{}.h"\n\n'.format(destFname)) # add constants and interface outh.write("static const int {}_COUNT = {};\n".format(idtf.upper(), len(indexes))) outh.write("static const int {}_BLOB_SZ = {};\n".format(idtf.upper(), len(blob))) outh.write("extern const unsigned short {}_offsets[];\n".format(idtf)) outh.write("extern const char {}_blob[];\n".format(idtf)) outh.write("\n#define {}_GET_OFFSET(I) pgm_read_word(&({}_offsets[(I)]]))\n".format(idtf.upper(), idtf)) outh.write("\n#define {}_GET(I) ( ((const char*) &{}_blob) + {}_GET_OFFSET(I) )\n".format(idtf.upper(), idtf, idtf.upper())) # write blob to c file now outc.write("const char {}_blob[] PROGMEM = \n".format(idtf)) allbytes = blob sz = len(allbytes) chunks = sz // 16 if (sz % 16): chunks += 1 for i in range(chunks): end = (i+1)*32 end = end if end <= len(allbytes) else len(allbytes) chunk = allbytes[i*16:end] outc.write('"') for j in range(len(chunk)): outc.write('\\x{:02x}'.format(chunk[j])); outc.write('"\n') outc.write(";\n\n") # write indices to c file now outc.write("const unsigned short {}_offsets[] PROGMEM = {}\n ".format(idtf, "{")) idxcnt = 1 for i in range(len(indexes)): outc.write(str(indexes[i])) if(i < len(indexes) - 1): outc.write(", ") if idxcnt%32 == 0: outc.write('\n ') idxcnt += 1 outc.write("};\n\n") print("str2pgmspace done!")