rename script tp match repo
[camargo/str2progmem.git] / str2progmem
1 #!/usr/bin/env python3
2
3 import os
4 import sys
5 import datetime
6
7
8 if len(sys.argv) <= 1:
9     print("Expected argument: string list. Strings to be put in PROGMEM, along with an index table.")
10     sys.exit(-1)
11
12 if len(sys.argv) <= 2:
13     print("Expected argument: destination. The path to be appended with '.h' for the destination file.")
14     sys.exit(-1)
15
16 stringFile = sys.argv[1]
17 destPath = sys.argv[2]
18
19 if destPath.endswith(".h"):
20     destPath = destPath.replace(".h", "")
21 if destPath.endswith(".cpp"):
22     destPath = destPath.replace(".cpp", "")
23
24 destFname = os.path.basename(destPath)
25
26 print("str2pgmspace: processing '{}' into '{}.[h,c]'".format(stringFile, destPath))
27
28 if not os.path.exists( stringFile ):
29     print("File does not exist...")
30     exit(-1)
31
32 fileDir = os.path.dirname(stringFile) + "/"
33
34 idtf = None
35 blob = bytearray()
36 indexes = []
37
38 with open(stringFile, "r") as flist:
39     lcounter = 1
40
41     l = flist.readline()
42     if(l.endswith('\n')):
43         l = l[:-1]
44
45     while l != "" :
46         tokens = l.split()
47         if len(tokens) == 2:
48             if tokens[0] == "__IDENTIFIER":
49                 idtf = tokens[1]
50                 l = flist.readline()
51                 lcounter += 1
52                 continue
53
54         if(not l.startswith("#")):
55             indexes.append(len(blob))
56             idx = 0
57             while idx < len(l):
58                 if(l[idx] == "¬"[0] and idx+2 < len(l)):
59                     # char byte in hex incoming
60                     hex = ""
61                     hex += l[idx+1]
62                     hex += l[idx+2]
63                     blob += bytes.fromhex(hex)
64                     idx += 2
65                 else:
66                     blob += bytes([ord(l[idx])])
67
68                 idx += 1
69             blob.append(0); # add null terminator to every string
70
71
72         l = flist.readline()
73         if(l.endswith('\n')):
74             l = l[:-1]
75
76 idtf = "_progmem_str" if not idtf else idtf
77
78 outh = open(destPath+".h", "w")
79 outc = open(destPath+".c", "w")
80
81 # add initial cruft
82 outh.write("#pragma once\n\n#include <avr/pgmspace.h>\n\n")
83 outh.write("// '{}.h': generated by str2pgmspace from '{}' at {}\n".format(destPath, stringFile, datetime.datetime.now()))
84 outc.write('#include "./{}.h"\n\n'.format(destFname))
85
86
87 # add constants and interface
88 outh.write("static const int {}_COUNT = {};\n".format(idtf.upper(), len(indexes)))
89 outh.write("static const int {}_BLOB_SZ = {};\n".format(idtf.upper(), len(blob)))
90 outh.write("extern const unsigned short {}_offsets[];\n".format(idtf))
91 outh.write("extern const char {}_blob[];\n".format(idtf))
92 outh.write("\n#define {}_GET_OFFSET(I) pgm_read_word(&({}_offsets[(I)]]))\n".format(idtf.upper(), idtf))
93 outh.write("\n#define {}_GET(I) ( ((const char*) &{}_blob) + {}_GET_OFFSET(I) )\n".format(idtf.upper(), idtf, idtf.upper()))
94
95
96 # write blob to c file now
97 outc.write("const char {}_blob[] PROGMEM = \n".format(idtf))
98 allbytes = blob
99 sz = len(allbytes)
100 chunks = sz // 16
101
102 if (sz % 16):
103     chunks += 1
104
105 for i in range(chunks):
106     end = (i+1)*32
107     end = end if end <= len(allbytes) else len(allbytes)
108     chunk = allbytes[i*16:end]
109
110     outc.write('"')
111     for j in range(len(chunk)):
112         outc.write('\\x{:02x}'.format(chunk[j]));
113     outc.write('"\n')
114
115 outc.write(";\n\n")
116
117
118 # write indices to c file now
119 outc.write("const unsigned short {}_offsets[] PROGMEM = {}\n    ".format(idtf, "{"))
120 idxcnt = 1
121 for i in range(len(indexes)):
122
123     outc.write(str(indexes[i]))
124     if(i < len(indexes) - 1):
125         outc.write(", ")
126     if idxcnt%32 == 0:
127         outc.write('\n    ')
128     idxcnt += 1
129
130 outc.write("};\n\n")
131
132
133 print("str2pgmspace done!")