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

Diff for /src/usr.bin/cvs/rcs.c between version 1.25 and 1.26

version 1.25, 2005/02/25 20:32:48 version 1.26, 2005/02/27 00:22:08
Line 32 
Line 32 
 #include <stdio.h>  #include <stdio.h>
 #include <ctype.h>  #include <ctype.h>
 #include <stdlib.h>  #include <stdlib.h>
   #include <stdarg.h>
 #include <string.h>  #include <string.h>
   
 #include "rcs.h"  #include "rcs.h"
 #include "log.h"  #include "log.h"
   
 #define RCS_BUFSIZE     16384  #define RCS_BUFSIZE     16384
 #define RCS_BUFEXTSIZE   8192  #define RCS_BUFEXTSIZE   8192
   
   
Line 104 
Line 105 
         struct rcs_tqh rl_lines;          struct rcs_tqh rl_lines;
 };  };
   
 static int  rcs_parse_admin     (RCSFILE *);  
 static int  rcs_parse_delta     (RCSFILE *);  
 static int  rcs_parse_deltatext (RCSFILE *);  
   
 static int      rcs_parse_access    (RCSFILE *);  
 static int      rcs_parse_symbols   (RCSFILE *);  
 static int      rcs_parse_locks     (RCSFILE *);  
 static int      rcs_parse_branches  (RCSFILE *, struct rcs_delta *);  
 static void     rcs_freedelta       (struct rcs_delta *);  
 static void     rcs_freepdata       (struct rcs_pdata *);  
 static int      rcs_gettok          (RCSFILE *);  
 static int      rcs_pushtok         (RCSFILE *, const char *, int);  
 static int      rcs_growbuf         (RCSFILE *);  
 static int      rcs_patch_lines     (struct rcs_foo *, struct rcs_foo *);  
   
 static struct rcs_delta*  rcs_findrev    (RCSFILE *, RCSNUM *);  
 static struct rcs_foo*    rcs_splitlines (const char *);  
 static void               rcs_freefoo    (struct rcs_foo *);  
   
 #define RCS_TOKSTR(rfp)   ((struct rcs_pdata *)rfp->rf_pdata)->rp_buf  #define RCS_TOKSTR(rfp)   ((struct rcs_pdata *)rfp->rf_pdata)->rp_buf
 #define RCS_TOKLEN(rfp)   ((struct rcs_pdata *)rfp->rf_pdata)->rp_blen  #define RCS_TOKLEN(rfp)   ((struct rcs_pdata *)rfp->rf_pdata)->rp_blen
   
Line 165 
Line 147 
 #define RCS_NKEYS   (sizeof(rcs_keys)/sizeof(rcs_keys[0]))  #define RCS_NKEYS   (sizeof(rcs_keys)/sizeof(rcs_keys[0]))
   
   
   static int   rcs_parse           (RCSFILE *);
   static int   rcs_parse_admin     (RCSFILE *);
   static int   rcs_parse_delta     (RCSFILE *);
   static int   rcs_parse_deltatext (RCSFILE *);
   
   static int   rcs_parse_access    (RCSFILE *);
   static int   rcs_parse_symbols   (RCSFILE *);
   static int   rcs_parse_locks     (RCSFILE *);
   static int   rcs_parse_branches  (RCSFILE *, struct rcs_delta *);
   static void  rcs_freedelta       (struct rcs_delta *);
   static void  rcs_freepdata       (struct rcs_pdata *);
   static int   rcs_gettok          (RCSFILE *);
   static int   rcs_pushtok         (RCSFILE *, const char *, int);
   static int   rcs_growbuf         (RCSFILE *);
   static int   rcs_patch_lines     (struct rcs_foo *, struct rcs_foo *);
   
   static struct rcs_delta*  rcs_findrev    (RCSFILE *, RCSNUM *);
   static struct rcs_foo*    rcs_splitlines (const char *);
   static void               rcs_freefoo    (struct rcs_foo *);
   
   
 /*  /*
  * rcs_open()   * rcs_open()
  *   *
  * Open a file containing RCS-formatted information.  The file's path is   * Open a file containing RCS-formatted information.  The file's path is
  * given in <path>, and the opening mode is given in <mode>, which is either   * given in <path>, and the opening flags are given in <flags>, which is either
  * RCS_MODE_READ, RCS_MODE_WRITE, or RCS_MODE_RDWR.  If the mode requests write   * RCS_READ, RCS_WRITE, or RCS_RDWR.  If the open requests write access and
  * access and the file does not exist, it will be created.   * the file does not exist, the RCS_CREATE flag must also be given, in which
  * The file isn't actually parsed by rcs_open(); parsing is delayed until the   * case it will be created with the mode specified in a third argument of
  * first operation that requires information from the file.   * type mode_t.  If the file exists and RCS_CREATE is passed, the open will
    * fail.
  * Returns a handle to the opened file on success, or NULL on failure.   * Returns a handle to the opened file on success, or NULL on failure.
  */   */
 RCSFILE*  RCSFILE*
 rcs_open(const char *path, u_int mode)  rcs_open(const char *path, int flags, ...)
 {  {
           int ret;
           mode_t fmode;
         RCSFILE *rfp;          RCSFILE *rfp;
         struct stat st;          struct stat st;
           va_list vap;
   
         if ((stat(path, &st) == -1) && (errno == ENOENT) &&          fmode = 0;
            !(mode & RCS_MODE_WRITE)) {          flags &= 0xffff;        /* ditch any internal flags */
                 cvs_log(LP_ERRNO, "cannot open RCS file `%s'", path);  
           if (((ret = stat(path, &st)) == -1) && (errno == ENOENT)) {
                   if (flags & RCS_CREATE) {
                           va_start(vap, flags);
                           fmode = va_arg(vap, mode_t);
                           va_end(vap);
                   } else {
                           cvs_log(LP_ERR, "RCS file `%s' does not exist", path);
                           return (NULL);
                   }
           } else if ((ret == 0) && (flags & RCS_CREATE)) {
                   cvs_log(LP_ERR, "RCS file `%s' exists", path);
                 return (NULL);                  return (NULL);
         }          }
   
         rfp = (RCSFILE *)malloc(sizeof(*rfp));          if ((rfp = (RCSFILE *)malloc(sizeof(*rfp))) == NULL) {
         if (rfp == NULL) {  
                 cvs_log(LP_ERRNO, "failed to allocate RCS file structure");                  cvs_log(LP_ERRNO, "failed to allocate RCS file structure");
                 return (NULL);                  return (NULL);
         }          }
         memset(rfp, 0, sizeof(*rfp));          memset(rfp, 0, sizeof(*rfp));
   
         rfp->rf_head = rcsnum_alloc();          if ((rfp->rf_head = rcsnum_parse(RCS_HEAD_INIT)) == NULL) {
         if (rfp->rf_head == NULL) {  
                 free(rfp);                  free(rfp);
                 return (NULL);                  return (NULL);
         }          }
   
         rfp->rf_branch = rcsnum_alloc();          if ((rfp->rf_branch = rcsnum_alloc()) == NULL) {
         if (rfp->rf_branch == NULL) {                  rcsnum_free(rfp->rf_head);
                 rcs_close(rfp);                  free(rfp);
                 return (NULL);                  return (NULL);
         }          }
   
         rfp->rf_path = strdup(path);          if ((rfp->rf_path = strdup(path)) == NULL) {
         if (rfp->rf_path == NULL) {  
                 cvs_log(LP_ERRNO, "failed to duplicate RCS file path");                  cvs_log(LP_ERRNO, "failed to duplicate RCS file path");
                 rcs_close(rfp);                  rcsnum_free(rfp->rf_branch);
                   rcsnum_free(rfp->rf_head);
                   free(rfp);
                 return (NULL);                  return (NULL);
         }          }
   
         rcsnum_aton(RCS_HEAD_INIT, NULL, rfp->rf_head);  
   
         rfp->rf_ref = 1;          rfp->rf_ref = 1;
         rfp->rf_flags |= RCS_RF_SLOCK;          rfp->rf_flags = flags | RCS_SLOCK;
         rfp->rf_mode = mode;          rfp->rf_mode = fmode;
   
         TAILQ_INIT(&(rfp->rf_delta));          TAILQ_INIT(&(rfp->rf_delta));
         TAILQ_INIT(&(rfp->rf_symbols));          TAILQ_INIT(&(rfp->rf_symbols));
         TAILQ_INIT(&(rfp->rf_locks));          TAILQ_INIT(&(rfp->rf_locks));
   
         if (rcs_parse(rfp) < 0) {          if (rfp->rf_flags & RCS_CREATE) {
           } else if (rcs_parse(rfp) < 0) {
                 rcs_close(rfp);                  rcs_close(rfp);
                 return (NULL);                  return (NULL);
         }          }
Line 250 
Line 266 
                 return;                  return;
         }          }
   
           if ((rfp->rf_flags & RCS_WRITE) && !(rfp->rf_flags & RCS_SYNCED))
                   rcs_write(rfp);
   
         while (!TAILQ_EMPTY(&(rfp->rf_delta))) {          while (!TAILQ_EMPTY(&(rfp->rf_delta))) {
                 rdp = TAILQ_FIRST(&(rfp->rf_delta));                  rdp = TAILQ_FIRST(&(rfp->rf_delta));
                 TAILQ_REMOVE(&(rfp->rf_delta), rdp, rd_list);                  TAILQ_REMOVE(&(rfp->rf_delta), rdp, rd_list);
Line 304 
Line 323 
         struct rcs_sym *symp;          struct rcs_sym *symp;
         struct rcs_delta *rdp;          struct rcs_delta *rdp;
   
         if (rfp->rf_flags & RCS_RF_SYNCED)          if ((rfp->rf_flags & RCS_SYNCED) || (rfp->rf_ndelta == 0))
                 return (0);                  return (0);
   
         fp = fopen(rfp->rf_path, "w");          fp = fopen(rfp->rf_path, "w");
Line 330 
Line 349 
   
         fprintf(fp, "locks;");          fprintf(fp, "locks;");
   
         if (rfp->rf_flags & RCS_RF_SLOCK)          if (rfp->rf_flags & RCS_SLOCK)
                 fprintf(fp, " strict;");                  fprintf(fp, " strict;");
         fputc('\n', fp);          fputc('\n', fp);
   
Line 356 
Line 375 
                     numbuf, sizeof(numbuf)));                      numbuf, sizeof(numbuf)));
         }          }
   
         fprintf(fp, "\ndesc\n@%s@\n\n", rfp->rf_desc);          fprintf(fp, "\ndesc\n@%s@\n\n",
               (rfp->rf_desc == NULL) ? "" : rfp->rf_desc);
   
         /* deltatexts */          /* deltatexts */
         TAILQ_FOREACH(rdp, &(rfp->rf_delta), rd_list) {          TAILQ_FOREACH(rdp, &(rfp->rf_delta), rd_list) {
Line 375 
Line 395 
         }          }
         fclose(fp);          fclose(fp);
   
         rfp->rf_flags |= RCS_RF_SYNCED;          rfp->rf_flags |= RCS_SYNCED;
   
         return (0);          return (0);
 }  }
   
   
 /*  /*
  * rcs_addsym()   * rcs_sym_add()
  *   *
  * Add a symbol to the list of symbols for the RCS file <rfp>.  The new symbol   * Add a symbol to the list of symbols for the RCS file <rfp>.  The new symbol
  * is named <sym> and is bound to the RCS revision <snum>.   * is named <sym> and is bound to the RCS revision <snum>.
  * Returns 0 on success, or -1 on failure.   * Returns 0 on success, or -1 on failure.
  */   */
 int  int
 rcs_addsym(RCSFILE *rfp, const char *sym, RCSNUM *snum)  rcs_sym_add(RCSFILE *rfp, const char *sym, RCSNUM *snum)
 {  {
         struct rcs_sym *symp;          struct rcs_sym *symp;
   
Line 426 
Line 446 
         TAILQ_INSERT_HEAD(&(rfp->rf_symbols), symp, rs_list);          TAILQ_INSERT_HEAD(&(rfp->rf_symbols), symp, rs_list);
   
         /* not synced anymore */          /* not synced anymore */
         rfp->rf_flags &= ~RCS_RF_SYNCED;          rfp->rf_flags &= ~RCS_SYNCED;
   
         return (0);          return (0);
 }  }
Line 600 
Line 620 
         if (res == 1) {          if (res == 1) {
                 cvs_log(LP_ERR, "sorry, can't travel in the future yet");                  cvs_log(LP_ERR, "sorry, can't travel in the future yet");
                 return (NULL);                  return (NULL);
         } else {          }
                 rdp = rcs_findrev(rfp, rfp->rf_head);  
                 if (rdp == NULL) {          rdp = rcs_findrev(rfp, rfp->rf_head);
                         cvs_log(LP_ERR, "failed to get RCS HEAD revision");          if (rdp == NULL) {
                   cvs_log(LP_ERR, "failed to get RCS HEAD revision");
                   return (NULL);
           }
   
           len = strlen(rdp->rd_text);
           if ((rbuf = cvs_buf_alloc(len, BUF_AUTOEXT)) == NULL)
                   return (NULL);
   
           cvs_buf_append(rbuf, rdp->rd_text, len);
   
           if (res != 0) {
                   /* Apply patches backwards to get the right version.
                    * This will need some rework to support sub branches.
                    */
                   if ((crev = rcsnum_alloc()) == NULL) {
                           cvs_buf_free(rbuf);
                         return (NULL);                          return (NULL);
                 }                  }
                   rcsnum_cpy(rfp->rf_head, crev, 0);
                   do {
                           crev->rn_id[crev->rn_len - 1]--;
                           rdp = rcs_findrev(rfp, crev);
                           if (rdp == NULL) {
                                   rcsnum_free(crev);
                                   cvs_buf_free(rbuf);
                                   return (NULL);
                           }
   
                 len = strlen(rdp->rd_text);                          if (cvs_buf_putc(rbuf, '\0') < 0) {
                 rbuf = cvs_buf_alloc(len, BUF_AUTOEXT);                                  rcsnum_free(crev);
                 if (rbuf == NULL)  
                         return (NULL);  
                 cvs_buf_append(rbuf, rdp->rd_text, len);  
   
                 if (res != 0) {  
                         /* Apply patches backwards to get the right version.  
                          * This will need some rework to support sub branches.  
                          */  
                         if ((crev = rcsnum_alloc()) == NULL) {  
                                 cvs_buf_free(rbuf);                                  cvs_buf_free(rbuf);
                                 return (NULL);                                  return (NULL);
                         }                          }
                         rcsnum_cpy(rfp->rf_head, crev, 0);                          bp = cvs_buf_release(rbuf);
                         do {                          rbuf = rcs_patch((char *)bp, rdp->rd_text);
                                 crev->rn_id[crev->rn_len - 1]--;                          if (rbuf == NULL)
                                 rdp = rcs_findrev(rfp, crev);                                  break;
                                 if (rdp == NULL) {                  } while (rcsnum_cmp(crev, rev, 0) != 0);
                                         rcsnum_free(crev);  
                                         cvs_buf_free(rbuf);  
                                         return (NULL);  
                                 }  
   
                                 if (cvs_buf_putc(rbuf, '\0') < 0) {                  rcsnum_free(crev);
                                         rcsnum_free(crev);  
                                         cvs_buf_free(rbuf);  
                                         return (NULL);  
                                 }  
                                 bp = cvs_buf_release(rbuf);  
                                 rbuf = rcs_patch((char *)bp, rdp->rd_text);  
                                 if (rbuf == NULL)  
                                         break;  
                         } while (rcsnum_cmp(crev, rev, 0) != 0);  
   
                         rcsnum_free(crev);  
                 }  
         }          }
   
         return (rbuf);          return (rbuf);
Line 688 
Line 708 
         struct rcs_delta *rdp;          struct rcs_delta *rdp;
         struct rcs_dlist *hp;          struct rcs_dlist *hp;
         int found;          int found;
   
         cmplen = 2;          cmplen = 2;
         hp = &(rfp->rf_delta);          hp = &(rfp->rf_delta);
   
Line 712 
Line 732 
   
   
 /*  /*
    * rcs_kwexp_set()
    *
    * Set the keyword expansion mode to use on the RCS file <file> to <mode>.
    * Returns 0 on success, or -1 on failure.
    */
   int
   rcs_kwexp_set(RCSFILE *file, int mode)
   {
           int i;
           char *tmp, buf[8] = "";
   
           if (RCS_KWEXP_INVAL(mode))
                   return (-1);
   
           i = 0;
           if (mode == RCS_KWEXP_NONE)
                   buf[0] = 'b';
           else if (mode == RCS_KWEXP_OLD)
                   buf[0] = 'o';
           else {
                   if (mode & RCS_KWEXP_NAME)
                           buf[i++] = 'k';
                   if (mode & RCS_KWEXP_VAL)
                           buf[i++] = 'v';
                   if (mode & RCS_KWEXP_LKR)
                           buf[i++] = 'l';
           }
   
           if ((tmp = strdup(buf)) == NULL) {
                   cvs_log(LP_ERRNO, "%s: failed to copy expansion mode",
                       file->rf_path);
                   return (-1);
           }
   
           free(file->rf_expand);
           file->rf_expand = tmp;
   
           return (0);
   }
   
   /*
    * rcs_kwexp_get()
    *
    * Retrieve the keyword expansion mode to be used for the RCS file <file>.
    */
   int
   rcs_kwexp_get(RCSFILE *file)
   {
           return rcs_kflag_get(file->rf_expand);
   }
   
   /*
  * rcs_kflag_get()   * rcs_kflag_get()
  *   *
  * Get the keyword expansion mode from a set of character flags given in   * Get the keyword expansion mode from a set of character flags given in
Line 762 
Line 834 
             "\t-kb\tGenerate binary file unmodified (merges not allowed).\n");              "\t-kb\tGenerate binary file unmodified (merges not allowed).\n");
 }  }
   
   
 /*  /*
  * rcs_parse()   * rcs_parse()
  *   *
  * Parse the contents of file <path>, which are in the RCS format.   * Parse the contents of file <path>, which are in the RCS format.
  * Returns 0 on success, or -1 on failure.   * Returns 0 on success, or -1 on failure.
  */   */
 int  static int
 rcs_parse(RCSFILE *rfp)  rcs_parse(RCSFILE *rfp)
 {  {
         int ret;          int ret;
         struct rcs_pdata *pdp;          struct rcs_pdata *pdp;
   
         if (rfp->rf_flags & RCS_RF_PARSED)          if (rfp->rf_flags & RCS_PARSED)
                 return (0);                  return (0);
   
         pdp = (struct rcs_pdata *)malloc(sizeof(*pdp));          if ((pdp = (struct rcs_pdata *)malloc(sizeof(*pdp))) == NULL) {
         if (pdp == NULL) {  
                 cvs_log(LP_ERRNO, "failed to allocate RCS parser data");                  cvs_log(LP_ERRNO, "failed to allocate RCS parser data");
                 return (-1);                  return (-1);
         }          }
Line 804 
Line 876 
         pdp->rp_bufend = pdp->rp_buf + pdp->rp_blen - 1;          pdp->rp_bufend = pdp->rp_buf + pdp->rp_blen - 1;
   
         /* ditch the strict lock */          /* ditch the strict lock */
         rfp->rf_flags &= ~RCS_RF_SLOCK;          rfp->rf_flags &= ~RCS_SLOCK;
         rfp->rf_pdata = pdp;          rfp->rf_pdata = pdp;
   
         if (rcs_parse_admin(rfp) < 0) {          if (rcs_parse_admin(rfp) < 0) {
Line 861 
Line 933 
         rcs_freepdata(pdp);          rcs_freepdata(pdp);
   
         rfp->rf_pdata = NULL;          rfp->rf_pdata = NULL;
         rfp->rf_flags |= RCS_RF_PARSED|RCS_RF_SYNCED;          rfp->rf_flags |= RCS_PARSED | RCS_SYNCED;
   
         return (0);          return (0);
 }  }
Line 945 
Line 1017 
                         if (ntok != RCS_TOK_SCOLON) {                          if (ntok != RCS_TOK_SCOLON) {
                                 cvs_log(LP_ERR,                                  cvs_log(LP_ERR,
                                     "missing semi-colon after RCS `%s' key",                                      "missing semi-colon after RCS `%s' key",
                                     rk->rk_str);                                      rk->rk_str);
                                 return (-1);                                  return (-1);
                         }                          }
                         break;                          break;
Line 1086 
Line 1158 
                         if (ntok != RCS_TOK_SCOLON) {                          if (ntok != RCS_TOK_SCOLON) {
                                 cvs_log(LP_ERR,                                  cvs_log(LP_ERR,
                                     "missing semi-colon after RCS `%s' key",                                      "missing semi-colon after RCS `%s' key",
                                     rk->rk_str);                                      rk->rk_str);
                                 rcs_freedelta(rdp);                                  rcs_freedelta(rdp);
                                 return (-1);                                  return (-1);
                         }                          }
Line 1139 
Line 1211 
                 free(tokstr);                  free(tokstr);
   
         TAILQ_INSERT_TAIL(&(rfp->rf_delta), rdp, rd_list);          TAILQ_INSERT_TAIL(&(rfp->rf_delta), rdp, rd_list);
           rfp->rf_ndelta++;
   
         return (ret);          return (ret);
 }  }
Line 1396 
Line 1469 
         if (type != RCS_TOK_STRICT) {          if (type != RCS_TOK_STRICT) {
                 rcs_pushtok(rfp, RCS_TOKSTR(rfp), type);                  rcs_pushtok(rfp, RCS_TOKSTR(rfp), type);
         } else {          } else {
                 rfp->rf_flags |= RCS_RF_SLOCK;                  rfp->rf_flags |= RCS_SLOCK;
   
                 type = rcs_gettok(rfp);                  type = rcs_gettok(rfp);
                 if (type != RCS_TOK_SCOLON) {                  if (type != RCS_TOK_SCOLON) {

Legend:
Removed from v.1.25  
changed lines
  Added in v.1.26