bammi@cwruecmp.UUCP (08/05/86)
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# main.c
# make.c
# makefile
# makefile.mmc
# mmcomp.sh
# mmlink.sh
# read.mee
# reader.c
# This archive created: Tue Aug 5 02:46:37 1986
# By: Jwahar R. Bammi ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'main.c'" '(6212 characters)'
if test -f 'main.c'
then
echo shar: over-writing existing file "'main.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'main.c'
X#define ATARIST
X
X /*******************************************************\
X * *
X * A full featured MAKE Clone *
X * *
X * Origional Author: (Thank You) *
X * Neil Russell *
X * ACSnet: caret@tictoc.oz *
X * UUCP: ...!seismo!munnari!tictoc.oz!caret *
X * ARPA: caret%tictoc.oz@seismo.arpa *
X * *
X * Atari St Port & C code cleanup: *
X * Jwahar R. Bammi *
X * UUCP: .....!decvax!cwruecmp!bammi *
X * CSNET: bammi@case *
X * ARPA: bammi%case@csnet-relay *
X * CompuServe: 71515,155 *
X * *
X \*******************************************************/
X
X
X/*
X * make [-f makefile] [-ins] [target(s) ...]
X *
X * (Better than EON mk but not quite as good as UNIX make)
X *
X * -f makefile name
X * -i ignore exit status
X * -n Pretend to make
X * -p Print all macros & targets
X * -q Question up-to-dateness of target. Return exit status 1 if not
X * -r Don't not use inbuilt rules
X * -s Make silently
X * -t Touch files instead of making them
X * -m Change memory requirements -- NOT in the Atari St version
X *
X * >>>>> net.sources posting by:
X *
X * Neil Russell
X * ACSnet: caret@tictoc.oz
X * UUCP: ...!seismo!munnari!tictoc.oz!caret
X * ARPA: caret%tictoc.oz@seismo.arpa
X *
X * >>>>> 7/86 Jwahar R. Bammi Added support for Atari ST
X * report any Atari ST related complaints/suggestions to
X * decvax!cwruecmp!bammi
X * bammi@case.CSNET
X * bammi%case@csnet-relay.ARPA
X * 71515,155
X */
X
X#include <stdio.h>
X#include "h.h"
X
X#ifndef ATARIST
X#include <sys/stat.h>
X#include <sys/err.h>
X
X#else
X#include "astat.h"
X
X#endif /* ATARIST */
X
X
X#ifndef ATARIST
X#define MEMSPACE (16384)
X#endif /* ATARIST */
X
X
Xchar * myname;
Xchar * makefile = ""; /* The make file */
X
X#ifndef ATARIST
Xunsigned int memspace = MEMSPACE;
X#endif /* ATARIST */
X
XFILE * ifd; /* Input file desciptor */
Xbool domake = TRUE; /* Go through the motions option */
Xbool ignore = FALSE; /* Ignore exit status option */
Xbool silent = FALSE; /* Silent option */
Xbool print = FALSE; /* Print debuging information */
Xbool rules = TRUE; /* Use inbuilt rules */
Xbool dotouch = FALSE;/* Touch files instead of making */
Xbool quest = FALSE; /* Question up-to-dateness of file */
X
X
Xvoid
Xmain(argc, argv)
Xint argc;
Xchar ** argv;
X{
X register char * p; /* For argument processing */
X int estat = 0; /* For question */
X register struct name * np;
X extern FILE *fopen();
X extern int atoi();
X extern char *index();
X
X#ifndef ATARIST
X myname = (argc-- < 1) ? "make" : *argv++;
X#else
X myname = "make";
X argc--; argv++;
X#endif /* ATARIST - TOS does not pass the prog. name in argv[0] */
X
X while ((argc > 0) && (**argv == '-'))
X {
X argc--; /* One less to process */
X p = *argv++; /* Now processing this one */
X
X while (*++p != '\0')
X {
X switch(*p)
X {
X case 'F': /* Goddamned MSDOS style shells pass caps */
X case 'f': /* Alternate file name */
X if (*++p == '\0')
X {
X if (argc-- <= 0)
X usage();
X p = *argv++;
X }
X makefile = p;
X goto end_of_args;
X#ifndef ATARIST
X case 'm': /* Change space requirements */
X if (*++p == '\0')
X {
X if (argc-- <= 0)
X usage();
X p = *argv++;
X }
X memspace = atoi(p);
X goto end_of_args;
X#endif /* ATARIST */
X case 'N':
X case 'n': /* Pretend mode */
X domake = FALSE;
X break;
X
X case 'I':
X case 'i': /* Ignore fault mode */
X ignore = TRUE;
X break;
X
X case 'S':
X case 's': /* Silent about commands */
X silent = TRUE;
X break;
X case 'P':
X case 'p':
X print = TRUE;
X break;
X case 'R':
X case 'r':
X rules = FALSE;
X break;
X case 'T':
X case 't':
X dotouch = TRUE;
X break;
X case 'Q':
X case 'q':
X quest = TRUE;
X break;
X default: /* Wrong option */
X usage();
X }
X }
X end_of_args:;
X }
X
X#ifndef ATARIST
X if (initalloc(memspace) == 0xffff) /* Must get memory for alloc */
X fatal("Cannot initalloc memory");
X#endif /* ATARIST */
X
X if (strcmp(makefile, "-") == 0) /* Can use stdin as makefile */
X ifd = stdin; /* Will create havoc with Alcyons libs! */
X else
X if (*makefile == '\0') /* If no file, then use default */
X {
X if ((ifd = fopen(DEFN1, "r")) == (FILE *)0)
X#ifndef ATARIST
X if (errno != ER_NOTF)
X fatal("Can't open %s; error %02x", DEFN1, errno);
X#else
X fatal("Can't open %s",DEFN1);
X else
X makefile = DEFN1;
X#endif /* ATARIST */
X
X#ifndef ATARIST
X if ((ifd == (FILE *)0)
X && ((ifd = fopen(DEFN2, "r")) == (FILE *)0))
X fatal("Can't open %s", DEFN2);
X#endif /* ATARIST */
X }
X else
X if ((ifd = fopen(makefile, "r")) == (FILE *)0)
X fatal("Can't open %s", makefile);
X
X makerules();
X
X setmacro("$", "$");
X
X while (argc && ((p = index(*argv, '=')) != (char *)NULL))
X {
X char c;
X
X c = *p;
X *p = '\0';
X setmacro(*argv, p+1);
X *p = c;
X
X argv++;
X argc--;
X }
X
X
X input(ifd); /* Input all the gunga */
X fclose(ifd); /* Finished with makefile */
X lineno = 0; /* Any calls to error now print no line number */
X
X
X if (print)
X prt(); /* Print out structures */
X
X np = newname(".SILENT");
X if (np->n_flag & N_TARG)
X silent = TRUE;
X
X np = newname(".IGNORE");
X if (np->n_flag & N_TARG)
X ignore = TRUE;
X
X precious();
X
X if (!domake)
X silent = FALSE;
X
X if (!firstname)
X fatal("No targets defined");
X
X circh(); /* Check circles in target definitions */
X
X
X if (!argc)
X estat = make(firstname, 0);
X else while (argc--)
X {
X if (!print && !silent && strcmp(*argv, "love") == 0)
X printf("Not war!\n");
X estat |= make(newname(*argv++), 0);
X }
X
X if (quest)
X exit(estat);
X else
X exit(0);
X}
X
X
Xusage()
X{
X#ifndef ATARIST
X fprintf(stderr, "Usage: %s [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n", myname);
X#else
X fprintf(stderr, "Usage: make [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n");
X#endif /* ATARIST - argv[0] not passed by TOS - is Atari EVER going to fix this?? */
X exit(1);
X}
X
X
Xvoid
Xfatal(msg, a1, a2, a3)
Xchar *msg;
X#ifdef ATARIST
Xchar *a1; /* Better be else you will get junk for a2 */
Xint a2, a3;
X#endif /* ATARIST - When will people learn that sizeof(int *) != sizeof(int) */
X{
X fprintf(stderr, "%s: ", myname);
X fprintf(stderr, msg, a1, a2, a3);
X fputc('\n', stderr);
X exit(1);
X}
SHAR_EOF
if test 6212 -ne "`wc -c 'main.c'`"
then
echo shar: error transmitting "'main.c'" '(should have been 6212 characters)'
fi
echo shar: extracting "'make.c'" '(5900 characters)'
if test -f 'make.c'
then
echo shar: over-writing existing file "'make.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'make.c'
X#define ATARIST
X
X /*******************************************************\
X * *
X * A full featured MAKE Clone *
X * *
X * Origional Author: (Thank You) *
X * Neil Russell *
X * ACSnet: caret@tictoc.oz *
X * UUCP: ...!seismo!munnari!tictoc.oz!caret *
X * ARPA: caret%tictoc.oz@seismo.arpa *
X * *
X * Atari St Port & C code cleanup: *
X * Jwahar R. Bammi *
X * UUCP: .....!decvax!cwruecmp!bammi *
X * CSNET: bammi@case *
X * ARPA: bammi%case@csnet-relay *
X * CompuServe: 71515,155 *
X * *
X \*******************************************************/
X
X
X/*
X * Do the actual making for make
X */
X
X#include <stdio.h>
X#include "h.h"
X
X#ifndef ATARIST
X#include <sys/stat.h>
X#include <sys/err.h>
X#else
X#include "astat.h"
X#endif /* ATARIST */
X
X
X#ifndef ATARIST
X/*
X * Exec a shell that returns exit status correctly (/bin/esh).
X * The standard EON shell returns the process number of the last
X * async command, used by the debugger (ugg).
X * [exec on eon is like a fork+exec on unix]
X */
Xint
Xdosh(string, shell)
Xchar * string;
Xchar * shell;
X{
X int number;
X
X return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
X -1: /* couldn't start the shell */
X wait(number); /* return its exit status */
X}
X
X#else
X /* Atari St will use the system() function defined in ststuff.c */
X
X#define dosh(X,Y) system(X)
X
X#endif /* ATARIST */
X
X/*
X * Do commands to make a target
X */
Xvoid
Xdocmds(np)
Xstruct name * np;
X{
X bool ssilent = silent;
X bool signore = ignore;
X int estat;
X register char * q;
X register char * p;
X char * shell;
X register struct line * lp;
X register struct cmd * cp;
X
X
X#ifndef ATARIST
X if (*(shell = getmacro("SHELL")) == '\0')
X shell = ":bin/esh";
X#endif /* ATARIST - does not have any standard shell */
X
X for (lp = np->n_line; lp; lp = lp->l_next)
X for (cp = lp->l_cmd; cp; cp = cp->c_next)
X {
X strcpy(str1, cp->c_cmd);
X expand(str1);
X q = str1;
X ssilent = silent;
X signore = ignore;
X while ((*q == '@') || (*q == '-'))
X {
X if (*q == '@') /* Specific silent */
X ssilent = TRUE;
X else /* Specific ignore */
X signore = TRUE;
X q++; /* Not part of the command */
X }
X
X if (!ssilent)
X putchar('\t');
X
X for (p=q; *p; p++)
X {
X if (*p == '\n' && p[1] != '\0')
X {
X *p = ' ';
X if (!ssilent)
X fputs("\\\n", stdout);
X }
X else if (!ssilent)
X putchar(*p);
X }
X if (!ssilent)
X putchar('\n');
X
X if (domake)
X { /* Get the shell to execute it */
X if ((estat = dosh(q, shell)) != 0)
X {
X if (estat == -1)
X#ifndef ATARIST
X fatal("Couldn't execute %s", shell);
X#else
X fatal("Couldn't execute %s", q);
X#endif /* ATARIST */
X else
X {
X printf("%s: Error code %d", myname, estat);
X if (signore)
X fputs(" (Ignored)\n", stdout);
X else
X {
X putchar('\n');
X if (!(np->n_flag & N_PREC))
X if (unlink(np->n_name) == 0)
X printf("%s: '%s' removed.\n", myname, np->n_name);
X exit(estat);
X }
X }
X }
X }
X }
X}
X
X
X/*
X * Get the modification time of a file. If the first
X * doesn't exist, it's modtime is set to 0.
X */
X#ifndef ATARIST
Xvoid
Xmodtime(np)
Xstruct name * np;
X{
X struct stat info;
X int fd;
X
X
X if ((fd = open(np->n_name, 0)) < 0)
X {
X if (errno != ER_NOTF)
X fatal("Can't open %s; error %02x", np->n_name, errno);
X np->n_time = 0L;
X }
X else if (getstat(fd, &info) < 0)
X fatal("Can't getstat %s; error %02x", np->n_name, errno);
X else
X np->n_time = info.st_mod;
X
X close(fd);
X}
X
X#else
X /* Atari St version of modtime() using getstat()
X * see ststuff.c for Atari st version of getstat()
X */
Xvoid
Xmodtime(np)
Xstruct name * np;
X{
X struct stat info;
X extern int getstat();
X
X if (getstat(np->n_name, &info) < 0)
X np->n_time = 0L;
X else
X {
X FlipWords(&info.st_mod);
X np->n_time = info.st_mod;
X }
X}
X#endif /* ATARIST */
X
X#ifndef ATARIST
X/*
X * Update the mod time of a file to now.
X */
Xvoid
Xtouch(np)
Xstruct name * np;
X{
X char c;
X int fd;
X
X
X if (!domake || !silent)
X printf(" touch %s\n", np->n_name);
X
X if (domake)
X {
X if ((fd = open(np->n_name, 0)) < 0)
X printf("%s: '%s' not touched - non-existant\n",
X myname, np->n_name);
X else
X {
X uread(fd, &c, 1, 0);
X uwrite(fd, &c, 1);
X }
X close(fd);
X }
X}
X
X# else
X/*
X * Update the mod time of a file to now -- Atari St style
X */
X
Xvoid
Xtouch(np)
Xstruct name *np;
X{
X register int fd;
X
X
X if (!domake || !silent)
X printf("\ttouch %s\n", np->n_name);
X
X if (domake)
X {
X if ((fd = Fopen(np->n_name, 0)) < 0)
X printf("%s: '%s' not touched - non-existant\n",
X myname, np->n_name);
X else
X {
X long tim;
X
X Fseek(0L, fd, 2); /* Seek to EOF */
X tim = Gettime();
X FlipWords(&tim);
X Fdatime( &tim, fd, 1); /* This time the Hitch Hikers
X * guide is wrong
X */
X Fclose(fd);
X }
X }
X}
X
X#endif /* ATARIST */
X
X/*
X * Recursive routine to make a target.
X */
Xint
Xmake(np, level)
Xstruct name * np;
Xint level;
X{
X register struct depend * dp;
X register struct line * lp;
X time_t dtime = 1L;
X
X
X if (np->n_flag & N_DONE)
X return 0;
X
X if (!np->n_time)
X modtime(np); /* Gets modtime of this file */
X
X if (rules)
X {
X for (lp = np->n_line; lp; lp = lp->l_next)
X if (lp->l_cmd)
X break;
X if (!lp)
X dyndep(np);
X }
X
X if (!(np->n_flag & N_TARG) && np->n_time == 0L)
X fatal("Don't know how to make %s", np->n_name);
X
X for (lp = np->n_line; lp; lp = lp->l_next)
X for (dp = lp->l_dep; dp; dp = dp->d_next)
X {
X make(dp->d_name, level+1);
X dtime = max(dtime, dp->d_name->n_time);
X }
X
X np->n_flag |= N_DONE;
X
X if (quest)
X {
X rtime(&np->n_time);
X return np->n_time < dtime;
X }
X else if (np->n_time < dtime)
X {
X if (dotouch)
X touch(np);
X else
X {
X setmacro("@", np->n_name);
X docmds(np);
X }
X rtime(&np->n_time);
X }
X else if (level == 0)
X printf("%s: '%s' is up to date\n", myname, np->n_name);
X return 0;
X}
SHAR_EOF
if test 5900 -ne "`wc -c 'make.c'`"
then
echo shar: error transmitting "'make.c'" '(should have been 5900 characters)'
fi
echo shar: extracting "'makefile'" '(561 characters)'
if test -f 'makefile'
then
echo shar: over-writing existing file "'makefile'"
fi
sed 's/^X//' << \SHAR_EOF > 'makefile'
X# Makefile for make
X
XBINDIR = d:\bin
X
XCPFLAGS = -i c:\include\ -DATARIST -DDECL
X
XOBJS1 = check.o input.o macro.o \
Xreader.o rules.o
X
XOBJS2 = main.o make.o ststuff.o
X
Xmake.prg : $(OBJS1) $(OBJS2) lnk
X $(LINKER) [com[lnk]]
X $(RELMOD) make
X ${ECHO} Break out the Champainge
X
Xtouch.prg: touch.o
X $(LINKER) touch.68k=gemstart,touch,osbind,gemlib
X $(RELMOD) touch
X $(ECHO) touch made
X
X
X# Dependencies
X
X$(OBJS1) : h.h
X$(OBJS2) : h.h astat.h
X
Xclean:
X $(RM) *.o *.68k
X
Xinstall: make.prg touch.prg
X $(CP) make.prg $(BINDIR)\make.prg
X $(CP) touch.prg $(BINDIR)\touch.prg
X
SHAR_EOF
if test 561 -ne "`wc -c 'makefile'`"
then
echo shar: error transmitting "'makefile'" '(should have been 561 characters)'
fi
echo shar: extracting "'makefile.mmc'" '(475 characters)'
if test -f 'makefile.mmc'
then
echo shar: over-writing existing file "'makefile.mmc'"
fi
sed 's/^X//' << \SHAR_EOF > 'makefile.mmc'
X# Makefile for make
X
XBINDIR = d:\bin
X
X
XOBJS1 = check.o input.o macro.o \
Xreader.o rules.o
X
XOBJS2 = main.o make.o ststuff.o
X
Xmake.prg : $(OBJS1) $(OBJS2)
X $(LINKER) $(OBJS1) $(OBJS2) -o make.prg
X ${ECHO} Break out the Champainge
X
Xtouch.prg: touch.o
X $(LINKER) touch.o -o touch.prg
X $(ECHO) touch made
X
X# Dependencies
X
X$(OBJS1) : h.h
X$(OBJS2) : h.h astat.h
X
Xclean:
X $(RM) *.o
X
Xinstall: make.prg touch.prg
X $(CP) make.prg $(BINDIR)\make.prg
X $(CP) touch.prg $(BINDIR)\touch.prg
SHAR_EOF
if test 475 -ne "`wc -c 'makefile.mmc'`"
then
echo shar: error transmitting "'makefile.mmc'" '(should have been 475 characters)'
fi
echo shar: extracting "'mmcomp.sh'" '(84 characters)'
if test -f 'mmcomp.sh'
then
echo shar: over-writing existing file "'mmcomp.sh'"
fi
sed 's/^X//' << \SHAR_EOF > 'mmcomp.sh'
Xmmlink check.o input.o macro.o main.o make.o reader.o rules.o ststuff.o -o make.prg
SHAR_EOF
if test 84 -ne "`wc -c 'mmcomp.sh'`"
then
echo shar: error transmitting "'mmcomp.sh'" '(should have been 84 characters)'
fi
echo shar: extracting "'mmlink.sh'" '(84 characters)'
if test -f 'mmlink.sh'
then
echo shar: over-writing existing file "'mmlink.sh'"
fi
sed 's/^X//' << \SHAR_EOF > 'mmlink.sh'
Xmmlink check.o input.o macro.o main.o make.o reader.o rules.o ststuff.o -o make.prg
SHAR_EOF
if test 84 -ne "`wc -c 'mmlink.sh'`"
then
echo shar: error transmitting "'mmlink.sh'" '(should have been 84 characters)'
fi
echo shar: extracting "'read.mee'" '(757 characters)'
if test -f 'read.mee'
then
echo shar: over-writing existing file "'read.mee'"
fi
sed 's/^X//' << \SHAR_EOF > 'read.mee'
Xmake.c:
X * Fix dosh() for your system.
X * Call to getstat() in modtime() is like a fstat() on unix,
X so it needs fixing.
Xmain.c:
X * You can have fun in main(). That call to initalloc() is
X really special to EON.
Xrules.c:
X * Fix makerules() to suit you compilers for the auto suffix
X stuff.
X
XIt supports most features of the UNIX make, the notable exceptions
Xbeing libraries, and some subtleties with quoting. I will support
Xproblems with it to a degree. Good luck.
X
XP.S. I never actually got around to writing a manual entry for
X it, so the best course of action is to refer to the UNIX
X manual entry, or the source.
X
X
XNeil Russell
XACSnet: caret@tictoc.oz
XUUCP: ...!seismo!munnari!tictoc.oz!caret
XARPA: caret%tictoc.oz@seismo.arpa
X
X
X
SHAR_EOF
if test 757 -ne "`wc -c 'read.mee'`"
then
echo shar: error transmitting "'read.mee'" '(should have been 757 characters)'
fi
echo shar: extracting "'reader.c'" '(2569 characters)'
if test -f 'reader.c'
then
echo shar: over-writing existing file "'reader.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'reader.c'
X#define ATARIST
X
X /*******************************************************\
X * *
X * A full featured MAKE Clone *
X * *
X * Origional Author: (Thank You) *
X * Neil Russell *
X * ACSnet: caret@tictoc.oz *
X * UUCP: ...!seismo!munnari!tictoc.oz!caret *
X * ARPA: caret%tictoc.oz@seismo.arpa *
X * *
X * Atari St Port & C code cleanup: *
X * Jwahar R. Bammi *
X * UUCP: .....!decvax!cwruecmp!bammi *
X * CSNET: bammi@case *
X * ARPA: bammi%case@csnet-relay *
X * CompuServe: 71515,155 *
X * *
X \*******************************************************/
X
X
X/*
X * Read in makefile
X */
X
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "h.h"
X
X
Xint lineno = 0;
X
X
X/*
X * Syntax error handler. Print message, with line number, and exits.
X */
Xvoid
Xerror(msg, a1, a2, a3)
Xchar * msg;
Xchar *a1;
Xint a2, a3;
X{
X fprintf(stderr, "%s: ", myname);
X fprintf(stderr, msg, a1, a2, a3);
X if (lineno)
X fprintf(stderr, " on line %d", lineno);
X fputc('\n', stderr);
X exit(1);
X}
X
X
X/*
X * Read a line into the supplied string of length LZ. Remove
X * comments, ignore blank lines. Deal with quoted (\) #, and
X * quoted newlines. If EOF return TRUE.
X */
Xbool
Xgetline(str, fd)
Xchar * str;
XFILE * fd;
X{
X register char * p;
X char * q;
X int pos = 0;
X extern char * fgets();
X
X for (;;)
X {
X if(fgets((char *)((long)str + (long)pos), (int)(LZ-pos), fd) ==
X (char *)0)
X return TRUE; /* EOF */
X
X lineno++;
X
X if ((p = index((char *)((long)str+(long)pos), '\n')) ==
X (char *)0)
X error("Line too long");
X
X if (p[-1] == '\\')
X {
X p[-1] = '\n';
X pos = (int)((long)p - (long)str);
X continue;
X }
X
X p = str;
X while (((q = index(p, '#')) != (char *)0) &&
X (p != q) && (q[-1] == '\\'))
X {
X char *a;
X
X a = q - 1; /* Del \ chr; move rest back */
X p = q;
X while (*a++ = *q++)
X ;
X }
X if (q != (char *)0)
X {
X q[0] = '\n';
X q[1] = '\0';
X }
X
X p = str;
X while (isspace(*p)) /* Checking for blank */
X p++;
X
X if (*p != '\0')
X return FALSE;
X pos = 0;
X }
X}
X
X
X/*
X * Get a word from the current line, surounded by white space.
X * return a pointer to it. String returned has no white spaces
X * in it.
X */
Xchar *
Xgettok(ptr)
Xchar **ptr;
X{
X register char * p;
X
X
X while (isspace(**ptr)) /* Skip spaces */
X (*ptr)++;
X
X if (**ptr == '\0') /* Nothing after spaces */
X return NULL;
X
X p = *ptr; /* word starts here */
X
X while ((**ptr != '\0') && (!isspace(**ptr)))
X (*ptr)++; /* Find end of word */
X
X *(*ptr)++ = '\0'; /* Terminate it */
X
X return(p);
X}
SHAR_EOF
if test 2569 -ne "`wc -c 'reader.c'`"
then
echo shar: error transmitting "'reader.c'" '(should have been 2569 characters)'
fi
# End of shell archive
exit 0
--
Jwahar R. Bammi
Usenet: .....!decvax!cwruecmp!bammi
CSnet: bammi@case Arpa: bammi%case@csnet-relay
CompuServe: 71515,155