]> sigrok.org Git - sigrok-util.git/blame - source/new-driver
new-driver: Use new DRIVER and drivers.c build changes.
[sigrok-util.git] / source / new-driver
CommitLineData
a65d66c0 1#!/usr/bin/python3
0af91589
UH
2##
3## This file is part of the sigrok-util project.
4##
5## Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
6##
7## This program is free software: you can redistribute it and/or modify
8## it under the terms of the GNU General Public License as published by
9## the Free Software Foundation, either version 3 of the License, or
10## (at your option) any later version.
11##
12## This program is distributed in the hope that it will be useful,
13## but WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15## GNU General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with this program. If not, see <http://www.gnu.org/licenses/>.
19##
a65d66c0
BV
20
21import os
22import sys
23import tempfile
24from subprocess import Popen, PIPE
25import shutil
26import re
27import socket
28import datetime
29
3e61a9d8
BV
30TMPL_AUTOCONF_DRIVER = "DRIVER([${name}], [${short}])\n"
31TMPL_AUTOCONF_AM_CONDITIONAL = """\
a65d66c0
BV
32AM_CONDITIONAL(HW_${upper}, test x$HW_${upper} = xyes)
33if test "x$HW_${upper}" = "xyes"; then
28113f29 34 AC_DEFINE(HAVE_HW_${upper}, 1, [${name} support])
a65d66c0
BV
35fi
36
37"""
7d787983 38
d51b5323 39TMPL_HWMAKE_DRIVERLIB = """if HW_${upper}
68ec5073
UH
40libsigrok_la_SOURCES += \\
41 hardware/${short}/protocol.h \\
42 hardware/${short}/protocol.c \\
7d787983 43 hardware/${short}/api.c
d51b5323 44endif
d51b5323 45"""
3e61a9d8 46TMPL_DRIVERS_EXTERN = """\
d51b5323
BV
47#ifdef HAVE_HW_${upper}
48extern SR_PRIV struct sr_dev_driver ${lib}_driver_info;
49#endif
50"""
3e61a9d8 51TMPL_DRIVERS_POINTER = """\
d51b5323
BV
52#ifdef HAVE_HW_${upper}
53 &${lib}_driver_info,
54#endif
55"""
a65d66c0
BV
56FILE_DRV_API = 'drv-api.c'
57FILE_DRV_PROTOCOL = 'drv-protocol.c'
58FILE_DRV_PROTOCOL_H = 'drv-protocol.h'
59
60def tmpl(template):
61 out = re.sub(r'\${([^}]+)}', lambda x: str(names[x.group(1)]), template)
62
63 return out
64
65
66def tmpl_file(filename):
67 template = open(TMPLDIR + '/' + filename).read()
68
69 return tmpl(template)
70
71
72def new_driver():
73 tmp = tempfile.mkdtemp()
74 try:
75 os.chdir(tmp)
617f4da0
AJ
76 process = Popen("git clone " + LIBSR, shell=True, stderr=PIPE)
77 out, err = process.communicate()
78 if process.returncode:
a65d66c0
BV
79 raise Exception(err.decode())
80 gitdir = tmp + '/libsigrok/'
3e61a9d8
BV
81 do_autoconf(gitdir)
82 do_drivers(gitdir)
83 do_automake(gitdir)
a65d66c0
BV
84 do_driverskel(gitdir)
85 make_patch(gitdir)
86 except Exception as e:
87 print(e)
88 shutil.rmtree(tmp)
89
90
3e61a9d8
BV
91# add DRIVER and AM_CONDITIONAL/AC_DEFINE entries to configure.ac
92def do_autoconf(gitdir):
a65d66c0
BV
93 cacpath = gitdir + 'configure.ac'
94 configure_ac = open(cacpath).read()
95
a65d66c0 96 out = ''
3e61a9d8
BV
97 state = 'driver'
98 active = False
a65d66c0 99 for line in configure_ac.split('\n')[:-1]:
3e61a9d8
BV
100 if state == 'driver':
101 m = re.match('DRIVER\(\[([^\]]+)', line)
a65d66c0 102 if m:
3e61a9d8
BV
103 active = True
104 if active:
105 if (m and m.group(1).upper() > names['name'].upper()) or m is None:
106 out += tmpl(TMPL_AUTOCONF_DRIVER)
107 state = 'automake'
108 active = False
109 elif state == 'automake':
110 m = re.match('AM_CONDITIONAL\(HW_([^,]+)', line)
a65d66c0 111 if m:
3e61a9d8 112 active = True
a65d66c0 113 else:
3e61a9d8
BV
114 submatch = re.match('(if|\s*AC_DEFINE|fi|$)', line)
115 if active and submatch is None:
116 # we're past the conditionals
117 out += tmpl(TMPL_AUTOCONF_AM_CONDITIONAL)
118 state = 'done'
119 if active:
120 if (m and m.group(1) > names['upper']):
121 out += tmpl(TMPL_AUTOCONF_AM_CONDITIONAL)
122 state = 'done'
a65d66c0
BV
123 out += line + '\n'
124 if state != 'done':
3e61a9d8
BV
125 raise Exception('No DRIVER entries found in configure.ac')
126 open(cacpath, 'w').write(out)
a65d66c0 127
a65d66c0 128
3e61a9d8
BV
129# add HAVE_HW_ extern and pointers to drivers.c
130def do_drivers(gitdir):
131 path = gitdir + 'drivers.c'
132 source = open(path).read()
d51b5323 133 out = ''
3e61a9d8
BV
134 state = 'extern'
135 first_entry = ''
136 for line in source.split('\n')[:-1]:
137 m = re.match('#ifdef HAVE_HW_(.*)', line)
138 if m:
139 if not first_entry:
140 first_entry = m.group(1)
141 elif m.group(1) == first_entry:
142 # second time we see this, so we're past the externs
143 if state != 'idle':
144 # tack driver on to the end of the list
145 out += tmpl(TMPL_DRIVERS_EXTERN)
146 state = 'pointer'
d51b5323 147 if state == 'extern':
3e61a9d8
BV
148 if m.group(1) > names['upper']:
149 out += tmpl(TMPL_DRIVERS_EXTERN)
150 state = 'idle'
151 elif state == 'pointer':
152 if m.group(1) > names['upper']:
153 out += tmpl(TMPL_DRIVERS_POINTER)
154 state = 'done'
155 elif state == 'pointer' and not re.match('(\s*&|#endif|$)', line):
156 # we passed the last entry
157 out += tmpl(TMPL_DRIVERS_POINTER)
158 state = 'done'
d51b5323
BV
159 out += line + '\n'
160 if state != 'done':
3e61a9d8
BV
161 raise Exception('No "HAVE_HW_*" markers found in drivers.c' + state)
162 open(path, 'w').write(out)
d51b5323
BV
163
164
3e61a9d8
BV
165# add HW_ entry to Makefile.am
166def do_automake(gitdir):
7d787983 167 path = gitdir + 'Makefile.am'
a65d66c0
BV
168 hwmake = open(path).read()
169
a65d66c0
BV
170 out = ''
171 state = 'copy'
172 for line in hwmake.split('\n')[:-1]:
3e61a9d8
BV
173 if state == 'copy' and re.match('if HW_(.*)$', line):
174 state = 'drivers'
175 if state == 'drivers':
176 m = re.match('if HW_(.*)$', line)
d51b5323
BV
177 if m:
178 drv_short = m.group(1)
179 if drv_short > names['upper']:
180 out += tmpl(TMPL_HWMAKE_DRIVERLIB)
181 state = 'done'
3e61a9d8
BV
182 elif not re.match('(libsigrok_la_SOURCES|\s*hardware/|endif)', line):
183 print("[%s]" % line.strip())
184 # we passed the last entry
185 out += tmpl(TMPL_HWMAKE_DRIVERLIB)
186 state = 'done'
a65d66c0 187 out += line + '\n'
7d787983 188 if state != 'done':
3e61a9d8
BV
189 raise Exception('No "if HW_" markers found in Makefile.am')
190 open(path, 'w').write(out)
a65d66c0
BV
191
192
193def do_driverskel(gitdir):
194 drvdir = gitdir + 'hardware/' + names['short']
195 os.mkdir(drvdir)
a65d66c0
BV
196 open(drvdir + '/api.c', 'w').write(tmpl_file(FILE_DRV_API))
197 open(drvdir + '/protocol.c', 'w').write(tmpl_file(FILE_DRV_PROTOCOL))
198 open(drvdir + '/protocol.h', 'w').write(tmpl_file(FILE_DRV_PROTOCOL_H))
199
200
201def make_patch(gitdir):
202 os.chdir(gitdir)
203 command('git add hardware/' + names['short'])
0af91589 204 cmd = 'git commit -m "%s: Initial driver skeleton." ' % names['short']
3e61a9d8 205 cmd += 'configure.ac Makefile.am drivers.c hardware/' + names['short']
a65d66c0
BV
206 command(cmd)
207 cmd = "git format-patch HEAD~1"
208 out, err = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).communicate()
209 if err:
210 raise Exception(err.decode())
211 patch = out.decode().strip()
212 shutil.move(gitdir + '/' + patch, scriptdir + '/' + patch)
213 print(patch)
214
215
216def command(cmd):
217 out, err = Popen(cmd, shell=True, stderr=PIPE).communicate()
218 if err:
219 raise Exception(err.decode())
220
221
222def parse_gitconfig():
0af91589
UH
223 try:
224 author = email = None
225 for line in open(os.environ['HOME'] + '/.gitconfig').readlines():
226 m = re.match('\s*(\w+)\s*=\s*(.*)\s*$', line)
227 if m:
228 key, value = m.groups()
229 if key == 'name':
230 author = value
231 elif key == 'email':
232 email = value
233 if author and email:
234 break
235 except:
236 pass
237 if not author or not email:
238 print("Please put your name and email in ~/.gitconfig")
239 sys.exit()
240
241 return author, email
a65d66c0
BV
242
243#
244# main
245#
246
247scriptdir = os.getcwd()
87c5b243
BV
248if scriptdir.split('/')[-2:] != ['sigrok-util', 'source']:
249 print("Please call this script from the 'source' directory.")
250 sys.exit(1)
251
252LIBSR = 'git://sigrok.org/libsigrok'
3e61a9d8 253LIBSR = 'file:///home/bert/sigrok/libsigrok'
87c5b243 254TMPLDIR = scriptdir
a65d66c0
BV
255
256if len(sys.argv) < 2:
0af91589 257 print("Usage: new-driver <name>")
a65d66c0
BV
258 sys.exit()
259
260author, email = parse_gitconfig()
261name = ' '.join(sys.argv[1:])
262names = {
263 'name': name,
264 'short': re.sub('[^a-z0-9]', '-', name.lower()),
265 'lib': re.sub('[^a-z0-9]', '_', name.lower()),
266 'upper': re.sub('[^A-Z0-9]', '_', name.upper()),
267 'libupper': re.sub('[^A-Z0-9]', '', name.upper()),
0af91589
UH
268 'year': datetime.datetime.now().year,
269 'author': author,
270 'email': email,
a65d66c0
BV
271}
272new_driver()
273