[news.software.anu-news] Patch part 6 of 7

fritz@unocss.UUCP (Tim Russell) (08/27/89)

+-+-+-+ Beginning of part 6 +-+-+-+
X`009    case '-':
X`009`009if (buf[1] == '-') `123
X`009`009    if (repl_beginning `124`124
X`009`009`009(p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n')))
X`009`009    `123
X`009`009`009if (p_end == 1) `123
X`009`009`009    /* `096old' lines were omitted - set up to fill */
X`009`009`009    /* them in from 'new' context lines. */
X`009`009`009    p_end = p_ptrn_lines + 1;
X`009`009`009    fillsrc = p_end + 1;
X`009`009`009    filldst = 1;
X`009`009`009    fillcnt = p_ptrn_lines;
X`009`009`009`125
X`009`009`009else `123
X`009`009`009    if (repl_beginning) `123
X`009`009`009`009if (repl_could_be_missing)`123
X`009`009`009`009    repl_missing = TRUE;
X`009`009`009`009    goto hunk_done;
X`009`009`009`009`125
X`009`009`009`009fatal3(
X"Duplicate \"---\" at line %ld--check line numbers at line %ld.\n",
X`009`009`009`009    p_input_line, p_hunk_beg + repl_beginning);
X`009`009`009    `125
X`009`009`009    else `123
X`009`009`009`009fatal4(
X"%s \"---\" at line %ld--check line numbers at line %ld.\n",
X`009`009`009`009    (p_end <= p_ptrn_lines
X`009`009`009`009`009? "Premature"
X`009`009`009`009`009: "Overdue" ),
X`009`009`009`009    p_input_line, p_hunk_beg);
X`009`009`009    `125
X`009`009`009`125
X`009`009    `125
X`009`009    repl_beginning = p_end;
X`009`009    repl_backtrack_position = ftell(pfp);
X`009`009    repl_patch_line = p_input_line;
X`009`009    p_line[p_end] = savestr(buf);
X`009`009    if (out_of_mem) `123
X`009`009`009p_end--;
X`009`009`009return FALSE;
X`009`009    `125
X`009`009    p_char[p_end] = '=';
X`009`009    for (s=buf; *s && !isdigit(*s); s++) ;
X`009`009    if (!*s)
X`009`009`009goto malformed;
X`009`009    p_newfirst = (LINENUM) atol(s);
X`009`009    while (isdigit(*s)) s++;
X`009`009    if (*s == ',') `123
X`009`009`009for (; *s && !isdigit(*s); s++) ;
X`009`009`009if (!*s)
X`009`009`009    goto malformed;
X`009`009`009p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1;
X`009`009    `125
X`009`009    else if (p_newfirst)
X`009`009`009p_repl_lines = 1;
X`009`009    else `123
X`009`009`009p_repl_lines = 0;
X`009`009`009p_newfirst = 1;
X`009`009    `125
X`009`009    p_max = p_repl_lines + p_end;
X`009`009    if (p_max > MAXHUNKSIZE)
X`009`009`009fatal4("Hunk too large (%ld lines) at line %ld: %s",
X`009`009`009      p_max, p_input_line, buf);
X`009`009    while (p_max >= hunkmax)
X`009`009`009grow_hunkmax();
X`009`009    if (p_repl_lines != ptrn_copiable)
X`009`009`009repl_could_be_missing = FALSE;
X`009`009    break;
X`009`009`125
X`009`009goto change_line;
X`009    case '+':  case '!':
X`009`009repl_could_be_missing = FALSE;
X`009      change_line:
X`009`009if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' &&
X`009`009  repl_beginning && repl_could_be_missing) `123
X`009`009    repl_missing = TRUE;
X`009`009    goto hunk_done;
X`009`009`125
X`009`009if (context > 0) `123
X`009`009    if (context < p_context)
X`009`009`009p_context = context;
X`009`009    context = -1000;
X`009`009`125
X`009`009p_line[p_end] = savestr(buf+2);
X`009`009if (out_of_mem) `123
X`009`009    p_end--;
X`009`009    return FALSE;
X`009`009`125
X`009`009break;
X`009    case '\t': case '\n':`009/* assume the 2 spaces got eaten */
X`009`009if (repl_beginning && repl_could_be_missing &&
X`009`009  (!ptrn_spaces_eaten `124`124 diff_type == NEW_CONTEXT_DIFF) ) `123
X`009`009    repl_missing = TRUE;
X`009`009    goto hunk_done;
X`009`009`125
X`009`009p_line[p_end] = savestr(buf);
X`009`009if (out_of_mem) `123
X`009`009    p_end--;
X`009`009    return FALSE;
X`009`009`125
X`009`009if (p_end != p_ptrn_lines + 1) `123
X`009`009    ptrn_spaces_eaten `124= (repl_beginning != 0);
X`009`009    context++;
X`009`009    if (!repl_beginning)
X`009`009`009ptrn_copiable++;
X`009`009    p_char[p_end] = ' ';
X`009`009`125
X`009`009break;
X`009    case ' ':
X`009`009if (!isspace(buf[1]) &&
X`009`009  repl_beginning && repl_could_be_missing) `123
X`009`009    repl_missing = TRUE;
X`009`009    goto hunk_done;
X`009`009`125
X`009`009context++;
X`009`009if (!repl_beginning)
X`009`009    ptrn_copiable++;
X`009`009p_line[p_end] = savestr(buf+2);
X`009`009if (out_of_mem) `123
X`009`009    p_end--;
X`009`009    return FALSE;
X`009`009`125
X`009`009break;
X`009    default:
X`009`009if (repl_beginning && repl_could_be_missing) `123
X`009`009    repl_missing = TRUE;
X`009`009    goto hunk_done;
X`009`009`125
X`009`009goto malformed;
X`009    `125
X`009    /* set up p_len for strncmp() so we don't have to */
X`009    /* assume null termination */
X`009    if (p_line[p_end])
X`009`009p_len[p_end] = strlen(p_line[p_end]);
X`009    else
X`009`009p_len[p_end] = 0;
X`009`125
X`009
X    hunk_done:
X`009if (p_end >=0 && !repl_beginning)
X`009    fatal2("No --- found in patch at line %ld\n", pch_hunk_beg());
X
X`009if (repl_missing) `123
X`009   `032
X`009    /* reset state back to just after --- */
X`009    p_input_line = repl_patch_line;
X`009    for (p_end--; p_end > repl_beginning; p_end--)
X`009`009free(p_line[p_end]);
X`009    Fseek(pfp, repl_backtrack_position, 0);
X`009   `032
X`009    /* redundant 'new' context lines were omitted - set */
X`009    /* up to fill them in from the old file context */
X`009    fillsrc = 1;
X`009    filldst = repl_beginning+1;
X`009    fillcnt = p_repl_lines;
X`009    p_end = p_max;
X`009`125
X
X`009if (diff_type == CONTEXT_DIFF &&
X`009  (fillcnt `124`124 (p_first > 1 && ptrn_copiable > 2*p_context)) ) `123
X`009    if (verbose)
X`009`009say1("\
V(Fascinating--this is really a new-style context diff but without the telltal
Xe\n\
Xextra asterisks on the *** line that usually indicate the new style...)\n");
X`009    diff_type = NEW_CONTEXT_DIFF;
X`009`125
X`009
X`009/* if there were omitted context lines, fill them in now */
X`009if (fillcnt) `123
X`009    p_bfake = filldst;`009`009/* remember where not to free() */
X`009    p_efake = filldst + fillcnt - 1;
X`009    while (fillcnt-- > 0) `123
X`009`009while (fillsrc <= p_end && p_char[fillsrc] != ' ')
X`009`009    fillsrc++;
X`009`009if (fillsrc > p_end)
V`009`009    fatal2("Replacement text or line numbers mangled in hunk at line
X %ld\n",
X`009`009`009p_hunk_beg);
X`009`009p_line[filldst] = p_line[fillsrc];
X`009`009p_char[filldst] = p_char[fillsrc];
X`009`009p_len[filldst] = p_len[fillsrc];
X`009`009fillsrc++; filldst++;
X`009    `125
X`009    while (fillsrc <= p_end && fillsrc != repl_beginning &&
X`009      p_char[fillsrc] != ' ')
X`009`009fillsrc++;
X#ifdef DEBUGGING
X`009    if (debug & 64)
X`009`009printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
X`009`009    fillsrc,filldst,repl_beginning,p_end+1);
X#endif
X`009    assert(fillsrc==p_end+1 `124`124 fillsrc==repl_beginning);
X`009    assert(filldst==p_end+1 `124`124 filldst==repl_beginning);
X`009`125
X    `125
X    else `123`009`009`009`009/* normal diff--fake it up */
X`009char hunk_type;
X`009Reg3 int i;
X`009LINENUM min, max;
X`009long line_beginning = ftell(pfp);
X
X`009p_context = 0;
X`009ret = pgets(buf, sizeof buf, pfp);
X`009p_input_line++;
X`009if (ret == Nullch `124`124 !isdigit(*buf)) `123
X`009    next_intuit_at(line_beginning,p_input_line);
X`009    return FALSE;
X`009`125
X`009p_first = (LINENUM)atol(buf);
X`009for (s=buf; isdigit(*s); s++) ;
X`009if (*s == ',') `123
X`009    p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
X`009    while (isdigit(*s)) s++;
X`009`125
X`009else
X`009    p_ptrn_lines = (*s != 'a');
X`009hunk_type = *s;
X`009if (hunk_type == 'a')
X`009    p_first++;`009`009`009/* do append rather than insert */
X`009min = (LINENUM)atol(++s);
X`009for (; isdigit(*s); s++) ;
X`009if (*s == ',')
X`009    max = (LINENUM)atol(++s);
X`009else
X`009    max = min;
X`009if (hunk_type == 'd')
X`009    min++;
X`009p_end = p_ptrn_lines + 1 + max - min + 1;
X`009if (p_end > MAXHUNKSIZE)
X`009    fatal4("Hunk too large (%ld lines) at line %ld: %s",
X`009`009  p_end, p_input_line, buf);
X`009while (p_end >= hunkmax)
X`009    grow_hunkmax();
X`009p_newfirst = min;
X`009p_repl_lines = max - min + 1;
X`009Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
X`009p_line[0] = savestr(buf);
X`009if (out_of_mem) `123
X`009    p_end = -1;
X`009    return FALSE;
X`009`125
X`009p_char[0] = '*';
X`009for (i=1; i<=p_ptrn_lines; i++) `123
X`009    ret = pgets(buf, sizeof buf, pfp);
X`009    p_input_line++;
X`009    if (ret == Nullch)
X`009`009fatal2("Unexpected end of file in patch at line %ld.\n",
X`009`009  p_input_line);
X`009    if (*buf != '<')
X`009`009fatal2("< expected at line %ld of patch.\n", p_input_line);
X`009    p_line[i] = savestr(buf+2);
X`009    if (out_of_mem) `123
X`009`009p_end = i-1;
X`009`009return FALSE;
X`009    `125
X`009    p_len[i] = strlen(p_line[i]);
X`009    p_char[i] = '-';
X`009`125
X`009if (hunk_type == 'c') `123
X`009    ret = pgets(buf, sizeof buf, pfp);
X`009    p_input_line++;
X`009    if (ret == Nullch)
X`009`009fatal2("Unexpected end of file in patch at line %ld.\n",
X`009`009    p_input_line);
X`009    if (*buf != '-')
X`009`009fatal2("--- expected at line %ld of patch.\n", p_input_line);
X`009`125
X`009Sprintf(buf, "--- %ld,%ld\n", min, max);
X`009p_line[i] = savestr(buf);
X`009if (out_of_mem) `123
X`009    p_end = i-1;
X`009    return FALSE;
X`009`125
X`009p_char[i] = '=';
X`009for (i++; i<=p_end; i++) `123
X`009    ret = pgets(buf, sizeof buf, pfp);
X`009    p_input_line++;
X`009    if (ret == Nullch)
X`009`009fatal2("Unexpected end of file in patch at line %ld.\n",
X`009`009    p_input_line);
X`009    if (*buf != '>')
X`009`009fatal2("> expected at line %ld of patch.\n", p_input_line);
X`009    p_line[i] = savestr(buf+2);
X`009    if (out_of_mem) `123
X`009`009p_end = i-1;
X`009`009return FALSE;
X`009    `125
X`009    p_len[i] = strlen(p_line[i]);
X`009    p_char[i] = '+';
X`009`125
X    `125
X    if (reverse)`009`009`009/* backwards patch? */
X`009if (!pch_swap())
X`009    say1("Not enough memory to swap next hunk!\n");
X#ifdef DEBUGGING
X    if (debug & 2) `123
X`009int i;
X`009char special;
X
X`009for (i=0; i <= p_end; i++) `123
X`009    if (i == p_ptrn_lines)
X`009`009special = '`094';
X`009    else
X`009`009special = ' ';
X`009    fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]);
X`009    Fflush(stderr);
X`009`125
X    `125
X#endif
X    if (p_end+1 < hunkmax)`009/* paranoia reigns supreme... */
X`009p_char[p_end+1] = '`094';  /* add a stopper for apply_hunk */
X    return TRUE;
X
Xmalformed:
X    fatal3("Malformed patch at line %ld: %s", p_input_line, buf);
X`009`009/* about as informative as "Syntax error" in C */
X    return FALSE;`009/* for lint */
X`125
X
X/* Input a line from the patch file, worrying about indentation. */
X
Xchar *
Xpgets(bf,sz,fp)
Xchar *bf;
Xint sz;
XFILE *fp;
X`123
X    char *ret = fgets(bf, sz, fp);
X    Reg1 char *s;
X    Reg2 int indent = 0;
X
X    if (p_indent && ret != Nullch) `123
V`009for (s=buf; indent < p_indent && (*s == ' ' `124`124 *s == '\t'); s++) `1
X23
X`009    if (*s == '\t')
X`009`009indent += 8 - (indent % 7);
X`009    else
X`009`009indent++;
X`009`125
X`009if (buf != s)
X`009    Strcpy(buf, s);
X    `125
X    return ret;
X`125
X
X/* Reverse the old and new portions of the current hunk. */
X
Xbool
Xpch_swap()
X`123
X    char **tp_line;`009`009/* the text of the hunk */
X    short *tp_len;`009`009/* length of each line */
X    char *tp_char;`009`009/* +, -, and ! */
X    Reg1 LINENUM i;
X    Reg2 LINENUM n;
X    bool blankline = FALSE;
X    Reg3 char *s;
X
X    i = p_first;
X    p_first = p_newfirst;
X    p_newfirst = i;
X   `032
X    /* make a scratch copy */
X
X    tp_line = p_line;
X    tp_len = p_len;
X    tp_char = p_char;
X    p_line = Null(char**);`009/* force set_hunkmax to allocate again */
X    p_len = Null(short*);
X    p_char = Nullch;
X    set_hunkmax();
V    if (p_line == Null(char**) `124`124 p_len == Null(short*) `124`124 p_char
X == Nullch) `123
X#ifndef lint
X`009if (p_line == Null(char**))
X`009    free((char*)p_line);
X`009p_line = tp_line;
X`009if (p_len == Null(short*))
X`009    free((char*)p_len);
X`009p_len = tp_len;
X#endif
X`009if (p_char == Nullch)
X`009    free((char*)p_char);
X`009p_char = tp_char;
X`009return FALSE;`009`009/* not enough memory to swap hunk! */
X    `125
X
X    /* now turn the new into the old */
X
X    i = p_ptrn_lines + 1;
X    if (tp_char[i] == '\n') `123`009`009/* account for possible blank line */
X`009blankline = TRUE;
X`009i++;
X    `125
X    if (p_efake >= 0) `123`009`009`009/* fix non-freeable ptr range */
X`009n = p_end - i + 1;
X`009if (p_efake > i)
X`009    n = -n;
X`009p_efake += n;
X`009p_bfake += n;
X    `125
X    for (n=0; i <= p_end; i++,n++) `123
X`009p_line[n] = tp_line[i];
X`009p_char[n] = tp_char[i];
X`009if (p_char[n] == '+')
X`009    p_char[n] = '-';
X`009p_len[n] = tp_len[i];
X    `125
X    if (blankline) `123
X`009i = p_ptrn_lines + 1;
X`009p_line[n] = tp_line[i];
X`009p_char[n] = tp_char[i];
X`009p_len[n] = tp_len[i];
X`009n++;
X    `125
X    assert(p_char[0] == '=');
X    p_char[0] = '*';
X    for (s=p_line[0]; *s; s++)
X`009if (*s == '-')
X`009    *s = '*';
X
X    /* now turn the old into the new */
X
X    assert(tp_char[0] == '*');
X    tp_char[0] = '=';
X    for (s=tp_line[0]; *s; s++)
X`009if (*s == '*')
X`009    *s = '-';
X    for (i=0; n <= p_end; i++,n++) `123
X`009p_line[n] = tp_line[i];
X`009p_char[n] = tp_char[i];
X`009if (p_char[n] == '-')
X`009    p_char[n] = '+';
X`009p_len[n] = tp_len[i];
X    `125
X    assert(i == p_ptrn_lines + 1);
X    i = p_ptrn_lines;
X    p_ptrn_lines = p_repl_lines;
X    p_repl_lines = i;
X#ifndef lint
X    if (tp_line == Null(char**))
X`009free((char*)tp_line);
X    if (tp_len == Null(short*))
X`009free((char*)tp_len);
X#endif
X    if (tp_char == Nullch)
X`009free((char*)tp_char);
X    return TRUE;
X`125
X
X/* Return the specified line position in the old file of the old context. */
X
XLINENUM
Xpch_first()
X`123
X    return p_first;
X`125
X
X/* Return the number of lines of old context. */
X
XLINENUM
Xpch_ptrn_lines()
X`123
X    return p_ptrn_lines;
X`125
X
X/* Return the probable line position in the new file of the first line. */
X
XLINENUM
Xpch_newfirst()
X`123
X    return p_newfirst;
X`125
X
X/* Return the number of lines in the replacement text including context. */
X
XLINENUM
Xpch_repl_lines()
X`123
X    return p_repl_lines;
X`125
X
X/* Return the number of lines in the whole hunk. */
X
XLINENUM
Xpch_end()
X`123
X    return p_end;
X`125
X
X/* Return the number of context lines before the first changed line. */
X
XLINENUM
Xpch_context()
X`123
X    return p_context;
X`125
X
X/* Return the length of a particular patch line. */
X
Xshort
Xpch_line_len(line)
XLINENUM line;
X`123
X    return p_len[line];
X`125
X
X/* Return the control character (+, -, *, !, etc) for a patch line. */
X
Xchar
Xpch_char(line)
XLINENUM line;
X`123
X    return p_char[line];
X`125
X
X/* Return a pointer to a particular patch line. */
X
Xchar *
Xpfetch(line)
XLINENUM line;
X`123
X    return p_line[line];
X`125
X
-+-+-+-+-+ End of part 6 +-+-+-+-+-
-- 
---------------------------------+--------------------------------------------
 Tim Russell, Computer Operator  | Internet: russell@zeus.unl.edu
 Campus Computing                | Bitnet:   russell@unoma1
 University of Nebraska at Omaha | UUCP:     uunet!zeus.unl.edu!russell