222 lines
3.6 KiB
C
222 lines
3.6 KiB
C
/* -*- mode: c; mode: fold -*- */
|
|
# include "config.h"
|
|
# include <stdio.h>
|
|
# include <stdlib.h>
|
|
# include <ctype.h>
|
|
# include "pager.h"
|
|
|
|
/*{{{ typedefs */
|
|
typedef struct {
|
|
# ifndef NDEBUG
|
|
# define MAGIC MKMAGIC ('c', 'o', 'n', 'v')
|
|
long magic;
|
|
# endif /* NDEBUG */
|
|
int c[256]; /* the conversion table */
|
|
} conv;
|
|
/*}}}*/
|
|
/*{{{ new/free */
|
|
void *
|
|
cv_new (void)
|
|
{
|
|
conv *c;
|
|
int n;
|
|
|
|
if (c = (conv *) malloc (sizeof (conv))) {
|
|
# ifndef NDEBUG
|
|
c -> magic = MAGIC;
|
|
# endif /* NDEBUG */
|
|
for (n = 0; n < 256; ++n)
|
|
c -> c[n] = n;
|
|
}
|
|
return (void *) c;
|
|
}
|
|
|
|
void *
|
|
cv_free (void *cv)
|
|
{
|
|
conv *c = (conv *) cv;
|
|
|
|
MCHK (c);
|
|
if (c)
|
|
free (c);
|
|
return NULL;
|
|
}
|
|
/*}}}*/
|
|
/*{{{ reverse */
|
|
void *
|
|
cv_reverse (void *src)
|
|
{
|
|
conv *s = (conv *) src;
|
|
conv *c;
|
|
int n;
|
|
|
|
MCHK (s);
|
|
if (c = (conv *) cv_new ())
|
|
for (n = 0; n < 256; ++n)
|
|
if (s -> c[n] != -1)
|
|
c -> c[s -> c[n]] = n;
|
|
return (void *) c;
|
|
}
|
|
/*}}}*/
|
|
/*{{{ define/undefine */
|
|
static char_t
|
|
getval (char *str)
|
|
{
|
|
char_t ret;
|
|
|
|
if (isdigit (*str))
|
|
ret = (char_t) strtol (str, NULL, 0);
|
|
else if (! *(str + 1))
|
|
ret = (char_t) *str;
|
|
else if (*str == '^') {
|
|
++str;
|
|
ret = (char_t) (*str == '?' ? 0x7f : (*str & 0x1f));
|
|
} else if (*str == '\\') {
|
|
++str;
|
|
switch (*str) {
|
|
case 'a': ret = (char_t) '\a'; break;
|
|
case 'b': ret = (char_t) '\b'; break;
|
|
case 'e': ret = (char_t) '\x1b'; break;
|
|
case 'f': ret = (char_t) '\f'; break;
|
|
case 'l': ret = (char_t) '\012'; break;
|
|
case 'n': ret = (char_t) '\n'; break;
|
|
case 'r': ret = (char_t) '\r'; break;
|
|
case 's': ret = (char_t) ' '; break;
|
|
case 't': ret = (char_t) '\t'; break;
|
|
case 'v': ret = (char_t) '\v'; break;
|
|
default: ret = (char_t) *str; break;
|
|
}
|
|
} else
|
|
ret = (char_t) *str;
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
cv_define (void *cv, char_t src, char_t dst)
|
|
{
|
|
conv *c = (conv *) cv;
|
|
|
|
MCHK (c);
|
|
if (c)
|
|
c -> c[src] = dst;
|
|
}
|
|
|
|
void
|
|
cv_sdefine (void *cv, char *src, char *dst)
|
|
{
|
|
cv_define (cv, getval (src), getval (dst));
|
|
}
|
|
|
|
void
|
|
cv_undefine (void *cv, char_t ch)
|
|
{
|
|
conv *c = (conv *) cv;
|
|
|
|
MCHK (c);
|
|
if (c)
|
|
c -> c[ch] = ch;
|
|
}
|
|
|
|
void
|
|
cv_sundefine (void *cv, char *ch)
|
|
{
|
|
cv_undefine (cv, getval (ch));
|
|
}
|
|
|
|
void
|
|
cv_invalid (void *cv, char_t ch)
|
|
{
|
|
conv *c = (conv *) cv;
|
|
|
|
MCHK (c);
|
|
if (c)
|
|
c -> c[ch] = -1;
|
|
}
|
|
|
|
void
|
|
cv_sinvalid (void *cv, char *ch)
|
|
{
|
|
cv_invalid (cv, getval (ch));
|
|
}
|
|
/*}}}*/
|
|
/*{{{ read/write table */
|
|
int
|
|
cv_read_table (void *cv, char *fname)
|
|
{
|
|
conv *c = (conv *) cv;
|
|
FILE *fp;
|
|
char *line;
|
|
char *sp, *dp;
|
|
|
|
MCHK (c);
|
|
if ((! c) || (! (fp = fopen (fname, "r"))))
|
|
return -1;
|
|
while (line = getline (fp, True)) {
|
|
for (sp = line; isspace (*sp); ++sp)
|
|
;
|
|
if (*sp && (*sp != '#')) {
|
|
dp = skip (sp);
|
|
skip (dp);
|
|
if (*sp)
|
|
if (*dp)
|
|
c -> c[getval (sp)] = getval (dp);
|
|
else
|
|
c -> c[getval (sp)] = -1;
|
|
|
|
}
|
|
free (line);
|
|
}
|
|
fclose (fp);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
cv_write_table (void *cv, char *fname)
|
|
{
|
|
conv *c = (conv *) cv;
|
|
FILE *fp;
|
|
int n;
|
|
|
|
MCHK (c);
|
|
if ((! c) || (! (fp = fopen (fname, "w"))))
|
|
return -1;
|
|
fprintf (fp, "#\tThis file is generated automatically\n");
|
|
for (n = 0; n < 256; ++n) {
|
|
if ((! (n & 0x80)) && isprint (n))
|
|
fprintf (fp, "#\t%c\n", (char) n);
|
|
if (c -> c[n] != -1)
|
|
fprintf (fp, "0x%02x\t0x%02x\n", n, c -> c[n]);
|
|
else
|
|
fprintf (fp, "0x%02x\n", n);
|
|
}
|
|
fclose (fp);
|
|
return 0;
|
|
}
|
|
/*}}}*/
|
|
/*{{{ merging */
|
|
void
|
|
cv_merge (void *cv, void *in, Bool second)
|
|
{
|
|
conv *c = (conv *) cv,
|
|
*i = (conv *) in;
|
|
int n;
|
|
|
|
MCHK (c);
|
|
MCHK (i);
|
|
if (c && i)
|
|
for (n = 0; n < 256; ++n)
|
|
if (second || (c -> c[n] == n))
|
|
c -> c[n] = i -> c[n];
|
|
}
|
|
/*}}}*/
|
|
/*{{{ converting */
|
|
int
|
|
cv_conv (void *cv, char_t ch)
|
|
{
|
|
conv *c = (conv *) cv;
|
|
|
|
MCHK (c);
|
|
return c ? c -> c[ch] : (int) ch;
|
|
}
|
|
/*}}}*/
|