]> sigrok.org Git - sigrok-util.git/blame - source/new-driver
new-driver: put the cleanup part in a finally block
[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
fe85502e 24from subprocess import Popen, PIPE, check_output
a65d66c0
BV
25import shutil
26import re
27import socket
28import datetime
29
fe85502e 30TMPL_AUTOCONF_DRIVER = "SR_DRIVER([${name}], [${short}])\n"
7d787983 31
d51b5323 32TMPL_HWMAKE_DRIVERLIB = """if HW_${upper}
68ec5073 33libsigrok_la_SOURCES += \\
6ebf3016
BV
34 src/hardware/${short}/protocol.h \\
35 src/hardware/${short}/protocol.c \\
36 src/hardware/${short}/api.c
d51b5323 37endif
d51b5323 38"""
a65d66c0
BV
39FILE_DRV_API = 'drv-api.c'
40FILE_DRV_PROTOCOL = 'drv-protocol.c'
41FILE_DRV_PROTOCOL_H = 'drv-protocol.h'
42
43def tmpl(template):
44 out = re.sub(r'\${([^}]+)}', lambda x: str(names[x.group(1)]), template)
45
46 return out
47
48
49def tmpl_file(filename):
b63f8cef 50 template = open(os.path.join(TMPLDIR, filename)).read()
a65d66c0
BV
51
52 return tmpl(template)
53
54
55def new_driver():
56 tmp = tempfile.mkdtemp()
57 try:
58 os.chdir(tmp)
e21df210
DD
59 process = Popen(['git', 'clone', '--depth=1', LIBSR],
60 stdout=PIPE, stderr=PIPE)
617f4da0
AJ
61 out, err = process.communicate()
62 if process.returncode:
a65d66c0 63 raise Exception(err.decode())
b63f8cef 64 gitdir = os.path.join(tmp, 'libsigrok')
3e61a9d8 65 do_autoconf(gitdir)
3e61a9d8 66 do_automake(gitdir)
a65d66c0
BV
67 do_driverskel(gitdir)
68 make_patch(gitdir)
69 except Exception as e:
70 print(e)
e3f27bc0
DD
71 finally:
72 shutil.rmtree(tmp)
a65d66c0
BV
73
74
d0d6e169 75# add DRIVER and DRIVER2 entries to configure.ac
3e61a9d8 76def do_autoconf(gitdir):
b63f8cef 77 cacpath = os.path.join(gitdir, 'configure.ac')
a65d66c0
BV
78 configure_ac = open(cacpath).read()
79
a65d66c0 80 out = ''
3e61a9d8
BV
81 state = 'driver'
82 active = False
a65d66c0 83 for line in configure_ac.split('\n')[:-1]:
3e61a9d8 84 if state == 'driver':
fe85502e 85 m = re.match(r'SR_DRIVER\(\[([^\]]+)', line)
a65d66c0 86 if m:
3e61a9d8
BV
87 active = True
88 if active:
89 if (m and m.group(1).upper() > names['name'].upper()) or m is None:
90 out += tmpl(TMPL_AUTOCONF_DRIVER)
3e61a9d8 91 state = 'done'
fe85502e 92 active = False
a65d66c0
BV
93 out += line + '\n'
94 if state != 'done':
fe85502e 95 raise Exception('No SR_DRIVER entries found in configure.ac')
3e61a9d8 96 open(cacpath, 'w').write(out)
a65d66c0 97
a65d66c0 98
3e61a9d8
BV
99# add HW_ entry to Makefile.am
100def do_automake(gitdir):
b63f8cef 101 path = os.path.join(gitdir, 'Makefile.am')
a65d66c0
BV
102 hwmake = open(path).read()
103
a65d66c0
BV
104 out = ''
105 state = 'copy'
106 for line in hwmake.split('\n')[:-1]:
fe85502e 107 if state == 'copy' and re.match(r'if\s+HW_\w+$', line):
3e61a9d8
BV
108 state = 'drivers'
109 if state == 'drivers':
fe85502e 110 m = re.match(r'if\s+HW_(\w+)$', line)
d51b5323
BV
111 if m:
112 drv_short = m.group(1)
113 if drv_short > names['upper']:
114 out += tmpl(TMPL_HWMAKE_DRIVERLIB)
115 state = 'done'
fe85502e 116 elif not re.match(r'\s*libsigrok_la_SOURCES\b|\s*src/hardware/|endif\b', line):
3e61a9d8
BV
117 print("[%s]" % line.strip())
118 # we passed the last entry
119 out += tmpl(TMPL_HWMAKE_DRIVERLIB)
120 state = 'done'
a65d66c0 121 out += line + '\n'
7d787983 122 if state != 'done':
3e61a9d8
BV
123 raise Exception('No "if HW_" markers found in Makefile.am')
124 open(path, 'w').write(out)
a65d66c0
BV
125
126
127def do_driverskel(gitdir):
b63f8cef 128 drvdir = os.path.join(gitdir, 'src', 'hardware', names['short'])
a65d66c0 129 os.mkdir(drvdir)
b63f8cef
DD
130 open(os.path.join(drvdir, 'api.c'), 'w').write(tmpl_file(FILE_DRV_API))
131 open(os.path.join(drvdir, 'protocol.c'), 'w').write(tmpl_file(FILE_DRV_PROTOCOL))
132 open(os.path.join(drvdir, 'protocol.h'), 'w').write(tmpl_file(FILE_DRV_PROTOCOL_H))
a65d66c0
BV
133
134
135def make_patch(gitdir):
136 os.chdir(gitdir)
b63f8cef 137 command(['git', 'add', os.path.join('src', 'hardware', names['short'])])
e21df210
DD
138 cmd = ['git', 'commit',
139 '-m', '%s: Initial driver skeleton.' % names['short'],
140 'configure.ac', 'Makefile.am',
b63f8cef 141 os.path.join('src', 'hardware', names['short'])]
a65d66c0 142 command(cmd)
e21df210
DD
143 cmd = ['git', 'format-patch', 'HEAD~1']
144 out, err = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
a65d66c0
BV
145 if err:
146 raise Exception(err.decode())
147 patch = out.decode().strip()
b63f8cef
DD
148 shutil.move(os.path.join(gitdir, patch),
149 os.path.join(scriptdir, patch))
a65d66c0
BV
150 print(patch)
151
152
153def command(cmd):
e21df210 154 out, err = Popen(cmd, stderr=PIPE).communicate()
a65d66c0
BV
155 if err:
156 raise Exception(err.decode())
157
158
159def parse_gitconfig():
fe85502e 160 author = email = None
0af91589 161 try:
fe85502e
DE
162 author = check_output(["git", "config", "user.name"]).decode().strip();
163 email = check_output(["git", "config", "user.email"]).decode().strip();
0af91589 164 except:
fe85502e 165 print("Please set your name and email in your git config")
0af91589 166 sys.exit()
0af91589 167 return author, email
a65d66c0
BV
168
169#
170# main
171#
172
173scriptdir = os.getcwd()
87c5b243
BV
174if scriptdir.split('/')[-2:] != ['sigrok-util', 'source']:
175 print("Please call this script from the 'source' directory.")
176 sys.exit(1)
177
178LIBSR = 'git://sigrok.org/libsigrok'
179TMPLDIR = scriptdir
a65d66c0
BV
180
181if len(sys.argv) < 2:
0af91589 182 print("Usage: new-driver <name>")
a65d66c0
BV
183 sys.exit()
184
185author, email = parse_gitconfig()
186name = ' '.join(sys.argv[1:])
187names = {
188 'name': name,
189 'short': re.sub('[^a-z0-9]', '-', name.lower()),
190 'lib': re.sub('[^a-z0-9]', '_', name.lower()),
191 'upper': re.sub('[^A-Z0-9]', '_', name.upper()),
0af91589
UH
192 'year': datetime.datetime.now().year,
193 'author': author,
194 'email': email,
a65d66c0
BV
195}
196new_driver()
197