libpayload: configs: Add new config.featuretest to broaden CI
[coreboot2.git] / payloads / libpayload / curses / form / fty_num.c
blob4bd71321d66acf67cfd4b4fd4d20e8ab2362d67a
1 /****************************************************************************
2 * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
29 /***************************************************************************
30 * *
31 * Author : Juergen Pfeifer *
32 * *
33 ***************************************************************************/
35 #include "form.priv.h"
37 MODULE_ID("$Id: fty_num.c,v 1.28 2010/01/23 21:14:36 tom Exp $")
39 #if HAVE_LOCALE_H
40 #include <locale.h>
41 #endif
43 #if HAVE_LOCALE_H
44 #define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.'))
45 #else
46 #define isDecimalPoint(c) ((c) == '.')
47 #endif
49 #if USE_WIDEC_SUPPORT
50 #define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c)))
51 #else
52 #define isDigit(c) isdigit(UChar(c))
53 #endif
55 #define thisARG numericARG
57 typedef struct
59 int precision;
60 double low;
61 double high;
62 struct lconv *L;
64 thisARG;
66 typedef struct
68 int precision;
69 double low;
70 double high;
72 thisPARM;
74 /*---------------------------------------------------------------------------
75 | Facility : libnform
76 | Function : static void *Generic_This_Type(void * arg)
78 | Description : Allocate structure for numeric type argument.
80 | Return Values : Pointer to argument structure or NULL on error
81 +--------------------------------------------------------------------------*/
82 static void *
83 Generic_This_Type(void *arg)
85 thisARG *argn = (thisARG *) 0;
86 thisPARM *args = (thisPARM *) arg;
88 if (args)
90 argn = typeMalloc(thisARG, 1);
92 if (argn)
94 T((T_CREATE("thisARG %p"), (void *)argn));
95 argn->precision = args->precision;
96 argn->low = args->low;
97 argn->high = args->high;
99 #if HAVE_LOCALE_H
100 argn->L = localeconv();
101 #else
102 argn->L = NULL;
103 #endif
106 return (void *)argn;
109 /*---------------------------------------------------------------------------
110 | Facility : libnform
111 | Function : static void *Make_This_Type(va_list * ap)
113 | Description : Allocate structure for numeric type argument.
115 | Return Values : Pointer to argument structure or NULL on error
116 +--------------------------------------------------------------------------*/
117 static void *
118 Make_This_Type(va_list *ap)
120 thisPARM arg;
122 arg.precision = va_arg(*ap, int);
123 arg.low = va_arg(*ap, double);
124 arg.high = va_arg(*ap, double);
126 return Generic_This_Type((void *)&arg);
129 /*---------------------------------------------------------------------------
130 | Facility : libnform
131 | Function : static void *Copy_This_Type(const void * argp)
133 | Description : Copy structure for numeric type argument.
135 | Return Values : Pointer to argument structure or NULL on error.
136 +--------------------------------------------------------------------------*/
137 static void *
138 Copy_This_Type(const void *argp)
140 const thisARG *ap = (const thisARG *)argp;
141 thisARG *result = (thisARG *) 0;
143 if (argp)
145 result = typeMalloc(thisARG, 1);
146 if (result)
148 T((T_CREATE("thisARG %p"), (void *)result));
149 *result = *ap;
152 return (void *)result;
155 /*---------------------------------------------------------------------------
156 | Facility : libnform
157 | Function : static void Free_This_Type(void * argp)
159 | Description : Free structure for numeric type argument.
161 | Return Values : -
162 +--------------------------------------------------------------------------*/
163 static void
164 Free_This_Type(void *argp)
166 if (argp)
167 free(argp);
170 /*---------------------------------------------------------------------------
171 | Facility : libnform
172 | Function : static bool Check_This_Field(FIELD * field,
173 | const void * argp)
175 | Description : Validate buffer content to be a valid numeric value
177 | Return Values : TRUE - field is valid
178 | FALSE - field is invalid
179 +--------------------------------------------------------------------------*/
180 static bool
181 Check_This_Field(FIELD *field, const void *argp)
183 const thisARG *argn = (const thisARG *)argp;
184 double low = argn->low;
185 double high = argn->high;
186 int prec = argn->precision;
187 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
188 char *s = (char *)bp;
189 double val = 0.0;
190 struct lconv *L = argn->L;
191 char buf[64];
192 bool result = FALSE;
194 while (*bp && *bp == ' ')
195 bp++;
196 if (*bp)
198 if (*bp == '-' || *bp == '+')
199 bp++;
200 #if USE_WIDEC_SUPPORT
201 if (*bp)
203 bool blank = FALSE;
204 int state = 0;
205 int len;
206 int n;
207 wchar_t *list = _nc_Widen_String((char *)bp, &len);
209 if (list != 0)
211 result = TRUE;
212 for (n = 0; n < len; ++n)
214 if (blank)
216 if (list[n] != ' ')
218 result = FALSE;
219 break;
222 else if (list[n] == ' ')
224 blank = TRUE;
226 else if (isDecimalPoint(list[n]))
228 if (++state > 1)
230 result = FALSE;
231 break;
234 else if (!isDigit(list[n]))
236 result = FALSE;
237 break;
240 free(list);
243 #else
244 while (*bp)
246 if (!isdigit(UChar(*bp)))
247 break;
248 bp++;
250 if (isDecimalPoint(*bp))
252 bp++;
253 while (*bp)
255 if (!isdigit(UChar(*bp)))
256 break;
257 bp++;
260 while (*bp && *bp == ' ')
261 bp++;
262 result = (*bp == '\0');
263 #endif
264 if (result)
266 val = atof(s);
267 if (low < high)
269 if (val < low || val > high)
270 result = FALSE;
272 if (result)
274 sprintf(buf, "%.*f", (prec > 0 ? prec : 0), val);
275 set_field_buffer(field, 0, buf);
279 return (result);
282 /*---------------------------------------------------------------------------
283 | Facility : libnform
284 | Function : static bool Check_This_Character(
285 | int c,
286 | const void * argp)
288 | Description : Check a character for the numeric type.
290 | Return Values : TRUE - character is valid
291 | FALSE - character is invalid
292 +--------------------------------------------------------------------------*/
293 static bool
294 Check_This_Character(int c, const void *argp)
296 const thisARG *argn = (const thisARG *)argp;
297 struct lconv *L = argn->L;
299 return ((isDigit(c) ||
300 c == '+' ||
301 c == '-' ||
302 isDecimalPoint(c))
303 ? TRUE
304 : FALSE);
307 static FIELDTYPE typeTHIS =
309 _HAS_ARGS | _RESIDENT,
310 1, /* this is mutable, so we can't be const */
311 (FIELDTYPE *)0,
312 (FIELDTYPE *)0,
313 Make_This_Type,
314 Copy_This_Type,
315 Free_This_Type,
316 INIT_FT_FUNC(Check_This_Field),
317 INIT_FT_FUNC(Check_This_Character),
318 INIT_FT_FUNC(NULL),
319 INIT_FT_FUNC(NULL),
320 #if NCURSES_INTEROP_FUNCS
321 Generic_This_Type
322 #endif
325 NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeTHIS;
327 #if NCURSES_INTEROP_FUNCS
328 /* The next routines are to simplify the use of ncurses from
329 programming languages with restictions on interop with C level
330 constructs (e.g. variable access or va_list + ellipsis constructs)
332 NCURSES_EXPORT(FIELDTYPE *)
333 _nc_TYPE_NUMERIC(void)
335 return TYPE_NUMERIC;
337 #endif
339 /* fty_num.c ends here */