[comp.sources.unix] v12i010: Cake, a make replacement, Part04/09

rsalz@uunet.UU.NET (Rich Salz) (10/16/87)

Submitted-by: Zoltan Somogyi <zs@munnari.oz>
Posting-number: Volume 12, Issue 10
Archive-name: cake/part04

#! /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:
#	README
#	Makefile
#	base.c
#	ccincl.c
#	ccincl_s.l
#	gsrc.c
#	later.c
#	need.c
#	needed.c
#	pattern_s.l
#	refs.c
#	std.h
#	sub.c
#	subcmd.c
#	usrc.c
# This archive created: Wed Oct 14 20:49:51 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo mkdir Aux
mkdir Aux
echo cd Aux
cd Aux
echo shar: "extracting 'README'" '(172 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XThis directory contains the sources for commands used by some
X"standard" cakefiles. You shouldn't need to do more than modify
XDEST in the Makefile and type "make install".
SHAR_EOF
if test 172 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 172 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(836 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#	Makefile for some of cake's auxiliary programs
X
XPROGS = base ccincl later need needed sub subcmd usrc gsrc
XDEST  = /mip/usr/bin
X
Xall:		$(PROGS)
X
Xinstall:	$(PROGS)
X		cp $(PROGS) $(DEST)
X
Xbase:		base.o pattern_s.o
X		cc -o base base.o pattern_s.o
X
Xccincl:		ccincl.o ccincl_s.o
X		cc -o ccincl ccincl.o ccincl_s.o
X
Xlater:		later.c
X		cc -o later later.c
X
Xneed:		need.c
X		cc -o need need.c
X
Xneeded:		needed.c
X		cc -o needed needed.c
X
Xrefs:		refs.o pattern_s.o
X		cc -o refs refs.o pattern_s.o
X
Xsub:		sub.c
X		cc -o sub sub.c
X
Xsubcmd:		subcmd.c
X		cc -o subcmd subcmd.c
X
Xusrc:		usrc.c
X		cc -o usrc usrc.c
X
Xgsrc:		gsrc.c
X		cc -o gsrc gsrc.c
X
Xccincl_s.c:	ccincl_s.l
X		lex ccincl_s.l
X		@mv lex.yy.c ccincl_s.c
X
Xpattern_s.c:	pattern_s.l
X		lex pattern_s.l
X		@mv lex.yy.c pattern_s.c
X
Xclean:		
X		/bin/rm	Make_errs *.o *_s.c
X
Xgclean:		
X		/bin/rm *_s.c
SHAR_EOF
if test 836 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 836 characters)'
fi
fi
echo shar: "extracting 'base.c'" '(754 characters)'
if test -f 'base.c'
then
	echo shar: "will not over-write existing file 'base.c'"
else
sed 's/^X//' << \SHAR_EOF > 'base.c'
X/*
X**	A program to prepare a base for spell and style
X*/
X
X#include	<stdio.h>
X#include	"std.h"
X
Xtypedef	struct	s_entry
X{
X	bool	reflexive;
X	char	*replacement;
X} Entry;
X
XEntry	table[5] =	/* we use subscripts 1 to 4 */
X{
X	{	FALSE,	""		},
X	{	TRUE,	"EQUATION"	},
X	{	FALSE,	"(REFERENCE)"	},
X	{	FALSE,	"PROGRAM"	},
X	{	FALSE,	"PICTURE"	},
X};
X
Xint	more = TRUE;
X
Xmain()
X{
X	extern	char	yytext[];
X	reg	int	code;
X
X	code = yylex();
X	while (more)
X	{
X		if (code <= 0)
X			fputs(yytext, stdout);
X		else
X		{
X			reg	int	oldcode;
X			reg	int	newcode;
X
X			oldcode = code;
X			newcode = table[code].reflexive? code: -code;
X
X			code = yylex();
X			while (more && code != newcode)
X				code = yylex();
X			
X			printf(table[oldcode].replacement);
X		}
X
X		code = yylex();
X	}
X
X	exit(0);
X}
SHAR_EOF
if test 754 -ne "`wc -c < 'base.c'`"
then
	echo shar: "error transmitting 'base.c'" '(should have been 754 characters)'
fi
fi
echo shar: "extracting 'ccincl.c'" '(5068 characters)'
if test -f 'ccincl.c'
then
	echo shar: "will not over-write existing file 'ccincl.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ccincl.c'
X/*
X**	Ccincl main file.
X*/
X
Xstatic	char
Xrcs_id[] = "$Header$";
X
X#include	<ctype.h>
X#include	<stdio.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	"std.h"
X
Xtypedef	struct	stat	Stat;
X
X#define	MAXDIRS		10
X#define	MAXSTOPS	10
X#define	MAXIGNORES	10
X#define	MAXFILES	64
X#define	MAXBUF		512
X
Xchar	*dir_list[MAXDIRS];
Xchar	*stop_list[MAXSTOPS];
Xchar	*ign_list[MAXIGNORES];
Xchar	*file_list[MAXFILES];
Xbool	search_list[MAXFILES];
Xino_t	ino_list[MAXFILES];
Xint	dircount = 0;
Xint	stopcount = 0;
Xint	igncount = 0;
Xint	filecount = 0;
X
Xchar	*currdir = ".";
Xchar	*filename;
XStat	statbuf;
Xint	rflag = FALSE;
Xint	fflag = FALSE;
Xint	errorcount = 0;
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	extern	FILE	*yyin;
X	reg	int	i;
X
X	dir_list[dircount++] = ".";
X	while (argc > 1 && argv[1][0] == '-')
X	{
X		for (i = 1; argv[1][i] != '\0'; i++)
X		{
X			switch (argv[1][i])
X			{
X
X		when 'f':
X				fflag = TRUE;
X		when 'r':
X				rflag = TRUE;
X		when 'i':
X				if (i != 1)
X					usage();
X
X				ign_list[igncount++] = &argv[1][2];
X				file_list[filecount] = &argv[1][2];
X
X				if (stat(&argv[1][2], &statbuf) != 0)
X				{
X					printf("ccincl: cannot find %s\n", &argv[1][2]);
X					exit(1);
X				}
X
X				search_list[filecount] = FALSE;
X				ino_list[filecount] = statbuf.st_ino;
X				filecount++;
X				goto nextword;
X		when 's':
X				if (i != 1)
X					usage();
X
X				stop_list[stopcount++] = &argv[1][2];
X				file_list[filecount] = &argv[1][2];
X
X				if (stat(&argv[1][2], &statbuf) != 0)
X				{
X					printf("ccincl: cannot find %s\n", &argv[1][2]);
X					exit(1);
X				}
X
X				search_list[filecount] = FALSE;
X				ino_list[filecount] = statbuf.st_ino;
X				filecount++;
X				goto nextword;
X		when 'C':
X				if (i != 1)
X					usage();
X
X				currdir = &argv[1][2];
X				goto nextword;
X		when 'I':
X				if (i != 1)
X					usage();
X
X				dir_list[dircount++] = &argv[1][2];
X				goto nextword;
X		otherwise:
X				usage();
X			}
X		}
X
Xnextword:
X		argc--;
X		argv++;
X	}
X
X	dir_list[dircount++] = "/usr/include";
X	if (dircount > MAXDIRS)
X	{
X		printf("ccincl: too many dir_list.\n");
X		exit(1);
X	}
X
X	if (argc < 2)
X		usage();
X	
X	while (argc > 1)
X	{
X		file_list[filecount] = argv[1];
X		if (stat(argv[1], &statbuf) != 0)
X		{
X			printf("ccincl: cannot find %s\n", argv[1]);
X			exit(1);
X		}
X
X		search_list[filecount] = TRUE;
X		ino_list[filecount] = statbuf.st_ino;
X		filecount++;
X		argc--;
X		argv++;
X	}
X	
X	for (i = 0; i < filecount; i++)
X	{
X		if (! search_list[i])
X			continue;
X
X		filename = file_list[i];
X		if ((yyin = fopen(filename, "r")) == NULL)
X		{
X			fflush(stdout);
X			perror("ccincl");
X			printf("ccincl: cannot open %s\n", filename);
X			exit(1);
X		}
X
X		yylex();
X		fclose(yyin);
X	}
X
X	exit(errorcount);
X}
X
Xprocess(line)
Xreg	char	*line;
X{
X	extern	char	*malloc();
X	extern	int	yylineno;
X	char		buf[MAXBUF];
X	reg	char	*s, *start;
X	reg	int	i, startdir;
X	reg	bool	index;
X	reg	char	endchar;
X	reg	bool	found;
X
X	for (s = line+1; *s != '\0' && isspace(*s); s++)
X		;
X	
X	if (strndiff(s, "include", 7))
X		return;
X	
X	for (s += 7; *s != '\0' && isspace(*s); s++)
X		;
X	
X	if (*s == '<')
X		endchar = '>', startdir = 1;
X	else
X		endchar = '"', startdir = 0;
X
X	start = s+1;
X	for (s = start; *s != '\0' && *s != endchar; s++)
X		;
X
X	if (*s != endchar)
X	{
X		printf("ccincl: %s(%d) bad include syntax\n", filename, yylineno);
X		errorcount++;
X		return;
X	}
X
X	/* terminate arg (now pointed to by start) */
X	*s = '\0';
X
X	/* handle absolute pathnames */
X	if (*start == '/')
X	{
X		sprintf(buf, "%s", start);
X		goto end;
X	}
X
X	/* handle relative pathnames */
X	if (*start == '.')
X	{
X		sprintf(buf, "%s/%s", currdir, start);
X		goto end;
X	}
X
X	/* handle implicit pathnames */
X	found = FALSE;
X	for (i = startdir; i < dircount; i++)
X	{
X		if (i == 0)
X		{
X			if (streq(currdir, "."))
X				strcpy(buf, "");
X			else
X			{
X				strcpy(buf, dir_list[i]);
X				strcat(buf, "/");
X			}
X
X			strcat(buf, start);
X		}
X		else
X		{
X			strcpy(buf, dir_list[i]);
X			strcat(buf, "/");
X			strcat(buf, start);
X		}
X
X		if (strlen(buf) > MAXBUF)
X		{
X			printf("ccincl: buffer length exceeded\n");
X			exit(1);
X		}
X
X		if (stat(buf, &statbuf) == 0)
X		{
X			found = TRUE;
X			break;
X		}
X	}
X
X	if (! found)
X	{
X		printf("ccincl: cannot find %s\n", start);
X		errorcount++;
X		return;
X	}
X
Xend:
X	if (stat(buf, &statbuf) != 0)
X	{
X		printf("ccincl: cannot stat %s\n", buf);
X		errorcount++;
X		return;
X	}
X
X	found = FALSE;
X	for (i = 0; i < filecount; i++)
X		if (ino_list[i] == statbuf.st_ino)
X		{
X			found = TRUE;
X			index = i;
X			break;
X		}
X
X	if (! found)
X	{
X		index = filecount;
X		ino_list[filecount]    = statbuf.st_ino;
X		search_list[filecount] = FALSE;
X		file_list[filecount]   = malloc(strlen(buf)+1);
X		strcpy(file_list[filecount], buf);
X		filecount++;
X	}
X
X	for (i = 0; i < igncount; i++)
X		if (streq(file_list[index], ign_list[i]))
X			return;
X
X	if (fflag)
X		printf("%s: ", filename);
X
X	printf("%s\n", file_list[index]);
X
X	if (rflag)
X	{
X		for (i = 0; i < stopcount; i++)
X			if (streq(buf, stop_list[i]))
X				return;
X
X		search_list[filecount] = TRUE;
X	}
X}
X
X/*
X**	Tell the unfortunate user how to use ccincl.
X*/
X
Xusage()
X{
X	printf("Usage: ccincl [-rf] [-ifile] [-sfile] [-Cdir] [-Idir] ... file ...\n");
X	exit(1);
X}
SHAR_EOF
if test 5068 -ne "`wc -c < 'ccincl.c'`"
then
	echo shar: "error transmitting 'ccincl.c'" '(should have been 5068 characters)'
fi
fi
echo shar: "extracting 'ccincl_s.l'" '(240 characters)'
if test -f 'ccincl_s.l'
then
	echo shar: "will not over-write existing file 'ccincl_s.l'"
else
sed 's/^X//' << \SHAR_EOF > 'ccincl_s.l'
X%{
X/*
X**	Scanner for ccincl
X*/
X
Xstatic	char
Xrcs_id[] = "$Header$";
X
X#undef	YYLMAX
X#define	YYLMAX	512
X%}
X
Xnl	[\n\f]
Xnonl	[^\n\f]
X
X%%
X
X#{nonl}*{nl}		{
X				process(yytext);
X				fflush(stdout);
X			}
X
X{nonl}*{nl}		;
X
X%%
X
Xyywrap()
X{
X	return 1;
X}
SHAR_EOF
if test 240 -ne "`wc -c < 'ccincl_s.l'`"
then
	echo shar: "error transmitting 'ccincl_s.l'" '(should have been 240 characters)'
fi
fi
echo shar: "extracting 'gsrc.c'" '(807 characters)'
if test -f 'gsrc.c'
then
	echo shar: "will not over-write existing file 'gsrc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'gsrc.c'
X/*
X**	Track down ultimate source files.
X*/
X
X#include	<stdio.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	"std.h"
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	char		buf[80];
X	struct	stat	statbuf;
X	reg	int	i, j;
X	reg	int	lastsuf, firstfile;
X	reg	bool	found;
X
X	lastsuf = 0;
X	firstfile = argc;
X	for (i = 1; i < argc; i++)
X	{
X		if (argv[i][0] == '.')
X			lastsuf = i;
X		or (firstfile == argc)
X			firstfile = i;
X	}
X
X	if (lastsuf > firstfile)
X	{
X		fprintf(stderr, "gsrc: mixed suffixes and filenames\n");
X		exit(1);
X	}
X
X	for (i = firstfile; i < argc; i++)
X	{
X		found = FALSE;
X		for (j = lastsuf; j > 0; j--)
X		{
X			sprintf(buf, "%s%s", argv[i], argv[j]);
X			if (stat(buf, &statbuf) == 0)
X			{
X				if (! found)
X					found = TRUE;
X				else
X					printf("%s%s\n", argv[i], argv[j]);
X			}
X		}
X	}
X
X	exit(0);
X}
SHAR_EOF
if test 807 -ne "`wc -c < 'gsrc.c'`"
then
	echo shar: "error transmitting 'gsrc.c'" '(should have been 807 characters)'
fi
fi
echo shar: "extracting 'later.c'" '(1244 characters)'
if test -f 'later.c'
then
	echo shar: "will not over-write existing file 'later.c'"
else
sed 's/^X//' << \SHAR_EOF > 'later.c'
X/*
X**	Find out which arg files are later than a reference file.
X*/
X
Xstatic	char
Xrcs_id[] = "$Header$";
X
X#include	<stdio.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	"std.h"
X
Xtypedef	struct	stat	Stat;
X
Xchar	scratchbuf[128];
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	Stat		statbuf;
X	reg	time_t	reftime;
X	reg	int	i, n;
X	reg	bool	count  = FALSE;
X	reg	bool	silent = FALSE;
X
X	while (argc > 1 && argv[1][0] == '-')
X	{
X		for (i = 1; argv[1][i] != '\0'; i++)
X		{
X			switch (argv[1][i])
X			{
X
X		when 'c':	count = TRUE;
X
X		when 's':	silent = TRUE;
X
X		otherwise:	usage();
X
X			}
X		}
X
X		argc--;
X		argv++;
X	}
X
X	if (argc < 3)
X		usage();
X	
X	if (stat(argv[1], &statbuf) != 0)
X	{
X		sprintf(scratchbuf, "later, stat %s", argv[1]);
X		perror(scratchbuf);
X		exit(127);
X	}
X
X	argv++;
X	argc--;
X	reftime = statbuf.st_mtime;
X	n = 0;
X
X	while (argc > 1)
X	{
X		if (stat(argv[1], &statbuf) != 0)
X		{
X			sprintf(scratchbuf, "later, stat %s", argv[1]);
X			perror(scratchbuf);
X			exit(127);
X		}
X
X		if (statbuf.st_mtime > reftime)
X		{
X			n++;
X			if (! silent)
X				printf("%s\n", argv[1]);
X		}
X
X		argc--;
X		argv++;
X	}
X
X	exit(count? n: 0);
X}
X
X/*
X**	Tell the unfortunate user how to use later.
X*/
X
Xusage()
X{
X	printf("Usage: later [-cs] reffile file ...\n");
X	exit(1);
X}
SHAR_EOF
if test 1244 -ne "`wc -c < 'later.c'`"
then
	echo shar: "error transmitting 'later.c'" '(should have been 1244 characters)'
fi
fi
echo shar: "extracting 'need.c'" '(996 characters)'
if test -f 'need.c'
then
	echo shar: "will not over-write existing file 'need.c'"
else
sed 's/^X//' << \SHAR_EOF > 'need.c'
X/*
X**	need: a simple utility for text processing with cake
X*/
X
X#include	<stdio.h>
X#include	"std.h"
X
X#define	MAXLINE	256
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	reg	FILE	*fp;
X	char		line[MAXLINE];
X
X	if (argc != 2 && argc != 3)
X	{
X		printf("Usage: need program [file]\n");
X		exit(127);
X	}
X
X	if (argc == 2)
X		fp = stdin;
X	else
X	{
X		if ((fp = fopen(argv[2], "r")) == NULL)
X		{
X			printf("need: cannot open %s\n", argv[2]);
X			exit(127);
X		}
X	}
X
X	while (getline(fp, line, MAXLINE) > 0)
X		if (match(line, "NEED"))
X			exit(match(line, argv[1])? 0: 1);
X	
X	exit(127);
X}
X
Xint
Xgetline(fp, s, lim)
Xreg	FILE	*fp;
Xchar		s[];
Xreg	int	lim;
X{
X	reg	int	c, i;
X
X	i = 0;
X	while (--lim > 0 && (c = getc(fp)) != EOF && c != '\n')
X		s[i++] = c;
X
X	if (c == '\n')
X		s[i++] = c;
X
X	s[i] = '\0';
X	return i;
X}
X
Xint
Xmatch(s, t)
Xreg	char	*s;
Xreg	char	*t;
X{
X	reg	int	i, j;
X
X	for (; *s != '\0'; s++)
X	{
X		for (i = 0, j = 0; t[j] != '\0' && s[i] == t[j]; i++, j++)
X			;
X		if (t[j] == '\0')
X			return TRUE;
X	}
X
X	return FALSE;
X}
SHAR_EOF
if test 996 -ne "`wc -c < 'need.c'`"
then
	echo shar: "error transmitting 'need.c'" '(should have been 996 characters)'
fi
fi
echo shar: "extracting 'needed.c'" '(1001 characters)'
if test -f 'needed.c'
then
	echo shar: "will not over-write existing file 'needed.c'"
else
sed 's/^X//' << \SHAR_EOF > 'needed.c'
X/*
X**	needed: an even simpler utility for text processing with cake
X*/
X
X#include	<stdio.h>
X#include	"std.h"
X
X#define	MAXLINE	256
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	extern	char	*match();
X	reg	FILE	*fp;
X	reg	char	*rest;
X	char		line[MAXLINE];
X
X	if (argc != 2)
X	{
X		printf("Usage: needed file\n");
X		exit(127);
X	}
X
X	if ((fp = fopen(argv[1], "r")) == NULL)
X	{
X		printf("needed: cannot open %s\n", argv[1]);
X		exit(127);
X	}
X
X	while (getline(fp, line, MAXLINE) > 0)
X		if ((rest = match(line, "NEED")) != NULL)
X		{
X			printf("%s", rest);
X			exit(0);
X		}
X
X	exit(0);
X}
X
Xint
Xgetline(fp, s, lim)
Xreg	FILE	*fp;
Xchar		s[];
Xreg	int	lim;
X{
X	reg	int	c, i;
X
X	i = 0;
X	while (--lim > 0 && (c = getc(fp)) != EOF && c != '\n')
X		s[i++] = c;
X
X	if (c == '\n')
X		s[i++] = c;
X
X	s[i] = '\0';
X	return i;
X}
X
Xchar *
Xmatch(s, t)
Xreg	char	*s;
Xreg	char	*t;
X{
X	reg	int	i, j;
X
X	for (; *s != '\0'; s++)
X	{
X		for (i = 0, j = 0; t[j] != '\0' && s[i] == t[j]; i++, j++)
X			;
X
X		if (t[j] == '\0')
X			return s+j;
X	}
X
X	return NULL;
X}
SHAR_EOF
if test 1001 -ne "`wc -c < 'needed.c'`"
then
	echo shar: "error transmitting 'needed.c'" '(should have been 1001 characters)'
fi
fi
echo shar: "extracting 'pattern_s.l'" '(389 characters)'
if test -f 'pattern_s.l'
then
	echo shar: "will not over-write existing file 'pattern_s.l'"
else
sed 's/^X//' << \SHAR_EOF > 'pattern_s.l'
X%{
X/*
X**	Scanner for base
X*/
X
X#include	"std.h"
X
Xextern	int	more;
X%}
X
X%%
X
X"$"			{	return 1;	}
X"[\."			{	return 2;	}
X".\]"			{	return -2;	}
X"\\f(as"		{	return 3;	}
X"\\f(CW"		{	return 3;	}
X"\\fP"			{	return -3;	}
X"\\fR"			{	return -3;	}
X".(p"			{	return 3;	}
X".)p"			{	return -3;	}
X".PS"			{	return 4;	}
X".PE"			{	return -4;	}
X.|\n			{	return 0;	}
X
X%%
X
Xyywrap()
X{
X	more = FALSE;
X	return 1;
X}
SHAR_EOF
if test 389 -ne "`wc -c < 'pattern_s.l'`"
then
	echo shar: "error transmitting 'pattern_s.l'" '(should have been 389 characters)'
fi
fi
echo shar: "extracting 'refs.c'" '(828 characters)'
if test -f 'refs.c'
then
	echo shar: "will not over-write existing file 'refs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'refs.c'
X/*
X**	A program to filter out references.
X*/
X
X#include	<stdio.h>
X#include	"std.h"
X
Xint	more = TRUE;
X
Xmain()
X{
X	extern	char	yytext[];
X	reg	FILE	*out;
X	reg	int	code;
X	reg	bool	init, ignore;
X
X	out = popen("sed -e 's/[ 	]*$//'", "w");
X
X	code = yylex();
X	while (more)
X	{
X		if (code == 2)
X		{
X			ignore = FALSE;
X			init = TRUE;
X			code = yylex();
X			while (more && code != -2)
X			{
X				if (streq(yytext, "{"))
X					ignore = TRUE;
X				or (streq(yytext, "}"))
X					ignore = FALSE;
X				or (ignore)
X					;
X				or (streq(yytext, ","))
X				{
X					putc('\n', out);
X					init = TRUE;
X				}
X				or (streq(yytext, " "))
X				{
X					if (! init)
X						putc(' ', out);
X				}
X				else
X				{
X					fprintf(out, "%s", yytext);
X					init = FALSE;
X				}
X
X				code = yylex();
X			}
X
X			putc('\n', out);
X		}
X
X		code = yylex();
X	}
X
X	pclose(out);
X	exit(0);
X}
SHAR_EOF
if test 828 -ne "`wc -c < 'refs.c'`"
then
	echo shar: "error transmitting 'refs.c'" '(should have been 828 characters)'
fi
fi
echo shar: "extracting 'std.h'" '(1030 characters)'
if test -f 'std.h'
then
	echo shar: "will not over-write existing file 'std.h'"
else
sed 's/^X//' << \SHAR_EOF > 'std.h'
X/*
X**	Standard definitions for C
X**
X**	$Header: /mip/zs/src/sys/cake/RCS/std.h,v 1.13 86/06/15 18:36:30 zs Exp $
X*/
X
X#define	or		else if
X#define	when		break;case
X#define	otherwise	break;default
X#define	loop		for(;;)
X#define	until(expr)	while(!(expr))
X#ifndef	reg
X#define	reg		register
X#endif
X#ifndef	bool
X#define	bool		char
X#endif
X
X#define	uint		unsigned int
X#define	ushort		unsigned short
X#define	uchar		unsigned char
X
X#define	max(a, b)	((a) > (b) ? (a) : (b))
X#define	min(a, b)	((a) < (b) ? (a) : (b))
X
X#define streq(s1, s2)		(strcmp(s1, s2) == 0)
X#define strdiff(s1, s2)		(strcmp(s1, s2) != 0)
X#define strneq(s1, s2, n)	(strncmp(s1, s2, n) == 0)
X#define strndiff(s1, s2, n)	(strncmp(s1, s2, n) != 0)
X
X#define	ungetchar(c)		ungetc(c, stdin)
X#define make(type)		((type *) newmem(sizeof(type)))
X#define make_many(type, count)	((type *) newmem(count * sizeof(type)))
X
X#ifndef	TRUE
X#define	TRUE		1
X#endif
X#ifndef	FALSE
X#define	FALSE		0
X#endif
X#ifndef	NULL
X#define	NULL		0
X#endif
X
X#define	CNULL		(char *) 0
X#define	LNULL		(List *) 0
SHAR_EOF
if test 1030 -ne "`wc -c < 'std.h'`"
then
	echo shar: "error transmitting 'std.h'" '(should have been 1030 characters)'
fi
fi
echo shar: "extracting 'sub.c'" '(4337 characters)'
if test -f 'sub.c'
then
	echo shar: "will not over-write existing file 'sub.c'"
else
sed 's/^X//' << \SHAR_EOF > 'sub.c'
X/*
X**	Sub - do substitutions on arguments
X*/
X
Xstatic	char
Xrcs_id[] = "$Header$";
X
X#include	"std.h"
X#include	<ctype.h>
X
Xchar	var_char = 'X';
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	extern	bool	match();
X	extern	char	*ground();
X	reg	char	*old, *new;
X	reg	bool	ignore;
X	reg	int	unmatched, i;
X	reg	char	*sep;
X
X	ignore = FALSE;
X	unmatched = 0;
X	while (argc > 1 && argv[1][0] == '-')
X	{
X		for (i = 1; argv[1][i] != '\0'; i++)
X		{
X			switch (argv[1][i])
X			{
X
X		when 'i':
X				ignore = TRUE;
X		when 'v':
X				if (argv[1][i+2] != '\0')
X					usage();
X
X				var_char = argv[1][i+1];
X				goto nextword;
X		otherwise:
X				usage();
X			}
X		}
X
Xnextword:
X		argc--;
X		argv++;
X	}
X
X	if (argc < 2)
X		usage();
X	
X	old = argv[1];
X	new = argv[2];
X	argv += 2;
X	argc -= 2;
X
X	sep = "";
X	while (argc > 1)
X	{
X		if (! match(argv[1], old))
X			unmatched++;
X		else
X		{
X			printf("%s%s", sep, ground(new));
X			sep = " ";
X		}
X
X		argc--;
X		argv++;
X	}
X
X	printf("\n");
X	exit(ignore? 0: unmatched);
X}
X
X/*
X**	Tell the unfortunate user how to use sub.
X*/
X
Xusage()
X{
X	printf("Usage: sub [-i] [-vX] oldpattern newpattern name ...\n");
X	exit(1);
X}
X
X/*
X**	Module to manipulate Cake patterns.
X*/
X
Xtypedef	struct	s_env
X{
X	char	*en_val;
X	bool	en_bound;
X} Env;
X
X#define	NOVAR	 10
X#define	MAXVAR	 11
X#define	MAXSIZE	128
X
XEnv	env[MAXVAR];
X
X/*
X**	This function initialises the environment of domatch.
X*/
X
Xbool
Xmatch(str, pat)
Xreg	char	*str;
Xreg	char	*pat;
X{
X	extern	bool	domatch();
X	reg	int	i;
X	reg	char	*s, *p;
X
X	p = pat+strlen(pat)-1;
X	if (*p != var_char && !isdigit(*p))	/* not part of a var */
X	{
X		s = str+strlen(str)-1;
X		if (*s != *p)			/* last chars differ */
X			return FALSE;
X	}
X
X	for (i = 0; i < MAXVAR; i++)
X		env[i].en_bound = FALSE;
X
X	return domatch(str, pat);
X}
X
X/*
X**	Match a string against a pattern.
X**	The pattern is expected to have been dereferenced.
X**	To handle nondeterminism, a brute force recursion approach
X**	is taken.
X*/
X
Xbool
Xdomatch(str, patstr)
Xreg	char	*str;
Xreg	char	*patstr;
X{
X	extern	char	*new_name();
X	char		buf[MAXSIZE];
X	reg	char	*follow;
X	reg	char	*s, *t;
X	reg	int	varno;
X	reg	int	i;
X	reg	bool	more;
X
X	if (patstr[0] == var_char)
X	{
X		if (isdigit(patstr[1]))
X		{
X			varno  = patstr[1] - '0';
X			follow = patstr + 2;
X		}
X		else
X		{
X			varno  = NOVAR;
X			follow = patstr + 1;
X		}
X
X		if (env[varno].en_bound)
X		{
X			/* lifetime of buf is local */
X			strcpy(buf, env[varno].en_val);
X			strcat(buf, follow);
X			return domatch(str, buf);
X		}
X
X		i = 0;
X		buf[0] = '\0';
X		env[varno].en_bound = TRUE;
X		env[varno].en_val = buf;
X
X		/* keep invariant: buf = tentative value of var  */
X		/* must consider *s == \0, but do not overshoot  */
X		for (s = str, more = TRUE; more; s++)
X		{
X			if (domatch(s, follow))
X			{
X				/* lifetime of buf is now global */
X				env[varno].en_val = new_name(buf);
X				return TRUE;
X			}
X
X			/* maintain invariant */
X			buf[i++] = *s;
X			buf[i]   = '\0';
X
X			more = (*s != '\0');
X		}
X		
X		/* no luck, match failed */
X		env[varno].en_bound = FALSE;
X		return FALSE;
X	}
X
X	/* here we have something other than a variable first off */
X	for (s = str, t = patstr; *t != '\0' && *t != var_char; s++, t++)
X	{
X		if (*t == '\\')
X			t++;	/* the new *t is not checked for % */
X		
X		if (*s != *t)
X			return FALSE;
X	}
X
X	/* see if we have come to the end of the pattern */
X	if (*t == '\0')
X		return *s == '\0';
X	
X	/* if not, recurse on the next variable */
X	return domatch(s, t);
X}
X
X/*
X**	Ground the argument string, i.e. replace all occurrences
X**	of variables in it. It is fatal error for the string to
X**	contain a variable which has no value.
X*/
X
Xchar *
Xground(str)
Xreg	char	*str;
X{
X	extern	char	*new_name();
X	reg	char	*s, *t;
X	reg	int	i, var;
X	char		buf[MAXSIZE];
X
X	i = 0;
X	for (s = str; *s != '\0'; s++)
X	{
X		if (*s == var_char)
X		{
X			if (isdigit(s[1]))
X				var = *++s - '0';
X			else
X				var = NOVAR;
X			
X			if (! env[var].en_bound)
X			{
X				printf("Attempt to use undefined value in %s\n", str);
X				exit(1);
X			}
X
X			for (t = env[var].en_val; *t != '\0'; t++)
X				buf[i++] = *t;
X		}
X		or (*s == '\\')
X		{
X			if (s[1] != '\0')
X				buf[i++] = *++s;
X		}
X		else
X			buf[i++] = *s;
X	}
X
X	if (i >= MAXSIZE)
X	{
X		printf("Ran out of buffer\n");
X		exit(1);
X	}
X
X	buf[i] = '\0';
X	return new_name(buf);
X}
X
Xchar *
Xnew_name(str)
Xreg	char	*str;
X{
X	extern	char	*malloc();
X	reg	char	*copy;
X
X	copy = malloc(strlen(str) + 1);
X	strcpy(copy, str);
X	return copy;
X}
SHAR_EOF
if test 4337 -ne "`wc -c < 'sub.c'`"
then
	echo shar: "error transmitting 'sub.c'" '(should have been 4337 characters)'
fi
fi
echo shar: "extracting 'subcmd.c'" '(5233 characters)'
if test -f 'subcmd.c'
then
	echo shar: "will not over-write existing file 'subcmd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'subcmd.c'
X/*
X**	Subcmd - execute commands with arguments based on substitutions
X*/
X
Xstatic	char
Xrcs_id[] = "$Header$";
X
X#include	<stdio.h>
X#include	<ctype.h>
X#include	"std.h"
X
X#define	MAXLEN	1024
X
Xchar	var_char = 'X';
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	extern	bool	match();
X	extern	char	*ground();
X	reg	char	*cmd, *old, *new;
X	reg	int	unmatched, i;
X	reg	bool	fast, general, ignore, noexec, needzero;
X	reg	FILE	*csh;
X	char		buf[MAXLEN];
X
X	fast     = FALSE;
X	general  = FALSE;
X	ignore   = FALSE;
X	noexec   = FALSE;
X	needzero = TRUE;
X	unmatched = 0;
X	while (argc > 1 && argv[1][0] == '-')
X	{
X		for (i = 1; argv[1][i] != '\0'; i++)
X		{
X			switch (argv[1][i])
X			{
X
X		when 'f':	fast = TRUE;
X
X		when 'g':	general = TRUE;
X
X		when 'i':	ignore = TRUE;
X
X		when 'n':	noexec = TRUE;
X
X		when 'v':	if (i != 1)
X					usage();
X
X				var_char = argv[1][2];
X				goto nextword;
X
X		when 'z':	needzero = FALSE;
X
X		otherwise:	usage();
X
X			}
X		}
X
Xnextword:
X		argc--;
X		argv++;
X	}
X
X	if (argc < 3)
X		usage();
X	
X	cmd = argv[1];
X	old = argv[2];
X	new = argv[3];
X	argv += 3;
X	argc -= 3;
X
X	if (fast)
X	{
X		csh = popen("/bin/csh -fs", "w");
X		if (csh == (FILE *) NULL)
X		{
X			printf("subcmd: cannot popen csh\n");
X			exit(1);
X		}
X	}
X
X	while (argc > 1)
X	{
X		if (! match(argv[1], old))
X			unmatched++;
X		else
X		{
X			if (general)
X				sprintf(buf, cmd, argv[1], ground(new));
X			else
X				sprintf(buf, "%s %s %s", cmd, argv[1], ground(new));
X
X			if (strlen(buf) >= MAXLEN)
X				printf("subcmd: command too long\n");
X			or (noexec)
X				printf("would be executing %s\n", buf);
X			or (fast)
X			{
X				printf("executing %s\n", buf);
X				fprintf(csh, "%s\n", buf);
X			}
X			else
X			{
X				printf("executing %s\n", buf);
X				if (system(buf) != 0 && needzero)
X					printf("subcmd: command failed\n");
X			}
X		}
X
X		argv++;
X		argc--;
X	}
X
X	if (fast)
X		pclose(csh);
X
X	exit(ignore? 0: unmatched);
X}
X
X/*
X**	Tell the unfortunate user how to use subcmd.
X*/
X
Xusage()
X{
X	printf("Usage: subcmd [-fginz] [-vX] cmd oldpattern newpattern files ...\n");
X	exit(1);
X}
X
X/*
X**	Module to manipulate Cake patterns.
X*/
X
Xtypedef	struct	s_env
X{
X	char	*en_val;
X	bool	en_bound;
X} Env;
X
X#define	NOVAR	 10
X#define	MAXVAR	 11
X#define	MAXSIZE	128
X
XEnv	env[MAXVAR];
X
X/*
X**	This function initialises the environment of domatch.
X*/
X
Xbool
Xmatch(str, pat)
Xreg	char	*str;
Xreg	char	*pat;
X{
X	extern	bool	domatch();
X	reg	int	i;
X	reg	char	*s, *p;
X
X	p = pat+strlen(pat)-1;
X	if (*p != var_char && !isdigit(*p))	/* not part of a var */
X	{
X		s = str+strlen(str)-1;
X		if (*s != *p)			/* last chars differ */
X			return FALSE;
X	}
X
X	for (i = 0; i < MAXVAR; i++)
X		env[i].en_bound = FALSE;
X
X	return domatch(str, pat);
X}
X
X/*
X**	Match a string against a pattern.
X**	The pattern is expected to have been dereferenced.
X**	To handle nondeterminism, a brute force recursion approach
X**	is taken.
X*/
X
Xbool
Xdomatch(str, patstr)
Xreg	char	*str;
Xreg	char	*patstr;
X{
X	extern	char	*new_name();
X	char		buf[MAXSIZE];
X	reg	char	*follow;
X	reg	char	*s, *t;
X	reg	int	varno;
X	reg	int	i;
X	reg	bool	more;
X
X	if (patstr[0] == var_char)
X	{
X		if (isdigit(patstr[1]))
X		{
X			varno  = patstr[1] - '0';
X			follow = patstr + 2;
X		}
X		else
X		{
X			varno  = NOVAR;
X			follow = patstr + 1;
X		}
X
X		if (env[varno].en_bound)
X		{
X			/* lifetime of buf is local */
X			strcpy(buf, env[varno].en_val);
X			strcat(buf, follow);
X			return domatch(str, buf);
X		}
X
X		i = 0;
X		buf[0] = '\0';
X		env[varno].en_bound = TRUE;
X		env[varno].en_val = buf;
X
X		/* keep invariant: buf = tentative value of var  */
X		/* must consider *s == \0, but do not overshoot  */
X		for (s = str, more = TRUE; more; s++)
X		{
X			if (domatch(s, follow))
X			{
X				/* lifetime of buf is now global */
X				env[varno].en_val = new_name(buf);
X				return TRUE;
X			}
X
X			/* maintain invariant */
X			buf[i++] = *s;
X			buf[i]   = '\0';
X
X			more = (*s != '\0');
X		}
X		
X		/* no luck, match failed */
X		env[varno].en_bound = FALSE;
X		return FALSE;
X	}
X
X	/* here we have something other than a variable first off */
X	for (s = str, t = patstr; *t != '\0' && *t != var_char; s++, t++)
X	{
X		if (*t == '\\')
X			t++;	/* the new *t is not checked for % */
X		
X		if (*s != *t)
X			return FALSE;
X	}
X
X	/* see if we have come to the end of the pattern */
X	if (*t == '\0')
X		return *s == '\0';
X	
X	/* if not, recurse on the next variable */
X	return domatch(s, t);
X}
X
X/*
X**	Ground the argument string, i.e. replace all occurrences
X**	of variables in it. It is fatal error for the string to
X**	contain a variable which has no value.
X*/
X
Xchar *
Xground(str)
Xreg	char	*str;
X{
X	extern	char	*new_name();
X	reg	char	*s, *t;
X	reg	int	i, var;
X	char		buf[MAXSIZE];
X
X	i = 0;
X	for (s = str; *s != '\0'; s++)
X	{
X		if (*s == var_char)
X		{
X			if (isdigit(s[1]))
X				var = *++s - '0';
X			else
X				var = NOVAR;
X			
X			if (! env[var].en_bound)
X			{
X				printf("Attempt to use undefined value in %s\n", str);
X				exit(1);
X			}
X
X			for (t = env[var].en_val; *t != '\0'; t++)
X				buf[i++] = *t;
X		}
X		or (*s == '\\')
X		{
X			if (s[1] != '\0')
X				buf[i++] = *++s;
X		}
X		else
X			buf[i++] = *s;
X	}
X
X	if (i >= MAXSIZE)
X	{
X		printf("Ran out of buffer\n");
X		exit(1);
X	}
X
X	buf[i] = '\0';
X	return new_name(buf);
X}
X
Xchar *
Xnew_name(str)
Xreg	char	*str;
X{
X	extern	char	*malloc();
X	reg	char	*copy;
X
X	copy = malloc(strlen(str) + 1);
X	strcpy(copy, str);
X	return copy;
X}
SHAR_EOF
if test 5233 -ne "`wc -c < 'subcmd.c'`"
then
	echo shar: "error transmitting 'subcmd.c'" '(should have been 5233 characters)'
fi
fi
echo shar: "extracting 'usrc.c'" '(904 characters)'
if test -f 'usrc.c'
then
	echo shar: "will not over-write existing file 'usrc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'usrc.c'
X/*
X**	Track down ultimate source files.
X*/
X
X#include	<stdio.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	"std.h"
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	char		buf[80];
X	struct	stat	statbuf;
X	reg	int	i, j, errcnt;
X	reg	int	lastsuf, firstfile;
X	reg	bool	found;
X
X	lastsuf = 0;
X	firstfile = argc;
X	for (i = 1; i < argc; i++)
X	{
X		if (argv[i][0] == '.')
X			lastsuf = i;
X		or (firstfile == argc)
X			firstfile = i;
X	}
X
X	if (lastsuf > firstfile)
X	{
X		fprintf(stderr, "usrc: mixed suffixes and filenames\n");
X		exit(1);
X	}
X
X	errcnt = 0;
X	for (i = firstfile; i < argc; i++)
X	{
X		found = FALSE;
X		for (j = lastsuf; j > 0; j--)
X		{
X			sprintf(buf, "%s%s", argv[i], argv[j]);
X			if (stat(buf, &statbuf) == 0)
X			{
X				found = TRUE;
X				printf("%s\n", buf);
X				break;
X			}
X		}
X
X		if (! found)
X		{
X			fprintf(stderr, "usrc: cannot find source for %s\n", argv[i]);
X			errcnt++;
X		}
X	}
X
X	exit(errcnt);
X}
SHAR_EOF
if test 904 -ne "`wc -c < 'usrc.c'`"
then
	echo shar: "error transmitting 'usrc.c'" '(should have been 904 characters)'
fi
fi
exit 0
#	End of shell archive