Logo Search packages:      
Sourcecode: kbd version File versions  Download package

loadunimap.c

/*
 * loadunimap.c - aeb
 *
 * Version 1.09
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
#include "paths.h"
#include "getfd.h"
#include "xmalloc.h"
#include "findfile.h"
#include "kdmapop.h"
#include "psffontop.h"
#include "loadunimap.h"
#include "utf8.h"
#include "psf.h"
#include "nls.h"

extern char *progname;
extern int force;

static char *unidirpath[] = { "", DATADIR "/" UNIMAPDIR "/", 0 };
static char *unisuffixes[] = { "", ".uni", 0 };

#ifdef MAIN
#include "version.h"
int verbose = 0;
int force = 0;

static void
usage(void) {
        fprintf(stderr,
            _("Usage:\n\t%s [-C console] [-o map.orig]\n"), progname);
        exit(1);
}

int
main(int argc, char *argv[]) {
      int fd, c;
      char *console = NULL;
      char *outfnam = NULL;
      char *infnam = "def.uni";

      set_progname(argv[0]);

      setlocale(LC_ALL, "");
      bindtextdomain(PACKAGE, LOCALEDIR);
      textdomain(PACKAGE);

      if (argc == 2 &&
          (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")))
            print_version_and_exit();

      while ((c = getopt(argc, argv, "C:o:")) != EOF) {
            switch (c) {
            case 'C':
                  console = optarg;
                  break;
            case 'o':
                  outfnam = optarg;
                  break;
            default:
                  usage();
            }
      }

      if (argc > 2 || (argc == 1 && !outfnam))
            usage();

      fd = getfd(console);

      if (outfnam) {
            saveunicodemap(fd, outfnam);
            if (argc == 1)
                  exit(0);
      }

      if (argc == 2)
            infnam = argv[optind];
      loadunicodemap(fd, infnam);
      exit(0);
}
#endif

/*
 * Skip spaces and read U+1234 or return -1 for error.
 * Return first non-read position in *p0 (unchanged on error).
 */ 
static int
getunicode(char **p0) {
      char *p = *p0;

      while (*p == ' ' || *p == '\t')
            p++;
#if 0
      /* The code below also allows one to accept 'utf8' */
      if (*p == '\'') {
            int err;
            unsigned long u;
            char *p1 = p+1;

            /*
             * Read a single complete utf-8 character, and
             * expect it to be closed by a single quote.
             */
            u = from_utf8(&p1, 0, &err);
            if (err || *p1 != '\'')
                  return -1;
            *p0 = p1+1;
            return u;
      }
#endif
      if (*p != 'U' || p[1] != '+' || !isxdigit(p[2]) || !isxdigit(p[3]) ||
          !isxdigit(p[4]) || !isxdigit(p[5]) || isxdigit(p[6]))
            return -1;
      *p0 = p+6;
      return strtol(p+2,0,16);
}

static struct unimapdesc descr;

static struct unipair *list = 0;
static int listsz = 0;
static int listct = 0;

static void
addpair(int fp, int un) {
    if (listct == listsz) {
      listsz += 4096;
      list = xrealloc((char *)list, listsz);
    }
    list[listct].fontpos = fp;
    list[listct].unicode = un;
    listct++;
}

/*
 * Syntax accepted:
 *    <fontpos>   <unicode> <unicode> ...
 *    <range>           idem
 *    <range>           <unicode>
 *    <range>           <unicode range>
 *
 * where <range> ::= <fontpos>-<fontpos>
 * and <unicode> ::= U+<h><h><h><h>
 * and <h> ::= <hexadecimal digit>
 */

static void
parseline(char *buffer, char *tblname) {
      int fontlen = 512;
      int i;
      int fp0, fp1, un0, un1;
      char *p, *p1;

      p = buffer;

      while (*p == ' ' || *p == '\t')
            p++;
      if (!*p || *p == '#')
            return;     /* skip comment or blank line */

      fp0 = strtol(p, &p1, 0);
      if (p1 == p) {
            fprintf(stderr, _("Bad input line: %s\n"), buffer);
            exit(EX_DATAERR);
      }
      p = p1;

      while (*p == ' ' || *p == '\t')
            p++;
      if (*p == '-') {
            p++;
            fp1 = strtol(p, &p1, 0);
            if (p1 == p) {
                  fprintf(stderr, _("Bad input line: %s\n"), buffer);
                  exit(EX_DATAERR);
            }
            p = p1;
      } else
            fp1 = 0;

      if ( fp0 < 0 || fp0 >= fontlen ) {
            fprintf(stderr,
                  _("%s: Glyph number (0x%x) larger than font length\n"),
                  tblname, fp0);
            exit(EX_DATAERR);
      }
      if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) ) {
            fprintf(stderr,
                  _("%s: Bad end of range (0x%x)\n"),
                  tblname, fp1);
            exit(EX_DATAERR);
      }

      if (fp1) {
            /* we have a range; expect the word "idem" or a Unicode range
               of the same length or a single Unicode value */
            while (*p == ' ' || *p == '\t')
                  p++;
            if (!strncmp(p, "idem", 4)) {
                  p += 4;
                  for (i=fp0; i<=fp1; i++)
                        addpair(i,i);
                  goto lookattail;
            }

            un0 = getunicode(&p);
            while (*p == ' ' || *p == '\t')
                  p++;
            if (*p != '-') {
                  for (i=fp0; i<=fp1; i++)
                        addpair(i,un0);
                  goto lookattail;
            }

            p++;
            un1 = getunicode(&p);
            if (un0 < 0 || un1 < 0) {
                  fprintf(stderr,
                        _("%s: Bad Unicode range corresponding to "
                          "font position range 0x%x-0x%x\n"),
                        tblname, fp0, fp1);
                  exit(EX_DATAERR);
            }
            if (un1 - un0 != fp1 - fp0) {
                  fprintf(stderr,
                        _("%s: Unicode range U+%x-U+%x not of the same"
                          " length as font position range 0x%x-0x%x\n"),
                        tblname, un0, un1, fp0, fp1);
                  exit(EX_DATAERR);
            }
            for(i=fp0; i<=fp1; i++)
                  addpair(i,un0-fp0+i);

      } else {
            /* no range; expect a list of unicode values
               for a single font position */

            while ( (un0 = getunicode(&p)) >= 0 )
                  addpair(fp0, un0);
      }
 lookattail:
      while (*p == ' ' || *p == '\t')
            p++;
      if (*p && *p != '#')
            fprintf(stderr, _("%s: trailing junk (%s) ignored\n"),
                  tblname, p);
}

void
loadunicodemap(int fd, char *tblname) {
      FILE *mapf;
      char buffer[65536];
      char *p;

      mapf = findfile(tblname, unidirpath, unisuffixes);
      if ( !mapf ) {
            perror(tblname);
            exit(EX_NOINPUT);
      }

      if (verbose)
            printf(_("Loading unicode map from file %s\n"), pathname);

      while ( fgets(buffer, sizeof(buffer), mapf) != NULL ) {
            if ( (p = strchr(buffer, '\n')) != NULL )
                  *p = '\0';
            else
                  fprintf(stderr, _("%s: %s: Warning: line too long\n"),
                        progname, tblname);

            parseline(buffer, tblname);
      }

      fpclose(mapf);

      if (listct == 0 && !force) {
            fprintf(stderr,
                  _("%s: not loading empty unimap\n"
                    "(if you insist: use option -f to override)\n"),
                  progname);
      } else {
            descr.entry_ct = listct;
            descr.entries = list;
            if (loadunimap (fd, NULL, &descr))
                  exit(1);
            listct = 0;
      }
}

static struct unimapdesc
getunicodemap(int fd) {
  struct unimapdesc descr;

  if (getunimap(fd, &descr))
        exit(1);

#ifdef MAIN
  fprintf(stderr, "# %d %s\n", descr.entry_ct,
       (descr.entry_ct == 1) ? _("entry") : _("entries"));
#endif

  return descr;
}

void
saveunicodemap(int fd, char *oufil) {
  FILE *fpo;
  struct unimapdesc descr;
  struct unipair *list;
  int i;

  if ((fpo = fopen(oufil, "w")) == NULL) {
      perror(oufil);
      exit(1);
  }

  descr = getunicodemap(fd);
  list = descr.entries;

  for(i=0; i<descr.entry_ct; i++)
      fprintf(fpo, "0x%02x\tU+%04x\n", list[i].fontpos, list[i].unicode);
  fclose(fpo);

  if (verbose)
    printf(_("Saved unicode map on `%s'\n"), oufil);
}

void
appendunicodemap(int fd, FILE *fp, int fontsize, int utf8) {
      struct unimapdesc descr;
      struct unipair *list;
      int i, j;

      descr = getunicodemap(fd);
      list = descr.entries;

      for(i=0; i<fontsize; i++) {
            for(j=0; j<descr.entry_ct; j++)
                  if (list[j].fontpos == i)
                        appendunicode(fp, list[j].unicode, utf8);
            appendseparator(fp, 0, utf8);
      }

      if (verbose)
            printf(_("Appended Unicode map\n"));
}

Generated by  Doxygen 1.6.0   Back to index