|
|
1.1 ! root 1: .TH SFIO 3 "21 August 1990" ! 2: .SH NAME ! 3: \fBsfio\fR \- safe/fast string/file input/output ! 4: .SH SYNOPSIS ! 5: .ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i ! 6: .PP ! 7: .nf ! 8: .ft 5 ! 9: #include <sfio.h> ! 10: ! 11: #define uchar unsigned char ! 12: #define uint unsigned int ! 13: #define ulong unsigned long ! 14: ! 15: Sfile_t* sfnew(Sfile_t* f, uchar* buf, int size, int fd, int flags); ! 16: Sfile_t* sfopen(Sfile_t* f, char* string, char* mode); ! 17: Sfile_t* sfdopen(int fd, char* mode); ! 18: Sfile_t* sfpopen(char* cmd, char* mode, Sfile_t** fcomp); ! 19: Sfile_t* sfstack(Sfile_t* base, Sfile_t* top); ! 20: Sfile_t* sfpushed(Sfile_t* f); ! 21: Sfile_t* sftmp(int size); ! 22: ! 23: int sfpool(Sfile_t* f, Sfile_t* poolf, int mode); ! 24: Sfdisc_t* sfsetdisc(Sfile_t* f, Sfdisc_t* disc); ! 25: ! 26: int sfclose(Sfile_t* f); ! 27: int sfsync(Sfile_t* f); ! 28: ! 29: int sfpeek(Sfile_t* f, uchar** bufp); ! 30: ! 31: int sfgetc(Sfile_t* f); ! 32: int sfungetc(Sfile_t* f, int c); ! 33: ulong sfgetu(Sfile_t* f); ! 34: long sfgetl(Sfile_t* f); ! 35: double sfgetd(Sfile_t* f); ! 36: char* sfgets(Sfile_t* f, char* buf, int size); ! 37: int sfread(Sfile_t* f, uchar* buf, int n); ! 38: int sfscanf(Sfile_t* f, char* format, ...); ! 39: int sfsscanf(char* s, char* format, ...); ! 40: int sfvscanf(Sfile_t* f, char* format, va_list args); ! 41: ! 42: int sfputc(Sfile_t* f, int c); ! 43: int sfnputc(Sfile_t* f, int c, int n); ! 44: int sfputu(Sfile_t* f, ulong v); ! 45: int sfputl(Sfile_t* f, long v); ! 46: int sfputd(Sfile_t* f, double v); ! 47: int sfputs(Sfile_t* f, char* s, int c); ! 48: int sfwrite(Sfile_t* f, uchar* buf, int n); ! 49: int sfmove(Sfile_t* fr, Sfile_t* fw, long n, char* seps); ! 50: int sfprintf(Sfile_t* f, char* format, ...); ! 51: int sfsprintf(char* s, int size, char* format, ...); ! 52: int sfvprintf(Sfile_t* f, char* format, va_list args); ! 53: ! 54: void sfnotice(void (*noticef)(Sfile_t* f, int type)); ! 55: int sfset(Sfile_t* f, int flags, int i); ! 56: uchar* sfsetbuf(Sfile_t* f, uchar* buf, int size); ! 57: int sffileno(Sfile_t* f); ! 58: int sfeof(Sfile_t* f); ! 59: int sferror(Sfile_t* f); ! 60: int sfclearerr(Sfile_t* f); ! 61: int sfclrlock(Sfile_t* f); ! 62: int sfslen(); ! 63: int sfulen(ulong v); ! 64: int sfllen(long v); ! 65: int sfdlen(double v); ! 66: ! 67: long sforigin(Sfile_t* f); ! 68: long sfseek(Sfile_t* f, long addr, int offset); ! 69: long sftell(Sfile_t* f); ! 70: ! 71: char* sfecvt(double v, int n, int* decpt, int* sign); ! 72: char* sffcvt(double v, int n, int* decpt, int* sign); ! 73: .fR ! 74: .fi ! 75: .SH DESCRIPTION ! 76: .PP ! 77: \fIsfio\fP is a library of functions to perform input/output on ! 78: objects called \fIsfio\fP streams. ! 79: Each \fIsfio\fP stream may correpond to some file descriptor (see \fIopen(2)\fP) ! 80: or some piece of primary memory. ! 81: A notion of stream stack is supported for ! 82: processing of data from complexes of streams. ! 83: Streams can be pooled so that their buffers can be synchronized ! 84: properly when switching streams for io. ! 85: It is also possible to change io disciplines by setting alternative ! 86: functions for read, write and seek. ! 87: .PP ! 88: A stream abstraction is represented by the type \f5Sfile_t\fP which ! 89: is defined in the header file \f5<sfio.h>\fP. A stream is locked while ! 90: it is being accessed by some \fIsfio\fP function. A locked stream ! 91: cannot be further accessed by operations that may change its internal states ! 92: (see \f5sfclrlock()\fP). Any such access fails and returns ! 93: an appropriate error code. ! 94: .PP ! 95: During an io request, if ! 96: a system call \f5read\fP or \f5write()\fP (or their ! 97: discipline counterparts) is interrupted, ! 98: unless a discipline function has been defined to process it, ! 99: the calling \fIsfio\fP function will resume the respective system call as necessary. ! 100: The interrupt condition is defined by \f5errno\ ==\ EINTR\fP (see \f5errno.h\fP). ! 101: To prevent infinite loops, this condition is always cleared before ! 102: the system call is resumed. ! 103: .PP ! 104: In general, \fIsfio\fP functions either return integer or pointer values. ! 105: In the event of an error, a function that returns integer value will ! 106: return \f5-1\fP while a function that returns a pointer value will return ! 107: \f5NULL\fP. ! 108: .PP ! 109: A number of bit flags define stream types and their operations. ! 110: Following are the flags: ! 111: .IP ! 112: \f5SF_READ\fP: ! 113: The stream is readable. ! 114: .IP ! 115: \f5SF_WRITE\fP: ! 116: The stream is writable. ! 117: .IP ! 118: \f5SF_STRING\fP: ! 119: The stream is a string (a byte array) that ! 120: is readable if \f5SF_READ\fP is specified or ! 121: writable if \f5SF_WRITE\fP is specified. ! 122: .IP ! 123: \f5SF_APPEND\fP: ! 124: The stream is a file opened for appending data. ! 125: This means that data written to the stream is always ! 126: appended at the end of the file. ! 127: On operating systems where there is no primitive to specify ! 128: at file opening time that a file is opened for append only, ! 129: \f5lseek()\fP (or its discipline replacement) will be used on ! 130: the file stream to approximate this behavior. ! 131: .IP ! 132: \f5SF_RELATIVE\fP: ! 133: If the stream corresponds to a file, ! 134: no seek is allowed backward beyond the starting point as defined ! 135: by \f5lseek(fd,0L,1)\fP (or its discipline replacement) ! 136: when the stream is initialized by \f5sfnew()\fP (below). ! 137: .IP ! 138: \f5SF_LINE\fP: ! 139: The stream is line-oriented. For write-streams, this means that the ! 140: buffer is flushed whenever a new-line character is output. ! 141: For read-streams, this means that \f5sfpeek()\fP (below) will return ! 142: a buffer of data which ends with a new-line. Note that the amount of ! 143: data that can be returned is limited by the buffer size. ! 144: .IP ! 145: \f5SF_KEEPFD\fP: ! 146: The file descriptor of the stream will be kept opened when the stream is closed. ! 147: .IP ! 148: \f5SF_MALLOC\fP: ! 149: To indicate that the stream buffer was obtained via \f5malloc()\fP ! 150: and can be reallocated or freed by the package. ! 151: .IP ! 152: \f5SF_REUSE\fP: ! 153: This flag can be set (\f5sfset()\fP so that when the stream is closed, ! 154: its data structure and associated information such as pool and discipline ! 155: is not destroyed. ! 156: It can also be used in a call to \f5sfnew()\fP (see below). ! 157: .IP ! 158: \f5SF_SHARE\fP: ! 159: This flag indicates that the associated stream is a file stream that may ! 160: be operated on by means beyond straightforward \fIsfio\fP usage (e.g., ! 161: by multiple processes). ! 162: In this case, each io system call (or its discipline replacement) will be ! 163: preceded by a \f5lseek()\fP (or its discipline replacement) to ensure that ! 164: the logical stream location corresponds to the physical file location. ! 165: .PP ! 166: \f5sfnew(f,buf,size,fd,flags)\fP ! 167: is the primitive for creating or renewing streams. ! 168: For file streams, a number of operations are performed to determine ! 169: seekability, optimal buffer sizes if not specified, etc. ! 170: Each stream has a origin. ! 171: The origin of a \f5SF_STRING\fP stream is always \f50L\fP. ! 172: If a file stream is not seekable, its origin is defined as \f5-1L\fP. ! 173: Otherwise, its origin is defined as either the current location or \f50L\fP ! 174: depending on whether or not the flag \f5SF_RELATIVE\fP is turned on. ! 175: \f5sfseek()\fP operations are relative to this location. ! 176: The argument \f5f\fP of \f5sfnew()\fP, if not \f5NULL\fP, is a stream to be modified. ! 177: If it is \f5NULL\fP, a new stream is created. ! 178: The argument \f5buf\fP, if not \f5NULL\fP, is a buffer to be used. ! 179: In this case, \f5size\fP should be positive. ! 180: If \f5size\fP is 0, the stream is unbuffered. ! 181: If \f5size\fP is negative, \fIsfio\fP will allocate a buffer. ! 182: The argument \f5fd\fP is a file descriptor (e.g., from \fIopen()\fP) ! 183: for io operations if the stream is not an \f5SF_STRING\fP stream. ! 184: The last argument \f5flags\fP is a bit vector composing from the flags described above. ! 185: The \f5SF_REUSE\fP flag, if given, indicates that the current attributes ! 186: of the stream \f5f\fP should be used instead of whatever else is defined by \f5flags\fP. ! 187: .PP ! 188: \f5sfopen(f,string,mode)\fP ! 189: is a high-level function based on \f5sfnew()\fP to create new streams from files ! 190: or strings. ! 191: The argument \f5f\fP for \f5sfopen()\fP, ! 192: if not \f5NULL\fP, is a currently opened stream to be ! 193: closed and replaced by a new stream corresponding to the object \f5string\fP. ! 194: The argument \f5mode\fP can be any one of: \f5"r"\fP, \f5"r+"\fP, ! 195: \f5"w"\fP, \f5"w+"\fP, \f5"a"\fP, \f5"a+"\fP, \f5s\fP and \f5s+\fP. ! 196: The \f5r\fP, \f5w\fP, and \f5a\fP specify read, write and append mode for file streams. ! 197: In these cases, the argument \f5string\fP defines a path name to a file. ! 198: The \f5s\fP specifies that \f5string\fP is a nul-terminated string to be opened for read. ! 199: The \f5+\fP means that the new stream will be opened for both reading and writing. ! 200: .PP ! 201: \f5sfdopen(fd,mode)\fP makes a stream using the file descriptor \f5fd\fP. ! 202: The \f5mode\fP argument is used in the same way as in \f5sfopen()\fP. ! 203: .PP ! 204: \f5sfpopen(cmd,mode,fcomp)\fP ! 205: opens a stream \f5f\fP which is a pipe to (from) the command \f5cmd\fP ! 206: if the mode is \f5"w"\fP (\f5"r"\fP). If the mode is \f5"w+"\fP or \f5"r+"\fP, ! 207: another stream for the opposite operation is created and returned in \f5fcomp\fP. ! 208: Note that if either of these streams is closed, the other is also closed. ! 209: .PP ! 210: \f5sfstack(base,top)\fP is used to push or pop stream stacks. ! 211: Each stream stack is identified by a \f5base\fP stream ! 212: via which all io operations are performed. ! 213: Other streams on the stack are locked so that operations that may change ! 214: their internal states are forbidden. ! 215: The type of operations that can be done on a stack is defined by ! 216: the top level stream. If an io operation is performed and the top level stream ! 217: reaches the end of file condition or an error condition other than interrupts, ! 218: it is automatically popped and closed (see also \f5sfsetdisc\fP for alternative ! 219: handling of these conditions). ! 220: The first argument of \f5sfstack()\fP specifies the \f5base\fP stream. ! 221: The second argument, \f5top\fP, if not \f5NULL\fP, ! 222: is pushed on top of the current top stream. ! 223: In this case, the \f5base\fP stream pointer is returned. ! 224: If \f5top\fP is \f5NULL\fP, the stack is popped and the pointer to ! 225: the popped stream is returned. ! 226: .PP ! 227: \f5sfpushed(f)\fP returns the pointer to the stream pushed below \f5f\fP. ! 228: .PP ! 229: \f5sftmp(size)\fP creates a stream for writing and reading temporary data. ! 230: If \f5size\fP is negative, the stream is a pure \f5SF_STRING\fP stream. ! 231: Otherwise, the stream is originally created as a \f5SF_STRING\fP stream ! 232: with a buffer of the given \f5size\fP. A discipline is set so that ! 233: when this buffer is exhausted, a real temporary file will be created. ! 234: Any attempt to change this discipline will also cause the temporary file ! 235: to be created. ! 236: .PP ! 237: \f5sfpool(f,poolf,mode)\fP manages pools of streams. ! 238: In a pool of streams, only one stream is current. ! 239: A stream becomes current when it is used for some io operation. ! 240: When a new stream is to become current, ! 241: the current stream is synchronized (see \f5sfsync()\fP) ! 242: if its type matches the type of the pool. ! 243: The first argument of \f5sfpool()\fP, \f5f\fP, is the stream to be manipulated. ! 244: The second argument, \f5poolf\fP, determines the operation to be done on \f5f\fP. ! 245: If \f5poolf\fP is \f5NULL\fP, \f5f\fP is deleted from its current pool. ! 246: Otherwise, \f5f\fP is put into the same pool with \f5poolf\fP. ! 247: If \f5poolf\fP is already in a pool, the third argument is ignored. ! 248: Otherwise, it determines the type of the new pool. ! 249: \f5mode\fP can be constructed by bitwise or-ing of \f5SF_READ\fP and \f5SF_WRITE\fP. ! 250: .PP ! 251: \f5sfsetdisc(f,disc)\fP changes ! 252: the io-discipline of the stream \f5f\fP, i.e., ! 253: to specify alternative functions for read, write, seek, and to handle exceptions. ! 254: The default discipline consists of the system calls \f5read()\fP, \f5write()\fP, ! 255: and \f5lseek()\fP. ! 256: The \f5disc\fP argument is either \f5NULL\fP to reset to the default discipline ! 257: or a pointer to a \f5Sfdisc_t\fP structure which contains the following fields: ! 258: .PP ! 259: .nf ! 260: \f5int (*readf)();\fP ! 261: \f5int (*writef)();\fP ! 262: \f5long (*seekf)();\fP ! 263: \f5int (*exceptf)();\fP ! 264: \f5void* handle;\fP ! 265: .fi ! 266: .PP ! 267: The first three fields of \f5Sfdisc_t\fP specify alternative io functions. ! 268: If any of them is \f5NULL\fP, the corresponding system call is used. ! 269: A discipline io function, say \f5(*readf)()\fP, ! 270: is called with 4 arguments. ! 271: The first argument is the stream pointer. ! 272: The second and third arguments correspond to the second and third arguments ! 273: of the respected system call. ! 274: The fourth argument is the \f5handle\fP field of \f5Sfdisc_t\fP. ! 275: The exception function, \f5(*exceptf)()\fP, if provided, is called ! 276: when an exception happens during a read/write operation, when a stream ! 277: is being closed, or when the discipline is being reset. ! 278: A read/write operation is said to cause an exception if its return value ! 279: is zero or negative. It is up to the exception function to determine ! 280: the type of exception (for example, by examining \f5errno\fP). ! 281: When \f5(*exceptf)()\fP is called, the stream will be opened for general operations. ! 282: However, \f5(*exceptf)()\fP should not attempt to close the stream. ! 283: \f5(*exceptf)()\fP is called as: ! 284: \f5(*exceptf)(f,type,handle)\fP. \f5type\fP is: ! 285: \f50\fP when the discipline is being reset, ! 286: \f5SF_EOF\fP when the stream is being closed, ! 287: \f5SF_READ\fP when an exception happens during a read operation, and ! 288: \f5SF_WRITE\fP when an exception happens during a write operation. ! 289: For the cases of \f5SF_READ\fP and \f5SF_WRITE\fP, ! 290: the executing \fIsfio\fP function will examine the return value of \f5(*exceptf)()\fP ! 291: for further actions: ! 292: \fInegative\fP for immediate return, ! 293: \fIzero\fP for executing default actions associated with the exception, ! 294: and \fIpositive\fP for resuming execution. ! 295: Note that a \f5SF_STRING\fP stream does not perform external io so the ! 296: io functions are not used. However, an exception occurs whenever ! 297: an io operation exceeds the stream buffer boundary and ! 298: \f5(*exceptf)()\fP, if defined, will be called as appropriate. ! 299: \f5sfsetdisc()\fP returns the pointer to the previous discipline ! 300: or \f5NULL\fP if an error happened. ! 301: Finally, it is the application's responsibility to manage the space used ! 302: by the \f5Sfdisc_t\fP structures. ! 303: .PP ! 304: \f5sfclose(f)\fP closes the given stream \f5f\fP and frees up its resources. ! 305: If \f5f\fP is \f5NULL\fP, all streams are closed. ! 306: If \f5f\fP is a stack of streams, all streams on the stack are closed. ! 307: If \f5f\fP is a \f5sfpopen\fP-stream, its companion stream, if any, is also closed. ! 308: Further, \f5sfclose()\fP will wait until the associated command terminates, ! 309: then return its exit status. ! 310: A few file flags affect the behavior of \f5sfclose()\fP. ! 311: If \f5SF_KEEPFD\fP is on, the underlying file descriptor is not closed. ! 312: If \f5SF_REUSE\fP is on, \f5sfclose()\fP will only synchronize the buffer ! 313: and close the file descriptor (subject to \f5SF_KEEPFD\fP). ! 314: The stream structure is left intact, including ! 315: pool (\f5sfpool()\fP) or discipline (\f5sfsetdisc()\fP) information. ! 316: .PP ! 317: \f5sfsync(f)\fP causes the physical file pointer of the stream ! 318: \f5f\fP to correspond to its logical position. ! 319: If \f5f\fP is the base of a stack of streams, all streams on the stack ! 320: are synchronized. Further, a stacked stream can only be synchronized ! 321: via its base stream. ! 322: .PP ! 323: \f5sfpeek(f,bufp)\fP provides a safe method for enquiring ! 324: information on the internal buffer of a stream. ! 325: If \f5bufp\fP is \f5NULL\fP, \f5sfpeek()\fP simply returns the amount of data ! 326: available in the buffer to read if \f5f\fP is in read mode ! 327: or the amount of buffer available to write if \f5f\fP is in write mode. ! 328: If \f5bufp\fP is not \f5NULL\fP, \f5sfpeek()\fP provides access to the buffer. ! 329: For a read stream, if the buffer is empty, it is filled and, ! 330: for a write-stream, if the buffer is full, it is flushed. ! 331: Then, for a read stream, \f5bufp\fP is set to the place in the buffer ! 332: where data is available and, for a write stream, ! 333: it is set to where data can be written. ! 334: The return value of \f5sfseek()\fP indicates how much data or space is available ! 335: in the buffer. However, if the stream is in \f5SF_LINE|SF_READ\fP mode, ! 336: the return value will be the data length up to and including the new-line character. ! 337: In this case, if there is not a new-line character in the buffered data, ! 338: more data may be read. ! 339: Note that the buffer location is not advanced by \f5sfpeek()\fP. ! 340: That must be done by a regular io call such as \f5sfread\fP or \f5sfwrite\fP on ! 341: the pointer returned in \f5bufp\fP. ! 342: Finally, \f5sfpeek()\fP treats a read/write-stream like a read-stream ! 343: (however, see also \f5sfset()\fP). ! 344: .PP ! 345: \f5sfgetc(f)\fP returns a byte from the stream \f5f\fP or -1 when an end-of-file ! 346: or error condition is encountered. ! 347: .PP ! 348: \f5sfungetc(f,c)\fP puts the byte \f5c\fP back into the stream \f5f\fP. ! 349: This is guaranteed to work only after a \f5sfgetc()\fP call. ! 350: .PP ! 351: \f5sfgetu(f)\fP, \f5sfgetl(f)\fP, and \f5sfgetd(f)\fP return ! 352: an \fIunsigned long\fP, a \fIlong\fP value, or a \fIdouble\fP value ! 353: that was coded in a portable fashion ! 354: (see \f5sfputu()\fP, \f5sfputl()\fP, and \f5sfputd()\fP). ! 355: If there is not enough data to decode a value, ! 356: these functions will return \f5-1\fP and the stream is set in an error state ! 357: (\f5see \f5sferror()\fP). ! 358: .PP ! 359: \f5sfgets(f,buf,size)\fP reads a line of input from the stream \f5f\fP. ! 360: If \f5buf\fP is not \f5NULL\fP and \f5size\fP is positive, \f5sfgets\fP ! 361: reads up to \f5size-1\fP characters into the buffer \f5buf\fP. ! 362: Otherwise, the characters are read into a static area that is dynamically ! 363: grown as necessary. Thus, in this case, there is no limit to line length. ! 364: A nul-character is appended after the input characters. ! 365: \f5sfgets()\fP returns the pointer to the new string or \f5NULL\fP when ! 366: no data was read due to end-of-file or an error condition. ! 367: After a string is read, its length can be found using \f5sfslen()\fP. ! 368: .PP ! 369: \f5sfread(f,buf,n)\fP reads up to \f5n\fP bytes from the stream \f5f\fP and ! 370: stores them in the given buffer \f5buf\fP. ! 371: It returns the number of bytes actually read. ! 372: .PP ! 373: \f5sfscanf(f,format,...)\fP scans a number of items from the stream \f5f\fP. ! 374: The item types are determined from the string \f5format\fP. ! 375: See \fIfscanf()\fP (UNIX User's Manual, Section 3) for details on predefined formats. ! 376: The standardly supported formats are: ! 377: \f5i, I, d, D, u, U, o, O, x, X, f, F, e, E, g, G, c, %, s,\fP and \f5[]\fP. ! 378: The \f5sfscanf()\fP interface also supports additional formats as described below. ! 379: .IP ! 380: The pattern \f5%&\fP indicates that the next argument in the argument list of ! 381: \f5sfscanf()\fP is a function, say \f5(*extf)()\fP, to process patterns that are not ! 382: predefined by the \f5sfscanf()\fP interface. ! 383: The prototype of \f5(*extf)()\fP is: ! 384: .nf ! 385: \f5int (*extf)(Sfile_t* f, int fmt, int length, char** rv);\fP ! 386: .fi ! 387: \f5f\fP is the same input stream passed to \f5sfvscanf\fP. ! 388: \f5fmt\fP is the pattern to be processed. ! 389: \f5length\fP, if non-negative, is the maximum number of input bytes ! 390: to be read in processing the pattern, ! 391: \f5rv\fP is used to return the ``address'' of the value to be assigned. ! 392: \f5(*extf)()\fP returns the size of the value to be assigned. ! 393: A negative return value from \f5(*extf)()\fP means that the specified pattern ! 394: cannot be handled. This pattern is treated as if it is not matched. ! 395: .IP ! 396: The pattern \f5%@\fP indicates that the next argument in the argument list \f5args\fP ! 397: is a function, say \f5(*argf)()\fP, to process the values of matched patterns. ! 398: The prototype of \f5(*argf)()\fP is: ! 399: .nf ! 400: \f5int (*argf)(int fmt, char* value, int n)\fP; ! 401: .fi ! 402: If the return value of \f5(*argf)()\fP is negative, the processing ! 403: of the current format string will be stopped (see \f5%$\fP below). ! 404: \f5fmt\fP determines the type of \f5value\fP: \f5f\fP for \fIfloat\fP, ! 405: \f5F\fP for \fIdouble\fP, \f5h\fP for \fIshort\fP, \f5d\fP for \fIint\fP, ! 406: \f5D\fP for \fIlong\fP, \f5s\fP for \fIchar*\fP. Any other value for \f5fmt\fP ! 407: means that it is an extended pattern and \f5value\fP contains an address ! 408: to the scanned value. \f5n\fP contains the size of the object if it is a ! 409: primitive type. If the object is \f5char*\fP or the address of the scanned ! 410: value of an extended format, \f5n\fP is the length of this object. ! 411: .IP ! 412: The pattern \f5%:\fP indicates that the next two arguments in the argument list ! 413: \f5args\fP define a new pair of format string and a list of arguments of ! 414: the type \f5va_list\fP (see \f5varargs.h\fP or \f5stdarg.h\fP). ! 415: The new pair is pushed on top of the stack and the scanning process continues with them. ! 416: The top pair of format string and argument list is popped when the processing ! 417: of the format string is stopped. When a new pair is stacked, ! 418: \f5(*argf)()\fP and \f5(*extf)()\fP are inherited. ! 419: They are reset when the stack is popped. ! 420: .PP ! 421: \f5sfsscanf(s,format,...)\fP is similar to \f5sfscanf()\fP ! 422: but it scans data from the string \f5s\fP. ! 423: .PP ! 424: \f5sfvscanf(f,format,args)\fP is the primitive underlying \f5sfscanf()\fP ! 425: and \f5sfscanf()\fP. It also provides a portable variable argument interface. ! 426: Programs that use \f5sfvscanf()\fP must include either of \f5varargs.h\fP ! 427: or \f5stdargs.h\fP as appropriate. ! 428: .PP ! 429: \f5sfputc(f,c)\fP writes the byte \f5c\fP to the stream \f5f\fP. ! 430: .PP ! 431: \f5sfnputc(f,c,n)\fP writes the byte \f5c\fP to the stream \f5f\fP \f5n\fP times. ! 432: It returns the number of bytes successfully written. ! 433: .PP ! 434: \f5sfputu(f,v)\fP, \f5sfputl(f,v)\fP write the \fIunsigned long\fP or \fIlong\fP ! 435: value \f5v\fP in a format that is byte-order transparent. ! 436: \f5sfputd(f,v)\fP writes the \fIdouble\fP value \f5v\fP in a portable format. ! 437: Portability across two different machines ! 438: requires that the bit order in a byte is the same on both machines. ! 439: \f5sfputd()\fP also relies on the functions \f5ldexp()\fP and \f5frexp()\fP ! 440: (See \fIfrexp.3\fP) for coding. ! 441: Upon success, \f5sfputu()\fP, \f5sfputl()\fP and \f5sfputd()\fP ! 442: return the number of bytes output. ! 443: .PP ! 444: \f5sfputs(f,s,c)\fP writes the null-terminated string \f5s\fP to the stream \f5f\fP. ! 445: If \f5c\fP is not 0, it is a character to be appended after the string has been output. ! 446: \f5sfputs()\fP returns the number of bytes written. ! 447: .PP ! 448: \f5sfwrite(f,buf,n)\fP writes out \f5n\fP bytes from the buffer \f5buf\fP to the ! 449: stream \f5f\fP. It returns the number of bytes written. ! 450: .PP ! 451: \f5sfmove(fr,fw,n,seps)\fP moves \f5n\fP objects ! 452: from the stream \f5fr\fP to the stream \f5fw\fP. ! 453: If either \f5fr\fP or \f5fw\fP is \f5NULL\fP, it acts ! 454: as if it is a stream corresponding to \fI/dev/null\fP. ! 455: If \f5n\fP is \f5<0\fP, all of \f5fr\fP is moved. ! 456: If \f5seps\fP is \f5NULL\fP or an empty string, the objects to be moved are bytes. ! 457: Otherwise, the moved objects are records separated by bytes defined in \f5seps\fP. ! 458: In \f5seps\fP, if the first two bytes is \f5\e0\fP, it is mapped to the zero byte. ! 459: All other cases map a byte to itself. ! 460: \f5sfmove()\fP returns the number of objects moved. ! 461: .PP ! 462: \f5sfprintf(f,format,...)\fP writes out data in ! 463: a format as defined by the string \f5format\fP. ! 464: See \fIfprintf()\fP (UNIX User's Manual, Section 3) for details on predefined ! 465: conversion formats. ! 466: The standardly supported formats are: ! 467: \f5n, s, c, %, h, i, d, p, u, o, x, X, g, G, e, E, f,\fP and \f5F\fP. ! 468: \f5sfprintf()\fP also supports additional formats as described below. ! 469: .IP ! 470: The pattern \f5%&\fP indicates that the next argument ! 471: is a function, say \f5(*extf)()\fP, to interpret patterns not yet defined ! 472: by \f5sfprintf()\fP. ! 473: The prototype of \f5(*extf)()\fP is: ! 474: .nf ! 475: \f5int (*extf)(void* value, int fmt, int precis, char** sp);\fP ! 476: .fi ! 477: \f5value\fP is the value to be formatted. ! 478: \f5fmt\fP is the pattern to format the value. ! 479: \f5precis\fP is the amount of precision required. ! 480: \f5sp\fP is used to return the address of a string containing the formatted value. ! 481: If upon returning from \f5(*extf)()\fP, \f5*sp\fP is \f5NULL\fP, the pattern \f5fmt\fP ! 482: is treated as if it is not matched. ! 483: Otherwise, the return value of \f5(*extf)()\fP, if nonnegative, is taken as the length ! 484: of the string returned in \f5sp\fP. If not, the string is considered null-terminated. ! 485: The string \f5*sp\fP is processed as if the pattern \f5`s'\fP was specified. ! 486: .IP ! 487: The pattern \f5%@\fP indicates that the next argument is a function, say \f5(*argf)()\fP, ! 488: to get arguments. As long as \f5(*argf)()\fP is defined, the argument list is ignored. ! 489: The prototype of \f5(*argf)()\fP is: ! 490: .nf ! 491: \f5int (*argf)(int fmt, char* val)\fP; ! 492: .fi ! 493: \f5fmt\fP is the pattern to be processed. ! 494: Following are ASCII characters and corresponding types: ! 495: \f5@\fP for getting a new \f5(*argf)()\fP, ! 496: \f5&\fP for getting a new \f5(*extf)()\fP, ! 497: \f51\fP for getting a new format string for stacking, ! 498: \f52\fP for getting a new argument list for stacking, ! 499: \f5d\fP for \fIint\fP, ! 500: \f5D\fP for \fIlong\fP, ! 501: \f5f\fP for \fIfloat\fP, ! 502: \f5F\fP for \f5double\fP, and ! 503: \f5s\fP for \fIchar*\fP. ! 504: If \f5(*extf)()\fP is defined, and an undefined pattern is encountered, ! 505: \f5(*argf)()\fP will be called with this pattern. ! 506: \f5val\fP is an address to store the value to be formatted. ! 507: The return value of \f5(*argf)()\fP, if negative, stops the processing ! 508: of the current format (see below). ! 509: .IP ! 510: The pattern \f5%:\fP indicates that the next two arguments define ! 511: a pair of format string and argument list of the type \f5va_list\fP. ! 512: If the argument getting function \f5(*argf)()\fP is already defined, ! 513: it is called with the argument \f5fmt\fP being the characters ! 514: \f51\fP and \fP2\fP for the new format string and argument list respectively. ! 515: The new pair is stacked on top and processing continue from there. ! 516: The top pair of format string and argument is popped when the format string ! 517: is exhausted. When a new pair is pushed, \f5(*argf)()\fP and \f5(*extf)()\fP ! 518: are inherited. When a pair is popped, these functions will be reset. ! 519: .PP ! 520: \f5sfsprintf(s,size,format,...)\fP is similar to \f5sfprintf()\fP ! 521: but it is used to format ! 522: the character array \f5s\fP which is of size \f5size\fP. ! 523: The length of the resulting string can be gotten via \f5sfslen()\fP. ! 524: .PP ! 525: \f5sfvprintf(f,format,args)\fP is the primitive underlying \f5sfprintf()\fP ! 526: and \f5sfsprintf()\fP. It provides a portable variable argument interface. ! 527: Programs that use \f5sfvprintf()\fP must include either of \f5varargs.h\fP ! 528: or \f5stdargs.h\fP as appropriate. ! 529: .PP ! 530: \f5sfnotice(noticef)\fP sets a function \f5(*noticef)()\fP which will ! 531: be called whenever a stream is created or closed. ! 532: \f5(*noticef)()\fP is called with two arguments. ! 533: The first argument is the stream pointer and ! 534: the second argument is either \f50\fP or \f5SF_EOF\fP to indicate ! 535: whether the stream is being opened or being closed. ! 536: .PP ! 537: \f5sfset(f,flags,i)\fP sets flags or file descriptor for the stream \f5f\fP. ! 538: If \f5flags\fP is the value \f5SF_EOF\fP, the file descriptor of the stream ! 539: is changed to the value in \f5i\fP. In this case, \f5sfset()\fP returns \f5-1\fP ! 540: on error or \f5i\fP on success. ! 541: If \f5flags\fP is not \f5SF_EOF\fP, it defines a collection of flags to be ! 542: turned on or off depending on whether \f5i\fP is non-zero or zero. ! 543: The flags that can be turned on or off are: ! 544: \f5SF_READ\fP, \f5SF_WRITE\fP, ! 545: \f5SF_LINE\fP, \f5SF_KEEPFD\fP, \f5SF_REUSE\fP, \f5SF_MALLOC\fP and \f5SF_SHARE\fP. ! 546: The flags \f5SF_READ\fP and \f5SF_WRITE\fP can be used in a call to \f5sfset()\fP ! 547: only if the stream \f5f\fP was opened for both read and write. ! 548: Turning off one of these flags means that the stream is to be treated as ! 549: if it was opened with the other flag exclusively (see \f5sfpeek()\fP). ! 550: In this case, \f5sfset()\fP returns the entire set of flags controlling the stream. ! 551: Thus, the current set of flags can be found by \f5sfset(f,0,0)\fP. ! 552: .PP ! 553: \f5sfsetbuf(f,buf,size)\fP changes the current buffer of the stream \f5f\fP to ! 554: the new buffer \f5buf\fP. If the stream is a \f5SF_WRITE\fP stream, ! 555: any data still in the current buffer is thrown away. ! 556: Thus, if an application desires to preserve such data, it should ! 557: call \f5sfsync()\fP before trying to switch buffers. ! 558: If \f5size\fP is positive, \f5buf\fP is taken as a buffer of the given size. ! 559: If \f5size\fP is zero, the stream will be unbuffered. ! 560: If \f5size\fP is negative, an internal buffer is allocated. ! 561: \f5sfsetbuf()\fP returns the address of the old buffer. ! 562: .PP ! 563: \f5sffileno(f)\fP returns the file descriptor of the stream \f5f\fP. ! 564: .PP ! 565: \f5sfeof(f)\fP tells whether there is any more data in the stream \f5f\fP. ! 566: .PP ! 567: \f5sforigin(f)\fP returns the origin location in the stream \f5f\fP (see \f5sfnew()\fP). ! 568: If this location is \f5-1L\fP, the stream is not seekable. ! 569: Note that the standard streams \f5sfstdin\fP, \f5sfstdout\fP, and \f5sfstderr\fP, ! 570: though statically allocated, are not initialized until an operation that may ! 571: affect its internal structure. Thus, the return value \f50L\fP of \f5sforigin()\fP ! 572: on such an initialized stream is not reliable. ! 573: .PP ! 574: \f5sferror(f)\fP and \f5sfclearerr(f)\fP returns or clears the error condition ! 575: of the stream \f5f\fP. Note that the error condition of a stream does not prevent ! 576: further io operations to be performed on them. ! 577: .PP ! 578: \f5sfclrlock(f)\fP clears the lock on a locked stream. ! 579: Though this is unsafe, it is useful for emergency access ! 580: to a locked stream or to clear a stream left locked because ! 581: of non-local jumps (e.g., \f5longjmp()\fP). ! 582: .PP ! 583: \f5sfslen()\fP returns the length of the string most recently obtained ! 584: via a \f5sfgets()\fP, \f5sfsprintf()\fP, \f5sfecvt()\fP or \f5sffcvt()\fP call. ! 585: .PP ! 586: \f5sfulen(v)\fP, \f5sfllen(v)\fP and \f5sfdlen(v)\fP ! 587: return the number of bytes required to code the ! 588: \fIunsigned long\fP, \fIlong\fP or \fIdouble\fP value \f5v\fP. ! 589: .PP ! 590: \f5sfseek(f,addr,offset)\fP sets the next read/write location for the stream \f5f\fP ! 591: at a new address defined by the combination of \f5addr\fP and \f5offset\fP. ! 592: If \f5offset\fP is 0, \f5addr\fP is offset from the origin of the stream ! 593: (see \f5sfnew()\fP). ! 594: If \f5offset\fP is 1, \f5addr\fP is offset from the current location. ! 595: Note that if \f5f\fP was opened for appending (\f5SF_APPEND\fP) and the last operation ! 596: done on it was a write operation, the \fIcurrent location\fP is at the physical ! 597: end of file. ! 598: If \f5offset\fP is 2, \f5addr\fP is offset from the \fIphysical\fP end of the stream. ! 599: In all cases, \f5sfseek()\fP is not allowed to seek backward beyond the stream origin. ! 600: .PP ! 601: \f5sftell(f)\fP returns the current location in the stream \f5f\fP relative ! 602: to the stream origin (see \f5sfnew()\fP). ! 603: As with \f5sfseek()\fP, if \f5f\fP was opened for appending (\f5SF_APPEND\fP) ! 604: and the last operation done on it was a write operation, ! 605: the \fIcurrent location\fP is at the physical end of file. ! 606: If the stream \f5f\fP is unseekable, \f5sftell\fP returns the number of bytes ! 607: read from or written to \f5f\fP. ! 608: .PP ! 609: \f5sfecvt(v,n,decpt,sign)\fP and ! 610: \f5sffcvt(v,n,decpt,sign)\fP are functions to convert floating values to ASCII. ! 611: They corresponds to the standard functions \f5ecvt()\fP and \f5fcvt()\fP. ! 612: The length of the conversion string most recently done by ! 613: \f5sfecvt()\fP or \f5sffcvt()\fP can be found by \f5sfslen()\fP. ! 614: .PP ! 615: .SH HISTORY AND FUTURE CONSIDERATIONS ! 616: \fIsfio\fP has similar functionality, but is more general ! 617: than the \fIstdio\fP package. ! 618: It grows from our dissatisfaction with the awkwardness, fragility ! 619: and inefficiency in \fIstdio\fP. ! 620: An example of \fIstdio\fP awkwardness is that ! 621: even if a stream was opened for read and write, ! 622: the application code cannot arbitrarily mix read and write operations. ! 623: An earlier attempt was made at rewriting \fIstdio\fP. ! 624: This failed due to problems that arise when linking with code based on \fIstdio\fP. ! 625: Changing the name space reduces this type of problems. ! 626: It also allows us to both stream-line and extend the interface as appropriate. ! 627: .SH AUTHORS ! 628: Kiem-Phong Vo (att!ulysses!kpv) and David G. Korn (att!ulysses!dgk).
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.