1/*
2 * Generic Options Support Header File
3 *
4 * Copyright (c) 2001  Stanislav Karchebny <berk@madfire.net>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the names of other contributors
15 *    may be used to endorse or promote products derived from this
16 *    software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30#include <util.h>
31#include <ctype.h>
32
33#include "yasm-options.h"
34
35
36#ifdef __DEBUG__
37#define DEBUG(x) fprintf ## x ;
38#else
39#define DEBUG(x)
40#endif
41
42
43/* Options Parser */
44int
45parse_cmdline(int argc, char **argv, opt_option *options, size_t nopts,
46              void (*print_error) (const char *fmt, ...))
47{
48    int errors = 0, warnings = 0;
49    size_t i;
50    int got_it;
51
52    DEBUG((stderr, "parse_cmdline: entered\n"));
53
54  fail:
55    while (--argc) {
56        argv++;
57
58        if (argv[0][0] == '-') {        /* opt */
59            got_it = 0;
60            if (argv[0][1] == '-') {    /* lopt */
61                if (argv[0][2] == '\0') {   /* --, end of options */
62                    /* Handle rest of args as non-options */
63                    while (--argc) {
64                        argv++;
65                        if (not_an_option_handler(argv[0]))
66                            errors++;
67                    }
68                    return errors;
69                }
70
71                for (i = 0; i < nopts; i++) {
72                    size_t optlen;
73                    if (options[i].lopt &&
74                        strncmp(&argv[0][2], options[i].lopt,
75                                (optlen = strlen(options[i].lopt))) == 0) {
76                        char *param;
77                        char c = argv[0][2 + optlen];
78
79                        if (c != '\0' && c != '=' && !isspace(c))
80                            continue;
81
82                        if (options[i].takes_param) {
83                            param = strchr(&argv[0][2], '=');
84                            if (!param) {
85                                print_error(
86                                    _("option `--%s' needs an argument!"),
87                                    options[i].lopt);
88                                errors++;
89                                goto fail;
90                            } else {
91                                *param = '\0';
92                                param++;
93                            }
94                        } else
95                            param = NULL;
96
97                        if (!options[i].
98                            handler(&argv[0][2], param, options[i].extra))
99                            got_it = 1;
100                        break;
101                    }
102                }
103                if (!got_it && !other_option_handler(argv[0]))
104                    got_it = 1;
105                if (!got_it) {
106                    print_error(_("warning: unrecognized option `%s'"),
107                                argv[0]);
108                    warnings++;
109                }
110            } else if (argv[0][1] == '\0') {   /* just -, is non-option */
111                if (not_an_option_handler(argv[0]))
112                    errors++;
113            } else {            /* sopt */
114                for (i = 0; i < nopts; i++) {
115                    if (argv[0][1] == options[i].sopt) {
116                        char *cmd = &argv[0][1];
117                        char *param;
118
119                        if (options[i].takes_param) {
120                            param = argv[1];
121                            if (argv[0][2] != '\0')
122                                param = &argv[0][2];
123                            else if (param == NULL || *param == '-') {
124                                print_error(
125                                    _("option `-%c' needs an argument!"),
126                                    options[i].sopt);
127                                errors++;
128                                goto fail;
129                            } else {
130                                argc--;
131                                argv++;
132                            }
133                        } else
134                            param = NULL;
135
136                        if (!options[i].handler(cmd, param, options[i].extra))
137                            got_it = 1;
138                        break;
139                    }
140                }
141                if (!got_it && !other_option_handler(argv[0]))
142                    got_it = 1;
143                if (!got_it) {
144                    print_error(_("warning: unrecognized option `%s'"),
145                                argv[0]);
146                    warnings++;
147                }
148            }
149        } else {    /* not an option, then it should be a file or something */
150
151            if (not_an_option_handler(argv[0]))
152                errors++;
153        }
154    }
155
156    DEBUG((stderr, "parse_cmdline: finished\n"));
157    return errors;
158}
159
160void
161help_msg(const char *msg, const char *tail, opt_option *options, size_t nopts)
162{
163    char optbuf[100], optopt[100];
164    size_t i;
165
166    printf("%s", gettext(msg));
167
168    for (i = 0; i < nopts; i++) {
169        size_t shortopt_len = 0;
170        size_t longopt_len = 0;
171
172        optbuf[0] = 0;
173        optopt[0] = 0;
174
175        if (options[i].takes_param) {
176            if (options[i].sopt) {
177                sprintf(optbuf, "-%c <%s>", options[i].sopt,
178                        options[i].param_desc ? options[i].
179                        param_desc : _("param"));
180                shortopt_len = strlen(optbuf);
181            }
182            if (options[i].sopt && options[i].lopt)
183                strcat(optbuf, ", ");
184            if (options[i].lopt) {
185                sprintf(optopt, "--%s=<%s>", options[i].lopt,
186                        options[i].param_desc ? options[i].
187                        param_desc : _("param"));
188                strcat(optbuf, optopt);
189                longopt_len = strlen(optbuf);
190            }
191        } else {
192            if (options[i].sopt) {
193                sprintf(optbuf, "-%c", options[i].sopt);
194                shortopt_len = strlen(optbuf);
195            }
196            if (options[i].sopt && options[i].lopt)
197                strcat(optbuf, ", ");
198            if (options[i].lopt) {
199                sprintf(optopt, "--%s", options[i].lopt);
200                strcat(optbuf, optopt);
201                longopt_len = strlen(optbuf);
202            }
203        }
204
205        /* split [-s <desc>], [--long <desc>] if it destroys columns */
206        if (shortopt_len && longopt_len && longopt_len > 22) {
207            optbuf[shortopt_len] = '\0';
208            printf("    %-22s  %s\n", optopt, gettext(options[i].description));
209            printf("     %s\n", optbuf);
210        }
211        else
212            printf("    %-22s  %s\n", optbuf, gettext(options[i].description));
213    }
214
215    printf("%s", gettext(tail));
216}
217