[BACK]Return to pch.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / patch

Diff for /src/usr.bin/patch/pch.c between version 1.31 and 1.32

version 1.31, 2003/09/28 07:55:19 version 1.32, 2003/10/31 20:20:45
Line 34 
Line 34 
 #include <sys/stat.h>  #include <sys/stat.h>
   
 #include <ctype.h>  #include <ctype.h>
   #include <libgen.h>
   #include <limits.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
Line 75 
Line 77 
 static void     next_intuit_at(LINENUM, LINENUM);  static void     next_intuit_at(LINENUM, LINENUM);
 static void     skip_to(LINENUM, LINENUM);  static void     skip_to(LINENUM, LINENUM);
 static char     *pgets(char *, int, FILE *);  static char     *pgets(char *, int, FILE *);
   static char     *best_name(const struct file_name *, bool);
   static char     *posix_name(const struct file_name *, bool);
   static size_t   num_components(const char *);
   
   
 /*  /*
  * Prepare to look for the next patch in the patch file.   * Prepare to look for the next patch in the patch file.
  */   */
Line 180 
Line 184 
 bool  bool
 there_is_another_patch(void)  there_is_another_patch(void)
 {  {
           bool exists = false;
   
         if (p_base != 0L && p_base >= p_filesize) {          if (p_base != 0L && p_base >= p_filesize) {
                 if (verbose)                  if (verbose)
                         say("done\n");                          say("done\n");
Line 219 
Line 225 
                 if (*buf != '\n') {                  if (*buf != '\n') {
                         free(bestguess);                          free(bestguess);
                         bestguess = savestr(buf);                          bestguess = savestr(buf);
                         filearg[0] = fetchname(buf, 0, false);                          filearg[0] = fetchname(buf, &exists, 0);
                 }                  }
                 if (filearg[0] == NULL) {                  if (!exists) {
                           free(filearg[0]);
                         ask("No file found--skip this patch? [n] ");                          ask("No file found--skip this patch? [n] ");
                         if (*buf != 'y')                          if (*buf != 'y')
                                 continue;                                  continue;
                         if (verbose)                          if (verbose)
                                 say("Skipping patch...\n");                                  say("Skipping patch...\n");
                         filearg[0] = fetchname(bestguess, 0, true);                          filearg[0] = fetchname(bestguess, &exists, 0);
                         skip_rest_of_patch = true;                          skip_rest_of_patch = true;
                         return true;                          return true;
                 }                  }
Line 246 
Line 253 
         bool    last_line_was_command = false, this_is_a_command = false;          bool    last_line_was_command = false, this_is_a_command = false;
         bool    stars_last_line = false, stars_this_line = false;          bool    stars_last_line = false, stars_this_line = false;
         char    *s, *t;          char    *s, *t;
         char    *indtmp = NULL;  
         char    *oldtmp = NULL;  
         char    *newtmp = NULL;  
         char    *indname = NULL;  
         char    *oldname = NULL;  
         char    *newname = NULL;  
         int     indent, retval;          int     indent, retval;
         bool    no_filearg = (filearg[0] == NULL);          struct file_name names[MAX_FILE];
   
           memset(names, 0, sizeof(names));
         ok_to_create_file = false;          ok_to_create_file = false;
         fseek(pfp, p_base, SEEK_SET);          fseek(pfp, p_base, SEEK_SET);
         p_input_line = p_bline - 1;          p_input_line = p_bline - 1;
Line 295 
Line 297 
                         p_indent = indent;      /* assume this for now */                          p_indent = indent;      /* assume this for now */
                 }                  }
                 if (!stars_last_line && strnEQ(s, "*** ", 4))                  if (!stars_last_line && strnEQ(s, "*** ", 4))
                         oldtmp = savestr(s + 4);                          names[OLD_FILE].path = fetchname(s + 4,
                               &names[OLD_FILE].exists, strippath);
                 else if (strnEQ(s, "--- ", 4))                  else if (strnEQ(s, "--- ", 4))
                         newtmp = savestr(s + 4);                          names[NEW_FILE].path = fetchname(s + 4,
                               &names[NEW_FILE].exists, strippath);
                 else if (strnEQ(s, "+++ ", 4))                  else if (strnEQ(s, "+++ ", 4))
                         oldtmp = savestr(s + 4); /* pretend it is the old name */                          /* pretend it is the old name */
                           names[OLD_FILE].path = fetchname(s + 4,
                               &names[OLD_FILE].exists, strippath);
                 else if (strnEQ(s, "Index:", 6))                  else if (strnEQ(s, "Index:", 6))
                         indtmp = savestr(s + 6);                          names[INDEX_FILE].path = fetchname(s + 6,
                               &names[INDEX_FILE].exists, strippath);
                 else if (strnEQ(s, "Prereq:", 7)) {                  else if (strnEQ(s, "Prereq:", 7)) {
                         for (t = s + 7; isspace(*t); t++)                          for (t = s + 7; isspace(*t); t++)
                                 ;                                  ;
Line 324 
Line 331 
                         goto scan_exit;                          goto scan_exit;
                 }                  }
                 if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {                  if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
                         if (!atol(s + 3))                          if (strnEQ(s + 4, "0,0", 3))
                                 ok_to_create_file = true;                                  ok_to_create_file = true;
                         p_indent = indent;                          p_indent = indent;
                         p_start = this_line;                          p_start = this_line;
Line 335 
Line 342 
                 stars_this_line = strnEQ(s, "********", 8);                  stars_this_line = strnEQ(s, "********", 8);
                 if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&                  if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
                     strnEQ(s, "*** ", 4)) {                      strnEQ(s, "*** ", 4)) {
                         if (!atol(s + 4))                          if (atol(s + 4) == 0)
                                 ok_to_create_file = true;                                  ok_to_create_file = true;
                         /*                          /*
                          * if this is a new context diff the character just                           * If this is a new context diff the character just
                          * before                           * before the newline is a '*'.
                          */                           */
                         /* the newline is a '*'. */  
                         while (*s != '\n')                          while (*s != '\n')
                                 s++;                                  s++;
                         p_indent = indent;                          p_indent = indent;
Line 361 
Line 367 
                 }                  }
         }          }
 scan_exit:  scan_exit:
         if (no_filearg) {          if (retval == UNI_DIFF) {
                 if (indtmp != NULL)                  /* unswap old and new */
                         indname = fetchname(indtmp, strippath, ok_to_create_file);                  struct file_name tmp = names[OLD_FILE];
                 if (oldtmp != NULL)                  names[OLD_FILE] = names[NEW_FILE];
                         oldname = fetchname(oldtmp, strippath, ok_to_create_file);                  names[NEW_FILE] = tmp;
                 if (newtmp != NULL)  
                         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 (filearg[0] == NULL) {
                   if (posix)
                           filearg[0] = posix_name(names, ok_to_create_file);
                   else {
                           /* Ignore the Index: name for context diffs, like GNU */
                           if (names[OLD_FILE].path != NULL ||
                               names[NEW_FILE].path != NULL) {
                                   free(names[INDEX_FILE].path);
                                   names[INDEX_FILE].path = NULL;
                           }
                           filearg[0] = best_name(names, ok_to_create_file);
                   }
           }
   
         free(bestguess);          free(bestguess);
         bestguess = NULL;          bestguess = NULL;
   
         if (filearg[0] != NULL)          if (filearg[0] != NULL)
                 bestguess = savestr(filearg[0]);                  bestguess = savestr(filearg[0]);
         else if (indtmp != NULL)          else if (!ok_to_create_file) {
                 bestguess = fetchname(indtmp, strippath, true);                  /*
         else {                   * We don't want to create a new file but we need a
                 if (oldtmp != NULL)                   * filename to set bestguess.  Avoid setting filearg[0]
                         oldname = fetchname(oldtmp, strippath, true);                   * so the file is not created automatically.
                 if (newtmp != NULL)                   */
                         newname = fetchname(newtmp, strippath, true);                  if (posix)
                 if (oldname && newname) {                          bestguess = posix_name(names, true);
                         if (strlen(oldname) < strlen(newname))                  else
                                 bestguess = savestr(oldname);                          bestguess = best_name(names, true);
                         else  
                                 bestguess = savestr(newname);  
                 } else if (oldname)  
                         bestguess = savestr(oldname);  
                 else if (newname)  
                         bestguess = savestr(newname);  
         }          }
         free(indtmp);          free(names[OLD_FILE].path);
         free(oldtmp);          free(names[NEW_FILE].path);
         free(newtmp);          free(names[INDEX_FILE].path);
         free(indname);  
         free(oldname);  
         free(newname);  
         return retval;          return retval;
 }  }
   
Line 1420 
Line 1416 
                         chmod(outname, filemode);                          chmod(outname, filemode);
         }          }
         set_signals(1);          set_signals(1);
   }
   
   /*
    * Choose the name of the file to be patched based on POSIX rules.
    * NOTE: the POSIX rules are amazingly stupid and we only follow them
    *       if the user specified --posix or set POSIXLY_CORRECT.
    */
   static char *
   posix_name(const struct file_name *names, bool assume_exists)
   {
           char *path = NULL;
           int i;
   
           /*
            * POSIX states that the filename will be chosen from one
            * of the old, new and index names (in that order) if
            * the file exists relative to CWD after -p stripping.
            */
           for (i = 0; i < MAX_FILE; i++) {
                   if (names[i].path != NULL && names[i].exists) {
                           path = names[i].path;
                           break;
                   }
           }
           if (path == NULL && !assume_exists) {
                   /*
                    * No files found, look for something we can checkout from
                    * RCS/SCCS dirs.  Same order as above.
                    */
                   for (i = 0; i < MAX_FILE; i++) {
                           if (names[i].path != NULL &&
                               (path = checked_in(names[i].path)) != NULL)
                                   break;
                   }
                   /*
                    * Still no match?  Check to see if the diff could be creating
                    * a new file.
                    */
                   if (path == NULL && ok_to_create_file &&
                       names[NEW_FILE].path != NULL)
                           path = names[NEW_FILE].path;
           }
   
           return path ? savestr(path) : NULL;
   }
   
   /*
    * Choose the name of the file to be patched based the "best" one
    * available.
    */
   static char *
   best_name(const struct file_name *names, bool assume_exists)
   {
           size_t min_components, min_baselen, min_len, tmp;
           char *best = NULL;
           int i;
   
           /*
            * The "best" name is the one with the fewest number of path
            * components, the shortest basename length, and the shortest
            * overall length (in that order).  We only use the Index: file
            * if neither of the old or new files could be intuited from
            * the diff header.
            */
           min_components = min_baselen = min_len = SIZE_MAX;
           for (i = INDEX_FILE; i >= OLD_FILE; i--) {
                   if (names[i].path == NULL ||
                       (!names[i].exists && !assume_exists))
                           continue;
                   if ((tmp = num_components(names[i].path)) > min_components)
                           continue;
                   min_components = tmp;
                   if ((tmp = strlen(basename(names[i].path))) > min_baselen)
                           continue;
                   min_baselen = tmp;
                   if ((tmp = strlen(names[i].path)) > min_len)
                           continue;
                   min_len = tmp;
                   best = names[i].path;
           }
           if (best == NULL) {
                   /*
                    * No files found, look for something we can checkout from
                    * RCS/SCCS dirs.  Logic is identical to that above...
                    */
                   min_components = min_baselen = min_len = SIZE_MAX;
                   for (i = INDEX_FILE; i >= OLD_FILE; i--) {
                           if (names[i].path == NULL ||
                               checked_in(names[i].path) == NULL)
                                   continue;
                           if ((tmp = num_components(names[i].path)) > min_components)
                                   continue;
                           min_components = tmp;
                           if ((tmp = strlen(basename(names[i].path))) > min_baselen)
                                   continue;
                           min_baselen = tmp;
                           if ((tmp = strlen(names[i].path)) > min_len)
                                   continue;
                           min_len = tmp;
                           best = names[i].path;
                   }
                   /*
                    * Still no match?  Check to see if the diff could be creating
                    * a new file.
                    */
                   if (best == NULL && ok_to_create_file &&
                       names[NEW_FILE].path != NULL)
                           best = names[NEW_FILE].path;
           }
   
           return best ? savestr(best) : NULL;
   }
   
   static size_t
   num_components(const char *path)
   {
           size_t n;
           const char *cp;
   
           for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) {
                   while (*cp == '/')
                           cp++;           /* skip consecutive slashes */
           }
           return n;
 }  }

Legend:
Removed from v.1.31  
changed lines
  Added in v.1.32