Fixes #7171
[opentx.git] / radio / util / luaexport.py
blob1e6355f57205f6241cf6d35c4f1fb7cf42ed3925
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 from __future__ import print_function
6 import sys
7 import os
8 import traceback
9 import time
10 import re
12 PREC1 = 10
13 PREC2 = 100
15 CONSTANT_VALUE = ""
16 dups_cnst = []
17 dups_name = []
18 exports = []
19 exports_multiple = []
20 exports_script_outputs = []
22 warning = None
23 error = None
26 def checkName(name):
27 global warning
28 if name in dups_name:
29 print("WARNING: Duplicate name %s found for constant %s" % (name, CONSTANT_VALUE))
30 warning = True
31 dups_name.append(name)
32 if name != name.lower():
33 print("WARNING: Name not in lower case %s found for constant %s" % (name, CONSTANT_VALUE))
34 warning = True
37 def LEXP(name, description):
38 # print "LEXP %s, %s" % (name, description)
39 checkName(name)
40 exports.append((CONSTANT_VALUE, name, description))
43 def LEXP_MULTIPLE(nameFormat, descriptionFormat, valuesCount):
44 # print "LEXP_MULTIPLE %s, %s, %s" % (nameFormat, descriptionFormat, valuesCount)
45 for v in range(valuesCount):
46 name = nameFormat + str(v)
47 # print name
48 checkName(name)
49 exports_multiple.append((CONSTANT_VALUE, nameFormat, descriptionFormat, valuesCount))
52 if len(sys.argv) < 3:
53 print("Error: not enough arguments!")
54 print("Usage:")
55 print(" luaexport.py <version> <input txt> <output cpp> [<doc output>]")
57 version = sys.argv[1]
58 inputFile = sys.argv[2]
59 outputFile = sys.argv[3]
60 docFile = None
61 if len(sys.argv) >= 4:
62 docFile = sys.argv[4]
63 print("Version %s" % version)
64 print("Input file %s" % inputFile)
65 print("Output file %s" % outputFile)
66 if docFile:
67 print("Documentation file %s" % docFile)
69 with open(inputFile, "r") as inp:
70 while True:
71 line = inp.readline()
72 if len(line) == 0:
73 break
74 line = line.strip('\r\n')
75 line = line.strip()
76 # print "line: %s" % line
78 if line.find('LEXP') < 0:
79 continue
81 parts = line.split('LEXP')
82 # print parts
83 if len(parts) != 2:
84 print("Wrong line: %s" % line)
85 continue
86 cmd = 'LEXP' + parts[1]
87 cnst = parts[0].rstrip(', ')
88 if cnst.find('=') != -1:
89 # constant contains =
90 cnst = cnst.split('=')[0].strip()
91 # print "Found constant %s with command: %s" % (cnst, cmd)
92 try:
93 CONSTANT_VALUE = cnst
94 # if CONSTANT_VALUE in dups_cnst:
95 # print "WARNING: Duplicate CONSTANT_VALUE found: %s" % CONSTANT_VALUE
96 # warning = True
97 # continue
98 # dups_cnst.append(CONSTANT_VALUE)
99 # print cmd
100 eval(cmd)
101 except:
102 print("ERROR: problem with the definition: %s" % line)
103 traceback.print_exc()
104 error = True
106 with open(outputFile, "w") as out:
107 out.write("//This file was generated by luaexport.py script on %s for OpenTX version %s\n\n\n"
108 % (time.asctime(), version))
110 header = """
111 struct LuaSingleField {
112 uint16_t id;
113 const char * name;
114 const char * desc;
117 struct LuaMultipleField {
118 uint16_t id;
119 const char * name;
120 const char * desc;
121 uint8_t count;
125 out.write(header)
127 out.write("""
128 // The list of Lua fields
129 // this aray is alphabetically sorted by the second field (name)
130 const LuaSingleField luaSingleFields[] = {
131 """)
132 exports.sort(key=lambda x: x[1]) # sort by name
133 data = [" {%s, \"%s\", \"%s\"}" % export for export in exports]
134 out.write(",\n".join(data))
135 out.write("\n};\n\n")
136 print("Generated %d items in luaFields[]" % len(exports))
138 out.write("""
139 // The list of Lua fields that have a range of values
140 const LuaMultipleField luaMultipleFields[] = {
141 """)
142 data = [" {%s, \"%s\", \"%s\", %d}" % export for export in exports_multiple]
143 out.write(",\n".join(data))
144 out.write("\n};\n\n")
145 print("Generated %d items in luaMultipleFields[]" % len(exports_multiple))
147 if docFile:
148 # prepare fields
149 all_exports = [(name, desc) for (id, name, desc) in exports]
150 for (id, nameFormat, descriptionFormat, valuesCount) in exports_multiple:
151 for v in range(1, valuesCount + 1):
152 name = nameFormat + str(v)
153 desc = descriptionFormat % v
154 all_exports.append((name, desc))
155 # natural sort by field name
156 convert = lambda text: int(text) if text.isdigit() else text
157 alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key[0])]
158 all_exports.sort(key=alphanum_key)
160 with open(docFile, "w") as out:
161 out.write("Alphabetical list of Lua fields for OpenTX version %s\n\n\n" % version)
162 FIELD_NAME_WIDTH = 25
163 out.write("Field name%sField description\n" % (' ' * (FIELD_NAME_WIDTH - len('Field name'))))
164 out.write("----------------------------------------------\n")
165 data = ["%s%s%s" % (name_, ' ' * (FIELD_NAME_WIDTH - len(name_)), desc_) for (name_, desc_) in all_exports]
166 out.write("\n".join(data))
167 out.write("\n")
169 if warning:
170 sys.exit(1)
171 elif error:
172 os.remove(outputFile)
173 sys.exit(2)
174 sys.exit(0)