libpayload: Add PDCurses and ncurses' libform/libmenu
[coreboot.git] / payloads / libpayload / curses / PDCurses-3.4 / pdcurses / scanw.c
1 /* Public Domain Curses */
2
3 #include <curspriv.h>
4
5 RCSID("$Id: scanw.c,v 1.42 2008/07/14 12:22:13 wmcbrine Exp $")
6
7 /*man-start**************************************************************
8
9   Name:                                                         scanw
10
11   Synopsis:
12         int scanw(const char *fmt, ...);
13         int wscanw(WINDOW *win, const char *fmt, ...);
14         int mvscanw(int y, int x, const char *fmt, ...);
15         int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...);
16         int vwscanw(WINDOW *win, const char *fmt, va_list varglist);
17         int vw_scanw(WINDOW *win, const char *fmt, va_list varglist);
18
19   Description:
20         These routines correspond to the standard C library's scanf()
21         family. Each gets a string from the window via wgetnstr(), and
22         uses the resulting line as input for the scan.
23
24   Return Value:
25         On successful completion, these functions return the number of
26         items successfully matched.  Otherwise they return ERR.
27
28   Portability                                X/Open    BSD    SYS V
29         scanw                                   Y       Y       Y
30         wscanw                                  Y       Y       Y
31         mvscanw                                 Y       Y       Y
32         mvwscanw                                Y       Y       Y
33         vwscanw                                 Y       -      4.0
34         vw_scanw                                Y
35
36 **man-end****************************************************************/
37
38 #include <string.h>
39
40 #ifndef HAVE_VSSCANF
41 # include <stdlib.h>
42 # include <ctype.h>
43 # include <limits.h>
44
45 static int _pdc_vsscanf(const char *, const char *, va_list);
46
47 # define vsscanf _pdc_vsscanf
48 #endif
49
50 int vwscanw(WINDOW *win, const char *fmt, va_list varglist)
51 {
52     char scanbuf[256];
53
54     PDC_LOG(("vwscanw() - called\n"));
55
56     if (wgetnstr(win, scanbuf, 255) == ERR)
57         return ERR;
58
59     return vsscanf(scanbuf, fmt, varglist);
60 }
61
62 int scanw(const char *fmt, ...)
63 {
64     va_list args;
65     int retval;
66
67     PDC_LOG(("scanw() - called\n"));
68
69     va_start(args, fmt);
70     retval = vwscanw(stdscr, fmt, args);
71     va_end(args);
72
73     return retval;
74 }
75
76 int wscanw(WINDOW *win, const char *fmt, ...)
77 {
78     va_list args;
79     int retval;
80
81     PDC_LOG(("wscanw() - called\n"));
82
83     va_start(args, fmt);
84     retval = vwscanw(win, fmt, args);
85     va_end(args);
86
87     return retval;
88 }
89
90 int mvscanw(int y, int x, const char *fmt, ...)
91 {
92     va_list args;
93     int retval;
94
95     PDC_LOG(("mvscanw() - called\n"));
96
97     if (move(y, x) == ERR)
98         return ERR;
99
100     va_start(args, fmt);
101     retval = vwscanw(stdscr, fmt, args);
102     va_end(args);
103
104     return retval;
105 }
106
107 int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...)
108 {
109     va_list args;
110     int retval;
111
112     PDC_LOG(("mvscanw() - called\n"));
113
114     if (wmove(win, y, x) == ERR)
115         return ERR;
116
117     va_start(args, fmt);
118     retval = vwscanw(win, fmt, args);
119     va_end(args);
120
121     return retval;
122 }
123
124 int vw_scanw(WINDOW *win, const char *fmt, va_list varglist)
125 {
126     PDC_LOG(("vw_scanw() - called\n"));
127
128     return vwscanw(win, fmt, varglist);
129 }
130
131 #ifndef HAVE_VSSCANF
132
133 /* _pdc_vsscanf() - Internal routine to parse and format an input 
134    buffer. It scans a series of input fields; each field is formatted 
135    according to a supplied format string and the formatted input is 
136    stored in the variable number of addresses passed. Returns the number 
137    of input fields or EOF on error.
138
139    Don't compile this unless required. Some compilers (at least Borland 
140    C++ 3.0) have to link with math libraries due to the use of floats.
141
142    Based on vsscanf.c and input.c from emx 0.8f library source, 
143    Copyright (c) 1990-1992 by Eberhard Mattes, who has kindly agreed to 
144    its inclusion in PDCurses. */
145
146 #define WHITE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
147
148 #define NEXT(x) \
149         do { \
150             x = *buf++; \
151             if (!x) \
152                return (count ? count : EOF); \
153             ++chars; \
154            } while (0)
155
156 #define UNGETC() \
157         do { \
158             --buf; --chars; \
159            } while (0)
160
161 static int _pdc_vsscanf(const char *buf, const char *fmt, va_list arg_ptr)
162 {
163     int count, chars, c, width, radix, d, i;
164     int *int_ptr;
165     long *long_ptr;
166     short *short_ptr;
167     char *char_ptr;
168     unsigned char f;
169     char neg, assign, ok, size;
170     long n;
171     char map[256], end;
172     double dx, dd, *dbl_ptr;
173     float *flt_ptr;
174     int exp;
175     char eneg;
176
177     count = 0;
178     chars = 0;
179     c = 0;
180     while ((f = *fmt) != 0)
181     {
182         if (WHITE(f))
183         {
184             do
185             {
186                 ++fmt;
187                 f = *fmt;
188             }
189             while (WHITE(f));
190             do
191             {
192                 c = *buf++;
193                 if (!c)
194                 {
195                     if (!f || count)
196                         return count;
197                     else
198                         return EOF;
199                 } else
200                     ++chars;
201             }
202             while (WHITE(c));
203             UNGETC();
204         } else if (f != '%')
205         {
206             NEXT(c);
207             if (c != f)
208                 return count;
209             ++fmt;
210         } else
211         {
212             assign = TRUE;
213             width = INT_MAX;
214             char_ptr = NULL;
215             ++fmt;
216             if (*fmt == '*')
217             {
218                 assign = FALSE;
219                 ++fmt;
220             }
221             if (isdigit(*fmt))
222             {
223                 width = 0;
224                 while (isdigit(*fmt))
225                     width = width * 10 + (*fmt++ - '0');
226                 if (!width)
227                     width = INT_MAX;
228             }
229             size = 0;
230             if (*fmt == 'h' || *fmt == 'l')
231                 size = *fmt++;
232             f = *fmt;
233             switch (f)
234             {
235             case 'c':
236                 if (width == INT_MAX)
237                     width = 1;
238                 if (assign)
239                     char_ptr = va_arg(arg_ptr, char *);
240                 while (width > 0)
241                 {
242                     --width;
243                     NEXT(c);
244                     if (assign)
245                     {
246                         *char_ptr++ = (char) c;
247                         ++count;
248                     }
249                 }
250                 break;
251             case '[':
252                 memset(map, 0, 256);
253                 end = 0;
254                 ++fmt;
255                 if (*fmt == '^')
256                 {
257                     ++fmt;
258                     end = 1;
259                 }
260                 i = 0;
261                 for (;;)
262                 {
263                     f = (unsigned char) *fmt;
264                     switch (f)
265                     {
266                     case 0:
267                         /* avoid skipping past 0 */
268                         --fmt;
269                         NEXT(c);
270                         goto string;
271                     case ']':
272                         if (i > 0)
273                         {
274                             NEXT(c);
275                             goto string;
276                         }
277                         /* no break */
278                     default:
279                         if (fmt[1] == '-' && fmt[2]
280                             && f < (unsigned char)fmt[2])
281                         {
282                             memset(map + f, 1, (unsigned char)fmt[2] - f);
283                             fmt += 2;
284                         }
285                         else
286                             map[f] = 1;
287                         break;
288                     }
289                     ++fmt;
290                     ++i;
291                 }
292             case 's':
293                 memset(map, 0, 256);
294                 map[' '] = 1;
295                 map['\n'] = 1;
296                 map['\r'] = 1;
297                 map['\t'] = 1;
298                 end = 1;
299                 do
300                 {
301                     NEXT(c);
302                 }
303                 while (WHITE(c));
304             string:
305                 if (assign)
306                     char_ptr = va_arg(arg_ptr, char *);
307                 while (width > 0 && map[(unsigned char) c] != end)
308                 {
309                     --width;
310                     if (assign)
311                         *char_ptr++ = (char) c;
312                     c = *buf++;
313                     if (!c)
314                         break;
315                     else
316                         ++chars;
317                 }
318                 if (assign)
319                 {
320                     *char_ptr = 0;
321                     ++count;
322                 }
323                 if (!c)
324                     return count;
325                 else
326                     UNGETC();
327                 break;
328             case 'f':
329             case 'e':
330             case 'E':
331             case 'g':
332             case 'G':
333                 neg = ok = FALSE;
334                 dx = 0.0;
335                 do
336                 {
337                     NEXT(c);
338                 }
339                 while (WHITE(c));
340                 if (c == '+')
341                 {
342                     NEXT(c);
343                     --width;
344                 } else if (c == '-')
345                 {
346                     neg = TRUE;
347                     NEXT(c);
348                     --width;
349                 }
350                 while (width > 0 && isdigit(c))
351                 {
352                     --width;
353                     dx = dx * 10.0 + (double) (c - '0');
354                     ok = TRUE;
355                     c = *buf++;
356                     if (!c)
357                         break;
358                     else
359                         ++chars;
360                 }
361                 if (width > 0 && c == '.')
362                 {
363                     --width;
364                     dd = 10.0;
365                     NEXT(c);
366                     while (width > 0 && isdigit(c))
367                     {
368                         --width;
369                         dx += (double) (c - '0') / dd;
370                         dd *= 10.0;
371                         ok = TRUE;
372                         c = *buf++;
373                         if (!c)
374                             break;
375                         else
376                             ++chars;
377                     }
378                 }
379                 if (!ok)
380                     return count;
381                 if (width > 0 && (c == 'e' || c == 'E'))
382                 {
383                     eneg = FALSE;
384                     exp = 0;
385                     NEXT(c);
386                     --width;
387                     if (width > 0 && c == '+')
388                     {
389                         NEXT(c);
390                         --width;
391                     } else if (width > 0 && c == '-')
392                     {
393                         eneg = TRUE;
394                         NEXT(c);
395                         --width;
396                     }
397                     if (!(width > 0 && isdigit(c)))
398                     {
399                         UNGETC();
400                         return count;
401                     }
402                     while (width > 0 && isdigit(c))
403                     {
404                         --width;
405                         exp = exp * 10 + (c - '0');
406                         c = *buf++;
407                         if (!c)
408                             break;
409                         else
410                             ++chars;
411                     }
412                     if (eneg)
413                         exp = -exp;
414                     while (exp > 0)
415                     {
416                         dx *= 10.0;
417                         --exp;
418                     }
419                     while (exp < 0)
420                     {
421                         dx /= 10.0;
422                         ++exp;
423                     }
424                 }
425                 if (assign)
426                 {
427                     if (neg)
428                         dx = -dx;
429                     if (size == 'l')
430                     {
431                         dbl_ptr = va_arg(arg_ptr, double *);
432                         *dbl_ptr = dx;
433                     }
434                     else
435                     {
436                         flt_ptr = va_arg(arg_ptr, float *);
437                         *flt_ptr = (float)dx;
438                     }
439                     ++count;
440                 }
441                 if (!c)
442                     return count;
443                 else
444                     UNGETC();
445                 break;
446             case 'i':
447                 neg = FALSE;
448                 radix = 10;
449                 do
450                 {
451                     NEXT(c);
452                 }
453                 while (WHITE(c));
454                 if (!(width > 0 && c == '0'))
455                     goto scan_complete_number;
456                 NEXT(c);
457                 --width;
458                 if (width > 0 && (c == 'x' || c == 'X'))
459                 {
460                     NEXT(c);
461                     radix = 16;
462                     --width;
463                 }
464                 else if (width > 0 && (c >= '0' && c <= '7'))
465                     radix = 8;
466                 goto scan_unsigned_number;
467             case 'd':
468             case 'u':
469             case 'o':
470             case 'x':
471             case 'X':
472                 do
473                 {
474                     NEXT(c);
475                 }
476                 while (WHITE(c));
477                 switch (f)
478                 {
479                 case 'o':
480                     radix = 8;
481                     break;
482                 case 'x':
483                 case 'X':
484                     radix = 16;
485                     break;
486                 default:
487                     radix = 10;
488                     break;
489                 }
490             scan_complete_number:
491                 neg = FALSE;
492                 if (width > 0 && c == '+')
493                 {
494                     NEXT(c);
495                     --width;
496                 }
497                 else if (width > 0 && c == '-' && radix == 10)
498                 {
499                     neg = TRUE;
500                     NEXT(c);
501                     --width;
502                 }
503             scan_unsigned_number:
504                 n = 0;
505                 ok = FALSE;
506                 while (width > 0)
507                 {
508                     --width;
509                     if (isdigit(c))
510                         d = c - '0';
511                     else if (isupper(c))
512                         d = c - 'A' + 10;
513                     else if (islower(c))
514                         d = c - 'a' + 10;
515                     else
516                         break;
517                     if (d < 0 || d >= radix)
518                         break;
519                     ok = TRUE;
520                     n = n * radix + d;
521                     c = *buf++;
522                     if (!c)
523                         break;
524                     else
525                         ++chars;
526                 }
527                 if (!ok)
528                     return count;
529                 if (assign)
530                 {
531                     if (neg)
532                         n = -n;
533                     switch (size)
534                     {
535                     case 'h':
536                         short_ptr = va_arg(arg_ptr, short *);
537                         *short_ptr = (short) n;
538                         break;
539                     case 'l':
540                         long_ptr = va_arg(arg_ptr, long *);
541                         *long_ptr = (long) n;
542                         break;
543                     default:
544                         int_ptr = va_arg(arg_ptr, int *);
545                         *int_ptr = (int) n;
546                     }
547                     ++count;
548                 }
549                 if (!c)
550                     return count;
551                 else
552                     UNGETC();
553                 break;
554             case 'n':
555                 if (assign)
556                 {
557                     int_ptr = va_arg(arg_ptr, int *);
558                     *int_ptr = chars;
559                     ++count;
560                 }
561                 break;
562             default:
563                 if (!f) /* % at end of string */
564                     return count;
565                 NEXT(c);
566                 if (c != f)
567                     return count;
568                 break;
569             }
570             ++fmt;
571         }
572     }
573     return count;
574 }
575 #endif /* HAVE_VSSCANF */