DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦bc4091025⟧ TextFile

    Length: 7765 (0x1e55)
    Types: TextFile
    Notes: UNIX file
    Names: »diff2.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/diff/diff2.c« 

TextFile

/*
 * This code is common between diff and /usr/lib/diffh.
 * It is a restructuring and re-write of the earlier
 * Tom Duff code so that reading options, opening files,
 * and outputing of the differences is common.
 */

#include "diff.h"
#include <sys/stat.h>
#include <signal.h>

int	dflag;			/* Dynamic decision about -h or not */
int	bflag;			/* Strip trailing blanks, multiple blanks */
int	eflag;			/* Editor script */
int	sflag;			/* Sed script output (used by SCCS) */
int	rflag;			/* Reversed order of printed (usually -e) */
int	incr;			/* Line number increment for `rflag' diff */
char	*csymbol;		/* Symbol for C pre-processor (#ifdef) */
int	sepflag;		/* On if text from both files involved */
int	caflag;			/* On for a change or append */
unsigned ninsert;		/* Number of lines inserted */
unsigned ndelete;		/* Number of lines deleted */
unsigned nunchanged;		/* Number of line unchanged */
char	*tmpnam1, *tmpnam2;
FILE	*fp1;			/* First input stream */
FILE	*fp2;			/* Second input stream */
char	*fn1, *fn2;		/* Filenames */

char	buf1[BUFSIZ];
char	buf2[BUFSIZ];

FILE	*openfile();
int	rmexit();
int	catchsig();
int	streq();
int	bstreq();

int	(*equal)() = streq;

main(argc, argv)
int argc;
char *argv[];
{
	register char *ap;
	register char **sargv = argv;
	size_t size1, size2;

	while (argc>1 && argv[1][0]=='-' && argv[1][1]!='\0') {
		for (ap = &argv[1][1]; *ap != '\0'; ap++)
			switch (*ap) {
			case 'b':
				bflag = 1;
				equal = bstreq;
				break;

			case 'c':
				if (argc < 3)
					usage();
				csymbol = argv[2];
				argv++;
				argc--;
				break;

			case 'd':
				dflag = 1;
				break;

			case 'e':
				eflag = rflag = 1;
				break;

			case 'f':
				eflag = 1;
				rflag = 0;
				break;

			case 's':
				eflag = sflag = 1;
				break;

			case 'h':
				diffh(sargv);
				break;

			default:
				usage();
			}
		argc--;
		argv++;
	}
	if (argc != 3)
		usage();
	if (eflag && csymbol!=NULL)
		cerr("-e and -c are incompatible options");
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, catchsig);
	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, catchsig);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, catchsig);
	fp1 = openfile(argv[1], argv[2], &tmpnam1, &size1);
	fp2 = openfile(argv[2], argv[1], &tmpnam2, &size2);
	if (dflag && (size1>NBIGF || size2>NBIGF))
		diffh(argv);
	setbuf(fp1, buf1);
	setbuf(fp2, buf2);
	fn1 = argv[1];
	fn2 = argv[2];
	diff(fp1, fp2);
	if (sflag)
		printf(":I%d\n:D%d\n:U%d\n", ninsert, ndelete, nunchanged);
	rmexit(ninsert || ndelete);
}

/*
 * Compare input lines for equality.
 */
bstreq(s1, s2)
register char *s1, *s2;
{
	for (;;) {
		if (*s1==' ' || *s1=='\t') {
			do {
				s1++;
			} while (*s1==' ' || *s1=='\t');
			if (*s1 == '\n') {
				while (*s2==' ' || *s2=='\t')
					s2++;
				return (*s2 == '\n');
			}
			if (*s2!=' ' && *s2!='\t')
				return (0);
			do {
				s2++;
			} while (*s2==' ' || *s2=='\t');
		} else {
			if (*s1 == '\n')
				while (*s2==' ' || *s2=='\t')
					s2++;
			if (*s1++ != *s2)
				return (0);
			if (*s2++ == '\n')
				return (1);
		}
	}
}

/*
 * Open the files, allowing for special standard input
 * convention (`-') and directories.  Copy any special
 * files or pipes to a tempfile because they cannot be
 * rewound.
 * `ofn' is the other name, for directory concatenation.
 */
FILE *
openfile(fn, ofn, tfnp, sizep)
char *fn;
char *ofn;
char **tfnp;
size_t *sizep;
{
	register char *cp;
	register int c;
	register FILE *fp;
	register FILE *tfp;
	char fname[300];
	struct stat sb;
	static int dirflag;

again:
	if (fn[0]=='-' && fn[1]=='\0')
		fp = stdin;
	else if ((fp = fopen(fn, "r")) == NULL)
		cerr("cannot open `%s'", fn);
	fstat(fileno(fp), &sb);
	*sizep = sb.st_size;
	switch (sb.st_mode & S_IFMT) {
	case S_IFDIR:
		if (dirflag)
			break;
		dirflag++;
		for (cp = ofn; *cp != '\0'; cp++)
			;
		while (cp > ofn)
			if (*--cp == '/') {
				cp++;
				break;
			}
		fn = sprintf(fname, "%s/%s", fn, cp);
		goto again;

	case S_IFREG:
		break;

	default:
		*tfnp = "/tmp/difXXXXXX";
		if ((tfp = fopen(mktemp(*tfnp), "w")) == NULL)
			cerr("cannot create tempfile");
		setbuf(fp, buf1);
		setbuf(tfp, buf2);
		while ((c = getc(fp)) != EOF)
			putc(c, tfp);
		fflush(tfp);
		if (ferror(tfp))
			cerr("write error on tempfile");
		fclose(tfp);
		if (fp != stdin)
			fclose(fp);
		if ((fp = fopen(*tfnp, "r")) == NULL)
			cerr("cannot re-open tempfile");
	}
	return (fp);
}

/*
 * Output a text line common to both files.
 * This is only used by the `-c' option.
 */
text(line)
char *line;
{
	++nunchanged;
	if (csymbol != NULL)
		fputs(line, stdout);
}

/*
 * Output a text line from the first file.
 */
text1(line)
register char *line;
{
	if (csymbol != NULL)
		fputs(line, stdout);
	else if (!eflag) {
		fputs("< ", stdout);
		fputs(line, stdout);
	}
	++ndelete;
}

/*
 * Output a line that is only in
 * the second file.
 */
text2(line)
register char *line;
{
	if (sflag) {
		putchar('\\');
		putchar('\n');
#if REALSED
		/*
		 * Sed is documented to strip
		 * leading blanks/tabs in appended
		 * text but doesn't.  This appears
		 * to be a feature rather than a bug.
		 */
		if (line[0]==' ' || line[0]=='\t')
			putchar('\\');
#endif
		while (*line != '\n') {
			if (*line == '\\')
				putchar(*line);
			putchar(*line++);
		}
	} else if (eflag) {
		if (line[0]=='.' && line[1]=='\n' && line[2]=='\0')
			fputs("~\n.\ns/~/./\na\n", stdout); else
			fputs(line, stdout);
	} else if (csymbol != NULL)
		fputs(line, stdout);
	else {
		fputs("> ", stdout);
		fputs(line, stdout);
	}
	caflag = 1;
	++ninsert;
}

/*
 * Output the start of a set of
 * changed lines.
 * Change is from `f1',`f2' (other file is `t1,t2').
 */
change(f1, f2, t1, t2)
unsigned f1, f2, t1, t2;
{
	sepflag = 1;
	if (csymbol != NULL)
		printf("#ifndef %s\n", csymbol);
	else {
		prange(f1, f2);
		if (sflag)
			putchar('c');
		else if (eflag)
			fputs("c\n", stdout);
		else {
			fputs(" c ", stdout);
			prange(t1, t2);
			putchar('\n');
		}
	}
	if (rflag)
		incr += t2-t1 + f1-f2;
}

/*
 * Output a set of appended lines.
 * Append after `f' the lines in
 * range `t1,t2'.
 */
append(f, t1, t2)
unsigned f, t1, t2;
{
	f--;
	if (csymbol != NULL)
		printf("#ifndef %s\n", csymbol);
	else {
		prange(f, f);
		if (sflag)
			putchar('a');
		else if (eflag) {
			fputs("a\n", stdout);
		} else {
			fputs(" a ", stdout);
			prange(t1, t2);
			putchar('\n');
		}
	}
	if (rflag)
		incr += t2-t1+1;
}

/*
 * Output a set of deleted lines.
 * Delete range `f1,f2' (other file
 * number is `t'.
 */
delete(f1, f2, t)
unsigned f1, f2, t;
{
	if (csymbol != NULL)
		printf("#ifdef %s\n", csymbol);
	else {
		prange(f1, f2);
		if (eflag)
			fputs("d\n", stdout);
		else
			printf(" d %u\n", t-1);
	}
	if (rflag)
		incr -= f2-f1+1;
}

/*
 * Output the middle of a set of
 * changed lines.
 */
prsep()
{
	if (!sepflag)
		return;
	sepflag = 0;
	if (csymbol != NULL)
		fputs("#else\n", stdout);
	else if (!eflag)
		fputs("---\n", stdout);
}

/*
 * Output the end part of a set
 * of changed lines.
 */
prend()
{
	if (csymbol != NULL)
		fputs("#endif\n", stdout);
	else if (caflag) {
		if (sflag)
			putchar('\n');
		else if (eflag)
			fputs(".\n", stdout);
	}
	caflag = 0;
}

/*
 * Print a line range either in the form
 * `a,b' or `a' (if a==b).
 */
prange(a, b)
register unsigned a, b;
{
	a += incr;
	b += incr;
	if (a == b)
		printf("%u", a); else
		printf("%u,%u", a, b);
}

/*
 * Exit, removing any possible temmpfiles.
 */
rmexit(s)
{
	if (tmpnam1 != NULL)
		unlink(tmpnam1);
	if (tmpnam2 != NULL)
		unlink(tmpnam2);
	exit(s);
}

/*
 * Catch signal and exit.
 */
catchsig()
{
	rmexit(2);
}
usage()
{
	fprintf(stderr, "Usage: diff [-bdefhs] [-c symbol] file1 file2\n");
	exit(2);
}

/* VARARGS */
cerr(x)
{
	fprintf(stderr, "diff: %r\n", &x);
	exit(2);
}