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