-/* input file with indexable lines abstract type */
-
-bool using_plan_a = TRUE;
-static long i_size; /* size of the input file */
-static char *i_womp; /* plan a buffer for entire file */
-static char **i_ptr; /* pointers to lines in i_womp */
-
-static int tifd = -1; /* plan b virtual string array */
-static char *tibuf[2]; /* plan b buffers */
-static LINENUM tiline[2] = {-1,-1}; /* 1st line in each buffer */
-static LINENUM lines_per_buf; /* how many lines per buffer */
-static int tireclen; /* length of records in tmp file */
-
-re_input()
-{
- if (using_plan_a) {
- i_size = 0;
- /*NOSTRICT*/
- if (i_ptr != Null(char**))
- free((char *)i_ptr);
- if (i_womp != Nullch)
- free(i_womp);
- i_womp = Nullch;
- i_ptr = Null(char **);
- }
- else {
- using_plan_a = TRUE; /* maybe the next one is smaller */
- Close(tifd);
- tifd = -1;
- free(tibuf[0]);
- free(tibuf[1]);
- tibuf[0] = tibuf[1] = Nullch;
- tiline[0] = tiline[1] = -1;
- tireclen = 0;
- }
-}
-
-scan_input(filename)
-char *filename;
-{
- bool plan_a();
-
- if (!plan_a(filename))
- plan_b(filename);
-}
-
-/* try keeping everything in memory */
-
-bool
-plan_a(filename)
-char *filename;
-{
- int ifd;
- register char *s;
- register LINENUM iline;
-
- if (stat(filename,&filestat) < 0) {
- Sprintf(buf,"RCS/%s%s",filename,RCSSUFFIX);
- if (stat(buf,&filestat) >= 0 || stat(buf+4,&filestat) >= 0) {
- Sprintf(buf,CHECKOUT,filename);
- if (verbose)
- say("Can't find %s--attempting to check it out from RCS.\n",
- filename);
- if (system(buf) || stat(filename,&filestat))
- fatal("Can't check out %s.\n",filename);
- }
- else {
- Sprintf(buf,"SCCS/%s%s",SCCSPREFIX,filename);
- if (stat(buf,&filestat) >= 0 || stat(buf+5,&filestat) >= 0) {
- Sprintf(buf,GET,filename);
- if (verbose)
- say("Can't find %s--attempting to get it from SCCS.\n",
- filename);
- if (system(buf) || stat(filename,&filestat))
- fatal("Can't get %s.\n",filename);
- }
- else
- fatal("Can't find %s.\n",filename);
- }
- }
- if ((filestat.st_mode & S_IFMT) & ~S_IFREG)
- fatal("%s is not a normal file--can't patch.\n",filename);
- i_size = filestat.st_size;
- /*NOSTRICT*/
- i_womp = malloc((MEM)(i_size+2));
- if (i_womp == Nullch)
- return FALSE;
- if ((ifd = open(filename,0)) < 0)
- fatal("Can't open file %s\n",filename);
- /*NOSTRICT*/
- if (read(ifd,i_womp,(int)i_size) != i_size) {
- Close(ifd);
- free(i_womp);
- return FALSE;
- }
- Close(ifd);
- if (i_womp[i_size-1] != '\n')
- i_womp[i_size++] = '\n';
- i_womp[i_size] = '\0';
-
- /* count the lines in the buffer so we know how many pointers we need */
-
- iline = 0;
- for (s=i_womp; *s; s++) {
- if (*s == '\n')
- iline++;
- }
- /*NOSTRICT*/
- i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
- if (i_ptr == Null(char **)) { /* shucks, it was a near thing */
- free((char *)i_womp);
- return FALSE;
- }
-
- /* now scan the buffer and build pointer array */
-
- iline = 1;
- i_ptr[iline] = i_womp;
- for (s=i_womp; *s; s++) {
- if (*s == '\n')
- i_ptr[++iline] = s+1; /* these are NOT null terminated */
- }
- input_lines = iline - 1;
-
- /* now check for revision, if any */
-
- if (revision != Nullch) {
- if (!rev_in_string(i_womp)) {
- ask("This file doesn't appear to be the %s version--patch anyway? [n] ",
- revision);
- if (*buf != 'y')
- fatal("Aborted.\n");
- }
- else if (verbose)
- say("Good. This file appears to be the %s version.\n",
- revision);
- }
- return TRUE; /* plan a will work */
-}
-
-/* keep (virtually) nothing in memory */
-
-plan_b(filename)
-char *filename;
-{
- FILE *ifp;
- register int i = 0;
- register int maxlen = 1;
- bool found_revision = (revision == Nullch);
-
- using_plan_a = FALSE;
- if ((ifp = fopen(filename,"r")) == Nullfp)
- fatal("Can't open file %s\n",filename);
- if ((tifd = creat(TMPINNAME,0666)) < 0)
- fatal("Can't open file %s\n",TMPINNAME);
- while (fgets(buf,sizeof buf, ifp) != Nullch) {
- if (revision != Nullch && !found_revision && rev_in_string(buf))
- found_revision = TRUE;
- if ((i = strlen(buf)) > maxlen)
- maxlen = i; /* find longest line */
- }
- if (revision != Nullch) {
- if (!found_revision) {
- ask("This file doesn't appear to be the %s version--patch anyway? [n] ",
- revision);
- if (*buf != 'y')
- fatal("Aborted.\n");
- }
- else if (verbose)
- say("Good. This file appears to be the %s version.\n",
- revision);
- }
- Fseek(ifp,0L,0); /* rewind file */
- lines_per_buf = BUFFERSIZE / maxlen;
- tireclen = maxlen;
- tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
- tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
- if (tibuf[1] == Nullch)
- fatal("Can't seem to get enough memory.\n");
- for (i=1; ; i++) {
- if (! (i % lines_per_buf)) /* new block */
- if (write(tifd,tibuf[0],BUFFERSIZE) < BUFFERSIZE)
- fatal("patch: can't write temp file.\n");
- if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
- == Nullch) {
- input_lines = i - 1;
- if (i % lines_per_buf)
- if (write(tifd,tibuf[0],BUFFERSIZE) < BUFFERSIZE)
- fatal("patch: can't write temp file.\n");
- break;
- }
- }
- Fclose(ifp);
- Close(tifd);
- if ((tifd = open(TMPINNAME,0)) < 0) {
- fatal("Can't reopen file %s\n",TMPINNAME);
- }
-}
-
-/* fetch a line from the input file, \n terminated, not necessarily \0 */
-char *
-ifetch(line,whichbuf)
-register LINENUM line;
-int whichbuf; /* ignored when file in memory */
-{
- if (line < 1 || line > input_lines)
- return "";
- if (using_plan_a)
- return i_ptr[line];
- else {
- LINENUM offline = line % lines_per_buf;
- LINENUM baseline = line - offline;
-
- if (tiline[0] == baseline)
- whichbuf = 0;
- else if (tiline[1] == baseline)
- whichbuf = 1;
- else {
- tiline[whichbuf] = baseline;
- Lseek(tifd,(long)baseline / lines_per_buf * BUFFERSIZE,0);
- if (read(tifd,tibuf[whichbuf],BUFFERSIZE) < 0)
- fatal("Error reading tmp file %s.\n",TMPINNAME);
- }
- return tibuf[whichbuf] + (tireclen*offline);
- }
-}
-
-/* patch abstract type */
-
-static long p_filesize; /* size of the patch file */
-static LINENUM p_first; /* 1st line number */
-static LINENUM p_newfirst; /* 1st line number of replacement */
-static LINENUM p_ptrn_lines; /* # lines in pattern */
-static LINENUM p_repl_lines; /* # lines in replacement text */
-static LINENUM p_end = -1; /* last line in hunk */
-static LINENUM p_max; /* max allowed value of p_end */
-static LINENUM p_context = 3; /* # of context lines */
-static LINENUM p_input_line = 0; /* current line # from patch file */
-static char *p_line[MAXHUNKSIZE]; /* the text of the hunk */
-static char p_char[MAXHUNKSIZE]; /* +, -, and ! */
-static int p_len[MAXHUNKSIZE]; /* length of each line */
-static int p_indent; /* indent to patch */
-static long p_base; /* where to intuit this time */
-static long p_start; /* where intuit found a patch */
-
-re_patch()
-{
- p_first = (LINENUM)0;
- p_newfirst = (LINENUM)0;
- p_ptrn_lines = (LINENUM)0;
- p_repl_lines = (LINENUM)0;
- p_end = (LINENUM)-1;
- p_max = (LINENUM)0;
- p_indent = 0;
-}
-
-open_patch_file(filename)
-char *filename;
-{
- if (filename == Nullch || !*filename || strEQ(filename,"-")) {
- pfp = fopen(TMPPATNAME,"w");
- if (pfp == Nullfp)
- fatal("patch: can't create %s.\n",TMPPATNAME);
- while (fgets(buf,sizeof buf,stdin) != NULL)
- fputs(buf,pfp);
- Fclose(pfp);
- filename = TMPPATNAME;
- }
- pfp = fopen(filename,"r");
- if (pfp == Nullfp)
- fatal("patch file %s not found\n",filename);
- Fstat(fileno(pfp), &filestat);
- p_filesize = filestat.st_size;
- next_intuit_at(0L); /* start at the beginning */
-}
-
-bool
-there_is_another_patch()
-{
- bool no_input_file = (filearg[0] == Nullch);
-
- if (p_base != 0L && p_base >= p_filesize) {
- if (verbose)
- say("done\n");
- return FALSE;
- }
- if (verbose)
- say("Hmm...");
- diff_type = intuit_diff_type();
- if (!diff_type) {
- if (p_base != 0L) {
- if (verbose)
- say(" Ignoring the trailing garbage.\ndone\n");
- }
- else
- say(" I can't seem to find a patch in there anywhere.\n");
- return FALSE;
- }
- if (verbose)
- say(" %sooks like %s to me...\n",
- (p_base == 0L ? "L" : "The next patch l"),
- diff_type == CONTEXT_DIFF ? "a context diff" :
- diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
- diff_type == NORMAL_DIFF ? "a normal diff" :
- "an ed script" );
- if (p_indent && verbose)
- say("(Patch is indented %d space%s.)\n",p_indent,p_indent==1?"":"s");
- skip_to(p_start);
- if (no_input_file) {
- while (filearg[0] == Nullch) {
- ask("File to patch: ");
- filearg[0] = fetchname(buf);
- }
- if (verbose) {
- say("Patching file %s...\n",filearg[0]);
- }
- }
- return TRUE;
-}
-
-intuit_diff_type()
-{
- long this_line = 0;
- long previous_line;
- long first_command_line = -1;
- bool last_line_was_command = FALSE;
- bool this_line_is_command = FALSE;
- bool last_line_was_stars = FALSE;
- bool this_line_is_stars = FALSE;
- register int indent;
- register char *s, *t;
- char *oldname = Nullch;
- char *newname = Nullch;
- bool no_filearg = (filearg[0] == Nullch);
-
- Fseek(pfp,p_base,0);
- for (;;) {
- previous_line = this_line;
- last_line_was_command = this_line_is_command;
- last_line_was_stars = this_line_is_stars;
- this_line = ftell(pfp);
- indent = 0;
- if (fgets(buf,sizeof buf,pfp) == Nullch) {
- if (first_command_line >= 0L) {
- /* nothing but deletes!? */
- p_start = first_command_line;
- return ED_DIFF;
- }
- else {
- p_start = this_line;
- return 0;
- }
- }
- for (s = buf; *s == ' ' || *s == '\t'; s++) {
- if (*s == '\t')
- indent += 8 - (indent % 8);
- else
- indent++;
- }
- for (t=s; isdigit(*t) || *t == ','; t++) ;
- this_line_is_command = (isdigit(*s) &&
- (*t == 'd' || *t == 'c' || *t == 'a') );
- if (first_command_line < 0L && this_line_is_command) {
- first_command_line = this_line;
- p_indent = indent; /* assume this for now */
- }
- if (strnEQ(s,"*** ",4))
- oldname = fetchname(s+4);
- else if (strnEQ(s,"--- ",4)) {
- newname = fetchname(s+4);
- if (no_filearg) {
- if (oldname && newname) {
- if (strlen(oldname) < strlen(newname))
- filearg[0] = oldname;
- else
- filearg[0] = newname;
- }
- else if (oldname)
- filearg[0] = oldname;
- else if (newname)
- filearg[0] = newname;
- }
- }
- else if (strnEQ(s,"Index:",6)) {
- if (no_filearg)
- filearg[0] = fetchname(s+6);
- /* this filearg might get limboed */
- }
- else if (strnEQ(s,"Prereq:",7)) {
- for (t=s+7; isspace(*t); t++) ;
- revision = savestr(t);
- for (t=revision; *t && !isspace(*t); t++) ;
- *t = '\0';
- if (!*revision) {
- free(revision);
- revision = Nullch;
- }
- }
- if ((!diff_type || diff_type == ED_DIFF) &&
- first_command_line >= 0L &&
- strEQ(s,".\n") ) {
- p_indent = indent;
- p_start = first_command_line;
- return ED_DIFF;
- }
- this_line_is_stars = strnEQ(s,"********",8);
- if ((!diff_type || diff_type == CONTEXT_DIFF) && last_line_was_stars &&
- strnEQ(s,"*** ",4)) {
- /* if this is a new context diff the character just before */
- /* the newline is a '*'. */
- while (*s != '\n')
- s++;
- p_indent = indent;
- p_start = previous_line;
- return (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
- }
- if ((!diff_type || diff_type == NORMAL_DIFF) &&
- last_line_was_command &&
- (strnEQ(s,"< ",2) || strnEQ(s,"> ",2)) ) {
- p_start = previous_line;
- p_indent = indent;
- return NORMAL_DIFF;
- }
- }
-}
-
-char *
-fetchname(at)
-char *at;
-{
- char *s = savestr(at);
- char *name;
- register char *t;
- char tmpbuf[200];
-
- for (t=s; isspace(*t); t++) ;
- name = t;
- for (; *t && !isspace(*t); t++)
- if (!usepath)
- if (*t == '/')
- name = t+1;
- *t = '\0';
- name = savestr(name);
- Sprintf(tmpbuf,"RCS/%s",name);
- free(s);
- if (stat(name,&filestat) < 0) {
- Strcat(tmpbuf,RCSSUFFIX);
- if (stat(tmpbuf,&filestat) < 0 && stat(tmpbuf+4,&filestat) < 0) {
- Sprintf(tmpbuf,"SCCS/%s%s",SCCSPREFIX,name);
- if (stat(tmpbuf,&filestat) < 0 && stat(tmpbuf+5,&filestat) < 0) {
- free(name);
- name = Nullch;
- }
- }
- }
- return name;
-}
-
-next_intuit_at(file_pos)
-long file_pos;
-{
- p_base = file_pos;
-}
-
-skip_to(file_pos)
-long file_pos;
-{
- char *ret;
-
- assert(p_base <= file_pos);
- if (verbose && p_base < file_pos) {
- Fseek(pfp,p_base,0);
- say("The text leading up to this was:\n--------------------------\n");
- while (ftell(pfp) < file_pos) {
- ret = fgets(buf,sizeof buf,pfp);
- assert(ret != Nullch);
- say("|%s",buf);
- }
- say("--------------------------\n");
- }
- else
- Fseek(pfp,file_pos,0);
-}
-
-bool
-another_hunk()
-{
- register char *s;
- char *ret;
- register int context = 0;
-
- while (p_end >= 0) {
- free(p_line[p_end--]);
- }
- assert(p_end == -1);
-
- p_max = MAXHUNKSIZE; /* gets reduced when --- found */
- if (diff_type == CONTEXT_DIFF) {
- long line_beginning = ftell(pfp);
- LINENUM repl_beginning = 0;
-
- 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) {
- ret = pgets(buf,sizeof buf, pfp);
- if (ret == Nullch) {
- if (p_max - p_end < 4)
- Strcpy(buf," \n"); /* assume blank lines got chopped */
- else
- fatal("Unexpected end of file in patch.\n");
- }
- p_input_line++;
- if (strnEQ(buf,"********",8))
- fatal("Unexpected end of hunk at line %d.\n",
- p_input_line);
- p_char[++p_end] = *buf;
- switch (*buf) {
- case '*':
- if (p_end != 0)
- fatal("Unexpected *** at line %d: %s", p_input_line, buf);
- context = 0;
- p_line[p_end] = savestr(buf);
- for (s=buf; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- fatal("Malformed patch at line %d: %s", p_input_line, buf);
- p_first = (LINENUM) atol(s);
- while (isdigit(*s)) s++;
- for (; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- p_ptrn_lines = 1;
- else
- p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
- break;
- case '-':
- if (buf[1] == '-') {
- if (p_end != p_ptrn_lines + 1 &&
- p_end != p_ptrn_lines + 2)
- fatal("Unexpected --- at line %d: %s",
- p_input_line,buf);
- repl_beginning = p_end;
- context = 0;
- p_line[p_end] = savestr(buf);
- p_char[p_end] = '=';
- for (s=buf; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- fatal("Malformed patch at line %d: %s",
- p_input_line, buf);
- p_newfirst = (LINENUM) atol(s);
- while (isdigit(*s)) s++;
- for (; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- p_max = p_newfirst;
- else
- p_max = ((LINENUM)atol(s));
- p_max += 1 + p_end - p_newfirst;
- if (p_max >= MAXHUNKSIZE)
- fatal("Hunk too large (%d lines) at line %d: %s",
- p_max - p_end, p_input_line, buf);
- break;
- }
- /* FALL THROUGH */
- case '+': case '!':
- if (context > 0) {
- if (context < p_context)
- p_context = context;
- context = -100;
- }
- p_line[p_end] = savestr(buf+2);
- break;
- case '\t': case '\n': /* assume the 2 spaces got eaten */
- p_line[p_end] = savestr(buf);
- if (p_end != p_ptrn_lines + 1) {
- context++;
- p_char[p_end] = ' ';
- }
- break;
- case ' ':
- context++;
- p_line[p_end] = savestr(buf+2);
- break;
- default:
- fatal("Malformed patch at line %d: %s",p_input_line,buf);
- }
- /* set up p_len for strncmp() so we don't have to */
- /* assume null termination */
- if (p_line[p_end])
- p_len[p_end] = strlen(p_line[p_end]);
- else
- p_len[p_end] = 0;
- }
- if (p_end >=0 && !p_ptrn_lines)
- fatal("No --- found in patch at line %d\n", pch_hunk_beg());
- p_repl_lines = p_end - repl_beginning;
- }
- else if (diff_type == NEW_CONTEXT_DIFF) {
- long line_beginning = ftell(pfp);
- LINENUM repl_beginning = 0;
- LINENUM fillcnt = 0;
- LINENUM fillsrc;
- LINENUM filldst;
-
- ret = pgets(buf,sizeof buf, pfp);
- if (ret == Nullch || strnNE(buf,"********",8)) {
- next_intuit_at(line_beginning);
- return FALSE;
- }
- p_context = 0;
- while (p_end < p_max) {
- ret = pgets(buf,sizeof buf, pfp);
- if (ret == Nullch) {
- if (p_max - p_end < 4)
- Strcpy(buf," \n"); /* assume blank lines got chopped */
- else
- fatal("Unexpected end of file in patch.\n");
- }
- p_input_line++;
- p_char[++p_end] = *buf;
- switch (*buf) {
- case '*': /* another hunk */
- if (strnEQ(buf,"********",8))
- fatal("Unexpected end of hunk at line %d.\n",
- p_input_line);
-
- if (p_end != 0)
- fatal("Unexpected *** at line %d: %s", p_input_line, buf);
- context = 0;
- p_line[p_end] = savestr(buf);
- for (s=buf; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- fatal("Malformed patch at line %d: %s", p_input_line, buf);
- p_first = (LINENUM) atol(s);
- while (isdigit(*s)) s++;
- for (; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- p_ptrn_lines = 1;
- else
- p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
- break;
- case '-':
- if (buf[1] == '-') {
- if (p_end != p_ptrn_lines + 1) {
- 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
- fatal("Unexpected --- at line %d: %s",
- p_input_line,buf);
- }
- repl_beginning = p_end;
- p_line[p_end] = savestr(buf);
- p_char[p_end] = '=';
- for (s=buf; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- fatal("Malformed patch at line %d: %s",
- p_input_line, buf);
- p_newfirst = (LINENUM) atol(s);
- while (isdigit(*s)) s++;
- for (; *s && !isdigit(*s); s++) ;
- if (!isdigit(*s))
- p_max = p_newfirst;
- else
- p_max = ((LINENUM)atol(s));
- p_max += 1 + p_end - p_newfirst;
- if (p_max >= MAXHUNKSIZE)
- fatal("Hunk too large (%d lines) at line %d: %s",
- p_max - p_end, p_input_line, buf);
- if (p_max - p_end == context) {
- /* redundant 'new' context lines were omitted */
- /* set up to fill them in from the the old file's */
- /* context */
- fillsrc = 1;
- filldst = p_end + 1;
- fillcnt = p_max - repl_beginning;
- p_end = p_max;
- }
- break;
- }
- /* FALL THROUGH */
- case '+': case '!':
- if (context > 0 && p_context == 0) {
- p_context = context;
- }
- p_line[p_end] = savestr(buf+2);
- break;
- case '\t': case '\n': /* assume the 2 spaces got eaten */
- p_line[p_end] = savestr(buf);
- if (p_end != p_ptrn_lines + 1) {
- context++;
- p_char[p_end] = ' ';
- }
- break;
- case ' ':
- context++;
- p_line[p_end] = savestr(buf+2);
- break;
- default:
- fatal("Malformed patch at line %d: %s",p_input_line,buf);
- }
- /* set up p_len for strncmp() so we don't have to */
- /* assume null termination */
- if (p_line[p_end])
- p_len[p_end] = strlen(p_line[p_end]);
- else
- p_len[p_end] = 0;
- }
- if (p_end >=0 && !p_ptrn_lines)
- fatal("No --- found in patch at line %d\n", pch_hunk_beg());
-
- /* if there were omitted context lines, fill them in */
- if (fillcnt) {
- while (fillcnt-- > 0) {
- while (p_char[fillsrc] != ' ')
- fillsrc++;
- if (p_line[fillsrc])
- p_line[filldst] = savestr (p_line[fillsrc]);
- else
- p_line[filldst] = p_line[fillsrc];
- p_char[filldst] = p_char[fillsrc];
- p_len[filldst] = p_len[fillsrc];
- fillsrc++; filldst++;
- }
- assert(filldst==p_end+1 || filldst==repl_beginning);
- }
- p_repl_lines = p_end - repl_beginning;
- }
- else { /* normal diff--fake it up */
- char hunk_type;
- register 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,"*** %d,%d\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)
- fatal("Unexpected end of file in patch at line %d.\n",
- p_input_line);
- if (*buf != '<')
- fatal("< expected at line %d of patch.\n", p_input_line);
- p_line[i] = savestr(buf+2);
- if (p_line[i])
- p_len[i] = strlen(p_line[i]);
- else
- p_len[i] = 0;
- p_char[i] = '-';
- }
- if (hunk_type == 'c') {
- ret = pgets(buf,sizeof buf, pfp);
- p_input_line++;
- if (ret == Nullch)
- fatal("Unexpected end of file in patch at line %d.\n",
- p_input_line);
- if (*buf != '-')
- fatal("--- expected at line %d of patch.\n", p_input_line);
- }
- Sprintf(buf,"--- %d,%d\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)
- fatal("Unexpected end of file in patch at line %d.\n",
- p_input_line);
- if (*buf != '>')
- fatal("> expected at line %d of patch.\n", p_input_line);
- p_line[i] = savestr(buf+2);
- /* set up p_len for strncmp() so we don't have to */
- /* assume null termination */
- if (p_line[i])
- p_len[i] = strlen(p_line[i]);
- else
- p_len[i] = 0;
- 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 = ' ';
- printf("%3d %c %c %s",i,p_char[i],special,p_line[i]);
- }
- }
-#endif
- return TRUE;
-}
-
-char *
-pgets(bf,sz,fp)
-char *bf;
-int sz;
-FILE *fp;
-{
- char *ret = fgets(bf,sz,fp);
- register char *s;
- register 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 */
- register LINENUM i, n;
- bool blankline = FALSE;
- register 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)
-register char *s;
-{
- register char *rv,
- *t;
-
- t = s;
- while (*t++);
- rv = malloc((MEM) (t - s));
- if (rv == NULL)
- fatal ("patch: out of memory (savestr)\n");
- t = rv;
- while (*t++ = *s++);
- return rv;
-}