1 /* This header file provides the reentrancy. */
3 /* WARNING: All identifiers here must begin with an underscore. This file is
4 included by stdio.h and others and we therefore must only use identifiers
5 in the namespace allotted to us. */
14 #include <sys/_types.h>
17 #if __LONG_MAX__ == 2147483647L
19 typedef unsigned __Long __ULong;
20 #elif __INT_MAX__ == 2147483647
22 typedef unsigned __Long __ULong;
27 #define __Long __int32_t
28 typedef __uint32_t __ULong;
32 * If _REENT_SMALL is defined, we make struct _reent as small as possible,
33 * by having nearly everything possible allocated at first use.
40 struct __sFILE *_iobs;
45 struct _Bigint *_next;
46 int _k, _maxwds, _sign, _wds;
50 /* needed by reentrant structure */
65 * atexit() support. For _REENT_SMALL, we limit to 32 max.
68 #define _ATEXIT_SIZE 32 /* must be at least 32 to guarantee ANSI conformance */
72 struct _atexit *_next; /* next in list */
73 int _ind; /* next index in this table */
74 void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */
75 void *_fnargs[_ATEXIT_SIZE]; /* fn args for on_exit */
76 __uint32_t _fntypes; /* type of exit routine */
80 int _ind; /* next index in this table */
81 void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */
82 void *_fnargs[_ATEXIT_SIZE]; /* fn args for on_exit */
83 __uint32_t _fntypes; /* type of exit routine */
90 * This and __sFILE are defined here because we need them for struct _reent,
91 * but we don't want stdio.h included when stdlib.h is.
100 * We need fpos_t for the following, but it doesn't have a leading "_",
101 * so we use _fpos_t instead.
104 typedef long _fpos_t; /* XXX must match off_t in <sys/types.h> */
105 /* (and must be `long' for now) */
108 * Stdio state variables.
110 * The following always hold:
112 * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
113 * _lbfsize is -_bf._size, else _lbfsize is 0
114 * if _flags&__SRD, _w is 0
115 * if _flags&__SWR, _r is 0
117 * This ensures that the getc and putc macros (or inline functions) never
118 * try to write or read from a file that is in `read' or `write' mode.
119 * (Moreover, they can, and do, automatically switch from read mode to
120 * write mode, and back, on "r+" and "w+" files.)
122 * _lbfsize is used only to make the inline line-buffered output stream
123 * code as compact as possible.
125 * _ub, _up, and _ur are used when ungetc() pushes back more characters
126 * than fit in the current _bf, or when ungetc() pushes back a character
127 * that does not match the previous one in _bf. When this happens,
128 * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
129 * _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
134 * struct __sFILE_fake is the start of a struct __sFILE, with only the
135 * minimal fields allocated. In __sinit() we really allocate the 3
136 * standard streams, etc., and point away from this fake.
138 struct __sFILE_fake {
139 unsigned char *_p; /* current position in (some) buffer */
140 int _r; /* read space left for getc() */
141 int _w; /* write space left for putc() */
142 short _flags; /* flags, below; this FILE is free if 0 */
143 short _file; /* fileno, if Unix descriptor, else -1 */
144 struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
145 int _lbfsize; /* 0 or -_bf._size, for inline putc */
147 struct _reent *_data;
149 /* CHECK_INIT() comes from stdio/local.h; be sure to include that. */
150 # define _REENT_SMALL_CHECK_INIT(fp) CHECK_INIT(fp)
152 # define _REENT_SMALL_CHECK_INIT(fp) /* nothing */
156 unsigned char *_p; /* current position in (some) buffer */
157 int _r; /* read space left for getc() */
158 int _w; /* write space left for putc() */
159 short _flags; /* flags, below; this FILE is free if 0 */
160 short _file; /* fileno, if Unix descriptor, else -1 */
161 struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
162 int _lbfsize; /* 0 or -_bf._size, for inline putc */
165 struct _reent *_data;
169 _PTR _cookie; /* cookie passed to io functions */
171 _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(_PTR _cookie, char *_buf, int _n));
172 _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(_PTR _cookie, const char *_buf,
174 _fpos_t _EXFUN((*_seek),(_PTR _cookie, _fpos_t _offset, int _whence));
175 int _EXFUN((*_close),(_PTR _cookie));
177 /* separate buffer for long sequences of ungetc() */
178 struct __sbuf _ub; /* ungetc buffer */
179 unsigned char *_up; /* saved _p when _p is doing ungetc data */
180 int _ur; /* saved _r when _r is counting ungetc data */
182 /* tricks to meet minimum requirements even when malloc() fails */
183 unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
184 unsigned char _nbuf[1]; /* guarantee a getc() buffer */
186 /* separate buffer for fgetline() when line crosses buffer boundary */
187 struct __sbuf _lb; /* buffer for fgetline() */
189 /* Unix stdio files get aligned to block boundaries on fseek() */
190 int _blksize; /* stat.st_blksize (may be != _bf._size) */
191 int _offset; /* current lseek offset */
194 struct _reent *_data; /* Here for binary compatibility? Remove? */
199 * rand48 family support
201 * Copyright (c) 1993 Martin Birgmeier
202 * All rights reserved.
204 * You may redistribute unmodified or modified versions of this source
205 * code provided that the above copyright notice and this and the
206 * following conditions are retained.
208 * This software is provided ``as is'', and comes with no warranties
209 * of any kind. I shall in no event be liable for anything that happens
210 * to anyone/anything when using this software.
212 #define _RAND48_SEED_0 (0x330e)
213 #define _RAND48_SEED_1 (0xabcd)
214 #define _RAND48_SEED_2 (0x1234)
215 #define _RAND48_MULT_0 (0xe66d)
216 #define _RAND48_MULT_1 (0xdeec)
217 #define _RAND48_MULT_2 (0x0005)
218 #define _RAND48_ADD (0x000b)
220 unsigned short _seed[3];
221 unsigned short _mult[3];
224 /* Put this in here as well, for good luck. */
225 __extension__ unsigned long long _rand_next;
229 /* How big the some arrays are. */
230 #define _REENT_EMERGENCY_SIZE 25
231 #define _REENT_ASCTIME_SIZE 26
236 * This structure contains *all* globals needed by the library.
237 * It's raison d'etre is to facilitate threads by making all library routines
238 * reentrant. IE: All state information is contained here.
245 /* used by mprec routines */
246 struct _Bigint *_result;
248 struct _Bigint *_p5s;
249 struct _Bigint **_freelist;
255 /* miscellaneous reentrant data */
263 /* This version of _reent is layed our with "int"s in pairs, to help
264 * ports with 16-bit int's but 32-bit pointers, align nicely. */
268 /* FILE is a big struct and may change over time. To try to achieve binary
269 compatibility with future versions, put stdin,stdout,stderr here.
270 These are pointers into member __sf defined below. */
271 struct __sFILE *_stdin, *_stdout, *_stderr; /* XXX */
273 int _errno; /* local copy of errno */
275 int _inc; /* used by tmpnam */
279 int __sdidinit; /* 1 means stdio has been init'd */
281 int _current_category; /* used by setlocale */
282 _CONST char *_current_locale;
286 void _EXFUN((*__cleanup),(struct _reent *));
290 /* used by some fp conversion routines */
291 int _cvtlen; /* should be size_t */
294 struct _rand48 *_r48;
295 struct __tm *_localtime_buf;
299 void (**(_sig_func))(int);
302 struct _atexit _atexit;
304 struct _glue __sglue; /* root of glue chain */
305 struct __sFILE *__sf; /* file descriptors */
306 struct __sFILE_fake __sf_fake; /* fake initial stdin/out/err */
307 struct _misc_reent *_misc; /* strtok, multibyte states */
310 #define _REENT_INIT(var) \
311 { (struct __sFILE *)&var.__sf_fake, (struct __sFILE *)&var.__sf_fake, \
312 (struct __sFILE *)&var.__sf_fake, 0, 0, _NULL, 0, 0, \
313 "C", _NULL, _NULL, 0, 0, _NULL, _NULL, _NULL, _NULL, _NULL, \
314 { 0, _NULL, _NULL, 0 }, { _NULL, 0, _NULL }, _NULL, 0, _NULL }
316 #define _REENT_INIT_PTR(var) \
317 { var->_stdin = (struct __sFILE *)&var->__sf_fake; \
318 var->_stdout = (struct __sFILE *)&var->__sf_fake; \
319 var->_stderr = (struct __sFILE *)&var->__sf_fake; \
322 var->_emergency = _NULL; \
323 var->__sdidinit = 0; \
324 var->_current_category = 0; \
325 var->_current_locale = "C"; \
327 var->__cleanup = _NULL; \
328 var->_gamma_signgam = 0; \
330 var->_cvtbuf = _NULL; \
332 var->_localtime_buf = _NULL; \
333 var->_asctime_buf = _NULL; \
334 var->_sig_func = _NULL; \
335 var->_atexit._ind = 0; \
336 var->_atexit._fns[0] = _NULL; \
337 var->_atexit._fnargs[0] = _NULL; \
338 var->_atexit._fntypes = 0; \
339 var->__sglue._next = _NULL; \
340 var->__sglue._niobs = 0; \
341 var->__sglue._iobs = _NULL; \
343 var->_misc = _NULL; \
344 var->__sf_fake._p = _NULL; \
345 var->__sf_fake._r = 0; \
346 var->__sf_fake._w = 0; \
347 var->__sf_fake._flags = 0; \
348 var->__sf_fake._file = 0; \
349 var->__sf_fake._lbfsize = 0; \
350 var->__sf_fake._data = _NULL; \
354 void (**(_sig_func))(int);
355 /* Only built the assert() calls if we are built with debugging. */
359 #define assert(x) ((void)0)
362 /* Generic _REENT check macro. */
363 #define _REENT_CHECK(var, what, type, size, init) do { \
364 struct _reent *_r = (var); \
365 if (_r->what == NULL) { \
366 _r->what = (type)malloc(size); \
372 #define _REENT_CHECK_TM(var) \
373 _REENT_CHECK(var, _localtime_buf, struct __tm *, sizeof *((var)->_localtime_buf), \
376 #define _REENT_CHECK_ASCTIME_BUF(var) \
377 _REENT_CHECK(var, _asctime_buf, char *, _REENT_ASCTIME_SIZE, \
378 memset((var)->_asctime_buf, 0, _REENT_ASCTIME_SIZE))
380 /* Handle the dynamically allocated rand48 structure. */
381 #define _REENT_INIT_RAND48(var) do { \
382 struct _reent *_r = (var); \
383 _r->_r48->_seed[0] = _RAND48_SEED_0; \
384 _r->_r48->_seed[1] = _RAND48_SEED_1; \
385 _r->_r48->_seed[2] = _RAND48_SEED_2; \
386 _r->_r48->_mult[0] = _RAND48_MULT_0; \
387 _r->_r48->_mult[1] = _RAND48_MULT_1; \
388 _r->_r48->_mult[2] = _RAND48_MULT_2; \
389 _r->_r48->_add = _RAND48_ADD; \
391 #define _REENT_CHECK_RAND48(var) \
392 _REENT_CHECK(var, _r48, struct _rand48 *, sizeof *((var)->_r48), _REENT_INIT_RAND48((var)))
394 #define _REENT_INIT_MP(var) do { \
395 struct _reent *_r = (var); \
396 _r->_mp->_result_k = 0; \
397 _r->_mp->_result = _r->_mp->_p5s = _NULL; \
398 _r->_mp->_freelist = _NULL; \
400 #define _REENT_CHECK_MP(var) \
401 _REENT_CHECK(var, _mp, struct _mprec *, sizeof *((var)->_mp), _REENT_INIT_MP(var))
403 #define _REENT_CHECK_EMERGENCY(var) \
404 _REENT_CHECK(var, _emergency, char *, _REENT_EMERGENCY_SIZE, /* nothing */)
406 #define _REENT_INIT_MISC(var) do { \
407 struct _reent *_r = (var); \
408 _r->_misc->_strtok_last = _NULL; \
409 _r->_misc->_mblen_state = 0; \
410 _r->_misc->_wctomb_state = 0; \
411 _r->_misc->_mbtowc_state = 0; \
412 _r->_misc->_l64a_buf[0] = '\0'; \
414 #define _REENT_CHECK_MISC(var) \
415 _REENT_CHECK(var, _misc, struct _misc_reent *, sizeof *((var)->_misc), _REENT_INIT_MISC(var))
417 #define _REENT_SIGNGAM(ptr) ((ptr)->_gamma_signgam)
418 #define _REENT_RAND_NEXT(ptr) ((ptr)->_r48->_rand_next)
419 #define _REENT_RAND48_SEED(ptr) ((ptr)->_r48->_seed)
420 #define _REENT_RAND48_MULT(ptr) ((ptr)->_r48->_mult)
421 #define _REENT_RAND48_ADD(ptr) ((ptr)->_r48->_add)
422 #define _REENT_MP_RESULT(ptr) ((ptr)->_mp->_result)
423 #define _REENT_MP_RESULT_K(ptr) ((ptr)->_mp->_result_k)
424 #define _REENT_MP_P5S(ptr) ((ptr)->_mp->_p5s)
425 #define _REENT_MP_FREELIST(ptr) ((ptr)->_mp->_freelist)
426 #define _REENT_ASCTIME_BUF(ptr) ((ptr)->_asctime_buf)
427 #define _REENT_TM(ptr) ((ptr)->_localtime_buf)
428 #define _REENT_EMERGENCY(ptr) ((ptr)->_emergency)
429 #define _REENT_STRTOK_LAST(ptr) ((ptr)->_misc->_strtok_last)
430 #define _REENT_MBLEN_STATE(ptr) ((ptr)->_misc->_mblen_state)
431 #define _REENT_MBTOWC_STATE(ptr)((ptr)->_misc->_mbtowc_state)
432 #define _REENT_WCTOMB_STATE(ptr)((ptr)->_misc->_wctomb_state)
433 #define _REENT_L64A_BUF(ptr) ((ptr)->_misc->_l64a_buf)
435 #else /* !_REENT_SMALL */
439 int _errno; /* local copy of errno */
441 /* FILE is a big struct and may change over time. To try to achieve binary
442 compatibility with future versions, put stdin,stdout,stderr here.
443 These are pointers into member __sf defined below. */
444 struct __sFILE *_stdin, *_stdout, *_stderr;
446 int _inc; /* used by tmpnam */
447 char _emergency[_REENT_EMERGENCY_SIZE];
449 int _current_category; /* used by setlocale */
450 _CONST char *_current_locale;
452 int __sdidinit; /* 1 means stdio has been init'd */
454 void _EXFUN((*__cleanup),(struct _reent *));
456 /* used by mprec routines */
457 struct _Bigint *_result;
459 struct _Bigint *_p5s;
460 struct _Bigint **_freelist;
462 /* used by some fp conversion routines */
463 int _cvtlen; /* should be size_t */
470 unsigned int _unused_rand;
472 char _asctime_buf[26];
473 struct __tm _localtime_buf;
475 __extension__ unsigned long long _rand_next;
482 /* Two next two fields were once used by malloc. They are no longer
483 used. They are used to preserve the space used before so as to
484 allow addition of new reent fields and keep binary compatibility. */
488 unsigned char * _nextf[_N_LISTS];
489 unsigned int _nmalloc[_N_LISTS];
494 struct _atexit *_atexit; /* points to head of LIFO stack */
495 struct _atexit _atexit0; /* one guaranteed table, required by ANSI */
498 void (**(_sig_func))(int);
500 /* These are here last so that __sFILE can grow without changing the offsets
501 of the above members (on the off chance that future binary compatibility
502 would be broken otherwise). */
503 struct _glue __sglue; /* root of glue chain */
504 struct __sFILE __sf[3]; /* first three file descriptors */
507 #define _REENT_INIT(var) \
508 { 0, &var.__sf[0], &var.__sf[1], &var.__sf[2], 0, "", 0, "C", \
509 0, _NULL, _NULL, 0, _NULL, _NULL, 0, _NULL, { {0, _NULL, "", \
510 { 0,0,0,0,0,0,0,0}, 0, 1, \
511 {{_RAND48_SEED_0, _RAND48_SEED_1, _RAND48_SEED_2}, \
512 {_RAND48_MULT_0, _RAND48_MULT_1, _RAND48_MULT_2}, _RAND48_ADD}, \
515 #define _REENT_INIT_PTR(var) \
519 var->_stdin = &var->__sf[0]; \
520 var->_stdout = &var->__sf[1]; \
521 var->_stderr = &var->__sf[2]; \
523 for (i = 0; i < _REENT_EMERGENCY_SIZE; ++i) \
524 var->_emergency[i] = 0; \
525 var->_current_category = 0; \
526 var->_current_locale = "C"; \
527 var->__sdidinit = 0; \
528 var->__cleanup = _NULL; \
529 var->_result = _NULL; \
530 var->_result_k = 0; \
532 var->_freelist = _NULL; \
534 var->_cvtbuf = _NULL; \
535 var->_new._reent._unused_rand = 0; \
536 var->_new._reent._strtok_last = _NULL; \
537 var->_new._reent._asctime_buf[0] = 0; \
538 tmp_ptr = (char *)&var->_new._reent._localtime_buf; \
539 for (i = 0; i < sizeof(struct __tm); ++i) \
541 var->_new._reent._gamma_signgam = 0; \
542 var->_new._reent._rand_next = 1; \
543 var->_new._reent._r48._seed[0] = _RAND48_SEED_0; \
544 var->_new._reent._r48._seed[1] = _RAND48_SEED_1; \
545 var->_new._reent._r48._seed[2] = _RAND48_SEED_2; \
546 var->_new._reent._r48._mult[0] = _RAND48_MULT_0; \
547 var->_new._reent._r48._mult[1] = _RAND48_MULT_1; \
548 var->_new._reent._r48._mult[2] = _RAND48_MULT_2; \
549 var->_new._reent._r48._add = _RAND48_ADD; \
550 var->_new._reent._mblen_state = 0; \
551 var->_new._reent._mbtowc_state = 0; \
552 var->_new._reent._wctomb_state = 0; \
553 var->_new._reent._l64a_buf[0] = '\0'; \
554 var->_atexit = _NULL; \
555 var->_atexit0._ind = 0; \
556 var->_atexit0._fns[0] = _NULL; \
557 var->_atexit0._fntypes = 0; \
558 var->_sig_func = _NULL; \
559 var->__sglue._next = _NULL; \
560 var->__sglue._niobs = 0; \
561 var->__sglue._iobs = _NULL; \
562 memset(var->__sf,0,sizeof(var->__sf)); \
565 #define _REENT_CHECK_RAND48(ptr) /* nothing */
566 #define _REENT_CHECK_MP(ptr) /* nothing */
567 #define _REENT_CHECK_TM(ptr) /* nothing */
568 #define _REENT_CHECK_ASCTIME_BUF(ptr) /* nothing */
569 #define _REENT_CHECK_EMERGENCY(ptr) /* nothing */
570 #define _REENT_CHECK_MISC(ptr) /* nothing */
572 #define _REENT_SIGNGAM(ptr) ((ptr)->_new._reent._gamma_signgam)
573 #define _REENT_RAND_NEXT(ptr) ((ptr)->_new._reent._rand_next)
574 #define _REENT_RAND48_SEED(ptr) ((ptr)->_new._reent._r48._seed)
575 #define _REENT_RAND48_MULT(ptr) ((ptr)->_new._reent._r48._mult)
576 #define _REENT_RAND48_ADD(ptr) ((ptr)->_new._reent._r48._add)
577 #define _REENT_MP_RESULT(ptr) ((ptr)->_result)
578 #define _REENT_MP_RESULT_K(ptr) ((ptr)->_result_k)
579 #define _REENT_MP_P5S(ptr) ((ptr)->_p5s)
580 #define _REENT_MP_FREELIST(ptr) ((ptr)->_freelist)
581 #define _REENT_ASCTIME_BUF(ptr) (&(ptr)->_new._reent._asctime_buf)
582 #define _REENT_TM(ptr) (&(ptr)->_new._reent._localtime_buf)
583 #define _REENT_EMERGENCY(ptr) ((ptr)->_emergency)
584 #define _REENT_STRTOK_LAST(ptr) ((ptr)->_new._reent._strtok_last)
585 #define _REENT_MBLEN_STATE(ptr) ((ptr)->_new._reent._mblen_state)
586 #define _REENT_MBTOWC_STATE(ptr)((ptr)->_new._reent._mbtowc_state)
587 #define _REENT_WCTOMB_STATE(ptr)((ptr)->_new._reent._wctomb_state)
588 #define _REENT_L64A_BUF(ptr) ((ptr)->_new._reent._l64a_buf)
590 #endif /* !_REENT_SMALL */
595 * All references to struct _reent are via this pointer.
596 * Internally, newlib routines that need to reference it should use _REENT.
599 #ifndef __ATTRIBUTE_IMPURE_PTR__
600 #define __ATTRIBUTE_IMPURE_PTR__
603 extern struct _reent *_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
605 void _reclaim_reent _PARAMS ((struct _reent *));
607 /* #define _REENT_ONLY define this to get only reentrant routines */
610 #define _REENT _impure_ptr
611 #endif /* !_REENT_ONLY */
616 #endif /* _SYS_REENT_H_ */