#!/bin/sh
# This is a shar archive.
# The rest of this file is a shell script which will extract:
#
# 6_4.h makefile tst.in tst1.c tst1.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:08:02 EDT 1990
#
echo x - 6_4.h
sed 's/^X//' > 6_4.h << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
// Exercise 6.4
// String class with value semantics
// and copying on assignment.
#ifndef STR_H
# define STR_H
# include <stream.h>
# include <string.h>

// a helper typedef for the cast
// back into a character pointer
typedef const char *charptr;

class string
{
    char *p;
    int size;

public:
    // string s;
    string()
    {
	p = new char[size = 1];
	p[0] = 0;
    }

    // string s(5);
    string(int sz)
    {
	if (sz <= 0) sz = 1;
	p = new char[size = sz];
	p[0] = 0;
    }

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

    // string s = string
    string &operator=(string &s)
    {
	delete p;
	p = new char[size = s.size];
	strcpy(p, s.p);
	return *this;
    }

    // string s = "xyz";
    string &operator=(char *s)
    {
	delete p;
	p = new char[size = strlen(s) + 1];
	strcpy(p, s);
	return *this;
    }

    ~string()
    { delete p; }

    // const char *c = s;
    charptr operator charptr()
    { return (charptr)p; }

    // x = s[3];
    // s[3] = 'x';
    char &operator[](int i)
    {
	if (i < 0 || i >= size)
	    return p[0];
	else
	    return p[i];
    }

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

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

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

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

    friend int operator!=(string &x, string &y)
    { return strcmp(x.p, y.p) != 0; }
							 // DELETE
    void outputstring()					 // DELETE
    {							 // DELETE
	cout << "\tsize = " << size << "\n";		 // DELETE
	cout << "\tp = '" << p << "'\n";		 // DELETE
    }							 // DELETE
};

inline ostream& operator<<(ostream &s, string &x)
{
    return s << x.p;
}

inline istream& operator>>(istream &s, string &x)
{
    char buf[1024];
    s >> buf;
    x = buf;
    return s;
}
#endif /* STR_H */
!EOF!
ls -l 6_4.h
echo x - makefile
sed 's/^X//' > makefile << '!EOF!'
CC= CC -I. -I../../CC
CFLAGS=
ERROR= ../../error.o

all: tst1

tst1: tst1.c 6_4.h makefile
	$(CC) $(CFLAGS) tst1.c -o tst1 $(ERROR)

CMP= tst1.cmp
OUT= tst1.out

tst1.out: tst1 tst.in ;	tst1 < tst.in > tst1.out

test: all $(OUT) $(CMP)
	cmp tst1.out tst1.cmp
	echo tests done
!EOF!
ls -l makefile
echo x - tst.in
sed 's/^X//' > tst.in << '!EOF!'
hello
there
again
done
!EOF!
ls -l tst.in
echo x - tst1.c
sed 's/^X//' > tst1.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
#include <6_4.h>
#include <error.h>

main()
{
    string x[100];
    cout << "here we go\n";
    for (int n = 0; cin>>x[n]; n++) 
	{
	string y;
	if (n == 100) error("too many strings");
	cout << (y = x[n]) << "\n";
	if (y == "done") break;
	}
    cout << "here we go back again\n";
    for (int i = n-1; 0 <= i; i--)
        cout << x[i] << "\n";
    return 0;
}
!EOF!
ls -l tst1.c
echo x - tst1.cmp
sed 's/^X//' > tst1.cmp << '!EOF!'
here we go
hello
there
again
done
here we go back again
again
there
hello
!EOF!
ls -l tst1.cmp
# The following exit is to ensure that extra garbage 
# after the end of the shar file will be ignored.
exit 0
