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