all: Eliminate the multi-stage cmdline parsing.

Unfortunately this means we lose the '-B backend' method, but the
overall control flow is much, much simpler now.
master
Solomon Peachy 2015-08-13 21:09:56 -04:00
parent 0e91abe75d
commit db0c7d8b99
16 changed files with 172 additions and 140 deletions

18
README
View File

@ -116,10 +116,9 @@
When compiled, a set of symlinks are created, corresponding to each
of the internal backends. Alternatively you may set the BACKEND
environment variable to force a specific backend to be used. These
commands are all equivalent:
commands are equivalent:
BACKEND=backend gutenprint52+usb [ arguments ]
gutenprint52+usb -B backend [ arguments ]
backend [ arguments ]
All backends support the following invocations:
@ -138,11 +137,10 @@
-D Increment debug level [1]
-G Display GPL text
-f Enable fast return mode if possible [2]
-B name Use Backend 'name' [3]
-S serno Use SerialNum 'serno' [4]
-V extra_vid [5]
-P extra_pid [5]
-T extra_type [5]
-S serno Use SerialNum 'serno' [3]
-V extra_vid [4]
-P extra_pid [4]
-T extra_type [4]
-d numcopies Print 'numcopies' of the supplied job
[1] This argument can be repeated to increase the debug level.
@ -156,9 +154,7 @@
when using this backend with CUPS. Not all backends support
fast return.
[3] Alternatively, you can use the 'BACKEND' environment variable.
[4] If you have multiple models of the same printer family connected
[3] If you have multiple models of the same printer family connected
simultaneously, the backend will choose the first one it finds.
If you wish to target a specific device, you may specify its
serial number with this switch, or using the 'SERIAL' environment
@ -167,7 +163,7 @@
SERIAL=N782 backend filename [ arguments ]
backend -S N782 filename [ arguments ]
[5] All backends support an additional operational mode, to test out
[4] All backends support an additional operational mode, to test out
unknown models. To use this mode, specify the VID, PID and its
internal device type as arguments or environment variables:

View File

@ -35,6 +35,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND canonselphy_backend
#include "backend_common.h"
#define P_ES40_CP790 (P_END + 1) // used for detection only
@ -951,10 +953,32 @@ top:
return CUPS_BACKEND_OK;
}
static int canonselphy_cmdline_arg(void *vctx, int argc, char **argv)
{
// struct canonselphy_ctx *ctx = vctx;
int i, j = 0;
UNUSED(vctx);
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL)) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
}
if (j) return j;
}
return 0;
}
struct dyesub_backend canonselphy_backend = {
.name = "Canon SELPHY CP/ES",
.version = "0.88",
.uri_prefix = "canonselphy",
.cmdline_arg = canonselphy_cmdline_arg,
.init = canonselphy_init,
.attach = canonselphy_attach,
.teardown = canonselphy_teardown,

View File

@ -35,6 +35,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND cw01_backend
#include "backend_common.h"
#define USB_VID_CITIZEN 0x1343
@ -293,8 +295,6 @@ static void *cw01_init(void)
return ctx;
}
extern struct dyesub_backend cw01_backend;
static void cw01_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
@ -836,8 +836,9 @@ static int cw01_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "inN:s")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "inN:s")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'i':
if (ctx) {
j = cw01_get_info(ctx);

View File

@ -27,7 +27,7 @@
#include "backend_common.h"
#define BACKEND_VERSION "0.59"
#define BACKEND_VERSION "0.60"
#ifndef URI_PREFIX
#error "Must Define URI_PREFIX"
#endif
@ -41,6 +41,8 @@ int fast_return = 0;
int extra_vid = -1;
int extra_pid = -1;
int extra_type = -1;
int copies = 1;
char *use_serno = NULL;
/* Support Functions */
static int backend_claim_interface(struct libusb_device_handle *dev, int iface)
@ -648,7 +650,7 @@ static struct dyesub_backend *find_backend(char *uri_prefix)
return NULL;
}
static void print_license_blurb(void)
void print_license_blurb(void)
{
const char *license = "\n\
Copyright 2007-2015 Solomon Peachy <pizza AT shaftnet DOT org>\n\
@ -671,7 +673,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\
fprintf(stderr, "%s", license);
}
static void print_help(char *argv0, struct dyesub_backend *backend)
void print_help(char *argv0, struct dyesub_backend *backend)
{
struct libusb_context *ctx = NULL;
struct libusb_device **list = NULL;
@ -696,7 +698,7 @@ static void print_help(char *argv0, struct dyesub_backend *backend)
DEBUG("Standalone Usage:\n");
DEBUG("\t%s\n", URI_PREFIX);
DEBUG(" [ -D ] [ -G ] [ -f ]\n");
DEBUG(" [ -S serialnum ] [ -B backendname ] \n");
DEBUG(" [ -S serialnum ] \n");
DEBUG(" [ -V extra_vid ] [ -P extra_pid ] [ -T extra_type ] \n");
DEBUG(" [ backend_specific_args ] \n");
DEBUG(" [ -d copies ] \n");
@ -705,7 +707,7 @@ static void print_help(char *argv0, struct dyesub_backend *backend)
backend = backends[i];
if (!backend)
break;
DEBUG(" -B %s\t# %s version %s\n",
DEBUG(" BACKEND=%s\t# %s version %s\n",
backend->uri_prefix, backend->name, backend->version);
if (backend->cmdline_usage)
backend->cmdline_usage();
@ -721,6 +723,7 @@ static void print_help(char *argv0, struct dyesub_backend *backend)
DEBUG("\t[ -d copies ] [ infile | - ]\n");
}
/* Probe for printers */
i = libusb_init(&ctx);
if (i) {
ERROR("Failed to initialize libusb (%d)\n", i);
@ -748,20 +751,16 @@ int main (int argc, char **argv)
int i;
int claimed;
int backend_cmd = 0;
int ret = CUPS_BACKEND_OK;
int iface = 0;
int found = -1;
int copies = 1;
int jobid = 0;
int pages = 0;
char *uri;
char *fname = NULL;
char *use_serno = NULL;
DEBUG("Multi-Call Dye-sublimation CUPS Backend version %s\n",
BACKEND_VERSION);
DEBUG("Copyright 2007-2015 Solomon Peachy\n");
@ -848,75 +847,7 @@ int main (int argc, char **argv)
ptr = argv[0];
backend = find_backend(ptr);
}
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "B:d:DfGhP:S:T:V:")) >= 0) {
switch(i) {
case 'B':
backend = find_backend(optarg);
if (!backend) {
fprintf(stderr, "ERROR: Unknown backend '%s'\n", optarg);
exit(1);
}
break;
case 'd':
copies = atoi(optarg);
break;
case 'D':
dyesub_debug++;
break;
case 'f':
fast_return++;
break;
case 'G':
print_license_blurb();
exit(0);
case 'h':
print_help(argv[0], backend);
exit(0);
case 'P':
extra_pid = strtol(optarg, NULL, 16);
break;
case 'S':
use_serno = optarg;
break;
case 'T':
extra_type = atoi(optarg);
break;
case 'V':
extra_pid = strtol(optarg, NULL, 16);
break;
default: {
/* Check to see if it is claimed by the backend */
if (backend && backend->cmdline_arg) {
int keep = optind;
int boo;
boo = backend->cmdline_arg(NULL, argc, argv);
backend_cmd += boo;
if (boo > 1)
keep++;
optind = keep;
}
break;
}
}
}
/* Make sure a filename was specified */
if (optind >= argc || !argv[optind]) {
if (!backend_cmd) {
print_help(argv[0], backend);
exit(0);
}
}
/* Grab the filename */
fname = argv[optind]; // XXX
srand(getpid());
jobid = rand();
}
@ -930,12 +861,6 @@ int main (int argc, char **argv)
}
#endif
/* Make sure we have a sane backend */
if (!backend) {
fprintf(stderr, "ERROR: Unknown backend\n");
exit(1);
}
/* Libusb setup */
ret = libusb_init(&ctx);
if (ret) {
@ -944,16 +869,30 @@ int main (int argc, char **argv)
goto done;
}
/* If we don't have a valid backend, print help and terminate */
if (!backend) {
print_help(argv[0], NULL); // probes all devices
exit(1);
}
/* If we're in standalone mode, print help only if no args */
if (!uri) {
if (argc < 2) {
print_help(argv[0], backend); // probes all devices
exit(1);
}
}
/* Enumerate devices */
found = find_and_enumerate(ctx, &list, backend, use_serno, 0);
#if 1
if (found == -1) {
ERROR("Printer open failure (No matching printers found!)\n");
ret = CUPS_BACKEND_HOLD;
goto done;
}
/* Open an appropriate device */
ret = libusb_open(list[found], &dev);
if (ret) {
ERROR("Printer open failure (Need to be root?) (%d)\n", ret);
@ -992,7 +931,6 @@ int main (int argc, char **argv)
endp_down = config->interface[0].altsetting[0].endpoint[i].bEndpointAddress;
}
}
#endif
/* Initialize backend */
DEBUG("Initializing '%s' backend (version %s)\n",
@ -1002,16 +940,18 @@ int main (int argc, char **argv)
/* Attach backend to device */
backend->attach(backend_ctx, dev, endp_up, endp_down, jobid);
if (backend_cmd && !uri) {
if (backend->cmdline_arg(backend_ctx, argc, argv))
goto done_claimed;
if (!fname)
if (!uri) {
if (backend->cmdline_arg(backend_ctx, argc, argv) < 0)
goto done_claimed;
/* Grab the filename */
fname = argv[optind]; // XXX do this a smarter way?
}
if (!fname) {
fprintf(stderr, "ERROR: No input file specified\n");
exit(1);
if (uri)
fprintf(stderr, "ERROR: No input file specified\n");
goto done_claimed;
}
/* Open file if not STDIN */

View File

@ -148,6 +148,9 @@ int read_data(struct libusb_device_handle *dev, uint8_t endp,
uint8_t *buf, int buflen, int *readlen);
int lookup_printer_type(struct dyesub_backend *backend, uint16_t idVendor, uint16_t idProduct);
void print_license_blurb(void);
void print_help(char *argv0, struct dyesub_backend *backend);
/* Global data */
extern int terminate;
extern int dyesub_debug;
@ -155,6 +158,12 @@ extern int fast_return;
extern int extra_vid;
extern int extra_pid;
extern int extra_type;
extern int copies;
extern char *use_serno;
#if defined(BACKEND)
extern struct dyesub_backend BACKEND;
#endif
/* CUPS compatibility */
#define CUPS_BACKEND_OK 0 /* Sucess */
@ -166,4 +175,35 @@ extern int extra_type;
#define CUPS_BACKEND_RETRY 6 /* Retry later */
#define CUPS_BACKEND_RETRY_CURRENT 7 /* Retry immediately */
/* Argument processing */
#define GETOPT_LIST_GLOBAL "d:DfGhP:S:T:V:"
#define GETOPT_PROCESS_GLOBAL \
case 'd': \
copies = atoi(optarg); \
break; \
case 'D': \
dyesub_debug++; \
break; \
case 'f': \
fast_return++; \
break; \
case 'G': \
print_license_blurb(); \
exit(0); \
case 'h': \
print_help(argv[0], &BACKEND); \
exit(0); \
case 'P': \
extra_pid = strtol(optarg, NULL, 16); \
break; \
case 'S': \
use_serno = optarg; \
break; \
case 'T': \
extra_type = atoi(optarg); \
break; \
case 'V': \
extra_pid = strtol(optarg, NULL, 16); \
break;
#endif /* __BACKEND_COMMON_H */

View File

@ -44,6 +44,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND dnpds40_backend
#include "backend_common.h"
#define USB_VID_CITIZEN 0x1343
@ -315,8 +317,6 @@ static void *dnpds40_init(void)
((ctx->ver_major > (__major)) || \
(ctx->ver_major == (__major) && ctx->ver_minor >= (__minor)))
extern struct dyesub_backend dnpds40_backend;
static void dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
@ -1573,8 +1573,9 @@ static int dnpds40_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "iInN:p:sK:k:")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "iInN:p:sK:k:")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'i':
if (ctx) {
j = dnpds40_get_info(ctx);

View File

@ -35,6 +35,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND kodak1400_backend
#include "backend_common.h"
/* Program states */
@ -262,8 +264,9 @@ int kodak1400_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "C:")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "C:")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'C':
if (ctx) {
j = kodak1400_set_tonecurve(ctx, optarg);
@ -292,8 +295,6 @@ static void *kodak1400_init(void)
return ctx;
}
extern struct dyesub_backend kodak1400_backend;
static void kodak1400_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{

View File

@ -35,6 +35,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND kodak605_backend
#include "backend_common.h"
#define USB_VID_KODAK 0x040A
@ -105,8 +107,6 @@ static void *kodak605_init(void)
return ctx;
}
extern struct dyesub_backend kodak605_backend;
static void kodak605_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
@ -515,8 +515,9 @@ static int kodak605_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "C:ms")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "C:ms")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'C':
if (ctx) {
j = kodak605_set_tonecurve(ctx, optarg);

View File

@ -39,6 +39,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND kodak6800_backend
#include "backend_common.h"
#define USB_VID_KODAK 0x040A
@ -585,8 +587,9 @@ static int kodak6800_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "C:c:ms")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "C:c:ms")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'c':
if (ctx) {
j = kodak6800_get_tonecurve(ctx, optarg);
@ -651,8 +654,6 @@ static void *kodak6800_init(void)
return ctx;
}
extern struct dyesub_backend kodak6800_backend;
static void kodak6800_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{

View File

@ -35,6 +35,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND mitsu70x_backend
#include "backend_common.h"
#define USB_VID_MITSU 0x06D3
@ -138,8 +140,6 @@ static void *mitsu70x_init(void)
return ctx;
}
extern struct dyesub_backend mitsu70x_backend;
static void mitsu70x_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
@ -571,8 +571,9 @@ static int mitsu70x_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "s")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "s")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 's':
if (ctx) {
j = mitsu70x_query_status(ctx);

View File

@ -35,6 +35,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND mitsu9550_backend
#include "backend_common.h"
#define USB_VID_MITSU 0x06D3
@ -151,8 +153,6 @@ static void *mitsu9550_init(void)
return ctx;
}
extern struct dyesub_backend mitsu9550_backend;
static void mitsu9550_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
@ -751,9 +751,10 @@ static int mitsu9550_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "ms")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "ms")) >= 0) {
switch(i) {
case 'm':
GETOPT_PROCESS_GLOBAL
case 'm':
if (ctx) {
j = mitsu9550_query_media(ctx);
break;

View File

@ -37,6 +37,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND shinkos1245_backend
#include "backend_common.h"
/* Structure of printjob header. All fields are LITTLE ENDIAN */
@ -1161,8 +1163,9 @@ int shinkos1245_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "c:C:l:L:FmsuU:X:")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:l:L:FmsuU:X:")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'F':
if (ctx) {
ctx->tonecurve = PARAM_TABLE_FINE;
@ -1259,8 +1262,6 @@ static void *shinkos1245_init(void)
return ctx;
}
extern struct dyesub_backend shinkos1245_backend;
static void shinkos1245_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{

View File

@ -39,8 +39,9 @@
#include <fcntl.h>
#include <signal.h>
#include "backend_common.h"
#define BACKEND shinkos2145_backend
#include "backend_common.h"
enum {
S_IDLE = 0,
@ -1295,8 +1296,9 @@ int shinkos2145_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "b:c:C:eFil:L:mr:R:suU:X:")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "b:c:C:eFil:L:mr:R:suU:X:")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'b':
if (ctx) {
if (optarg[0] == '1')
@ -1416,8 +1418,6 @@ static void *shinkos2145_init(void)
return ctx;
}
extern struct dyesub_backend shinkos2145_backend;
static void shinkos2145_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{

View File

@ -38,6 +38,8 @@
#include <signal.h>
#include <time.h>
#define BACKEND shinkos6145_backend
#include "backend_common.h"
//#define WITH_6145_LIB
@ -1383,8 +1385,9 @@ int shinkos6145_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "c:C:eFik:l:L:mr:R:sX:")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:eFik:l:L:mr:R:sX:")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'c':
if (ctx) {
j = get_tonecurve(ctx, TONECURVE_USER, optarg);
@ -1500,8 +1503,6 @@ static void *shinkos6145_init(void)
return ctx;
}
extern struct dyesub_backend shinkos6145_backend;
static void shinkos6145_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{

View File

@ -38,6 +38,8 @@
#include <signal.h>
#include <time.h>
#define BACKEND shinkos6245_backend
#include "backend_common.h"
@ -1377,8 +1379,9 @@ int shinkos6245_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "c:C:eFik:l:L:mr:R:sX:")) >= 0) {
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:eFik:l:L:mr:R:sX:")) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
case 'c':
if (ctx) {
j = get_tonecurve(ctx, TONECURVE_USER, optarg);
@ -1494,8 +1497,6 @@ static void *shinkos6245_init(void)
return ctx;
}
extern struct dyesub_backend shinkos6245_backend;
static void shinkos6245_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{

View File

@ -35,6 +35,8 @@
#include <fcntl.h>
#include <signal.h>
#define BACKEND updr150_backend
#include "backend_common.h"
/* Exported */
@ -67,8 +69,6 @@ static void* updr150_init(void)
return ctx;
}
extern struct dyesub_backend updr150_backend;
static void updr150_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
@ -255,10 +255,32 @@ top:
return CUPS_BACKEND_OK;
}
static int updr150_cmdline_arg(void *vctx, int argc, char **argv)
{
// struct updr150_ctx *ctx = vctx;
int i, j = 0;
UNUSED(vctx);
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL)) >= 0) {
switch(i) {
GETOPT_PROCESS_GLOBAL
}
if (j) return j;
}
return 0;
}
struct dyesub_backend updr150_backend = {
.name = "Sony UP-DR150/UP-DR200/UP-CR10",
.version = "0.17",
.uri_prefix = "sonyupdr150",
.cmdline_arg = updr150_cmdline_arg,
.init = updr150_init,
.attach = updr150_attach,
.teardown = updr150_teardown,