#ifndef lint
#ifdef __GNUC__
static char rcsid[] __attribute__ ((unused)) = "Id: remap.c,v 1.9 1999/06/16 16:13:11 mleisher Exp $";
#else
static char rcsid[] = "Id: remap.c,v 1.9 1999/06/16 16:13:11 mleisher Exp $";
#endif
#endif
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#else
#include <stdlib.h>
#include <unistd.h>
#endif
typedef struct {
unsigned char *bfield;
unsigned long bsize;
unsigned long bused;
unsigned char **field;
unsigned long size;
unsigned long used;
} list_t;
typedef int (*scanlines_callback_t)(
#ifdef __STDC__
unsigned char *line,
unsigned long linelen,
unsigned long lineno,
void *client_data
#endif
);
#define setsbit(m, cc) (m[(cc) >> 3] |= (1 << ((cc) & 7)))
#define sbitset(m, cc) (m[(cc) >> 3] & (1 << ((cc) & 7)))
static unsigned char empty[1] = { 0 };
static void
#ifdef __STDC__
splitline(unsigned char *separators, unsigned char *line,
unsigned long linelen, list_t *list)
#else
splitline(separators, line, linelen, list)
unsigned char *separators, *line;
unsigned long linelen;
list_t *list;
#endif
{
int mult, final_empty;
unsigned char *sp, *ep, *end;
unsigned char seps[32];
list->used = list->bused = 0;
if (linelen == 0 || line[0] == 0)
return;
if (separators == 0 || *separators == 0) {
if (linelen > list->bsize) {
if (list->bsize)
list->bfield = (unsigned char *) malloc(linelen);
else
list->bfield = (unsigned char *) realloc(list->bfield, linelen);
list->bsize = linelen;
}
list->bused = linelen;
(void) memcpy(list->bfield, line, linelen);
return;
}
(void) memset((char *) seps, 0, 32);
for (mult = 0, sp = separators; sp && *sp; sp++) {
if (*sp == '+' && *(sp + 1) == 0)
mult = 1;
else
setsbit(seps, *sp);
}
for (final_empty = 0, sp = ep = line, end = sp + linelen;
sp < end && *sp;) {
for (; ep < end && *ep && !sbitset(seps, *ep); ep++) ;
if (list->used == list->size) {
if (list->size == 0)
list->field = (unsigned char **)
malloc(sizeof(unsigned char *) << 3);
else
list->field = (unsigned char **)
realloc((char *) list->field,
sizeof(unsigned char *) * (list->size + 8));
list->size += 8;
}
list->field[list->used++] = (ep > sp) ? sp : empty;
sp = ep;
if (mult) {
for (; ep < end && *ep && sbitset(seps, *ep); ep++)
*ep = 0;
} else
*ep++ = 0;
final_empty = (ep > sp && *ep == 0);
sp = ep;
}
if (list->used + final_empty + 1 >= list->size) {
if (list->used == list->size) {
if (list->size == 0)
list->field = (unsigned char **)
malloc(sizeof(unsigned char *) << 3);
else
list->field = (unsigned char **)
realloc((unsigned char *) list->field,
sizeof(char *) * (list->size + 8));
list->size += 8;
}
}
if (final_empty)
list->field[list->used++] = empty;
if (list->used == list->size) {
if (list->size == 0)
list->field = (unsigned char **)
malloc(sizeof(unsigned char *) << 3);
else
list->field = (unsigned char **)
realloc((char *) list->field,
sizeof(unsigned char *) * (list->size + 8));
list->size += 8;
}
list->field[list->used] = 0;
}
static int
#ifdef __STDC__
scanlines(int fd, scanlines_callback_t callback, void *client_data,
unsigned long *lineno)
#else
scanlines(fd, callback, client_data, lineno)
int fd;
scanlines_callback_t callback;
void *client_data;
unsigned long *lineno;
#endif
{
unsigned long lno;
int n, res, done, refill, bytes, hold;
char *ls, *le, *pp, *pe, *hp;
char buf[65536];
if (callback == 0)
return -1;
lno = 1;
(void) memset(buf, 0, 65536);
res = done = 0;
pp = ls = le = buf;
bytes = 65536;
while (!done && (n = read(fd, pp, bytes)) > 0) {
pe = pp + n;
for (refill = 0; done == 0 && refill == 0; ) {
while (le < pe && *le != '\n' && *le != '\r')
le++;
if (le == pe) {
pp = buf + (((ls - buf) >> 13) << 13);
n = pp - buf;
ls -= n;
le -= n;
n = pe - pp;
(void) memcpy(buf, pp, n);
pp = buf + n;
bytes = 65536 - n;
refill = 1;
} else {
hp = le;
hold = *le;
*le = 0;
if (callback && *ls != '#' && *ls != 0x1a && le > ls &&
(res = (*callback)((unsigned char *) ls, le - ls, lno,
client_data)) != 0)
done = 1;
else {
ls = ++le;
if (le < pe && hold == '\n' && *le =='\r')
ls = ++le;
}
lno++;
*hp = hold;
}
}
}
*lineno = lno;
return res;
}
static unsigned char a2i[128] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static unsigned char odigits[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static unsigned char ddigits[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static unsigned char hdigits[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define isdigok(m, d) (m[(d) >> 3] & (1 << ((d) & 7)))
static unsigned short
#ifdef __STDC__
my_atous(unsigned char *s, unsigned char **end, int base)
#else
my_atous(s, end, base)
unsigned char *s, **end;
int base;
#endif
{
unsigned short v;
unsigned char *dmap;
if (s == 0 || *s == 0)
return 0;
switch (base) {
case 8: dmap = odigits; break;
case 16: dmap = hdigits; break;
default: base = 10; dmap = ddigits; break;
}
if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) {
base = 16;
dmap = hdigits;
s += 2;
}
for (v = 0; isdigok(dmap, *s); s++)
v = (v * base) + a2i[(int) *s];
if (end != 0)
*end = s;
return v;
}
static char *registry;
static char *encoding;
typedef struct {
unsigned short key;
unsigned short val;
unsigned long sibs;
unsigned long kids;
} node_t;
static node_t *nodes;
static unsigned long nodes_size = 0;
static unsigned long nodes_used = 0;
static unsigned long
#ifdef __STDC__
getnode(unsigned short key)
#else
getnode(key)
unsigned short key;
#endif
{
unsigned long loc;
node_t *np;
if (nodes_used == nodes_size) {
if (nodes_size == 0)
nodes = (node_t *) malloc(sizeof(node_t) << 7);
else
nodes = (node_t *) realloc((char *) nodes, sizeof(node_t) *
(nodes_size + 128));
np = nodes + nodes_size;
nodes_size += 128;
(void) memset((char *) np, 0, sizeof(node_t) << 7);
}
loc = nodes_used++;
np = nodes + loc;
np->kids = np->sibs = 0;
np->key = key;
return loc;
}
static void
#ifdef __STDC__
trie_insert(unsigned short key, unsigned short val)
#else
trie_insert(key, val)
unsigned short key, val;
#endif
{
unsigned long i, n, t, l;
unsigned short codes[2];
codes[0] = (key >> 8) & 0xff;
codes[1] = key & 0xff;
for (i = t = 0; i < 2; i++) {
if (nodes[t].kids == 0) {
n = getnode(codes[i]);
nodes[t].kids = t = n;
} else if (nodes[nodes[t].kids].key == codes[i])
t = nodes[t].kids;
else if (nodes[nodes[t].kids].key > codes[i]) {
n = getnode(codes[i]);
nodes[n].sibs = nodes[t].kids;
nodes[t].kids = t = n;
} else {
t = nodes[t].kids;
for (l = t; nodes[t].sibs && nodes[t].key < codes[i]; ) {
l = t;
t = nodes[t].sibs;
}
if (nodes[t].key < codes[i]) {
n = getnode(codes[i]);
nodes[t].sibs = t = n;
} else if (nodes[t].key > codes[i]) {
n = getnode(codes[i]);
nodes[n].sibs = t;
nodes[l].sibs = t = n;
}
}
}
nodes[t].val = val;
}
static list_t list;
static int
#ifdef __STDC__
add_mapping(unsigned char *line, unsigned long linelen, unsigned long lineno,
void *client_data)
#else
add_mapping(line, linelen, lineno, client_data)
unsigned char *line;
unsigned long linelen, lineno;
void *client_data;
#endif
{
unsigned short key, val;
splitline((unsigned char *) " \t+", line, linelen, &list);
if (memcmp((char *) list.field[0], "REGISTRY", 8) == 0) {
if (registry != 0)
free((char *) registry);
if ((val = strlen((char *) list.field[1])) == 0)
registry = 0;
else {
registry = (char *) malloc(val + 1);
(void) memcpy(registry, (char *) list.field[1], val + 1);
}
return 0;
}
if (memcmp((char *) list.field[0], "ENCODING", 8) == 0) {
if (encoding != 0)
free((char *) encoding);
if ((val = strlen((char *) list.field[1])) == 0)
encoding = 0;
else {
encoding = (char *) malloc(val + 1);
(void) memcpy(encoding, (char *) list.field[1], val + 1);
}
return 0;
}
key = my_atous(list.field[1], 0, 16);
val = my_atous(list.field[0], 0, 16);
trie_insert(key, val);
return 0;
}
int
#ifdef __STDC__
ttf2bdf_load_map(FILE *in)
#else
ttf2bdf_load_map(in)
FILE *in;
#endif
{
unsigned long lineno;
if (nodes_size == 0) {
nodes = (node_t *) malloc(sizeof(node_t) << 7);
nodes_size = 128;
}
if (nodes_size > 0)
(void) memset((char *) nodes, 0, sizeof(node_t) * nodes_size);
nodes_used = 1;
return scanlines(fileno(in), add_mapping, 0, &lineno);
}
void
#ifdef __STDC__
ttf2bdf_free_map(void)
#else
ttf2bdf_free_map()
#endif
{
if (registry != 0)
free((char *) registry);
if (encoding != 0)
free((char *) encoding);
registry = encoding = 0;
if (list.size > 0)
free((char *) list.field);
list.size = list.used = 0;
if (nodes_size > 0)
free((char *) nodes);
nodes_size = nodes_used = 0;
}
int
#ifdef __STDC__
ttf2bdf_remap(unsigned short *code)
#else
ttf2bdf_remap(code)
unsigned short *code;
#endif
{
unsigned long i, n, t;
unsigned short c, codes[2];
if (nodes_used == 0)
return 1;
c = *code;
codes[0] = (c >> 8) & 0xff;
codes[1] = c & 0xff;
for (i = n = 0; i < 2; i++) {
t = nodes[n].kids;
if (t == 0)
return 0;
for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs);
if (nodes[t].key != codes[i])
return 0;
n = t;
}
*code = nodes[n].val;
return 1;
}
void
#ifdef __STDC__
ttf2bdf_remap_charset(char **registry_name, char **encoding_name)
#else
ttf2bdf_remap_charset(registry_name, encoding_name)
char **registry_name, **encoding_name;
#endif
{
if (registry_name != 0)
*registry_name = registry;
if (encoding_name != 0)
*encoding_name = encoding;
}