diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2003-07-21 14:00:42 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2003-07-21 14:00:42 +0000 |
commit | 030e9c816f2a21d808512a38b551c9db704f1f59 (patch) | |
tree | 6410131126b7d60dc39a772bd17700de49015fc2 /usr.bin/patch | |
parent | 302d48fc7269447e90636196dd32b5b47738baaa (diff) |
knf and other cleanup; ok otto
Diffstat (limited to 'usr.bin/patch')
-rw-r--r-- | usr.bin/patch/EXTERN.h | 2 | ||||
-rw-r--r-- | usr.bin/patch/INTERN.h | 2 | ||||
-rw-r--r-- | usr.bin/patch/backupfile.c | 405 | ||||
-rw-r--r-- | usr.bin/patch/backupfile.h | 54 | ||||
-rw-r--r-- | usr.bin/patch/common.h | 70 | ||||
-rw-r--r-- | usr.bin/patch/config.h | 44 | ||||
-rw-r--r-- | usr.bin/patch/inp.c | 607 | ||||
-rw-r--r-- | usr.bin/patch/inp.h | 19 | ||||
-rw-r--r-- | usr.bin/patch/patch.c | 1528 | ||||
-rw-r--r-- | usr.bin/patch/pch.c | 2317 | ||||
-rw-r--r-- | usr.bin/patch/pch.h | 50 | ||||
-rw-r--r-- | usr.bin/patch/util.c | 628 | ||||
-rw-r--r-- | usr.bin/patch/util.h | 28 |
13 files changed, 2852 insertions, 2902 deletions
diff --git a/usr.bin/patch/EXTERN.h b/usr.bin/patch/EXTERN.h index c7eeb0f81b6..1ac8f256930 100644 --- a/usr.bin/patch/EXTERN.h +++ b/usr.bin/patch/EXTERN.h @@ -1,4 +1,4 @@ -/* $OpenBSD: EXTERN.h,v 1.2 1996/06/10 11:21:23 niklas Exp $ */ +/* $OpenBSD: EXTERN.h,v 1.3 2003/07/21 14:00:41 deraadt Exp $ */ #ifdef EXT #undef EXT diff --git a/usr.bin/patch/INTERN.h b/usr.bin/patch/INTERN.h index c13d9ed97f2..2e8f97801ff 100644 --- a/usr.bin/patch/INTERN.h +++ b/usr.bin/patch/INTERN.h @@ -1,4 +1,4 @@ -/* $OpenBSD: INTERN.h,v 1.2 1996/06/10 11:21:24 niklas Exp $ */ +/* $OpenBSD: INTERN.h,v 1.3 2003/07/21 14:00:41 deraadt Exp $ */ #ifdef EXT #undef EXT diff --git a/usr.bin/patch/backupfile.c b/usr.bin/patch/backupfile.c index 308bed34c42..b1d37a98b1a 100644 --- a/usr.bin/patch/backupfile.c +++ b/usr.bin/patch/backupfile.c @@ -1,21 +1,24 @@ -/* $OpenBSD: backupfile.c,v 1.10 2003/07/18 02:00:09 deraadt Exp $ */ - -/* backupfile.c -- make Emacs style backup file names - Copyright (C) 1990 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it without restriction. - - 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. */ - -/* David MacKenzie <djm@ai.mit.edu>. - Some algorithms adapted from GNU Emacs. */ +/* $OpenBSD: backupfile.c,v 1.11 2003/07/21 14:00:41 deraadt Exp $ */ + +/* + * backupfile.c -- make Emacs style backup file names Copyright (C) 1990 Free + * Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * without restriction. + * + * 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. + */ + +/* + * David MacKenzie <djm@ai.mit.edu>. Some algorithms adapted from GNU Emacs. + */ #ifndef lint -static char rcsid[] = "$OpenBSD: backupfile.c,v 1.10 2003/07/18 02:00:09 deraadt Exp $"; -#endif /* not lint */ +static char rcsid[] = "$OpenBSD: backupfile.c,v 1.11 2003/07/21 14:00:41 deraadt Exp $"; +#endif /* not lint */ #include <stdio.h> #include <stdlib.h> @@ -33,32 +36,19 @@ static char rcsid[] = "$OpenBSD: backupfile.c,v 1.10 2003/07/18 02:00:09 deraadt #endif #define direct dirent #define NLENGTH(direct) (strlen((direct)->d_name)) -#else /* !DIRENT */ +#else /* !DIRENT */ #define NLENGTH(direct) ((direct)->d_namlen) -#ifdef USG -#ifdef SYSNDIR -#include <sys/ndir.h> -#else /* !SYSNDIR */ -#include <ndir.h> -#endif /* !SYSNDIR */ -#else /* !USG */ -#ifdef SYSDIR -#include <sys/dir.h> -#endif /* SYSDIR */ -#endif /* !USG */ -#endif /* !DIRENT */ - -#ifndef isascii -#define ISDIGIT(c) (isdigit ((unsigned char) (c))) -#else +#endif /* !DIRENT */ + #define ISDIGIT(c) (isascii (c) && isdigit (c)) -#endif #include <unistd.h> #if defined (_POSIX_VERSION) -/* POSIX does not require that the d_ino field be present, and some - systems do not provide it. */ +/* + * POSIX does not require that the d_ino field be present, and some systems + * do not provide it. + */ #define REAL_DIR_ENTRY(dp) 1 #else #define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0) @@ -67,221 +57,204 @@ static char rcsid[] = "$OpenBSD: backupfile.c,v 1.10 2003/07/18 02:00:09 deraadt /* Which type of backup file names are generated. */ enum backup_type backup_type = none; -/* The extension added to file names to produce a simple (as opposed - to numbered) backup file name. */ -char *simple_backup_suffix = "~"; - -static char *concat(char *, char *); -char *find_backup_file_name(char *); -static char *make_version_name(char *, int); -static int max_backup_version(char *, char *); -static int version_number(char *, char *, int); -static int argmatch(char *, char **); -static void invalid_arg(char *, char *, int); - -#ifndef NODIR -/* Return the name of the new backup file for file FILE, - allocated with malloc. Return 0 if out of memory. - FILE must not end with a '/' unless it is the root directory. - Do not call this function if backup_type == none. */ - +/* + * The extension added to file names to produce a simple (as opposed to + * numbered) backup file name. + */ +char *simple_backup_suffix = "~"; + +static char *concat(char *, char *); +char *find_backup_file_name(char *); +static char *make_version_name(char *, int); +static int max_backup_version(char *, char *); +static int version_number(char *, char *, int); +static int argmatch(char *, char **); +static void invalid_arg(char *, char *, int); + +/* + * Return the name of the new backup file for file FILE, allocated with + * malloc. Return 0 if out of memory. FILE must not end with a '/' unless it + * is the root directory. Do not call this function if backup_type == none. + */ char * -find_backup_file_name (file) - char *file; +find_backup_file_name(char *file) { - char *dir; - char *base_versions; - int highest_backup; - - if (backup_type == simple) - return concat (file, simple_backup_suffix); - base_versions = concat (basename (file), ".~"); - if (base_versions == 0) - return 0; - dir = dirname (file); - if (dir == 0) - { - free (base_versions); - return 0; - } - highest_backup = max_backup_version (base_versions, dir); - free (base_versions); - if (backup_type == numbered_existing && highest_backup == 0) - return concat (file, simple_backup_suffix); - return make_version_name (file, highest_backup + 1); + char *dir, *base_versions; + int highest_backup; + + if (backup_type == simple) + return concat(file, simple_backup_suffix); + base_versions = concat(basename(file), ".~"); + if (base_versions == 0) + return 0; + dir = dirname(file); + if (dir == 0) { + free(base_versions); + return 0; + } + highest_backup = max_backup_version(base_versions, dir); + free(base_versions); + if (backup_type == numbered_existing && highest_backup == 0) + return concat(file, simple_backup_suffix); + return make_version_name(file, highest_backup + 1); } -/* Return the number of the highest-numbered backup file for file - FILE in directory DIR. If there are no numbered backups - of FILE in DIR, or an error occurs reading DIR, return 0. - FILE should already have ".~" appended to it. */ - +/* + * Return the number of the highest-numbered backup file for file FILE in + * directory DIR. If there are no numbered backups of FILE in DIR, or an + * error occurs reading DIR, return 0. FILE should already have ".~" appended + * to it. + */ static int -max_backup_version (file, dir) - char *file, *dir; +max_backup_version(char *file, char *dir) { - DIR *dirp; - struct direct *dp; - int highest_version; - int this_version; - int file_name_length; - - dirp = opendir (dir); - if (!dirp) - return 0; - - highest_version = 0; - file_name_length = strlen (file); - - while ((dp = readdir (dirp)) != 0) - { - if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) <= file_name_length) - continue; - - this_version = version_number (file, dp->d_name, file_name_length); - if (this_version > highest_version) - highest_version = this_version; - } - closedir (dirp); - return highest_version; -} + DIR *dirp; + struct direct *dp; + int highest_version, this_version, file_name_length; + + dirp = opendir(dir); + if (!dirp) + return 0; -/* Return a string, allocated with malloc, containing - "FILE.~VERSION~". Return 0 if out of memory. */ + highest_version = 0; + file_name_length = strlen(file); + while ((dp = readdir(dirp)) != 0) { + if (!REAL_DIR_ENTRY(dp) || NLENGTH(dp) <= file_name_length) + continue; + + this_version = version_number(file, dp->d_name, file_name_length); + if (this_version > highest_version) + highest_version = this_version; + } + closedir(dirp); + return highest_version; +} + +/* + * Return a string, allocated with malloc, containing "FILE.~VERSION~". + * Return 0 if out of memory. + */ static char * -make_version_name (file, version) - char *file; - int version; +make_version_name(char *file, int version) { - char *backup_name; + char *backup_name; - if (asprintf (&backup_name, "%s.~%d~", file, version) == -1) - return 0; - return backup_name; + if (asprintf(&backup_name, "%s.~%d~", file, version) == -1) + return 0; + return backup_name; } -/* If BACKUP is a numbered backup of BASE, return its version number; - otherwise return 0. BASE_LENGTH is the length of BASE. - BASE should already have ".~" appended to it. */ - +/* + * If BACKUP is a numbered backup of BASE, return its version number; + * otherwise return 0. BASE_LENGTH is the length of BASE. BASE should + * already have ".~" appended to it. + */ static int -version_number (base, backup, base_length) - char *base; - char *backup; - int base_length; +version_number(char *base, char *backup, int base_length) { - int version; - char *p; - - version = 0; - if (!strncmp (base, backup, base_length) && ISDIGIT (backup[base_length])) - { - for (p = &backup[base_length]; ISDIGIT (*p); ++p) - version = version * 10 + *p - '0'; - if (p[0] != '~' || p[1]) + int version; + char *p; + version = 0; - } - return version; + if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) { + for (p = &backup[base_length]; ISDIGIT(*p); ++p) + version = version * 10 + *p - '0'; + if (p[0] != '~' || p[1]) + version = 0; + } + return version; } -/* Return the newly-allocated concatenation of STR1 and STR2. - If out of memory, return 0. */ - -static char * -concat (str1, str2) - char *str1, *str2; +/* + * Return the newly-allocated concatenation of STR1 and STR2. If out of + * memory, return 0. + */ +static char * +concat(char *str1, char *str2) { - char *newstr; + char *newstr; - if (asprintf(&newstr, "%s%s", str1, str2) == -1) - return 0; - return newstr; + if (asprintf(&newstr, "%s%s", str1, str2) == -1) + return 0; + return newstr; } -/* If ARG is an unambiguous match for an element of the - null-terminated array OPTLIST, return the index in OPTLIST - of the matched element, else -1 if it does not match any element - or -2 if it is ambiguous (is a prefix of more than one element). */ - +/* + * If ARG is an unambiguous match for an element of the null-terminated array + * OPTLIST, return the index in OPTLIST of the matched element, else -1 if it + * does not match any element or -2 if it is ambiguous (is a prefix of more + * than one element). + */ int -argmatch (arg, optlist) - char *arg; - char **optlist; +argmatch(char *arg, char **optlist) { - int i; /* Temporary index in OPTLIST. */ - int arglen; /* Length of ARG. */ - int matchind = -1; /* Index of first nonexact match. */ - int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */ - - arglen = strlen (arg); - - /* Test all elements for either exact match or abbreviated matches. */ - for (i = 0; optlist[i]; i++) - { - if (!strncmp (optlist[i], arg, arglen)) - { - if (strlen (optlist[i]) == arglen) - /* Exact match found. */ - return i; - else if (matchind == -1) - /* First nonexact match found. */ - matchind = i; - else - /* Second nonexact match found. */ - ambiguous = 1; + int i; /* Temporary index in OPTLIST. */ + int arglen; /* Length of ARG. */ + int matchind = -1; /* Index of first nonexact match. */ + int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */ + + arglen = strlen(arg); + + /* Test all elements for either exact match or abbreviated matches. */ + for (i = 0; optlist[i]; i++) { + if (!strncmp(optlist[i], arg, arglen)) { + if (strlen(optlist[i]) == arglen) + /* Exact match found. */ + return i; + else if (matchind == -1) + /* First nonexact match found. */ + matchind = i; + else + /* Second nonexact match found. */ + ambiguous = 1; + } } - } - if (ambiguous) - return -2; - else - return matchind; + if (ambiguous) + return -2; + else + return matchind; } -/* Error reporting for argmatch. - KIND is a description of the type of entity that was being matched. - VALUE is the invalid value that was given. - PROBLEM is the return value from argmatch. */ - +/* + * Error reporting for argmatch. KIND is a description of the type of entity + * that was being matched. VALUE is the invalid value that was given. PROBLEM + * is the return value from argmatch. + */ void -invalid_arg (kind, value, problem) - char *kind; - char *value; - int problem; +invalid_arg(char *kind, char *value, int problem) { - fprintf (stderr, "patch: "); - if (problem == -1) - fprintf (stderr, "invalid"); - else /* Assume -2. */ - fprintf (stderr, "ambiguous"); - fprintf (stderr, " %s `%s'\n", kind, value); + fprintf(stderr, "patch: "); + if (problem == -1) + fprintf(stderr, "invalid"); + else /* Assume -2. */ + fprintf(stderr, "ambiguous"); + fprintf(stderr, " %s `%s'\n", kind, value); } -static char *backup_args[] = -{ - "never", "simple", "nil", "existing", "t", "numbered", 0 +static char *backup_args[] = { + "never", "simple", "nil", "existing", "t", "numbered", 0 }; -static enum backup_type backup_types[] = -{ - simple, simple, numbered_existing, numbered_existing, numbered, numbered +static enum backup_type backup_types[] = { + simple, simple, numbered_existing, + numbered_existing, numbered, numbered }; -/* Return the type of backup indicated by VERSION. - Unique abbreviations are accepted. */ - +/* + * Return the type of backup indicated by VERSION. Unique abbreviations are + * accepted. + */ enum backup_type -get_version (version) - char *version; +get_version(char *version) { - int i; - - if (version == 0 || *version == 0) - return numbered_existing; - i = argmatch (version, backup_args); - if (i >= 0) - return backup_types[i]; - invalid_arg ("version control type", version, i); - exit (1); + int i; + + if (version == 0 || *version == 0) + return numbered_existing; + i = argmatch(version, backup_args); + if (i >= 0) + return backup_types[i]; + invalid_arg("version control type", version, i); + exit(1); } -#endif /* NODIR */ diff --git a/usr.bin/patch/backupfile.h b/usr.bin/patch/backupfile.h index 3773aa12b28..43a27a8bc1b 100644 --- a/usr.bin/patch/backupfile.h +++ b/usr.bin/patch/backupfile.h @@ -1,35 +1,37 @@ -/* $OpenBSD: backupfile.h,v 1.3 2002/02/19 19:39:39 millert Exp $*/ -/* backupfile.h -- declarations for making Emacs style backup file names - Copyright (C) 1990 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it without restriction. - - 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. - -*/ +/* $OpenBSD: backupfile.h,v 1.4 2003/07/21 14:00:41 deraadt Exp $ */ +/* + * backupfile.h -- declarations for making Emacs style backup file names + * Copyright (C) 1990 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * without restriction. + * + * 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. + * + */ /* When to make backup files. */ -enum backup_type -{ - /* Never make backups. */ - none, +enum backup_type { + /* Never make backups. */ + none, - /* Make simple backups of every file. */ - simple, + /* Make simple backups of every file. */ + simple, - /* Make numbered backups of files that already have numbered backups, - and simple backups of the others. */ - numbered_existing, + /* + * Make numbered backups of files that already have numbered backups, + * and simple backups of the others. + */ + numbered_existing, - /* Make numbered backups of every file. */ - numbered + /* Make numbered backups of every file. */ + numbered }; extern enum backup_type backup_type; -extern char *simple_backup_suffix; +extern char *simple_backup_suffix; -char *find_backup_file_name (char *file); -enum backup_type get_version (char *version); +char *find_backup_file_name(char *file); +enum backup_type get_version(char *version); diff --git a/usr.bin/patch/common.h b/usr.bin/patch/common.h index 7da6a168f2f..22512185130 100644 --- a/usr.bin/patch/common.h +++ b/usr.bin/patch/common.h @@ -1,4 +1,4 @@ -/* $OpenBSD: common.h,v 1.13 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: common.h,v 1.14 2003/07/21 14:00:41 deraadt Exp $ */ #define DEBUGGING @@ -34,8 +34,8 @@ #define TRUE (1) #define FALSE (0) -#define MAXHUNKSIZE 100000 /* is this enough lines? */ -#define INITHUNKMAX 125 /* initial dynamic allocation size */ +#define MAXHUNKSIZE 100000 /* is this enough lines? */ +#define INITHUNKMAX 125 /* initial dynamic allocation size */ #define MAXLINELEN 8192 #define BUFFERSIZE 1024 @@ -66,54 +66,54 @@ /* typedefs */ -typedef char bool; -typedef long LINENUM; /* must be signed */ -typedef unsigned MEM; /* what to feed malloc */ +typedef char bool; +typedef long LINENUM; /* must be signed */ +typedef unsigned MEM; /* what to feed malloc */ /* globals */ -EXT int Argc; /* guess */ -EXT char **Argv; -EXT int Argc_last; /* for restarting plan_b */ -EXT char **Argv_last; +EXT int Argc; /* guess */ +EXT char **Argv; +EXT int Argc_last; /* for restarting plan_b */ +EXT char **Argv_last; -EXT struct stat filestat; /* file statistics area */ +EXT struct stat filestat; /* file statistics area */ EXT int filemode INIT(0644); -EXT char buf[MAXLINELEN]; /* general purpose buffer */ -EXT FILE *ofp INIT(Nullfp); /* output file pointer */ -EXT FILE *rejfp INIT(Nullfp); /* reject file pointer */ +EXT char buf[MAXLINELEN];/* general purpose buffer */ +EXT FILE *ofp INIT(Nullfp); /* output file pointer */ +EXT FILE *rejfp INIT(Nullfp); /* reject file pointer */ -EXT int myuid; /* cache getuid return value */ +EXT int myuid; /* cache getuid return value */ EXT bool using_plan_a INIT(TRUE); /* try to keep everything in memory */ -EXT bool out_of_mem INIT(FALSE); /* ran out of memory in plan a */ +EXT bool out_of_mem INIT(FALSE);/* ran out of memory in plan a */ #define MAXFILEC 2 -EXT int filec INIT(0); /* how many file arguments? */ -EXT char *filearg[MAXFILEC]; +EXT int filec INIT(0); /* how many file arguments? */ +EXT char *filearg[MAXFILEC]; EXT bool ok_to_create_file INIT(FALSE); -EXT char *bestguess INIT(Nullch); /* guess at correct filename */ +EXT char *bestguess INIT(Nullch); /* guess at correct filename */ -EXT char *outname INIT(Nullch); -EXT char rejname[128]; +EXT char *outname INIT(Nullch); +EXT char rejname[128]; -EXT char *origprae INIT(Nullch); +EXT char *origprae INIT(Nullch); -EXT char *TMPOUTNAME; -EXT char *TMPINNAME; -EXT char *TMPREJNAME; -EXT char *TMPPATNAME; +EXT char *TMPOUTNAME; +EXT char *TMPINNAME; +EXT char *TMPREJNAME; +EXT char *TMPPATNAME; EXT bool toutkeep INIT(FALSE); EXT bool trejkeep INIT(FALSE); EXT LINENUM last_offset INIT(0); #ifdef DEBUGGING -EXT int debug INIT(0); +EXT int debug INIT(0); #endif EXT LINENUM maxfuzz INIT(2); -EXT bool force INIT(FALSE); -EXT bool batch INIT(FALSE); +EXT bool force INIT(FALSE); +EXT bool batch INIT(FALSE); EXT bool verbose INIT(TRUE); EXT bool reverse INIT(FALSE); EXT bool noreverse INIT(FALSE); @@ -128,13 +128,13 @@ EXT bool canonicalize INIT(FALSE); #define UNI_DIFF 5 EXT int diff_type INIT(0); -EXT bool do_defines INIT(FALSE); /* patch using ifdef, ifndef, etc. */ -EXT char if_defined[128]; /* #ifdef xyzzy */ -EXT char not_defined[128]; /* #ifndef xyzzy */ -EXT char else_defined[] INIT("#else\n");/* #else */ -EXT char end_defined[128]; /* #endif xyzzy */ +EXT bool do_defines INIT(FALSE);/* patch using ifdef, ifndef, etc. */ +EXT char if_defined[128];/* #ifdef xyzzy */ +EXT char not_defined[128]; /* #ifndef xyzzy */ +EXT char else_defined[] INIT("#else\n"); /* #else */ +EXT char end_defined[128]; /* #endif xyzzy */ -EXT char *revision INIT(Nullch); /* prerequisite revision, if any */ +EXT char *revision INIT(Nullch); /* prerequisite revision, if any */ #if !defined(S_ISDIR) && defined(S_IFDIR) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) diff --git a/usr.bin/patch/config.h b/usr.bin/patch/config.h index 764d7e04070..efaee2c2a86 100644 --- a/usr.bin/patch/config.h +++ b/usr.bin/patch/config.h @@ -1,33 +1,33 @@ -/* $OpenBSD: config.h,v 1.4 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: config.h,v 1.5 2003/07/21 14:00:41 deraadt Exp $ */ -/* config.h - * This file was produced by running the config.h.SH script, which - * gets its values from config.sh, which is generally produced by - * running Configure. - * - * Feel free to modify any of this as the need arises. Note, however, - * that running config.h.SH again will wipe out any changes you've made. - * For a more permanent change edit config.sh and rerun config.h.SH. - * +/* + * config.h This file was produced by running the config.h.SH script, which + * gets its values from config.sh, which is generally produced by running + * Configure. + * + * Feel free to modify any of this as the need arises. Note, however, that + * running config.h.SH again will wipe out any changes you've made. For a + * more permanent change edit config.sh and rerun config.h.SH. + * */ -/* CPPSTDIN: - * This symbol contains the first part of the string which will invoke - * the C preprocessor on the standard input and produce to standard - * output. Typical value of "cc -E" or "/lib/cpp". +/* + * CPPSTDIN: This symbol contains the first part of the string which will + * invoke the C preprocessor on the standard input and produce to standard + * output. Typical value of "cc -E" or "/lib/cpp". */ -/* CPPMINUS: - * This symbol contains the second part of the string which will invoke - * the C preprocessor on the standard input and produce to standard - * output. This symbol will have the value "-" if CPPSTDIN needs a minus - * to specify standard input, otherwise the value is "". +/* + * CPPMINUS: This symbol contains the second part of the string which will + * invoke the C preprocessor on the standard input and produce to standard + * output. This symbol will have the value "-" if CPPSTDIN needs a minus to + * specify standard input, otherwise the value is "". */ #define CPPSTDIN "/usr/bin/cpp" #define CPPMINUS "" -/* DIRHEADER: - * This definition indicates which directory library header to use. +/* + * DIRHEADER: This definition indicates which directory library header to + * use. */ #define DIRENT - diff --git a/usr.bin/patch/inp.c b/usr.bin/patch/inp.c index a4cd46bc28b..ecea07e9c7b 100644 --- a/usr.bin/patch/inp.c +++ b/usr.bin/patch/inp.c @@ -1,8 +1,8 @@ -/* $OpenBSD: inp.c,v 1.11 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: inp.c,v 1.12 2003/07/21 14:00:41 deraadt Exp $ */ #ifndef lint -static char rcsid[] = "$OpenBSD: inp.c,v 1.11 2003/07/18 02:00:09 deraadt Exp $"; -#endif /* not lint */ +static char rcsid[] = "$OpenBSD: inp.c,v 1.12 2003/07/21 14:00:41 deraadt Exp $"; +#endif /* not lint */ #include "EXTERN.h" #include "common.h" @@ -11,362 +11,365 @@ static char rcsid[] = "$OpenBSD: inp.c,v 1.11 2003/07/18 02:00:09 deraadt Exp $" #include "INTERN.h" #include "inp.h" -extern bool check_only; +extern bool check_only; /* Input-file-with-indexable-lines abstract type */ -static off_t 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 off_t 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 */ +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 */ -void re_input(void); +void re_input(void); /* New patch--prepare to edit another file. */ void re_input(void) { - if (using_plan_a) { - i_size = 0; + if (using_plan_a) { + i_size = 0; #ifndef lint - if (i_ptr != Null(char**)) - free((char *)i_ptr); + if (i_ptr != Null(char **)) + free((char *) i_ptr); #endif - 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; - } + 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; + } } /* Constuct the line index, somehow or other. */ void -scan_input(filename) -char *filename; +scan_input(char *filename) { - if (!plan_a(filename)) - plan_b(filename); - if (verbose) { - say("Patching file %s using Plan %s...\n", filename, - (using_plan_a ? "A" : "B") ); - } + if (!plan_a(filename)) + plan_b(filename); + if (verbose) { + say("Patching file %s using Plan %s...\n", filename, + (using_plan_a ? "A" : "B")); + } } /* Try keeping everything in memory. */ bool -plan_a(filename) -char *filename; +plan_a(char *filename) { - int ifd, statfailed; - char *s; - LINENUM iline; - char lbuf[MAXLINELEN]; + int ifd, statfailed; + char *s, lbuf[MAXLINELEN]; + LINENUM iline; - if (!filename || *filename == '\0') - return FALSE; + if (!filename || *filename == '\0') + return FALSE; - statfailed = stat(filename, &filestat); - if (statfailed && ok_to_create_file) { - if (verbose) - say("(Creating file %s...)\n",filename); - /* in check_patch case, we still display `Creating file' even - though we're not. The rule is that -C should be as similar - to normal patch behavior as possible - */ - if (check_only) - return TRUE; - makedirs(filename, TRUE); - close(creat(filename, 0666)); statfailed = stat(filename, &filestat); - } - if (statfailed && check_only) - fatal("%s not found, -C mode, can't probe further\n", filename); - /* For nonexistent or read-only files, look for RCS or SCCS versions. */ - if (statfailed - /* No one can write to it. */ - || (filestat.st_mode & 0222) == 0 - /* I can't write to it. */ - || ((filestat.st_mode & 0022) == 0 && filestat.st_uid != myuid)) { - struct stat cstat; - char *cs = Nullch; - char *filebase, *filedir; - - filebase = basename(filename); - filedir = dirname(filename); - - /* Leave room in lbuf for the diff command. */ - s = lbuf + 20; - -#define try(f, a1, a2, a3) (snprintf(s, sizeof lbuf - 20, f, a1, a2, a3), stat(s, &cstat) == 0) - if ( try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) - || try("%s/RCS/%s%s", filedir, filebase, "") - || try( "%s/%s%s", filedir, filebase, RCSSUFFIX)) { - snprintf(buf, sizeof buf, CHECKOUT, filename); - snprintf(lbuf, sizeof lbuf, RCSDIFF, filename); - cs = "RCS"; - } else if ( try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) - || try( "%s/%s%s", filedir, SCCSPREFIX, filebase)) { - snprintf(buf, sizeof buf, GET, s); - snprintf(lbuf, sizeof lbuf, SCCSDIFF, s, filename); - cs = "SCCS"; - } else if (statfailed) - fatal("can't find %s\n", filename); - /* else we can't write to it but it's not under a version - control system, so just proceed. */ - if (cs) { - if (!statfailed) { - if ((filestat.st_mode & 0222) != 0) - /* The owner can write to it. */ - fatal("file %s seems to be locked by somebody else under %s\n", - filename, cs); - /* It might be checked out unlocked. See if it's safe to - check out the default version locked. */ + if (statfailed && ok_to_create_file) { if (verbose) - say("Comparing file %s to default %s version...\n", - filename, cs); - if (system(lbuf)) - fatal("can't check out file %s: differs from default %s version\n", - filename, cs); - } - if (verbose) - say("Checking out file %s from %s...\n", filename, cs); - if (system(buf) || stat(filename, &filestat)) - fatal("can't check out file %s from %s\n", filename, cs); + say("(Creating file %s...)\n", filename); + + /* + * in check_patch case, we still display `Creating file' even + * though we're not. The rule is that -C should be as similar + * to normal patch behavior as possible + */ + if (check_only) + return TRUE; + makedirs(filename, TRUE); + close(creat(filename, 0666)); + statfailed = stat(filename, &filestat); + } + if (statfailed && check_only) + fatal("%s not found, -C mode, can't probe further\n", filename); + /* For nonexistent or read-only files, look for RCS or SCCS versions. */ + if (statfailed || + /* No one can write to it. */ + (filestat.st_mode & 0222) == 0 || + /* I can't write to it. */ + ((filestat.st_mode & 0022) == 0 && filestat.st_uid != myuid)) { + char *cs = Nullch, *filebase, *filedir; + struct stat cstat; + + filebase = basename(filename); + filedir = dirname(filename); + + /* Leave room in lbuf for the diff command. */ + s = lbuf + 20; + +#define try(f, a1, a2, a3) \ + (snprintf(s, sizeof lbuf - 20, f, a1, a2, a3), stat(s, &cstat) == 0) + + if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) || + try("%s/RCS/%s%s", filedir, filebase, "") || + try("%s/%s%s", filedir, filebase, RCSSUFFIX)) { + snprintf(buf, sizeof buf, CHECKOUT, filename); + snprintf(lbuf, sizeof lbuf, RCSDIFF, filename); + cs = "RCS"; + } else if (try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) || + try("%s/%s%s", filedir, SCCSPREFIX, filebase)) { + snprintf(buf, sizeof buf, GET, s); + snprintf(lbuf, sizeof lbuf, SCCSDIFF, s, filename); + cs = "SCCS"; + } else if (statfailed) + fatal("can't find %s\n", filename); + /* + * else we can't write to it but it's not under a version + * control system, so just proceed. + */ + if (cs) { + if (!statfailed) { + if ((filestat.st_mode & 0222) != 0) + /* The owner can write to it. */ + fatal("file %s seems to be locked " + "by somebody else under %s\n", + filename, cs); + /* + * It might be checked out unlocked. See if + * it's safe to check out the default version + * locked. + */ + if (verbose) + say("Comparing file %s to default " + "%s version...\n", + filename, cs); + if (system(lbuf)) + fatal("can't check out file %s: " + "differs from default %s version\n", + filename, cs); + } + if (verbose) + say("Checking out file %s from %s...\n", + filename, cs); + if (system(buf) || stat(filename, &filestat)) + fatal("can't check out file %s from %s\n", + filename, cs); + } + } + filemode = filestat.st_mode; + if (!S_ISREG(filemode)) + fatal("%s is not a normal file--can't patch\n", filename); + i_size = filestat.st_size; + if (out_of_mem) { + set_hunkmax(); /* make sure dynamic arrays are allocated */ + out_of_mem = FALSE; + return FALSE; /* force plan b because plan a bombed */ } - } - filemode = filestat.st_mode; - if (!S_ISREG(filemode)) - fatal("%s is not a normal file--can't patch\n", filename); - i_size = filestat.st_size; - if (out_of_mem) { - set_hunkmax(); /* make sure dynamic arrays are allocated */ - out_of_mem = FALSE; - return FALSE; /* force plan b because plan a bombed */ - } #ifdef lint - i_womp = Nullch; + i_womp = Nullch; #else - i_womp = malloc((MEM)(i_size+2)); /* lint says this may alloc less than */ - /* i_size, but that's okay, I think. */ + i_womp = malloc((MEM) (i_size + 2)); /* lint says this may alloc + * less than */ + /* i_size, but that's okay, I think. */ #endif - if (i_womp == Nullch) - return FALSE; - if ((ifd = open(filename, O_RDONLY)) < 0) - pfatal("can't open file %s", filename); + if (i_womp == Nullch) + return FALSE; + if ((ifd = open(filename, O_RDONLY)) < 0) + pfatal("can't open file %s", filename); #ifndef lint - if (read(ifd, i_womp, (size_t)i_size) != i_size) { - close(ifd); /* probably means i_size > 15 or 16 bits worth */ - free(i_womp); /* at this point it doesn't matter if i_womp was */ - return FALSE; /* undersized. */ - } + if (read(ifd, i_womp, (size_t) i_size) != i_size) { + close(ifd); /* probably means i_size > 15 or 16 bits worth */ + free(i_womp); /* at this point it doesn't matter if i_womp was */ + return FALSE; /* undersized. */ + } #endif - close(ifd); - if (i_size && 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++; - } + close(ifd); + if (i_size && 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++; + } #ifdef lint - i_ptr = Null(char**); + i_ptr = Null(char **); #else - i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *))); + i_ptr = (char **) malloc((MEM) ((iline + 2) * sizeof(char *))); #endif - 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)) { - if (force) { - if (verbose) - 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.\n", revision); - } - else { - ask( -"This file doesn't appear to be the %s version--patch anyway? [n] ", - revision); - if (*buf != 'y') - fatal("aborted\n"); - } + 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)) { + if (force) { + if (verbose) + 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.\n", + revision); + } else { + 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); } - else if (verbose) - say("Good. This file appears to be the %s version.\n", - revision); - } - return TRUE; /* plan a will work */ + return TRUE; /* plan a will work */ } /* Keep (virtually) nothing in memory. */ void -plan_b(filename) -char *filename; +plan_b(char *filename) { - FILE *ifp; - int i = 0; - int maxlen = 1; - bool found_revision = (revision == Nullch); - - using_plan_a = FALSE; - if ((ifp = fopen(filename, "r")) == Nullfp) - pfatal("can't open file %s", filename); - (void) unlink(TMPINNAME); - if ((tifd = open(TMPINNAME, O_EXCL|O_CREAT|O_WRONLY, 0666)) < 0) - pfatal("can't open file %s", 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) { - if (force) { - if (verbose) - 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.\n", revision); - } - else { - ask( -"This file doesn't appear to be the %s version--patch anyway? [n] ", - revision); - if (*buf != 'y') - fatal("aborted\n"); - } + FILE *ifp; + int i = 0, maxlen = 1; + bool found_revision = (revision == Nullch); + + using_plan_a = FALSE; + if ((ifp = fopen(filename, "r")) == Nullfp) + pfatal("can't open file %s", filename); + (void) unlink(TMPINNAME); + if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0) + pfatal("can't open file %s", 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) { + if (force) { + if (verbose) + 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.\n", + revision); + } else { + 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); } - 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)); - if (tibuf[0] == Nullch) - fatal("out of memory\n"); - tibuf[1] = malloc((MEM)(BUFFERSIZE + 1)); - if (tibuf[1] == Nullch) - fatal("out of memory\n"); - for (i=1; ; i++) { - if (! (i % lines_per_buf)) /* new block */ - if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE) - pfatal("can't write temp file"); - 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) - pfatal("can't write temp file"); - break; + fseek(ifp, 0L, 0); /* rewind file */ + lines_per_buf = BUFFERSIZE / maxlen; + tireclen = maxlen; + tibuf[0] = malloc((MEM) (BUFFERSIZE + 1)); + if (tibuf[0] == Nullch) + fatal("out of memory\n"); + tibuf[1] = malloc((MEM) (BUFFERSIZE + 1)); + if (tibuf[1] == Nullch) + fatal("out of memory\n"); + for (i = 1;; i++) { + if (!(i % lines_per_buf)) /* new block */ + if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE) + pfatal("can't write temp file"); + 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) + pfatal("can't write temp file"); + break; + } } - } - fclose(ifp); - close(tifd); - if ((tifd = open(TMPINNAME, O_RDONLY)) < 0) { - pfatal("can't reopen file %s", TMPINNAME); - } + fclose(ifp); + close(tifd); + if ((tifd = open(TMPINNAME, O_RDONLY)) < 0) + pfatal("can't reopen file %s", TMPINNAME); } -/* Fetch a line from the input file, \n terminated, not necessarily \0. */ - +/* + * Fetch a line from the input file, \n terminated, not necessarily \0. + */ char * -ifetch(line,whichbuf) -LINENUM line; -int whichbuf; /* ignored when file in memory */ +ifetch(LINENUM line, int whichbuf) { - if (line < 1 || line > input_lines) { - say("No such line %ld in input file, ignoring\n", line); - return NULL; - } - 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; + if (line < 1 || line > input_lines) { + say("No such line %ld in input file, ignoring\n", line); + return NULL; + } + if (using_plan_a) + return i_ptr[line]; else { - tiline[whichbuf] = baseline; -#ifndef lint /* complains of long accuracy */ - lseek(tifd, (off_t)(baseline / lines_per_buf * BUFFERSIZE), 0); + 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; +#ifndef lint /* complains of long accuracy */ + lseek(tifd, (off_t) (baseline / lines_per_buf * + BUFFERSIZE), 0); #endif - if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0) - pfatal("error reading tmp file %s", TMPINNAME); + if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0) + pfatal("error reading tmp file %s", TMPINNAME); + } + return tibuf[whichbuf] + (tireclen * offline); } - return tibuf[whichbuf] + (tireclen*offline); - } } -/* True if the string argument contains the revision number we want. */ - +/* + * True if the string argument contains the revision number we want. + */ bool -rev_in_string(string) -char *string; +rev_in_string(char *string) { - char *s; - int patlen; - - if (revision == Nullch) - return TRUE; - patlen = strlen(revision); - if (strnEQ(string,revision,patlen) && isspace(string[patlen])) - return TRUE; - for (s = string; *s; s++) { - if (isspace(*s) && strnEQ(s+1, revision, patlen) && - isspace(s[patlen+1] )) { - return TRUE; + char *s; + int patlen; + + if (revision == Nullch) + return TRUE; + patlen = strlen(revision); + if (strnEQ(string, revision, patlen) && isspace(string[patlen])) + return TRUE; + for (s = string; *s; s++) { + if (isspace(*s) && strnEQ(s + 1, revision, patlen) && + isspace(s[patlen + 1])) { + return TRUE; + } } - } - return FALSE; + return FALSE; } diff --git a/usr.bin/patch/inp.h b/usr.bin/patch/inp.h index 0b4e09d3647..5ebe3ae1f13 100644 --- a/usr.bin/patch/inp.h +++ b/usr.bin/patch/inp.h @@ -1,12 +1,11 @@ -/* $OpenBSD: inp.h,v 1.3 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: inp.h,v 1.4 2003/07/21 14:00:41 deraadt Exp $ */ -EXT LINENUM input_lines INIT(0); /* how long is input file in lines */ -EXT LINENUM last_frozen_line INIT(0); /* how many input lines have been */ - /* irretractibly output */ - -bool rev_in_string(char *); -void scan_input(char *); -bool plan_a(char *); /* returns false if insufficient memory */ -void plan_b(char *); -char *ifetch(LINENUM, int); +EXT LINENUM input_lines INIT(0); /* how long is input file in lines */ +EXT LINENUM last_frozen_line INIT(0); /* how many input lines have been */ +/* irretractibly output */ +bool rev_in_string(char *); +void scan_input(char *); +bool plan_a(char *); /* returns false if insufficient memory */ +void plan_b(char *); +char *ifetch(LINENUM, int); diff --git a/usr.bin/patch/patch.c b/usr.bin/patch/patch.c index a840825ebc1..dd23e02e935 100644 --- a/usr.bin/patch/patch.c +++ b/usr.bin/patch/patch.c @@ -1,33 +1,33 @@ -/* $OpenBSD: patch.c,v 1.19 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: patch.c,v 1.20 2003/07/21 14:00:41 deraadt Exp $ */ -/* patch - a program to apply diffs to original files - * +/* + * patch - a program to apply diffs to original files + * * Copyright 1986, Larry Wall - * + * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following condition - * is met: - * 1. Redistributions of source code must retain the above copyright - * notice, this condition and the following disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * modification, are permitted provided that the following condition is met: + * 1. Redistributions of source code must retain the above copyright notice, + * this condition and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * -C option added in 1998, original code by Marc Espie, - * based on FreeBSD behaviour + * + * -C option added in 1998, original code by Marc Espie, based on FreeBSD + * behaviour */ #ifndef lint -static char rcsid[] = "$OpenBSD: patch.c,v 1.19 2003/07/18 02:00:09 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: patch.c,v 1.20 2003/07/21 14:00:41 deraadt Exp $"; #endif /* not lint */ #include "INTERN.h" @@ -38,369 +38,345 @@ static char rcsid[] = "$OpenBSD: patch.c,v 1.19 2003/07/18 02:00:09 deraadt Exp #include "inp.h" #include "backupfile.h" -/* procedures */ - -void reinitialize_almost_everything(void); -void get_some_switches(void); -LINENUM locate_hunk(LINENUM); -void abort_hunk(void); -void apply_hunk(LINENUM); -void init_output(char *); -void init_reject(char *); -void copy_till(LINENUM); -void spew_output(void); -void dump_line(LINENUM); -bool patch_match(LINENUM, LINENUM, LINENUM); -bool similar(char *, char *, int); -void re_input(void); -void my_exit(int) __attribute__((noreturn)); -int optcmp(const void *, const void *); -char decode_long_option(char *); +void reinitialize_almost_everything(void); +void get_some_switches(void); +LINENUM locate_hunk(LINENUM); +void abort_hunk(void); +void apply_hunk(LINENUM); +void init_output(char *); +void init_reject(char *); +void copy_till(LINENUM); +void spew_output(void); +void dump_line(LINENUM); +bool patch_match(LINENUM, LINENUM, LINENUM); +bool similar(char *, char *, int); +void re_input(void); +void my_exit(int) __attribute__((noreturn)); +int optcmp(const void *, const void *); +char decode_long_option(char *); /* TRUE if -E was specified on command line. */ -static int remove_empty_files = FALSE; +static int remove_empty_files = FALSE; /* TRUE if -R was specified on command line. */ -static int reverse_flag_specified = FALSE; +static int reverse_flag_specified = FALSE; /* TRUE if -C was specified on command line. */ -bool check_only = FALSE; +bool check_only = FALSE; /* Apply a set of diffs as appropriate. */ int main(int argc, char *argv[]) { - LINENUM where; - LINENUM newwhere; - LINENUM fuzz; - LINENUM mymaxfuzz; - int hunk = 0; - int failed = 0; - int failtotal = 0; - int patch_seen = 0; - int i; - - setbuf(stderr, serrbuf); - for (i = 0; i<MAXFILEC; i++) - filearg[i] = Nullch; - - myuid = getuid(); - - /* Cons up the names of the temporary files. */ - { - /* Directory for temporary files. */ - char *tmpdir; - - tmpdir = getenv ("TMPDIR"); - if (tmpdir == NULL) { - tmpdir = "/tmp"; - } - - if (asprintf(&TMPOUTNAME, "%s/patchoXXXXXXXXXX", tmpdir) == -1) - fatal("cannot allocate memory"); - if ((i = mkstemp(TMPOUTNAME)) < 0) - pfatal("can't create %s", TMPOUTNAME); - close(i); - - if (asprintf(&TMPINNAME, "%s/patchiXXXXXXXXXX", tmpdir) == -1) - fatal("cannot allocate memory"); - if ((i = mkstemp(TMPINNAME)) < 0) - pfatal("can't create %s", TMPINNAME); - close(i); - - if (asprintf(&TMPREJNAME, "%s/patchrXXXXXXXXXX", tmpdir) == -1) - fatal("cannot allocate memory"); - if ((i = mkstemp(TMPREJNAME)) < 0) - pfatal("can't create %s", TMPREJNAME); - close(i); - - if (asprintf(&TMPPATNAME, "%s/patchpXXXXXXXXXX", tmpdir) == -1) - fatal("cannot allocate memory"); - if ((i = mkstemp(TMPPATNAME)) < 0) - pfatal("can't create %s", TMPPATNAME); - close(i); - } - - { - char *v; - - v = getenv ("SIMPLE_BACKUP_SUFFIX"); - if (v) - simple_backup_suffix = v; - else - simple_backup_suffix = ORIGEXT; -#ifndef NODIR - v = getenv ("VERSION_CONTROL"); - backup_type = get_version (v); /* OK to pass NULL. */ -#endif - } - - /* parse switches */ - Argc = argc; - Argv = argv; - get_some_switches(); - - /* make sure we clean up /tmp in case of disaster */ - set_signals(0); - - for ( - open_patch_file(filearg[1]); - there_is_another_patch(); - reinitialize_almost_everything() - ) { /* for each patch in patch file */ - patch_seen = TRUE; - - if (outname == Nullch) - outname = savestr(filearg[0]); - - /* for ed script just up and do it and exit */ - if (diff_type == ED_DIFF) { - do_ed_script(); - continue; - } + int hunk = 0, failed = 0, failtotal = 0, patch_seen = 0, i; + LINENUM where, newwhere, fuzz, mymaxfuzz; + char *tmpdir, *v; - /* initialize the patched file */ - if (!skip_rest_of_patch) - init_output(TMPOUTNAME); - - /* initialize reject file */ - init_reject(TMPREJNAME); - - /* find out where all the lines are */ - if (!skip_rest_of_patch) - scan_input(filearg[0]); - - /* from here on, open no standard i/o files, because malloc */ - /* might misfire and we can't catch it easily */ - - /* apply each hunk of patch */ - hunk = 0; - failed = 0; - out_of_mem = FALSE; - while (another_hunk()) { - hunk++; - fuzz = Nulline; - mymaxfuzz = pch_context(); - if (maxfuzz < mymaxfuzz) - mymaxfuzz = maxfuzz; - if (!skip_rest_of_patch) { - do { - where = locate_hunk(fuzz); - if (hunk == 1 && where == Nulline && !force) { - /* dwim for reversed patch? */ - if (!pch_swap()) { - if (fuzz == Nulline) - say( -"Not enough memory to try swapped hunk! Assuming unswapped.\n"); - continue; - } - reverse = !reverse; - where = locate_hunk(fuzz); /* try again */ - if (where == Nulline) { /* didn't find it swapped */ - if (!pch_swap()) /* put it back to normal */ - fatal("lost hunk on alloc error!\n"); - reverse = !reverse; - } - else if (noreverse) { - if (!pch_swap()) /* put it back to normal */ - fatal("lost hunk on alloc error!\n"); - reverse = !reverse; - say( -"Ignoring previously applied (or reversed) patch.\n"); - skip_rest_of_patch = TRUE; - } - else if (batch) { - if (verbose) - say( -"%seversed (or previously applied) patch detected! %s -R.", - reverse ? "R" : "Unr", - reverse ? "Assuming" : "Ignoring"); - } - else { - ask( -"%seversed (or previously applied) patch detected! %s -R? [y] ", - reverse ? "R" : "Unr", - reverse ? "Assume" : "Ignore"); - if (*buf == 'n') { - ask("Apply anyway? [n] "); - if (*buf != 'y') - skip_rest_of_patch = TRUE; - where = Nulline; - reverse = !reverse; - if (!pch_swap()) /* put it back to normal */ - fatal("lost hunk on alloc error!\n"); - } - } - } - } while (!skip_rest_of_patch && where == Nulline && - ++fuzz <= mymaxfuzz); + setbuf(stderr, serrbuf); + for (i = 0; i < MAXFILEC; i++) + filearg[i] = Nullch; - if (skip_rest_of_patch) { /* just got decided */ - fclose(ofp); - ofp = Nullfp; - } - } - - newwhere = pch_newfirst() + last_offset; - if (skip_rest_of_patch) { - abort_hunk(); - failed++; - if (verbose) - say("Hunk #%d ignored at %ld.\n", hunk, newwhere); - } - else if (where == Nulline) { - abort_hunk(); - failed++; - if (verbose) - say("Hunk #%d failed at %ld.\n", hunk, newwhere); - } - else { - apply_hunk(where); - if (verbose) { - say("Hunk #%d succeeded at %ld", hunk, newwhere); - if (fuzz) - say(" with fuzz %ld", fuzz); - if (last_offset) - say(" (offset %ld line%s)", - last_offset, last_offset==1L?"":"s"); - say(".\n"); - } - } - } + myuid = getuid(); - if (out_of_mem && using_plan_a) { - Argc = Argc_last; - Argv = Argv_last; - say("\n\nRan out of memory using Plan A--trying again...\n\n"); - if (ofp) - fclose(ofp); - ofp = Nullfp; - if (rejfp) - fclose(rejfp); - rejfp = Nullfp; - continue; + /* Cons up the names of the temporary files. */ + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) { + tmpdir = "/tmp"; } + if (asprintf(&TMPOUTNAME, "%s/patchoXXXXXXXXXX", tmpdir) == -1) + fatal("cannot allocate memory"); + if ((i = mkstemp(TMPOUTNAME)) < 0) + pfatal("can't create %s", TMPOUTNAME); + close(i); + + if (asprintf(&TMPINNAME, "%s/patchiXXXXXXXXXX", tmpdir) == -1) + fatal("cannot allocate memory"); + if ((i = mkstemp(TMPINNAME)) < 0) + pfatal("can't create %s", TMPINNAME); + close(i); + + if (asprintf(&TMPREJNAME, "%s/patchrXXXXXXXXXX", tmpdir) == -1) + fatal("cannot allocate memory"); + if ((i = mkstemp(TMPREJNAME)) < 0) + pfatal("can't create %s", TMPREJNAME); + close(i); + + if (asprintf(&TMPPATNAME, "%s/patchpXXXXXXXXXX", tmpdir) == -1) + fatal("cannot allocate memory"); + if ((i = mkstemp(TMPPATNAME)) < 0) + pfatal("can't create %s", TMPPATNAME); + close(i); + + v = getenv("SIMPLE_BACKUP_SUFFIX"); + if (v) + simple_backup_suffix = v; + else + simple_backup_suffix = ORIGEXT; + + v = getenv("VERSION_CONTROL"); + backup_type = get_version(v); /* OK to pass NULL. */ + + /* parse switches */ + Argc = argc; + Argv = argv; + get_some_switches(); - assert(hunk); + /* make sure we clean up /tmp in case of disaster */ + set_signals(0); - /* finish spewing out the new file */ - if (!skip_rest_of_patch) - spew_output(); + for (open_patch_file(filearg[1]); there_is_another_patch(); + reinitialize_almost_everything()) { + /* for each patch in patch file */ - /* and put the output where desired */ - ignore_signals(); - if (!skip_rest_of_patch) { - struct stat statbuf; - char *realout = outname; + patch_seen = TRUE; - if (!check_only) { - if (move_file(TMPOUTNAME, outname) < 0) { - toutkeep = TRUE; - realout = TMPOUTNAME; - chmod(TMPOUTNAME, filemode); + if (outname == Nullch) + outname = savestr(filearg[0]); + + /* for ed script just up and do it and exit */ + if (diff_type == ED_DIFF) { + do_ed_script(); + continue; + } + /* initialize the patched file */ + if (!skip_rest_of_patch) + init_output(TMPOUTNAME); + + /* initialize reject file */ + init_reject(TMPREJNAME); + + /* find out where all the lines are */ + if (!skip_rest_of_patch) + scan_input(filearg[0]); + + /* from here on, open no standard i/o files, because malloc */ + /* might misfire and we can't catch it easily */ + + /* apply each hunk of patch */ + hunk = 0; + failed = 0; + out_of_mem = FALSE; + while (another_hunk()) { + hunk++; + fuzz = Nulline; + mymaxfuzz = pch_context(); + if (maxfuzz < mymaxfuzz) + mymaxfuzz = maxfuzz; + if (!skip_rest_of_patch) { + do { + where = locate_hunk(fuzz); + if (hunk == 1 && where == Nulline && !force) { + /* dwim for reversed patch? */ + if (!pch_swap()) { + if (fuzz == Nulline) + say("Not enough memory to try swapped hunk! Assuming unswapped.\n"); + continue; + } + reverse = !reverse; + /* try again */ + where = locate_hunk(fuzz); + if (where == Nulline) { + /* didn't find it swapped */ + if (!pch_swap()) + /* put it back to normal */ + fatal("lost hunk on alloc error!\n"); + reverse = !reverse; + } else if (noreverse) { + if (!pch_swap()) + /* put it back to normal */ + fatal("lost hunk on alloc error!\n"); + reverse = !reverse; + say("Ignoring previously applied (or reversed) patch.\n"); + skip_rest_of_patch = TRUE; + } else if (batch) { + if (verbose) + say("%seversed (or previously applied) patch detected! %s -R.", + reverse ? "R" : "Unr", + reverse ? "Assuming" : "Ignoring"); + } else { + ask("%seversed (or previously applied) patch detected! %s -R? [y] ", + reverse ? "R" : "Unr", + reverse ? "Assume" : "Ignore"); + if (*buf == 'n') { + ask("Apply anyway? [n] "); + if (*buf != 'y') + skip_rest_of_patch = TRUE; + where = Nulline; + reverse = !reverse; + if (!pch_swap()) + /* put it back to normal */ + fatal("lost hunk on alloc error!\n"); + } + } + } + } while (!skip_rest_of_patch && where == Nulline && + ++fuzz <= mymaxfuzz); + + if (skip_rest_of_patch) { /* just got decided */ + fclose(ofp); + ofp = Nullfp; + } + } + newwhere = pch_newfirst() + last_offset; + if (skip_rest_of_patch) { + abort_hunk(); + failed++; + if (verbose) + say("Hunk #%d ignored at %ld.\n", + hunk, newwhere); + } else if (where == Nulline) { + abort_hunk(); + failed++; + if (verbose) + say("Hunk #%d failed at %ld.\n", + hunk, newwhere); + } else { + apply_hunk(where); + if (verbose) { + say("Hunk #%d succeeded at %ld", + hunk, newwhere); + if (fuzz) + say(" with fuzz %ld", fuzz); + if (last_offset) + say(" (offset %ld line%s)", + last_offset, + last_offset == 1L ? "" : "s"); + say(".\n"); + } + } } - else - chmod(outname, filemode); - if (remove_empty_files && stat(realout, &statbuf) == 0 - && statbuf.st_size == 0) { - if (verbose) - say("Removing %s (empty after patching).\n", realout); - while (unlink(realout) >= 0) ; /* while is for Eunice. */ + if (out_of_mem && using_plan_a) { + Argc = Argc_last; + Argv = Argv_last; + say("\n\nRan out of memory using Plan A--trying again...\n\n"); + if (ofp) + fclose(ofp); + ofp = Nullfp; + if (rejfp) + fclose(rejfp); + rejfp = Nullfp; + continue; } - } - } - fclose(rejfp); - rejfp = Nullfp; - if (failed) { - failtotal += failed; - if (!*rejname) { - if (strlcpy(rejname, outname, sizeof(rejname)) >= sizeof(rejname)) - fatal("filename %s is too long\n", outname); - if (strlcat(rejname, REJEXT, sizeof(rejname)) >= sizeof(rejname)) - fatal("filename %s is too long\n", outname); - } - if (skip_rest_of_patch) { - say("%d out of %d hunks ignored--saving rejects to %s\n", - failed, hunk, rejname); - } - else { - say("%d out of %d hunks failed--saving rejects to %s\n", - failed, hunk, rejname); - } - if (!check_only && move_file(TMPREJNAME, rejname) < 0) - trejkeep = TRUE; + assert(hunk); + + /* finish spewing out the new file */ + if (!skip_rest_of_patch) + spew_output(); + + /* and put the output where desired */ + ignore_signals(); + if (!skip_rest_of_patch) { + struct stat statbuf; + char *realout = outname; + + if (!check_only) { + if (move_file(TMPOUTNAME, outname) < 0) { + toutkeep = TRUE; + realout = TMPOUTNAME; + chmod(TMPOUTNAME, filemode); + } else + chmod(outname, filemode); + + if (remove_empty_files && + stat(realout, &statbuf) == 0 && + statbuf.st_size == 0) { + if (verbose) + say("Removing %s (empty after patching).\n", + realout); + unlink(realout); + } + } + } + fclose(rejfp); + rejfp = Nullfp; + if (failed) { + failtotal += failed; + if (!*rejname) { + if (strlcpy(rejname, outname, + sizeof(rejname)) >= sizeof(rejname)) + fatal("filename %s is too long\n", outname); + if (strlcat(rejname, REJEXT, + sizeof(rejname)) >= sizeof(rejname)) + fatal("filename %s is too long\n", outname); + } + if (skip_rest_of_patch) { + say("%d out of %d hunks ignored--saving rejects to %s\n", + failed, hunk, rejname); + } else { + say("%d out of %d hunks failed--saving rejects to %s\n", + failed, hunk, rejname); + } + if (!check_only && move_file(TMPREJNAME, rejname) < 0) + trejkeep = TRUE; + } + set_signals(1); } - set_signals(1); - } - if (!patch_seen) - failtotal++; - my_exit(failtotal); - /* NOTREACHED */ + if (!patch_seen) + failtotal++; + my_exit(failtotal); + /* NOTREACHED */ } /* Prepare to find the next patch to do in the patch file. */ void -reinitialize_almost_everything() +reinitialize_almost_everything(void) { - re_patch(); - re_input(); - - input_lines = 0; - last_frozen_line = 0; - - filec = 0; - if (filearg[0] != Nullch && !out_of_mem) { - free(filearg[0]); - filearg[0] = Nullch; - } + re_patch(); + re_input(); - if (outname != Nullch) { - free(outname); - outname = Nullch; - } + input_lines = 0; + last_frozen_line = 0; - last_offset = 0; - - diff_type = 0; + filec = 0; + if (filearg[0] != Nullch && !out_of_mem) { + free(filearg[0]); + filearg[0] = Nullch; + } + if (outname != Nullch) { + free(outname); + outname = Nullch; + } + last_offset = 0; - if (revision != Nullch) { - free(revision); - revision = Nullch; - } + diff_type = 0; - reverse = reverse_flag_specified; - skip_rest_of_patch = FALSE; + if (revision != Nullch) { + free(revision); + revision = Nullch; + } + reverse = reverse_flag_specified; + skip_rest_of_patch = FALSE; - get_some_switches(); + get_some_switches(); - if (filec >= 2) - fatal("you may not change to a different patch file\n"); + if (filec >= 2) + fatal("you may not change to a different patch file\n"); } static char * nextarg(void) { - if (!--Argc) - fatal("missing argument after `%s'\n", *Argv); - return *++Argv; + if (!--Argc) + fatal("missing argument after `%s'\n", *Argv); + return *++Argv; } /* Module for handling of long options. */ struct option { - char *long_opt; - char short_opt; + char *long_opt; + char short_opt; }; int optcmp(const void *v1, const void *v2) { - const struct option *a = v1, *b = v2; + const struct option *a = v1, *b = v2; - return strcmp (a->long_opt, b->long_opt); + return strcmp(a->long_opt, b->long_opt); } /* Decode Long options beginning with "--" to their short equivalents. */ @@ -408,538 +384,528 @@ optcmp(const void *v1, const void *v2) char decode_long_option(char *opt) { - /* This table must be sorted on the first field. We also decode - unimplemented options as those will be handled later anyway. */ - static struct option options[] = { - { "batch", 't' }, - { "check", 'C' }, - { "context", 'c' }, - { "debug", 'x' }, - { "directory", 'd' }, - { "ed", 'e' }, - { "force", 'f' }, - { "forward", 'N' }, - { "fuzz", 'F' }, - { "ifdef", 'D' }, - { "ignore-whitespace", 'l' }, - { "normal", 'n' }, - { "output", 'o' }, - { "prefix", 'B' }, - { "quiet", 's' }, - { "reject-file", 'r' }, - { "remove-empty-files", 'E' }, - { "reverse", 'R' }, - { "silent", 's' }, - { "skip", 'S' }, - { "strip", 'p' }, - { "suffix", 'b' }, - { "unified", 'u' }, - { "version", 'v' }, - { "version-control", 'V' }, - }; - struct option key, *found; - - key.long_opt = opt; - found = (struct option *)bsearch(&key, options, - sizeof(options) / sizeof(options[0]), - sizeof(options[0]), optcmp); - return found ? found->short_opt : '\0'; + /* + * This table must be sorted on the first field. We also decode + * unimplemented options as those will be handled later anyway. + */ + static struct option options[] = { + {"batch", 't'}, + {"check", 'C'}, + {"context", 'c'}, + {"debug", 'x'}, + {"directory", 'd'}, + {"ed", 'e'}, + {"force", 'f'}, + {"forward", 'N'}, + {"fuzz", 'F'}, + {"ifdef", 'D'}, + {"ignore-whitespace", 'l'}, + {"normal", 'n'}, + {"output", 'o'}, + {"prefix", 'B'}, + {"quiet", 's'}, + {"reject-file", 'r'}, + {"remove-empty-files", 'E'}, + {"reverse", 'R'}, + {"silent", 's'}, + {"skip", 'S'}, + {"strip", 'p'}, + {"suffix", 'b'}, + {"unified", 'u'}, + {"version", 'v'}, + {"version-control", 'V'}, + }; + struct option key, *found; + + key.long_opt = opt; + found = (struct option *) bsearch(&key, options, + sizeof(options) / sizeof(options[0]), + sizeof(options[0]), optcmp); + return found ? found->short_opt : '\0'; } /* Process switches and filenames up to next '+' or end of list. */ void -get_some_switches() +get_some_switches(void) { - char *s; - - rejname[0] = '\0'; - Argc_last = Argc; - Argv_last = Argv; - if (!Argc) - return; - for (Argc--,Argv++; Argc; Argc--,Argv++) { - s = Argv[0]; - if (strEQ(s, "+")) { - return; /* + will be skipped by for loop */ - } - if (*s != '-' || !s[1]) { - if (filec == MAXFILEC) - fatal("too many file arguments\n"); - filearg[filec++] = savestr(s); - } - else { - char opt; - - if (*(s + 1) == '-') { - opt = decode_long_option(s + 2); - s += strlen(s) - 1; - } - else - opt = *++s; - switch (opt) { - case 'b': - simple_backup_suffix = savestr(nextarg()); - break; - case 'B': - origprae = savestr(nextarg()); - break; - case 'c': - diff_type = CONTEXT_DIFF; - break; - case 'C': - check_only = TRUE; - break; - case 'd': - if (!*++s) - s = nextarg(); - if (chdir(s) < 0) - pfatal("can't cd to %s", s); - break; - case 'D': - do_defines = TRUE; - if (!*++s) - s = nextarg(); - if (!isalpha(*s) && '_' != *s) - fatal("argument to -D is not an identifier\n"); - snprintf(if_defined, sizeof if_defined, "#ifdef %s\n", s); - snprintf(not_defined, sizeof not_defined, "#ifndef %s\n", s); - snprintf(end_defined, sizeof end_defined, "#endif /* %s */\n", s); - break; - case 'e': - diff_type = ED_DIFF; - break; - case 'E': - remove_empty_files = TRUE; - break; - case 'f': - force = TRUE; - break; - case 'F': - if (!*++s) - s = nextarg(); - else if (*s == '=') - s++; - maxfuzz = atoi(s); - break; - case 'l': - canonicalize = TRUE; - break; - case 'n': - diff_type = NORMAL_DIFF; - break; - case 'N': - noreverse = TRUE; - break; - case 'o': - outname = savestr(nextarg()); - break; - case 'p': - if (!*++s) - s = nextarg(); - else if (*s == '=') - s++; - strippath = atoi(s); - break; - case 'r': - if (strlcpy(rejname, nextarg(), sizeof(rejname)) >= sizeof(rejname)) - fatal("argument for -r is too long\n"); - break; - case 'R': - reverse = TRUE; - reverse_flag_specified = TRUE; - break; - case 's': - verbose = FALSE; - break; - case 'S': - skip_rest_of_patch = TRUE; - break; - case 't': - batch = TRUE; - break; - case 'u': - diff_type = UNI_DIFF; - break; - case 'v': - version(); - break; - case 'V': -#ifndef NODIR - backup_type = get_version (nextarg ()); -#endif - break; + char *s; + + rejname[0] = '\0'; + Argc_last = Argc; + Argv_last = Argv; + if (!Argc) + return; + for (Argc--, Argv++; Argc; Argc--, Argv++) { + s = Argv[0]; + if (strEQ(s, "+")) { + return; /* + will be skipped by for loop */ + } + if (*s != '-' || !s[1]) { + if (filec == MAXFILEC) + fatal("too many file arguments\n"); + filearg[filec++] = savestr(s); + } else { + char opt; + + if (*(s + 1) == '-') { + opt = decode_long_option(s + 2); + s += strlen(s) - 1; + } else + opt = *++s; + switch (opt) { + case 'b': + simple_backup_suffix = savestr(nextarg()); + break; + case 'B': + origprae = savestr(nextarg()); + break; + case 'c': + diff_type = CONTEXT_DIFF; + break; + case 'C': + check_only = TRUE; + break; + case 'd': + if (!*++s) + s = nextarg(); + if (chdir(s) < 0) + pfatal("can't cd to %s", s); + break; + case 'D': + do_defines = TRUE; + if (!*++s) + s = nextarg(); + if (!isalpha(*s) && '_' != *s) + fatal("argument to -D is not an identifier\n"); + snprintf(if_defined, sizeof if_defined, + "#ifdef %s\n", s); + snprintf(not_defined, sizeof not_defined, + "#ifndef %s\n", s); + snprintf(end_defined, sizeof end_defined, + "#endif /* %s */\n", s); + break; + case 'e': + diff_type = ED_DIFF; + break; + case 'E': + remove_empty_files = TRUE; + break; + case 'f': + force = TRUE; + break; + case 'F': + if (!*++s) + s = nextarg(); + else if (*s == '=') + s++; + maxfuzz = atoi(s); + break; + case 'l': + canonicalize = TRUE; + break; + case 'n': + diff_type = NORMAL_DIFF; + break; + case 'N': + noreverse = TRUE; + break; + case 'o': + outname = savestr(nextarg()); + break; + case 'p': + if (!*++s) + s = nextarg(); + else if (*s == '=') + s++; + strippath = atoi(s); + break; + case 'r': + if (strlcpy(rejname, nextarg(), + sizeof(rejname)) >= sizeof(rejname)) + fatal("argument for -r is too long\n"); + break; + case 'R': + reverse = TRUE; + reverse_flag_specified = TRUE; + break; + case 's': + verbose = FALSE; + break; + case 'S': + skip_rest_of_patch = TRUE; + break; + case 't': + batch = TRUE; + break; + case 'u': + diff_type = UNI_DIFF; + break; + case 'v': + version(); + break; + case 'V': + backup_type = get_version(nextarg()); + break; #ifdef DEBUGGING - case 'x': - if (!*++s) - s = nextarg(); - debug = atoi(s); - break; + case 'x': + if (!*++s) + s = nextarg(); + debug = atoi(s); + break; #endif - default: - fprintf(stderr, "patch: unrecognized option `%s'\n", Argv[0]); - fprintf(stderr, "\ + default: + fprintf(stderr, "patch: unrecognized option `%s'\n", + Argv[0]); + fprintf(stderr, "\ Usage: patch [options] [origfile [patchfile]] [+ [options] [origfile]]...\n\ Options:\n\ [-cCeEflnNRsStuv] [-b backup-ext] [-B backup-prefix] [-d directory]\n\ [-D symbol] [-Fmax-fuzz] [-o out-file] [-p[strip-count]]\n\ [-r rej-name] [-V {numbered,existing,simple}]\n"); - my_exit(1); - } + my_exit(1); + } + } } - } } -/* Attempt to find the right place to apply this hunk of patch. */ - +/* + * Attempt to find the right place to apply this hunk of patch. + */ LINENUM -locate_hunk(fuzz) -LINENUM fuzz; +locate_hunk(LINENUM fuzz) { - LINENUM first_guess = pch_first() + last_offset; - LINENUM offset; - LINENUM pat_lines = pch_ptrn_lines(); - LINENUM max_pos_offset = input_lines - first_guess - - pat_lines + 1; - LINENUM max_neg_offset = first_guess - last_frozen_line - 1 - + pch_context(); - - if (!pat_lines) /* null range matches always */ - return first_guess; - if (max_neg_offset >= first_guess) /* do not try lines < 0 */ - max_neg_offset = first_guess - 1; - if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz)) - return first_guess; - for (offset = 1; ; offset++) { - bool check_after = (offset <= max_pos_offset); - bool check_before = (offset <= max_neg_offset); - - if (check_after && patch_match(first_guess, offset, fuzz)) { + LINENUM first_guess = pch_first() + last_offset; + LINENUM offset; + LINENUM pat_lines = pch_ptrn_lines(); + LINENUM max_pos_offset = input_lines - first_guess - pat_lines + 1; + LINENUM max_neg_offset = first_guess - last_frozen_line - 1 + pch_context(); + + if (!pat_lines) /* null range matches always */ + return first_guess; + if (max_neg_offset >= first_guess) /* do not try lines < 0 */ + max_neg_offset = first_guess - 1; + if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz)) + return first_guess; + for (offset = 1; ; offset++) { + bool check_after = (offset <= max_pos_offset); + bool check_before = (offset <= max_neg_offset); + + if (check_after && patch_match(first_guess, offset, fuzz)) { #ifdef DEBUGGING - if (debug & 1) - say("Offset changing from %ld to %ld\n", last_offset, offset); + if (debug & 1) + say("Offset changing from %ld to %ld\n", + last_offset, offset); #endif - last_offset = offset; - return first_guess+offset; - } - else if (check_before && patch_match(first_guess, -offset, fuzz)) { + last_offset = offset; + return first_guess + offset; + } else if (check_before && patch_match(first_guess, -offset, fuzz)) { #ifdef DEBUGGING - if (debug & 1) - say("Offset changing from %ld to %ld\n", last_offset, -offset); + if (debug & 1) + say("Offset changing from %ld to %ld\n", + last_offset, -offset); #endif - last_offset = -offset; - return first_guess-offset; + last_offset = -offset; + return first_guess - offset; + } else if (!check_before && !check_after) + return Nulline; } - else if (!check_before && !check_after) - return Nulline; - } } /* We did not find the pattern, dump out the hunk so they can handle it. */ void -abort_hunk() +abort_hunk(void) { - LINENUM i; - LINENUM pat_end = pch_end(); - /* add in last_offset to guess the same as the previous successful hunk */ - LINENUM oldfirst = pch_first() + last_offset; - LINENUM newfirst = pch_newfirst() + last_offset; - LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1; - LINENUM newlast = newfirst + pch_repl_lines() - 1; - char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : ""); - char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----"); - - fprintf(rejfp, "***************\n"); - for (i=0; i<=pat_end; i++) { - switch (pch_char(i)) { - case '*': - if (oldlast < oldfirst) - fprintf(rejfp, "*** 0%s\n", stars); - else if (oldlast == oldfirst) - fprintf(rejfp, "*** %ld%s\n", oldfirst, stars); - else - fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars); - break; - case '=': - if (newlast < newfirst) - fprintf(rejfp, "--- 0%s\n", minuses); - else if (newlast == newfirst) - fprintf(rejfp, "--- %ld%s\n", newfirst, minuses); - else - fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses); - break; - case '\n': - fprintf(rejfp, "%s", pfetch(i)); - break; - case ' ': case '-': case '+': case '!': - fprintf(rejfp, "%c %s", pch_char(i), pfetch(i)); - break; - default: - fatal("fatal internal error in abort_hunk\n"); + LINENUM i; + LINENUM pat_end = pch_end(); + /* + * add in last_offset to guess the same as the previous successful + * hunk + */ + LINENUM oldfirst = pch_first() + last_offset; + LINENUM newfirst = pch_newfirst() + last_offset; + LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1; + LINENUM newlast = newfirst + pch_repl_lines() - 1; + char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : ""); + char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----"); + + fprintf(rejfp, "***************\n"); + for (i = 0; i <= pat_end; i++) { + switch (pch_char(i)) { + case '*': + if (oldlast < oldfirst) + fprintf(rejfp, "*** 0%s\n", stars); + else if (oldlast == oldfirst) + fprintf(rejfp, "*** %ld%s\n", oldfirst, stars); + else + fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, + oldlast, stars); + break; + case '=': + if (newlast < newfirst) + fprintf(rejfp, "--- 0%s\n", minuses); + else if (newlast == newfirst) + fprintf(rejfp, "--- %ld%s\n", newfirst, minuses); + else + fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, + newlast, minuses); + break; + case '\n': + fprintf(rejfp, "%s", pfetch(i)); + break; + case ' ': + case '-': + case '+': + case '!': + fprintf(rejfp, "%c %s", pch_char(i), pfetch(i)); + break; + default: + fatal("fatal internal error in abort_hunk\n"); + } } - } } /* We found where to apply it (we hope), so do it. */ void -apply_hunk(where) -LINENUM where; +apply_hunk(LINENUM where) { - LINENUM old = 1; - LINENUM lastline = pch_ptrn_lines(); - LINENUM new = lastline+1; + LINENUM old = 1; + LINENUM lastline = pch_ptrn_lines(); + LINENUM new = lastline + 1; #define OUTSIDE 0 #define IN_IFNDEF 1 #define IN_IFDEF 2 #define IN_ELSE 3 - int def_state = OUTSIDE; - bool R_do_defines = do_defines; - LINENUM pat_end = pch_end(); - - where--; - while (pch_char(new) == '=' || pch_char(new) == '\n') - new++; - - while (old <= lastline) { - if (pch_char(old) == '-') { - copy_till(where + old - 1); - if (R_do_defines) { - if (def_state == OUTSIDE) { - fputs(not_defined, ofp); - def_state = IN_IFNDEF; - } - else if (def_state == IN_IFDEF) { - fputs(else_defined, ofp); - def_state = IN_ELSE; - } - fputs(pfetch(old), ofp); - } - last_frozen_line++; - old++; - } - else if (new > pat_end) { - break; - } - else if (pch_char(new) == '+') { - copy_till(where + old - 1); - if (R_do_defines) { - if (def_state == IN_IFNDEF) { - fputs(else_defined, ofp); - def_state = IN_ELSE; - } - else if (def_state == OUTSIDE) { - fputs(if_defined, ofp); - def_state = IN_IFDEF; - } - } - fputs(pfetch(new), ofp); - new++; - } - else if (pch_char(new) != pch_char(old)) { - say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n", - pch_hunk_beg() + old, - pch_hunk_beg() + new); + int def_state = OUTSIDE; + bool R_do_defines = do_defines; + LINENUM pat_end = pch_end(); + + where--; + while (pch_char(new) == '=' || pch_char(new) == '\n') + new++; + + while (old <= lastline) { + if (pch_char(old) == '-') { + copy_till(where + old - 1); + if (R_do_defines) { + if (def_state == OUTSIDE) { + fputs(not_defined, ofp); + def_state = IN_IFNDEF; + } else if (def_state == IN_IFDEF) { + fputs(else_defined, ofp); + def_state = IN_ELSE; + } + fputs(pfetch(old), ofp); + } + last_frozen_line++; + old++; + } else if (new > pat_end) { + break; + } else if (pch_char(new) == '+') { + copy_till(where + old - 1); + if (R_do_defines) { + if (def_state == IN_IFNDEF) { + fputs(else_defined, ofp); + def_state = IN_ELSE; + } else if (def_state == OUTSIDE) { + fputs(if_defined, ofp); + def_state = IN_IFDEF; + } + } + fputs(pfetch(new), ofp); + new++; + } else if (pch_char(new) != pch_char(old)) { + say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n", + pch_hunk_beg() + old, + pch_hunk_beg() + new); #ifdef DEBUGGING - say("oldchar = '%c', newchar = '%c'\n", - pch_char(old), pch_char(new)); + say("oldchar = '%c', newchar = '%c'\n", + pch_char(old), pch_char(new)); #endif - my_exit(1); + my_exit(1); + } else if (pch_char(new) == '!') { + copy_till(where + old - 1); + if (R_do_defines) { + fputs(not_defined, ofp); + def_state = IN_IFNDEF; + } + while (pch_char(old) == '!') { + if (R_do_defines) { + fputs(pfetch(old), ofp); + } + last_frozen_line++; + old++; + } + if (R_do_defines) { + fputs(else_defined, ofp); + def_state = IN_ELSE; + } + while (pch_char(new) == '!') { + fputs(pfetch(new), ofp); + new++; + } + } else { + assert(pch_char(new) == ' '); + old++; + new++; + if (R_do_defines && def_state != OUTSIDE) { + fputs(end_defined, ofp); + def_state = OUTSIDE; + } + } } - else if (pch_char(new) == '!') { - copy_till(where + old - 1); - if (R_do_defines) { - fputs(not_defined, ofp); - def_state = IN_IFNDEF; - } - while (pch_char(old) == '!') { + if (new <= pat_end && pch_char(new) == '+') { + copy_till(where + old - 1); if (R_do_defines) { - fputs(pfetch(old), ofp); + if (def_state == OUTSIDE) { + fputs(if_defined, ofp); + def_state = IN_IFDEF; + } else if (def_state == IN_IFNDEF) { + fputs(else_defined, ofp); + def_state = IN_ELSE; + } + } + while (new <= pat_end && pch_char(new) == '+') { + fputs(pfetch(new), ofp); + new++; } - last_frozen_line++; - old++; - } - if (R_do_defines) { - fputs(else_defined, ofp); - def_state = IN_ELSE; - } - while (pch_char(new) == '!') { - fputs(pfetch(new), ofp); - new++; - } } - else { - assert(pch_char(new) == ' '); - old++; - new++; - if (R_do_defines && def_state != OUTSIDE) { + if (R_do_defines && def_state != OUTSIDE) { fputs(end_defined, ofp); - def_state = OUTSIDE; - } - } - } - if (new <= pat_end && pch_char(new) == '+') { - copy_till(where + old - 1); - if (R_do_defines) { - if (def_state == OUTSIDE) { - fputs(if_defined, ofp); - def_state = IN_IFDEF; - } - else if (def_state == IN_IFNDEF) { - fputs(else_defined, ofp); - def_state = IN_ELSE; - } } - while (new <= pat_end && pch_char(new) == '+') { - fputs(pfetch(new), ofp); - new++; - } - } - if (R_do_defines && def_state != OUTSIDE) { - fputs(end_defined, ofp); - } } -/* Open the new file. */ - +/* + * Open the new file. + */ void -init_output(name) -char *name; +init_output(char *name) { - ofp = fopen(name, "w"); - if (ofp == Nullfp) - pfatal("can't create %s", name); + ofp = fopen(name, "w"); + if (ofp == Nullfp) + pfatal("can't create %s", name); } -/* Open a file to put hunks we can't locate. */ - +/* + * Open a file to put hunks we can't locate. + */ void -init_reject(name) -char *name; +init_reject(char *name) { - rejfp = fopen(name, "w"); - if (rejfp == Nullfp) - pfatal("can't create %s", name); + rejfp = fopen(name, "w"); + if (rejfp == Nullfp) + pfatal("can't create %s", name); } -/* Copy input file to output, up to wherever hunk is to be applied. */ - +/* + * Copy input file to output, up to wherever hunk is to be applied. + */ void -copy_till(lastline) -LINENUM lastline; +copy_till(LINENUM lastline) { - LINENUM R_last_frozen_line = last_frozen_line; - - if (R_last_frozen_line > lastline) - fatal("misordered hunks! output would be garbled\n"); - while (R_last_frozen_line < lastline) { - dump_line(++R_last_frozen_line); - } - last_frozen_line = R_last_frozen_line; -} + LINENUM R_last_frozen_line = last_frozen_line; -/* Finish copying the input file to the output file. */ + if (R_last_frozen_line > lastline) + fatal("misordered hunks! output would be garbled\n"); + while (R_last_frozen_line < lastline) + dump_line(++R_last_frozen_line); + last_frozen_line = R_last_frozen_line; +} +/* + * Finish copying the input file to the output file. + */ void -spew_output() +spew_output(void) { #ifdef DEBUGGING - if (debug & 256) - say("il=%ld lfl=%ld\n",input_lines,last_frozen_line); + if (debug & 256) + say("il=%ld lfl=%ld\n", input_lines, last_frozen_line); #endif - if (input_lines) - copy_till(input_lines); /* dump remainder of file */ - fclose(ofp); - ofp = Nullfp; + if (input_lines) + copy_till(input_lines); /* dump remainder of file */ + fclose(ofp); + ofp = Nullfp; } -/* Copy one line from input to output. */ - +/* + * Copy one line from input to output. + */ void -dump_line(line) -LINENUM line; +dump_line(LINENUM line) { - char *s; - char R_newline = '\n'; - - s = ifetch(line, 0); - if (s == NULL) - return; - /* Note: string is not null terminated. */ - for (; putc(*s, ofp) != R_newline; s++) ; + char *s, R_newline = '\n'; + + s = ifetch(line, 0); + if (s == NULL) + return; + /* Note: string is not null terminated. */ + for (; putc(*s, ofp) != R_newline; s++) + ; } -/* Does the patch pattern match at line base+offset? */ - +/* + * Does the patch pattern match at line base+offset? + */ bool -patch_match(base, offset, fuzz) -LINENUM base; -LINENUM offset; -LINENUM fuzz; +patch_match(LINENUM base, LINENUM offset, LINENUM fuzz) { - LINENUM pline = 1 + fuzz; - LINENUM iline; - LINENUM pat_lines = pch_ptrn_lines() - fuzz; - - for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) { - if (canonicalize) { - if (!similar(ifetch(iline, (offset >= 0)), - pfetch(pline), - pch_line_len(pline) )) - return FALSE; + LINENUM pline = 1 + fuzz; + LINENUM iline; + LINENUM pat_lines = pch_ptrn_lines() - fuzz; + + for (iline = base + offset + fuzz; pline <= pat_lines; pline++, iline++) { + if (canonicalize) { + if (!similar(ifetch(iline, (offset >= 0)), + pfetch(pline), pch_line_len(pline))) + return FALSE; + } else if (strnNE(ifetch(iline, (offset >= 0)), + pfetch(pline), pch_line_len(pline))) + return FALSE; } - else if (strnNE(ifetch(iline, (offset >= 0)), - pfetch(pline), - pch_line_len(pline) )) - return FALSE; - } - return TRUE; + return TRUE; } -/* Do two lines match with canonicalized white space? */ - +/* + * Do two lines match with canonicalized white space? + */ bool -similar(a,b,len) -char *a; -char *b; -int len; +similar(char *a, char *b, int len) { - if (a == NULL || b == NULL) - return FALSE; - while (len) { - if (isspace(*b)) { /* whitespace (or \n) to match? */ - if (!isspace(*a)) /* no corresponding whitespace? */ + if (a == NULL || b == NULL) return FALSE; - while (len && isspace(*b) && *b != '\n') - b++,len--; /* skip pattern whitespace */ - while (isspace(*a) && *a != '\n') - a++; /* skip target whitespace */ - if (*a == '\n' || *b == '\n') - return (*a == *b); /* should end in sync */ + while (len) { + if (isspace(*b)) { /* whitespace (or \n) to match? */ + if (!isspace(*a)) /* no corresponding whitespace? */ + return FALSE; + while (len && isspace(*b) && *b != '\n') + b++, len--; /* skip pattern whitespace */ + while (isspace(*a) && *a != '\n') + a++; /* skip target whitespace */ + if (*a == '\n' || *b == '\n') + return (*a == *b); /* should end in sync */ + } else if (*a++ != *b++) /* match non-whitespace chars */ + return FALSE; + else + len--; /* probably not necessary */ } - else if (*a++ != *b++) /* match non-whitespace chars */ - return FALSE; - else - len--; /* probably not necessary */ - } - return TRUE; /* actually, this is not reached */ - /* since there is always a \n */ + return TRUE; /* actually, this is not reached */ + /* since there is always a \n */ } -/* Exit with cleanup. */ - +/* + * Exit with cleanup. + */ void -my_exit(status) -int status; +my_exit(int status) { - unlink(TMPINNAME); - if (!toutkeep) { - unlink(TMPOUTNAME); - } - if (!trejkeep) { - unlink(TMPREJNAME); - } - unlink(TMPPATNAME); - exit(status); + unlink(TMPINNAME); + if (!toutkeep) + unlink(TMPOUTNAME); + if (!trejkeep) + unlink(TMPREJNAME); + unlink(TMPPATNAME); + exit(status); } diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c index 4087daf841d..1fdf26ec9c4 100644 --- a/usr.bin/patch/pch.c +++ b/usr.bin/patch/pch.c @@ -1,7 +1,7 @@ -/* $OpenBSD: pch.c,v 1.16 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: pch.c,v 1.17 2003/07/21 14:00:41 deraadt Exp $ */ #ifndef lint -static char rcsid[] = "$OpenBSD: pch.c,v 1.16 2003/07/18 02:00:09 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: pch.c,v 1.17 2003/07/21 14:00:41 deraadt Exp $"; #endif /* not lint */ #include "EXTERN.h" @@ -10,398 +10,394 @@ static char rcsid[] = "$OpenBSD: pch.c,v 1.16 2003/07/18 02:00:09 deraadt Exp $" #include "INTERN.h" #include "pch.h" -extern bool check_only; +extern bool check_only; /* Patch (diff listing) 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 = Null(char**); /* the text of the hunk */ -static short *p_len = Null(short*); /* length of each line */ -static char *p_char = Nullch; /* +, -, and ! */ -static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */ -static int p_indent; /* indent to patch */ -static LINENUM p_base; /* where to intuit this time */ -static LINENUM p_bline; /* line # of p_base */ -static LINENUM 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 */ - -/* Prepare to look for the next patch in the patch file. */ +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 = Null(char **); /* the text of the hunk */ +static short *p_len = Null(short *); /* length of each line */ +static char *p_char = Nullch;/* +, -, and ! */ +static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */ +static int p_indent; /* indent to patch */ +static LINENUM p_base; /* where to intuit this time */ +static LINENUM p_bline; /* line # of p_base */ +static LINENUM 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 */ +/* + * Prepare to look for the next patch in the patch file. + */ void -re_patch() +re_patch(void) { - p_first = Nulline; - p_newfirst = Nulline; - p_ptrn_lines = Nulline; - p_repl_lines = Nulline; - p_end = (LINENUM)-1; - p_max = Nulline; - p_indent = 0; + p_first = Nulline; + p_newfirst = Nulline; + p_ptrn_lines = Nulline; + p_repl_lines = Nulline; + p_end = (LINENUM) - 1; + p_max = Nulline; + p_indent = 0; } -/* Open the patch file at the beginning of time. */ - +/* + * Open the patch file at the beginning of time. + */ void -open_patch_file(filename) -char *filename; +open_patch_file(char *filename) { - if (filename == Nullch || !*filename || strEQ(filename, "-")) { - pfp = fopen(TMPPATNAME, "w"); + if (filename == Nullch || !*filename || strEQ(filename, "-")) { + pfp = fopen(TMPPATNAME, "w"); + if (pfp == Nullfp) + pfatal("can't create %s", TMPPATNAME); + while (fgets(buf, sizeof buf, stdin) != Nullch) + fputs(buf, pfp); + fclose(pfp); + filename = TMPPATNAME; + } + pfp = fopen(filename, "r"); if (pfp == Nullfp) - pfatal("can't create %s", TMPPATNAME); - while (fgets(buf, sizeof buf, stdin) != Nullch) - fputs(buf, pfp); - fclose(pfp); - filename = TMPPATNAME; - } - pfp = fopen(filename, "r"); - if (pfp == Nullfp) - pfatal("patch file %s not found", filename); - fstat(fileno(pfp), &filestat); - p_filesize = filestat.st_size; - next_intuit_at(0L,1L); /* start at the beginning */ - set_hunkmax(); + pfatal("patch file %s not found", filename); + fstat(fileno(pfp), &filestat); + p_filesize = filestat.st_size; + next_intuit_at(0L, 1L); /* start at the beginning */ + set_hunkmax(); } -/* Make sure our dynamically realloced tables are malloced to begin with. */ - +/* + * Make sure our dynamically realloced tables are malloced to begin with. + */ void -set_hunkmax() +set_hunkmax(void) { #ifndef lint - if (p_line == Null(char**)) - p_line = (char**) malloc((MEM)hunkmax * sizeof(char *)); - if (p_len == Null(short*)) - p_len = (short*) malloc((MEM)hunkmax * sizeof(short)); + if (p_line == Null(char **)) + p_line = (char **) malloc((MEM) hunkmax * sizeof(char *)); + if (p_len == Null(short *)) + p_len = (short *) malloc((MEM) hunkmax * sizeof(short)); #endif - if (p_char == Nullch) - p_char = (char*) malloc((MEM)hunkmax * sizeof(char)); + if (p_char == Nullch) + p_char = (char *) malloc((MEM) hunkmax * sizeof(char)); } -/* Enlarge the arrays containing the current hunk of patch. */ - +/* + * Enlarge the arrays containing the current hunk of patch. + */ void -grow_hunkmax() +grow_hunkmax(void) { - hunkmax *= 2; - /* - * Note that on most systems, only the p_line array ever gets fresh memory - * since p_len can move into p_line's old space, and p_char can move into - * p_len's old space. Not on PDP-11's however. But it doesn't matter. - */ - assert(p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch); + hunkmax *= 2; + + /* + * Note that on most systems, only the p_line array ever gets fresh memory + * since p_len can move into p_line's old space, and p_char can move into + * p_len's old space. Not on PDP-11's however. But it doesn't matter. + */ + assert(p_line != Null(char **) &&p_len != Null(short *) &&p_char != Nullch); #ifndef lint - p_line = (char**) realloc((char*)p_line, (MEM)hunkmax * sizeof(char *)); - p_len = (short*) realloc((char*)p_len, (MEM)hunkmax * sizeof(short)); - p_char = (char*) realloc((char*)p_char, (MEM)hunkmax * sizeof(char)); + p_line = (char **) realloc((char *) p_line, (MEM) hunkmax * sizeof(char *)); + p_len = (short *) realloc((char *) p_len, (MEM) hunkmax * sizeof(short)); + p_char = (char *) realloc((char *) p_char, (MEM) hunkmax * sizeof(char)); #endif - if (p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch) - return; - if (!using_plan_a) - fatal("out of memory\n"); - out_of_mem = TRUE; /* whatever is null will be allocated again */ - /* from within plan_a(), of all places */ + if (p_line != Null(char **) &&p_len != Null(short *) &&p_char != Nullch) + return; + if (!using_plan_a) + fatal("out of memory\n"); + out_of_mem = TRUE; /* whatever is null will be allocated again */ + /* from within plan_a(), of all places */ } /* True if the remainder of the patch file contains a diff of some sort. */ bool -there_is_another_patch() +there_is_another_patch(void) { - 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 == 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 (p_indent && verbose) - say("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s"); - skip_to(p_start,p_sline); - while (filearg[0] == Nullch) { - if (force || batch) { - say("No file to patch. Skipping...\n"); - filearg[0] = savestr(bestguess); - skip_rest_of_patch = TRUE; - return TRUE; + if (p_base != 0L && p_base >= p_filesize) { + if (verbose) + say("done\n"); + return FALSE; } - ask("File to patch: "); - if (*buf != '\n') { - if (bestguess) - free(bestguess); - bestguess = savestr(buf); - filearg[0] = fetchname(buf, 0, 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 (filearg[0] == Nullch) { - ask("No file found--skip this patch? [n] "); - if (*buf != 'y') { - continue; - } - if (verbose) - say("Skipping patch...\n"); - filearg[0] = fetchname(bestguess, 0, TRUE); - skip_rest_of_patch = TRUE; - return TRUE; + if (verbose) + say(" %sooks like %s to me...\n", + (p_base == 0L ? "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 (p_indent && verbose) + say("(Patch is indented %d space%s.)\n", p_indent, + p_indent == 1 ? "" : "s"); + skip_to(p_start, p_sline); + while (filearg[0] == Nullch) { + if (force || batch) { + say("No file to patch. Skipping...\n"); + filearg[0] = savestr(bestguess); + skip_rest_of_patch = TRUE; + return TRUE; + } + ask("File to patch: "); + if (*buf != '\n') { + if (bestguess) + free(bestguess); + bestguess = savestr(buf); + filearg[0] = fetchname(buf, 0, FALSE); + } + if (filearg[0] == Nullch) { + ask("No file found--skip this patch? [n] "); + if (*buf != 'y') + continue; + if (verbose) + say("Skipping patch...\n"); + filearg[0] = fetchname(bestguess, 0, TRUE); + skip_rest_of_patch = TRUE; + return TRUE; + } } - } - return TRUE; + return TRUE; } /* Determine what kind of diff is in the remaining part of the patch file. */ int -intuit_diff_type() +intuit_diff_type(void) { - long this_line = 0; - long previous_line; - long first_command_line = -1; - long fcl_line; - bool last_line_was_command = FALSE; - bool this_is_a_command = FALSE; - bool stars_last_line = FALSE; - bool stars_this_line = FALSE; - int indent; - char *s; - char *t; - char *indtmp = Nullch; - char *oldtmp = Nullch; - char *newtmp = Nullch; - char *indname = Nullch; - char *oldname = Nullch; - char *newname = Nullch; - int retval; - bool no_filearg = (filearg[0] == Nullch); - - ok_to_create_file = FALSE; - fseek(pfp, p_base, 0); - p_input_line = p_bline - 1; - for (;;) { - previous_line = this_line; - last_line_was_command = this_is_a_command; - stars_last_line = stars_this_line; - this_line = ftell(pfp); - indent = 0; - p_input_line++; - if (fgets(buf, sizeof buf, pfp) == Nullch) { - if (first_command_line >= 0L) { - /* 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; - retval = 0; - goto scan_exit; - } - } - for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) { - if (*s == '\t') - indent += 8 - (indent % 8); - else - indent++; - } - for (t=s; isdigit(*t) || *t == ','; t++) ; - this_is_a_command = (isdigit(*s) && - (*t == 'd' || *t == 'c' || *t == 'a') ); - if (first_command_line < 0L && this_is_a_command) { - first_command_line = this_line; - fcl_line = p_input_line; - p_indent = indent; /* assume this for now */ - } - if (!stars_last_line && strnEQ(s, "*** ", 4)) - oldtmp = savestr(s+4); - else if (strnEQ(s, "--- ", 4)) - newtmp = savestr(s+4); - else if (strnEQ(s, "+++ ", 4)) - oldtmp = savestr(s+4); /* pretend it is the old name */ - else if (strnEQ(s, "Index:", 6)) - indtmp = savestr(s+6); - 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; - p_sline = fcl_line; - retval = ED_DIFF; - goto scan_exit; + long this_line = 0, previous_line; + long first_command_line = -1, fcl_line; + bool last_line_was_command = FALSE, this_is_a_command = FALSE; + bool stars_last_line = FALSE, stars_this_line = FALSE; + char *s, *t; + char *indtmp = Nullch; + char *oldtmp = Nullch; + char *newtmp = Nullch; + char *indname = Nullch; + char *oldname = Nullch; + char *newname = Nullch; + int indent, retval; + bool no_filearg = (filearg[0] == Nullch); + + ok_to_create_file = FALSE; + fseek(pfp, p_base, 0); + p_input_line = p_bline - 1; + for (;;) { + previous_line = this_line; + last_line_was_command = this_is_a_command; + stars_last_line = stars_this_line; + this_line = ftell(pfp); + indent = 0; + p_input_line++; + if (fgets(buf, sizeof buf, pfp) == Nullch) { + if (first_command_line >= 0L) { + /* 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; + retval = 0; + goto scan_exit; + } + } + for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) { + if (*s == '\t') + indent += 8 - (indent % 8); + else + indent++; + } + for (t = s; isdigit(*t) || *t == ','; t++) + ; + this_is_a_command = (isdigit(*s) && + (*t == 'd' || *t == 'c' || *t == 'a')); + if (first_command_line < 0L && this_is_a_command) { + first_command_line = this_line; + fcl_line = p_input_line; + p_indent = indent; /* assume this for now */ + } + if (!stars_last_line && strnEQ(s, "*** ", 4)) + oldtmp = savestr(s + 4); + else if (strnEQ(s, "--- ", 4)) + newtmp = savestr(s + 4); + else if (strnEQ(s, "+++ ", 4)) + oldtmp = savestr(s + 4); /* pretend it is the old + * name */ + else if (strnEQ(s, "Index:", 6)) + indtmp = savestr(s + 6); + 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; + p_sline = fcl_line; + retval = ED_DIFF; + goto scan_exit; + } + if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) { + if (!atol(s + 3)) + ok_to_create_file = TRUE; + p_indent = indent; + p_start = this_line; + p_sline = p_input_line; + retval = UNI_DIFF; + goto scan_exit; + } + stars_this_line = strnEQ(s, "********", 8); + if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line && + strnEQ(s, "*** ", 4)) { + if (!atol(s + 4)) + ok_to_create_file = TRUE; + /* + * 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; + p_sline = p_input_line - 1; + retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF); + goto scan_exit; + } + if ((!diff_type || 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; + retval = NORMAL_DIFF; + goto scan_exit; + } } - if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) { - if (!atol(s+3)) - ok_to_create_file = TRUE; - p_indent = indent; - p_start = this_line; - p_sline = p_input_line; - retval = UNI_DIFF; - goto scan_exit; +scan_exit: + if (no_filearg) { + if (indtmp != Nullch) + indname = fetchname(indtmp, strippath, ok_to_create_file); + if (oldtmp != Nullch) + oldname = fetchname(oldtmp, strippath, ok_to_create_file); + if (newtmp != Nullch) + newname = fetchname(newtmp, strippath, ok_to_create_file); + if (indname) + filearg[0] = savestr(indname); + else if (oldname && newname) { + if (strlen(oldname) < strlen(newname)) + filearg[0] = savestr(oldname); + else + filearg[0] = savestr(newname); + } else if (oldname) + filearg[0] = savestr(oldname); + else if (newname) + filearg[0] = savestr(newname); } - stars_this_line = strnEQ(s, "********", 8); - if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line && - strnEQ(s, "*** ", 4)) { - if (!atol(s+4)) - ok_to_create_file = TRUE; - /* 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; - p_sline = p_input_line - 1; - retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF); - goto scan_exit; + if (bestguess) { + free(bestguess); + bestguess = Nullch; } - if ((!diff_type || 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; - retval = NORMAL_DIFF; - goto scan_exit; + if (filearg[0] != Nullch) + bestguess = savestr(filearg[0]); + else if (indtmp != Nullch) + bestguess = fetchname(indtmp, strippath, TRUE); + else { + if (oldtmp != Nullch) + oldname = fetchname(oldtmp, strippath, TRUE); + if (newtmp != Nullch) + newname = fetchname(newtmp, strippath, TRUE); + if (oldname && newname) { + if (strlen(oldname) < strlen(newname)) + bestguess = savestr(oldname); + else + bestguess = savestr(newname); + } else if (oldname) + bestguess = savestr(oldname); + else if (newname) + bestguess = savestr(newname); } - } - scan_exit: - if (no_filearg) { if (indtmp != Nullch) - indname = fetchname(indtmp, strippath, ok_to_create_file); + free(indtmp); if (oldtmp != Nullch) - oldname = fetchname(oldtmp, strippath, ok_to_create_file); + free(oldtmp); if (newtmp != Nullch) - newname = fetchname(newtmp, strippath, ok_to_create_file); - if (indname) - filearg[0] = savestr(indname); - else if (oldname && newname) { - if (strlen(oldname) < strlen(newname)) - filearg[0] = savestr(oldname); - else - filearg[0] = savestr(newname); - } - else if (oldname) - filearg[0] = savestr(oldname); - else if (newname) - filearg[0] = savestr(newname); - } - if (bestguess) { - free(bestguess); - bestguess = Nullch; - } - if (filearg[0] != Nullch) - bestguess = savestr(filearg[0]); - else if (indtmp != Nullch) - bestguess = fetchname(indtmp, strippath, TRUE); - else { - if (oldtmp != Nullch) - oldname = fetchname(oldtmp, strippath, TRUE); - if (newtmp != Nullch) - newname = fetchname(newtmp, strippath, TRUE); - if (oldname && newname) { - if (strlen(oldname) < strlen(newname)) - bestguess = savestr(oldname); - else - bestguess = savestr(newname); - } - else if (oldname) - bestguess = savestr(oldname); - else if (newname) - bestguess = savestr(newname); - } - if (indtmp != Nullch) - free(indtmp); - if (oldtmp != Nullch) - free(oldtmp); - if (newtmp != Nullch) - free(newtmp); - if (indname != Nullch) - free(indname); - if (oldname != Nullch) - free(oldname); - if (newname != Nullch) - free(newname); - return retval; + free(newtmp); + if (indname != Nullch) + free(indname); + if (oldname != Nullch) + free(oldname); + if (newname != Nullch) + free(newname); + return retval; } -/* Remember where this patch ends so we know where to start up again. */ - +/* + * Remember where this patch ends so we know where to start up again. + */ void -next_intuit_at(file_pos,file_line) -long file_pos; -long file_line; +next_intuit_at(long file_pos, long file_line) { - p_base = file_pos; - p_bline = file_line; + p_base = file_pos; + p_bline = file_line; } -/* Basically a verbose fseek() to the actual diff listing. */ - +/* + * Basically a verbose fseek() to the actual diff listing. + */ void -skip_to(file_pos,file_line) -long file_pos; -long file_line; +skip_to(long file_pos, long file_line) { - 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); - p_input_line = file_line - 1; + 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); + p_input_line = file_line - 1; } /* Make this a function for better debugging. */ static void malformed(void) { - fatal("malformed patch at line %ld: %s", p_input_line, buf); - /* about as informative as "Syntax error" in C */ + fatal("malformed patch at line %ld: %s", p_input_line, buf); + /* about as informative as "Syntax error" in C */ } /* @@ -411,7 +407,7 @@ malformed(void) static bool remove_special_line(void) { - int c; + int c; c = fgetc(pfp); if (c == '\\') { @@ -421,927 +417,944 @@ remove_special_line(void) return TRUE; } - if (c != EOF) fseek(pfp, -1L, SEEK_CUR); return FALSE; } -/* True if there is more of the current diff listing to process. */ - +/* + * True if there is more of the current diff listing to process. + */ bool -another_hunk() +another_hunk(void) { - char *s; - char *ret; - int context = 0; + long line_beginning; /* file pos of the current line */ + LINENUM repl_beginning; /* index of --- line */ + LINENUM fillcnt; /* #lines of missing ptrn or repl */ + LINENUM fillsrc; /* index of first line to copy */ + LINENUM filldst; /* index of first missing line */ + bool ptrn_spaces_eaten; /* ptrn was slightly misformed */ + bool repl_could_be_missing; /* no + or ! lines in this hunk */ + bool repl_missing; /* we are now backtracking */ + long repl_backtrack_position; /* file pos of first repl line */ + LINENUM repl_patch_line; /* input line number for same */ + LINENUM ptrn_copiable; /* # of copiable lines in ptrn */ + char *s, *ret; + int context = 0; + + while (p_end >= 0) { + if (p_end == p_efake) + p_end = p_bfake; /* don't free twice */ + else + free(p_line[p_end]); + p_end--; + } + assert(p_end == -1); + p_efake = -1; + + p_max = hunkmax; /* gets reduced when --- found */ + if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) { + line_beginning = ftell(pfp); + repl_beginning = 0; + fillcnt = 0; + ptrn_spaces_eaten = FALSE; + repl_could_be_missing = TRUE; + repl_missing = FALSE; + repl_backtrack_position = 0; + ptrn_copiable = 0; + + ret = pgets(buf, sizeof buf, pfp); + p_input_line++; + if (ret == Nullch || strnNE(buf, "********", 8)) { + next_intuit_at(line_beginning, p_input_line); + return FALSE; + } + p_context = 100; + p_hunk_beg = p_input_line + 1; + while (p_end < p_max) { + line_beginning = ftell(pfp); + ret = pgets(buf, sizeof buf, pfp); + p_input_line++; + if (ret == Nullch) { + if (p_max - p_end < 4) { + /* assume blank lines got chopped */ + strlcpy(buf, " \n", sizeof buf); + } else { + if (repl_beginning && repl_could_be_missing) { + repl_missing = TRUE; + goto hunk_done; + } + fatal("unexpected end of file in patch\n"); + } + } + p_end++; + assert(p_end < hunkmax); + p_char[p_end] = *buf; + p_line[p_end] = Nullch; + switch (*buf) { + case '*': + if (strnEQ(buf, "********", 8)) { + if (repl_beginning && repl_could_be_missing) { + repl_missing = TRUE; + goto hunk_done; + } else + fatal("unexpected end of hunk " + "at line %ld\n", + p_input_line); + } + if (p_end != 0) { + if (repl_beginning && repl_could_be_missing) { + repl_missing = TRUE; + goto hunk_done; + } + fatal("unexpected *** at line %ld: %s", + p_input_line, buf); + } + context = 0; + p_line[p_end] = savestr(buf); + if (out_of_mem) { + p_end--; + return FALSE; + } + for (s = buf; *s && !isdigit(*s); s++) + ; + if (!*s) + malformed(); + if (strnEQ(s, "0,0", 3)) + memmove(s, s + 2, strlen(s + 2) + 1); + p_first = (LINENUM) atol(s); + while (isdigit(*s)) + s++; + if (*s == ',') { + for (; *s && !isdigit(*s); s++); + if (!*s) + malformed(); + p_ptrn_lines = ((LINENUM) atol(s)) - p_first + 1; + } else if (p_first) + p_ptrn_lines = 1; + else { + p_ptrn_lines = 0; + p_first = 1; + } + p_max = p_ptrn_lines + 6; /* we need this much at + * least */ + while (p_max >= hunkmax) + grow_hunkmax(); + p_max = hunkmax; + break; + case '-': + if (buf[1] == '-') { + if (repl_beginning || + (p_end != p_ptrn_lines + 1 + + (p_char[p_end - 1] == '\n'))) { + 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 { + if (repl_beginning) { + if (repl_could_be_missing) { + repl_missing = TRUE; + goto hunk_done; + } + fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n", + p_input_line, p_hunk_beg + repl_beginning); + } else { + fatal("%s \"---\" at line %ld--check line numbers at line %ld\n", + (p_end <= p_ptrn_lines + ? "Premature" + : "Overdue"), + p_input_line, p_hunk_beg); + } + } + } + repl_beginning = p_end; + repl_backtrack_position = ftell(pfp); + repl_patch_line = p_input_line; + p_line[p_end] = savestr(buf); + if (out_of_mem) { + p_end--; + return FALSE; + } + p_char[p_end] = '='; + for (s = buf; *s && !isdigit(*s); s++) + ; + if (!*s) + malformed(); + p_newfirst = (LINENUM) atol(s); + while (isdigit(*s)) + s++; + if (*s == ',') { + for (; *s && !isdigit(*s); s++) + ; + if (!*s) + malformed(); + 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; + if (p_max > MAXHUNKSIZE) + fatal("hunk too large (%ld lines) at line %ld: %s", + p_max, p_input_line, buf); + while (p_max >= hunkmax) + grow_hunkmax(); + if (p_repl_lines != ptrn_copiable && + (p_context != 0 || p_repl_lines != 1)) + repl_could_be_missing = FALSE; + break; + } + goto change_line; + case '+': + case '!': + repl_could_be_missing = FALSE; + change_line: + if (buf[1] == '\n' && canonicalize) + strlcpy(buf + 1, " \n", sizeof buf - 1); + if (!isspace(buf[1]) && buf[1] != '>' && + buf[1] != '<' && + repl_beginning && repl_could_be_missing) { + repl_missing = TRUE; + goto hunk_done; + } + if (context >= 0) { + if (context < p_context) + p_context = context; + context = -1000; + } + p_line[p_end] = savestr(buf + 2); + if (out_of_mem) { + p_end--; + return FALSE; + } + if (p_end == p_ptrn_lines) { + if (remove_special_line()) { + int len; + + len = strlen(p_line[p_end]) - 1; + (p_line[p_end])[len] = 0; + } + } + break; + case '\t': + case '\n': /* assume the 2 spaces got eaten */ + if (repl_beginning && repl_could_be_missing && + (!ptrn_spaces_eaten || + diff_type == NEW_CONTEXT_DIFF)) { + repl_missing = TRUE; + goto hunk_done; + } + p_line[p_end] = savestr(buf); + if (out_of_mem) { + p_end--; + return FALSE; + } + if (p_end != p_ptrn_lines + 1) { + ptrn_spaces_eaten |= (repl_beginning != 0); + context++; + if (!repl_beginning) + ptrn_copiable++; + p_char[p_end] = ' '; + } + break; + case ' ': + if (!isspace(buf[1]) && + repl_beginning && repl_could_be_missing) { + repl_missing = TRUE; + goto hunk_done; + } + context++; + if (!repl_beginning) + ptrn_copiable++; + p_line[p_end] = savestr(buf + 2); + if (out_of_mem) { + p_end--; + return FALSE; + } + break; + default: + if (repl_beginning && repl_could_be_missing) { + repl_missing = TRUE; + goto hunk_done; + } + malformed(); + } + /* 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; + } - while (p_end >= 0) { - if (p_end == p_efake) - p_end = p_bfake; /* don't free twice */ - else - free(p_line[p_end]); - p_end--; - } - assert(p_end == -1); - p_efake = -1; +hunk_done: + if (p_end >= 0 && !repl_beginning) + fatal("no --- found in patch at line %ld\n", pch_hunk_beg()); - p_max = hunkmax; /* gets reduced when --- found */ - if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) { - long line_beginning = ftell(pfp); - /* file pos of the current line */ - LINENUM repl_beginning = 0; /* index of --- line */ - LINENUM fillcnt = 0; /* #lines of missing ptrn or repl */ - LINENUM fillsrc; /* index of first line to copy */ - LINENUM filldst; /* index of first missing line */ - bool ptrn_spaces_eaten = FALSE; /* ptrn was slightly misformed */ - bool repl_could_be_missing = TRUE; - /* no + or ! lines in this hunk */ - bool repl_missing = FALSE; /* we are now backtracking */ - long repl_backtrack_position = 0; - /* file pos of first repl line */ - LINENUM repl_patch_line; /* input line number for same */ - LINENUM ptrn_copiable = 0; - /* # of copiable lines in ptrn */ + if (repl_missing) { - ret = pgets(buf, sizeof buf, pfp); - p_input_line++; - if (ret == Nullch || strnNE(buf, "********", 8)) { - next_intuit_at(line_beginning,p_input_line); - return FALSE; - } - p_context = 100; - p_hunk_beg = p_input_line + 1; - while (p_end < p_max) { - line_beginning = ftell(pfp); - ret = pgets(buf, sizeof buf, pfp); - p_input_line++; - if (ret == Nullch) { - if (p_max - p_end < 4) { - /* assume blank lines got chopped */ - strlcpy(buf, " \n", sizeof buf); - } else { - if (repl_beginning && repl_could_be_missing) { - repl_missing = TRUE; - goto hunk_done; - } - fatal("unexpected end of file in patch\n"); + /* reset state back to just after --- */ + p_input_line = repl_patch_line; + for (p_end--; p_end > repl_beginning; p_end--) + free(p_line[p_end]); + fseek(pfp, repl_backtrack_position, 0); + + /* redundant 'new' context lines were omitted - set */ + /* up to fill them in from the old file context */ + if (!p_context && p_repl_lines == 1) { + p_repl_lines = 0; + p_max--; + } + fillsrc = 1; + filldst = repl_beginning + 1; + fillcnt = p_repl_lines; + p_end = p_max; + } else if (!p_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_end++; - assert(p_end < hunkmax); - p_char[p_end] = *buf; -#ifdef zilog - p_line[(short)p_end] = Nullch; -#else - p_line[p_end] = Nullch; + if (diff_type == CONTEXT_DIFF && + (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) { + if (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 = 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 && p_char[fillsrc] != ' ') + fillsrc++; + if (fillsrc > p_end) + fatal("replacement text or line numbers mangled in hunk at line %ld\n", + 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 && + p_char[fillsrc] != ' ') + fillsrc++; +#ifdef DEBUGGING + if (debug & 64) + printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n", + fillsrc, filldst, repl_beginning, p_end + 1); #endif - switch (*buf) { - case '*': - if (strnEQ(buf, "********", 8)) { - if (repl_beginning && repl_could_be_missing) { - repl_missing = TRUE; - goto hunk_done; - } - else - fatal("unexpected end of hunk at line %ld\n", - p_input_line); + assert(fillsrc == p_end + 1 || fillsrc == repl_beginning); + assert(filldst == p_end + 1 || filldst == repl_beginning); } - if (p_end != 0) { - if (repl_beginning && repl_could_be_missing) { - repl_missing = TRUE; - goto hunk_done; - } - fatal("unexpected *** at line %ld: %s", p_input_line, buf); + if (p_line[p_end] != NULL) { + if (remove_special_line()) { + p_len[p_end] -= 1; + (p_line[p_end])[p_len[p_end]] = 0; + } } - context = 0; - p_line[p_end] = savestr(buf); - if (out_of_mem) { - p_end--; - return FALSE; + } else if (diff_type == UNI_DIFF) { + long line_beginning = ftell(pfp); /* file pos of the current line */ + LINENUM fillsrc; /* index of old lines */ + LINENUM filldst; /* index of new lines */ + char ch; + + ret = pgets(buf, sizeof buf, pfp); + p_input_line++; + if (ret == Nullch || strnNE(buf, "@@ -", 4)) { + next_intuit_at(line_beginning, p_input_line); + return FALSE; } - for (s=buf; *s && !isdigit(*s); s++) ; + s = buf + 4; if (!*s) - malformed (); - if (strnEQ(s,"0,0",3)) - memmove(s, s+2, strlen(s+2)+1); + malformed(); p_first = (LINENUM) atol(s); - while (isdigit(*s)) s++; + while (isdigit(*s)) + s++; if (*s == ',') { - for (; *s && !isdigit(*s); s++) ; - if (!*s) - malformed (); - p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1; + 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 */ + p_max = p_ptrn_lines + p_repl_lines + 1; + while (p_max >= hunkmax) + grow_hunkmax(); + fillsrc = 1; + filldst = fillsrc + p_ptrn_lines; + p_end = filldst + p_repl_lines; + snprintf(buf, sizeof buf, "*** %ld,%ld ****\n", p_first, + p_first + p_ptrn_lines - 1); + p_line[0] = savestr(buf); + if (out_of_mem) { + p_end = -1; + return FALSE; } - else if (p_first) - p_ptrn_lines = 1; - else { - p_ptrn_lines = 0; - p_first = 1; + p_char[0] = '*'; + snprintf(buf, sizeof buf, "--- %ld,%ld ----\n", p_newfirst, + p_newfirst + p_repl_lines - 1); + p_line[filldst] = savestr(buf); + if (out_of_mem) { + p_end = 0; + return FALSE; } - p_max = p_ptrn_lines + 6; /* we need this much at least */ - while (p_max >= hunkmax) - grow_hunkmax(); - p_max = hunkmax; - break; - case '-': - if (buf[1] == '-') { - if (repl_beginning || - (p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n'))) - { - 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; + p_char[filldst++] = '='; + p_context = 100; + context = 0; + p_hunk_beg = p_input_line + 1; + while (fillsrc <= p_ptrn_lines || filldst <= p_end) { + line_beginning = ftell(pfp); + ret = pgets(buf, sizeof buf, pfp); + p_input_line++; + if (ret == Nullch) { + if (p_max - filldst < 3) { + /* assume blank lines got chopped */ + strlcpy(buf, " \n", sizeof buf); + } else { + fatal("unexpected end of file in patch\n"); + } + } + if (*buf == '\t' || *buf == '\n') { + ch = ' '; /* assume the space got eaten */ + s = savestr(buf); + } else { + ch = *buf; + s = savestr(buf + 1); } - else { - if (repl_beginning) { - if (repl_could_be_missing){ - repl_missing = TRUE; - goto hunk_done; + if (out_of_mem) { + while (--filldst > p_ptrn_lines) + free(p_line[filldst]); + p_end = fillsrc - 1; + return FALSE; + } + switch (ch) { + case '-': + if (fillsrc > p_ptrn_lines) { + free(s); + p_end = filldst - 1; + malformed(); + } + p_char[fillsrc] = ch; + p_line[fillsrc] = s; + p_len[fillsrc++] = strlen(s); + if (fillsrc > p_ptrn_lines) { + if (remove_special_line()) { + p_len[fillsrc - 1] -= 1; + s[p_len[fillsrc - 1]] = 0; + } + } + 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++; + p_char[fillsrc] = ch; + p_line[fillsrc] = s; + p_len[fillsrc++] = strlen(s); + s = savestr(s); + if (out_of_mem) { + while (--filldst > p_ptrn_lines) + free(p_line[filldst]); + p_end = fillsrc - 1; + return FALSE; + } + /* FALL THROUGH */ + case '+': + if (filldst > p_end) { + free(s); + while (--filldst > p_ptrn_lines) + free(p_line[filldst]); + p_end = fillsrc - 1; + malformed(); + } + p_char[filldst] = ch; + p_line[filldst] = s; + p_len[filldst++] = strlen(s); + if (fillsrc > p_ptrn_lines) { + if (remove_special_line()) { + p_len[filldst - 1] -= 1; + s[p_len[filldst - 1]] = 0; + } } - fatal( -"duplicate \"---\" at line %ld--check line numbers at line %ld\n", - p_input_line, p_hunk_beg + repl_beginning); - } - else { - fatal( -"%s \"---\" at line %ld--check line numbers at line %ld\n", - (p_end <= p_ptrn_lines - ? "Premature" - : "Overdue" ), - p_input_line, p_hunk_beg); - } + break; + default: + p_end = filldst; + malformed(); } - } - repl_beginning = p_end; - repl_backtrack_position = ftell(pfp); - repl_patch_line = p_input_line; - p_line[p_end] = savestr(buf); - if (out_of_mem) { - p_end--; + if (ch != ' ' && context > 0) { + if (context < p_context) + p_context = context; + context = -1000; + } + } /* while */ + } else { /* normal diff--fake it up */ + char hunk_type; + 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, p_input_line); return FALSE; - } - p_char[p_end] = '='; - for (s=buf; *s && !isdigit(*s); s++) ; - if (!*s) - malformed (); - p_newfirst = (LINENUM) atol(s); - while (isdigit(*s)) s++; - if (*s == ',') { - for (; *s && !isdigit(*s); s++) ; - if (!*s) - malformed (); - 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; - if (p_max > MAXHUNKSIZE) + } + 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; + if (p_end > MAXHUNKSIZE) fatal("hunk too large (%ld lines) at line %ld: %s", - p_max, p_input_line, buf); - while (p_max >= hunkmax) + p_end, p_input_line, buf); + while (p_end >= hunkmax) grow_hunkmax(); - if (p_repl_lines != ptrn_copiable - && (p_context != 0 || p_repl_lines != 1)) - repl_could_be_missing = FALSE; - break; - } - goto change_line; - case '+': case '!': - repl_could_be_missing = FALSE; - change_line: - if (buf[1] == '\n' && canonicalize) - strlcpy(buf+1," \n", sizeof buf -1); - if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' && - repl_beginning && repl_could_be_missing) { - repl_missing = TRUE; - goto hunk_done; - } - if (context >= 0) { - if (context < p_context) - p_context = context; - context = -1000; - } - p_line[p_end] = savestr(buf+2); + p_newfirst = min; + p_repl_lines = max - min + 1; + snprintf(buf, sizeof buf, "*** %ld,%ld\n", p_first, + p_first + p_ptrn_lines - 1); + p_line[0] = savestr(buf); if (out_of_mem) { - p_end--; - return FALSE; + p_end = -1; + return FALSE; } - if (p_end == p_ptrn_lines) { - if (remove_special_line()) { - int len; - - len = strlen(p_line[p_end]) - 1; - (p_line[p_end])[len] = 0; + 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 %ld\n", + p_input_line); + if (*buf != '<') + fatal("< expected at line %ld of patch\n", + p_input_line); + p_line[i] = savestr(buf + 2); + if (out_of_mem) { + p_end = i - 1; + return FALSE; } + p_len[i] = strlen(p_line[i]); + p_char[i] = '-'; } - break; - case '\t': case '\n': /* assume the 2 spaces got eaten */ - if (repl_beginning && repl_could_be_missing && - (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF) ) { - repl_missing = TRUE; - goto hunk_done; - } - p_line[p_end] = savestr(buf); - if (out_of_mem) { - p_end--; - return FALSE; - } - if (p_end != p_ptrn_lines + 1) { - ptrn_spaces_eaten |= (repl_beginning != 0); - context++; - if (!repl_beginning) - ptrn_copiable++; - p_char[p_end] = ' '; - } - break; - case ' ': - if (!isspace(buf[1]) && - repl_beginning && repl_could_be_missing) { - repl_missing = TRUE; - goto hunk_done; - } - context++; - if (!repl_beginning) - ptrn_copiable++; - p_line[p_end] = savestr(buf+2); - if (out_of_mem) { - p_end--; - return FALSE; - } - break; - default: - if (repl_beginning && repl_could_be_missing) { - repl_missing = TRUE; - goto hunk_done; - } - malformed (); - } - /* 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; - } - - hunk_done: - if (p_end >=0 && !repl_beginning) - fatal("no --- found in patch at line %ld\n", pch_hunk_beg()); - - if (repl_missing) { - - /* reset state back to just after --- */ - p_input_line = repl_patch_line; - for (p_end--; p_end > repl_beginning; p_end--) - free(p_line[p_end]); - fseek(pfp, repl_backtrack_position, 0); - /* redundant 'new' context lines were omitted - set */ - /* up to fill them in from the old file context */ - if (!p_context && p_repl_lines == 1) { - p_repl_lines = 0; - p_max--; - } - fillsrc = 1; - filldst = repl_beginning+1; - fillcnt = p_repl_lines; - p_end = p_max; - } - else if (!p_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; - } - - if (diff_type == CONTEXT_DIFF && - (fillcnt || (p_first > 1 && ptrn_copiable > 2*p_context)) ) { - if (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 = 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 && p_char[fillsrc] != ' ') - fillsrc++; - if (fillsrc > p_end) - fatal("replacement text or line numbers mangled in hunk at line %ld\n", - 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 && - p_char[fillsrc] != ' ') - fillsrc++; -#ifdef DEBUGGING - if (debug & 64) - printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n", - fillsrc,filldst,repl_beginning,p_end+1); -#endif - assert(fillsrc==p_end+1 || fillsrc==repl_beginning); - assert(filldst==p_end+1 || filldst==repl_beginning); - } - if (p_line[p_end] != NULL) { if (remove_special_line()) { - p_len[p_end] -= 1; - (p_line[p_end])[p_len[p_end]] = 0; + p_len[i - 1] -= 1; + (p_line[i - 1])[p_len[i - 1]] = 0; } - } - } - else if (diff_type == UNI_DIFF) { - long line_beginning = ftell(pfp); - /* file pos of the current line */ - LINENUM fillsrc; /* index of old lines */ - LINENUM filldst; /* index of new lines */ - char ch; - - ret = pgets(buf, sizeof buf, pfp); - p_input_line++; - if (ret == Nullch || strnNE(buf, "@@ -", 4)) { - next_intuit_at(line_beginning,p_input_line); - return FALSE; - } - 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 */ - p_max = p_ptrn_lines + p_repl_lines + 1; - while (p_max >= hunkmax) - grow_hunkmax(); - fillsrc = 1; - filldst = fillsrc + p_ptrn_lines; - p_end = filldst + p_repl_lines; - snprintf(buf, sizeof buf, "*** %ld,%ld ****\n", p_first, - p_first + p_ptrn_lines - 1); - p_line[0] = savestr(buf); - if (out_of_mem) { - p_end = -1; - return FALSE; - } - p_char[0] = '*'; - snprintf(buf, sizeof buf, "--- %ld,%ld ----\n", p_newfirst, - p_newfirst + p_repl_lines - 1); - p_line[filldst] = savestr(buf); - if (out_of_mem) { - p_end = 0; - return FALSE; - } - p_char[filldst++] = '='; - p_context = 100; - context = 0; - p_hunk_beg = p_input_line + 1; - while (fillsrc <= p_ptrn_lines || filldst <= p_end) { - line_beginning = ftell(pfp); - ret = pgets(buf, sizeof buf, pfp); - p_input_line++; - if (ret == Nullch) { - if (p_max - filldst < 3) { - /* assume blank lines got chopped */ - strlcpy(buf, " \n", sizeof buf); - } else { - fatal("unexpected end of file in patch\n"); - } - } - if (*buf == '\t' || *buf == '\n') { - ch = ' '; /* assume the space got eaten */ - s = savestr(buf); - } - else { - ch = *buf; - s = savestr(buf+1); - } - if (out_of_mem) { - while (--filldst > p_ptrn_lines) - free(p_line[filldst]); - p_end = fillsrc-1; - return FALSE; - } - switch (ch) { - case '-': - if (fillsrc > p_ptrn_lines) { - free(s); - p_end = filldst-1; - malformed (); - } - p_char[fillsrc] = ch; - p_line[fillsrc] = s; - p_len[fillsrc++] = strlen(s); - if (fillsrc > p_ptrn_lines) { - if (remove_special_line()) { - p_len[fillsrc - 1] -= 1; - s[p_len[fillsrc - 1]] = 0; - } + 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 %ld\n", + p_input_line); + if (*buf != '-') + fatal("--- expected at line %ld of patch\n", + p_input_line); } - 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++; - p_char[fillsrc] = ch; - p_line[fillsrc] = s; - p_len[fillsrc++] = strlen(s); - s = savestr(s); + snprintf(buf, sizeof(buf), "--- %ld,%ld\n", min, max); + p_line[i] = savestr(buf); if (out_of_mem) { - while (--filldst > p_ptrn_lines) - free(p_line[filldst]); - p_end = fillsrc-1; - return FALSE; - } - /* FALL THROUGH */ - case '+': - if (filldst > p_end) { - free(s); - while (--filldst > p_ptrn_lines) - free(p_line[filldst]); - p_end = fillsrc-1; - malformed (); + p_end = i - 1; + return FALSE; } - p_char[filldst] = ch; - p_line[filldst] = s; - p_len[filldst++] = strlen(s); - if (fillsrc > p_ptrn_lines) { - if (remove_special_line()) { - p_len[filldst - 1] -= 1; - s[p_len[filldst - 1]] = 0; + 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 %ld\n", + p_input_line); + if (*buf != '>') + fatal("> expected at line %ld of patch\n", + p_input_line); + p_line[i] = savestr(buf + 2); + if (out_of_mem) { + p_end = i - 1; + return FALSE; } + p_len[i] = strlen(p_line[i]); + p_char[i] = '+'; } - break; - default: - p_end = filldst; - malformed (); - } - if (ch != ' ' && context > 0) { - if (context < p_context) - p_context = context; - context = -1000; - } - }/* while */ - } - else { /* normal diff--fake it up */ - char hunk_type; - 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,p_input_line); - 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; - if (p_end > MAXHUNKSIZE) - fatal("hunk too large (%ld lines) at line %ld: %s", - p_end, p_input_line, buf); - while (p_end >= hunkmax) - grow_hunkmax(); - p_newfirst = min; - p_repl_lines = max - min + 1; - snprintf(buf, sizeof buf, "*** %ld,%ld\n", p_first, - p_first + p_ptrn_lines - 1); - p_line[0] = savestr(buf); - if (out_of_mem) { - p_end = -1; - return FALSE; - } - 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 %ld\n", - p_input_line); - if (*buf != '<') - fatal("< expected at line %ld of patch\n", p_input_line); - p_line[i] = savestr(buf+2); - if (out_of_mem) { - p_end = i-1; - return FALSE; - } - p_len[i] = strlen(p_line[i]); - p_char[i] = '-'; - } - - if (remove_special_line()) { - p_len[i - 1] -= 1; - (p_line[i - 1])[p_len[i - 1]] = 0; - } - - 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 %ld\n", - p_input_line); - if (*buf != '-') - fatal("--- expected at line %ld of patch\n", p_input_line); - } - snprintf(buf, sizeof(buf), "--- %ld,%ld\n", min, max); - p_line[i] = savestr(buf); - if (out_of_mem) { - p_end = i-1; - return FALSE; - } - 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 %ld\n", - p_input_line); - if (*buf != '>') - fatal("> expected at line %ld of patch\n", p_input_line); - p_line[i] = savestr(buf+2); - if (out_of_mem) { - p_end = i-1; - return FALSE; - } - p_len[i] = strlen(p_line[i]); - p_char[i] = '+'; - } - - if (remove_special_line()) { - p_len[i - 1] -= 1; - (p_line[i - 1])[p_len[i - 1]] = 0; + if (remove_special_line()) { + p_len[i - 1] -= 1; + (p_line[i - 1])[p_len[i - 1]] = 0; + } } - } - if (reverse) /* backwards patch? */ - if (!pch_swap()) - say("Not enough memory to swap next hunk!\n"); + if (reverse) /* backwards patch? */ + if (!pch_swap()) + say("Not enough memory to swap next hunk!\n"); #ifdef DEBUGGING - if (debug & 2) { - int i; - char special; - - for (i=0; i <= p_end; i++) { - if (i == p_ptrn_lines) - special = '^'; - else - special = ' '; - fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]); - fflush(stderr); + if (debug & 2) { + int i; + char special; + + for (i = 0; i <= p_end; i++) { + if (i == p_ptrn_lines) + special = '^'; + else + special = ' '; + fprintf(stderr, "%3d %c %c %s", i, p_char[i], + special, p_line[i]); + fflush(stderr); + } } - } #endif - if (p_end+1 < hunkmax) /* paranoia reigns supreme... */ - p_char[p_end+1] = '^'; /* add a stopper for apply_hunk */ - return TRUE; + if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */ + p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */ + return TRUE; } -/* Input a line from the patch file, worrying about indentation. */ - +/* + * Input a line from the patch file, worrying about indentation. + */ char * -pgets(bf,sz,fp) -char *bf; -int sz; -FILE *fp; +pgets(char *bf, int sz, FILE *fp) { - char *ret = fgets(bf, sz, fp); - char *s; - int indent = 0; - - if (p_indent && ret != Nullch) { - for (s=buf; - indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); s++) { - if (*s == '\t') - indent += 8 - (indent % 7); - else - indent++; + char *s, *ret = fgets(bf, sz, fp); + int indent = 0; + + if (p_indent && ret != Nullch) { + for (s = buf; + indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); + s++) { + if (*s == '\t') + indent += 8 - (indent % 7); + else + indent++; + } + if (buf != s && strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) + fatal("buffer too small in pgets()\n"); } - if (buf != s && strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) - fatal("buffer too small in pgets()\n"); - } - return ret; + return ret; } -/* Reverse the old and new portions of the current hunk. */ - +/* + * Reverse the old and new portions of the current hunk. + */ bool -pch_swap() +pch_swap(void) { - char **tp_line; /* the text of the hunk */ - short *tp_len; /* length of each line */ - char *tp_char; /* +, -, and ! */ - LINENUM i; - LINENUM n; - bool blankline = FALSE; - char *s; - - i = p_first; - p_first = p_newfirst; - p_newfirst = i; - - /* make a scratch copy */ - - tp_line = p_line; - tp_len = p_len; - tp_char = p_char; - p_line = Null(char**); /* force set_hunkmax to allocate again */ - p_len = Null(short*); - p_char = Nullch; - set_hunkmax(); - if (p_line == Null(char**) || p_len == Null(short*) || p_char == Nullch) { + char **tp_line; /* the text of the hunk */ + short *tp_len; /* length of each line */ + char *tp_char; /* +, -, and ! */ + LINENUM i; + LINENUM n; + bool blankline = FALSE; + char *s; + + i = p_first; + p_first = p_newfirst; + p_newfirst = i; + + /* make a scratch copy */ + + tp_line = p_line; + tp_len = p_len; + tp_char = p_char; + p_line = Null(char **); /* force set_hunkmax to allocate again */ + p_len = Null(short *); + p_char = Nullch; + set_hunkmax(); + if (p_line == Null(char **) ||p_len == Null(short *) ||p_char == Nullch) { #ifndef lint - if (p_line == Null(char**)) - free((char*)p_line); - p_line = tp_line; - if (p_len == Null(short*)) - free((char*)p_len); - p_len = tp_len; + if (p_line == Null(char **)) + free((char *) p_line); + p_line = tp_line; + if (p_len == Null(short *)) + free((char *) p_len); + p_len = tp_len; #endif - if (p_char == Nullch) - free((char*)p_char); - p_char = tp_char; - return FALSE; /* not enough memory to swap hunk! */ - } - - /* now turn the new into the old */ + if (p_char == Nullch) + free((char *) p_char); + p_char = tp_char; + return FALSE; /* not enough memory to swap hunk! */ + } + /* 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++; - } - if (p_efake >= 0) { /* fix non-freeable ptr range */ - if (p_efake <= i) - n = p_end - i + 1; - else - n = -i; - p_efake += n; - p_bfake += n; - } - 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; + if (tp_char[i] == '\n') { /* account for possible blank line */ + blankline = TRUE; + i++; + } + if (p_efake >= 0) { /* fix non-freeable ptr range */ + if (p_efake <= i) + n = p_end - i + 1; + else + n = -i; + p_efake += n; + p_bfake += n; + } + 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; #ifndef lint - if (tp_line == Null(char**)) - free((char*)tp_line); - if (tp_len == Null(short*)) - free((char*)tp_len); + if (tp_line == Null(char **)) + free((char *) tp_line); + if (tp_len == Null(short *)) + free((char *) tp_len); #endif - if (tp_char == Nullch) - free((char*)tp_char); - return TRUE; + if (tp_char == Nullch) + free((char *) tp_char); + return TRUE; } -/* Return the specified line position in the old file of the old context. */ - +/* + * Return the specified line position in the old file of the old context. + */ LINENUM -pch_first() +pch_first(void) { - return p_first; + return p_first; } -/* Return the number of lines of old context. */ - +/* + * Return the number of lines of old context. + */ LINENUM -pch_ptrn_lines() +pch_ptrn_lines(void) { - return p_ptrn_lines; + return p_ptrn_lines; } -/* Return the probable line position in the new file of the first line. */ - +/* + * Return the probable line position in the new file of the first line. + */ LINENUM -pch_newfirst() +pch_newfirst(void) { - return p_newfirst; + return p_newfirst; } -/* Return the number of lines in the replacement text including context. */ - +/* + * Return the number of lines in the replacement text including context. + */ LINENUM -pch_repl_lines() +pch_repl_lines(void) { - return p_repl_lines; + return p_repl_lines; } -/* Return the number of lines in the whole hunk. */ - +/* + * Return the number of lines in the whole hunk. + */ LINENUM -pch_end() +pch_end(void) { - return p_end; + return p_end; } -/* Return the number of context lines before the first changed line. */ - +/* + * Return the number of context lines before the first changed line. + */ LINENUM -pch_context() +pch_context(void) { - return p_context; + return p_context; } -/* Return the length of a particular patch line. */ - +/* + * Return the length of a particular patch line. + */ short -pch_line_len(line) -LINENUM line; +pch_line_len(LINENUM line) { - return p_len[line]; + return p_len[line]; } -/* Return the control character (+, -, *, !, etc) for a patch line. */ - +/* + * Return the control character (+, -, *, !, etc) for a patch line. + */ char -pch_char(line) -LINENUM line; +pch_char(LINENUM line) { - return p_char[line]; + return p_char[line]; } -/* Return a pointer to a particular patch line. */ - +/* + * Return a pointer to a particular patch line. + */ char * -pfetch(line) -LINENUM line; +pfetch(LINENUM line) { - return p_line[line]; + return p_line[line]; } -/* Return where in the patch file this hunk began, for error messages. */ - +/* + * Return where in the patch file this hunk began, for error messages. + */ LINENUM -pch_hunk_beg() +pch_hunk_beg(void) { - return p_hunk_beg; + return p_hunk_beg; } -/* Apply an ed script by feeding ed itself. */ - +/* + * Apply an ed script by feeding ed itself. + */ void -do_ed_script() +do_ed_script(void) { - char *t; - long beginning_of_this_line; - bool this_line_is_command = FALSE; - FILE *pipefp; - - if (!skip_rest_of_patch) { - unlink(TMPOUTNAME); - copy_file(filearg[0], TMPOUTNAME); - if (verbose) - snprintf(buf, sizeof buf, "/bin/ed %s", TMPOUTNAME); - else - snprintf(buf, sizeof buf, "/bin/ed - %s", TMPOUTNAME); - pipefp = popen(buf, "w"); - } - for (;;) { - beginning_of_this_line = ftell(pfp); - if (pgets(buf, sizeof buf, pfp) == Nullch) { - next_intuit_at(beginning_of_this_line,p_input_line); - break; + char *t; + long beginning_of_this_line; + bool this_line_is_command = FALSE; + FILE *pipefp; + + if (!skip_rest_of_patch) { + unlink(TMPOUTNAME); + copy_file(filearg[0], TMPOUTNAME); + if (verbose) + snprintf(buf, sizeof buf, "/bin/ed %s", TMPOUTNAME); + else + snprintf(buf, sizeof buf, "/bin/ed - %s", TMPOUTNAME); + pipefp = popen(buf, "w"); } - p_input_line++; - for (t=buf; isdigit(*t) || *t == ','; t++) ; - this_line_is_command = (isdigit(*buf) && - (*t == 'd' || *t == 'c' || *t == 'a') ); - if (this_line_is_command) { - if (!skip_rest_of_patch) - fputs(buf, pipefp); - if (*t != 'd') { - while (pgets(buf, sizeof buf, pfp) != Nullch) { - p_input_line++; - if (!skip_rest_of_patch) - fputs(buf, pipefp); - if (strEQ(buf, ".\n")) + for (;;) { + beginning_of_this_line = ftell(pfp); + if (pgets(buf, sizeof buf, pfp) == Nullch) { + next_intuit_at(beginning_of_this_line, p_input_line); + break; + } + p_input_line++; + for (t = buf; isdigit(*t) || *t == ','; t++); + this_line_is_command = (isdigit(*buf) && + (*t == 'd' || *t == 'c' || *t == 'a')); + if (this_line_is_command) { + if (!skip_rest_of_patch) + fputs(buf, pipefp); + if (*t != 'd') { + while (pgets(buf, sizeof buf, pfp) != Nullch) { + p_input_line++; + if (!skip_rest_of_patch) + fputs(buf, pipefp); + if (strEQ(buf, ".\n")) + break; + } + } + } else { + next_intuit_at(beginning_of_this_line, p_input_line); break; } - } - } - else { - next_intuit_at(beginning_of_this_line,p_input_line); - break; } - } - if (skip_rest_of_patch) - return; - fprintf(pipefp, "w\n"); - fprintf(pipefp, "q\n"); - fflush(pipefp); - pclose(pipefp); - ignore_signals(); - if (!check_only) { - if (move_file(TMPOUTNAME, outname) < 0) { - toutkeep = TRUE; - chmod(TMPOUTNAME, filemode); + if (skip_rest_of_patch) + return; + fprintf(pipefp, "w\n"); + fprintf(pipefp, "q\n"); + fflush(pipefp); + pclose(pipefp); + ignore_signals(); + if (!check_only) { + if (move_file(TMPOUTNAME, outname) < 0) { + toutkeep = TRUE; + chmod(TMPOUTNAME, filemode); + } else + chmod(outname, filemode); } - else - chmod(outname, filemode); - } - set_signals(1); + set_signals(1); } diff --git a/usr.bin/patch/pch.h b/usr.bin/patch/pch.h index 0e26355b67a..a07bc914d4c 100644 --- a/usr.bin/patch/pch.h +++ b/usr.bin/patch/pch.h @@ -1,27 +1,27 @@ -/* $OpenBSD: pch.h,v 1.3 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: pch.h,v 1.4 2003/07/21 14:00:41 deraadt Exp $ */ -EXT FILE *pfp INIT(Nullfp); /* patch file pointer */ +EXT FILE *pfp INIT(Nullfp); /* patch file pointer */ -void re_patch(void); -void open_patch_file(char *); -void set_hunkmax(void); -void grow_hunkmax(void); -bool there_is_another_patch(void); -int intuit_diff_type(void); -void next_intuit_at(long, long); -void skip_to(long, long); -bool another_hunk(void); -bool pch_swap(void); -char *pfetch(LINENUM); -short pch_line_len(LINENUM); -LINENUM pch_first(void); -LINENUM pch_ptrn_lines(void); -LINENUM pch_newfirst(void); -LINENUM pch_repl_lines(void); -LINENUM pch_end(void); -LINENUM pch_context(void); -LINENUM pch_hunk_beg(void); -char pch_char(LINENUM); -char *pfetch(LINENUM); -char *pgets(char *, int, FILE *); -void do_ed_script(void); +void re_patch(void); +void open_patch_file(char *); +void set_hunkmax(void); +void grow_hunkmax(void); +bool there_is_another_patch(void); +int intuit_diff_type(void); +void next_intuit_at(long, long); +void skip_to(long, long); +bool another_hunk(void); +bool pch_swap(void); +char *pfetch(LINENUM); +short pch_line_len(LINENUM); +LINENUM pch_first(void); +LINENUM pch_ptrn_lines(void); +LINENUM pch_newfirst(void); +LINENUM pch_repl_lines(void); +LINENUM pch_end(void); +LINENUM pch_context(void); +LINENUM pch_hunk_beg(void); +char pch_char(LINENUM); +char *pfetch(LINENUM); +char *pgets(char *, int, FILE *); +void do_ed_script(void); diff --git a/usr.bin/patch/util.c b/usr.bin/patch/util.c index 91cc68bbe48..7074bf3c5d3 100644 --- a/usr.bin/patch/util.c +++ b/usr.bin/patch/util.c @@ -1,8 +1,8 @@ -/* $OpenBSD: util.c,v 1.12 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: util.c,v 1.13 2003/07/21 14:00:41 deraadt Exp $ */ #ifndef lint -static char rcsid[] = "$OpenBSD: util.c,v 1.12 2003/07/18 02:00:09 deraadt Exp $"; -#endif /* not lint */ +static char rcsid[] = "$OpenBSD: util.c,v 1.13 2003/07/21 14:00:41 deraadt Exp $"; +#endif /* not lint */ #include "EXTERN.h" #include "common.h" @@ -10,397 +10,391 @@ static char rcsid[] = "$OpenBSD: util.c,v 1.12 2003/07/18 02:00:09 deraadt Exp $ #include "util.h" #include "backupfile.h" -void my_exit(int) __attribute__((noreturn)); +void my_exit(int) __attribute__((noreturn)); /* Rename a file, copying it if necessary. */ int -move_file(from,to) -char *from, *to; +move_file(char *from, char *to) { - char bakname[MAXPATHLEN]; - char *s; - int i; - int fromfd; + char bakname[MAXPATHLEN], *s; + int i, fromfd; - /* to stdout? */ + /* to stdout? */ - if (strEQ(to, "-")) { + if (strEQ(to, "-")) { #ifdef DEBUGGING - if (debug & 4) - say("Moving %s to stdout.\n", from); + if (debug & 4) + say("Moving %s to stdout.\n", from); #endif - fromfd = open(from, O_RDONLY); - if (fromfd < 0) - pfatal("internal error, can't reopen %s", from); - while ((i=read(fromfd, buf, sizeof buf)) > 0) - if (write(1, buf, i) != 1) - pfatal("write failed"); - close(fromfd); - return 0; - } - - if (origprae) { - if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) || - strlcat(bakname, to, sizeof(bakname)) >= sizeof(bakname)) - fatal("filename %s too long for buffer\n", origprae); - } else { -#ifndef NODIR - char *backupname = find_backup_file_name(to); - if (backupname == (char *) 0) - fatal("out of memory\n"); - if (strlcpy(bakname, backupname, sizeof(bakname)) >= sizeof(bakname)) - fatal("filename %s too long for buffer\n", backupname); - free(backupname); -#else /* NODIR */ - if (strlcpy(bakname, to, sizeof(bakname)) >= sizeof(bakname) || - strlcat(bakname, simple_backup_suffix, sizeof(bakname)) >= sizeof(bakname)) - fatal("filename %s too long for buffer\n", to); -#endif /* NODIR */ - } - - if (stat(to, &filestat) == 0) { /* output file exists */ - dev_t to_device = filestat.st_dev; - ino_t to_inode = filestat.st_ino; - char *simplename = bakname; - - for (s=bakname; *s; s++) { - if (*s == '/') - simplename = s+1; + fromfd = open(from, O_RDONLY); + if (fromfd < 0) + pfatal("internal error, can't reopen %s", from); + while ((i = read(fromfd, buf, sizeof buf)) > 0) + if (write(1, buf, i) != 1) + pfatal("write failed"); + close(fromfd); + return 0; } - /* Find a backup name that is not the same file. - Change the first lowercase char into uppercase; - if that isn't sufficient, chop off the first char and try again. */ - while (stat(bakname, &filestat) == 0 && - to_device == filestat.st_dev && to_inode == filestat.st_ino) { - /* Skip initial non-lowercase chars. */ - for (s=simplename; *s && !islower(*s); s++) ; - if (*s) - *s = toupper(*s); - else - memmove(simplename, simplename+1, strlen(simplename+1)+1); + if (origprae) { + if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) || + strlcat(bakname, to, sizeof(bakname)) >= sizeof(bakname)) + fatal("filename %s too long for buffer\n", origprae); + } else { + char *backupname = find_backup_file_name(to); + if (backupname == (char *) 0) + fatal("out of memory\n"); + if (strlcpy(bakname, backupname, sizeof(bakname)) >= sizeof(bakname)) + fatal("filename %s too long for buffer\n", backupname); + free(backupname); } - while (unlink(bakname) >= 0) ; /* while() is for benefit of Eunice */ + + if (stat(to, &filestat) == 0) { /* output file exists */ + dev_t to_device = filestat.st_dev; + ino_t to_inode = filestat.st_ino; + char *simplename = bakname; + + for (s = bakname; *s; s++) { + if (*s == '/') + simplename = s + 1; + } + + /* + * Find a backup name that is not the same file. Change the + * first lowercase char into uppercase; if that isn't + * sufficient, chop off the first char and try again. + */ + while (stat(bakname, &filestat) == 0 && + to_device == filestat.st_dev && to_inode == filestat.st_ino) { + /* Skip initial non-lowercase chars. */ + for (s = simplename; *s && !islower(*s); s++) + ; + if (*s) + *s = toupper(*s); + else + memmove(simplename, simplename + 1, + strlen(simplename + 1) + 1); + } + unlink(bakname); + #ifdef DEBUGGING - if (debug & 4) - say("Moving %s to %s.\n", to, bakname); + if (debug & 4) + say("Moving %s to %s.\n", to, bakname); #endif - if (link(to, bakname) < 0) { - /* Maybe `to' is a symlink into a different file system. - Copying replaces the symlink with a file; using rename - would be better. */ - int tofd; - int bakfd; - - bakfd = creat(bakname, 0666); - if (bakfd < 0) { - say("Can't backup %s, output is in %s: %s\n", to, from, - strerror(errno)); - return -1; - } - tofd = open(to, O_RDONLY); - if (tofd < 0) - pfatal("internal error, can't open %s", to); - while ((i=read(tofd, buf, sizeof buf)) > 0) - if (write(bakfd, buf, i) != i) - pfatal("write failed"); - close(tofd); - close(bakfd); + if (link(to, bakname) < 0) { + /* + * Maybe `to' is a symlink into a different file + * system. Copying replaces the symlink with a file; + * using rename would be better. + */ + int tofd, bakfd; + + bakfd = creat(bakname, 0666); + if (bakfd < 0) { + say("Can't backup %s, output is in %s: %s\n", + to, from, strerror(errno)); + return -1; + } + tofd = open(to, O_RDONLY); + if (tofd < 0) + pfatal("internal error, can't open %s", to); + while ((i = read(tofd, buf, sizeof buf)) > 0) + if (write(bakfd, buf, i) != i) + pfatal("write failed"); + close(tofd); + close(bakfd); + } + unlink(to); } - while (unlink(to) >= 0) ; - } #ifdef DEBUGGING - if (debug & 4) - say("Moving %s to %s.\n", from, to); + if (debug & 4) + say("Moving %s to %s.\n", from, to); #endif - if (link(from, to) < 0) { /* different file system? */ - int tofd; + if (link(from, to) < 0) { /* different file system? */ + int tofd; + + tofd = creat(to, 0666); + if (tofd < 0) { + say("Can't create %s, output is in %s: %s\n", + to, from, strerror(errno)); + return -1; + } + fromfd = open(from, O_RDONLY); + if (fromfd < 0) + pfatal("internal error, can't reopen %s", from); + while ((i = read(fromfd, buf, sizeof buf)) > 0) + if (write(tofd, buf, i) != i) + pfatal("write failed"); + close(fromfd); + close(tofd); + } + unlink(from); + return 0; +} + +/* + * Copy a file. + */ +void +copy_file(char *from, char *to) +{ + int tofd, fromfd, i; tofd = creat(to, 0666); - if (tofd < 0) { - say("Can't create %s, output is in %s: %s\n", - to, from, strerror(errno)); - return -1; - } + if (tofd < 0) + pfatal("can't create %s", to); fromfd = open(from, O_RDONLY); if (fromfd < 0) - pfatal("internal error, can't reopen %s", from); - while ((i=read(fromfd, buf, sizeof buf)) > 0) - if (write(tofd, buf, i) != i) - pfatal("write failed"); + pfatal("internal error, can't reopen %s", from); + while ((i = read(fromfd, buf, sizeof buf)) > 0) + if (write(tofd, buf, i) != i) + pfatal("write to %s failed", to); close(fromfd); close(tofd); - } - unlink(from); - return 0; -} - -/* Copy a file. */ - -void -copy_file(from,to) -char *from, *to; -{ - int tofd; - int fromfd; - int i; - - tofd = creat(to, 0666); - if (tofd < 0) - pfatal("can't create %s", to); - fromfd = open(from, O_RDONLY); - if (fromfd < 0) - pfatal("internal error, can't reopen %s", from); - while ((i=read(fromfd, buf, sizeof buf)) > 0) - if (write(tofd, buf, i) != i) - pfatal("write to %s failed", to); - close(fromfd); - close(tofd); } -/* Allocate a unique area for a string. */ - +/* + * Allocate a unique area for a string. + */ char * -savestr(s) -char *s; +savestr(char *s) { - char *rv; - char *t; - - if (!s) - s = "Oops"; - t = s; - while (*t++); - rv = malloc((MEM) (t - s)); - if (rv == Nullch) { - if (using_plan_a) - out_of_mem = TRUE; - else - fatal("out of memory\n"); - } - else { - t = rv; - while ((*t++ = *s++)) - ; - } - return rv; + char *rv, *t; + + if (!s) + s = "Oops"; + t = s; + while (*t++) + ; + rv = malloc((MEM) (t - s)); + if (rv == Nullch) { + if (using_plan_a) + out_of_mem = TRUE; + else + fatal("out of memory\n"); + } else { + t = rv; + while ((*t++ = *s++)) + ; + } + return rv; } -/* Vanilla terminal output (buffered). */ - +/* + * Vanilla terminal output (buffered). + */ void say(char *fmt, ...) { - va_list ap; + va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fflush(stderr); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fflush(stderr); } -/* Terminal output, pun intended. */ - +/* + * Terminal output, pun intended. + */ void fatal(char *fmt, ...) { - va_list ap; + va_list ap; - va_start(ap, fmt); - fprintf(stderr, "patch: **** "); - vfprintf(stderr, fmt, ap); - va_end(ap); - my_exit(1); + va_start(ap, fmt); + fprintf(stderr, "patch: **** "); + vfprintf(stderr, fmt, ap); + va_end(ap); + my_exit(1); } -/* Say something from patch, something from the system, then silence . . . */ - +/* + * Say something from patch, something from the system, then silence . . . + */ void pfatal(char *fmt, ...) { - va_list ap; - int errnum = errno; - - fprintf(stderr, "patch: **** "); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, ": %s\n", strerror(errnum)); - my_exit(1); + va_list ap; + int errnum = errno; + + fprintf(stderr, "patch: **** "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(errnum)); + my_exit(1); } -/* Get a response from the user, somehow or other. */ - +/* + * Get a response from the user, somehow or other. + */ void ask(char *fmt, ...) { - va_list ap; - int ttyfd; - int r; - bool tty2 = isatty(2); - - va_start(ap, fmt); - vsnprintf(buf, sizeof buf, fmt, ap); - va_end(ap); - fflush(stderr); - write(2, buf, strlen(buf)); - if (tty2) { /* might be redirected to a file */ - r = read(2, buf, sizeof buf); - } else if (isatty(1)) { /* this may be new file output */ - fflush(stdout); - write(1, buf, strlen(buf)); - r = read(1, buf, sizeof buf); - } else if ((ttyfd = open(_PATH_TTY, O_RDWR)) >= 0 && isatty(ttyfd)) { - /* might be deleted or unwriteable */ - write(ttyfd, buf, strlen(buf)); - r = read(ttyfd, buf, sizeof buf); - close(ttyfd); - } else if (isatty(0)) { /* this is probably patch input */ - fflush(stdin); - write(0, buf, strlen(buf)); - r = read(0, buf, sizeof buf); - } else { /* no terminal at all--default it */ - buf[0] = '\n'; - r = 1; - } - if (r <= 0) - buf[0] = 0; - else - buf[r] = '\0'; - if (!tty2) - say(buf); + va_list ap; + int ttyfd, r; + bool tty2 = isatty(2); + + va_start(ap, fmt); + vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + fflush(stderr); + write(2, buf, strlen(buf)); + if (tty2) { + /* might be redirected to a file */ + r = read(2, buf, sizeof buf); + } else if (isatty(1)) { /* this may be new file output */ + fflush(stdout); + write(1, buf, strlen(buf)); + r = read(1, buf, sizeof buf); + } else if ((ttyfd = open(_PATH_TTY, O_RDWR)) >= 0 && isatty(ttyfd)) { + /* might be deleted or unwriteable */ + write(ttyfd, buf, strlen(buf)); + r = read(ttyfd, buf, sizeof buf); + close(ttyfd); + } else if (isatty(0)) { /* this is probably patch input */ + fflush(stdin); + write(0, buf, strlen(buf)); + r = read(0, buf, sizeof buf); + } else { /* no terminal at all--default it */ + buf[0] = '\n'; + r = 1; + } + if (r <= 0) + buf[0] = 0; + else + buf[r] = '\0'; + if (!tty2) + say(buf); } -/* How to handle certain events when not in a critical region. */ - +/* + * How to handle certain events when not in a critical region. + */ void -set_signals(reset) -int reset; +set_signals(int reset) { #ifndef lint - static sig_t hupval, intval; - - if (!reset) { - hupval = signal(SIGHUP, SIG_IGN); - if (hupval != SIG_IGN) - hupval = (sig_t)my_exit; - intval = signal(SIGINT, SIG_IGN); - if (intval != SIG_IGN) - intval = (sig_t)my_exit; - } - signal(SIGHUP, hupval); - signal(SIGINT, intval); + static sig_t hupval, intval; + + if (!reset) { + hupval = signal(SIGHUP, SIG_IGN); + if (hupval != SIG_IGN) + hupval = (sig_t) my_exit; + intval = signal(SIGINT, SIG_IGN); + if (intval != SIG_IGN) + intval = (sig_t) my_exit; + } + signal(SIGHUP, hupval); + signal(SIGINT, intval); #endif } -/* How to handle certain events when in a critical region. */ - +/* + * How to handle certain events when in a critical region. + */ void -ignore_signals() +ignore_signals(void) { #ifndef lint - signal(SIGHUP, SIG_IGN); - signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); #endif } -/* Make sure we'll have the directories to create a file. - If `striplast' is TRUE, ignore the last element of `filename'. */ +/* + * Make sure we'll have the directories to create a file. If `striplast' is + * TRUE, ignore the last element of `filename'. + */ void -makedirs(filename,striplast) -char *filename; -bool striplast; +makedirs(char *filename, bool striplast) { - char *tmpbuf; - - if ((tmpbuf = strdup(filename)) == NULL) - fatal("out of memory\n"); + char *tmpbuf; - if (striplast) { - char *s = strrchr(tmpbuf, '/'); - if (s == NULL) - return; /* nothing to be done */ - *s = '\0'; - } + if ((tmpbuf = strdup(filename)) == NULL) + fatal("out of memory\n"); - strlcpy(buf, "/bin/mkdir -p ", sizeof buf); - if (strlcat(buf, tmpbuf, sizeof(buf)) >= sizeof(buf)) - fatal("buffer too small to hold %.20s...\n", tmpbuf); + if (striplast) { + char *s = strrchr(tmpbuf, '/'); + if (s == NULL) + return; /* nothing to be done */ + *s = '\0'; + } + strlcpy(buf, "/bin/mkdir -p ", sizeof buf); + if (strlcat(buf, tmpbuf, sizeof(buf)) >= sizeof(buf)) + fatal("buffer too small to hold %.20s...\n", tmpbuf); - if (system(buf)) - pfatal("%.40s failed", buf); + if (system(buf)) + pfatal("%.40s failed", buf); } -/* Make filenames more reasonable. */ - +/* + * Make filenames more reasonable. + */ char * -fetchname(at,strip_leading,assume_exists) -char *at; -int strip_leading; -int assume_exists; +fetchname(char *at, int strip_leading, int assume_exists) { - char *fullname; - char *name; - char *t; - char tmpbuf[200]; - int sleading = strip_leading; - - if (!at || *at == '\0') - return Nullch; - while (isspace(*at)) - at++; + char *fullname, *name, *t, tmpbuf[200]; + int sleading = strip_leading; + + if (!at || *at == '\0') + return Nullch; + while (isspace(*at)) + at++; #ifdef DEBUGGING - if (debug & 128) - say("fetchname %s %d %d\n",at,strip_leading,assume_exists); + if (debug & 128) + say("fetchname %s %d %d\n", at, strip_leading, assume_exists); #endif - if (strnEQ(at, "/dev/null", 9)) /* so files can be created by diffing */ - return Nullch; /* against /dev/null. */ - name = fullname = t = savestr(at); - - /* Strip off up to `sleading' leading slashes and null terminate. */ - for (; *t && !isspace(*t); t++) - if (*t == '/') - if (--sleading >= 0) - name = t+1; - *t = '\0'; - - /* If no -p option was given (957 is the default value!), - we were given a relative pathname, - and the leading directories that we just stripped off all exist, - put them back on. */ - if (strip_leading == 957 && name != fullname && *fullname != '/') { - name[-1] = '\0'; - if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) { - name[-1] = '/'; - name=fullname; + if (strnEQ(at, "/dev/null", 9)) /* so files can be created by diffing */ + return Nullch; /* against /dev/null. */ + name = fullname = t = savestr(at); + + /* Strip off up to `sleading' leading slashes and null terminate. */ + for (; *t && !isspace(*t); t++) + if (*t == '/') + if (--sleading >= 0) + name = t + 1; + *t = '\0'; + + /* + * If no -p option was given (957 is the default value!), we were + * given a relative pathname, and the leading directories that we + * just stripped off all exist, put them back on. + */ + if (strip_leading == 957 && name != fullname && *fullname != '/') { + name[-1] = '\0'; + if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) { + name[-1] = '/'; + name = fullname; + } + } + name = savestr(name); + free(fullname); + + if (stat(name, &filestat) && !assume_exists) { + char *filebase = basename(name); + char *filedir = dirname(name); + +#define try(f, a1, a2, a3) \ + (snprintf(tmpbuf, sizeof tmpbuf, f, a1, a2, a3), stat(tmpbuf, &filestat) == 0) + + if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) || + try("%s/RCS/%s%s", filedir, filebase, "") || + try("%s/%s%s", filedir, filebase, RCSSUFFIX) || + try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) || + try("%s/%s%s", filedir, SCCSPREFIX, filebase)) + return name; + free(name); + name = Nullch; } - } - - name = savestr(name); - free(fullname); - - if (stat(name, &filestat) && !assume_exists) { - char *filebase = basename(name); - char *filedir = dirname(name); - -#define try(f, a1, a2, a3) (snprintf(tmpbuf, sizeof tmpbuf, f, a1, a2, a3), stat(tmpbuf, &filestat) == 0) - if ( try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) - || try("%s/RCS/%s%s", filedir, filebase, "") - || try( "%s/%s%s", filedir, filebase, RCSSUFFIX) - || try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) - || try( "%s/%s%s", filedir, SCCSPREFIX, filebase)) - return name; - free(name); - name = Nullch; - } - - return name; + return name; } void -version() +version(void) { - fprintf(stderr, "Patch version 2.0-12u8-OpenBSD\n"); - my_exit(0); + fprintf(stderr, "Patch version 2.0-12u8-OpenBSD\n"); + my_exit(0); } diff --git a/usr.bin/patch/util.h b/usr.bin/patch/util.h index bfdb2ef8c7b..dfeaaad4c22 100644 --- a/usr.bin/patch/util.h +++ b/usr.bin/patch/util.h @@ -1,18 +1,18 @@ -/* $OpenBSD: util.h,v 1.4 2003/07/18 02:00:09 deraadt Exp $ */ +/* $OpenBSD: util.h,v 1.5 2003/07/21 14:00:41 deraadt Exp $ */ /* and for those machine that can't handle a variable argument list */ -EXT char serrbuf[BUFSIZ]; /* buffer for stderr */ +EXT char serrbuf[BUFSIZ];/* buffer for stderr */ -char *fetchname(char *, int, int); -int move_file(char *, char *); -void copy_file(char *, char *); -void say(char *, ...); -void fatal(char *, ...); -void pfatal(char *, ...); -void ask(char *, ...); -char *savestr(char *); -void set_signals(int); -void ignore_signals(void); -void makedirs(char *, bool); -void version(void); +char *fetchname(char *, int, int); +int move_file(char *, char *); +void copy_file(char *, char *); +void say(char *, ...); +void fatal(char *, ...); +void pfatal(char *, ...); +void ask(char *, ...); +char *savestr(char *); +void set_signals(int); +void ignore_signals(void); +void makedirs(char *, bool); +void version(void); |