};


const TBLSZ = 23;
name* table[TBLSZ];

int no_of_errors;

double error(char* s) {
cerr << "error: " << s << "\n";
no_of_errors++;
return 1;
}

extern int strlen(const char*);
extern int strcmp(const char*, const char*);
extern char* strcpy(char*, const char*);

name* look(char* p, int ins = 0)
{
int ii= 0;
char *pp = p;
while (*pp) ii = ii<<1 ^ *pp++;
if (ii < 0) ii = -ii;
ii %= TBLSZ;

for (name* n=table [ii]; n; n=n->next)
if (strcmp(p,n->string) == 0) return n;

if (ins == 0) error("name not found");

name* nn = new name;
nn->string = new char[strlen(p) + 1];
strcpy(nn->string,p);
nn->value = 1;
nn->next = table[ii];
table[ii] = nn;
return nn;
}

inline name* insert(char* s) { return look (s,1); }

token_value get_token();
double term();

double expr()
{
double left = term();

for (;;)
switch (curr_tok) {
case PLUS:
get_token();
left += term();
break;
case MINUS:
get_token();
left -= term();
break;
default :
return left;
}
}

double prim();

double term()
{
double left = prim();

for (;;)
switch (curr_tok) {
case MUL:
get_token();
left *= prim();
break;
case DIV:
get_token();
double d = prim();
if (d == 0) return error("divide by o");
left /= d;
break;
default:
return left;
}
}
int number_value;
char name_string[80];

double prim()
{
switch (curr_tok) {
case NUMBER:
get_token();
return number_value;
case NAME:
if (get_token() == ASSIGN) {
name* n = insert(name_string);
get_token();
n->value = expr();
return n->value;
}
return look(name_string)->value;
case MINUS:
get_token();
return -prim();
case LP:
get_token();
double e = expr();
if (curr_tok != RP) return error(") expected");
get_token();
return e;
case END:
return 1;
default:
return error ("primary expected");
}
}

token_value get_token()
{
char ch = 0;

do {
if(!cin.get(ch)) return curr_tok = END;
} while (ch!='\n' && isspace(ch));

switch (ch) {
case ';':
case '\n':
cin >> WS;
return curr_tok=PRINT;
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
return curr_tok=ch;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
cin.putback(ch);
cin >> number_value;
return curr_tok=NUMBER;
default:
if (isalpha(ch)) {
char* p = name_string;
*p++ = ch;
while (cin.get(ch) && isalnum(ch)) *p++ = ch;
cin.putback(ch);
*p = 0;
return curr_tok=NAME;
}
error ("bad token");
return curr_tok=PRINT;
}
}

int main(int argc, char* argv[])
{
switch (argc) {
case 1:
break;
case 2:
cin = *new istream(strlen(argv[1]),argv[1]);
break;
default:
error("too many arguments");
return 1;
}

// insert predefined names:
insert("pi")->value = 3.1415926535897932385;
insert("e")->value = 2.7182818284590452354;

while (1) {
get_token();
if( curr_tok == END) break;
if (curr_tok == PRINT) continue;
cout << expr() << "\n";
}

return no_of_errors;
}



    b3_2_6a.cxx


extern void strcpy(char *,char *);
extern void exit(int);
extern int strlen(char *);

char *save_string(char* p)
{
char* s = new char[strlen(p)+1];
strcpy(s,p);
return s;
}

int main (int argc, char* argv[])
{
if (argc < 2) exit(1);
int size = strlen(argv[1])+1;
char* p = save_string (argv[1]);
delete[size] p;
}



    b3_2_6b.cxx


#include <stream.hxx>

extern void exit( int );
void out_of_store()
{

cout << "operator new failed: out of store\n";
exit(1);
}

typedef void (*PF)();

extern PF set_new_handler(PF);

main()
{
set_new_handler(&out_of_store);
char *p = new char[100000000];
cout << "done, p = " << long(p) << "\n";
}



    b4_6_8.cxx


// This version of the program does not assume sizeof(int)==sizeof(char*) !

#include <stream.hxx>
#include <stdarg.hxx>

extern void exit(int);
void error (int ...);

main(int argc, char* argv[])
{
switch (argc) {
case 1:
error(0,argv[0],(char*)0);
break;
case 2:
error(0,argv[0],argv[1],(char*)0);
break;
default :
error(1,"with",dec(argc-1),"arguments",(char*)0);
}
}


void error(int n ...)
{
va_list ap;
va_start(ap,n);

for (;;) {
char *p = va_arg(ap,char*);
if (p == 0) break;
cerr << p << " ";
}

va_end(ap);

cerr << "\n";
if (n) exit(n);
}

    b4_6_9.cxx


#include <stream.hxx>

struct user {
char *name;
char* id;
int dept;
};

typedef user* Puser;

user heads[] = {
"Mcilroy M.D", "doug", 11271,
"Aho A.v.", "ava", 11272,
"Weinberger P.J.", "pjw", 11273,
"Schryer N.L.", "nls", 11274,
"Schryer N.L.", "nls", 11275,
"Kernighan B.W.", "bwk", 11276
};

typedef int (*CFT)(char*,char*);

void sort(char* base, unsigned n, int sz, CFT cmp)
{
for (int i=0; i<n-1; i++)
for (int j=n-1; i<j; j--) {
char* pj = base+j*sz;
char *pj1 = pj-sz;
if ((*cmp)(pj,pj1) < 0)
// swap b[j] and b[j-1]
for (int k=0; k<sz; k++) {
char temp = pj[k];
pj[k] = pj1[k];
pj1[k] = temp;
}
}
}

void print_id(Puser v, int n)
{
for (int i=0; i<n; i++)
cout << v[i].name << "\t"
<< v[i].id << "\t"
<< v[i].dept << "\n";
}
extern int strcmp(char*, char*);

int cmp1(char* p, char* q)
{
return strcmp(Puser(p)->name, Puser(q)->name);
}

int cmp2(char* p, char* q)
{
return Puser(p)->dept - Puser(q)->dept;
}

main ()
{
sort((char*)heads,6,sizeof(user),cmp1);
print_id(heads,6);
cout << "\n";
sort ((char*)heads,6,sizeof(user),cmp2);
print_id(heads,6); // in department number order
}



    b5_3_2.cxx



#include <stream.hxx>

class intset {
int cursize, maxsize;
int *x;
public:
intset(int m, int n);
~intset();

int member(int t);
void insert(int t);

void iterate(int& i) { i = 0; }
int ok(int& i) { return i<cursize; }
int next(int& i) { return x[i++]; }
};

extern void exit (int);

void error(char *s)
{
cout << "set: " << s << "\n";
exit(1);
}

extern int atoi(char *);

extern int rand();

int randint (int u) // in the range 1..u
{
int r = rand();
if (r < 0) r = -r;
return 1 + r%u ;
}

intset::intset(int m, int n)
{
if (m<1 || n<m) error("illegal intset size");
cursize = 0;
maxsize = m;
x = new int[maxsize];
}

intset::~intset()
{
delete x;
}

void intset::insert(int t)
{
if (++cursize > maxsize) error("too many elements");
int i = cursize-1;
x[i] = t;

while (i>0 && x[i-1]>x[i]) {
int t = x[i];
x[i] = x[i-1];
x[i-1] = t;
i--;
}
}

int intset::member(int t)
{
int l = 0;
int u = cursize-1;

int m =0;
while (l <= u) {
m = (l+u)/2;
if (t < x[m])
u = m-1;
else if (t > x[m])
l = m+1;
else
return 1; // found
}
return 0; // not found
}

void print_in_order(intset* set)
{
int var;
set->iterate(var);
while (set->ok(var)) cout << set->next(var) << "\n";
}

main (int argc, char *argv[])
{
if (argc != 3) error("two arguments expected");
int count = 0;
int m = atoi(argv[1]);
int n = atoi (argv[2]);
intset s(m,n);

int t = 0;
while (count <m) {
t = randint(n);
if (s.member(t)==0) {
s.insert(t);
count++;
}
}
print_in_order(&s);
}



    b5_4_5.cxx


#include <stream.hxx>

struct cl
{
char* val;
void print(int x) { cout << val << x << "\n"; }
cl(char *v) { val = v; }
};


typedef void (cl::*PROC)(int);

main()
{
cl z1("z1 ");
cl z2("z2 ");
PROC pf1 = &cl::print;
PROC pf2 = &cl::print;
z1.print(1);
(z1.*pf1)(2);
z2.print(3);
((&z2)->*pf2)(4);
}



    b5_5_3.cxx


main() {
char *p = new char[100];
char *q = new char[100];
delete p;
delete p;
}



    b6_3_2.cxx



#include "stream.hxx"

int error (char * p)
{
cout << p << "\n";
return 1;
}

class tiny {
char v;
tiny assign(int i)
{ v = (i&~63) ? (error("range error"),0) : i; return *this; }
public:
tiny (int i) { assign(i); }
tiny (tiny& t) { v = t.v; }
tiny operator=(tiny& t1) { v = t1.v; return *this; }
tiny operator=(int i ) { return assign(i); }
int operator int() { return v; }
};

void main()
{
tiny c1 = 2;
tiny c2 = 62;
tiny c3 = (c2 - c1);
tiny c4 = c3;
int i = (c1 + c2);
c1 = (c2 + (2 * c1));
c2 = c1 - i;
c3 = c2;
}



    b6_6.cxx


#include <stream.hxx>

extern int strcpy(char* , char*);

extern int strlen(char *);

struct string {
char *p;
int size;
inline string(int sz) { p = new char[size=sz]; }
string(char *);
inline ~string() { delete p; }
void operator=(string&);
string(string& );
};

string::string(char* s)
{
p = new char [size = strlen(s) + 1];
strcpy (p,s);
}

void string::operator=(string& a)
{
if (this == &a) return;
delete p;
p=new char[size=a.size];
strcpy(p,a.p);
}


string::string(string& a)
{
p=new char[size=a.size];
strcpy(p,a.p);
}
string g(string arg)
{
return arg;
}

main()
{
string s = "asdf";
s = g(s);
cout << s.p << "\n";
}



    b6_7.cxx


#include <stream.hxx>
#include <string.h>
struct pair {
char * name;
int val;
};

class assoc {
pair * vec;
int max;
int free;
public:
assoc(int);
int& operator[](char* );
void print_all();
};

assoc::assoc(int s)
{
max = (s<16) ? s: 16;
free = 0;
vec = new pair[max];
}

int& assoc::operator[](char * p)
/*
maintain a set of "pair"s
search for p,
return a reference to the integer part of its "pair"
make a new "pair" if "p" has not been seen
*/
{
register pair* pp;
for (pp=&vec[free-1]; vec<=pp; pp-- )
if (strcmp(p, pp->name)==0) return pp->val;

if (free==max) { // overflow: grow the vector
pair* nvec = new pair[max*2];
for (int i=0; i<max; i++) nvec[i] = vec[i];
delete vec;
vec = nvec;
max = 2*max;
}

pp = &vec[free++];
pp->name = new char[strlen(p)+1];
strcpy(pp->name,p);
pp->val = 0;
return pp->val;
}

void assoc::print_all()
{
for (int i=0; i<free; i++)
cout << vec[i].name << ": " << vec[i].val << "\n";
}

main()
{
const MAX = 256;
char buf[MAX];
assoc vec(512);
while ( cin>>buf) vec[buf]++;
vec.print_all();
}



    b6_8.cxx



#include <stream.hxx>
#include <string.h>

struct pair {
char* name;
int val;
};

class assoc {
friend class assoc_iterator;
pair* vec;
int max;
int free;
public:
assoc(int);
int& operator[](char*);
};
class assoc_iterator {
assoc* cs;
int i;
public:
assoc_iterator(assoc& s) { cs = &s; i = 0; }
pair* operator()()
{ return (i<cs->free)? &cs->vec[i++] : 0; }
};

assoc::assoc(int s)
{
max = (s<16) ? s : 16;
free = 0;
vec = new pair[max];
}

int& assoc::operator[](char* p)
{
register pair* pp;

for (pp=&vec[free-1]; vec<=pp; pp-- )
if (strcmp(p,pp->name)==0) return pp->val;

if (free ==max) {
pair* nvec = new pair[max*2];
for (int i=0; i<max; i++) nvec[i] = vec[i];
delete vec;
vec = nvec;
max = 2*max;
}

pp = &vec[free++];
pp->name = new char[strlen(p)+1];
strcpy(pp->name,p);
pp->val = 0;
return pp->val;
}

main()
{
const MAX = 256;
char buf[MAX];
assoc vec(512);
while ( cin>>buf) vec[buf]++;
assoc_iterator next(vec);
pair* p;
while (p = next() )
cout << p->name << ": " << p->val << "\n";
}



    b6_9.cxx


#include <stream.hxx>
#include <string.h>

extern void exit(int);
class string {
struct srep {
char* s;
int n;
};
srep *p;

public:
string(char *);
string();
string(string &);
string& operator=(char *);
string& operator=(string &);
~string();
char& operator[](int i);

friend ostream& operator<<(ostream&, string&);
friend istream& operator>> (istream&, string&);

friend int operator==(string &x, char *s)
{ return strcmp(x.p->s, s) == 0; }

friend int operator==(string &x, string &y)
{ return strcmp(x.p->s, y.p->s) == 0; }

friend int operator!=(string &x, char *s)
{ return strcmp(x.p->s, s) != 0; }

friend int operator!=(string &x, string &y)
{ return strcmp (x.p->s, y.p->s) != 0; }
};

string::string()
{
p = new srep;
p->s = 0;
p->n = 1;
}

string::string(char* s)
{
p = new srep;
p->s = new char[ strlen(s) +1];
strcpy(p->s, s);
p->n = 1;
}
string::string(string& x)
{
x.p->n++;
p = x.p;
}

string::~string()
{
if (--p->n == 0){
delete p->s;
delete p;
}
}

string& string::operator=(char* s)
{
if (p->n > 1) {
p->n--;
p = new srep;
}
else if (p->n == 1)
delete p->s;

p->s = new char[ strlen(s)+1 ];
strcpy(p->s, s);
p->n = 1;
return *this;
}

string& string::operator=(string& x)
{
x.p->n++;
if (--p->n == 0) {
delete p->s;
delete p;
}
p = x.p;
return *this;
}

ostream& operator<<(ostream& s, string& x)
{
return s << x.p->s << " [" << x.p->n << "]\n";
}

istream& operator>>(istream& s, string& x)
{
char buf[256];
s>>buf;
x = buf;
cout << "echo: " << x << "\n";
return s;
}

void error(char* p)
{
cout << p << "\n";
exit(1);
}
char& string::operator[](int i)
{
if (i<0 || strlen(p->s)<i) error("index out of range");
return p->s[i];
}

main()
{
string x[100];
int n;

cout << "here we go\n";
for (n = 0; cin>>x[n]; n++) {
string y;
if (n==100) error("too many strings");
cout << (y = x[n]);
if (y=="done") break;
}
cout << "here we go back again\n";
for (int i=n-1; 0<=i; i--) cout << x[i];
}



    b7_2_8.cxx


#include <stream.hxx>

struct employee {
friend class manager;
employee* next;
char* name;
short department;
virtual void print();
};

struct manager : employee {
employee* group;
short level;
void print();
};

void employee::print()
{
cout << name << "\t" << department << "\n";
}

void manager::print()
{
employee::print();
cout << "\tlevel " << level << "\n";
}

void f(employee* ll)
{
for ( ; ll; ll=ll->next) ll->print();
}

main ()
{
employee e;
e.name = "J. Brown";
e.department = 1234;
e.next = 0;
manager m;
m.name = "J. Smith";
m.department = 1234;
m.level = 2;
m.next = &e;
f(&m);
}



    b7_7.cxx



#include <stream.hxx>

struct base { base(); };

struct derived : base { derived(); };

base:: base()
{
cout << "\tbase 1: this=" << long(this) << "\n";
if (this == 0) this = (base*)27;
cout << "\tbase 2: this=" << long(this) << "\n";
}

derived::derived()
{
cout << "\tderived 1: this=" << long(this) << "\n";
if (this == 0) this = (derived*)43;
cout << "\tderived 2: this=" << long(this) << "\n";
}

main()
{
cout << "base b;\n";
base b;
cout << "new base;\n";
new base;
cout << "derived d;\n";
derived d;
cout << "new derived;\n";
new derived;
cout << "new derived;\n";
new derived;
cout << "at the end\n";
}



    b8_3_3.cxx



#include <xstream.hxx>

extern void exit(int);

void error(char* s, char* s2)
{
cerr << s << " " << s2 << "\n";
exit(1);
}

main(int argc, char* argv[])
{
if (argc != 3) error ("wrong number of arguments","");

filebuf f1;
if (f1.open(argv[1],input) == 0)
error("cannot open input file",argv[1]);
istream from(&f1);

filebuf f2;
if (f2.open(argv[2],output) == 0)
error("cannot open input file",argv[2]);
ostream to(&f2);

char ch;
while (from.get(ch)) to.put(ch);

if (!from.eof() || to.bad())
error("something strange happened","");
}