capi4yaps/cv.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;
}
/*}}}*/