1 /* Copyright (c) 2002,2005, Joerg Wunsch
2    All rights reserved.
3 
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions are met:
6 
7    * Redistributions of source code must retain the above copyright
8      notice, this list of conditions and the following disclaimer.
9    * Redistributions in binary form must reproduce the above copyright
10      notice, this list of conditions and the following disclaimer in
11      the documentation and/or other materials provided with the
12      distribution.
13    * Neither the name of the copyright holders nor the names of
14      contributors may be used to endorse or promote products derived
15      from this software without specific prior written permission.
16 
17   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27   POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 /* $Id: stdio_private.h 847 2005-09-06 18:49:15Z joerg_wunsch $ */
31 
32 #ifndef _STDIO_PRIVATE_H_
33 #define _STDIO_PRIVATE_H_
34 
35 #include <stdio-bufio.h>
36 #include <stdbool.h>
37 #include <sys/lock.h>
38 
39 /* values for PRINTF_LEVEL */
40 #define PRINTF_STD 1
41 #define PRINTF_FLT 2
42 
43 /* values for SCANF_LEVEL */
44 #define SCANF_STD 1
45 #define SCANF_FLT 2
46 
47 struct __file_str {
48 	struct __file file;	/* main file struct */
49         char	*pos;		/* current buffer position */
50         char    *end;           /* end of buffer */
51         size_t  size;           /* size of allocated storage */
52 };
53 
54 int
55 __file_str_get(FILE *stream);
56 
57 int
58 __file_wstr_get(FILE *stream);
59 
60 int
61 __file_str_put(char c, FILE *stream);
62 
63 int
64 __file_str_put_alloc(char c, FILE *stream);
65 
66 extern const char __match_inf[];
67 extern const char __match_inity[];
68 extern const char __match_nan[];
69 
70 /* Returns 'true' if prefix of input matches pattern, independent of
71  * case. pattern is only upper case letters.
72  */
73 bool __matchcaseprefix(const char *input, const char *pattern);
74 
75 /*
76  * It is OK to discard the "const" qualifier here.  f.buf is
77  * non-const as in the generic case, this buffer is obtained
78  * by malloc().  In the scanf case however, the buffer is
79  * really only be read (by getc()), and as this our FILE f we
80  * be discarded upon exiting sscanf(), nobody will ever get
81  * a chance to get write access to it again.
82  */
83 #define FDEV_SETUP_STRING_READ(_s) {		\
84 		.file = {			\
85 			.flags = __SRD,		\
86 			.get = __file_str_get	\
87 		},				\
88 		.pos = (char *) (_s)		\
89 	}
90 
91 #define FDEV_SETUP_WSTRING_READ(_s) {		\
92 		.file = {			\
93 			.flags = __SRD,		\
94 			.get = __file_wstr_get	\
95 		},				\
96                 .pos = (char *) (_s),           \
97                 .end = (char *) (_s)            \
98 	}
99 
100 #define FDEV_SETUP_STRING_WRITE(_s, _size) {	\
101 		.file = {			\
102 			.flags = __SWR,		\
103 			.put = __file_str_put	\
104 		},				\
105 		.pos = (_s),			\
106                 .end = (_s) + (_size),          \
107 	}
108 
109 #define FDEV_SETUP_STRING_ALLOC() {		\
110 		.file = {			\
111 			.flags = __SWR,		\
112 			.put = __file_str_put_alloc	\
113 		},				\
114 		.pos = NULL,			\
115 		.end = NULL,			\
116                 .size = 0,                      \
117 	}
118 
119 #ifdef POSIX_IO
120 
121 #define FDEV_SETUP_POSIX(fd, buf, size, rwflags, bflags)        \
122         FDEV_SETUP_BUFIO(fd, buf, size,                         \
123                          read, write,                           \
124                          lseek, close, rwflags, bflags)
125 
126 int
127 __posix_sflags (const char *mode, int *optr);
128 
129 #endif
130 
131 int	__d_vfprintf(FILE *__stream, const char *__fmt, va_list __ap) __FORMAT_ATTRIBUTE__(printf, 2, 0);
132 int	__f_vfprintf(FILE *__stream, const char *__fmt, va_list __ap) __FORMAT_ATTRIBUTE__(printf, 2, 0);
133 int	__d_sprintf(char *__s, const char *__fmt, ...) __FORMAT_ATTRIBUTE__(printf, 2, 0);
134 int	__f_sprintf(char *__s, const char *__fmt, ...) __FORMAT_ATTRIBUTE__(printf, 2, 0);
135 int	__d_snprintf(char *__s, size_t __n, const char *__fmt, ...) __FORMAT_ATTRIBUTE__(printf, 3, 0);
136 int	__f_snprintf(char *__s, size_t __n, const char *__fmt, ...) __FORMAT_ATTRIBUTE__(printf, 3, 0);
137 
138 double
139 __atod_engine(uint64_t m10, int e10);
140 
141 float
142 __atof_engine(uint32_t m10, int e10);
143 
144 #ifdef __SIZEOF_INT128__
145 typedef __uint128_t _u128;
146 typedef __int128_t _i128;
147 #define to_u128(x)              (x)
148 #define from_u128(x)            (x)
149 #define _u128_to_ld(a)          ((long double) (a))
150 #define _u128_is_zero(a)        ((a) == 0)
151 #define _i128_lt_zero(a)        ((_i128) (a) < 0)
152 #define _u128_plus_64(a,b) ((a) + (b))
153 #define _u128_plus(a,b) ((a) + (b))
154 #define _u128_minus(a,b) ((a) - (b))
155 #define _u128_minus_64(a,b) ((a) - (b))
156 #define _u128_times_10(a) ((a) * 10)
157 #define _u128_times_base(a,b)   ((a) * (b))
158 #define _u128_to_ld(a) ((long double) (a))
159 #define _u128_oflow(a)	((a) >= (((((_u128) 0xffffffffffffffffULL) << 64) | 0xffffffffffffffffULL) - 9 / 10))
160 #define _u128_zero	(_u128) 0
161 #define _u128_lshift(a,b)       ((_u128) (a) << (b))
162 #define _u128_lshift_64(a,b)    ((_u128) (a) << (b))
163 #define _u128_rshift(a,b)       ((a) >> (b))
164 #define _i128_rshift(a,b)       ((_i128) (a) >> (b))
165 #define _u128_or_64(a,b)        ((a) | (_u128) (b))
166 #define _u128_and_64(a,b)       ((uint64_t) (a) & (b))
167 #define _u128_or(a,b)           ((a) | (b))
168 #define _u128_and(a,b)          ((a) & (b))
169 #define _u128_ge(a,b)           ((a) >= (b))
170 #define _i128_ge(a,b)           ((_i128)(a) >= (_i128)(b))
171 #define _u128_lt(a,b)           ((a) < (b))
172 #define _i128_lt(a,b)           ((_i128)(a) < (_i128)(b))
173 #define _u128_not(a)            (~(a))
174 #else
175 typedef struct {
176 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
177     uint64_t	lo, hi;
178 #else
179     uint64_t	hi, lo;
180 #endif
181 } _u128;
182 #define _u128_zero	(_u128) { 0, 0 }
183 
to_u128(uint64_t x)184 static inline _u128 to_u128(uint64_t x)
185 {
186     _u128 a = { .hi = 0, .lo = x };
187     return a;
188 }
189 
from_u128(_u128 a)190 static inline uint64_t from_u128(_u128 a)
191 {
192     return a.lo;
193 }
194 
195 static inline long double
_u128_to_ld(_u128 a)196 _u128_to_ld(_u128 a)
197 {
198     return (long double) a.hi * ((long double) (1LL << 32) * (long double) (1LL << 32)) + (long double) a.lo;
199 }
200 
201 static inline bool
_u128_is_zero(_u128 a)202 _u128_is_zero(_u128 a)
203 {
204     return a.hi == 0 && a.lo == 0;
205 }
206 
207 static inline bool
_i128_lt_zero(_u128 a)208 _i128_lt_zero(_u128 a)
209 {
210     return (int64_t) a.hi < 0;
211 }
212 
213 static inline bool
_u128_lt(_u128 a,_u128 b)214 _u128_lt(_u128 a, _u128 b)
215 {
216     if (a.hi == b.hi)
217         return a.lo < b.lo;
218     return a.hi < b.hi;
219 }
220 
221 static inline bool
_i128_lt(_u128 a,_u128 b)222 _i128_lt(_u128 a, _u128 b)
223 {
224     if (a.hi == b.hi) {
225         if ((int64_t) a.hi < 0)
226             return a.lo > b.lo;
227         else
228             return a.lo < b.lo;
229     }
230     return (int64_t) a.hi < (int64_t) b.hi;
231 }
232 
233 static inline bool
_u128_ge(_u128 a,_u128 b)234 _u128_ge(_u128 a, _u128 b)
235 {
236     if (a.hi == b.hi)
237         return a.lo >= b.lo;
238     return a.hi >= b.hi;
239 }
240 
241 static inline bool
_i128_ge(_u128 a,_u128 b)242 _i128_ge(_u128 a, _u128 b)
243 {
244     if (a.hi == b.hi) {
245         if ((int64_t) a.hi < 0)
246             return a.lo <= b.lo;
247         else
248             return a.lo >= b.lo;
249     }
250     return (int64_t) a.hi >= (int64_t) b.hi;
251 }
252 
253 static inline _u128
_u128_plus_64(_u128 a,uint64_t b)254 _u128_plus_64(_u128 a, uint64_t b)
255 {
256     _u128 v;
257 
258     v.lo = a.lo + b;
259     v.hi = a.hi;
260     if (v.lo < a.lo)
261 	v.hi++;
262     return v;
263 }
264 
265 static inline _u128
_u128_plus(_u128 a,_u128 b)266 _u128_plus(_u128 a, _u128 b)
267 {
268     _u128 v;
269 
270     v.lo = a.lo + b.lo;
271     v.hi = a.hi + b.hi;
272     if (v.lo < a.lo)
273 	v.hi++;
274     return v;
275 }
276 
277 static inline _u128
_u128_minus_64(_u128 a,uint64_t b)278 _u128_minus_64(_u128 a, uint64_t b)
279 {
280     _u128 v;
281 
282     v.lo = a.lo - b;
283     v.hi = a.hi;
284     if (v.lo > a.lo)
285 	v.hi--;
286     return v;
287 }
288 
289 static inline _u128
_u128_minus(_u128 a,_u128 b)290 _u128_minus(_u128 a, _u128 b)
291 {
292     _u128 v;
293 
294     v.lo = a.lo - b.lo;
295     v.hi = a.hi - b.hi;
296     if (v.lo > a.lo)
297 	v.hi--;
298     return v;
299 }
300 
301 static inline _u128
_u128_lshift(_u128 a,int amt)302 _u128_lshift(_u128 a, int amt)
303 {
304     _u128	v;
305 
306     if (amt == 0) {
307         v = a;
308     } else if (amt < 64) {
309         v.lo = a.lo << amt;
310         v.hi = (a.lo >> (64 - amt)) | (a.hi << amt);
311     } else {
312         v.lo = 0;
313         v.hi = a.lo << (amt - 64);
314     }
315     return v;
316 }
317 
318 static inline _u128
_u128_lshift_64(uint64_t a,int amt)319 _u128_lshift_64(uint64_t a, int amt)
320 {
321     _u128	v;
322 
323     if (amt == 0) {
324         v.lo = a;
325         v.hi = 0;
326     } else if (amt < 64) {
327         v.lo = a << amt;
328         v.hi = (a >> (64 - amt));
329     } else {
330         v.lo = 0;
331         v.hi = a << (amt - 64);
332     }
333     return v;
334 }
335 
336 static inline _u128
_u128_rshift(_u128 a,int amt)337 _u128_rshift(_u128 a, int amt)
338 {
339     _u128	v;
340 
341     if (amt == 0) {
342         v = a;
343     } else if (amt < 64) {
344         v.lo = (a.hi << (64 - amt)) | (a.lo >> amt);
345         v.hi = a.hi >> amt;
346     } else {
347         v.hi = 0;
348         v.lo = a.hi >> (amt - 64);
349     }
350     return v;
351 }
352 
353 static inline _u128
_u128_and(_u128 a,_u128 b)354 _u128_and(_u128 a, _u128 b)
355 {
356     _u128       v;
357 
358     v.hi = a.hi & b.hi;
359     v.lo = a.lo & b.lo;
360     return v;
361 }
362 
363 static inline uint64_t
_u128_and_64(_u128 a,uint64_t b)364 _u128_and_64(_u128 a, uint64_t b)
365 {
366     return a.lo & b;
367 }
368 
369 static inline _u128
_u128_or(_u128 a,_u128 b)370 _u128_or(_u128 a, _u128 b)
371 {
372     _u128       v;
373 
374     v.lo = a.lo | b.lo;
375     v.hi = a.hi | b.hi;
376     return v;
377 }
378 
379 static inline _u128
_u128_or_64(_u128 a,uint64_t b)380 _u128_or_64(_u128 a, uint64_t b)
381 {
382     _u128       v;
383 
384     v.lo = a.lo | b;
385     v.hi = a.hi;
386     return v;
387 }
388 
389 static inline _u128
_u128_not(_u128 a)390 _u128_not(_u128 a)
391 {
392     _u128       v;
393 
394     v.lo = ~a.lo;
395     v.hi = ~a.hi;
396     return v;
397 }
398 
399 static inline _u128
_u128_times_10(_u128 a)400 _u128_times_10(_u128 a)
401 {
402     return _u128_plus(_u128_lshift(a, 3), _u128_lshift(a, 1));
403 }
404 
405 static inline _u128
_u128_times_base(_u128 a,int base)406 _u128_times_base(_u128 a, int base)
407 {
408     if (base == 10)
409         return _u128_times_10(a);
410     return _u128_lshift(a, 4);
411 }
412 
413 static inline bool
_u128_oflow(_u128 a)414 _u128_oflow(_u128 a)
415 {
416     return a.hi >= (0xffffffffffffffffULL - 9) / 10;
417 }
418 #endif
419 
420 static inline _u128
asuint128(long double f)421 asuint128(long double f)
422 {
423     union {
424         long double     f;
425         _u128           i;
426     } v;
427 
428     v.f = f;
429     return v.i;
430 }
431 
432 static inline long double
aslongdouble(_u128 i)433 aslongdouble(_u128 i)
434 {
435     union {
436         long double     f;
437         _u128           i;
438     } v;
439 
440     v.i = i;
441     return v.f;
442 }
443 
444 static inline bool
_u128_gt(_u128 a,_u128 b)445 _u128_gt(_u128 a, _u128 b)
446 {
447     return _u128_lt(b, a);
448 }
449 
450 long double
451 __atold_engine(_u128 m10, int e10);
452 
453 static inline uint16_t
__non_atomic_exchange_ungetc(__ungetc_t * p,__ungetc_t v)454 __non_atomic_exchange_ungetc(__ungetc_t *p, __ungetc_t v)
455 {
456 	__ungetc_t e = *p;
457 	*p = v;
458 	return e;
459 }
460 
461 static inline bool
__non_atomic_compare_exchange_ungetc(__ungetc_t * p,__ungetc_t d,__ungetc_t v)462 __non_atomic_compare_exchange_ungetc(__ungetc_t *p, __ungetc_t d, __ungetc_t v)
463 {
464 	if (*p != d)
465 		return false;
466 	*p = v;
467 	return true;
468 }
469 
470 #ifdef ATOMIC_UNGETC
471 
472 #if __PICOLIBC_UNGETC_SIZE == 4 && defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
473 #define PICOLIBC_HAVE_SYNC_COMPARE_AND_SWAP
474 #endif
475 
476 #if __PICOLIBC_UNGETC_SIZE == 2 && defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
477 #define PICOLIBC_HAVE_SYNC_COMPARE_AND_SWAP
478 #endif
479 
480 #ifdef PICOLIBC_HAVE_SYNC_COMPARE_AND_SWAP
481 
482 /* Use built-in atomic functions if they exist */
483 #include <stdatomic.h>
484 static inline bool
__atomic_compare_exchange_ungetc(__ungetc_t * p,__ungetc_t d,__ungetc_t v)485 __atomic_compare_exchange_ungetc(__ungetc_t *p, __ungetc_t d, __ungetc_t v)
486 {
487 	_Atomic __ungetc_t *pa = (_Atomic __ungetc_t *) p;
488         return atomic_compare_exchange_strong(pa, &d, v);
489 }
490 
491 static inline __ungetc_t
__atomic_exchange_ungetc(__ungetc_t * p,__ungetc_t v)492 __atomic_exchange_ungetc(__ungetc_t *p, __ungetc_t v)
493 {
494 	_Atomic __ungetc_t *pa = (_Atomic __ungetc_t *) p;
495 	return atomic_exchange_explicit(pa, v, memory_order_relaxed);
496 }
497 
498 #else
499 
500 bool
501 __atomic_compare_exchange_ungetc(__ungetc_t *p, __ungetc_t d, __ungetc_t v);
502 
503 __ungetc_t
504 __atomic_exchange_ungetc(__ungetc_t *p, __ungetc_t v);
505 
506 #endif /* PICOLIBC_HAVE_SYNC_COMPARE_AND_SWAP */
507 
508 #else
509 
510 #define __atomic_compare_exchange_ungetc(p,d,v) __non_atomic_compare_exchange_ungetc(p,d,v)
511 
512 #define __atomic_exchange_ungetc(p,v) __non_atomic_exchange_ungetc(p,v)
513 
514 #endif /* ATOMIC_UNGETC */
515 
516 #define CASE_CONVERT    ('a' - 'A')
517 #define TOLOW(c)        ((c) | CASE_CONVERT)
518 
519 /*
520  * Convert a single character to the value of the digit for any
521  * character 0 .. 9, A .. Z or a .. z
522  *
523  * Characters out of these ranges will return a value above 36
524  *
525  * Work in unsigned int type to avoid extra instructions required for
526  * unsigned char folding. The only time this matters is when
527  * subtracting '0' from values below '0', which results in very large
528  * unsigned values.
529  */
530 
531 static inline unsigned int
digit_to_val(unsigned int c)532 digit_to_val(unsigned int c)
533 {
534     /*
535      * Convert letters with some tricky code.
536      *
537      * TOLOW(c-1) maps characters as follows (Skipping values not
538      * greater than '9' (0x39), as those are skipped by the 'if'):
539      *
540      * Minus 1, bitwise-OR ('a' - 'A') (0x20):
541      *
542      *             0x3a..0x40 -> 0x39..0x3f
543      * 0x41..0x60, 0x61..0x80 -> 0x60..0x7f
544      * 0x81..0xa0, 0xa1..0xc0 -> 0xa0..0xbf
545      * 0xc1..0xe0, 0xe1..0x00 -> 0xe0..0xff
546      *
547      * Plus '0' (0x30), minus 'a') (0x61), plus 11 (0xb), for
548      * a total of minus 0x26:
549      *
550      *             0x3a..0x40 -> 0x39..0x3f -> 0x13..0x19
551      * 0x41..0x60, 0x61..0x80 -> 0x60..0x7f -> 0x3a..0x59
552      * 0x81..0xa0, 0xa1..0xc0 -> 0xa0..0xbf -> 0x7a..0x99
553      * 0xc1..0xe0, 0xe1..0x00 -> 0xe0..0xff -> 0xba..0xd9
554      */
555 
556     if (c > '9') {
557 
558         /*
559          * For the letters, we want TOLOW(c) - 'a' + 10, but that
560          * would map both '@' and '`' to 9.
561          *
562          * To work around this, subtract 1 before the bitwise-or so
563          * that '@' (0x40) gets mapped down to 0x3f (0x3f | 0x20)
564          * while '`' (0x60) gets mapped up to 0x7f (0x5f | 0x20),
565          * moving them away from the letters (which end up in the
566          * range 0x60..0x79). Then add the 1 back in when subtracting
567          * 'a' and adding 10.
568          *
569          * Add in '0' so that it can get subtracted out in the common
570          * code (c -= '0') below, avoiding an else clause.
571          */
572 
573         c = TOLOW(c-1) + ('0' - 'a' + 11);
574     }
575 
576     /*
577      * Now, include the range from NUL (0x00) through '9' (0x39)
578      *
579      * Minus '0' (0x30):
580      *
581      * 0x00..0x2f                                         ->-0x30..-0x01
582      * 0x30..0x39                                         -> 0x00..0x09 *
583      *             0x3a..0x40 -> 0x39..0x3f -> 0x13..0x19 ->-0x1d..-0x17
584      * 0x41..0x60, 0x61..0x80 -> 0x60..0x7f -> 0x3a..0x59 -> 0x0a..0x29 *
585      * 0x81..0xa0, 0xa1..0xc0 -> 0xa0..0xbf -> 0x7a..0x99 -> 0x4a..0x69
586      * 0xc1..0xe0, 0xe1..0x00 -> 0xe0..0xff -> 0xba..0xd9 -> 0x8a..0xa9
587      *
588      * The first starred row has the digits '0'..'9', while the second
589      * starts with the letters 'A'..'Z' and 'a'..'z'. All of the other
590      * rows end up with values above any allowed conversion base
591      */
592 
593     c -= '0';
594     return c;
595 }
596 
597 #endif /* _STDIO_PRIVATE_H_ */
598