[net.sources] tail of patch 1.5, kit 1 of 2

lwall@sdcrdcf.UUCP (Larry Wall) (08/05/86)

The first patch kit appears to have arrived truncated at a large portion
of the net.  Since it seems to have been truncated at the same place
everywhere, rather than retransmit the whole thing, I'll deprive AT&T of
a few bucks by sending the tail end of the kit.  This will also keep it from
getting truncated again.

Take the first ~1565 lines of your kit and combine it with what is below,
and that should make a complete kit.  Kit 1 only contains patch.c, so you
could just edit off the shar header and trailer yourself if you prefer, though
you wouldn't get the cute message about having run all the kits and now you
should run Configure.

Also, there are two lines that should be commented out in the Makefile that
aren't.  You don't need to tell me about that.

Larry Wall
{allegra,burdvax,cbosgd,hplabs,ihnp4,sdcsvax}!sdcrdcf!lwall
-------------------------------------------------------------------------------
bool
another_hunk()
{
    Reg1 char *s;
    Reg8 char *ret;
    Reg2 int context = 0;

    while (p_end >= 0) {
	free(p_line[p_end]);		/* Changed from postdecrement */
	p_end--;			/* by Keenan Ross for BSD2.9  */
    }
    assert(p_end == -1);

    p_max = MAXHUNKSIZE;		/* gets reduced when --- found */
    if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
	long line_beginning = ftell(pfp);
					/* file pos of the current line */
	LINENUM repl_beginning = 0;	/* index of --- line */
	Reg4 LINENUM fillcnt = 0;	/* #lines of missing ptrn or repl */
	Reg5 LINENUM fillsrc;		/* index of first line to copy */
	Reg6 LINENUM filldst;		/* index of first missing line */
	bool ptrn_spaces_eaten = FALSE;	/* ptrn was slightly misformed */
	Reg9 bool repl_could_be_missing = TRUE;
					/* no + or ! lines in this hunk */
	bool repl_missing = FALSE;	/* we are now backtracking */
	long repl_backtrack_position = 0;
					/* file pos of first repl line */
	Reg7 LINENUM ptrn_copiable = 0;
					/* # of copiable lines in ptrn */

	ret = pgets(buf, sizeof buf, pfp);
	if (ret == Nullch || strnNE(buf, "********", 8)) {
	    next_intuit_at(line_beginning);
	    return FALSE;
	}
	p_context = 100;
	while (p_end < p_max) {
	    line_beginning = ftell(pfp);
	    ret = pgets(buf, sizeof buf, pfp);
	    if (ret == Nullch) {
		if (p_max - p_end < 4)
		    Strcpy(buf, "  \n");  /* assume blank lines got chopped */
		else {
		    if (repl_beginning && repl_could_be_missing) {
			repl_missing = TRUE;
			goto hunk_done;
		    }
		    fatal1("Unexpected end of file in patch.\n");
		}
	    }
	    p_input_line++;
	    p_char[++p_end] = *buf;
	    p_line[p_end] = Nullch;
	    switch (*buf) {
	    case '*':
		if (strnEQ(buf, "********", 8)) {
		    if (repl_beginning && repl_could_be_missing) {
			repl_missing = TRUE;
			goto hunk_done;
		    }
		    else
			fatal2("Unexpected end of hunk at line %ld.\n",
			    p_input_line);
		}
		if (p_end != 0) {
		    if (repl_beginning && repl_could_be_missing) {
			repl_missing = TRUE;
			goto hunk_done;
		    }
		    fatal3("Unexpected *** at line %ld: %s", p_input_line, buf);
		}
		context = 0;
		p_line[p_end] = savestr(buf);
		for (s=buf; *s && !isdigit(*s); s++) ;
		p_first = (LINENUM) atol(s);
		while (isdigit(*s)) s++;
		if (*s == ',') {
		    for (; *s && !isdigit(*s); s++) ;
		    p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
		}
		else if (p_first)
		    p_ptrn_lines = 1;
		else {
		    p_ptrn_lines = 0;
		    p_first = 1;
		}
		break;
	    case '-':
		if (buf[1] == '-') {
		    if (p_end != p_ptrn_lines + 1 &&
			p_end != p_ptrn_lines + 2) {
			if (p_end == 1) {
			    /* `old' lines were omitted - set up to fill */
			    /* them in from 'new' context lines. */
			    p_end = p_ptrn_lines + 1;
			    fillsrc = p_end + 1;
			    filldst = 1;
			    fillcnt = p_ptrn_lines;
			}
			else {
			    if (repl_beginning && repl_could_be_missing){
				repl_missing = TRUE;
				goto hunk_done;
			    }
			    fatal3("Unexpected --- at line %ld: %s",
				p_input_line, buf);
			}
		    }
		    repl_beginning = p_end;
		    repl_backtrack_position = ftell(pfp);
		    p_line[p_end] = savestr(buf);
		    p_char[p_end] = '=';
		    for (s=buf; *s && !isdigit(*s); s++) ;
		    p_newfirst = (LINENUM) atol(s);
		    while (isdigit(*s)) s++;
		    if (*s == ',') {
			for (; *s && !isdigit(*s); s++) ;
			p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1;
		    }
		    else if (p_newfirst)
			p_repl_lines = 1;
		    else {
			p_repl_lines = 0;
			p_newfirst = 1;
		    }
		    p_max = p_repl_lines + p_end;
		    if (p_repl_lines != ptrn_copiable)
			repl_could_be_missing = FALSE;
		    break;
		}
		goto change_line;
	    case '+':  case '!':
		repl_could_be_missing = FALSE;
	      change_line:
		if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' &&
		  repl_beginning && repl_could_be_missing) {
		    repl_missing = TRUE;
		    goto hunk_done;
		}
		if (context > 0) {
		    if (context < p_context)
			p_context = context;
		    context = -1000;
		}
		p_line[p_end] = savestr(buf+2);
		break;
	    case '\t': case '\n':	/* assume the 2 spaces got eaten */
		if (repl_beginning && repl_could_be_missing &&
		  (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF) ) {
		    repl_missing = TRUE;
		    goto hunk_done;
		}
		p_line[p_end] = savestr(buf);
		if (p_end != p_ptrn_lines + 1) {
		    ptrn_spaces_eaten |= (repl_beginning != 0);
		    context++;
		    if (!repl_beginning)
			ptrn_copiable++;
		    p_char[p_end] = ' ';
		}
		break;
	    case ' ':
		if (!isspace(buf[1]) &&
		  repl_beginning && repl_could_be_missing) {
		    repl_missing = TRUE;
		    goto hunk_done;
		}
		context++;
		if (!repl_beginning)
		    ptrn_copiable++;
		p_line[p_end] = savestr(buf+2);
		break;
	    default:
		if (repl_beginning && repl_could_be_missing) {
		    repl_missing = TRUE;
		    goto hunk_done;
		}
		fatal3("Malformed patch at line %ld: %s", p_input_line, buf);
	    }
	    p_len[p_end] = strlen(p_line[p_end]);
					/* for strncmp() so we do not have */
					/* to assume null termination */
	}
	
    hunk_done:
	if (p_end >=0 && !repl_beginning)
	    fatal2("No --- found in patch at line %ld\n", pch_hunk_beg());

	if (repl_missing) {
	    
	    /* reset state back to just after --- */
	    for (p_end--; p_end > repl_beginning; p_end--)
		free(p_line[p_end]);
	    Fseek(pfp, repl_backtrack_position, 0);
	    
	    /* redundant 'new' context lines were omitted - set */
	    /* up to fill them in from the old file context */
	    fillsrc = 1;
	    filldst = repl_beginning+1;
	    fillcnt = p_repl_lines;
	    p_end = p_max;
	}

	if (diff_type == CONTEXT_DIFF &&
	  (fillcnt || ptrn_copiable > 2*p_context) ) {
	    if (verbose)
		say1("\
(Fascinating--this is really a new-style context diff but without the telltale\n\
extra asterisks on the *** line that usually indicate the new style...)\n");
	    diff_type = NEW_CONTEXT_DIFF;
	}
	
	/* if there were omitted context lines, fill them in now */
	if (fillcnt) {
	    while (fillcnt-- > 0) {
		while (p_char[fillsrc] != ' ')
		    fillsrc++;
		p_line[filldst] = p_line[fillsrc];
		p_char[filldst] = p_char[fillsrc];
		p_len[filldst] = p_len[fillsrc];
		fillsrc++; filldst++;
	    }
	    assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
	    assert(filldst==p_end+1 || filldst==repl_beginning);
	}
    }
    else {				/* normal diff--fake it up */
	char hunk_type;
	Reg3 int i;
	LINENUM min, max;
	long line_beginning = ftell(pfp);

	p_context = 0;
	ret = pgets(buf, sizeof buf, pfp);
	p_input_line++;
	if (ret == Nullch || !isdigit(*buf)) {
	    next_intuit_at(line_beginning);
	    return FALSE;
	}
	p_first = (LINENUM)atol(buf);
	for (s=buf; isdigit(*s); s++) ;
	if (*s == ',') {
	    p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
	    while (isdigit(*s)) s++;
	}
	else
	    p_ptrn_lines = (*s != 'a');
	hunk_type = *s;
	if (hunk_type == 'a')
	    p_first++;			/* do append rather than insert */
	min = (LINENUM)atol(++s);
	for (; isdigit(*s); s++) ;
	if (*s == ',')
	    max = (LINENUM)atol(++s);
	else
	    max = min;
	if (hunk_type == 'd')
	    min++;
	p_end = p_ptrn_lines + 1 + max - min + 1;
	p_newfirst = min;
	p_repl_lines = max - min + 1;
	Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
	p_line[0] = savestr(buf);
	p_char[0] = '*';
	for (i=1; i<=p_ptrn_lines; i++) {
	    ret = pgets(buf, sizeof buf, pfp);
	    p_input_line++;
	    if (ret == Nullch)
		fatal2("Unexpected end of file in patch at line %ld.\n",
		  p_input_line);
	    if (*buf != '<')
		fatal2("< expected at line %ld of patch.\n", p_input_line);
	    p_line[i] = savestr(buf+2);
	    p_len[i] = strlen(p_line[i]);
	    p_char[i] = '-';
	}
	if (hunk_type == 'c') {
	    ret = pgets(buf, sizeof buf, pfp);
	    p_input_line++;
	    if (ret == Nullch)
		fatal2("Unexpected end of file in patch at line %ld.\n",
		    p_input_line);
	    if (*buf != '-')
		fatal2("--- expected at line %ld of patch.\n", p_input_line);
	}
	Sprintf(buf, "--- %ld,%ld\n", min, max);
	p_line[i] = savestr(buf);
	p_char[i] = '=';
	for (i++; i<=p_end; i++) {
	    ret = pgets(buf, sizeof buf, pfp);
	    p_input_line++;
	    if (ret == Nullch)
		fatal2("Unexpected end of file in patch at line %ld.\n",
		    p_input_line);
	    if (*buf != '>')
		fatal2("> expected at line %ld of patch.\n", p_input_line);
	    p_line[i] = savestr(buf+2);
	    p_len[i] = strlen(p_line[i]);
	    p_char[i] = '+';
	}
    }
    if (reverse)			/* backwards patch? */
	pch_swap();
#ifdef DEBUGGING
    if (debug & 2) {
	int i;
	char special;

	for (i=0; i <= p_end; i++) {
	    if (i == p_ptrn_lines)
		special = '^';
	    else
		special = ' ';
	    fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]);
	    Fflush(stderr);
	}
    }
#endif
    return TRUE;
}

char *
pgets(bf,sz,fp)
char *bf;
int sz;
FILE *fp;
{
    char *ret = fgets(bf, sz, fp);
    Reg1 char *s;
    Reg2 int indent = 0;

    if (p_indent && ret != Nullch) {
	for (s=buf; indent < p_indent && (*s == ' ' || *s == '\t'); s++) {
	    if (*s == '\t')
		indent += 8 - (indent % 7);
	    else
		indent++;
	}
	if (buf != s)
	    Strcpy(buf, s);
    }
    return ret;
}

pch_swap()
{
    char *tp_line[MAXHUNKSIZE];		/* the text of the hunk */
    char tp_char[MAXHUNKSIZE];		/* +, -, and ! */
    int tp_len[MAXHUNKSIZE];		/* length of each line */
    Reg1 LINENUM i;
    Reg2 LINENUM n;
    bool blankline = FALSE;
    Reg3 char *s;

    i = p_first;
    p_first = p_newfirst;
    p_newfirst = i;
    
    /* make a scratch copy */

    for (i=0; i<=p_end; i++) {
	tp_line[i] = p_line[i];
	tp_char[i] = p_char[i];
	tp_len[i] = p_len[i];
    }

    /* now turn the new into the old */

    i = p_ptrn_lines + 1;
    if (tp_char[i] == '\n') {		/* account for possible blank line */
	blankline = TRUE;
	i++;
    }
    for (n=0; i <= p_end; i++,n++) {
	p_line[n] = tp_line[i];
	p_char[n] = tp_char[i];
	if (p_char[n] == '+')
	    p_char[n] = '-';
	p_len[n] = tp_len[i];
    }
    if (blankline) {
	i = p_ptrn_lines + 1;
	p_line[n] = tp_line[i];
	p_char[n] = tp_char[i];
	p_len[n] = tp_len[i];
	n++;
    }
    assert(p_char[0] == '=');
    p_char[0] = '*';
    for (s=p_line[0]; *s; s++)
	if (*s == '-')
	    *s = '*';

    /* now turn the old into the new */

    assert(tp_char[0] == '*');
    tp_char[0] = '=';
    for (s=tp_line[0]; *s; s++)
	if (*s == '*')
	    *s = '-';
    for (i=0; n <= p_end; i++,n++) {
	p_line[n] = tp_line[i];
	p_char[n] = tp_char[i];
	if (p_char[n] == '-')
	    p_char[n] = '+';
	p_len[n] = tp_len[i];
    }
    assert(i == p_ptrn_lines + 1);
    i = p_ptrn_lines;
    p_ptrn_lines = p_repl_lines;
    p_repl_lines = i;
}

LINENUM
pch_first()
{
    return p_first;
}

LINENUM
pch_ptrn_lines()
{
    return p_ptrn_lines;
}

LINENUM
pch_newfirst()
{
    return p_newfirst;
}

LINENUM
pch_repl_lines()
{
    return p_repl_lines;
}

LINENUM
pch_end()
{
    return p_end;
}

LINENUM
pch_context()
{
    return p_context;
}

pch_line_len(line)
LINENUM line;
{
    return p_len[line];
}

char
pch_char(line)
LINENUM line;
{
    return p_char[line];
}

char *
pfetch(line)
LINENUM line;
{
    return p_line[line];
}

LINENUM
pch_hunk_beg()
{
    return p_input_line - p_end - 1;
}

char *
savestr(s)
Reg1 char *s;
{
    Reg3 char *rv;
    Reg2 char *t;

    t = s;
    while (*t++);
    rv = malloc((MEM) (t - s));
    if (rv == NULL)
	fatal1("patch: out of memory (savestr)\n");
    t = rv;
    while (*t++ = *s++);
    return rv;
}

my_exit(status)
int status;
{
    Unlink(TMPINNAME);
    if (!toutkeep) {
	Unlink(TMPOUTNAME);
    }
    if (!trejkeep) {
	Unlink(TMPREJNAME);
    }
    Unlink(TMPPATNAME);
    exit(status);
}

#ifdef lint

/*VARARGS ARGSUSED*/
say(pat) char *pat; { ; }
/*VARARGS ARGSUSED*/
fatal(pat) char *pat; { ; }
/*VARARGS ARGSUSED*/
ask(pat) char *pat; { ; }

#else lint

say(pat,arg1,arg2,arg3)
char *pat;
int arg1,arg2,arg3;
{
    fprintf(stderr, pat, arg1, arg2, arg3);
    Fflush(stderr);
}

fatal(pat,arg1,arg2,arg3)
char *pat;
int arg1,arg2,arg3;
{
    say(pat, arg1, arg2, arg3);
    my_exit(1);
}

ask(pat,arg1,arg2,arg3)
char *pat;
int arg1,arg2,arg3;
{
    int ttyfd;
    int r;
    bool tty2 = isatty(2);

    Sprintf(buf, pat, arg1, arg2, arg3);
    Fflush(stderr);
    write(2, buf, strlen(buf));
    if (tty2) {				/* might be redirected to a file */
	r = read(2, buf, sizeof buf);
    }
    else if (isatty(1)) {		/* this may be new file output */
	Fflush(stdout);
	write(1, buf, strlen(buf));
	r = read(1, buf, sizeof buf);
    }
    else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
					/* might be deleted or unwriteable */
	write(ttyfd, buf, strlen(buf));
	r = read(ttyfd, buf, sizeof buf);
	Close(ttyfd);
    }
    else if (isatty(0)) {		/* this is probably patch input */
	Fflush(stdin);
	write(0, buf, strlen(buf));
	r = read(0, buf, sizeof buf);
    }
    else {				/* no terminal at all--default it */
	buf[0] = '\n';
	r = 1;
    }
    if (r <= 0)
	buf[0] = 0;
    else
	buf[r] = '\0';
    if (!tty2)
	say1(buf);
}
#endif lint

bool
rev_in_string(string)
char *string;
{
    Reg1 char *s;
    Reg2 int patlen;

    if (revision == Nullch)
	return TRUE;
    patlen = strlen(revision);
    for (s = string; *s; s++) {
	if (isspace(*s) && strnEQ(s+1, revision, patlen) && 
		isspace(s[patlen+1] )) {
	    return TRUE;
	}
    }
    return FALSE;
}

set_signals()
{
    /*NOSTRICT*/
    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
	Signal(SIGHUP, my_exit);
    /*NOSTRICT*/
    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
	Signal(SIGINT, my_exit);
}

ignore_signals()
{
    /*NOSTRICT*/
    Signal(SIGHUP, SIG_IGN);
    /*NOSTRICT*/
    Signal(SIGINT, SIG_IGN);
}

makedirs(filename,striplast)
Reg1 char *filename;
bool striplast;
{
    char tmpbuf[256];
    Reg2 char *s = tmpbuf;
    char *dirv[20];
    Reg3 int i;
    Reg4 int dirvp = 0;

    while (*filename) {
	if (*filename == '/') {
	    filename++;
	    dirv[dirvp++] = s;
	    *s++ = '\0';
	}
	else {
	    *s++ = *filename++;
	}
    }
    *s = '\0';
    dirv[dirvp] = s;
    if (striplast)
	dirvp--;
    if (dirvp < 0)
	return;
    strcpy(buf, "mkdir");
    s = buf;
    for (i=0; i<=dirvp; i++) {
	while (*s) s++;
	*s++ = ' ';
	strcpy(s, tmpbuf);
	*dirv[i] = '/';
    }
    system(buf);
}
!STUFFY!FUNK!
echo ""
echo "End of kit 1 (of 2)"
cat /dev/null >kit1isdone
config=true
for iskit in 1 2; do
    if test -f kit${iskit}isdone; then
	echo "You have run kit ${iskit}."
    else
	echo "You still need to run kit ${iskit}."
	config=false
    fi
done
case $config in
    true)
	echo "You have run all your kits.  Please read README and then type Configure."
	chmod 755 Configure
	;;
esac
: I do not append .signature, but someone might mail this.
exit