]> git.sur5r.net Git - glabels/blob - barcode-0.98/cmdline.c
Imported Upstream version 2.2.8
[glabels] / barcode-0.98 / cmdline.c
1 /*
2  * cmdline.c -- parse a command line using getopt, environment and defaults
3  *
4  * Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)
5  * Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
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 2 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, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20  *
21  *   Changes:
22  *      Michele Comitini (mcm@glisco.it): better handling of numeric type args.
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #ifdef NO_GETOPT
30   /* use replacement */
31   #include "compat/getopt.h"
32 #else
33   #include <getopt.h>
34 #endif
35
36 #include "cmdline.h"
37
38 /* In case of error, print help string and return error (-1) */
39 int commandline_errormsg(FILE *f, struct commandline *args,
40                                        char *prgname, char *messagehead)
41 {
42     char *buffer;
43     char *buffer2;
44     int len;
45     struct commandline *ptr;
46
47     if (!messagehead) {
48         fprintf(f,"%s: Error in cmdline\nPossible options:\n",prgname);
49     } else {
50         fprintf(f,"%s: %s",prgname,messagehead);
51     }
52
53     for (ptr = args; ptr->option; ptr++) {
54         if (ptr->descrip) {
55             len = strlen(ptr->descrip);
56             len +=  ptr->default_v ? strlen(ptr->default_v) : 6;
57             len += ptr->env ? strlen(ptr->env) : 6;
58             buffer2 = malloc(len+3); /* 3 to be safe :) */
59             len += 32;
60             if (buffer2) {
61                 buffer = malloc(len);
62                 if (buffer) {
63                     sprintf(buffer2, ptr->descrip,
64                             ptr->default_v ? ptr->default_v : "(none)",
65                             ptr->env ? ptr->env : "(none)");
66                     sprintf(buffer, "   -%c %s     %s", ptr->option,
67                             ptr->type ? "<arg>" : "     ", buffer2);
68                     fprintf(f, "%s\n",buffer);
69                     free(buffer);
70                 }
71                 free(buffer2);
72             }
73         }
74     }
75     return -1;
76 }
77
78 /*
79  * Associate formats to type.
80  */
81 struct type_fmt {
82     enum option_type type;
83     char *fmt;
84 };
85 static struct type_fmt formats[] = {
86     {CMDLINE_I, "%i%s"},   /* the trailing "%s" is used for error check */
87     {CMDLINE_D, "%d%s"},
88     {CMDLINE_X, "%x%s"},
89     {CMDLINE_O, "%o%s"},
90     {CMDLINE_F, "%lf%s"},
91     {CMDLINE_P, "%p%s"},
92     {0, NULL}  /* If we get here, it's CMDLINE_S: no sscanf buf strcpy() */
93 };
94
95
96 /* Parse one argument (default or provided) */
97 static int commandline_oneopt(struct commandline *ptr, char *value)
98 {
99     struct type_fmt *tptr;
100     char *trash = value ? strdup(value) : NULL;
101
102     /* convert it, if needed */
103     if ((ptr->type != CMDLINE_NONE) && ptr->result) {
104         for (tptr = formats; tptr->type; tptr++)
105             if (tptr->type == ptr->type)
106                 break;
107         if (!tptr->type) /* not found: it is a string */
108             *(char **)(ptr->result) = value;
109         else
110             if (sscanf(value, tptr->fmt, ptr->result, trash)!=1) {
111                 free(trash);
112                 return -1;
113             }
114     }
115     if (trash)
116         free(trash);
117     
118     if ((ptr->type == CMDLINE_NONE) && ptr->result) /* no type, just count */
119         (*(int *)(ptr->result))++;
120
121     /* call the function, if needed */
122     if (ptr->fun) {
123         if (ptr->type) {
124             if (ptr->result) return ptr->fun(ptr->result); /* converted */
125             return ptr->fun(value); /* type, but not converted */
126         }
127         return ptr->fun(NULL); /* no type: just call it */
128     }
129     return 0;
130 }
131
132 /* The main function */
133 int commandline(struct commandline *args, int argc, char **argv,
134                 char *errorhead)
135 {
136     struct commandline *ptr;
137     char *getopt_desc = (char *)calloc(512, 1);
138     int desc_offset = 0;
139     int opt, retval;
140     char *value;
141
142     /* Build getopt string and process defaults values */
143     for (ptr = args; ptr->option; ptr++) {
144         getopt_desc[desc_offset++] = ptr->option;
145         if (ptr->type) getopt_desc[desc_offset++] = ':';
146
147         value = NULL;
148         if (ptr->env)
149             value = getenv(ptr->env);
150         if (!value)
151             value = ptr->default_v;
152         if (value && (retval = commandline_oneopt(ptr, value))) {
153             /*
154              * if the function returns a specific (not -1) value, it already
155              * printed its message, so avoid the generic help
156              */
157             if (retval == -1)
158                 commandline_errormsg(stderr, args, argv[0], errorhead);
159             return retval;
160         }
161     }
162
163     /* Run getopt and process material */
164     while ((opt = getopt(argc, argv, getopt_desc)) != -1) {
165         for (ptr = args; ptr->option; ptr++)
166             if (opt == ptr->option)
167                 break;
168         if (!ptr->option) /* unknown option */
169             return commandline_errormsg(stderr, args, argv[0], errorhead);
170         if ( (retval = commandline_oneopt(ptr, optarg)) ) { /*  wrong arg */
171             if (retval == -1)
172                 commandline_errormsg(stderr, args, argv[0], errorhead);
173             return retval;
174         }
175     }
176     return 0;
177 }