1/*
2 * Description.
3 *
4 * Copyright (C) 1999-2013, Broadcom Corporation
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id: miniopt.c 310902 2012-01-26 19:45:33Z $
19 */
20
21/* ---- Include Files ---------------------------------------------------- */
22
23#include <typedefs.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <miniopt.h>
28
29
30/* ---- Public Variables ------------------------------------------------- */
31/* ---- Private Constants and Types -------------------------------------- */
32
33
34
35/* ---- Private Variables ------------------------------------------------ */
36/* ---- Private Function Prototypes -------------------------------------- */
37/* ---- Functions -------------------------------------------------------- */
38
39/* ----------------------------------------------------------------------- */
40void
41miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags)
42{
43	static const char *null_flags = "";
44
45	memset(t, 0, sizeof(miniopt_t));
46	t->name = name;
47	if (flags == NULL)
48		t->flags = null_flags;
49	else
50		t->flags = flags;
51	t->longflags = longflags;
52}
53
54
55/* ----------------------------------------------------------------------- */
56int
57miniopt(miniopt_t *t, char **argv)
58{
59	int keylen;
60	char *p, *eq, *valstr, *endptr = NULL;
61	int err = 0;
62
63	t->consumed = 0;
64	t->positional = FALSE;
65	memset(t->key, 0, MINIOPT_MAXKEY);
66	t->opt = '\0';
67	t->valstr = NULL;
68	t->good_int = FALSE;
69	valstr = NULL;
70
71	if (*argv == NULL) {
72		err = -1;
73		goto exit;
74	}
75
76	p = *argv++;
77	t->consumed++;
78
79	if (!t->opt_end && !strcmp(p, "--")) {
80		t->opt_end = TRUE;
81		if (*argv == NULL) {
82			err = -1;
83			goto exit;
84		}
85		p = *argv++;
86		t->consumed++;
87	}
88
89	if (t->opt_end) {
90		t->positional = TRUE;
91		valstr = p;
92	}
93	else if (!strncmp(p, "--", 2)) {
94		eq = strchr(p, '=');
95		if (eq == NULL && !t->longflags) {
96			fprintf(stderr,
97				"%s: missing \" = \" in long param \"%s\"\n", t->name, p);
98			err = 1;
99			goto exit;
100		}
101		keylen = eq ? (eq - (p + 2)) : (int)strlen(p) - 2;
102		if (keylen > 63) keylen = 63;
103		memcpy(t->key, p + 2, keylen);
104
105		if (eq) {
106			valstr = eq + 1;
107			if (*valstr == '\0') {
108				fprintf(stderr,
109				        "%s: missing value after \" = \" in long param \"%s\"\n",
110				        t->name, p);
111				err = 1;
112				goto exit;
113			}
114		}
115	}
116	else if (!strncmp(p, "-", 1)) {
117		t->opt = p[1];
118		if (strlen(p) > 2) {
119			fprintf(stderr,
120				"%s: only single char options, error on param \"%s\"\n",
121				t->name, p);
122			err = 1;
123			goto exit;
124		}
125		if (strchr(t->flags, t->opt)) {
126			/* this is a flag option, no value expected */
127			valstr = NULL;
128		} else {
129			if (*argv == NULL) {
130				fprintf(stderr,
131				"%s: missing value parameter after \"%s\"\n", t->name, p);
132				err = 1;
133				goto exit;
134			}
135			valstr = *argv;
136			argv++;
137			t->consumed++;
138		}
139	} else {
140		t->positional = TRUE;
141		valstr = p;
142	}
143
144	/* parse valstr as int just in case */
145	if (valstr) {
146		t->uval = (uint)strtoul(valstr, &endptr, 0);
147		t->val = (int)t->uval;
148		t->good_int = (*endptr == '\0');
149	}
150
151	t->valstr = valstr;
152
153exit:
154	if (err == 1)
155		t->opt = '?';
156
157	return err;
158}
159