#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # 5_10a.h 5_10a1.c 5_10a2.c 5_10a3.c 5_10c.h 5_10c0.h 5_10c1.h 5_10c2.h 5_10c3.h 5_10c4.h 5_10c5.c 5_10c5.cmp makefile table.h tableentry.h tst.c tst2.c tstc.c tstc.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:04:41 EDT 1990 # echo x - 5_10a.h sed 's/^X//' > 5_10a.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 5.10 // class table #ifndef TABLE_H #define TABLE_H #include /* declare the class which contains the names, */ /* values and pointers for a list of these names */ struct name { char *string; name *next; union { double dvalue; float fvalue; void *pvalue; void (*pfvalue)(); long lvalue; short svalue; unsigned long ulvalue; unsigned short usvalue; }; name(char *str) { string = new char[strlen(str) + 1]; strcpy(string, str); dvalue = 0; } ~name() { delete string; } }; class table { name **tbl; int size; public: table(int sz = 23); ~table(); name *look(char*, int = 0); name *insert(char *s) { return look(s, 1); } name *lookfor(char *s) { return look(s, 2); } }; #endif /* TABLE_H */ !EOF! ls -l 5_10a.h echo x - 5_10a1.c sed 's/^X//' > 5_10a1.c << '!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. */ // look up a name within a symbol table #include #include #include name *table::look(char *p, int ins) { // hash the name int ii = 0; char *pp = p; while (*pp) ii = (ii << 1) ^ *pp++; if (ii < 0) ii = -ii; ii %= size; // run down that list, looking for the name for (name *n = tbl[ii]; n; n = n->next) if (strcmp(p, n->string) == 0) return n; // the name was not found switch (ins) { case 0: error("name not found"); return 0; case 2: return 0; case 1: name *nn = new name(p); nn->next = tbl[ii]; tbl[ii] = nn; return nn; default: error("unknown ins value for table::look()"); return 0; } } !EOF! ls -l 5_10a1.c echo x - 5_10a2.c sed 's/^X//' > 5_10a2.c << '!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. */ // construct a symbol table #include #include table::table(int sz) { if (sz <= 0) error("non-positive table size"); tbl = new name*[size = sz]; for (int i = 0; i < sz; i++) tbl[i] = 0; } !EOF! ls -l 5_10a2.c echo x - 5_10a3.c sed 's/^X//' > 5_10a3.c << '!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. */ // cleanup a symbol table #include table::~table() { for (int i = 0; i < size; i++) for (name *n = tbl[i]; n; n = n->next) delete n; delete tbl; } !EOF! ls -l 5_10a3.c echo x - 5_10c.h sed 's/^X//' > 5_10c.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // exercise 5.10 // class entry table #ifndef TABLEENTRY_H #define TABLEENTRY_H #include #include "5_10c0.h" // EXPAND public: tableentry(); ~tableentry(); int getvardata(char *, vardata **); vardata* settype(char *, vartypes); }; #endif /* TABLEENTRY_H */ !EOF! ls -l 5_10c.h echo x - 5_10c0.h sed 's/^X//' > 5_10c0.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ enum vartypes { tinteger = '%', tsingle = '!', tdouble = '#', tstring = '$' }; const sizeinteger = 4, sizesingle = 4, sizedouble = 8, sizestring = 8; struct vardata { vartypes type; long address; }; class tableentry { table *tbl; long address_offset; // ... !EOF! ls -l 5_10c0.h echo x - 5_10c1.h sed 's/^X//' > 5_10c1.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // allocate the symbol table tableentry::tableentry() { tbl = new table; address_offset = 0; } !EOF! ls -l 5_10c1.h echo x - 5_10c2.h sed 's/^X//' > 5_10c2.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // deallocate the symbol table tableentry::~tableentry() { delete tbl; } !EOF! ls -l 5_10c2.h echo x - 5_10c3.h sed 's/^X//' > 5_10c3.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Get the type and address back for a given variable. // Also return an indication of whether we had to // allocate the variable here. #include int tableentry::getvardata(char *nm, vardata **addr) { name *n = tbl->lookfor(nm); // name not found, allocate its data now if (!n) { // the last char is the type of the variable char *lastchar = strchr(nm, '\0') - 1; *addr = settype(nm, *lastchar); return 1; } // the name is there, return its data else { *addr = (vardata*)(n->pvalue); return 0; } } !EOF! ls -l 5_10c3.h echo x - 5_10c4.h sed 's/^X//' > 5_10c4.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Allocate the space and set the type for a given name vardata* tableentry::settype(char *nm, vartypes v) { // allocate the data space name *n = tbl->insert(nm); vardata *nv = new vardata; n->pvalue = nv; nv->address = address_offset; // add in the appropriate size switch (v) { case tinteger: nv->type = tinteger; address_offset += sizeinteger; break; case tsingle: nv->type = tsingle; address_offset += sizesingle; break; default: case tdouble: nv->type = tdouble; address_offset += sizedouble; break; case tstring: nv->type = tstring; address_offset += sizestring; break; } return nv; } !EOF! ls -l 5_10c4.h echo x - 5_10c5.c sed 's/^X//' > 5_10c5.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 5.10 // demonstration program showing the use // of the tableentry class #include #include #include "5_10c1.h" /* DELETE tableentry::tableentry() */ #include "5_10c2.h" /* DELETE tableentry::~tableentry() */ #include "5_10c3.h" /* DELETE tableentry::getvardata() */ #include "5_10c4.h" /* DELETE tableentry::settype() */ tableentry namespace; void showvar(char *varname) { vardata *v; int newvar = namespace.getvardata(varname, &v); cout << "name='" << varname << "'\n"; cout << "\taddress=" << v->address << "\n"; cout << "\ttype=" << chr(v->type) << "\n"; if (newvar) cout << "\tvariable is new\n"; } main(int,char**) { showvar("hello#"); showvar("there!"); showvar("howare#"); showvar("you"); showvar("hello#"); showvar("howare!"); showvar("you"); return 0; } !EOF! ls -l 5_10c5.c echo x - 5_10c5.cmp sed 's/^X//' > 5_10c5.cmp << '!EOF!' name='hello#' address=0 type=# variable is new name='there!' address=8 type=! variable is new name='howare#' address=12 type=# variable is new name='you' address=20 type=# variable is new name='hello#' address=0 type=# name='howare!' address=28 type=! variable is new name='you' address=20 type=# !EOF! ls -l 5_10c5.cmp echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../../CC ERROR= ../../error.o CFLAGS= -I. all: 5_10c5 tstc tst.o 5_10c5: 5_10c5.o 5_10a2.o 5_10a3.o 5_10a1.o $(CC) $(CFLAGS) 5_10c5.o 5_10a2.o 5_10a3.o 5_10a1.o -o 5_10c5 $(ERROR) tstc: tstc.o 5_10a2.o 5_10a3.o 5_10a1.o $(CC) $(CFLAGS) tstc.o 5_10a2.o 5_10a3.o 5_10a1.o -o tstc $(ERROR) tstc.o: tstc.c 5_10c0.h 5_10c1.h 5_10c2.h 5_10c3.h 5_10c4.h 5_10c5.o: 5_10c5.c 5_10c0.h 5_10c1.h 5_10c2.h 5_10c3.h 5_10c4.h tst.o: tst.c 5_10a.h 5_10a1.c 5_10a2.c 5_10a3.c $(CC) -c $(CFLAGS) tst.c CMP= tstc.cmp 5_10c5.cmp OUT= tstc.out 5_10c5.out tstc.out: tstc ; tstc > tstc.out 5_10c5.out: 5_10c5 ; 5_10c5 > 5_10c5.out test: all $(OUT) $(CMP) cmp tstc.out tstc.cmp cmp 5_10c5.out 5_10c5.cmp echo tests done !EOF! ls -l makefile echo x - table.h sed 's/^X//' > table.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include "5_10a.h" !EOF! ls -l table.h echo x - tableentry.h sed 's/^X//' > tableentry.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include "5_10c.h" !EOF! ls -l tableentry.h 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 #include #include "5_10a1.c" // table::look() #include "5_10a2.c" // table::table() #include "5_10a3.c" // table::~table() !EOF! ls -l tst.c echo x - tst2.c sed 's/^X//' > tst2.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #define x(t, xn) \ cout << "t.get(" << xn << ")=" << t.getaddress(xn, &addr) << "\n"; \ cout << "\taddr=" << addr << "\n" main() { const int SizeInteger = 4, SizeSingle = 4, SizeDouble = 8, SizeString = 4; tableentry integers(SizeInteger); tableentry singles(SizeSingle); tableentry doubles(SizeDouble); tableentry strings(SizeString); long addr; x(integers, "hello"); x(strings, "hello"); x(integers, "there"); x(integers, "hi"); x(strings, "hello"); x(integers, "hello"); return 0; } !EOF! ls -l tst2.c echo x - tstc.c sed 's/^X//' > tstc.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include #include "5_10c.h" // class tableentry #include "5_10c1.h" // tableentry::tableentry() #include "5_10c2.h" // tableentry::~tableentry() #include "5_10c3.h" // tableentry::getvardata() #include "5_10c4.h" // tableentry::settype() #define x(xn) \ cout << "namespace.get(" << xn << ")=" << namespace.getvardata(xn, &v) << "\n" \ << "\taddr=" << v->address << "\n" \ << "\ttype='" << chr(v->type) << "'\n" main() { tableentry namespace; vardata *v; x("hello"); x("hello"); x("there"); x("hi"); x("hello"); x("hello"); return 0; } !EOF! ls -l tstc.c echo x - tstc.cmp sed 's/^X//' > tstc.cmp << '!EOF!' namespace.get(hello)=1 addr=0 type='#' namespace.get(hello)=0 addr=0 type='#' namespace.get(there)=1 addr=8 type='#' namespace.get(hi)=1 addr=16 type='#' namespace.get(hello)=0 addr=0 type='#' namespace.get(hello)=0 addr=0 type='#' !EOF! ls -l tstc.cmp # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0