modified: diffout.py
[GalaxyCodeBases.git] / c_cpp / lib / Galaxy / argp.h
blobe4bfdd46c4108684015e7bfe7a36d88cee13cae3
1 /*
2 * file: argp.h
3 * description: minimal replacement for GNU Argp library
4 * Copyright 2011 Peter Desnoyers, Northeastern University
6 * This file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * <http://pjd-notes.blogspot.jp/2011/06/gnu-argp-for-osx.html>
12 GNU Argp for OSX
14 After using optparse in Python, I've become spoiled and never want to go back to getopt/getopt_long for C code. The only package I've found for C that handles both options and help strings in a reasonable fashion seems to be GNU Argp, but it's non-standard and works on my Linux machines but not my Mac. A quick try at pulling Argp from the glibc source and porting to the Mac was leading to more work than I wanted, so the solution was this quick-and-dirty replacement.
16 And yes, it commits the cardinal sin of including code in a header file, but it works fine if you're only including it from main.c, and keeps your source compatible between systems. (just put it in the local directory, add "-I ." to your compile flags, and you're done.)
18 #ifndef __ARGP_H__
20 #include <getopt.h>
21 #include <string.h>
23 /* This only includes the features I've used in my programs to date;
24 * in particular, it totally ignores any sort of flag.
27 #ifndef __error_t_defined
28 typedef int error_t;
29 # define __error_t_defined
30 #endif
32 struct argp_option {
33 char *name;
34 char key;
35 char *arg;
36 int flags;
37 char *doc;
38 int group; /* ignored */
41 struct argp_state {
42 void *input;
43 char *name;
44 struct argp *argp;
45 int maxlen;
48 struct argp {
49 struct argp_option *options;
50 error_t (*parser)(int key, char *arg, struct argp_state *state);
51 char *arg_doc;
52 char *prog_doc;
55 void argp_help(struct argp_state *state)
57 printf("Usage: %s [OPTIONS...] %s\n%s\n\n",
58 state->name, state->argp->arg_doc, state->argp->prog_doc);
60 struct argp_option *o = state->argp->options;
61 int i;
63 for (i = 0; o[i].name != NULL; i++) {
64 char tmp[80], *p = tmp;
65 p += sprintf(tmp, "--%s", o[i].name);
66 if (o[i].arg)
67 sprintf(p, "=%s", o[i].arg);
68 printf(" %-*s%s\n", state->maxlen + 8, tmp, o[i].doc);
70 printf(" --%-*s%s\n", state->maxlen+6, "help", "Give this help list");
71 printf(" --%-*s%s\n", state->maxlen+6, "usage",
72 "Give a short usage message");
74 exit(1);
77 void argp_usage(struct argp_state *state)
79 char buf[1024], *p = buf, *col0 = buf;
80 p += sprintf(p, "Usage: %s", state->name);
81 int i, indent = p-buf;
82 struct argp_option *o = state->argp->options;
84 for (i = 0; o[i].name != NULL; i++) {
85 p += sprintf(p, " [--%s%s%s]", o[i].name, o[i].arg ? "=":"",
86 o[i].arg ? o[i].arg : "");
87 if (p-col0 > (78-state->maxlen)) {
88 p += sprintf(p, "\n");
89 col0 = p;
90 p += sprintf(p, "%*s", indent, "");
93 sprintf(p, " %s\n", state->argp->arg_doc);
94 printf("%s", buf);
95 exit(0);
98 char *cleanarg(char *s)
100 char *v = strrchr(s, '/');
101 return v ? v+1 : s;
104 enum {ARGP_KEY_ARG, ARGP_KEY_END, ARGP_ERR_UNKNOWN, ARGP_IN_ORDER};
106 void argp_parse(struct argp *argp, int argc, char **argv, int flags, int tmp,
107 void *input)
109 int n_opts, c;
110 struct argp_state state = {.name = cleanarg(argv[0]),
111 .input = input, .argp = argp};
113 /* calculate max "--opt=var" length */
114 int i, max = 0;
115 struct argp_option *opt = argp->options;
116 for (i = 0; opt[i].name != NULL; i++) {
117 int m = strlen(opt[i].name) +
118 (opt[i].arg ? 1+strlen(opt[i].arg) : 0);
119 max = (max < m) ? m : max;
121 state.maxlen = max+2;
122 n_opts = i;
124 struct option *long_opts = calloc((n_opts+3) * sizeof(*long_opts), 1);
126 i = 0;
127 long_opts[i].name = "usage";
128 long_opts[i++].has_arg = no_argument;
130 long_opts[i].name = "help";
131 long_opts[i++].has_arg = no_argument;
133 for (opt = argp->options; opt->name != NULL; opt++, i++) {
134 int has_arg = opt->arg != NULL;
135 long_opts[i].name = opt->name;
136 long_opts[i].has_arg = has_arg ? required_argument : no_argument;
139 /* we only accept long arguments - return value is zero, and 'i'
140 * gives us the index into 'long_opts[]'
142 while ((c = getopt_long(argc, argv, "", long_opts, &i)) != -1) {
143 if (i == 0)
144 argp_usage(&state);
145 else if (i == 1)
146 argp_help(&state);
147 else
148 argp->parser(argp->options[i-2].key, optarg, &state);
151 while (optind < argc)
152 argp->parser(ARGP_KEY_ARG, argv[optind++], &state);
153 argp->parser(ARGP_KEY_END, NULL, &state);
155 free(long_opts);
158 #endif /* __ARGP_H__ */