xref: /titanic_41/usr/src/lib/libast/common/include/sfio.h (revision 0a05e7057ae5537db2da83492d375e6524599463)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #ifndef _SFIO_H
23 #define _SFIO_H	1
24 
25 #define SFIO_VERSION	20050202L
26 
27 /*	Public header file for the sfio library
28 **
29 **	Written by Kiem-Phong Vo
30 */
31 
32 typedef struct _sfio_s		Sfio_t;
33 typedef struct _sfdisc_s	Sfdisc_t;
34 
35 #if defined(_AST_STD_H) || defined(_PACKAGE_ast) && defined(_SFIO_PRIVATE)
36 #include	<ast_std.h>
37 #else
38 #include	<ast_common.h>
39 #endif /* _PACKAGE_ast */
40 
41 /* Sfoff_t should be large enough for largest file address */
42 #define Sfoff_t		intmax_t
43 #define Sflong_t	intmax_t
44 #define Sfulong_t	uintmax_t
45 #define Sfdouble_t	_ast_fltmax_t
46 
47 typedef ssize_t		(*Sfread_f)_ARG_((Sfio_t*, Void_t*, size_t, Sfdisc_t*));
48 typedef ssize_t		(*Sfwrite_f)_ARG_((Sfio_t*, const Void_t*, size_t, Sfdisc_t*));
49 typedef Sfoff_t		(*Sfseek_f)_ARG_((Sfio_t*, Sfoff_t, int, Sfdisc_t*));
50 typedef int		(*Sfexcept_f)_ARG_((Sfio_t*, int, Void_t*, Sfdisc_t*));
51 
52 /* discipline structure */
53 struct _sfdisc_s
54 {	Sfread_f	readf;		/* read function		*/
55 	Sfwrite_f	writef;		/* write function		*/
56 	Sfseek_f	seekf;		/* seek function		*/
57 	Sfexcept_f	exceptf;	/* to handle exceptions		*/
58 	Sfdisc_t*	disc;		/* the continuing discipline	*/
59 };
60 
61 #include <sfio_s.h>
62 
63 /* formatting environment */
64 typedef struct _sffmt_s	Sffmt_t;
65 typedef int		(*Sffmtext_f)_ARG_((Sfio_t*, Void_t*, Sffmt_t*));
66 typedef int		(*Sffmtevent_f)_ARG_((Sfio_t*, int, Void_t*, Sffmt_t*));
67 struct _sffmt_s
68 {	long		version;/* version of this structure		*/
69 	Sffmtext_f	extf;	/* function to process arguments	*/
70 	Sffmtevent_f	eventf;	/* process events			*/
71 
72 	char*		form;	/* format string to stack		*/
73 	va_list	args;	/* corresponding arg list		*/
74 
75 	int		fmt;	/* format character			*/
76 	ssize_t		size;	/* object size				*/
77 	int		flags;	/* formatting flags			*/
78 	int		width;	/* width of field			*/
79 	int		precis;	/* precision required			*/
80 	int		base;	/* conversion base			*/
81 
82 	char*		t_str;	/* type string 				*/
83 	ssize_t		n_str;	/* length of t_str 			*/
84 
85 	Void_t*		mbs;	/* multibyte state for format string	*/
86 
87 	Void_t*		none;	/* unused for now			*/
88 };
89 #define sffmtversion(fe,type) \
90 		((type) ? ((fe)->version = SFIO_VERSION) : (fe)->version)
91 
92 #define SFFMT_SSHORT	000000010 /* 'hh' flag, char			*/
93 #define SFFMT_TFLAG	000000020 /* 't' flag, ptrdiff_t			*/
94 #define SFFMT_ZFLAG	000000040 /* 'z' flag, size_t			*/
95 
96 #define SFFMT_LEFT	000000100 /* left-justification			*/
97 #define SFFMT_SIGN	000000200 /* must have a sign			*/
98 #define SFFMT_BLANK	000000400 /* if not signed, prepend a blank	*/
99 #define SFFMT_ZERO	000001000 /* zero-padding on the left		*/
100 #define SFFMT_ALTER	000002000 /* alternate formatting		*/
101 #define SFFMT_THOUSAND	000004000 /* thousand grouping			*/
102 #define SFFMT_SKIP	000010000 /* skip assignment in scanf()		*/
103 #define SFFMT_SHORT	000020000 /* 'h' flag				*/
104 #define SFFMT_LONG	000040000 /* 'l' flag				*/
105 #define SFFMT_LLONG	000100000 /* 'll' flag				*/
106 #define SFFMT_LDOUBLE	000200000 /* 'L' flag				*/
107 #define SFFMT_VALUE	000400000 /* value is returned			*/
108 #define SFFMT_ARGPOS	001000000 /* getting arg for $ patterns		*/
109 #define SFFMT_IFLAG	002000000 /* 'I' flag				*/
110 #define SFFMT_JFLAG	004000000 /* 'j' flag, intmax_t			*/
111 #define SFFMT_CENTER	010000000 /* '=' flag, center justification	*/
112 #define SFFMT_SET	017777770 /* flags settable on calling extf	*/
113 
114 /* for sfmutex() call */
115 #define SFMTX_LOCK	0	/* up mutex count			*/
116 #define SFMTX_TRYLOCK	1	/* try to up mutex count		*/
117 #define SFMTX_UNLOCK	2	/* down mutex count			*/
118 #define SFMTX_CLRLOCK	3	/* clear mutex count			*/
119 
120 /* various constants */
121 #ifndef NULL
122 #define NULL		0
123 #endif
124 #ifndef EOF
125 #define EOF		(-1)
126 #endif
127 #ifndef SEEK_SET
128 #define SEEK_SET	0
129 #define SEEK_CUR	1
130 #define SEEK_END	2
131 #endif
132 
133 /* bits for various types of files */
134 #define	SF_READ		0000001	/* open for reading			*/
135 #define SF_WRITE	0000002	/* open for writing			*/
136 #define SF_STRING	0000004	/* a string stream			*/
137 #define SF_APPENDWR	0000010	/* file is in append mode only		*/
138 #define SF_MALLOC	0000020	/* buffer is malloc-ed			*/
139 #define SF_LINE		0000040	/* line buffering			*/
140 #define SF_SHARE	0000100	/* stream with shared file descriptor 	*/
141 #define SF_EOF		0000200	/* eof was detected			*/
142 #define SF_ERROR	0000400	/* an error happened			*/
143 #define SF_STATIC	0001000	/* a stream that cannot be freed	*/
144 #define SF_IOCHECK	0002000	/* call exceptf before doing IO		*/
145 #define SF_PUBLIC	0004000	/* SF_SHARE and follow physical seek	*/
146 #define SF_MTSAFE	0010000	/* need thread safety			*/
147 #define SF_WHOLE	0020000	/* preserve wholeness of sfwrite/sfputr */
148 #define SF_IOINTR	0040000	/* return on interrupts			*/
149 #define SF_WCWIDTH	0100000	/* wcwidth display stream		*/
150 
151 #define SF_FLAGS	0177177	/* PUBLIC FLAGS PASSABLE TO SFNEW()	*/
152 #define SF_SETS		0177163	/* flags passable to sfset()		*/
153 
154 #ifndef _SF_NO_OBSOLETE
155 #define SF_BUFCONST	0400000 /* unused flag - for compatibility only	*/
156 #endif
157 
158 /* for sfgetr/sfreserve to hold a record */
159 #define SF_LOCKR	0000010	/* lock record, stop access to stream	*/
160 #define SF_LASTR	0000020	/* get the last incomplete record	*/
161 
162 /* exception events: SF_NEW(0), SF_READ(1), SF_WRITE(2) and the below 	*/
163 #define SF_SEEK		3	/* seek error				*/
164 #define SF_CLOSING	4	/* when stream is about to be closed	*/
165 #define SF_DPUSH	5	/* when discipline is being pushed	*/
166 #define SF_DPOP		6	/* when discipline is being popped	*/
167 #define SF_DPOLL	7	/* see if stream is ready for I/O	*/
168 #define SF_DBUFFER	8	/* buffer not empty during push or pop	*/
169 #define SF_SYNC		9	/* announcing start/end synchronization */
170 #define SF_PURGE	10	/* a sfpurge() call was issued		*/
171 #define SF_FINAL	11	/* closing is done except stream free	*/
172 #define SF_READY	12	/* a polled stream is ready		*/
173 #define SF_LOCKED	13	/* stream is in a locked state		*/
174 #define SF_ATEXIT	14	/* process is exiting			*/
175 #define SF_EVENT	100	/* start of user-defined events		*/
176 
177 /* for stack and disciplines */
178 #define SF_POPSTACK	((Sfio_t*)0)	/* pop the stream stack		*/
179 #define SF_POPDISC	((Sfdisc_t*)0)	/* pop the discipline stack	*/
180 
181 /* for the notify function and discipline exception */
182 #define SF_NEW		0	/* new stream				*/
183 #define SF_SETFD	(-1)	/* about to set the file descriptor 	*/
184 
185 #define SF_BUFSIZE	8192	/* default buffer size			*/
186 #define SF_UNBOUND	(-1)	/* unbounded buffer size		*/
187 
188 /* namespace incursion workarounds -- migrate to the new names */
189 #if !_mac_SF_APPEND
190 #define SF_APPEND	SF_APPENDWR	/* BSDI sys/stat.h		*/
191 #endif
192 #if !_mac_SF_CLOSE
193 #define SF_CLOSE	SF_CLOSING	/* AIX sys/socket.h		*/
194 #endif
195 
196 _BEGIN_EXTERNS_
197 
198 /* standard in/out/err streams */
199 
200 #if _BLD_sfio && defined(__EXPORT__)
201 #define extern		extern __EXPORT__
202 #endif
203 #if !_BLD_sfio && defined(__IMPORT__)
204 #define extern		extern __IMPORT__
205 #endif
206 
207 extern ssize_t		_Sfi;
208 extern ssize_t		_Sfmaxr;
209 
210 extern Sfio_t*		sfstdin;
211 extern Sfio_t*		sfstdout;
212 extern Sfio_t*		sfstderr;
213 
214 #if _UWIN
215 #undef	extern
216 #endif
217 
218 extern Sfio_t		_Sfstdin;
219 extern Sfio_t		_Sfstdout;
220 extern Sfio_t		_Sfstderr;
221 
222 #undef	extern
223 
224 #if _BLD_sfio && defined(__EXPORT__)
225 #define extern	__EXPORT__
226 #endif
227 
228 extern Sfio_t*		sfnew _ARG_((Sfio_t*, Void_t*, size_t, int, int));
229 extern Sfio_t*		sfopen _ARG_((Sfio_t*, const char*, const char*));
230 extern Sfio_t*		sfpopen _ARG_((Sfio_t*, const char*, const char*));
231 extern Sfio_t*		sfstack _ARG_((Sfio_t*, Sfio_t*));
232 extern Sfio_t*		sfswap _ARG_((Sfio_t*, Sfio_t*));
233 extern Sfio_t*		sftmp _ARG_((size_t));
234 extern int		sfpurge _ARG_((Sfio_t*));
235 extern int		sfpoll _ARG_((Sfio_t**, int, int));
236 extern Void_t*		sfreserve _ARG_((Sfio_t*, ssize_t, int));
237 extern int		sfresize _ARG_((Sfio_t*, Sfoff_t));
238 extern int		sfsync _ARG_((Sfio_t*));
239 extern int		sfclrlock _ARG_((Sfio_t*));
240 extern Void_t*		sfsetbuf _ARG_((Sfio_t*, Void_t*, size_t));
241 extern Sfdisc_t*	sfdisc _ARG_((Sfio_t*,Sfdisc_t*));
242 extern int		sfraise _ARG_((Sfio_t*, int, Void_t*));
243 extern int		sfnotify _ARG_((void(*)(Sfio_t*, int, int)));
244 extern int		sfset _ARG_((Sfio_t*, int, int));
245 extern int		sfsetfd _ARG_((Sfio_t*, int));
246 extern Sfio_t*		sfpool _ARG_((Sfio_t*, Sfio_t*, int));
247 extern ssize_t		sfread _ARG_((Sfio_t*, Void_t*, size_t));
248 extern ssize_t		sfwrite _ARG_((Sfio_t*, const Void_t*, size_t));
249 extern Sfoff_t		sfmove _ARG_((Sfio_t*, Sfio_t*, Sfoff_t, int));
250 extern int		sfclose _ARG_((Sfio_t*));
251 extern Sfoff_t		sftell _ARG_((Sfio_t*));
252 extern Sfoff_t		sfseek _ARG_((Sfio_t*, Sfoff_t, int));
253 extern ssize_t		sfputr _ARG_((Sfio_t*, const char*, int));
254 extern char*		sfgetr _ARG_((Sfio_t*, int, int));
255 extern ssize_t		sfnputc _ARG_((Sfio_t*, int, size_t));
256 extern int		sfungetc _ARG_((Sfio_t*, int));
257 extern int		sfprintf _ARG_((Sfio_t*, const char*, ...));
258 extern char*		sfprints _ARG_((const char*, ...));
259 extern ssize_t		sfsprintf _ARG_((char*, size_t, const char*, ...));
260 extern ssize_t		sfvsprintf _ARG_((char*, size_t, const char*, va_list));
261 extern int		sfvprintf _ARG_((Sfio_t*, const char*, va_list));
262 extern int		sfscanf _ARG_((Sfio_t*, const char*, ...));
263 extern int		sfsscanf _ARG_((const char*, const char*, ...));
264 extern int		sfvsscanf _ARG_((const char*, const char*, va_list));
265 extern int		sfvscanf _ARG_((Sfio_t*, const char*, va_list));
266 
267 /* mutex locking for thread-safety */
268 extern int		sfmutex _ARG_((Sfio_t*, int));
269 
270 /* io functions with discipline continuation */
271 extern ssize_t		sfrd _ARG_((Sfio_t*, Void_t*, size_t, Sfdisc_t*));
272 extern ssize_t		sfwr _ARG_((Sfio_t*, const Void_t*, size_t, Sfdisc_t*));
273 extern Sfoff_t		sfsk _ARG_((Sfio_t*, Sfoff_t, int, Sfdisc_t*));
274 extern ssize_t		sfpkrd _ARG_((int, Void_t*, size_t, int, long, int));
275 
276 /* portable handling of primitive types */
277 extern int		sfdlen _ARG_((Sfdouble_t));
278 extern int		sfllen _ARG_((Sflong_t));
279 extern int		sfulen _ARG_((Sfulong_t));
280 
281 extern int		sfputd _ARG_((Sfio_t*, Sfdouble_t));
282 extern int		sfputl _ARG_((Sfio_t*, Sflong_t));
283 extern int		sfputu _ARG_((Sfio_t*, Sfulong_t));
284 extern int		sfputm _ARG_((Sfio_t*, Sfulong_t, Sfulong_t));
285 extern int		sfputc _ARG_((Sfio_t*, int));
286 
287 extern Sfdouble_t	sfgetd _ARG_((Sfio_t*));
288 extern Sflong_t		sfgetl _ARG_((Sfio_t*));
289 extern Sfulong_t	sfgetu _ARG_((Sfio_t*));
290 extern Sfulong_t	sfgetm _ARG_((Sfio_t*, Sfulong_t));
291 extern int		sfgetc _ARG_((Sfio_t*));
292 
293 extern int		_sfputd _ARG_((Sfio_t*, Sfdouble_t));
294 extern int		_sfputl _ARG_((Sfio_t*, Sflong_t));
295 extern int		_sfputu _ARG_((Sfio_t*, Sfulong_t));
296 extern int		_sfputm _ARG_((Sfio_t*, Sfulong_t, Sfulong_t));
297 extern int		_sfflsbuf _ARG_((Sfio_t*, int));
298 
299 extern int		_sffilbuf _ARG_((Sfio_t*, int));
300 
301 extern int		_sfdlen _ARG_((Sfdouble_t));
302 extern int		_sfllen _ARG_((Sflong_t));
303 extern int		_sfulen _ARG_((Sfulong_t));
304 
305 /* miscellaneous function analogues of fast in-line functions */
306 extern Sfoff_t		sfsize _ARG_((Sfio_t*));
307 extern int		sfclrerr _ARG_((Sfio_t*));
308 extern int		sfeof _ARG_((Sfio_t*));
309 extern int		sferror _ARG_((Sfio_t*));
310 extern int		sffileno _ARG_((Sfio_t*));
311 extern int		sfstacked _ARG_((Sfio_t*));
312 extern ssize_t		sfvalue _ARG_((Sfio_t*));
313 extern ssize_t		sfslen _ARG_((void));
314 extern ssize_t		sfmaxr _ARG_((ssize_t, int));
315 
316 #undef extern
317 _END_EXTERNS_
318 
319 /* coding long integers in a portable and compact fashion */
320 #define SF_SBITS	6
321 #define SF_UBITS	7
322 #define SF_BBITS	8
323 #define SF_SIGN		(1 << SF_SBITS)
324 #define SF_MORE		(1 << SF_UBITS)
325 #define SF_BYTE		(1 << SF_BBITS)
326 #define SF_U1		SF_MORE
327 #define SF_U2		(SF_U1*SF_U1)
328 #define SF_U3		(SF_U2*SF_U1)
329 #define SF_U4		(SF_U3*SF_U1)
330 
331 #if __cplusplus
332 #define _SF_(f)		(f)
333 #else
334 #define _SF_(f)		((Sfio_t*)(f))
335 #endif
336 
337 #define __sf_putd(f,v)		(_sfputd(_SF_(f),(Sfdouble_t)(v)))
338 #define __sf_putl(f,v)		(_sfputl(_SF_(f),(Sflong_t)(v)))
339 #define __sf_putu(f,v)		(_sfputu(_SF_(f),(Sfulong_t)(v)))
340 #define __sf_putm(f,v,m)	(_sfputm(_SF_(f),(Sfulong_t)(v),(Sfulong_t)(m)))
341 
342 #define __sf_putc(f,c)	(_SF_(f)->_next >= _SF_(f)->_endw ? \
343 			 _sfflsbuf(_SF_(f),(int)((unsigned char)(c))) : \
344 			 (int)(*_SF_(f)->_next++ = (unsigned char)(c)) )
345 #define __sf_getc(f)	(_SF_(f)->_next >= _SF_(f)->_endr ? _sffilbuf(_SF_(f),0) : \
346 			 (int)(*_SF_(f)->_next++) )
347 
348 #define __sf_dlen(v)	(_sfdlen((Sfdouble_t)(v)) )
349 #define __sf_llen(v)	(_sfllen((Sflong_t)(v)) )
350 #define __sf_ulen(v)	((Sfulong_t)(v) < SF_U1 ? 1 : (Sfulong_t)(v) < SF_U2 ? 2 : \
351 			 (Sfulong_t)(v) < SF_U3 ? 3 : (Sfulong_t)(v) < SF_U4 ? 4 : 5)
352 
353 #define __sf_fileno(f)	(_SF_(f)->_file)
354 #define __sf_eof(f)	(_SF_(f)->_flags&SF_EOF)
355 #define __sf_error(f)	(_SF_(f)->_flags&SF_ERROR)
356 #define __sf_clrerr(f)	(_SF_(f)->_flags &= ~(SF_ERROR|SF_EOF))
357 #define __sf_stacked(f)	(_SF_(f)->_push != (Sfio_t*)0)
358 #define __sf_value(f)	(_SF_(f)->_val)
359 #define __sf_slen()	(_Sfi)
360 #define __sf_maxr(n,s)	((s)?((_Sfi=_Sfmaxr),(_Sfmaxr=(n)),_Sfi):_Sfmaxr)
361 
362 #if defined(__INLINE__) && !_BLD_sfio
363 
364 __INLINE__ int sfputd(Sfio_t* f, Sfdouble_t v)	{ return __sf_putd(f,v); }
365 __INLINE__ int sfputl(Sfio_t* f, Sflong_t v)	{ return __sf_putl(f,v); }
366 __INLINE__ int sfputu(Sfio_t* f, Sfulong_t v)	{ return __sf_putu(f,v); }
367 __INLINE__ int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t m)
368 						{ return __sf_putm(f,v,m); }
369 
370 __INLINE__ int sfputc(Sfio_t* f, int c)		{ return __sf_putc(f,c); }
371 __INLINE__ int sfgetc(Sfio_t* f)		{ return __sf_getc(f); }
372 
373 __INLINE__ int sfdlen(Sfdouble_t v)		{ return __sf_dlen(v); }
374 __INLINE__ int sfllen(Sflong_t v)		{ return __sf_llen(v); }
375 __INLINE__ int sfulen(Sfulong_t v)		{ return __sf_ulen(v); }
376 
377 __INLINE__ int sffileno(Sfio_t* f)		{ return __sf_fileno(f); }
378 __INLINE__ int sfeof(Sfio_t* f)			{ return __sf_eof(f); }
379 __INLINE__ int sferror(Sfio_t* f)		{ return __sf_error(f); }
380 __INLINE__ int sfclrerr(Sfio_t* f)		{ return __sf_clrerr(f); }
381 __INLINE__ int sfstacked(Sfio_t* f)		{ return __sf_stacked(f); }
382 __INLINE__ ssize_t sfvalue(Sfio_t* f)		{ return __sf_value(f); }
383 __INLINE__ ssize_t sfslen()			{ return __sf_slen(); }
384 __INLINE__ ssize_t sfmaxr(ssize_t n, int s)	{ return __sf_maxr(n,s); }
385 
386 #else
387 
388 #define sfputd(f,v)				( __sf_putd((f),(v)) )
389 #define sfputl(f,v)				( __sf_putl((f),(v)) )
390 #define sfputu(f,v)				( __sf_putu((f),(v)) )
391 #define sfputm(f,v,m)				( __sf_putm((f),(v),(m)) )
392 
393 #define sfputc(f,c)				( __sf_putc((f),(c)) )
394 #define sfgetc(f)				( __sf_getc(f) )
395 
396 #define sfdlen(v)				( __sf_dlen(v) )
397 #define sfllen(v)				( __sf_llen(v) )
398 #define sfulen(v)				( __sf_ulen(v) )
399 
400 #define sffileno(f)				( __sf_fileno(f) )
401 #define sfeof(f)				( __sf_eof(f) )
402 #define sferror(f)				( __sf_error(f) )
403 #define sfclrerr(f)				( __sf_clrerr(f) )
404 #define sfstacked(f)				( __sf_stacked(f) )
405 #define sfvalue(f)				( __sf_value(f) )
406 #define sfslen()				( __sf_slen() )
407 #define sfmaxr(n,s)				( __sf_maxr(n,s) )
408 
409 #endif /*__INLINE__*/
410 
411 #ifndef _SFSTR_H /* GSF's string manipulation stuff */
412 #define _SFSTR_H		1
413 
414 #define sfstropen()		sfnew(0, 0, -1, -1, SF_READ|SF_WRITE|SF_STRING)
415 #define sfstrclose(f)		sfclose(f)
416 
417 #define sfstrseek(f,p,m) \
418 	( (m) == SEEK_SET ? \
419 	 	(((p) < 0 || (p) > (f)->_size) ? (char*)0 : \
420 		 (char*)((f)->_next = (f)->_data+(p)) ) \
421 	: (m) == SEEK_CUR ? \
422 		((f)->_next += (p), \
423 		 (((f)->_next < (f)->_data || (f)->_next > (f)->_data+(f)->_size) ? \
424 			((f)->_next -= (p), (char*)0) : (char*)(f)->_next ) ) \
425 	: (m) == SEEK_END ? \
426 		( ((p) > 0 || (f)->_size+(p) < 0) ? (char*)0 : \
427 			(char*)((f)->_next = (f)->_data+(f)->_size+(p)) ) \
428 	: (char*)0 \
429 	)
430 
431 #define sfstrsize(f)		((f)->_size)
432 #define sfstrtell(f)		((f)->_next - (f)->_data)
433 #define sfstrpend(f)		((f)->_size - sfstrtell())
434 #define sfstrbase(f)		((char*)(f)->_data)
435 
436 #define sfstruse(f) \
437 	(sfputc((f),0) < 0 ? (char*)0 : (char*)((f)->_next = (f)->_data) \
438 	)
439 
440 #define sfstrrsrv(f,n) \
441 	(sfreserve((f),(n),SF_WRITE|SF_LOCKR), sfwrite((f),(f)->_next,0), \
442 	 ((f)->_next+(n) <= (f)->_data+(f)->_size ? (char*)(f)->_next : (char*)0) \
443 	)
444 
445 #define sfstrbuf(f,b,n,m) \
446 	(sfsetbuf((f),(b),(n)), ((f)->_flags |= (m) ? SF_MALLOC : 0), \
447 	 ((f)->_data == (unsigned char*)(b) ? 0 : -1) \
448 	)
449 
450 #endif /* _SFSTR_H */
451 
452 #endif /* _SFIO_H */
453