From: David Douard Date: Mon, 30 May 2016 20:00:46 +0000 (+0200) Subject: new-driver: refactoring X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=bc02c2bf465c0ad26410596f0b8ac0a9be57ea0c;p=sigrok-util.git new-driver: refactoring - use argparse and add several cmdline options - prevent global vars - allow to be run from other directory than sigrok-util/source - use plain python .format() for templating --- diff --git a/source/drv-api.c b/source/drv-api.c index f696600..6566d62 100644 --- a/source/drv-api.c +++ b/source/drv-api.c @@ -1,7 +1,7 @@ /* * This file is part of the libsigrok project. * - * Copyright (C) ${year} ${author} <${email}> + * Copyright (C) {year} {author} <{email}> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,15 +20,15 @@ #include #include "protocol.h" -SR_PRIV struct sr_dev_driver ${lib}_driver_info; +SR_PRIV struct sr_dev_driver {lib}_driver_info; static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx) -{ +{{ return std_init(sr_ctx, di, LOG_PREFIX); -} +}} static GSList *scan(struct sr_dev_driver *di, GSList *options) -{ +{{ struct drv_context *drvc; GSList *devices; @@ -42,20 +42,20 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) * or on a USB scan. */ return devices; -} +}} static GSList *dev_list(const struct sr_dev_driver *di) -{ +{{ return ((struct drv_context *)(di->context))->instances; -} +}} static int dev_clear(const struct sr_dev_driver *di) -{ +{{ return std_dev_clear(di, NULL); -} +}} static int dev_open(struct sr_dev_inst *sdi) -{ +{{ (void)sdi; /* TODO: get handle from sdi->conn and open it. */ @@ -63,10 +63,10 @@ static int dev_open(struct sr_dev_inst *sdi) sdi->status = SR_ST_ACTIVE; return SR_OK; -} +}} static int dev_close(struct sr_dev_inst *sdi) -{ +{{ (void)sdi; /* TODO: get handle from sdi->conn and close it. */ @@ -74,20 +74,20 @@ static int dev_close(struct sr_dev_inst *sdi) sdi->status = SR_ST_INACTIVE; return SR_OK; -} +}} static int cleanup(const struct sr_dev_driver *di) -{ +{{ dev_clear(di); /* TODO: free other driver resources, if any. */ return SR_OK; -} +}} static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) -{ +{{ int ret; (void)sdi; @@ -95,18 +95,18 @@ static int config_get(uint32_t key, GVariant **data, (void)cg; ret = SR_OK; - switch (key) { + switch (key) {{ /* TODO */ default: return SR_ERR_NA; - } + }} return ret; -} +}} static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) -{ +{{ int ret; (void)data; @@ -116,18 +116,18 @@ static int config_set(uint32_t key, GVariant *data, return SR_ERR_DEV_CLOSED; ret = SR_OK; - switch (key) { + switch (key) {{ /* TODO */ default: ret = SR_ERR_NA; - } + }} return ret; -} +}} static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) -{ +{{ int ret; (void)sdi; @@ -135,17 +135,17 @@ static int config_list(uint32_t key, GVariant **data, (void)cg; ret = SR_OK; - switch (key) { + switch (key) {{ /* TODO */ default: return SR_ERR_NA; - } + }} return ret; -} +}} static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ +{{ (void)sdi; (void)cb_data; @@ -156,10 +156,10 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) * callbacks and send header packet. */ return SR_OK; -} +}} static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ +{{ (void)cb_data; if (sdi->status != SR_ST_ACTIVE) @@ -168,11 +168,11 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) /* TODO: stop acquisition. */ return SR_OK; -} +}} -SR_PRIV struct sr_dev_driver ${lib}_driver_info = { - .name = "${short}", - .longname = "${name}", +SR_PRIV struct sr_dev_driver {lib}_driver_info = {{ + .name = "{short}", + .longname = "{name}", .api_version = 1, .init = init, .cleanup = cleanup, @@ -187,6 +187,6 @@ SR_PRIV struct sr_dev_driver ${lib}_driver_info = { .dev_acquisition_start = dev_acquisition_start, .dev_acquisition_stop = dev_acquisition_stop, .context = NULL, -}; +}}; SR_REGISTER_DEV_DRIVER({lib}_driver_info); diff --git a/source/drv-protocol.c b/source/drv-protocol.c index 74f8fb8..1b300bb 100644 --- a/source/drv-protocol.c +++ b/source/drv-protocol.c @@ -1,7 +1,7 @@ /* * This file is part of the libsigrok project. * - * Copyright (C) ${year} ${author} <${email}> + * Copyright (C) {year} {author} <{email}> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +20,8 @@ #include #include "protocol.h" -SR_PRIV int ${lib}_receive_data(int fd, int revents, void *cb_data) -{ +SR_PRIV int {lib}_receive_data(int fd, int revents, void *cb_data) +{{ const struct sr_dev_inst *sdi; struct dev_context *devc; @@ -33,9 +33,9 @@ SR_PRIV int ${lib}_receive_data(int fd, int revents, void *cb_data) if (!(devc = sdi->priv)) return TRUE; - if (revents == G_IO_IN) { + if (revents == G_IO_IN) {{ /* TODO */ - } + }} return TRUE; -} +}} diff --git a/source/drv-protocol.h b/source/drv-protocol.h index f690611..30d42a5 100644 --- a/source/drv-protocol.h +++ b/source/drv-protocol.h @@ -1,7 +1,7 @@ /* * This file is part of the libsigrok project. * - * Copyright (C) ${year} ${author} <${email}> + * Copyright (C) {year} {author} <{email}> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,18 +17,18 @@ * along with this program. If not, see . */ -#ifndef LIBSIGROK_HARDWARE_${upper}_PROTOCOL_H -#define LIBSIGROK_HARDWARE_${upper}_PROTOCOL_H +#ifndef LIBSIGROK_HARDWARE_{upper}_PROTOCOL_H +#define LIBSIGROK_HARDWARE_{upper}_PROTOCOL_H #include #include #include #include "libsigrok-internal.h" -#define LOG_PREFIX "${short}" +#define LOG_PREFIX "{short}" /** Private, per-device-instance driver context. */ -struct dev_context { +struct dev_context {{ /* Model-specific information */ /* Acquisition settings */ @@ -37,8 +37,8 @@ struct dev_context { /* Temporary state across callbacks */ -}; +}}; -SR_PRIV int ${lib}_receive_data(int fd, int revents, void *cb_data); +SR_PRIV int {lib}_receive_data(int fd, int revents, void *cb_data); #endif diff --git a/source/new-driver b/source/new-driver index 33b7177..64a20c9 100755 --- a/source/new-driver +++ b/source/new-driver @@ -27,53 +27,48 @@ import re import socket import datetime -TMPL_AUTOCONF_DRIVER = "SR_DRIVER([${name}], [${short}])\n" +TMPL_AUTOCONF_DRIVER = "SR_DRIVER([{name}], [{short}])\n" -TMPL_HWMAKE_DRIVERLIB = """if HW_${upper} -libsigrok_la_SOURCES += \\ - src/hardware/${short}/protocol.h \\ - src/hardware/${short}/protocol.c \\ - src/hardware/${short}/api.c -endif -""" -FILE_DRV_API = 'drv-api.c' -FILE_DRV_PROTOCOL = 'drv-protocol.c' -FILE_DRV_PROTOCOL_H = 'drv-protocol.h' +TMPL_FILES = ('api.c', 'protocol.c', 'protocol.h') -def tmpl(template): - out = re.sub(r'\${([^}]+)}', lambda x: str(names[x.group(1)]), template) +TMPL_HWMAKE_DRIVERLIB = """if HW_{upper} +libsigrok_la_SOURCES +=""" +for tmpl_file in TMPL_FILES: + TMPL_HWMAKE_DRIVERLIB += " \\\nsrc/hardware/{short}/" + tmpl_file +TMPL_HWMAKE_DRIVERLIB += "\nendif" - return out +def tmpl(template, names): + return template.format(**names) -def tmpl_file(filename): - template = open(os.path.join(TMPLDIR, filename)).read() - return tmpl(template) +def tmpl_file(filename, tmpldir, names): + with open(os.path.join(tmpldir, filename)) as template: + return tmpl(template.read(), names) -def new_driver(): +def new_driver(srcurl, tmpldir, names): tmp = tempfile.mkdtemp() try: - os.chdir(tmp) - process = Popen(['git', 'clone', '--depth=1', LIBSR], + process = Popen(['git', 'clone', '--depth=1', srcurl, tmp], stdout=PIPE, stderr=PIPE) out, err = process.communicate() if process.returncode: raise Exception(err.decode()) - gitdir = os.path.join(tmp, 'libsigrok') - do_autoconf(gitdir) - do_automake(gitdir) - do_driverskel(gitdir) + gitdir = tmp + do_autoconf(gitdir, names) + do_automake(gitdir, names) + do_driverskel(gitdir, tmpldir, names) make_patch(gitdir) except Exception as e: + raise print(e) finally: shutil.rmtree(tmp) -# add DRIVER and DRIVER2 entries to configure.ac -def do_autoconf(gitdir): +# add DRIVER entry to configure.ac +def do_autoconf(gitdir, names): cacpath = os.path.join(gitdir, 'configure.ac') configure_ac = open(cacpath).read() @@ -87,7 +82,7 @@ def do_autoconf(gitdir): active = True if active: if (m and m.group(1).upper() > names['name'].upper()) or m is None: - out += tmpl(TMPL_AUTOCONF_DRIVER) + out += tmpl(TMPL_AUTOCONF_DRIVER, names) state = 'done' active = False out += line + '\n' @@ -97,7 +92,7 @@ def do_autoconf(gitdir): # add HW_ entry to Makefile.am -def do_automake(gitdir): +def do_automake(gitdir, names): path = os.path.join(gitdir, 'Makefile.am') hwmake = open(path).read() @@ -111,12 +106,12 @@ def do_automake(gitdir): if m: drv_short = m.group(1) if drv_short > names['upper']: - out += tmpl(TMPL_HWMAKE_DRIVERLIB) + out += tmpl(TMPL_HWMAKE_DRIVERLIB, names) state = 'done' elif not re.match(r'\s*libsigrok_la_SOURCES\b|\s*src/hardware/|endif\b', line): print("[%s]" % line.strip()) # we passed the last entry - out += tmpl(TMPL_HWMAKE_DRIVERLIB) + out += tmpl(TMPL_HWMAKE_DRIVERLIB, names) state = 'done' out += line + '\n' if state != 'done': @@ -124,30 +119,33 @@ def do_automake(gitdir): open(path, 'w').write(out) -def do_driverskel(gitdir): +def do_driverskel(gitdir, tmpldir, names): drvdir = os.path.join(gitdir, 'src', 'hardware', names['short']) os.mkdir(drvdir) - open(os.path.join(drvdir, 'api.c'), 'w').write(tmpl_file(FILE_DRV_API)) - open(os.path.join(drvdir, 'protocol.c'), 'w').write(tmpl_file(FILE_DRV_PROTOCOL)) - open(os.path.join(drvdir, 'protocol.h'), 'w').write(tmpl_file(FILE_DRV_PROTOCOL_H)) - - -def make_patch(gitdir): - os.chdir(gitdir) - command(['git', 'add', os.path.join('src', 'hardware', names['short'])]) - cmd = ['git', 'commit', - '-m', '%s: Initial driver skeleton.' % names['short'], - 'configure.ac', 'Makefile.am', - os.path.join('src', 'hardware', names['short'])] - command(cmd) - cmd = ['git', 'format-patch', 'HEAD~1'] - out, err = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate() - if err: - raise Exception(err.decode()) - patch = out.decode().strip() - shutil.move(os.path.join(gitdir, patch), - os.path.join(scriptdir, patch)) - print(patch) + for fname in TMPL_FILES: + with open(os.path.join(drvdir, fname), 'w') as outf: + outf.write(tmpl_file('drv-{0}'.format(fname), tmpldir, names)) + + +def make_patch(gitdir, names): + cwd = os.getcwd() + try: + os.chdir(gitdir) + command(['git', 'add', os.path.join('src', 'hardware', names['short'])]) + cmd = ['git', 'commit', + '-m', '%s: Initial driver skeleton.' % names['short'], + 'configure.ac', 'Makefile.am', + os.path.join('src', 'hardware', names['short'])] + command(cmd) + cmd = ['git', 'format-patch', 'HEAD~1'] + out, err = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate() + if err: + raise Exception(err.decode()) + patch = out.decode().strip() + shutil.move(os.path.join(gitdir, patch), cwd) + print("Patch {0} has been generated in {1}".format(patch, cwd)) + finally: + os.chdir(cwd) def command(cmd): @@ -157,41 +155,54 @@ def command(cmd): def parse_gitconfig(): - author = email = None try: author = check_output(["git", "config", "user.name"]).decode().strip(); + except: + author = None + try: email = check_output(["git", "config", "user.email"]).decode().strip(); except: - print("Please set your name and email in your git config") - sys.exit() + email = None return author, email + # # main # -scriptdir = os.getcwd() -if scriptdir.split('/')[-2:] != ['sigrok-util', 'source']: - print("Please call this script from the 'source' directory.") - sys.exit(1) - -LIBSR = 'git://sigrok.org/libsigrok' -TMPLDIR = scriptdir - -if len(sys.argv) < 2: - print("Usage: new-driver ") - sys.exit() - -author, email = parse_gitconfig() -name = ' '.join(sys.argv[1:]) -names = { - 'name': name, - 'short': re.sub('[^a-z0-9]', '-', name.lower()), - 'lib': re.sub('[^a-z0-9]', '_', name.lower()), - 'upper': re.sub('[^A-Z0-9]', '_', name.upper()), - 'year': datetime.datetime.now().year, - 'author': author, - 'email': email, -} -new_driver() +if __name__ == '__main__': + from argparse import ArgumentParser + + defaulturl = 'git://sigrok.org/libsigrok' + defaultdir = os.path.abspath(os.path.dirname(__file__)) + author, email = parse_gitconfig() + + parser = ArgumentParser(description='Bootstrap a new sigrok hardware driver') + parser.add_argument('name', help='new driver name') + parser.add_argument('--giturl', default=defaulturl, + help='URL of the libsigrok git repository ' + '(defaults to {0})'.format(defaulturl)) + parser.add_argument('--tmpl-dir', default=defaultdir, + help='Directory in which the templates are stored ' + '(defaults to {0})'.format(defaultdir)) + parser.add_argument('--author', default=author, required=not author, + help='User name to write the Copyright lines') + parser.add_argument('--email', default=email, required=not email, + help='Email address to write the Copyright lines') + opts = parser.parse_args() + + if not opts.author or not opts.email: + parser.error('Please provide your username and email address, ' + 'or set your git configuration up.') + name = opts.name + names = { + 'name': name, + 'short': re.sub('[^a-z0-9]', '-', name.lower()), + 'lib': re.sub('[^a-z0-9]', '_', name.lower()), + 'upper': re.sub('[^A-Z0-9]', '_', name.upper()), + 'year': datetime.datetime.now().year, + 'author': opts.author, + 'email': opts.email, + } + new_driver(opts.giturl, opts.tmpl_dir, names)