pch.c

来自「这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易」· C语言 代码 · 共 1,866 行 · 第 1/4 页

C
1,866
字号
		  s++;		if (*s == ',')		  {		    do		      {			if (!*++s)			  malformed ();		      }		    while (! ISDIGIT (*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;		while (p_max >= hunkmax)		  if (! grow_hunkmax ())		    return -1;		if (p_repl_lines != ptrn_copiable		    && (p_prefix_context != 0			|| context != 0			|| p_repl_lines != 1))		  repl_could_be_missing = FALSE;		context = 0;		break;	    case '+':  case '!':		repl_could_be_missing = FALSE;	      change_line:		s = buf + 1;		chars_read--;		if (*s == '\n' && canonicalize) {		    strcpy (s, " \n");		    chars_read = 2;		}		if (*s == ' ' || *s == '\t') {		    s++;		    chars_read--;		} else if (repl_beginning && repl_could_be_missing) {		    repl_missing = TRUE;		    goto hunk_done;		}		if (! repl_beginning)		  {		    if (ptrn_prefix_context == -1)		      ptrn_prefix_context = context;		  }		else		  {		    if (repl_prefix_context == -1)		      repl_prefix_context = context;		  }		chars_read -=		  (1 < chars_read		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)		   && incomplete_line ());		p_len[p_end] = chars_read;		if (! (p_line[p_end] = savebuf (s, chars_read))) {		    p_end--;		    return -1;		}		context = 0;		break;	    case '\t': case '\n':	/* assume spaces got eaten */		s = buf;		if (*buf == '\t') {		    s++;		    chars_read--;		}		if (repl_beginning && repl_could_be_missing &&		    (!ptrn_spaces_eaten || difftype == NEW_CONTEXT_DIFF) ) {		    repl_missing = TRUE;		    goto hunk_done;		}		chars_read -=		  (1 < chars_read		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)		   && incomplete_line ());		p_len[p_end] = chars_read;		if (! (p_line[p_end] = savebuf (buf, chars_read))) {		    p_end--;		    return -1;		}		if (p_end != p_ptrn_lines + 1) {		    ptrn_spaces_eaten |= (repl_beginning != 0);		    some_context = TRUE;		    context++;		    if (!repl_beginning)			ptrn_copiable++;		    p_Char[p_end] = ' ';		}		break;	    case ' ':		s = buf + 1;		chars_read--;		if (*s == '\n' && canonicalize) {		    strcpy (s, "\n");		    chars_read = 2;		}		if (*s == ' ' || *s == '\t') {		    s++;		    chars_read--;		} else if (repl_beginning && repl_could_be_missing) {		    repl_missing = TRUE;		    goto hunk_done;		}		some_context = TRUE;		context++;		if (!repl_beginning)		    ptrn_copiable++;		chars_read -=		  (1 < chars_read		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)		   && incomplete_line ());		p_len[p_end] = chars_read;		if (! (p_line[p_end] = savebuf (buf + 2, chars_read))) {		    p_end--;		    return -1;		}		break;	    default:		if (repl_beginning && repl_could_be_missing) {		    repl_missing = TRUE;		    goto hunk_done;		}		malformed ();	    }	}    hunk_done:	if (p_end >=0 && !repl_beginning)	    fatal ("no `---' found in patch at line %ld", pch_hunk_beg ());	if (repl_missing) {	    /* reset state back to just after --- */	    p_input_line = repl_patch_line;	    context = repl_context;	    for (p_end--; p_end > repl_beginning; p_end--)		free(p_line[p_end]);	    Fseek (pfp, repl_backtrack_position, SEEK_SET);	    /* 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;	}	else if (!some_context && fillcnt == 1) {	    /* the first hunk was a null hunk with no context */	    /* and we were expecting one line -- fix it up. */	    while (filldst < p_end) {		p_line[filldst] = p_line[filldst+1];		p_Char[filldst] = p_Char[filldst+1];		p_len[filldst] = p_len[filldst+1];		filldst++;	    }#if 0	    repl_beginning--;		/* this doesn't need to be fixed */#endif	    p_end--;	    p_first++;			/* do append rather than insert */	    fillcnt = 0;	    p_ptrn_lines = 0;	}	p_prefix_context = ((repl_prefix_context == -1			     || (ptrn_prefix_context != -1				 && ptrn_prefix_context < repl_prefix_context))			    ? ptrn_prefix_context : repl_prefix_context);	p_suffix_context = ((ptrn_suffix_context != -1			     && ptrn_suffix_context < context)			    ? ptrn_suffix_context : context);	assert (p_prefix_context != -1 && p_suffix_context != -1);	if (difftype == CONTEXT_DIFF	    && (fillcnt		|| (p_first > 1		    && p_prefix_context + p_suffix_context < ptrn_copiable))) {	    if (verbosity == VERBOSE)		say ("%s\n%s\n%s\n","(Fascinating -- this is really a new-style context diff but without","the telltale extra asterisks on the *** line that usually indicate","the new style...)");	    diff_type = difftype = NEW_CONTEXT_DIFF;	}	/* if there were omitted context lines, fill them in now */	if (fillcnt) {	    p_bfake = filldst;		/* remember where not to free() */	    p_efake = filldst + fillcnt - 1;	    while (fillcnt-- > 0) {		while (fillsrc <= p_end && fillsrc != repl_beginning		       && p_Char[fillsrc] != ' ')		    fillsrc++;		if (p_end < fillsrc || fillsrc == repl_beginning)		    fatal ("replacement text or line numbers mangled in hunk at line %ld",			p_hunk_beg);		p_line[filldst] = p_line[fillsrc];		p_Char[filldst] = p_Char[fillsrc];		p_len[filldst] = p_len[fillsrc];		fillsrc++; filldst++;	    }	    while (fillsrc <= p_end && fillsrc != repl_beginning)	      {		if (p_Char[fillsrc] == ' ')		  fatal ("replacement text or line numbers mangled in hunk at line %ld",			 p_hunk_beg);		fillsrc++;	      }	    if (debug & 64)		printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",		    fillsrc,filldst,repl_beginning,p_end+1);	    assert(fillsrc==p_end+1 || fillsrc==repl_beginning);	    assert(filldst==p_end+1 || filldst==repl_beginning);	}    }    else if (difftype == UNI_DIFF) {	file_offset line_beginning = file_tell (pfp);					/* file pos of the current line */	register LINENUM fillsrc;	/* index of old lines */	register LINENUM filldst;	/* index of new lines */	char ch = '\0';	chars_read = get_line ();	if (chars_read == (size_t) -1	    || chars_read <= 4	    || strncmp (buf, "@@ -", 4) != 0) {	    next_intuit_at(line_beginning,p_input_line);	    return chars_read == (size_t) -1 ? -1 : 0;	}	s = buf+4;	if (!*s)	    malformed ();	p_first = (LINENUM) atol(s);	while (ISDIGIT (*s))	  s++;	if (*s == ',') {	    p_ptrn_lines = (LINENUM) atol(++s);	    while (ISDIGIT (*s))	      s++;	} else	    p_ptrn_lines = 1;	if (*s == ' ') s++;	if (*s != '+' || !*++s)	    malformed ();	p_newfirst = (LINENUM) atol(s);	while (ISDIGIT (*s))	  s++;	if (*s == ',') {	    p_repl_lines = (LINENUM) atol(++s);	    while (ISDIGIT (*s))	      s++;	} else	    p_repl_lines = 1;	if (*s == ' ') s++;	if (*s != '@')	    malformed ();	if (!p_ptrn_lines)	    p_first++;			/* do append rather than insert */	if (!p_repl_lines)	    p_newfirst++;	p_max = p_ptrn_lines + p_repl_lines + 1;	while (p_max >= hunkmax)	    if (! grow_hunkmax ())		return -1;	fillsrc = 1;	filldst = fillsrc + p_ptrn_lines;	p_end = filldst + p_repl_lines;	sprintf (buf,"*** %ld,%ld ****\n",p_first,p_first + p_ptrn_lines - 1);	p_len[0] = strlen (buf);	if (! (p_line[0] = savestr (buf))) {	    p_end = -1;	    return -1;	}	p_Char[0] = '*';	sprintf (buf,"--- %ld,%ld ----\n",p_newfirst,p_newfirst+p_repl_lines-1);	p_len[filldst] = strlen (buf);	if (! (p_line[filldst] = savestr (buf))) {	    p_end = 0;	    return -1;	}	p_Char[filldst++] = '=';	p_prefix_context = -1;	p_hunk_beg = p_input_line + 1;	while (fillsrc <= p_ptrn_lines || filldst <= p_end) {	    chars_read = get_line ();	    if (!chars_read) {		if (p_max - filldst < 3) {		    strcpy (buf, " \n");  /* assume blank lines got chopped */		    chars_read = 2;		} else {		    fatal ("unexpected end of file in patch");		}	    }	    if (chars_read == (size_t) -1)		s = 0;	    else if (*buf == '\t' || *buf == '\n') {		ch = ' ';		/* assume the space got eaten */		s = savebuf (buf, chars_read);	    }	    else {		ch = *buf;		s = savebuf (buf+1, --chars_read);	    }	    if (!s) {		while (--filldst > p_ptrn_lines)		    free(p_line[filldst]);		p_end = fillsrc-1;		return -1;	    }	    switch (ch) {	    case '-':		if (fillsrc > p_ptrn_lines) {		    free(s);		    p_end = filldst-1;		    malformed ();		}		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();		p_Char[fillsrc] = ch;		p_line[fillsrc] = s;		p_len[fillsrc++] = chars_read;		break;	    case '=':		ch = ' ';		/* FALL THROUGH */	    case ' ':		if (fillsrc > p_ptrn_lines) {		    free(s);		    while (--filldst > p_ptrn_lines)			free(p_line[filldst]);		    p_end = fillsrc-1;		    malformed ();		}		context++;		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();		p_Char[fillsrc] = ch;		p_line[fillsrc] = s;		p_len[fillsrc++] = chars_read;		s = savebuf (s, chars_read);		if (!s) {		    while (--filldst > p_ptrn_lines)			free(p_line[filldst]);		    p_end = fillsrc-1;		    return -1;		}		/* FALL THROUGH */	    case '+':		if (filldst > p_end) {		    free(s);		    while (--filldst > p_ptrn_lines)			free(p_line[filldst]);		    p_end = fillsrc-1;		    malformed ();		}		chars_read -= filldst == p_end && incomplete_line ();		p_Char[filldst] = ch;		p_line[filldst] = s;		p_len[filldst++] = chars_read;		break;	    default:		p_end = filldst;		malformed ();	    }	    if (ch != ' ') {		if (p_prefix_context == -1)		    p_prefix_context = context;		context = 0;	    }	}/* while */	if (p_prefix_context == -1)	  malformed ();	p_suffix_context = context;    }    else {				/* normal diff--fake it up */	char hunk_type;	register int i;	LINENUM min, max;	file_offset line_beginning = file_tell (pfp);	p_prefix_context = p_suffix_context = 0;	chars_read = get_line ();	if (chars_read == (size_t) -1 || !chars_read || !ISDIGIT (*buf)) {	    next_intuit_at(line_beginning,p_input_line);	    return chars_read == (size_t) -1 ? -1 : 0;	}	p_first = (LINENUM)atol(buf);	for (s = buf;  ISDIGIT (*s);  s++)	  continue;	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);	while (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;	while (p_end >= hunkmax)	  if (! grow_hunkmax ())	    {	      p_end = -1;	      return -1;	    }	p_newfirst = min;	p_repl_lines = max - min + 1;	sprintf (buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);	p_len[0] = strlen (buf);	if (! (p_line[0] = savestr (buf))) {	    p_end = -1;	    return -1;	}	p_Char[0] = '*';	for (i=1; i<=p_ptrn_lines; i++) {	    chars_read = get_line ();	    if (chars_read == (size_t) -1)	      {		p_end = i - 1;		return -1;	      }	    if (!chars_read)		fatal ("unexpected end of file in patch at line %ld",		  p_input_line);	    if (buf[0] != '<' || (buf[1] != ' ' && buf[1] != '\t'))		fatal ("`<' expected at line %ld of patch", p_input_line);	    chars_read -= 2 + (i == p_ptrn_lines && incomplete_line ());	    p_len[i] = chars_read;	    if (! (p_line[i] = savebuf (buf + 2, chars_read))) {		p_end = i-1;		return -1;	    }	    p_Char[i] = '-';	}	if (hunk_type == 'c') {	    chars_read = get_line ();	    if (chars_read == (size_t) -1)	      {		p_end = i - 1;		return -1;	      }	    if (! chars_read)		fatal ("unexpected end of file in patch at line %ld",		    p_input_line);	    if (*buf != '-')		fatal ("`---' expected at line %ld of patch", p_input_line);	}	sprintf (buf, "--- %ld,%ld\n", min, max);	p_len[i] = strlen (buf);	if (! (p_line[i] = savestr (buf))) {	    p_end = i-1;	    return -1;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?