1/*
2 * Description.
3 *
4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
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 * $Id: miniopt.c 419467 2013-08-21 09:19:48Z $
18 */
19
20/* ---- Include Files ---------------------------------------------------- */
21
22#include <typedefs.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <miniopt.h>
27
28
29/* ---- Public Variables ------------------------------------------------- */
30/* ---- Private Constants and Types -------------------------------------- */
31
32#if	defined(_CFE_)
33	#define fprintf(stream, fmt, args...) xprintf(fmt , ## args)
34#endif
35
36
37/* ---- Private Variables ------------------------------------------------ */
38/* ---- Private Function Prototypes -------------------------------------- */
39/* ---- Functions -------------------------------------------------------- */
40
41/* ----------------------------------------------------------------------- */
42void
43miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags)
44{
45	static const char *null_flags = "";
46
47	memset(t, 0, sizeof(miniopt_t));
48	t->name = name;
49	if (flags == NULL)
50		t->flags = null_flags;
51	else
52		t->flags = flags;
53	t->longflags = longflags;
54}
55
56
57/* ----------------------------------------------------------------------- */
58int
59miniopt(miniopt_t *t, char **argv)
60{
61	int keylen;
62	char *p, *eq, *valstr, *endptr = NULL;
63	int err = 0;
64
65	t->consumed = 0;
66	t->positional = FALSE;
67	memset(t->key, 0, MINIOPT_MAXKEY);
68	t->opt = '\0';
69	t->valstr = NULL;
70	t->good_int = FALSE;
71	valstr = NULL;
72
73	if (*argv == NULL) {
74		err = -1;
75		goto exit;
76	}
77
78	p = *argv++;
79	t->consumed++;
80
81	if (!t->opt_end && !strcmp(p, "--")) {
82		t->opt_end = TRUE;
83		if (*argv == NULL) {
84			err = -1;
85			goto exit;
86		}
87		p = *argv++;
88		t->consumed++;
89	}
90
91	if (t->opt_end) {
92		t->positional = TRUE;
93		valstr = p;
94	}
95	else if (!strncmp(p, "--", 2)) {
96		eq = strchr(p, '=');
97		if (eq == NULL && !t->longflags) {
98			fprintf(stderr,
99				"%s: missing \" = \" in long param \"%s\"\n", t->name, p);
100			err = 1;
101			goto exit;
102		}
103		keylen = eq ? (eq - (p + 2)) : (int)strlen(p) - 2;
104		if (keylen > 63) keylen = 63;
105		memcpy(t->key, p + 2, keylen);
106
107		if (eq) {
108			valstr = eq + 1;
109			if (*valstr == '\0') {
110				fprintf(stderr,
111				        "%s: missing value after \" = \" in long param \"%s\"\n",
112				        t->name, p);
113				err = 1;
114				goto exit;
115			}
116		}
117	}
118	else if (!strncmp(p, "-", 1)) {
119		t->opt = p[1];
120		if (strlen(p) > 2) {
121			fprintf(stderr,
122				"%s: only single char options, error on param \"%s\"\n",
123				t->name, p);
124			err = 1;
125			goto exit;
126		}
127		if (strchr(t->flags, t->opt)) {
128			/* this is a flag option, no value expected */
129			valstr = NULL;
130		} else {
131			if (*argv == NULL) {
132				fprintf(stderr,
133				"%s: missing value parameter after \"%s\"\n", t->name, p);
134				err = 1;
135				goto exit;
136			}
137			valstr = *argv;
138			argv++;
139			t->consumed++;
140		}
141	} else {
142		t->positional = TRUE;
143		valstr = p;
144	}
145
146	/* parse valstr as int just in case */
147	if (valstr) {
148		t->uval = (uint)strtoul(valstr, &endptr, 0);
149		t->val = (int)t->uval;
150		t->good_int = (*endptr == '\0');
151	}
152
153	t->valstr = valstr;
154
155exit:
156	if (err == 1)
157		t->opt = '?';
158
159	return err;
160}
161