#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # FILE.c FILE2.c FILE3.c clearerr.c doprint.c doscan.c extbuf.h fclose.c feof.c ferror.c fflush.c fgetc.c fgets.c fopen.c fprintf.c fputc.c fputs.c fread.c freopen.c fscanf.c fwrite.c getc.c getchar.c gets.c makefile nstdio.h printf.c putc.c putchar.c puts.c scanf.c scanset.h scanset1.c setbuf.c sprintf.c sscanf.c stdin.c tst.c tst.cmp tst.ecmp tst.err tst.in ungetc.c vfprintf.c vfscanf.c vprintf.c vscanf.c vsprintf.c vsscanf.c ~FILE.c # # To extract the files from this shell archive file simply # create a directory for this file, move the archive file # to it and enter the command # # sh filename # # The files will be extracted automatically. # Note: Do not use csh. # # Archive created: Mon Jul 30 23:13:02 EDT 1990 # echo x - FILE.c sed 's/^X//' > FILE.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // create a FILE using the given buffer and mode FILE::FILE(streambuf *st, open_mode m) { sb = st; mode = m; // create the appropriate stream if (mode == input) in = new istream(sb); else out = new ostream(sb); } !EOF! ls -l FILE.c echo x - FILE2.c sed 's/^X//' > FILE2.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ FILE::FILE(istream *is) { mode = input; in = is; sb = 0; } !EOF! ls -l FILE2.c echo x - FILE3.c sed 's/^X//' > FILE3.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ FILE::FILE(ostream *os) { mode = output; out = os; sb = 0; } !EOF! ls -l FILE3.c echo x - clearerr.c sed 's/^X//' > clearerr.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // clear out any error indications void clearerr(FILE *f) { if (f->mode == input) f->in->clear(); else f->out->clear(); } !EOF! ls -l clearerr.c echo x - doprint.c sed 's/^X//' > doprint.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // _doprint(): low level function for doing // formatted output, to be invoked by the // v*printf() family of functions #include // endchar() returns TRUE for those format // characters which cause output. int endchar(char c) { switch (c) { case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': case 'f': case 'e': case 'E': case 'g': case 'G': case 'c': case 's': case 'p': case 'n': case '%': case 0: return 1; default: return 0; } } int _doprint(ostream *out, const char *fmt, va_list vl) { if (!fmt) return EOF; char *cfmt = new char[strlen(fmt)+1]; while (*fmt) { char *buf = cfmt; int asterisks = 0; int shortarg = 0; int longarg = 0; char c; // loop looking for the beginning of a format while ((c = *buf++ = *fmt++) && (c != '%')) ; // loop looking for the end of the format if (c) while (!endchar(c = *buf++ = *fmt++)) if (c == '*') asterisks++; else if (c == 'h') shortarg++; else if (c == 'l') longarg++; // polish off the buffer. leave fmt // pointing at the null if just past it. *buf = '\0'; if (!c) fmt--; // pull off the width and precision int prec = 0, width = 0; switch (asterisks) { case 0: break; case 2: width = va_arg(vl, int); // NO BREAK case 1: prec = va_arg(vl, int); break; } // Declare a generic output routine for the type passed // on the stack and the type used for output. This // cannot be an inline since the parameters are types. #define OUTPUT(parmtype, outtype) \ do { \ outtype val = va_arg(vl, parmtype); \ switch (asterisks) \ { \ case 0: \ (*out) << form(cfmt, val); break; \ case 1: \ (*out) << form(cfmt, prec, val); break; \ case 2: \ (*out) << form(cfmt,width,prec,val);break; \ } \ } while (0) // extract the value and output it switch (c) { // decimal variables case 'd': case 'i': if (longarg) OUTPUT(long, long); else if (shortarg) OUTPUT(short, int); else OUTPUT(int, int); break; // unsigned decimal variables case 'o': case 'u': case 'x': case 'X': if (longarg) OUTPUT(unsigned long, unsigned long); else if (shortarg) OUTPUT(unsigned short, unsigned int); else OUTPUT(unsigned int, unsigned int); break; // double variables case 'f': case 'e': case 'E': case 'g': case 'G': OUTPUT(double, double); break; // character variables case 'c': OUTPUT(unsigned char, int); break; // string variable case 's': OUTPUT(char*, char*); break; // nothing much here case '%': case 0: (*out) << form(cfmt); break; } } delete cfmt; return 1; } !EOF! ls -l doprint.c echo x - doscan.c sed 's/^X//' > doscan.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // _doscanf(): low level function for doing formatted // input, to be invoked by the v*scanf() family // of functions. #include #include #include #include // get the next character on the input stream, // adding to charcnt and returning EOF on end-of-file. inline int nextc(istream *in, int &charcnt) { char c; return (!in->get(c)) ? EOF : (charcnt++, c); } /* Define a macro to decrement the fieldwidth */ /* and add the character to the buffer. */ #define addc() \ fieldwidth--, svbuf.add(c) /* Define a macro to decrement the fieldwidth, */ /* add the character to the buffer and get the */ /* next character. */ #define Nextc() \ do { addc(); c = nextc(in, charcnt); } while (0) /* Define macros to use for assigning the */ /* appropriate value to the appropriate pointer */ /* type to be pulled off the stack based on the */ /* booleans halfsize, longsize and suppress. */ /* assign() checks for halfsize, then invokes */ /* liassign() below. */ #define assign(var, stype, itype, ltype) \ if (halfsize) \ { \ stype *p = va_arg(vl, stype*); \ *p = (stype)var; \ } \ \ else \ liassign(var, itype, ltype) /* This macro is invoked from assign() above */ /* and for %f, which doesn't allow the halfsized*/ /* modifier. It checks for the booleans longsize*/ /* and suppress. */ #define liassign(var, itype, ltype) \ if (longsize) \ { \ ltype *p = va_arg(vl, ltype*); \ *p = (ltype)var; \ } \ \ else if (!suppress) \ { \ itype *p = va_arg(vl, itype*); \ *p = (itype)var; \ } /* define a macro to check for an optional sign */ #define checksign() \ if ((fieldwidth > 0) && \ ((c == '-') || (c == '+'))) \ { \ Nextc(); \ } /* This macro will check for one or more */ /* characters which have a certain */ /* characteristic checked by the testprog, such */ /* as isdigit. If the sequence is missing, it */ /* is an error and the macro will break out of */ /* the switch statement. */ #define checkfield(testprog) \ if ((fieldwidth > 0) && testprog(c)) \ do { \ addc(); \ } while ((fieldwidth > 0) && \ testprog(c = nextc(in, charcnt))); \ \ else \ { \ goodformat = 0; \ break; \ } /* This macro works just like checkfield() */ /* except that it is not an error for the */ /* sequence to be missing. */ #define checkoptfield(testprog) \ for ( ; (fieldwidth > 0) && testprog(c); \ c = nextc(in, charcnt)) \ { \ addc(); \ } // the input function int _doscanf(istream *in, const char *fmt, va_list vl) { if (!fmt) return EOF; int charcnt = 0; int fieldcnt = EOF; int goodformat = 1; int c = nextc(in, charcnt); extarray svbuf; // loop through the format string while (*fmt && (c != EOF) && goodformat) { switch (*fmt++) { // format specification case '%': { // '*' means suppress assignment int suppress = 0; if (*fmt == '*') { suppress = 1; fmt++; } // check for a fieldwidth int fieldwidth = -1; if (isdigit(*fmt)) fieldwidth = (int)strtol(fmt, (char**)&fmt, 10); // Check for size modifiers. // Just skip past if assignment // is being suppressed. int halfsize = 0; int longsize = 0; switch (*fmt) { case 'h': if (!suppress) halfsize = 1; fmt++; break; case 'l': if (!suppress) longsize = 1; fmt++; break; } // set the default field width if (fieldwidth == -1) fieldwidth = (*fmt == 'c') ? 1 : INT_MAX; // check for skipping white space switch (*fmt) { // these do not skip white space case '%': case 'n': case '[': case 'c': break; default: // loop until a non-white-space // character is found if (isspace(c)) do { c = nextc(in, charcnt); } while (isspace(c)); break; } // only return EOF if an error // occurred before the first // field specifier is reached if (fieldcnt == EOF) fieldcnt = 0; svbuf.reset(); // check for assignment type switch (*fmt) { // store the number of read chars case 'n': assign(charcnt, short, int, long); break; // fill svbuf with an integer // or an unsigned integer case 'd': case 'u': { checksign(); checkfield(isdigit); /* assign to a signed number */ if (*fmt == 'd') { long i = strtol(svbuf.val(), 0, 10); assign(i, short, int, long); } /* assign to an unsigned number */ else { unsigned long i = strtoul(svbuf.val(), 0, 10); assign(i, unsigned short, unsigned int, unsigned long); } fieldcnt++; break; } // fill svbuf with a C++ integer case 'i': { checksign(); // check for leading 0 or 0x if ((fieldwidth > 0) && (c == '0')) { Nextc(); if ((fieldwidth > 0) && ((c == 'x') || (c == 'X'))) { Nextc(); checkfield(isxdigit); } else checkfield(isodigit); } else checkfield(isdigit); long i = strtol(svbuf.val(), 0, 0); assign(i, short, int, long); fieldcnt++; break; } // fill svbuf with an octal integer case 'o': { checksign(); checkfield(isodigit); unsigned long i = strtoul(svbuf.val(), 0, 8); assign(i, unsigned short, unsigned int, unsigned long); fieldcnt++; break; } // fill svbuf with a hex integer case 'x': case 'X': { checksign(); checkfield(isxdigit); unsigned long i = strtoul(svbuf.val(), 0, 16); assign(i, unsigned short, unsigned int, unsigned long); fieldcnt++; break; } // Read in a floating point number case 'e': case 'E': case 'g': case 'G': case 'f': { checksign(); checkoptfield(isdigit); if ((fieldwidth > 0) && (c == '.')) { Nextc(); checkoptfield(isdigit); } if ((fieldwidth > 0) && ((c == 'e') || (c == 'E'))) { Nextc(); checksign(); checkfield(isdigit); } double i = strtod(svbuf.val(), 0); liassign(i, float, double); fieldcnt++; break; } // Read up to fieldwidth characters // (minimum of 1) which match the // scanset. Add a null character at // the end of the string. case '[': { char *p; if (c == EOF) break; if (!suppress) p = va_arg(vl, char*); scanset s(fmt, &fmt); for ( ; (fieldwidth-- > 0) && s.match(c) ; c = nextc(in, charcnt)) if (!suppress) *p++ = c; if (!suppress) *p = '\0'; fieldcnt++; break; } // Read fieldwidth characters. // Do NOT add a null character after. case 'c': { char *p; if (c == EOF) break; if (!suppress) p = va_arg(vl, char*); for ( ; (fieldwidth-- > 0) && (c != EOF) ; c = nextc(in, charcnt)) if (!suppress) *p++ = c; fieldcnt++; break; } // Read a string terminated by // white-space. Add a null character // at the end of the string. case 's': { char *p; if (c == EOF) break; if (!suppress) p = va_arg(vl, char*); for ( ; (fieldwidth-- > 0) && !isspace(c) ; c = nextc(in, charcnt)) if (!suppress) *p++ = c; if (!suppress) *p = '\0'; fieldcnt++; break; } // match a single % case '%': if (c == '%') c = nextc(in, charcnt); else goodformat = 0; break; } break; } case ' ': // match white-space case '\t': // match white-space if (isspace(c)) do { svbuf.add(c); } while (isspace(c = nextc(in, charcnt))); else goodformat = 0; break; default: // match character if (c == fmt[-1]) c = nextc(in, charcnt); else goodformat = 0; break; } } if (c != EOF) in->putback(c); return fieldcnt; } !EOF! ls -l doscan.c echo x - extbuf.h sed 's/^X//' > extbuf.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // class "extensible array" // This class maintains a character array // which dynamically lengthens. The array // begins with a fixed size allocated statically, // but goes into the heap when the bounds // of that array are exceeded. #include const int extstartsize = 50; // initial size of buffer class extarray { char buf[extstartsize]; // starting buffer char *base; // ptr to current buffer char *end; // end of current buffer char *p; // current location int cursize; // size of current buffer public: // Initialize the pointers // and the static array. extarray() { base = p = buf; end = base + extstartsize; cursize = extstartsize; } // If there is a dynamic // array, delete it. ~extarray() { if (base != buf) delete base; } // Add a character to the array. // If it won't fit (along with // the null byte) lengthen the // array, going into heap memory // when necessary. void add(char c) { *p++ = c; if (p == end) { char *svp = p; char *svbase = base; base = new char[cursize + extstartsize]; memcpy(base, svbase, cursize); cursize += extstartsize; end = base + cursize; p = base + (svp - svbase); if (svbase != buf) delete svbase; } } // return the current value char *val() { *p = '\0'; return base; } // Reset the current pointer to the // beginning of the array so that it // can be reused. void reset() { p = base; } }; !EOF! ls -l extbuf.h echo x - fclose.c sed 's/^X//' > fclose.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // close the file int fclose(FILE *f) { delete f->sb; delete f; return 0; } !EOF! ls -l fclose.c echo x - feof.c sed 's/^X//' > feof.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // return TRUE if at the end of file int feof(FILE *f) { if (f->mode == input) return f->in->eof(); else return f->out->eof(); } !EOF! ls -l feof.c echo x - ferror.c sed 's/^X//' > ferror.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // return TRUE if an error condition exists int ferror(FILE *f) { if (f->mode == input) return !f->in->good(); else return !f->out->good(); } !EOF! ls -l ferror.c echo x - fflush.c sed 's/^X//' > fflush.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // flush out the stream int fflush(FILE *f) { if (f->mode != input) f->out->flush(); return ferror(f) ? EOF : 0; } !EOF! ls -l fflush.c echo x - fgetc.c sed 's/^X//' > fgetc.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Read in a single character int fgetc(FILE *f) { return getc(f); } !EOF! ls -l fgetc.c echo x - fgets.c sed 's/^X//' > fgets.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a string up to and including a newline #include char *fgets(char *buf, int length, FILE *f) { if ((f->mode == input) && (f->in->get(buf, length-2))) { char c = 0; f->in->get(c); if (c == '\n') { char *nl = buf + strlen(buf); *nl++ = '\n'; *nl = 0; } return buf; } return NULL; } !EOF! ls -l fgets.c echo x - fopen.c sed 's/^X//' > fopen.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Open a named file. // The mode can be "r", "w" or "a" FILE *fopen(const char *file, const char *fmode) { // set the modes up open_mode m = (*fmode == 'w') ? output : (*fmode == 'a') ? append : input; // open the file filebuf *st = new filebuf; st->open((char*)file, m); return new FILE(st, m); } !EOF! ls -l fopen.c echo x - fprintf.c sed 's/^X//' > fprintf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write the arguments in a formatted manner #include int fprintf(FILE *f, const char *fmt, ...) { if (f->mode != input) { va_list ap; va_start(ap, fmt); int ret = vfprintf(f, fmt, ap); va_end(ap); return ret; } return EOF; } !EOF! ls -l fprintf.c echo x - fputc.c sed 's/^X//' > fputc.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // output a character int fputc(int c, FILE *f) { return putc(c, f); } !EOF! ls -l fputc.c echo x - fputs.c sed 's/^X//' > fputs.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write a string int fputs(const char *buf, FILE *f) { if (f->mode != input) (*f->out) << buf; return ferror(stdout) ? EOF : 0; } !EOF! ls -l fputs.c echo x - fread.c sed 's/^X//' > fread.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read in num objects of the given size into the buffer int fread(void *vbuf, unsigned int size, unsigned int num, FILE *f) { char *buf = (char*)vbuf; if (f->mode == input) { // read in num * size bytes for (unsigned int n = num; n-- > 0; ) for (unsigned int s = size; s-- > 0; ) { char c; if (f->in->get(c)) *buf++ = c; else // The end of the input // partway through an object. // Return the number of complete // objects read so far. return num - n; } // Return the number of // complete objects read. return num - n; } return 0; } !EOF! ls -l fread.c echo x - freopen.c sed 's/^X//' > freopen.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Open a named file on a stdio // stream which is already active. FILE *freopen(const char *file, const char *fmode, FILE *f) { open_mode svmode = f->mode; // set the modes up open_mode m = (*fmode == 'w') ? output : (*fmode == 'a') ? append : input; // close the old stream if (svmode == input) delete f->in; else delete f->out; delete f->sb; // open the file delete f->sb; filebuf *nsb = new filebuf; nsb->open((char*)file, m); f->sb = nsb; // create the appropriate new stream if (f->mode == input) f->in = new istream(f->sb); else f->out = new ostream(f->sb); return f; } !EOF! ls -l freopen.c echo x - fscanf.c sed 's/^X//' > fscanf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a set of arguments from a file int fscanf(FILE *f, const char *fmt, ...) { if (f->mode == input) { va_list ap; va_start(ap, fmt); int ret = vfscanf(f, fmt, ap); va_end(ap); return ret; } return EOF; } !EOF! ls -l fscanf.c echo x - fwrite.c sed 's/^X//' > fwrite.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write out num objects of the given // size from the named buffer int fwrite(void *vbuf, unsigned int size, unsigned int num, FILE *f) { char *buf = (char*)vbuf; if (f->mode != input) { // read in num * size bytes for (unsigned int n = num; n-- > 0; ) for (unsigned int s = size; s-- > 0; ) if (!f->out->put(*buf++)) // The end of the output // partway through an object. // Return the number of complete // objects written so far. return num - n; // Return the number of // complete objects written return num - n; } return 0; } !EOF! ls -l fwrite.c echo x - getc.c sed 's/^X//' > getc.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Read in a single character // inline int getc(FILE *f) { unsigned char c; if ((f->mode == input) && f->in->get(c)) return c; else return EOF; } !EOF! ls -l getc.c echo x - getchar.c sed 's/^X//' > getchar.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // get a character from stdin inline int getchar() { return getc(stdin); } !EOF! ls -l getchar.c echo x - gets.c sed 's/^X//' > gets.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a string up to a newline, discarding the newline #include char *gets(char *buf) { if ((stdin->mode == input) && stdin->in->get(buf, INT_MAX)) { char c; stdin->in->get(c); return buf; } return NULL; } !EOF! ls -l gets.c echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../../CC CFLAGS= +i -g all: tst tst: extbuf.h nstdio.h scanset.h FILE.c FILE2.c FILE3.c clearerr.c doprint.c doscan.c fclose.c feof.c ferror.c fflush.c fgetc.c fgets.c fopen.c fprintf.c fputc.c fputs.c fread.c freopen.c fscanf.c fwrite.c getc.c getchar.c gets.c printf.c putc.c putchar.c puts.c scanf.c scanset1.c setbuf.c sprintf.c sscanf.c stdin.c sv_8_5.c tst.c ungetc.c vfprintf.c vfscanf.c vprintf.c vscanf.c vsprintf.c vsscanf.c ~FILE.c $(CC) $(CFLAGS) tst.c -o tst OUT= tst.out CMP= tst.cmp tst.ecmp tst.out: tst ; tst < tst.in > tst.out 2> tst.err test: all $(OUT) $(CMP) cmp tst.out tst.cmp cmp tst.err tst.ecmp cmp /etc/termcap /tmp/foo.out @echo test done !EOF! ls -l makefile echo x - nstdio.h sed 's/^X//' > nstdio.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.5 // // Implementation of standard I/O // using the stream I/O functions. #ifndef STDIO_H #define STDIO_H #include #include #undef FILE /* DELETE */ #undef _bufend /* DELETE */ #undef _bufsiz /* DELETE */ #undef getc /* DELETE */ #undef putc /* DELETE */ #undef getchar /* DELETE */ #undef putchar /* DELETE */ #undef clearerr /* DELETE */ #undef feof /* DELETE */ #undef ferror /* DELETE */ #undef fileno /* DELETE */ #undef EOF /* DELETE */ #undef NULL /* DELETE */ #undef BUFSIZ /* DELETE */ #undef stdin /* DELETE */ #undef stdout /* DELETE */ #undef stderr /* DELETE */ #undef L_ctermid /* DELETE */ #undef L_cuserid /* DELETE */ #undef P_tmpdir /* DELETE */ #undef L_tmpnam /* DELETE */ #undef _NFILE /* DELETE */ #undef _SBFSIZ /* DELETE */ #undef _IOFBF /* DELETE */ #undef _IOREAD /* DELETE */ #undef _IOWRT /* DELETE */ #undef _IONBF /* DELETE */ #undef _IOMYBUF /* DELETE */ #undef _IOEOF /* DELETE */ #undef _IOERR /* DELETE */ #undef _IOLBF /* DELETE */ #undef _IORW /* DELETE */ #define FILE xFILE /* DELETE */ #define BUFSIZ xBUFSIZ /* DELETE */ #define EOF xEOF /* DELETE */ #define clearerr xclearerr /* DELETE */ #define fclose xfclose /* DELETE */ #define feof xfeof /* DELETE */ #define ferror xferror /* DELETE */ #define fflush xfflush /* DELETE */ #define fgetc xfgetc /* DELETE */ #define fgets xfgets /* DELETE */ #define fileno xfileno /* DELETE */ #define fopen xfopen /* DELETE */ #define fprintf xfprintf /* DELETE */ #define fputc xfputc /* DELETE */ #define fputs xfputs /* DELETE */ #define fread xfread /* DELETE */ #define freopen xfreopen /* DELETE */ #define fscanf xfscanf /* DELETE */ #define fwrite xfwrite /* DELETE */ #define getc xgetc /* DELETE */ #define getchar xgetchar /* DELETE */ #define gets xgets /* DELETE */ #define printf xprintf /* DELETE */ #define putc xputc /* DELETE */ #define putchar xputchar /* DELETE */ #define scanf xscanf /* DELETE */ #define setbuf xsetbuf /* DELETE */ #define sprintf xsprintf /* DELETE */ #define sscanf xsscanf /* DELETE */ #define stderr xstderr /* DELETE */ #define stdin xstdin /* DELETE */ #define stdout xstdout /* DELETE */ #define ungetc xungetc /* DELETE */ #define vfprintf xvfprintf /* DELETE */ #define vfscanf xvfscanf /* DELETE */ #define vprintf xvprintf /* DELETE */ #define vscanf xvscanf /* DELETE */ #define vsprintf xvsprintf /* DELETE */ #define vsscanf xvsscanf /* DELETE */ class FILE { open_mode mode; union { istream *in; ostream *out; }; streambuf *sb; char unbuf; public: FILE(streambuf *st, open_mode m); FILE(istream *is); FILE(ostream *os); ~FILE(); // open and close FILEs friend FILE *fopen(const char *file, const char *mode); friend FILE *freopen(const char *file, const char *mode, FILE *f); friend int fclose(FILE *); // input functions friend int getc(FILE *); friend int ungetc(int const, FILE *); friend int fgetc(FILE *); friend int getchar(); friend char *gets(char *buf); friend char *fgets(char *buf, int sz, FILE *); friend int fread(void *buf, unsigned int sz, unsigned int n, FILE *); friend int scanf(const char *fmt, ...); friend int fscanf(FILE *, const char *fmt, ...); friend int sscanf(const char *buf, const char *fmt, ...); friend int vscanf(const char *fmt, va_list vl); friend int vfscanf(FILE *f, const char *fmt, va_list vl); friend int vsscanf(const char *str, const char *fmt, va_list vl); // output functions friend int putc(int c, FILE *); friend int putchar(int c); friend int fputc(int c, FILE *); friend int puts(const char *buf); friend int fputs(const char *buf, FILE *); friend int fwrite(void *buf, unsigned int sz, unsigned int n, FILE *); friend int printf(const char *fmt, ...); friend int fprintf(FILE *, const char *fmt, ...); friend int sprintf(char *buf, const char *fmt, ...); friend int vprintf(const char *fmt, va_list); friend int vfprintf(FILE *, const char *fmt, va_list); friend int vsprintf(char *buf, const char *fmt, va_list); // status manipulation and checking friend int ferror(FILE *); friend int feof(FILE *); friend void clearerr(FILE *); // buffering manipulation friend void setbuf(FILE *, char *); friend int fflush(FILE *); }; #define NULL 0 const int EOF = -1; const int BUFSIZ = 1024; extern FILE *stdin, *stdout, *stderr; #endif /* STDIO_H */ !EOF! ls -l nstdio.h echo x - printf.c sed 's/^X//' > printf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write the arguments in a formatted manner to stdout #include int printf(const char *fmt, ...) { if (stdout->mode != input) { va_list ap; va_start(ap, fmt); int ret = vprintf(fmt, ap); va_end(ap); return ret; } return EOF; } !EOF! ls -l printf.c echo x - putc.c sed 's/^X//' > putc.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // output a character // inline int putc(int c, FILE *f) { if (f->mode != input) f->out->put(c); return c; } !EOF! ls -l putc.c echo x - putchar.c sed 's/^X//' > putchar.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // output a character to stdout // inline int putchar(int c) { return putc(c, stdout); } !EOF! ls -l putchar.c echo x - puts.c sed 's/^X//' > puts.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write a string to stdout, adding a newline int puts(const char *buf) { if (stdout->mode != input) (*stdout->out) << buf << "\n"; return ferror(stdout) ? EOF : 0; } !EOF! ls -l puts.c echo x - scanf.c sed 's/^X//' > scanf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a set of arguments from stdin int scanf(const char *fmt, ...) { if (stdin->mode == input) { va_list ap; va_start(ap, fmt); int ret = vscanf(fmt, ap); va_end(ap); return ret; } return EOF; } !EOF! ls -l scanf.c echo x - scanset.h sed 's/^X//' > scanset.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ /* declare a class for use in manipulating */ /* scansets such as [a-zA-Z] */ #include class scanset { unsigned char set[UCHAR_MAX + 1]; public: scanset(const char *pattern, const char **retpat = 0); match(int c) { return ((c >= 0) && (c <= UCHAR_MAX)) ? set[c] : 0; } }; !EOF! ls -l scanset.h echo x - scanset1.c sed 's/^X//' > scanset1.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // construct the scanset scanset::scanset(const char *pattern, const char **retpat) { // Set the value which indicates a match based // on whether the set is complemented or not. int match = 1; if (*pattern == '^') { match = 0; pattern++; } // Initialize the array for all non-matches. memset(set, !match, UCHAR_MAX + 1); // The first character is special and // can contain `]' or `-'. if ((*pattern == ']') || (*pattern == '-')) set[*pattern++] = match; // Run down the pattern looking for the `]', // setting appropriate members of the // set to match. for ( ; *pattern && (*pattern != ']'); pattern++) // either a range or trailing `-' if (*pattern == '-') { // special case for trailing `-' if (pattern[1] == ']') set['-'] = match; // char range, a-z else { for (int i = pattern[-1] + 1; i <= pattern[1]; i++) set[i] = match; pattern++; } } else set[*pattern] = match; // The pattern now points to the `]'. // Return the value just beyond it. if (retpat) *retpat = pattern + 1; } !EOF! ls -l scanset1.c echo x - setbuf.c sed 's/^X//' > setbuf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // change the buffering associated with a stream void setbuf(FILE *f, char *buf) { #undef setbuf /* DELETE */ if (f->sb) if (buf) f->sb->setbuf(buf, BUFSIZ); else f->sb->setbuf(&(f->unbuf), 1); #define setbuf xsetbuf /* DELETE */ } !EOF! ls -l setbuf.c echo x - sprintf.c sed 's/^X//' > sprintf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write the arguments in a formatted manner to a string #include int sprintf(char *s, const char *fmt, ...) { if (s) { va_list ap; va_start(ap, fmt); int ret = vsprintf(s, fmt, ap); va_end(ap); return ret; } return EOF; } !EOF! ls -l sprintf.c echo x - sscanf.c sed 's/^X//' > sscanf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a set of arguments from a string int sscanf(const char *s, const char *fmt, ...) { if (s) { va_list ap; va_start(ap, fmt); int ret = vsscanf(s, fmt, ap); va_end(ap); return ret; } return EOF; } !EOF! ls -l sscanf.c echo x - stdin.c sed 's/^X//' > stdin.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // define the preopened FILEs and // tie them to the preopened streams static FILE fstdin(&cin); static FILE fstdout(&cout); static FILE fstderr(&cerr); FILE *stdin = &fstdin; FILE *stdout = &fstdout; FILE *stderr = &fstderr; !EOF! ls -l stdin.c echo x - tst.c sed 's/^X//' > tst.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include "nstdio.h" #include inline unsigned long strtoul(const char *nptr, char **endptr, int base) { return (unsigned long) strtol(nptr, endptr, base); } #include "FILE.c" #include "FILE2.c" #include "FILE3.c" #include "clearerr.c" #include "doprint.c" #include "doscan.c" #include "fclose.c" #include "feof.c" #include "ferror.c" #include "fflush.c" #include "fgetc.c" #include "fgets.c" #include "fopen.c" #include "fprintf.c" #include "fputc.c" #include "fputs.c" #include "fread.c" #include "freopen.c" #include "fscanf.c" #include "fwrite.c" #include "getc.c" #include "getchar.c" #include "gets.c" #include "printf.c" #include "putc.c" #include "putchar.c" #include "puts.c" #include "scanf.c" #include "scanset1.c" #include "setbuf.c" #include "sprintf.c" #include "sscanf.c" #include "stdin.c" #include "ungetc.c" #include "vfprintf.c" #include "vfscanf.c" #include "vprintf.c" #include "vscanf.c" #include "vsprintf.c" #include "vsscanf.c" #include "~FILE.c" main() { FILE *tp = fopen("/etc/termcap", "r"); if (!tp) { (void) fprintf (stderr, "cannot open /etc/termcap\n"); exit(1); } else (void) fprintf (stderr, "openned /etc/termcap\n"); FILE *op = fopen("/tmp/foo.out", "w"); if (!op) { (void) fprintf (stderr, "cannot open /tmp/foo.out\n"); exit(1); } else (void) fprintf (stderr, "openned /tmp/foo.out\n"); int c; while ((c = getc(tp)) != EOF) putc(c, op); printf("feof(tp)==%d\n", feof(tp)); printf("ferror(tp)==%d\n", ferror(tp)); printf("feof(op)==%d\n", feof(op)); printf("ferror(op)==%d\n", ferror(op)); fclose(op); fclose(tp); (void) fprintf (stderr, "all done\n"); tp = fopen("/etc/termcap", "r"); if (!tp) { (void) fprintf (stderr, "cannot open /etc/termcap\n"); exit(1); } else (void) fprintf (stderr, "openned /etc/termcap\n"); op = fopen("/tmp/foo2.out", "w"); if (!op) { (void) fprintf (stderr, "cannot open /tmp/foo2.out\n"); exit(1); } else (void) fprintf (stderr, "openned /tmp/foo2.out\n"); char buf[BUFSIZ]; while (fgets(buf, sizeof buf, tp)) fputs(buf, op); printf("feof(tp)==%d\n", feof(tp)); printf("ferror(tp)==%d\n", ferror(tp)); printf("feof(op)==%d\n", feof(op)); printf("ferror(op)==%d\n", ferror(op)); fclose(op); fclose(tp); (void) fprintf (stderr, "all done\n"); int x; int ret = scanf("%d", &x); (void) printf("scanf returns %d, x = %d\n", ret, x); ret = scanf(" %5[a-d]xyz %d", buf, &x); (void) printf("scanf returns %d, buf = '%s', x = %d\n", ret, buf, x); return 0; } !EOF! ls -l tst.c echo x - tst.cmp sed 's/^X//' > tst.cmp << '!EOF!' feof(tp)==1 ferror(tp)==1 feof(op)==0 ferror(op)==0 feof(tp)==1 ferror(tp)==1 feof(op)==0 ferror(op)==0 scanf returns 1, x = 15 scanf returns 2, buf = 'dcba', x = 27 !EOF! ls -l tst.cmp echo x - tst.ecmp sed 's/^X//' > tst.ecmp << '!EOF!' openned /etc/termcap openned /tmp/foo.out all done openned /etc/termcap openned /tmp/foo2.out all done !EOF! ls -l tst.ecmp echo x - tst.err sed 's/^X//' > tst.err << '!EOF!' openned /etc/termcap openned /tmp/foo.out all done openned /etc/termcap openned /tmp/foo2.out all done !EOF! ls -l tst.err echo x - tst.in sed 's/^X//' > tst.in << '!EOF!' 15 dcbaxyz 27 !EOF! ls -l tst.in echo x - ungetc.c sed 's/^X//' > ungetc.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // put back a single character previously read in inline int ungetc(const int c, FILE *f) { if (f->mode == input) f->in->putback(c); return c; } !EOF! ls -l ungetc.c echo x - vfprintf.c sed 's/^X//' > vfprintf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write a variable argument list in a formatted manner int vfprintf(FILE *f, const char *fmt, va_list vl) { if (f->mode != input) return _doprint(f->out, fmt, vl); return EOF; } !EOF! ls -l vfprintf.c echo x - vfscanf.c sed 's/^X//' > vfscanf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a variable argument list in a // formatted manner from a given file int vfscanf(FILE *f, const char *fmt, va_list vl) { if (f->mode == input) return _doscanf(f->in, fmt, vl); else return EOF; } !EOF! ls -l vfscanf.c echo x - vprintf.c sed 's/^X//' > vprintf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write a variable argument list // in a formatted manner to stdout int vprintf(const char *fmt, va_list vl) { if (stdout->mode != input) return _doprint(stdout->out, fmt, vl); return EOF; } !EOF! ls -l vprintf.c echo x - vscanf.c sed 's/^X//' > vscanf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a variable argument list in a // formatted manner from stdin int vscanf(const char *fmt, va_list vl) { if (stdin->mode == input) return _doscanf(stdin->in, fmt, vl); else return EOF; } !EOF! ls -l vscanf.c echo x - vsprintf.c sed 's/^X//' > vsprintf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // write a variable argument list // in a formatted manner to a string #include int vsprintf(char *s, const char *fmt, va_list vl) { ostream f(INT_MAX, s); return _doprint(&f, fmt, vl); } !EOF! ls -l vsprintf.c echo x - vsscanf.c sed 's/^X//' > vsscanf.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // read a variable argument list in a // formatted manner from a string int vsscanf(const char *str, const char *fmt, va_list vl) { istream in(strlen(str), (char*)str); return _doscanf(&in, fmt, vl); } !EOF! ls -l vsscanf.c echo x - ~FILE.c sed 's/^X//' > ~FILE.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // free the stream created for a FILE FILE::~FILE() { if (sb) if (mode == input) delete in; else delete out; } !EOF! ls -l ~FILE.c # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0