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

Diff for /src/usr.bin/fold/fold.c between version 1.17 and 1.18

version 1.17, 2015/10/09 01:37:07 version 1.18, 2016/05/23 10:31:42
Line 33 
Line 33 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
   #include <ctype.h>
   #include <err.h>
   #include <limits.h>
   #include <locale.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
 #include <ctype.h>  #include <wchar.h>
 #include <err.h>  
 #include <limits.h>  
   
 #define DEFLINEWIDTH    80  #define DEFLINEWIDTH    80
   
 static void fold(unsigned int);  static void fold(unsigned int);
 static unsigned int new_column_position(unsigned int, int);  static int isu8cont(unsigned char);
 static __dead void usage(void);  static __dead void usage(void);
   
 int count_bytes = 0;  int count_bytes = 0;
 int split_words = 0;  int split_words = 0;
   
Line 56 
Line 59 
         unsigned int width;          unsigned int width;
         const char *errstr;          const char *errstr;
   
           setlocale(LC_CTYPE, "");
   
         if (pledge("stdio rpath", NULL) == -1)          if (pledge("stdio rpath", NULL) == -1)
                 err(1, "pledge");                  err(1, "pledge");
   
Line 110 
Line 115 
                 for (; *argv; ++argv) {                  for (; *argv; ++argv) {
                         if (!freopen(*argv, "r", stdin))                          if (!freopen(*argv, "r", stdin))
                                 err(1, "%s", *argv);                                  err(1, "%s", *argv);
                                 /* NOTREACHED */  
                         else                          else
                                 fold(width);                                  fold(width);
                 }                  }
         }          }
         exit(0);          return 0;
 }  }
   
 /*  /*
Line 130 
Line 134 
  * returns embedded in the input stream.   * returns embedded in the input stream.
  */   */
 static void  static void
 fold(unsigned int width)  fold(unsigned int max_width)
 {  {
         static char *buf = NULL;          static char     *buf = NULL;
         static int   buf_max = 0;          static size_t    bufsz = 2048;
         int ch;          char            *cp;    /* Current mb character. */
         unsigned int col, indx;          char            *np;    /* Next mb character. */
           char            *sp;    /* To search for the last space. */
           char            *nbuf;  /* For buffer reallocation. */
           wchar_t          wc;    /* Current wide character. */
           int              ch;    /* Last byte read. */
           int              len;   /* Bytes in the current mb character. */
           unsigned int     col;   /* Current display position. */
           int              width; /* Display width of wc. */
   
         col = indx = 0;          if (buf == NULL && (buf = malloc(bufsz)) == NULL)
         while ((ch = getchar()) != EOF) {                  err(1, NULL);
                 if (ch == '\n') {  
                         if (indx != 0)  
                                 fwrite(buf, 1, indx, stdout);  
                         putchar('\n');  
                         col = indx = 0;  
                         continue;  
                 }  
   
                 col = new_column_position(col, ch);          np = cp = buf;
                 if (col > width) {          ch = 0;
                         unsigned int i, last_space;          col = 0;
   
                         if (split_words) {          while (ch != EOF) {  /* Loop on input characters. */
                                 for (i = 0, last_space = -1; i < indx; i++)                  while ((ch = getchar()) != EOF) {  /* Loop on input bytes. */
                                         if(buf[i] == ' ')                          if (np + 1 == buf + bufsz) {
                                                 last_space = i;                                  nbuf = reallocarray(buf, 2, bufsz);
                                   if (nbuf == NULL)
                                           err(1, NULL);
                                   bufsz *= 2;
                                   cp = nbuf + (cp - buf);
                                   np = nbuf + (np - buf);
                                   buf = nbuf;
                         }                          }
                           *np++ = ch;
   
                         if (split_words && last_space != -1) {                          /*
                                 last_space++;                           * Read up to and including the first byte of
                            * the next character, such that we are sure
                            * to have a complete character in the buffer.
                            * There is no need to read more than five bytes
                            * ahead, since UTF-8 characters are four bytes
                            * long at most.
                            */
   
                                 fwrite(buf, 1, last_space, stdout);                          if (np - cp > 4 || (np - cp > 1 && !isu8cont(ch)))
                                 memmove(buf, buf+last_space, indx-last_space);                                  break;
                   }
   
                                 indx -= last_space;                  while (cp < np) {  /* Loop on output characters. */
   
                           /* Handle end of line and backspace. */
   
                           if (*cp == '\n' || (*cp == '\r' && !count_bytes)) {
                                   fwrite(buf, 1, ++cp - buf, stdout);
                                   memmove(buf, cp, np - cp);
                                   np = buf + (np - cp);
                                   cp = buf;
                                 col = 0;                                  col = 0;
                                 for (i = 0; i < indx; i++) {                                  continue;
                                         col = new_column_position(col, buf[i]);  
                                 }  
                         } else {  
                                 fwrite(buf, 1, indx, stdout);  
                                 col = indx = 0;  
                         }                          }
                         putchar('\n');                          if (*cp == '\b' && !count_bytes) {
                                   if (col)
                                           col--;
                                   cp++;
                                   continue;
                           }
   
                         /* calculate the column position for the next line. */                          /*
                         col = new_column_position(col, ch);                           * Measure display width.
                 }                           * Process the last byte only if
                            * end of file was reached.
                            */
   
                 if (indx + 1 > buf_max) {                          if (np - cp > (ch != EOF)) {
                         int newmax = buf_max + 2048;                                  len = 1;
                         char *newbuf;                                  width = 1;
   
                         /* Allocate buffer in LINE_MAX increments */                                  if (*cp == '\t') {
                         if ((newbuf = realloc(buf, newmax)) == NULL) {                                          if (count_bytes == 0)
                                 err(1, NULL);                                                  width = 8 - (col & 7);
                                 /* NOTREACHED */                                  } else if ((len = mbtowc(&wc, cp,
                                       np - cp)) < 1)
                                           len = 1;
                                   else if (count_bytes)
                                           width = len;
                                   else if ((width = wcwidth(wc)) < 0)
                                           width = 1;
   
                                   col += width;
                                   if (col <= max_width || cp == buf) {
                                           cp += len;
                                           continue;
                                   }
                         }                          }
                         buf = newbuf;  
                         buf_max = newmax;  
                 }  
                 buf[indx++] = ch;  
         }  
   
         if (indx != 0)                          /* Line break required. */
                 fwrite(buf, 1, indx, stdout);  
 }  
   
 /*                          if (col > max_width) {
  * calculate the column position                                  if (split_words) {
  */                                          for (sp = cp; sp > buf; sp--) {
 static unsigned int                                                  if (sp[-1] == ' ') {
 new_column_position(unsigned int col, int ch)                                                          cp = sp;
 {                                                          break;
         if (!count_bytes) {                                                  }
                 switch (ch) {                                          }
                 case '\b':                                  }
                         if (col > 0)                                  fwrite(buf, 1, cp - buf, stdout);
                                 --col;                                  putchar('\n');
                                   memmove(buf, cp, np - cp);
                                   np = buf + (np - cp);
                                   cp = buf;
                                   col = 0;
                                   continue;
                           }
   
                           /* Need more input. */
   
                         break;                          break;
                 case '\r':  
                         col = 0;  
                         break;  
                 case '\t':  
                         col = (col + 8) & ~7;  
                         break;  
                 default:  
                         ++col;  
                         break;  
                 }                  }
         } else {  
                 ++col;  
         }          }
           fwrite(buf, 1, np - buf, stdout);
   
         return col;          if (ferror(stdin))
                   err(1, NULL);
   }
   
   static int
   isu8cont(unsigned char c)
   {
           return MB_CUR_MAX > 1 && (c & (0x80 | 0x40)) == 0x80;
 }  }
   
 static __dead void  static __dead void

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.18