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

Diff for /src/usr.bin/rcs/rcs.c between version 1.76 and 1.77

version 1.76, 2011/05/20 19:21:10 version 1.77, 2011/07/06 15:36:52
Line 53 
Line 53 
 struct rcs_kw rcs_expkw[] =  {  struct rcs_kw rcs_expkw[] =  {
         { "Author",     RCS_KW_AUTHOR   },          { "Author",     RCS_KW_AUTHOR   },
         { "Date",       RCS_KW_DATE     },          { "Date",       RCS_KW_DATE     },
           { "Locker",     RCS_KW_LOCKER   },
         { "Header",     RCS_KW_HEADER   },          { "Header",     RCS_KW_HEADER   },
         { "Id",         RCS_KW_ID       },          { "Id",         RCS_KW_ID       },
         { "OpenBSD",    RCS_KW_ID       },          { "OpenBSD",    RCS_KW_ID       },
Line 1479 
Line 1480 
  * On error, return NULL.   * On error, return NULL.
  */   */
 static BUF *  static BUF *
 rcs_expand_keywords(char *rcsfile, struct rcs_delta *rdp, BUF *bp, int mode)  rcs_expand_keywords(char *rcsfile_in, struct rcs_delta *rdp, BUF *bp, int mode)
 {  {
         BUF *newbuf;          BUF *newbuf;
           u_char *c, *kw, *fin;
           char buf[256], *tmpf, resolved[MAXPATHLEN], *rcsfile;
           u_char *line, *line2;
           u_int i, j;
         int kwtype;          int kwtype;
         u_int j, found;          int found;
         u_char *c, *kwstr, *start, *end, *fin;  
         char expbuf[256], buf[256];  
         struct tm tb;          struct tm tb;
         char *fmt;  
         size_t len;  
   
         kwtype = 0;  
         kwstr = NULL;  
   
         /*  
          * -z support for RCS  
          */  
         tb = rdp->rd_date;          tb = rdp->rd_date;
         if (timezone_flag != NULL)          if (timezone_flag != NULL)
                 rcs_set_tz(timezone_flag, rdp, &tb);                  rcs_set_tz(timezone_flag, rdp, &tb);
   
         len = buf_len(bp);          if (realpath(rcsfile_in, resolved) == NULL)
                   rcsfile = rcsfile_in;
           else
                   rcsfile = resolved;
   
         c = buf_get(bp);          newbuf = buf_alloc(buf_len(bp));
         found = 0;  
         /* Final character in buffer. */  
         fin = c + len - 1;  
   
         /* If no keywords are found, return original buffer. */  
         newbuf = bp;  
   
         /*          /*
          * Keyword formats:           * Keyword formats:
          * $Keyword$           * $Keyword$
          * $Keyword: value$           * $Keyword: value$
          */           */
         for (; c < fin; c++) {          c = buf_get(bp);
                 if (*c == '$') {          fin = c + buf_len(bp);
                         BUF *tmpbuf;          /* Copying to newbuf is deferred until the first keyword. */
                         size_t clen;          found = 0;
   
                         /* remember start of this possible keyword */          while (c < fin) {
                         start = c;                  kw = memchr(c, '$', fin - c);
                   if (kw == NULL)
                           break;
                   ++kw;
                   if (found) {
                           /* Copy everything up to and including the $. */
                           buf_append(newbuf, c, kw - c);
                   }
                   c = kw;
                   /* c points after the $ now. */
                   if (c == fin)
                           break;
                   if (!isalpha(*c)) /* all valid keywords start with a letter */
                           continue;
   
                         /* first following character has to be alphanumeric */                  for (i = 0; i < RCS_NKWORDS; ++i) {
                         c++;                          size_t kwlen;
                         if (!isalpha(*c)) {  
                                 c = start;                          kwlen = strlen(rcs_expkw[i].kw_str);
                                 continue;                          /*
                            * kwlen must be less than clen since clen includes
                            * either a terminating `$' or a `:'.
                            */
                           if (c + kwlen < fin &&
                               memcmp(c , rcs_expkw[i].kw_str, kwlen) == 0 &&
                               (c[kwlen] == '$' || c[kwlen] == ':')) {
                                   c += kwlen;
                                   break;
                         }                          }
                   }
                   if (i == RCS_NKWORDS)
                           continue;
                   kwtype = rcs_expkw[i].kw_type;
   
                         /* Number of characters between c and fin, inclusive. */                  /*
                         clen = fin - c + 1;                   * If the next character is ':' we need to look for an '$'
                    * before the end of the line to be sure it is in fact a
                         /* look for any matching keywords */                   * keyword.
                         found = 0;                   */
                         for (j = 0; j < RCS_NKWORDS; j++) {                  if (*c == ':') {
                                 size_t kwlen;                          for (; c < fin; ++c) {
                                   if (*c == '$' || *c == '\n')
                                 kwlen = strlen(rcs_expkw[j].kw_str);  
                                 /*  
                                  * kwlen must be less than clen since clen  
                                  * includes either a terminating `$' or a `:'.  
                                  */  
                                 if (kwlen < clen &&  
                                     memcmp(c, rcs_expkw[j].kw_str, kwlen) == 0 &&  
                                     (c[kwlen] == '$' || c[kwlen] == ':')) {  
                                         found = 1;  
                                         kwstr = rcs_expkw[j].kw_str;  
                                         kwtype = rcs_expkw[j].kw_type;  
                                         c += kwlen;  
                                         break;                                          break;
                                 }  
                         }                          }
   
                         /* unknown keyword, continue looking */                          if (*c != '$') {
                         if (found == 0) {                                  if (found)
                                 c = start;                                          buf_append(newbuf, kw, c - kw);
                                 continue;                                  continue;
                         }                          }
                   }
                   ++c;
   
                         /*                  if (!found) {
                          * if the next character was ':' we need to look for                          found = 1;
                          * an '$' before the end of the line to be sure it is                          /* Copy everything up to and including the $. */
                          * in fact a keyword.                          buf_append(newbuf, buf_get(bp), kw - buf_get(bp));
                          */                  }
                         if (*c == ':') {  
                                 for (; c <= fin; ++c) {  
                                         if (*c == '$' || *c == '\n')  
                                                 break;  
                                 }  
   
                                 if (*c != '$') {                  if (mode & RCS_KWEXP_NAME) {
                                         c = start;                          buf_puts(newbuf, rcs_expkw[i].kw_str);
                                         continue;                          if (mode & RCS_KWEXP_VAL)
                                 }                                  buf_puts(newbuf, ": ");
                   }
   
                   /* Order matters because of RCS_KW_ID and RCS_KW_HEADER. */
                   if (mode & RCS_KWEXP_VAL) {
                           if (kwtype & (RCS_KW_RCSFILE|RCS_KW_LOG)) {
                                   if ((kwtype & RCS_KW_FULLPATH) ||
                                       (tmpf = strrchr(rcsfile, '/')) == NULL)
                                           buf_puts(newbuf, rcsfile);
                                   else
                                           buf_puts(newbuf, tmpf + 1);
                                   buf_putc(newbuf, ' ');
                         }                          }
                         end = c + 1;  
   
                         /* start constructing the expansion */                          if (kwtype & RCS_KW_REVISION) {
                         expbuf[0] = '\0';                                  rcsnum_tostr(rdp->rd_num, buf, sizeof(buf));
                                   buf_puts(newbuf, buf);
                                   buf_putc(newbuf, ' ');
                           }
   
                         if (mode & RCS_KWEXP_NAME) {                          if (kwtype & RCS_KW_DATE) {
                                 char *tmp;                                  strftime(buf, sizeof(buf),
                                       "%Y/%m/%d %H:%M:%S ", &tb);
                                   buf_puts(newbuf, buf);
                           }
   
                                 (void)xasprintf(&tmp, "$%s%s", kwstr,                          if (kwtype & RCS_KW_AUTHOR) {
                                     (mode & RCS_KWEXP_VAL) ? ": " : "");                                  buf_puts(newbuf, rdp->rd_author);
                                 if (strlcat(expbuf, tmp, sizeof(expbuf)) >= sizeof(expbuf))                                  buf_putc(newbuf, ' ');
                                         errx(1, "rcs_expand_keywords: string truncated");  
                                 xfree(tmp);  
                         }                          }
   
                         /*                          if (kwtype & RCS_KW_STATE) {
                          * order matters because of RCS_KW_ID and                                  buf_puts(newbuf, rdp->rd_state);
                          * RCS_KW_HEADER here                                  buf_putc(newbuf, ' ');
                          */                          }
                         if (mode & RCS_KWEXP_VAL) {  
                                 if (kwtype & RCS_KW_RCSFILE) {  
                                         char *tmp;  
   
                                         (void)xasprintf(&tmp, "%s ",                          /* Order does not matter anymore below. */
                                             (kwtype & RCS_KW_FULLPATH) ? rcsfile : basename(rcsfile));                          if (kwtype & RCS_KW_SOURCE) {
                                         if (strlcat(expbuf, tmp, sizeof(expbuf)) >= sizeof(expbuf))                                  buf_puts(newbuf, rcsfile);
                                                 errx(1, "rcs_expand_keywords: string truncated");                                  buf_putc(newbuf, ' ');
                                         xfree(tmp);                          }
                                 }  
   
                                 if (kwtype & RCS_KW_REVISION) {                          if (kwtype & RCS_KW_NAME)
                                         char *tmp;                                  buf_putc(newbuf, ' ');
   
                                         rcsnum_tostr(rdp->rd_num, buf, sizeof(buf));                          if ((kwtype & RCS_KW_LOCKER)) {
                                         (void)xasprintf(&tmp, "%s ", buf);                                  if (rdp->rd_locker) {
                                         if (strlcat(expbuf, tmp, sizeof(expbuf)) >= sizeof(buf))                                          buf_puts(newbuf, rdp->rd_locker);
                                                 errx(1, "rcs_expand_keywords: string truncated");                                          buf_putc(newbuf, ' ');
                                         xfree(tmp);  
                                 }                                  }
                           }
                   }
   
                                 if (kwtype & RCS_KW_DATE) {                  /* End the expansion. */
                                         if (timezone_flag != NULL)                  if (mode & RCS_KWEXP_NAME)
                                                 fmt = "%Y/%m/%d %H:%M:%S%z ";                          buf_putc(newbuf, '$');
                                         else  
                                                 fmt = "%Y/%m/%d %H:%M:%S ";  
   
                                         strftime(buf, sizeof(buf), fmt, &tb);                  if (kwtype & RCS_KW_LOG) {
                                         if (strlcat(expbuf, buf, sizeof(expbuf)) >= sizeof(expbuf))                          line = memrchr(buf_get(bp), '\n', kw - buf_get(bp) - 1);
                                                 errx(1, "rcs_expand_keywords: string truncated");                          if (line == NULL)
                                 }                                  line = buf_get(bp);
                           else
                                   ++line;
                           line2 = kw - 1;
                           while (line2 > line && line2[-1] == ' ')
                                   --line2;
   
                                 if (kwtype & RCS_KW_AUTHOR) {                          buf_putc(newbuf, '\n');
                                         char *tmp;                          buf_append(newbuf, line, kw - 1 - line);
                           buf_puts(newbuf, "Revision ");
                           rcsnum_tostr(rdp->rd_num, buf, sizeof(buf));
                           buf_puts(newbuf, buf);
                           buf_puts(newbuf, "  ");
                           strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S", &tb);
                           buf_puts(newbuf, buf);
   
                                         (void)xasprintf(&tmp, "%s ", rdp->rd_author);                          buf_puts(newbuf, "  ");
                                         if (strlcat(expbuf, tmp, sizeof(expbuf)) >= sizeof(expbuf))                          buf_puts(newbuf, rdp->rd_author);
                                                 errx(1, "rcs_expand_keywords: string truncated");                          buf_putc(newbuf, '\n');
                                         xfree(tmp);  
                                 }  
   
                                 if (kwtype & RCS_KW_STATE) {                          for (i = 0; rdp->rd_log[i]; i += j) {
                                         char *tmp;                                  j = strcspn(rdp->rd_log + i, "\n");
                                   if (j == 0)
                                         (void)xasprintf(&tmp, "%s ", rdp->rd_state);                                          buf_append(newbuf, line, line2 - line);
                                         if (strlcat(expbuf, tmp, sizeof(expbuf)) >= sizeof(expbuf))                                  else
                                                 errx(1, "rcs_expand_keywords: string truncated");                                          buf_append(newbuf, line, kw - 1 - line);
                                         xfree(tmp);                                  if (rdp->rd_log[i + j])
                                 }                                          ++j;
                                   buf_append(newbuf, rdp->rd_log + i, j);
                                 /* order does not matter anymore below */  
                                 if (kwtype & RCS_KW_LOG)  
                                         if (strlcat(expbuf, " ", sizeof(expbuf)) >= sizeof(expbuf))  
                                                 errx(1, "rcs_expand_keywords: string truncated");  
   
                                 if (kwtype & RCS_KW_SOURCE) {  
                                         char *tmp;  
   
                                         (void)xasprintf(&tmp, "%s ", rcsfile);  
                                         if (strlcat(expbuf, tmp, sizeof(expbuf)) >= sizeof(expbuf))  
                                                 errx(1, "rcs_expand_keywords: string truncated");  
                                         xfree(tmp);  
                                 }  
   
                                 if (kwtype & RCS_KW_NAME)  
                                         if (strlcat(expbuf, " ", sizeof(expbuf)) >= sizeof(expbuf))  
                                                 errx(1, "rcs_expand_keywords: string truncated");  
                         }                          }
                           buf_append(newbuf, line, line2 - line);
                         /* end the expansion */                          for (j = 0; c + j < fin; ++j) {
                         if (mode & RCS_KWEXP_NAME)                                  if (c[j] != ' ')
                                 if (strlcat(expbuf, "$", sizeof(expbuf)) >= sizeof(expbuf))                                          break;
                                         errx(1, "rcs_expand_keywords: string truncated");                          }
                           if (c + j == fin || c[j] == '\n')
                         /* Concatenate everything together. */                                  c += j;
                         tmpbuf = buf_alloc(len + strlen(expbuf));  
                         /* Append everything before keyword. */  
                         buf_append(tmpbuf, buf_get(newbuf),  
                             start - (unsigned char *)buf_get(newbuf));  
                         /* Append keyword. */  
                         buf_append(tmpbuf, expbuf, strlen(expbuf));  
                         /* Point c to end of keyword. */  
                         c = buf_get(tmpbuf) + buf_len(tmpbuf) - 1;  
                         /* Append everything after keyword. */  
                         buf_append(tmpbuf, end,  
                             ((unsigned char *)buf_get(newbuf) + buf_len(newbuf)) - end);  
                         /* Point fin to end of data. */  
                         fin = buf_get(tmpbuf) + buf_len(tmpbuf) - 1;  
                         /* Recalculate new length. */  
                         len = buf_len(tmpbuf);  
   
                         /* tmpbuf is now ready, free old newbuf if allocated here. */  
                         if (newbuf != bp)  
                                 buf_free(newbuf);  
                         newbuf = tmpbuf;  
                 }                  }
         }          }
   
         return (newbuf);          if (found) {
                   buf_append(newbuf, c, fin - c);
                   buf_free(bp);
                   return (newbuf);
           } else {
                   buf_free(newbuf);
                   return (bp);
           }
 }  }
   
 /*  /*

Legend:
Removed from v.1.76  
changed lines
  Added in v.1.77