#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # 8_11.h 8_11a.h makefile rc.h rctst.c tst.cmp tst.data tst.save tst2.cmp # # 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:12:05 EDT 1990 # echo x - 8_11.h sed 's/^X//' > 8_11.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.11 // Generic random access to objects kept within a file. // The user would use the generic class randomOBJ // for a user type TYPE by the following steps: // // declare(randomOBJ,TYPE) // implement(randomOBJ,TYPE) // ... // randomOBJ(TYPE) x("filename", // read-err-func, write-err-func); // randomOBJ(TYPE) y("filename"); #ifndef RANDACCESS_H #define RANDACCESS_H #include #include #include "8_11a.h" /* EXPAND */ /* An extended FILE which keeps track of its current location within the file. This class has no type-specific implementation and can be used across all instantiations of randomOBJ. */ class eFILE { long fileoffset; FILE *fp; eFILE() { }; public: friend eFILE *efopen(char *file); friend void efclose(eFILE *efp); friend int egetobj(eFILE *efp, long offset, void *obj, unsigned szobj); friend int eputobj(eFILE *efp, long offset, void *obj, unsigned szobj); }; #define randomOBJdeclare(type) \ class randomOBJ(type); \ \ class OBJrandomloc(type) \ { \ randomOBJ(type) *rOBJ; \ long thisoffset; \ \ public: \ OBJrandomloc(type)(randomOBJ(type) *robj, \ long offset) \ { \ rOBJ = robj; \ thisoffset = offset; \ } \ \ operator type(); \ \ OBJrandomloc(type) operator=(type newobj); \ OBJrandomloc(type) operator=( \ OBJrandomloc(type) r); \ }; \ \ class randomOBJ(type) \ { \ eFILE *rfp; \ void (*rdrfnc)(type *); \ void (*wtrfnc)(type *); \ friend OBJrandomloc(type); \ OBJrandomloc(type) operator=(type newobj); \ \ public: \ randomOBJ(type)(char *filename, \ void (*rfnc)(type *) = 0, \ void (*wfnc)(type *) = 0) \ { \ rfp = efopen(filename); \ rdrfnc = rfnc; \ wtrfnc = wfnc; \ } \ \ ~randomOBJ(type)() \ { \ efclose(rfp); \ } \ \ int openedokay() \ { \ return rfp != 0; \ } \ \ OBJrandomloc(type) operator[](long offset) \ { \ OBJrandomloc(type) ret(this, offset); \ return ret; \ } \ }; #define randomOBJimplement(type) \ OBJrandomloc(type)::operator type() \ { \ type x; \ if (!egetobj(rOBJ->rfp, thisoffset, &x, \ sizeof x)) \ if (rOBJ->rdrfnc) \ (*rOBJ->rdrfnc)(&x); \ return x; \ } \ \ OBJrandomloc(type) OBJrandomloc(type)::operator=( \ type newobj) \ { \ if (!eputobj(rOBJ->rfp, thisoffset, \ &newobj, sizeof newobj)) \ if (rOBJ->wtrfnc) \ (*rOBJ->wtrfnc)(&newobj); \ return *this; \ } \ \ OBJrandomloc(type) OBJrandomloc(type)::operator=( \ OBJrandomloc(type) r) \ { \ return (*this = (type) r); \ } #endif /* RANDACCESS_H */ !EOF! ls -l 8_11.h echo x - 8_11a.h sed 's/^X//' > 8_11a.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #define randomOBJ(type) name3(type,random,OBJ) #define OBJrandomloc(type) name3(type,OBJ,randomloc) !EOF! ls -l 8_11a.h echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../../CC CFLAGS= +i -g all: rctst rctst: rctst.c rc.h 8_11a.h ../8.10dir/pr.c ../8.9dir/8_9a2.c \ ../8.9dir/8_9a3.c ../8.10dir/8_10a4.c ../8.10dir/8_10a5.c $(CC) $(CFLAGS) rctst.c -o rctst CMP= tst.cmp tst2.cmp OUT= tst.out tst.out: rctst tst.save cp tst.save tst.data rctst > tst.out test: $(CMP) $(OUT) cmp tst.out tst.cmp cmp tst.data tst2.cmp @echo test done !EOF! ls -l makefile echo x - rc.h sed 's/^X//' > rc.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.11 // Generic random access to objects kept within a file. // The user would use the generic class randomOBJ // for a user type TYPE by the following steps: // // declare(randomOBJ,TYPE) // implement(randomOBJ,TYPE) // ... // randomOBJ(TYPE) x("filename", // read-err-func, write-err-func); // randomOBJ(TYPE) y("filename"); #ifndef RANDACCESS_H #define RANDACCESS_H #include #include #include "8_11a.h" /* EXPAND */ /* An extended FILE which keeps track of its current location within the file. This class has no type-specific implementation and can be used across all instantiations of randomOBJ. */ class eFILE { long fileoffset; FILE *fp; eFILE() { }; public: friend eFILE *efopen(char *file); friend void efclose(eFILE *efp); friend int egetobj(eFILE *efp, long offset, void *obj, unsigned szobj); friend int eputobj(eFILE *efp, long offset, void *obj, unsigned szobj); }; #define randomOBJdeclare(type) \ class randomOBJ(type); \ \ class OBJrandomloc(type) \ { \ randomOBJ(type) *rOBJ; \ long thisoffset; \ \ public: \ OBJrandomloc(type)(randomOBJ(type) *robj, \ long offset) \ { \ rOBJ = robj; \ thisoffset = offset; \ } \ \ operator type(); \ \ OBJrandomloc(type) operator=(type newobj); \ OBJrandomloc(type) operator=( \ OBJrandomloc(type) r); \ }; \ \ class randomOBJ(type) \ { \ eFILE *rfp; \ void (*rdrfnc)(type *); \ void (*wtrfnc)(type *); \ friend OBJrandomloc(type); \ OBJrandomloc(type) operator=(type newobj); \ \ public: \ randomOBJ(type)(char *filename, \ void (*rfnc)(type *) = 0, \ void (*wfnc)(type *) = 0) \ { \ rfp = efopen(filename); \ rdrfnc = rfnc; \ wtrfnc = wfnc; \ } \ \ ~randomOBJ(type)() \ { \ efclose(rfp); \ } \ \ int openedokay() \ { \ return rfp != 0; \ } \ \ OBJrandomloc(type) operator[](long offset) \ { \ OBJrandomloc(type) ret(this, offset); \ return ret; \ } \ }; #define randomOBJimplement(type) \ OBJrandomloc(type)::operator type() \ { \ type x; \ if (!egetobj(rOBJ->rfp, thisoffset, &x, \ sizeof x)) \ if (rOBJ->rdrfnc) \ (*rOBJ->rdrfnc)(&x); \ return x; \ } \ \ OBJrandomloc(type) OBJrandomloc(type)::operator=( \ type newobj) \ { \ if (!eputobj(rOBJ->rfp, thisoffset, \ &newobj, sizeof newobj)) \ if (rOBJ->wtrfnc) \ (*rOBJ->wtrfnc)(&newobj); \ return *this; \ } \ \ OBJrandomloc(type) OBJrandomloc(type)::operator=( \ OBJrandomloc(type) r) \ { \ return (*this = (type) r); \ } #endif /* RANDACCESS_H */ !EOF! ls -l rc.h echo x - rctst.c sed 's/^X//' > rctst.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include #include struct INT { char x[4]; }; #define XXXXOBJ INT #include "../8.10dir/pr.c" #include "rc.h" declare(randomOBJ,INT); implement(randomOBJ,INT); #include "../8.9dir/8_9a2.c" #include "../8.9dir/8_9a3.c" #include "../8.10dir/8_10a4.c" #include "../8.10dir/8_10a5.c" int main(int, char**) { randomOBJ(INT) x("tst.data"); INT i = x[3]; pr("x[3] = ", i); i = x[2]; pr("x[2] = ", i); i.x[0] = '3'; i.x[1] = ';'; pr("i = ", i); x[1] = i; cout << "assigned x[1] <- i('3;')\n"; x[0] = x[8]; cout << "assigned x[0] <- x[8]\n"; i = x[8]; pr("x[8] = ", i); i = x[0]; pr("x[0] = ", i); return 0; } !EOF! ls -l rctst.c echo x - tst.cmp sed 's/^X//' > tst.cmp << '!EOF!' x[3] = 10,111(o),116(t),104(h) x[2] = 114(r),111(o),111(o),116(t) i = 51(3),59(;),111(o),116(t) assigned x[1] <- i('3;') assigned x[0] <- x[8] x[8] = 111(o),116(t),44(,),98(b) x[0] = 111(o),116(t),44(,),98(b) !EOF! ls -l tst.cmp echo x - tst.data sed 's/^X//' > tst.data << '!EOF!' ot,b3;otroot other::1: bin::2:root,bin,daemon sys::3:root,bin,sys,adm adm::4:root,adm,daemon uucp::5:root,uucp mail::6:root daemon::12:root,daemon docx::21:pcor,russak,mds,dsl,jeremy,bwp,hansen,coleman,chu,jack guest::22: !EOF! ls -l tst.data echo x - tst.save sed 's/^X//' > tst.save << '!EOF!' root::0:root other::1: bin::2:root,bin,daemon sys::3:root,bin,sys,adm adm::4:root,adm,daemon uucp::5:root,uucp mail::6:root daemon::12:root,daemon docx::21:pcor,russak,mds,dsl,jeremy,bwp,hansen,coleman,chu,jack guest::22: !EOF! ls -l tst.save echo x - tst2.cmp sed 's/^X//' > tst2.cmp << '!EOF!' ot,b3;otroot other::1: bin::2:root,bin,daemon sys::3:root,bin,sys,adm adm::4:root,adm,daemon uucp::5:root,uucp mail::6:root daemon::12:root,daemon docx::21:pcor,russak,mds,dsl,jeremy,bwp,hansen,coleman,chu,jack guest::22: !EOF! ls -l tst2.cmp # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0