[BACK]Return to preconv.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/preconv.c between version 1.1 and 1.8

version 1.1, 2011/05/26 00:30:11 version 1.8, 2014/08/16 19:00:01
Line 14 
Line 14 
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */   */
 #ifdef HAVE_CONFIG_H  
 #include "config.h"  #include "config.h"
 #endif  
   
   #include <sys/types.h>
   #if HAVE_MMAP
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/mman.h>  #include <sys/mman.h>
   #endif
   
 #include <assert.h>  #include <assert.h>
 #include <fcntl.h>  #include <fcntl.h>
Line 30 
Line 31 
   
 /*  /*
  * The read_whole_file() and resize_buf() functions are copied from   * The read_whole_file() and resize_buf() functions are copied from
  * read.c, including all dependency code (MAP_FILE, etc.).   * read.c, including all dependency code.
  */   */
   
 #ifndef MAP_FILE  
 #define MAP_FILE        0  
 #endif  
   
 enum    enc {  enum    enc {
         ENC_UTF_8, /* UTF-8 */          ENC_UTF_8, /* UTF-8 */
         ENC_US_ASCII, /* US-ASCII */          ENC_US_ASCII, /* US-ASCII */
Line 55  struct encode {
Line 52  struct encode {
         int             (*conv)(const struct buf *);          int             (*conv)(const struct buf *);
 };  };
   
   static  int      cue_enc(const struct buf *, size_t *, enum enc *);
 static  int      conv_latin_1(const struct buf *);  static  int      conv_latin_1(const struct buf *);
 static  int      conv_us_ascii(const struct buf *);  static  int      conv_us_ascii(const struct buf *);
 static  int      conv_utf_8(const struct buf *);  static  int      conv_utf_8(const struct buf *);
Line 85  static int
Line 83  static int
 conv_latin_1(const struct buf *b)  conv_latin_1(const struct buf *b)
 {  {
         size_t           i;          size_t           i;
         unsigned char    c;          unsigned char    cu;
         const char      *cp;          const char      *cp;
   
         cp = b->buf + (int)b->offs;          cp = b->buf + (int)b->offs;
Line 94  conv_latin_1(const struct buf *b)
Line 92  conv_latin_1(const struct buf *b)
          * Latin-1 falls into the first 256 code-points of Unicode, so           * Latin-1 falls into the first 256 code-points of Unicode, so
          * there's no need for any sort of translation.  Just make the           * there's no need for any sort of translation.  Just make the
          * 8-bit characters use the Unicode escape.           * 8-bit characters use the Unicode escape.
            * Note that binary values 128 < v < 160 are passed through
            * unmodified to mandoc.
          */           */
   
         for (i = b->offs; i < b->sz; i++) {          for (i = b->offs; i < b->sz; i++) {
                 c = (unsigned char)*cp++;                  cu = (unsigned char)*cp++;
                 c < 128 ? putchar(c) : printf("\\[u%.4X]", c);                  cu < 160U ? putchar(cu) : printf("\\[u%.4X]", cu);
         }          }
   
         return(1);          return(1);
Line 120  conv_us_ascii(const struct buf *b)
Line 120  conv_us_ascii(const struct buf *b)
 static int  static int
 conv_utf_8(const struct buf *b)  conv_utf_8(const struct buf *b)
 {  {
           int              state, be;
           unsigned int     accum;
           size_t           i;
           unsigned char    cu;
           const char      *cp;
           const long       one = 1L;
   
           cp = b->buf + (int)b->offs;
           state = 0;
           accum = 0U;
           be = 0;
   
           /* Quick test for big-endian value. */
   
           if ( ! (*((const char *)(&one))))
                   be = 1;
   
           for (i = b->offs; i < b->sz; i++) {
                   cu = (unsigned char)*cp++;
                   if (state) {
                           if ( ! (cu & 128) || (cu & 64)) {
                                   /* Bad sequence header. */
                                   return(0);
                           }
   
                           /* Accept only legitimate bit patterns. */
   
                           if (cu > 191 || cu < 128) {
                                   /* Bad in-sequence bits. */
                                   return(0);
                           }
   
                           accum |= (cu & 63) << --state * 6;
   
                           /*
                            * Accum is held in little-endian order as
                            * stipulated by the UTF-8 sequence coding.  We
                            * need to convert to a native big-endian if our
                            * architecture requires it.
                            */
   
                           if (0 == state && be)
                                   accum = (accum >> 24) |
                                           ((accum << 8) & 0x00FF0000) |
                                           ((accum >> 8) & 0x0000FF00) |
                                           (accum << 24);
   
                           if (0 == state) {
                                   accum < 128U ? putchar(accum) :
                                           printf("\\[u%.4X]", accum);
                                   accum = 0U;
                           }
                   } else if (cu & (1 << 7)) {
                           /*
                            * Entering a UTF-8 state:  if we encounter a
                            * UTF-8 bitmask, calculate the expected UTF-8
                            * state from it.
                            */
                           for (state = 0; state < 7; state++)
                                   if ( ! (cu & (1 << (7 - state))))
                                           break;
   
                           /* Accept only legitimate bit patterns. */
   
                           switch (state) {
                           case (4):
                                   if (cu <= 244 && cu >= 240) {
                                           accum = (cu & 7) << 18;
                                           break;
                                   }
                                   /* Bad 4-sequence start bits. */
                                   return(0);
                           case (3):
                                   if (cu <= 239 && cu >= 224) {
                                           accum = (cu & 15) << 12;
                                           break;
                                   }
                                   /* Bad 3-sequence start bits. */
                                   return(0);
                           case (2):
                                   if (cu <= 223 && cu >= 194) {
                                           accum = (cu & 31) << 6;
                                           break;
                                   }
                                   /* Bad 2-sequence start bits. */
                                   return(0);
                           default:
                                   /* Bad sequence bit mask. */
                                   return(0);
                           }
                           state--;
                   } else
                           putchar(cu);
           }
   
           if (0 != state) {
                   /* Bad trailing bits. */
                   return(0);
           }
   
         return(1);          return(1);
 }  }
   
Line 142  static int
Line 241  static int
 read_whole_file(const char *f, int fd,  read_whole_file(const char *f, int fd,
                 struct buf *fb, int *with_mmap)                  struct buf *fb, int *with_mmap)
 {  {
         struct stat      st;  
         size_t           off;          size_t           off;
         ssize_t          ssz;          ssize_t          ssz;
   
   #if HAVE_MMAP
           struct stat      st;
         if (-1 == fstat(fd, &st)) {          if (-1 == fstat(fd, &st)) {
                 perror(f);                  perror(f);
                 return(0);                  return(0);
Line 166  read_whole_file(const char *f, int fd, 
Line 266  read_whole_file(const char *f, int fd, 
         if (S_ISREG(st.st_mode)) {          if (S_ISREG(st.st_mode)) {
                 *with_mmap = 1;                  *with_mmap = 1;
                 fb->sz = (size_t)st.st_size;                  fb->sz = (size_t)st.st_size;
                 fb->buf = mmap(NULL, fb->sz, PROT_READ,                  fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
                                 MAP_FILE|MAP_SHARED, fd, 0);  
                 if (fb->buf != MAP_FAILED)                  if (fb->buf != MAP_FAILED)
                         return(1);                          return(1);
         }          }
   #endif
   
         /*          /*
          * If this isn't a regular file (like, say, stdin), then we must           * If this isn't a regular file (like, say, stdin), then we must
Line 207  read_whole_file(const char *f, int fd, 
Line 307  read_whole_file(const char *f, int fd, 
         return(0);          return(0);
 }  }
   
   static int
   cue_enc(const struct buf *b, size_t *offs, enum enc *enc)
   {
           const char      *ln, *eoln, *eoph;
           size_t           sz, phsz, nsz;
           int              i;
   
           ln = b->buf + (int)*offs;
           sz = b->sz - *offs;
   
           /* Look for the end-of-line. */
   
           if (NULL == (eoln = memchr(ln, '\n', sz)))
                   return(-1);
   
           /* Set next-line marker. */
   
           *offs = (size_t)((eoln + 1) - b->buf);
   
           /* Check if we have the correct header/trailer. */
   
           if ((sz = (size_t)(eoln - ln)) < 10 ||
                           memcmp(ln, ".\\\" -*-", 7) ||
                           memcmp(eoln - 3, "-*-", 3))
                   return(0);
   
           /* Move after the header and adjust for the trailer. */
   
           ln += 7;
           sz -= 10;
   
           while (sz > 0) {
                   while (sz > 0 && ' ' == *ln) {
                           ln++;
                           sz--;
                   }
                   if (0 == sz)
                           break;
   
                   /* Find the end-of-phrase marker (or eoln). */
   
                   if (NULL == (eoph = memchr(ln, ';', sz)))
                           eoph = eoln - 3;
                   else
                           eoph++;
   
                   /* Only account for the "coding" phrase. */
   
                   if ((phsz = (size_t)(eoph - ln)) < 7 ||
                                   strncasecmp(ln, "coding:", 7)) {
                           sz -= phsz;
                           ln += phsz;
                           continue;
                   }
   
                   sz -= 7;
                   ln += 7;
   
                   while (sz > 0 && ' ' == *ln) {
                           ln++;
                           sz--;
                   }
                   if (0 == sz)
                           break;
   
                   /* Check us against known encodings. */
   
                   for (i = 0; i < (int)ENC__MAX; i++) {
                           nsz = strlen(encs[i].name);
                           if (phsz < nsz)
                                   continue;
                           if (strncasecmp(ln, encs[i].name, nsz))
                                   continue;
   
                           *enc = (enum enc)i;
                           return(1);
                   }
   
                   /* Unknown encoding. */
   
                   *enc = ENC__MAX;
                   return(1);
           }
   
           return(0);
   }
   
 int  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
 {  {
         int              i, ch, map, fd, rc;          int              i, ch, map, fd, rc;
         struct buf       buf;          struct buf       b;
         const char      *fn;          const char      *fn;
         enum enc         enc, def;          enum enc         enc, def;
           unsigned char    bom[3] = { 0xEF, 0xBB, 0xBF };
           size_t           offs;
         extern int       optind;          extern int       optind;
         extern char     *optarg;          extern char     *optarg;
   
Line 229  main(int argc, char *argv[])
Line 418  main(int argc, char *argv[])
         enc = def = ENC__MAX;          enc = def = ENC__MAX;
         map = 0;          map = 0;
   
         memset(&buf, 0, sizeof(struct buf));          memset(&b, 0, sizeof(struct buf));
   
         while (-1 != (ch = getopt(argc, argv, "D:e:rdvh")))          while (-1 != (ch = getopt(argc, argv, "D:e:rdvh")))
                 switch (ch) {                  switch (ch) {
                 case ('D'):                  case ('D'):
                         /* FALLTHROUGH */                          /* FALLTHROUGH */
                 case ('e'):                  case ('e'):
                         for (i = 0; i < ENC__MAX; i++) {                          for (i = 0; i < (int)ENC__MAX; i++) {
                                 if (strcasecmp(optarg, encs[i].name))                                  if (strcasecmp(optarg, encs[i].name))
                                         continue;                                          continue;
                                 break;                                  break;
                         }                          }
                         if (i < ENC__MAX) {                          if (i < (int)ENC__MAX) {
                                 if ('D' == ch)                                  if ('D' == ch)
                                         def = (enum enc)i;                                          def = (enum enc)i;
                                 else                                  else
Line 283  main(int argc, char *argv[])
Line 472  main(int argc, char *argv[])
                 }                  }
         }          }
   
         if ( ! read_whole_file(fn, fd, &buf, &map))          if ( ! read_whole_file(fn, fd, &b, &map))
                 goto out;                  goto out;
   
           /* Try to read the UTF-8 BOM. */
   
           if (ENC__MAX == enc)
                   if (b.sz > 3 && 0 == memcmp(b.buf, bom, 3)) {
                           b.offs = 3;
                           enc = ENC_UTF_8;
                   }
   
           /* Try reading from the "-*-" cue. */
   
         if (ENC__MAX == enc) {          if (ENC__MAX == enc) {
                 /* TODO: search for BOM. */                  offs = b.offs;
                   ch = cue_enc(&b, &offs, &enc);
                   if (0 == ch)
                           ch = cue_enc(&b, &offs, &enc);
         }          }
   
         /*          /*
Line 299  main(int argc, char *argv[])
Line 501  main(int argc, char *argv[])
         if (ENC__MAX == enc)          if (ENC__MAX == enc)
                 enc = ENC__MAX == def ? ENC_LATIN_1 : def;                  enc = ENC__MAX == def ? ENC_LATIN_1 : def;
   
         if ( ! (*encs[(int)enc].conv)(&buf))          if ( ! (*encs[(int)enc].conv)(&b)) {
                   fprintf(stderr, "%s: Bad encoding\n", fn);
                 goto out;                  goto out;
           }
   
         rc = EXIT_SUCCESS;          rc = EXIT_SUCCESS;
 out:  out:
   #if HAVE_MMAP
         if (map)          if (map)
                 munmap(buf.buf, buf.sz);                  munmap(b.buf, b.sz);
         else          else
                 free(buf.buf);  #endif
                   free(b.buf);
   
         if (fd > STDIN_FILENO)          if (fd > STDIN_FILENO)
                 close(fd);                  close(fd);

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.8

CVSweb