etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / roken / parse_units.c
blobc412544331cd74266ad3a53cce44181635ec9f50
1 /* $NetBSD: parse_units.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */
3 /*
4 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include <config.h>
38 #include <stdio.h>
39 #include <ctype.h>
40 #include <string.h>
41 #include <krb5/roken.h>
42 #include <krb5/parse_units.h>
45 * Parse string in `s' according to `units' and return value.
46 * def_unit defines the default unit.
49 static int
50 parse_something (const char *s, const struct units *units,
51 const char *def_unit,
52 int (*func)(int res, int val, unsigned mult),
53 int init,
54 int accept_no_val_p)
56 const char *p;
57 int res = init;
58 unsigned def_mult = 1;
60 if (def_unit != NULL) {
61 const struct units *u;
63 for (u = units; u->name; ++u) {
64 if (strcasecmp (u->name, def_unit) == 0) {
65 def_mult = u->mult;
66 break;
69 if (u->name == NULL)
70 return -1;
73 p = s;
74 while (*p) {
75 int val;
76 char *next;
77 const struct units *u, *partial_unit;
78 size_t u_len;
79 unsigned partial;
80 int no_val_p = 0;
82 while(isspace((unsigned char)*p) || *p == ',')
83 ++p;
85 val = strtol(p, &next, 0);
86 if (p == next) {
87 val = 0;
88 if(!accept_no_val_p)
89 return -1;
90 no_val_p = 1;
92 p = next;
93 while (isspace((unsigned char)*p))
94 ++p;
95 if (*p == '\0') {
96 res = (*func)(res, val, def_mult);
97 if (res < 0)
98 return res;
99 break;
100 } else if (*p == '+') {
101 ++p;
102 val = 1;
103 } else if (*p == '-') {
104 ++p;
105 val = -1;
107 if (no_val_p && val == 0)
108 val = 1;
109 u_len = strcspn (p, ", \t");
110 partial = 0;
111 partial_unit = NULL;
112 if (u_len > 1 && p[u_len - 1] == 's')
113 --u_len;
114 for (u = units; u->name; ++u) {
115 if (strncasecmp (p, u->name, u_len) == 0) {
116 if (u_len == strlen (u->name)) {
117 p += u_len;
118 res = (*func)(res, val, u->mult);
119 if (res < 0)
120 return res;
121 break;
122 } else {
123 ++partial;
124 partial_unit = u;
128 if (u->name == NULL) {
129 if (partial == 1) {
130 p += u_len;
131 res = (*func)(res, val, partial_unit->mult);
132 if (res < 0)
133 return res;
134 } else {
135 return -1;
138 if (*p == 's')
139 ++p;
141 return res;
145 * The string consists of a sequence of `n unit'
148 static int
149 acc_units(int res, int val, unsigned mult)
151 return res + val * mult;
154 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
155 parse_units (const char *s, const struct units *units,
156 const char *def_unit)
158 return parse_something (s, units, def_unit, acc_units, 0, 0);
162 * The string consists of a sequence of `[+-]flag'. `orig' consists
163 * the original set of flags, those are then modified and returned as
164 * the function value.
167 static int
168 acc_flags(int res, int val, unsigned mult)
170 if(val == 1)
171 return res | mult;
172 else if(val == -1)
173 return res & ~mult;
174 else if (val == 0)
175 return mult;
176 else
177 return -1;
180 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
181 parse_flags (const char *s, const struct units *units,
182 int orig)
184 return parse_something (s, units, NULL, acc_flags, orig, 1);
188 * Return a string representation according to `units' of `num' in `s'
189 * with maximum length `len'. The actual length is the function value.
192 static int
193 unparse_something (int num, const struct units *units, char *s, size_t len,
194 int (*print) (char *, size_t, int, const char *, int),
195 int (*update) (int, unsigned),
196 const char *zero_string)
198 const struct units *u;
199 int ret = 0, tmp;
201 if (num == 0)
202 return snprintf (s, len, "%s", zero_string);
204 for (u = units; num > 0 && u->name; ++u) {
205 int divisor;
207 divisor = num / u->mult;
208 if (divisor) {
209 num = (*update) (num, u->mult);
210 tmp = (*print) (s, len, divisor, u->name, num);
211 if (tmp < 0)
212 return tmp;
213 if (tmp > (int) len) {
214 len = 0;
215 s = NULL;
216 } else {
217 len -= tmp;
218 s += tmp;
220 ret += tmp;
223 return ret;
226 static int
227 print_unit (char *s, size_t len, int divisor, const char *name, int rem)
229 return snprintf (s, len, "%u %s%s%s",
230 divisor, name,
231 divisor == 1 ? "" : "s",
232 rem > 0 ? " " : "");
235 static int
236 update_unit (int in, unsigned mult)
238 return in % mult;
241 static int
242 update_unit_approx (int in, unsigned mult)
244 if (in / mult > 0)
245 return 0;
246 else
247 return update_unit (in, mult);
250 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
251 unparse_units (int num, const struct units *units, char *s, size_t len)
253 return unparse_something (num, units, s, len,
254 print_unit,
255 update_unit,
256 "0");
259 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
260 unparse_units_approx (int num, const struct units *units, char *s, size_t len)
262 return unparse_something (num, units, s, len,
263 print_unit,
264 update_unit_approx,
265 "0");
268 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
269 print_units_table (const struct units *units, FILE *f)
271 const struct units *u, *u2;
272 size_t max_sz = 0;
274 for (u = units; u->name; ++u) {
275 max_sz = max(max_sz, strlen(u->name));
278 for (u = units; u->name;) {
279 char buf[1024];
280 const struct units *next;
282 for (next = u + 1; next->name && next->mult == u->mult; ++next)
285 if (next->name) {
286 for (u2 = next;
287 u2->name && u->mult % u2->mult != 0;
288 ++u2)
290 if (u2->name == NULL)
291 --u2;
292 unparse_units (u->mult, u2, buf, sizeof(buf));
293 fprintf (f, "1 %*s = %s\n", (int)max_sz, u->name, buf);
294 } else {
295 fprintf (f, "1 %s\n", u->name);
297 u = next;
301 static int
302 print_flag (char *s, size_t len, int divisor, const char *name, int rem)
304 return snprintf (s, len, "%s%s", name, rem > 0 ? ", " : "");
307 static int
308 update_flag (int in, unsigned mult)
310 return in - mult;
313 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
314 unparse_flags (int num, const struct units *units, char *s, size_t len)
316 return unparse_something (num, units, s, len,
317 print_flag,
318 update_flag,
319 "");
322 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
323 print_flags_table (const struct units *units, FILE *f)
325 const struct units *u;
327 for(u = units; u->name; ++u)
328 fprintf(f, "%s%s", u->name, (u+1)->name ? ", " : "\n");