]> sigrok.org Git - sigrok-util.git/blob - source/new-driver
81f40699ada296e03a5855031189744e0101445f
[sigrok-util.git] / source / new-driver
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
21 import os
22 import sys
23 import tempfile
24 from subprocess import Popen, PIPE, check_output
25 import shutil
26 import re
27 import socket
28 import datetime
29
30 TMPL_AUTOCONF_DRIVER = "SR_DRIVER([${name}], [${short}])\n"
31
32 TMPL_HWMAKE_DRIVERLIB = """if HW_${upper}
33 libsigrok_la_SOURCES += \\
34         src/hardware/${short}/protocol.h \\
35         src/hardware/${short}/protocol.c \\
36         src/hardware/${short}/api.c
37 endif
38 """
39 FILE_DRV_API = 'drv-api.c'
40 FILE_DRV_PROTOCOL = 'drv-protocol.c'
41 FILE_DRV_PROTOCOL_H = 'drv-protocol.h'
42
43 def tmpl(template):
44     out = re.sub(r'\${([^}]+)}', lambda x: str(names[x.group(1)]), template)
45
46     return out
47
48
49 def tmpl_file(filename):
50     template = open(os.path.join(TMPLDIR, filename)).read()
51
52     return tmpl(template)
53
54
55 def 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 = os.path.join(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
75 def do_autoconf(gitdir):
76     cacpath = os.path.join(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
99 def do_automake(gitdir):
100     path = os.path.join(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
126 def do_driverskel(gitdir):
127     drvdir = os.path.join(gitdir, 'src', 'hardware', names['short'])
128     os.mkdir(drvdir)
129     open(os.path.join(drvdir, 'api.c'), 'w').write(tmpl_file(FILE_DRV_API))
130     open(os.path.join(drvdir, 'protocol.c'), 'w').write(tmpl_file(FILE_DRV_PROTOCOL))
131     open(os.path.join(drvdir, 'protocol.h'), 'w').write(tmpl_file(FILE_DRV_PROTOCOL_H))
132
133
134 def make_patch(gitdir):
135     os.chdir(gitdir)
136     command(['git', 'add', os.path.join('src', 'hardware', names['short'])])
137     cmd = ['git', 'commit',
138            '-m', '%s: Initial driver skeleton.' % names['short'],
139            'configure.ac', 'Makefile.am',
140            os.path.join('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(os.path.join(gitdir, patch),
148                 os.path.join(scriptdir, patch))
149     print(patch)
150
151
152 def command(cmd):
153     out, err = Popen(cmd, stderr=PIPE).communicate()
154     if err:
155         raise Exception(err.decode())
156
157
158 def parse_gitconfig():
159     author = email = None
160     try:
161         author = check_output(["git", "config", "user.name"]).decode().strip();
162         email = check_output(["git", "config", "user.email"]).decode().strip();
163     except:
164         print("Please set your name and email in your git config")
165         sys.exit()
166     return author, email
167
168 #
169 # main
170 #
171
172 scriptdir = os.getcwd()
173 if scriptdir.split('/')[-2:] != ['sigrok-util', 'source']:
174         print("Please call this script from the 'source' directory.")
175         sys.exit(1)
176
177 LIBSR = 'git://sigrok.org/libsigrok'
178 TMPLDIR = scriptdir
179
180 if len(sys.argv) < 2:
181     print("Usage: new-driver <name>")
182     sys.exit()
183
184 author, email = parse_gitconfig()
185 name = ' '.join(sys.argv[1:])
186 names = {
187     'name': name,
188     'short': re.sub('[^a-z0-9]', '-', name.lower()),
189     'lib': re.sub('[^a-z0-9]', '_', name.lower()),
190     'upper': re.sub('[^A-Z0-9]', '_', name.upper()),
191     'year': datetime.datetime.now().year,
192     'author': author,
193     'email': email,
194 }
195 new_driver()
196