preconv.c revision 698f87a48e2e945bfe5493ce168e0d0ae1cedd5c
/* $Id: preconv.c,v 1.6 2013/06/02 03:52:21 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_MMAP
#endif
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
* The read_whole_file() and resize_buf() functions are copied from
* read.c, including all dependency code.
*/
enum enc {
ENC_UTF_8, /* UTF-8 */
ENC_US_ASCII, /* US-ASCII */
ENC_LATIN_1, /* Latin-1 */
};
struct buf {
char *buf; /* binary input buffer */
};
struct encode {
const char *name;
};
static int conv_latin_1(const struct buf *);
static int conv_us_ascii(const struct buf *);
static int conv_utf_8(const struct buf *);
static int read_whole_file(const char *, int,
struct buf *, int *);
static void usage(void);
};
static const char *progname;
static void
usage(void)
{
"[-D enc] "
"[-e ENC] "
"[file]\n", progname);
}
static int
conv_latin_1(const struct buf *b)
{
size_t i;
unsigned char cu;
const char *cp;
/*
* Latin-1 falls into the first 256 code-points of Unicode, so
* there's no need for any sort of translation. Just make the
* 8-bit characters use the Unicode escape.
* Note that binary values 128 < v < 160 are passed through
* unmodified to mandoc.
*/
}
return(1);
}
static int
conv_us_ascii(const struct buf *b)
{
/*
* US-ASCII has no conversion since it falls into the first 128
* bytes of Unicode.
*/
return(1);
}
static int
conv_utf_8(const struct buf *b)
{
unsigned int accum;
size_t i;
unsigned char cu;
const char *cp;
const long one = 1L;
state = 0;
accum = 0U;
be = 0;
/* Quick test for big-endian value. */
if ( ! (*((const char *)(&one))))
be = 1;
if (state) {
/* Bad sequence header. */
return(0);
}
/* Accept only legitimate bit patterns. */
/* Bad in-sequence bits. */
return(0);
}
/*
* 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.
*/
(accum << 24);
if (0 == state) {
accum = 0U;
}
/*
* Entering a UTF-8 state: if we encounter a
* UTF-8 bitmask, calculate the expected UTF-8
* state from it.
*/
break;
/* Accept only legitimate bit patterns. */
switch (state) {
case (4):
break;
}
/* Bad 4-sequence start bits. */
return(0);
case (3):
break;
}
/* Bad 3-sequence start bits. */
return(0);
case (2):
break;
}
/* Bad 2-sequence start bits. */
return(0);
default:
/* Bad sequence bit mask. */
return(0);
}
state--;
} else
}
if (0 != state) {
/* Bad trailing bits. */
return(0);
}
return(1);
}
static void
{
}
}
static int
read_whole_file(const char *f, int fd,
{
#ifdef HAVE_MMAP
perror(f);
return(0);
}
/*
* If we're a regular file, try just reading in the whole entry
* via mmap(). This is faster than reading it into blocks, and
* since each file is only a few bytes to begin with, I'm not
* concerned that this is going to tank any machines.
*/
return(0);
}
*with_mmap = 1;
return(1);
}
#endif
/*
* If this isn't a regular file (like, say, stdin), then we must
* go the old way and just read things in bit by bit.
*/
*with_mmap = 0;
off = 0;
for (;;) {
break;
}
if (ssz == 0) {
return(1);
}
if (ssz == -1) {
perror(f);
break;
}
}
return(0);
}
static int
{
int i;
/* Look for the end-of-line. */
return(-1);
/* Set next-line marker. */
return(0);
/* Move after the header and adjust for the trailer. */
ln += 7;
sz -= 10;
while (sz > 0) {
ln++;
sz--;
}
if (0 == sz)
break;
/* Find the end-of-phrase marker (or eoln). */
else
eoph++;
/* Only account for the "coding" phrase. */
continue;
}
sz -= 7;
ln += 7;
ln++;
sz--;
}
if (0 == sz)
break;
/* Check us against known encodings. */
for (i = 0; i < (int)ENC__MAX; i++) {
continue;
continue;
return(1);
}
/* Unknown encoding. */
return(1);
}
return(0);
}
int
{
struct buf b;
const char *fn;
extern int optind;
extern char *optarg;
else
++progname;
fn = "<stdin>";
fd = STDIN_FILENO;
rc = EXIT_FAILURE;
map = 0;
switch (ch) {
case ('D'):
/* FALLTHROUGH */
case ('e'):
for (i = 0; i < (int)ENC__MAX; i++) {
continue;
break;
}
if (i < (int)ENC__MAX) {
if ('D' == ch)
else
break;
}
return(EXIT_FAILURE);
case ('r'):
/* FALLTHROUGH */
case ('d'):
/* FALLTHROUGH */
case ('v'):
/* Compatibility with GNU preconv. */
break;
case ('h'):
/* Compatibility with GNU preconv. */
/* FALLTHROUGH */
default:
usage();
return(EXIT_FAILURE);
}
/*
* Open and read the first argument on the command-line.
* If we don't have one, we default to stdin.
*/
if (argc > 0) {
if (-1 == fd) {
return(EXIT_FAILURE);
}
}
goto out;
/* Try to read the UTF-8 BOM. */
b.offs = 3;
}
/* Try reading from the "-*-" cue. */
if (0 == ch)
}
/*
* No encoding has been detected.
* Thus, we either fall into our default encoder, if specified,
* or use Latin-1 if all else fails.
*/
goto out;
}
rc = EXIT_SUCCESS;
out:
#ifdef HAVE_MMAP
if (map)
else
#endif
if (fd > STDIN_FILENO)
return(rc);
}