⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pch.c

📁 制作2.6内核的CLFS时 patch包
💻 C
📖 第 1 页 / 共 4 页
字号:
/* reading patches *//* $Id: pch.c,v 1.44 2003/05/20 14:03:17 eggert Exp $ *//* Copyright (C) 1986, 1987, 1988 Larry Wall   Copyright (C) 1990, 1991, 1992, 1993, 1997, 1998, 1999, 2000, 2001,   2002, 2003 Free Software Foundation, Inc.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; see the file COPYING.   If not, write to the Free Software Foundation,   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#define XTERN extern#include <common.h>#include <backupfile.h>#include <dirname.h>#include <inp.h>#include <quotearg.h>#include <util.h>#undef XTERN#define XTERN#include <pch.h>#define INITHUNKMAX 125			/* initial dynamic allocation size *//* Patch (diff listing) abstract type. */static FILE *pfp;			/* patch file pointer */static int p_says_nonexistent[2];	/* [0] for old file, [1] for new:		0 for existent and nonempty,		1 for existent and probably (but not necessarily) empty,		2 for nonexistent */static int p_rfc934_nesting;		/* RFC 934 nesting level */static time_t p_timestamp[2];		/* timestamps in patch headers */static off_t 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_prefix_context;	/* # of prefix context lines */static LINENUM p_suffix_context;	/* # of suffix context lines */static LINENUM p_input_line;		/* current line # from patch file */static char **p_line;			/* the text of the hunk */static size_t *p_len;			/* line length including \n if any */static char *p_Char;			/* +, -, and ! */static LINENUM hunkmax = INITHUNKMAX;	/* size of above arrays */static int p_indent;			/* indent to patch */static bool p_strip_trailing_cr;	/* true if stripping trailing \r */static bool p_pass_comments_through;	/* true if not ignoring # lines */static file_offset p_base;		/* where to intuit this time */static LINENUM p_bline;			/* line # of p_base */static file_offset p_start;		/* where intuit found a patch */static LINENUM p_sline;			/* and the line number for it */static LINENUM p_hunk_beg;		/* line number of current hunk */static LINENUM p_efake = -1;		/* end of faked up lines--don't free */static LINENUM p_bfake = -1;		/* beg of faked up lines */enum nametype { OLD, NEW, INDEX, NONE };static char *scan_linenum (char *, LINENUM *);static enum diff intuit_diff_type (void);static enum nametype best_name (char * const *, int const *);static int prefix_components (char *, bool);static size_t pget_line (int, int, bool, bool);static size_t get_line (void);static bool incomplete_line (void);static bool grow_hunkmax (void);static void malformed (void) __attribute__ ((noreturn));static void next_intuit_at (file_offset, LINENUM);static void skip_to (file_offset, LINENUM);static char get_ed_command_letter (char const *);/* Prepare to look for the next patch in the patch file. */voidre_patch (void){    p_first = 0;    p_newfirst = 0;    p_ptrn_lines = 0;    p_repl_lines = 0;    p_end = -1;    p_max = 0;    p_indent = 0;    p_strip_trailing_cr = false;}/* Open the patch file at the beginning of time. */voidopen_patch_file (char const *filename){    file_offset file_pos = 0;    struct stat st;    if (!filename || !*filename || strEQ (filename, "-"))      {	file_offset stdin_pos;#if HAVE_SETMODE_DOS	if (binary_transput)	  {	    if (isatty (STDIN_FILENO))	      fatal ("cannot read binary data from tty on this platform");	    setmode (STDIN_FILENO, O_BINARY);	  }#endif	if (fstat (STDIN_FILENO, &st) != 0)	  pfatal ("fstat");	if (S_ISREG (st.st_mode) && (stdin_pos = file_tell (stdin)) != -1)	  {	    pfp = stdin;	    file_pos = stdin_pos;	  }	else	  {	    size_t charsread;	    int exclusive = TMPPATNAME_needs_removal ? 0 : O_EXCL;	    TMPPATNAME_needs_removal = 1;	    pfp = fdopen (create_file (TMPPATNAME,				       O_RDWR | O_BINARY | exclusive,				       (mode_t) 0),			  "w+b");	    if (!pfp)	      pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME));	    for (st.st_size = 0;		 (charsread = fread (buf, 1, bufsize, stdin)) != 0;		 st.st_size += charsread)	      if (fwrite (buf, 1, charsread, pfp) != charsread)		write_fatal ();	    if (ferror (stdin) || fclose (stdin) != 0)	      read_fatal ();	    if (fflush (pfp) != 0		|| file_seek (pfp, (file_offset) 0, SEEK_SET) != 0)	      write_fatal ();	  }      }    else      {	pfp = fopen (filename, binary_transput ? "rb" : "r");	if (!pfp)	  pfatal ("Can't open patch file %s", quotearg (filename));	if (fstat (fileno (pfp), &st) != 0)	  pfatal ("fstat");      }    p_filesize = st.st_size;    if (p_filesize != (file_offset) p_filesize)      fatal ("patch file is too long");    next_intuit_at (file_pos, (LINENUM) 1);    set_hunkmax();}/* Make sure our dynamically realloced tables are malloced to begin with. */voidset_hunkmax (void){    if (!p_line)	p_line = (char **) malloc (hunkmax * sizeof *p_line);    if (!p_len)	p_len = (size_t *) malloc (hunkmax * sizeof *p_len);    if (!p_Char)	p_Char = malloc (hunkmax * sizeof *p_Char);}/* Enlarge the arrays containing the current hunk of patch. */static boolgrow_hunkmax (void){    hunkmax *= 2;    assert (p_line && p_len && p_Char);    if ((p_line = (char **) realloc (p_line, hunkmax * sizeof (*p_line)))	&& (p_len = (size_t *) realloc (p_len, hunkmax * sizeof (*p_len)))	&& (p_Char = realloc (p_Char, hunkmax * sizeof (*p_Char))))      return true;    if (!using_plan_a)      memory_fatal ();    /* Don't free previous values of p_line etc.,       since some broken implementations free them for us.       Whatever is null will be allocated again from within plan_a (),       of all places.  */    return false;}/* True if the remainder of the patch file contains a diff of some sort. */boolthere_is_another_patch (void){    if (p_base != 0 && p_base >= p_filesize) {	if (verbosity == VERBOSE)	    say ("done\n");	return false;    }    if (verbosity == VERBOSE)	say ("Hmm...");    diff_type = intuit_diff_type();    if (diff_type == NO_DIFF) {	if (verbosity == VERBOSE)	  say (p_base	       ? "  Ignoring the trailing garbage.\ndone\n"	       : "  I can't seem to find a patch in there anywhere.\n");	if (! p_base && p_filesize)	  fatal ("Only garbage was found in the patch input.");	return false;    }    if (skip_rest_of_patch)      {	Fseek (pfp, p_start, SEEK_SET);	p_input_line = p_sline - 1;	return true;      }    if (verbosity == VERBOSE)	say ("  %sooks like %s to me...\n",	    (p_base == 0 ? "L" : "The next patch l"),	    diff_type == UNI_DIFF ? "a unified diff" :	    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 (verbosity != SILENT)      {	if (p_indent)	  say ("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");	if (p_strip_trailing_cr)	  say ("(Stripping trailing CRs from patch.)\n");	if (! inname)	  {	    char numbuf[LINENUM_LENGTH_BOUND + 1];	    say ("can't find file to patch at input line %s\n",		 format_linenum (numbuf, p_sline));	    if (diff_type != ED_DIFF)	      say (strippath == -1		   ? "Perhaps you should have used the -p or --strip option?\n"		   : "Perhaps you used the wrong -p or --strip option?\n");	  }      }    skip_to(p_start,p_sline);    while (!inname) {	if (force | batch) {	    say ("No file to patch.  Skipping patch.\n");	    skip_rest_of_patch = true;	    return true;	}	ask ("File to patch: ");	inname = fetchname (buf, 0, (time_t *) 0);	if (inname)	  {	    if (stat (inname, &instat) == 0)	      {		inerrno = 0;		invc = -1;	      }	    else	      {		perror (inname);		fflush (stderr);		free (inname);		inname = 0;	      }	  }	if (!inname) {	    ask ("Skip this patch? [y] ");	    if (*buf != 'n') {		if (verbosity != SILENT)		    say ("Skipping patch.\n");		skip_rest_of_patch = true;		return true;	    }	}    }    return true;}/* Determine what kind of diff is in the remaining part of the patch file. */static enum diffintuit_diff_type (void){    register file_offset this_line = 0;    register file_offset first_command_line = -1;    char first_ed_command_letter = 0;    LINENUM fcl_line = 0; /* Pacify `gcc -W'.  */    register bool this_is_a_command = false;    register bool stars_this_line = false;    enum nametype i;    char *name[3];    struct stat st[3];    int stat_errno[3];    int version_controlled[3];    register enum diff retval;    name[OLD] = name[NEW] = name[INDEX] = 0;    version_controlled[OLD] = -1;    version_controlled[NEW] = -1;    version_controlled[INDEX] = -1;    p_rfc934_nesting = 0;    p_timestamp[OLD] = p_timestamp[NEW] = (time_t) -1;    p_says_nonexistent[OLD] = p_says_nonexistent[NEW] = 0;    Fseek (pfp, p_base, SEEK_SET);    p_input_line = p_bline - 1;    for (;;) {	register char *s;	register char *t;	register file_offset previous_line = this_line;	register bool last_line_was_command = this_is_a_command;	register bool stars_last_line = stars_this_line;	register int indent = 0;	char ed_command_letter;	bool strip_trailing_cr;	size_t chars_read;	this_line = file_tell (pfp);	chars_read = pget_line (0, 0, false, false);	if (chars_read == (size_t) -1)	  memory_fatal ();	if (! chars_read) {	    if (first_ed_command_letter) {					/* nothing but deletes!? */		p_start = first_command_line;		p_sline = fcl_line;		retval = ED_DIFF;		goto scan_exit;	    }	    else {		p_start = this_line;		p_sline = p_input_line;		return NO_DIFF;	    }	}	strip_trailing_cr = 2 <= chars_read && buf[chars_read - 2] == '\r';	for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {	    if (*s == '\t')		indent = (indent + 8) & ~7;	    else		indent++;	}	for (t = s;  ISDIGIT (*t) || *t == ',';  t++)	  continue;	this_is_a_command = (ISDIGIT (*s) &&	  (*t == 'd' || *t == 'c' || *t == 'a') );	if (first_command_line < 0	    && ((ed_command_letter = get_ed_command_letter (s))		|| this_is_a_command)) {	    first_command_line = this_line;	    first_ed_command_letter = ed_command_letter;	    fcl_line = p_input_line;	    p_indent = indent;		/* assume this for now */	    p_strip_trailing_cr = strip_trailing_cr;	}	if (!stars_last_line && strnEQ(s, "*** ", 4))	    name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);	else if (strnEQ(s, "+++ ", 4))	    /* Swap with NEW below.  */	    name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);	else if (strnEQ(s, "Index:", 6))	    name[INDEX] = fetchname (s+6, strippath, (time_t *) 0);	else if (strnEQ(s, "Prereq:", 7)) {	    for (t = s + 7;  ISSPACE ((unsigned char) *t);  t++)	      continue;	    revision = t;	    for (t = revision;  *t;  t++)	      if (ISSPACE ((unsigned char) *t))		{		  char const *u;		  for (u = t + 1;  ISSPACE ((unsigned char) *u);  u++)		    continue;		  if (*u)		    {		      char numbuf[LINENUM_LENGTH_BOUND + 1];		      say ("Prereq: with multiple words at line %s of patch\n",			   format_linenum (numbuf, this_line));		    }		  break;		}	    if (t == revision)		revision = 0;	    else {		char oldc = *t;		*t = '\0';		revision = savestr (revision);		*t = oldc;	    }	} else	  {	    for (t = s;  t[0] == '-' && t[1] == ' ';  t += 2)	      continue;	    if (strnEQ(t, "--- ", 4))	      {		time_t timestamp = (time_t) -1;		name[NEW] = fetchname (t+4, strippath, &timestamp);		if (timestamp != (time_t) -1)		  {		    p_timestamp[NEW] = timestamp;		    p_rfc934_nesting = (t - s) >> 1;		  }	      }	  }	if ((diff_type == NO_DIFF || diff_type == ED_DIFF) &&	  first_command_line >= 0 &&	  strEQ(s, ".\n") ) {	    p_start = first_command_line;	    p_sline = fcl_line;	    retval = ED_DIFF;	    goto scan_exit;	}	if ((diff_type == NO_DIFF || diff_type == UNI_DIFF)	    && strnEQ(s, "@@ -", 4)) {	    /* `name' and `p_timestamp' are backwards; swap them.  */	    time_t ti = p_timestamp[OLD];	    p_timestamp[OLD] = p_timestamp[NEW];	    p_timestamp[NEW] = ti;	    t = name[OLD];	    name[OLD] = name[NEW];	    name[NEW] = t;	    s += 4;	    if (s[0] == '0' && !ISDIGIT (s[1]))	      p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];	    while (*s != ' ' && *s != '\n')	      s++;	    while (*s == ' ')	      s++;	    if (s[0] == '+' && s[1] == '0' && !ISDIGIT (s[2]))	      p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW];	    p_indent = indent;	    p_start = this_line;	    p_sline = p_input_line;	    retval = UNI_DIFF;	    if (! ((name[OLD] || ! p_timestamp[OLD])		   && (name[NEW] || ! p_timestamp[NEW]))		&& ! name[INDEX])	      {		char numbuf[LINENUM_LENGTH_BOUND + 1];		say ("missing header for unified diff at line %s of patch\n",		     format_linenum (numbuf, p_sline));	      }	    goto scan_exit;	}	stars_this_line = strnEQ(s, "********", 8);	if ((diff_type == NO_DIFF	     || diff_type == CONTEXT_DIFF	     || diff_type == NEW_CONTEXT_DIFF)	    && stars_last_line && strnEQ (s, "*** ", 4)) {	    s += 4;	    if (s[0] == '0' && !ISDIGIT (s[1]))	      p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];	    /* if this is a new context diff the character just before */	    /* the newline is a '*'. */	    while (*s != '\n')		s++;	    p_indent = indent;	    p_strip_trailing_cr = strip_trailing_cr;	    p_start = previous_line;	    p_sline = p_input_line - 1;	    retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);	    {	      /* Scan the first hunk to see whether the file contents		 appear to have been deleted.  */	      file_offset saved_p_base = p_base;	      LINENUM saved_p_bline = p_bline;	      Fseek (pfp, previous_line, SEEK_SET);	      p_input_line -= 2;	      if (another_hunk (retval, false)		  && ! p_repl_lines && p_newfirst == 1)		p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW];	      next_intuit_at (saved_p_base, saved_p_bline);	    }	    if (! ((name[OLD] || ! p_timestamp[OLD])		   && (name[NEW] || ! p_timestamp[NEW]))		&& ! name[INDEX])	      {		char numbuf[LINENUM_LENGTH_BOUND + 1];		say ("missing header for context diff at line %s of patch\n",		     format_linenum (numbuf, p_sline));	      }	    goto scan_exit;	}	if ((diff_type == NO_DIFF || diff_type == NORMAL_DIFF) &&	  last_line_was_command &&	  (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {	    p_start = previous_line;	    p_sline = p_input_line - 1;	    p_indent = indent;

⌨️ 快捷键说明

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