diff options
Diffstat (limited to 'contrib/patch/inp.c')
-rw-r--r-- | contrib/patch/inp.c | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/contrib/patch/inp.c b/contrib/patch/inp.c deleted file mode 100644 index 880b90e..0000000 --- a/contrib/patch/inp.c +++ /dev/null @@ -1,462 +0,0 @@ -/* inputting files to be patched */ - -/* $Id: inp.c,v 1.18 1997/07/21 17:59:46 eggert Exp $ */ - -/* -Copyright 1986, 1988 Larry Wall -Copyright 1991, 1992, 1993, 1997 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 <pch.h> -#include <util.h> -#undef XTERN -#define XTERN -#include <inp.h> - -/* Input-file-with-indexable-lines abstract type */ - -static char *i_buffer; /* plan A buffer */ -static char const **i_ptr; /* pointers to lines in plan A buffer */ - -static size_t tibufsize; /* size of plan b buffers */ -#ifndef TIBUFSIZE_MINIMUM -#define TIBUFSIZE_MINIMUM (8 * 1024) /* minimum value for tibufsize */ -#endif -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 size_t tireclen; /* length of records in tmp file */ -static size_t last_line_size; /* size of last input line */ - -static bool plan_a PARAMS ((char const *));/* yield FALSE if memory runs out */ -static void plan_b PARAMS ((char const *)); -static void report_revision PARAMS ((int)); -static void too_many_lines PARAMS ((char const *)) __attribute__((noreturn)); - -/* New patch--prepare to edit another file. */ - -void -re_input() -{ - if (using_plan_a) { - free (i_buffer); - free (i_ptr); - } - else { - close (tifd); - tifd = -1; - free(tibuf[0]); - tibuf[0] = 0; - tiline[0] = tiline[1] = -1; - tireclen = 0; - } -} - -/* Construct the line index, somehow or other. */ - -void -scan_input(filename) -char *filename; -{ - using_plan_a = ! (debug & 16) && plan_a (filename); - if (!using_plan_a) - plan_b(filename); - switch (verbosity) - { - case SILENT: - break; - - case VERBOSE: - say ("Patching file `%s' using Plan %s...\n", - filename, using_plan_a ? "A" : "B"); - break; - - case DEFAULT_VERBOSITY: - say ("patching file `%s'\n", filename); - break; - } -} - -/* Report whether a desired revision was found. */ - -static void -report_revision (found_revision) - int found_revision; -{ - if (found_revision) - { - if (verbosity == VERBOSE) - say ("Good. This file appears to be the %s version.\n", revision); - } - else if (force) - { - if (verbosity != SILENT) - say ("Warning: this file doesn't appear to be the %s version -- patching anyway.\n", - revision); - } - else if (batch) - { - fatal ("This file doesn't appear to be the %s version -- aborting.", - revision); - } - else - { - ask ("This file doesn't appear to be the %s version -- patch anyway? [n] ", - revision); - if (*buf != 'y') - fatal ("aborted"); - } -} - - -static void -too_many_lines (filename) - char const *filename; -{ - fatal ("File `%s' has too many lines.", filename); -} - - -void -get_input_file (filename, outname) - char const *filename; - char const *outname; -{ - int elsewhere = strcmp (filename, outname); - char const *cs; - char *diffbuf; - char *getbuf; - - if (inerrno == -1) - inerrno = stat (inname, &instat) == 0 ? 0 : errno; - - /* Perhaps look for RCS or SCCS versions. */ - if (patch_get - && invc != 0 - && (inerrno - || (! elsewhere - && (/* No one can write to it. */ - (instat.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0 - /* Only the owner (who's not me) can write to it. */ - || ((instat.st_mode & (S_IWGRP|S_IWOTH)) == 0 - && instat.st_uid != geteuid ())))) - && (invc = !! (cs = (version_controller - (filename, elsewhere, - inerrno ? (struct stat *) 0 : &instat, - &getbuf, &diffbuf))))) { - - if (!inerrno) { - if (!elsewhere - && (instat.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) != 0) - /* Somebody can write to it. */ - fatal ("file `%s' seems to be locked by somebody else under %s", - filename, cs); - /* It might be checked out unlocked. See if it's safe to - check out the default version locked. */ - if (verbosity == VERBOSE) - say ("Comparing file `%s' to default %s version...\n", - filename, cs); - if (systemic (diffbuf) != 0) - { - say ("warning: patching file `%s', which does not match default %s version\n", - filename, cs); - cs = 0; - } - } - - if (cs && version_get (filename, cs, ! inerrno, elsewhere, getbuf, - &instat)) - inerrno = 0; - - free (getbuf); - free (diffbuf); - - } else if (inerrno && !pch_says_nonexistent (reverse)) - { - errno = inerrno; - pfatal ("can't find file `%s'", filename); - } - - if (inerrno) - { - instat.st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; - instat.st_size = 0; - } - else if (! S_ISREG (instat.st_mode)) - fatal ("`%s' is not a regular file -- can't patch", filename); -} - - -/* Try keeping everything in memory. */ - -static bool -plan_a(filename) - char const *filename; -{ - register char const *s; - register char const *lim; - register char const **ptr; - register char *buffer; - register LINENUM iline; - size_t size = instat.st_size; - - /* Fail if the file size doesn't fit in a size_t, - or if storage isn't available. */ - if (! (size == instat.st_size - && (buffer = malloc (size ? size : (size_t) 1)))) - return FALSE; - - /* Read the input file, but don't bother reading it if it's empty. - When creating files, the files do not actually exist. */ - if (size) - { - int ifd = open (filename, O_RDONLY|binary_transput); - size_t buffered = 0, n; - if (ifd < 0) - pfatal ("can't open file `%s'", filename); - - while (size - buffered != 0) - { - n = read (ifd, buffer + buffered, size - buffered); - if (n == 0) - { - /* Some non-POSIX hosts exaggerate st_size in text mode; - or the file may have shrunk! */ - size = buffered; - break; - } - if (n == (size_t) -1) - { - /* Perhaps size is too large for this host. */ - close (ifd); - free (buffer); - return FALSE; - } - buffered += n; - } - - if (close (ifd) != 0) - read_fatal (); - } - - /* Scan the buffer and build array of pointers to lines. */ - lim = buffer + size; - iline = 3; /* 1 unused, 1 for SOF, 1 for EOF if last line is incomplete */ - for (s = buffer; (s = (char *) memchr (s, '\n', lim - s)); s++) - if (++iline < 0) - too_many_lines (filename); - if (! (iline == (size_t) iline - && (size_t) iline * sizeof *ptr / sizeof *ptr == (size_t) iline - && (ptr = (char const **) malloc ((size_t) iline * sizeof *ptr)))) - { - free (buffer); - return FALSE; - } - iline = 0; - for (s = buffer; ; s++) - { - ptr[++iline] = s; - if (! (s = (char *) memchr (s, '\n', lim - s))) - break; - } - if (size && lim[-1] != '\n') - ptr[++iline] = lim; - input_lines = iline - 1; - - if (revision) - { - char const *rev = revision; - int rev0 = rev[0]; - int found_revision = 0; - size_t revlen = strlen (rev); - - if (revlen <= size) - { - char const *limrev = lim - revlen; - - for (s = buffer; (s = (char *) memchr (s, rev0, limrev - s)); s++) - if (memcmp (s, rev, revlen) == 0 - && (s == buffer || ISSPACE ((unsigned char) s[-1])) - && (s + 1 == limrev || ISSPACE ((unsigned char) s[revlen]))) - { - found_revision = 1; - break; - } - } - - report_revision (found_revision); - } - - /* Plan A will work. */ - i_buffer = buffer; - i_ptr = ptr; - return TRUE; -} - -/* Keep (virtually) nothing in memory. */ - -static void -plan_b(filename) - char const *filename; -{ - register FILE *ifp; - register int c; - register size_t len; - register size_t maxlen; - register int found_revision; - register size_t i; - register char const *rev; - register size_t revlen; - register LINENUM line = 1; - - if (instat.st_size == 0) - filename = NULL_DEVICE; - if (! (ifp = fopen (filename, binary_transput ? "rb" : "r"))) - pfatal ("can't open file `%s'", filename); - tifd = create_file (TMPINNAME, O_RDWR | O_BINARY, (mode_t) 0); - i = 0; - len = 0; - maxlen = 1; - rev = revision; - found_revision = !rev; - revlen = rev ? strlen (rev) : 0; - - while ((c = getc (ifp)) != EOF) - { - len++; - - if (c == '\n') - { - if (++line < 0) - too_many_lines (filename); - if (maxlen < len) - maxlen = len; - len = 0; - } - - if (!found_revision) - { - if (i == revlen) - { - found_revision = ISSPACE ((unsigned char) c); - i = (size_t) -1; - } - else if (i != (size_t) -1) - i = rev[i]==c ? i + 1 : (size_t) -1; - - if (i == (size_t) -1 && ISSPACE ((unsigned char) c)) - i = 0; - } - } - - if (revision) - report_revision (found_revision); - Fseek (ifp, (off_t) 0, SEEK_SET); /* rewind file */ - for (tibufsize = TIBUFSIZE_MINIMUM; tibufsize < maxlen; tibufsize <<= 1) - continue; - lines_per_buf = tibufsize / maxlen; - tireclen = maxlen; - tibuf[0] = xmalloc (2 * tibufsize); - tibuf[1] = tibuf[0] + tibufsize; - - for (line = 1; ; line++) - { - char *p = tibuf[0] + maxlen * (line % lines_per_buf); - char const *p0 = p; - if (! (line % lines_per_buf)) /* new block */ - if (write (tifd, tibuf[0], tibufsize) != tibufsize) - write_fatal (); - if ((c = getc (ifp)) == EOF) - break; - - for (;;) - { - *p++ = c; - if (c == '\n') - { - last_line_size = p - p0; - break; - } - - if ((c = getc (ifp)) == EOF) - { - last_line_size = p - p0; - line++; - goto EOF_reached; - } - } - } - EOF_reached: - if (ferror (ifp) || fclose (ifp) != 0) - read_fatal (); - - if (line % lines_per_buf != 0) - if (write (tifd, tibuf[0], tibufsize) != tibufsize) - write_fatal (); - input_lines = line - 1; -} - -/* Fetch a line from the input file. */ - -char const * -ifetch (line, whichbuf, psize) -register LINENUM line; -int whichbuf; /* ignored when file in memory */ -size_t *psize; -{ - register char const *q; - register char const *p; - - if (line < 1 || line > input_lines) { - *psize = 0; - return ""; - } - if (using_plan_a) { - p = i_ptr[line]; - *psize = i_ptr[line + 1] - p; - return p; - } 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; - if (lseek (tifd, (off_t) (baseline/lines_per_buf * tibufsize), - SEEK_SET) == -1 - || read (tifd, tibuf[whichbuf], tibufsize) < 0) - read_fatal (); - } - p = tibuf[whichbuf] + (tireclen*offline); - if (line == input_lines) - *psize = last_line_size; - else { - for (q = p; *q++ != '\n'; ) - continue; - *psize = q - p; - } - return p; - } -} |