Blame src/loadunimap.c

Packit Service 50ad14
/*
Packit Service 50ad14
 * loadunimap.c - aeb
Packit Service 50ad14
 *
Packit Service 50ad14
 * Version 1.09
Packit Service 50ad14
 */
Packit Service 50ad14
#include "config.h"
Packit Service 50ad14
Packit Service 50ad14
#include <errno.h>
Packit Service 50ad14
#include <stdio.h>
Packit Service 50ad14
#include <stdlib.h>
Packit Service 50ad14
#include <sysexits.h>
Packit Service 50ad14
#include <string.h>
Packit Service 50ad14
#include <ctype.h>
Packit Service 50ad14
#include <unistd.h>
Packit Service 50ad14
#include <fcntl.h>
Packit Service 50ad14
#include <sys/ioctl.h>
Packit Service 50ad14
#include <linux/kd.h>
Packit Service 50ad14
#include "paths.h"
Packit Service 50ad14
#include "getfd.h"
Packit Service 50ad14
#include "xmalloc.h"
Packit Service 50ad14
#include "findfile.h"
Packit Service 50ad14
#include "kdmapop.h"
Packit Service 50ad14
#include "psffontop.h"
Packit Service 50ad14
#include "loadunimap.h"
Packit Service 50ad14
#include "utf8.h"
Packit Service 50ad14
#include "psf.h"
Packit Service 50ad14
#include "nls.h"
Packit Service 50ad14
#include "kbd_error.h"
Packit Service 50ad14
Packit Service 50ad14
extern char *progname;
Packit Service 50ad14
extern int force;
Packit Service 50ad14
Packit Service 50ad14
static const char *const unidirpath[]  = { "", DATADIR "/" UNIMAPDIR "/", 0 };
Packit Service 50ad14
static const char *const unisuffixes[] = { "", ".uni", ".sfm", 0 };
Packit Service 50ad14
Packit Service 50ad14
#ifdef MAIN
Packit Service 50ad14
#include "version.h"
Packit Service 50ad14
int verbose = 0;
Packit Service 50ad14
int force   = 0;
Packit Service 50ad14
int debug   = 0;
Packit Service 50ad14
Packit Service 50ad14
static void __attribute__((noreturn))
Packit Service 50ad14
usage(void)
Packit Service 50ad14
{
Packit Service 50ad14
	fprintf(stderr,
Packit Service 50ad14
	        _("Usage:\n\t%s [-C console] [-o map.orig]\n"), progname);
Packit Service 50ad14
	exit(1);
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
int main(int argc, char *argv[])
Packit Service 50ad14
{
Packit Service 50ad14
	int fd, c;
Packit Service 50ad14
	char *console = NULL;
Packit Service 50ad14
	char *outfnam = NULL;
Packit Service 50ad14
	char *infnam  = "def.uni";
Packit Service 50ad14
Packit Service 50ad14
	set_progname(argv[0]);
Packit Service 50ad14
Packit Service 50ad14
	setlocale(LC_ALL, "");
Packit Service 50ad14
	bindtextdomain(PACKAGE_NAME, LOCALEDIR);
Packit Service 50ad14
	textdomain(PACKAGE_NAME);
Packit Service 50ad14
Packit Service 50ad14
	if (argc == 2 &&
Packit Service 50ad14
	    (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")))
Packit Service 50ad14
		print_version_and_exit();
Packit Service 50ad14
Packit Service 50ad14
	while ((c = getopt(argc, argv, "C:o:")) != EOF) {
Packit Service 50ad14
		switch (c) {
Packit Service 50ad14
			case 'C':
Packit Service 50ad14
				console = optarg;
Packit Service 50ad14
				break;
Packit Service 50ad14
			case 'o':
Packit Service 50ad14
				outfnam = optarg;
Packit Service 50ad14
				break;
Packit Service 50ad14
			default:
Packit Service 50ad14
				usage();
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if (argc > optind + 1 || (argc == optind && !outfnam))
Packit Service 50ad14
		usage();
Packit Service 50ad14
Packit Service 50ad14
	if ((fd = getfd(console)) < 0)
Packit Service 50ad14
		kbd_error(EXIT_FAILURE, 0, _("Couldn't get a file descriptor referring to the console"));
Packit Service 50ad14
Packit Service 50ad14
	if (outfnam) {
Packit Service 50ad14
		saveunicodemap(fd, outfnam);
Packit Service 50ad14
		if (argc == optind)
Packit Service 50ad14
			exit(0);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if (argc == optind + 1)
Packit Service 50ad14
		infnam = argv[optind];
Packit Service 50ad14
	loadunicodemap(fd, infnam);
Packit Service 50ad14
	exit(0);
Packit Service 50ad14
}
Packit Service 50ad14
#endif
Packit Service 50ad14
Packit Service 50ad14
/*
Packit Service 50ad14
 * Skip spaces and read U+1234 or return -1 for error.
Packit Service 50ad14
 * Return first non-read position in *p0 (unchanged on error).
Packit Service 50ad14
 */
Packit Service 50ad14
static int
Packit Service 50ad14
getunicode(char **p0)
Packit Service 50ad14
{
Packit Service 50ad14
	char *p = *p0;
Packit Service 50ad14
Packit Service 50ad14
	while (*p == ' ' || *p == '\t')
Packit Service 50ad14
		p++;
Packit Service 50ad14
#if 0
Packit Service 50ad14
	/* The code below also allows one to accept 'utf8' */
Packit Service 50ad14
	if (*p == '\'') {
Packit Service 50ad14
		int err;
Packit Service 50ad14
		unsigned long u;
Packit Service 50ad14
		char *p1 = p+1;
Packit Service 50ad14
Packit Service 50ad14
		/*
Packit Service 50ad14
		 * Read a single complete utf-8 character, and
Packit Service 50ad14
		 * expect it to be closed by a single quote.
Packit Service 50ad14
		 */
Packit Service 50ad14
		u = from_utf8(&p1, 0, &err;;
Packit Service 50ad14
		if (err || *p1 != '\'')
Packit Service 50ad14
			return -1;
Packit Service 50ad14
		*p0 = p1+1;
Packit Service 50ad14
		return u;
Packit Service 50ad14
	}
Packit Service 50ad14
#endif
Packit Service 50ad14
	if (*p != 'U' || p[1] != '+' || !isxdigit(p[2]) || !isxdigit(p[3]) ||
Packit Service 50ad14
	    !isxdigit(p[4]) || !isxdigit(p[5]) || isxdigit(p[6]))
Packit Service 50ad14
		return -1;
Packit Service 50ad14
	*p0 = p + 6;
Packit Service 50ad14
	return strtol(p + 2, 0, 16);
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
static struct unimapdesc descr;
Packit Service 50ad14
Packit Service 50ad14
static struct unipair *list = 0;
Packit Service 50ad14
static int listsz           = 0;
Packit Service 50ad14
static int listct           = 0;
Packit Service 50ad14
Packit Service 50ad14
static void
Packit Service 50ad14
addpair(int fp, int un)
Packit Service 50ad14
{
Packit Service 50ad14
	if (listct == listsz) {
Packit Service 50ad14
		listsz += 4096;
Packit Service 50ad14
		list = xrealloc((char *)list, listsz);
Packit Service 50ad14
	}
Packit Service 50ad14
	list[listct].fontpos = fp;
Packit Service 50ad14
	list[listct].unicode = un;
Packit Service 50ad14
	listct++;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
/*
Packit Service 50ad14
 * Syntax accepted:
Packit Service 50ad14
 *	<fontpos>	<unicode> <unicode> ...
Packit Service 50ad14
 *	<range>		idem
Packit Service 50ad14
 *	<range>		<unicode>
Packit Service 50ad14
 *	<range>		<unicode range>
Packit Service 50ad14
 *
Packit Service 50ad14
 * where <range> ::= <fontpos>-<fontpos>
Packit Service 50ad14
 * and <unicode> ::= U+<h><h><h><h>
Packit Service 50ad14
 * and <h> ::= <hexadecimal digit>
Packit Service 50ad14
 */
Packit Service 50ad14
Packit Service 50ad14
static void
Packit Service 50ad14
parseline(char *buffer, char *tblname)
Packit Service 50ad14
{
Packit Service 50ad14
	int fontlen = 512;
Packit Service 50ad14
	int i;
Packit Service 50ad14
	int fp0, fp1, un0, un1;
Packit Service 50ad14
	char *p, *p1;
Packit Service 50ad14
Packit Service 50ad14
	p = buffer;
Packit Service 50ad14
Packit Service 50ad14
	while (*p == ' ' || *p == '\t')
Packit Service 50ad14
		p++;
Packit Service 50ad14
	if (!*p || *p == '#')
Packit Service 50ad14
		return; /* skip comment or blank line */
Packit Service 50ad14
Packit Service 50ad14
	fp0 = strtol(p, &p1, 0);
Packit Service 50ad14
	if (p1 == p) {
Packit Service 50ad14
		fprintf(stderr, _("Bad input line: %s\n"), buffer);
Packit Service 50ad14
		exit(EX_DATAERR);
Packit Service 50ad14
	}
Packit Service 50ad14
	p = p1;
Packit Service 50ad14
Packit Service 50ad14
	while (*p == ' ' || *p == '\t')
Packit Service 50ad14
		p++;
Packit Service 50ad14
	if (*p == '-') {
Packit Service 50ad14
		p++;
Packit Service 50ad14
		fp1 = strtol(p, &p1, 0);
Packit Service 50ad14
		if (p1 == p) {
Packit Service 50ad14
			fprintf(stderr, _("Bad input line: %s\n"), buffer);
Packit Service 50ad14
			exit(EX_DATAERR);
Packit Service 50ad14
		}
Packit Service 50ad14
		p = p1;
Packit Service 50ad14
	} else
Packit Service 50ad14
		fp1 = 0;
Packit Service 50ad14
Packit Service 50ad14
	if (fp0 < 0 || fp0 >= fontlen) {
Packit Service 50ad14
		fprintf(stderr,
Packit Service 50ad14
		        _("%s: Glyph number (0x%x) larger than font length\n"),
Packit Service 50ad14
		        tblname, fp0);
Packit Service 50ad14
		exit(EX_DATAERR);
Packit Service 50ad14
	}
Packit Service 50ad14
	if (fp1 && (fp1 < fp0 || fp1 >= fontlen)) {
Packit Service 50ad14
		fprintf(stderr,
Packit Service 50ad14
		        _("%s: Bad end of range (0x%x)\n"),
Packit Service 50ad14
		        tblname, fp1);
Packit Service 50ad14
		exit(EX_DATAERR);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if (fp1) {
Packit Service 50ad14
		/* we have a range; expect the word "idem" or a Unicode range
Packit Service 50ad14
		   of the same length or a single Unicode value */
Packit Service 50ad14
		while (*p == ' ' || *p == '\t')
Packit Service 50ad14
			p++;
Packit Service 50ad14
		if (!strncmp(p, "idem", 4)) {
Packit Service 50ad14
			p += 4;
Packit Service 50ad14
			for (i = fp0; i <= fp1; i++)
Packit Service 50ad14
				addpair(i, i);
Packit Service 50ad14
			goto lookattail;
Packit Service 50ad14
		}
Packit Service 50ad14
Packit Service 50ad14
		un0 = getunicode(&p);
Packit Service 50ad14
		while (*p == ' ' || *p == '\t')
Packit Service 50ad14
			p++;
Packit Service 50ad14
		if (*p != '-') {
Packit Service 50ad14
			for (i = fp0; i <= fp1; i++)
Packit Service 50ad14
				addpair(i, un0);
Packit Service 50ad14
			goto lookattail;
Packit Service 50ad14
		}
Packit Service 50ad14
Packit Service 50ad14
		p++;
Packit Service 50ad14
		un1 = getunicode(&p);
Packit Service 50ad14
		if (un0 < 0 || un1 < 0) {
Packit Service 50ad14
			fprintf(stderr,
Packit Service 50ad14
			        _("%s: Bad Unicode range corresponding to "
Packit Service 50ad14
			          "font position range 0x%x-0x%x\n"),
Packit Service 50ad14
			        tblname, fp0, fp1);
Packit Service 50ad14
			exit(EX_DATAERR);
Packit Service 50ad14
		}
Packit Service 50ad14
		if (un1 - un0 != fp1 - fp0) {
Packit Service 50ad14
			fprintf(stderr,
Packit Service 50ad14
			        _("%s: Unicode range U+%x-U+%x not of the same"
Packit Service 50ad14
			          " length as font position range 0x%x-0x%x\n"),
Packit Service 50ad14
			        tblname, un0, un1, fp0, fp1);
Packit Service 50ad14
			exit(EX_DATAERR);
Packit Service 50ad14
		}
Packit Service 50ad14
		for (i = fp0; i <= fp1; i++)
Packit Service 50ad14
			addpair(i, un0 - fp0 + i);
Packit Service 50ad14
Packit Service 50ad14
	} else {
Packit Service 50ad14
		/* no range; expect a list of unicode values
Packit Service 50ad14
		   for a single font position */
Packit Service 50ad14
Packit Service 50ad14
		while ((un0 = getunicode(&p)) >= 0)
Packit Service 50ad14
			addpair(fp0, un0);
Packit Service 50ad14
	}
Packit Service 50ad14
lookattail:
Packit Service 50ad14
	while (*p == ' ' || *p == '\t')
Packit Service 50ad14
		p++;
Packit Service 50ad14
	if (*p && *p != '#')
Packit Service 50ad14
		fprintf(stderr, _("%s: trailing junk (%s) ignored\n"),
Packit Service 50ad14
		        tblname, p);
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void loadunicodemap(int fd, char *tblname)
Packit Service 50ad14
{
Packit Service 50ad14
	char buffer[65536];
Packit Service 50ad14
	char *p;
Packit Service 50ad14
	lkfile_t fp;
Packit Service 50ad14
Packit Service 50ad14
	if (lk_findfile(tblname, unidirpath, unisuffixes, &fp)) {
Packit Service 50ad14
		perror(tblname);
Packit Service 50ad14
		exit(EX_NOINPUT);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if (verbose)
Packit Service 50ad14
		printf(_("Loading unicode map from file %s\n"), fp.pathname);
Packit Service 50ad14
Packit Service 50ad14
	while (fgets(buffer, sizeof(buffer), fp.fd) != NULL) {
Packit Service 50ad14
		if ((p = strchr(buffer, '\n')) != NULL)
Packit Service 50ad14
			*p = '\0';
Packit Service 50ad14
		else
Packit Service 50ad14
			fprintf(stderr, _("%s: %s: Warning: line too long\n"),
Packit Service 50ad14
			        progname, tblname);
Packit Service 50ad14
Packit Service 50ad14
		parseline(buffer, tblname);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	lk_fpclose(&fp);
Packit Service 50ad14
Packit Service 50ad14
	if (listct == 0 && !force) {
Packit Service 50ad14
		fprintf(stderr,
Packit Service 50ad14
		        _("%s: not loading empty unimap\n"
Packit Service 50ad14
		          "(if you insist: use option -f to override)\n"),
Packit Service 50ad14
		        progname);
Packit Service 50ad14
	} else {
Packit Service 50ad14
		descr.entry_ct = listct;
Packit Service 50ad14
		descr.entries  = list;
Packit Service 50ad14
		if (loadunimap(fd, NULL, &descr))
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
		listct = 0;
Packit Service 50ad14
	}
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
static struct unimapdesc
Packit Service 50ad14
getunicodemap(int fd)
Packit Service 50ad14
{
Packit Service 50ad14
	struct unimapdesc unimap_descr;
Packit Service 50ad14
Packit Service 50ad14
	if (getunimap(fd, &unimap_descr))
Packit Service 50ad14
		exit(1);
Packit Service 50ad14
Packit Service 50ad14
#ifdef MAIN
Packit Service 50ad14
	fprintf(stderr, "# %d %s\n", unimap_descr.entry_ct,
Packit Service 50ad14
	        (unimap_descr.entry_ct == 1) ? _("entry") : _("entries"));
Packit Service 50ad14
#endif
Packit Service 50ad14
Packit Service 50ad14
	return unimap_descr;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void saveunicodemap(int fd, char *oufil)
Packit Service 50ad14
{
Packit Service 50ad14
	FILE *fpo;
Packit Service 50ad14
	struct unimapdesc unimap_descr;
Packit Service 50ad14
	struct unipair *unilist;
Packit Service 50ad14
	int i;
Packit Service 50ad14
Packit Service 50ad14
	if ((fpo = fopen(oufil, "w")) == NULL) {
Packit Service 50ad14
		perror(oufil);
Packit Service 50ad14
		exit(1);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	unimap_descr = getunicodemap(fd);
Packit Service 50ad14
	unilist      = unimap_descr.entries;
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < unimap_descr.entry_ct; i++)
Packit Service 50ad14
		fprintf(fpo, "0x%02x\tU+%04x\n", unilist[i].fontpos, unilist[i].unicode);
Packit Service 50ad14
	fclose(fpo);
Packit Service 50ad14
Packit Service 50ad14
	if (verbose)
Packit Service 50ad14
		printf(_("Saved unicode map on `%s'\n"), oufil);
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void appendunicodemap(int fd, FILE *fp, int fontsize, int utf8)
Packit Service 50ad14
{
Packit Service 50ad14
	struct unimapdesc unimap_descr;
Packit Service 50ad14
	struct unipair *unilist;
Packit Service 50ad14
	int i, j;
Packit Service 50ad14
Packit Service 50ad14
	unimap_descr = getunicodemap(fd);
Packit Service 50ad14
	unilist      = unimap_descr.entries;
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < fontsize; i++) {
Packit Service 50ad14
#if 0
Packit Service 50ad14
		/* More than one mapping is not a sequence! */
Packit Service 50ad14
		int no = 0;
Packit Service 50ad14
		for(j=0; j
Packit Service 50ad14
			if (unilist[j].fontpos == i)
Packit Service 50ad14
				no++;
Packit Service 50ad14
		if (no > 1)
Packit Service 50ad14
			appendseparator(fp, 1, utf8);
Packit Service 50ad14
#endif
Packit Service 50ad14
		if (debug)
Packit Service 50ad14
			printf("\nchar %03x: ", i);
Packit Service 50ad14
		for (j = 0; j < unimap_descr.entry_ct; j++)
Packit Service 50ad14
			if (unilist[j].fontpos == i) {
Packit Service 50ad14
				if (debug)
Packit Service 50ad14
					printf("%04x ", unilist[j].unicode);
Packit Service 50ad14
				appendunicode(fp, unilist[j].unicode, utf8);
Packit Service 50ad14
			}
Packit Service 50ad14
		appendseparator(fp, 0, utf8);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if (debug)
Packit Service 50ad14
		printf("\n");
Packit Service 50ad14
	if (verbose)
Packit Service 50ad14
		printf(_("Appended Unicode map\n"));
Packit Service 50ad14
}