Blame src/encparse.c

Packit 2bba5f
/*
Packit 2bba5f
Copyright (c) 1998-2001 by Juliusz Chroboczek
Packit 2bba5f
Packit 2bba5f
Permission is hereby granted, free of charge, to any person obtaining a copy
Packit 2bba5f
of this software and associated documentation files (the "Software"), to deal
Packit 2bba5f
in the Software without restriction, including without limitation the rights
Packit 2bba5f
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Packit 2bba5f
copies of the Software, and to permit persons to whom the Software is
Packit 2bba5f
furnished to do so, subject to the following conditions:
Packit 2bba5f
Packit 2bba5f
The above copyright notice and this permission notice shall be included in
Packit 2bba5f
all copies or substantial portions of the Software.
Packit 2bba5f
Packit 2bba5f
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit 2bba5f
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit 2bba5f
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit 2bba5f
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit 2bba5f
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Packit 2bba5f
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Packit 2bba5f
THE SOFTWARE.
Packit 2bba5f
*/
Packit 2bba5f
Packit 2bba5f
/* Parser for encoding files */
Packit 2bba5f
Packit 2bba5f
/* This code assumes that we are using ASCII.  We don't use the ctype
Packit 2bba5f
   functions, as they depend on the current locale.  On the other
Packit 2bba5f
   hand, we do use strcasecmp, but only on strings that we've checked
Packit 2bba5f
   to be pure ASCII.  Bloody ``Code Set Independence''. */
Packit 2bba5f
Packit 2bba5f
#include <string.h>
Packit 2bba5f
#include <strings.h>
Packit 2bba5f
#include <stdio.h>
Packit 2bba5f
Packit 2bba5f
#include <stdlib.h>
Packit 2bba5f
Packit 2bba5f
#include "zlib.h"
Packit 2bba5f
typedef gzFile FontFilePtr;
Packit 2bba5f
Packit 2bba5f
#define FontFileGetc(f) gzgetc(f)
Packit 2bba5f
#define FontFileOpen(filename) gzopen(filename, "rb")
Packit 2bba5f
#define FontFileClose(f) gzclose(f)
Packit 2bba5f
Packit 2bba5f
#define MAXFONTFILENAMELEN 1024
Packit 2bba5f
#define MAXFONTNAMELEN 1024
Packit 2bba5f
Packit 2bba5f
#include <X11/fonts/fontenc.h>
Packit 2bba5f
#include "fontencI.h"
Packit 2bba5f
Packit 2bba5f
#define MAXALIASES 20
Packit 2bba5f
Packit 2bba5f
#define EOF_TOKEN -1
Packit 2bba5f
#define ERROR_TOKEN -2
Packit 2bba5f
#define EOL_TOKEN 0
Packit 2bba5f
#define NUMBER_TOKEN 1
Packit 2bba5f
#define KEYWORD_TOKEN 2
Packit 2bba5f
Packit 2bba5f
#define EOF_LINE -1
Packit 2bba5f
#define ERROR_LINE -2
Packit 2bba5f
#define STARTENCODING_LINE 1
Packit 2bba5f
#define STARTMAPPING_LINE 2
Packit 2bba5f
#define ENDMAPPING_LINE 3
Packit 2bba5f
#define CODE_LINE 4
Packit 2bba5f
#define CODE_RANGE_LINE 5
Packit 2bba5f
#define CODE_UNDEFINE_LINE 6
Packit 2bba5f
#define NAME_LINE 7
Packit 2bba5f
#define SIZE_LINE 8
Packit 2bba5f
#define ALIAS_LINE 9
Packit 2bba5f
#define FIRSTINDEX_LINE 10
Packit 2bba5f
Packit 2bba5f
/* Return from lexer */
Packit 2bba5f
#define MAXKEYWORDLEN 100
Packit 2bba5f
Packit 2bba5f
static long number_value;
Packit 2bba5f
static char keyword_value[MAXKEYWORDLEN + 1];
Packit 2bba5f
Packit 2bba5f
static long value1, value2, value3;
Packit 2bba5f
Packit 2bba5f
/* Lexer code */
Packit 2bba5f
Packit 2bba5f
/* Skip to the beginning of new line */
Packit 2bba5f
static void
Packit 2bba5f
skipEndOfLine(FontFilePtr f, int c)
Packit 2bba5f
{
Packit 2bba5f
    if (c == 0)
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
Packit 2bba5f
    for (;;)
Packit 2bba5f
        if (c <= 0 || c == '\n')
Packit 2bba5f
            return;
Packit 2bba5f
        else
Packit 2bba5f
            c = FontFileGetc(f);
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
/* Get a number; we're at the first digit. */
Packit 2bba5f
static unsigned
Packit 2bba5f
getnum(FontFilePtr f, int c, int *cp)
Packit 2bba5f
{
Packit 2bba5f
    unsigned n = 0;
Packit 2bba5f
    int base = 10;
Packit 2bba5f
Packit 2bba5f
    /* look for `0' or `0x' prefix */
Packit 2bba5f
    if (c == '0') {
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
        base = 8;
Packit 2bba5f
        if (c == 'x' || c == 'X') {
Packit 2bba5f
            base = 16;
Packit 2bba5f
            c = FontFileGetc(f);
Packit 2bba5f
        }
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    /* accumulate digits */
Packit 2bba5f
    for (;;) {
Packit 2bba5f
        if ('0' <= c && c <= '9') {
Packit 2bba5f
            n *= base;
Packit 2bba5f
            n += c - '0';
Packit 2bba5f
        }
Packit 2bba5f
        else if ('a' <= c && c <= 'f') {
Packit 2bba5f
            n *= base;
Packit 2bba5f
            n += c - 'a' + 10;
Packit 2bba5f
        }
Packit 2bba5f
        else if ('A' <= c && c <= 'F') {
Packit 2bba5f
            n *= base;
Packit 2bba5f
            n += c - 'A' + 10;
Packit 2bba5f
        }
Packit 2bba5f
        else
Packit 2bba5f
            break;
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    *cp = c;
Packit 2bba5f
    return n;
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
/* Skip to beginning of new line; return 1 if only whitespace was found. */
Packit 2bba5f
static int
Packit 2bba5f
endOfLine(FontFilePtr f, int c)
Packit 2bba5f
{
Packit 2bba5f
    if (c == 0)
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
Packit 2bba5f
    for (;;) {
Packit 2bba5f
        if (c <= 0 || c == '\n')
Packit 2bba5f
            return 1;
Packit 2bba5f
        else if (c == '#') {
Packit 2bba5f
            skipEndOfLine(f, c);
Packit 2bba5f
            return 1;
Packit 2bba5f
        }
Packit 2bba5f
        else if (c == ' ' || c == '\t') {
Packit 2bba5f
            skipEndOfLine(f, c);
Packit 2bba5f
            return 0;
Packit 2bba5f
        }
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
    }
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
/* Get a token; we're at first char */
Packit 2bba5f
static int
Packit 2bba5f
gettoken(FontFilePtr f, int c, int *cp)
Packit 2bba5f
{
Packit 2bba5f
    char *p;
Packit 2bba5f
Packit 2bba5f
    if (c <= 0)
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
Packit 2bba5f
    if (c <= 0) {
Packit 2bba5f
        return EOF_TOKEN;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    while (c == ' ' || c == '\t')
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
Packit 2bba5f
    if (c == '\n') {
Packit 2bba5f
        return EOL_TOKEN;
Packit 2bba5f
    }
Packit 2bba5f
    else if (c == '#') {
Packit 2bba5f
        skipEndOfLine(f, c);
Packit 2bba5f
        return EOL_TOKEN;
Packit 2bba5f
    }
Packit 2bba5f
    else if (c >= '0' && c <= '9') {
Packit 2bba5f
        number_value = getnum(f, c, cp);
Packit 2bba5f
        return NUMBER_TOKEN;
Packit 2bba5f
    }
Packit 2bba5f
    else if ((c >= 'A' && c <= 'Z') ||
Packit 2bba5f
             (c >= 'a' && c <= 'z') ||
Packit 2bba5f
             c == '/' || c == '_' || c == '-' || c == '.') {
Packit 2bba5f
        p = keyword_value;
Packit 2bba5f
        *p++ = c;
Packit 2bba5f
        while (p - keyword_value < MAXKEYWORDLEN) {
Packit 2bba5f
            c = FontFileGetc(f);
Packit 2bba5f
            if (c <= ' ' || c > '~' || c == '#')
Packit 2bba5f
                break;
Packit 2bba5f
            *p++ = c;
Packit 2bba5f
        }
Packit 2bba5f
        *cp = c;
Packit 2bba5f
        *p = '\0';
Packit 2bba5f
        return KEYWORD_TOKEN;
Packit 2bba5f
    }
Packit 2bba5f
    else {
Packit 2bba5f
        *cp = c;
Packit 2bba5f
        return ERROR_TOKEN;
Packit 2bba5f
    }
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
/* Parse a line.
Packit 2bba5f
 * Always skips to the beginning of a new line, even if an error occurs */
Packit 2bba5f
static int
Packit 2bba5f
getnextline(FontFilePtr f)
Packit 2bba5f
{
Packit 2bba5f
    int c, token;
Packit 2bba5f
Packit 2bba5f
    c = FontFileGetc(f);
Packit 2bba5f
    if (c <= 0)
Packit 2bba5f
        return EOF_LINE;
Packit 2bba5f
Packit 2bba5f
 again:
Packit 2bba5f
    token = gettoken(f, c, &c);
Packit 2bba5f
Packit 2bba5f
    switch (token) {
Packit 2bba5f
    case EOF_TOKEN:
Packit 2bba5f
        return EOF_LINE;
Packit 2bba5f
    case EOL_TOKEN:
Packit 2bba5f
        /* empty line */
Packit 2bba5f
        c = FontFileGetc(f);
Packit 2bba5f
        goto again;
Packit 2bba5f
    case NUMBER_TOKEN:
Packit 2bba5f
        value1 = number_value;
Packit 2bba5f
        token = gettoken(f, c, &c);
Packit 2bba5f
        switch (token) {
Packit 2bba5f
        case NUMBER_TOKEN:
Packit 2bba5f
            value2 = number_value;
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            switch (token) {
Packit 2bba5f
            case NUMBER_TOKEN:
Packit 2bba5f
                value3 = number_value;
Packit 2bba5f
                return CODE_RANGE_LINE;
Packit 2bba5f
            case EOL_TOKEN:
Packit 2bba5f
                return CODE_LINE;
Packit 2bba5f
            default:
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
        case KEYWORD_TOKEN:
Packit 2bba5f
            if (!endOfLine(f, c))
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            else
Packit 2bba5f
                return NAME_LINE;
Packit 2bba5f
        default:
Packit 2bba5f
            skipEndOfLine(f, c);
Packit 2bba5f
            return ERROR_LINE;
Packit 2bba5f
        }
Packit 2bba5f
    case KEYWORD_TOKEN:
Packit 2bba5f
        if (!strcasecmp(keyword_value, "STARTENCODING")) {
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token == KEYWORD_TOKEN) {
Packit 2bba5f
                if (endOfLine(f, c))
Packit 2bba5f
                    return STARTENCODING_LINE;
Packit 2bba5f
                else
Packit 2bba5f
                    return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "ALIAS")) {
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token == KEYWORD_TOKEN) {
Packit 2bba5f
                if (endOfLine(f, c))
Packit 2bba5f
                    return ALIAS_LINE;
Packit 2bba5f
                else
Packit 2bba5f
                    return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "SIZE")) {
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token == NUMBER_TOKEN) {
Packit 2bba5f
                value1 = number_value;
Packit 2bba5f
                token = gettoken(f, c, &c);
Packit 2bba5f
                switch (token) {
Packit 2bba5f
                case NUMBER_TOKEN:
Packit 2bba5f
                    value2 = number_value;
Packit 2bba5f
                    return SIZE_LINE;
Packit 2bba5f
                case EOL_TOKEN:
Packit 2bba5f
                    value2 = 0;
Packit 2bba5f
                    return SIZE_LINE;
Packit 2bba5f
                default:
Packit 2bba5f
                    skipEndOfLine(f, c);
Packit 2bba5f
                    return ERROR_LINE;
Packit 2bba5f
                }
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "FIRSTINDEX")) {
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token == NUMBER_TOKEN) {
Packit 2bba5f
                value1 = number_value;
Packit 2bba5f
                token = gettoken(f, c, &c);
Packit 2bba5f
                switch (token) {
Packit 2bba5f
                case NUMBER_TOKEN:
Packit 2bba5f
                    value2 = number_value;
Packit 2bba5f
                    return FIRSTINDEX_LINE;
Packit 2bba5f
                case EOL_TOKEN:
Packit 2bba5f
                    value2 = 0;
Packit 2bba5f
                    return FIRSTINDEX_LINE;
Packit 2bba5f
                default:
Packit 2bba5f
                    skipEndOfLine(f, c);
Packit 2bba5f
                    return ERROR_LINE;
Packit 2bba5f
                }
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "STARTMAPPING")) {
Packit 2bba5f
            keyword_value[0] = 0;
Packit 2bba5f
            value1 = 0;
Packit 2bba5f
            value2 = 0;
Packit 2bba5f
            /* first a keyword */
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token != KEYWORD_TOKEN) {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
Packit 2bba5f
            /* optional first integer */
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token == NUMBER_TOKEN) {
Packit 2bba5f
                value1 = number_value;
Packit 2bba5f
            }
Packit 2bba5f
            else if (token == EOL_TOKEN) {
Packit 2bba5f
                return STARTMAPPING_LINE;
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
Packit 2bba5f
            /* optional second integer */
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token == NUMBER_TOKEN) {
Packit 2bba5f
                value2 = number_value;
Packit 2bba5f
            }
Packit 2bba5f
            else if (token == EOL_TOKEN) {
Packit 2bba5f
                return STARTMAPPING_LINE;
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
Packit 2bba5f
            if (!endOfLine(f, c))
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            else {
Packit 2bba5f
                return STARTMAPPING_LINE;
Packit 2bba5f
            }
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "UNDEFINE")) {
Packit 2bba5f
            /* first integer */
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token != NUMBER_TOKEN) {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
            value1 = number_value;
Packit 2bba5f
            /* optional second integer */
Packit 2bba5f
            token = gettoken(f, c, &c);
Packit 2bba5f
            if (token == EOL_TOKEN) {
Packit 2bba5f
                value2 = value1;
Packit 2bba5f
                return CODE_UNDEFINE_LINE;
Packit 2bba5f
            }
Packit 2bba5f
            else if (token == NUMBER_TOKEN) {
Packit 2bba5f
                value2 = number_value;
Packit 2bba5f
                if (endOfLine(f, c)) {
Packit 2bba5f
                    return CODE_UNDEFINE_LINE;
Packit 2bba5f
                }
Packit 2bba5f
                else
Packit 2bba5f
                    return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                skipEndOfLine(f, c);
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
            }
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "ENDENCODING")) {
Packit 2bba5f
            if (endOfLine(f, c))
Packit 2bba5f
                return EOF_LINE;
Packit 2bba5f
            else
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "ENDMAPPING")) {
Packit 2bba5f
            if (endOfLine(f, c))
Packit 2bba5f
                return ENDMAPPING_LINE;
Packit 2bba5f
            else
Packit 2bba5f
                return ERROR_LINE;
Packit 2bba5f
        }
Packit 2bba5f
        else {
Packit 2bba5f
            skipEndOfLine(f, c);
Packit 2bba5f
            return ERROR_LINE;
Packit 2bba5f
        }
Packit 2bba5f
    default:
Packit 2bba5f
        return ERROR_LINE;
Packit 2bba5f
    }
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
static void
Packit 2bba5f
install_mapping(FontEncPtr encoding, FontMapPtr mapping)
Packit 2bba5f
{
Packit 2bba5f
    FontMapPtr m;
Packit 2bba5f
Packit 2bba5f
    if (encoding->mappings == NULL)
Packit 2bba5f
        encoding->mappings = mapping;
Packit 2bba5f
    else {
Packit 2bba5f
        m = encoding->mappings;
Packit 2bba5f
        while (m->next != NULL)
Packit 2bba5f
            m = m->next;
Packit 2bba5f
        m->next = mapping;
Packit 2bba5f
    }
Packit 2bba5f
    mapping->next = NULL;
Packit 2bba5f
    mapping->encoding = encoding;
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
static int
Packit 2bba5f
setCode(unsigned from, unsigned to, unsigned row_size,
Packit 2bba5f
        unsigned *first, unsigned *last,
Packit 2bba5f
        unsigned *encsize, unsigned short **enc)
Packit 2bba5f
{
Packit 2bba5f
    unsigned index, i;
Packit 2bba5f
Packit 2bba5f
    unsigned short *newenc;
Packit 2bba5f
Packit 2bba5f
    if (from > 0xFFFF)
Packit 2bba5f
        return 0;               /* success */
Packit 2bba5f
Packit 2bba5f
    if (row_size == 0)
Packit 2bba5f
        index = from;
Packit 2bba5f
    else {
Packit 2bba5f
        if ((value1 & 0xFF) >= row_size)
Packit 2bba5f
            return 0;           /* ignore out of range mappings */
Packit 2bba5f
        index = (from >> 8) * row_size + (from & 0xFF);
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    /* Optimize away useless identity mappings.  This is only expected
Packit 2bba5f
       to be useful with linear encodings. */
Packit 2bba5f
    if (index == to && (index < *first || index > *last))
Packit 2bba5f
        return 0;
Packit 2bba5f
    if (*encsize == 0) {
Packit 2bba5f
        *encsize = (index < 256) ? 256 : 0x10000;
Packit 2bba5f
        *enc = malloc((*encsize) * sizeof(unsigned short));
Packit 2bba5f
        if (*enc == NULL) {
Packit 2bba5f
            *encsize = 0;
Packit 2bba5f
            return 1;
Packit 2bba5f
        }
Packit 2bba5f
    }
Packit 2bba5f
    else if (*encsize <= index) {
Packit 2bba5f
        *encsize = 0x10000;
Packit 2bba5f
        if ((newenc =
Packit 2bba5f
             realloc(*enc, (*encsize) * sizeof(unsigned short))) == NULL)
Packit 2bba5f
            return 1;
Packit 2bba5f
        *enc = newenc;
Packit 2bba5f
    }
Packit 2bba5f
    if (*first > *last) {
Packit 2bba5f
        *first = *last = index;
Packit 2bba5f
    }
Packit 2bba5f
    if (index < *first) {
Packit 2bba5f
        for (i = index; i < *first; i++)
Packit 2bba5f
            (*enc)[i] = i;
Packit 2bba5f
        *first = index;
Packit 2bba5f
    }
Packit 2bba5f
    if (index > *last) {
Packit 2bba5f
        for (i = *last + 1; i <= index; i++)
Packit 2bba5f
            (*enc)[i] = i;
Packit 2bba5f
        *last = index;
Packit 2bba5f
    }
Packit 2bba5f
    (*enc)[index] = to;
Packit 2bba5f
    return 0;
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
/* Parser.  If headerOnly is true, we're only interested in the
Packit 2bba5f
   data contained in the encoding file's header. */
Packit 2bba5f
Packit 2bba5f
/* As font encodings are currently never freed, the allocations done
Packit 2bba5f
   by this function are mostly its private business.  Note, however,
Packit 2bba5f
   that FontEncIdentify needs to free the header fields -- so if you
Packit 2bba5f
   change this function, you may need to change FontEncIdentify. */
Packit 2bba5f
Packit 2bba5f
/* I want a garbage collector. */
Packit 2bba5f
Packit 2bba5f
static FontEncPtr
Packit 2bba5f
parseEncodingFile(FontFilePtr f, int headerOnly)
Packit 2bba5f
{
Packit 2bba5f
    int line;
Packit 2bba5f
Packit 2bba5f
    unsigned short *enc = NULL;
Packit 2bba5f
    char **nam = NULL, **newnam;
Packit 2bba5f
    unsigned i, first = 0xFFFF, last = 0, encsize = 0, namsize = 0;
Packit 2bba5f
    FontEncPtr encoding = NULL;
Packit 2bba5f
    FontMapPtr mapping = NULL;
Packit 2bba5f
    FontEncSimpleMapPtr sm;
Packit 2bba5f
    FontEncSimpleNamePtr sn;
Packit 2bba5f
    char *aliases[MAXALIASES] = { NULL };
Packit 2bba5f
    int numaliases = 0;
Packit 2bba5f
Packit 2bba5f
#if 0
Packit 2bba5f
    /* GCC complains about unused labels.  Please fix GCC rather than
Packit 2bba5f
       obfuscating my code. */
Packit 2bba5f
 no_encoding:
Packit 2bba5f
#endif
Packit 2bba5f
    line = getnextline(f);
Packit 2bba5f
    switch (line) {
Packit 2bba5f
    case EOF_LINE:
Packit 2bba5f
        goto error;
Packit 2bba5f
    case STARTENCODING_LINE:
Packit 2bba5f
        encoding = malloc(sizeof(FontEncRec));
Packit 2bba5f
        if (encoding == NULL)
Packit 2bba5f
            goto error;
Packit 2bba5f
        encoding->name = strdup(keyword_value);
Packit 2bba5f
        if (encoding->name == NULL)
Packit 2bba5f
            goto error;
Packit 2bba5f
        encoding->size = 256;
Packit 2bba5f
        encoding->row_size = 0;
Packit 2bba5f
        encoding->mappings = NULL;
Packit 2bba5f
        encoding->next = NULL;
Packit 2bba5f
        encoding->first = encoding->first_col = 0;
Packit 2bba5f
        goto no_mapping;
Packit 2bba5f
    default:
Packit 2bba5f
        goto error;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
 no_mapping:
Packit 2bba5f
    line = getnextline(f);
Packit 2bba5f
    switch (line) {
Packit 2bba5f
    case EOF_LINE:
Packit 2bba5f
        goto done;
Packit 2bba5f
    case ALIAS_LINE:
Packit 2bba5f
        if (numaliases < MAXALIASES) {
Packit 2bba5f
            aliases[numaliases] = strdup(keyword_value);
Packit 2bba5f
            if (aliases[numaliases] == NULL)
Packit 2bba5f
                goto error;
Packit 2bba5f
            numaliases++;
Packit 2bba5f
        }
Packit 2bba5f
        goto no_mapping;
Packit 2bba5f
    case SIZE_LINE:
Packit 2bba5f
        encoding->size = value1;
Packit 2bba5f
        encoding->row_size = value2;
Packit 2bba5f
        goto no_mapping;
Packit 2bba5f
    case FIRSTINDEX_LINE:
Packit 2bba5f
        encoding->first = value1;
Packit 2bba5f
        encoding->first_col = value2;
Packit 2bba5f
        goto no_mapping;
Packit 2bba5f
    case STARTMAPPING_LINE:
Packit 2bba5f
        if (headerOnly)
Packit 2bba5f
            goto done;
Packit 2bba5f
        if (!strcasecmp(keyword_value, "unicode")) {
Packit 2bba5f
            mapping = malloc(sizeof(FontMapRec));
Packit 2bba5f
            if (mapping == NULL)
Packit 2bba5f
                goto error;
Packit 2bba5f
            mapping->type = FONT_ENCODING_UNICODE;
Packit 2bba5f
            mapping->pid = 0;
Packit 2bba5f
            mapping->eid = 0;
Packit 2bba5f
            mapping->recode = NULL;
Packit 2bba5f
            mapping->name = NULL;
Packit 2bba5f
            mapping->client_data = NULL;
Packit 2bba5f
            mapping->next = NULL;
Packit 2bba5f
            goto mapping;
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "cmap")) {
Packit 2bba5f
            mapping = malloc(sizeof(FontMapRec));
Packit 2bba5f
            if (mapping == NULL)
Packit 2bba5f
                goto error;
Packit 2bba5f
            mapping->type = FONT_ENCODING_TRUETYPE;
Packit 2bba5f
            mapping->pid = value1;
Packit 2bba5f
            mapping->eid = value2;
Packit 2bba5f
            mapping->recode = NULL;
Packit 2bba5f
            mapping->name = NULL;
Packit 2bba5f
            mapping->client_data = NULL;
Packit 2bba5f
            mapping->next = NULL;
Packit 2bba5f
            goto mapping;
Packit 2bba5f
        }
Packit 2bba5f
        else if (!strcasecmp(keyword_value, "postscript")) {
Packit 2bba5f
            mapping = malloc(sizeof(FontMapRec));
Packit 2bba5f
            if (mapping == NULL)
Packit 2bba5f
                goto error;
Packit 2bba5f
            mapping->type = FONT_ENCODING_POSTSCRIPT;
Packit 2bba5f
            mapping->pid = 0;
Packit 2bba5f
            mapping->eid = 0;
Packit 2bba5f
            mapping->recode = NULL;
Packit 2bba5f
            mapping->name = NULL;
Packit 2bba5f
            mapping->client_data = NULL;
Packit 2bba5f
            mapping->next = NULL;
Packit 2bba5f
            goto string_mapping;
Packit 2bba5f
        }
Packit 2bba5f
        else {                  /* unknown mapping type -- ignore */
Packit 2bba5f
            goto skipmapping;
Packit 2bba5f
        }
Packit 2bba5f
        /* NOTREACHED */
Packit 2bba5f
        goto error;
Packit 2bba5f
    default:
Packit 2bba5f
        goto no_mapping;        /* ignore unknown lines */
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
 skipmapping:
Packit 2bba5f
    line = getnextline(f);
Packit 2bba5f
    switch (line) {
Packit 2bba5f
    case ENDMAPPING_LINE:
Packit 2bba5f
        goto no_mapping;
Packit 2bba5f
    case EOF_LINE:
Packit 2bba5f
        goto error;
Packit 2bba5f
    default:
Packit 2bba5f
        goto skipmapping;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
 mapping:
Packit 2bba5f
    line = getnextline(f);
Packit 2bba5f
    switch (line) {
Packit 2bba5f
    case EOF_LINE:
Packit 2bba5f
        goto error;
Packit 2bba5f
    case ENDMAPPING_LINE:
Packit 2bba5f
        mapping->recode = FontEncSimpleRecode;
Packit 2bba5f
        mapping->name = FontEncUndefinedName;
Packit 2bba5f
        mapping->client_data = sm = malloc(sizeof(FontEncSimpleMapRec));
Packit 2bba5f
        if (sm == NULL)
Packit 2bba5f
            goto error;
Packit 2bba5f
        sm->row_size = encoding->row_size;
Packit 2bba5f
        if (first <= last) {
Packit 2bba5f
            unsigned short *newmap;
Packit 2bba5f
Packit 2bba5f
            sm->first = first;
Packit 2bba5f
            sm->len = last - first + 1;
Packit 2bba5f
            newmap = malloc(sm->len * sizeof(unsigned short));
Packit 2bba5f
            if (newmap == NULL) {
Packit 2bba5f
                free(sm);
Packit 2bba5f
                mapping->client_data = sm = NULL;
Packit 2bba5f
                goto error;
Packit 2bba5f
            }
Packit 2bba5f
            for (i = 0; i < sm->len; i++)
Packit 2bba5f
                newmap[i] = enc[first + i];
Packit 2bba5f
            sm->map = newmap;
Packit 2bba5f
        }
Packit 2bba5f
        else {
Packit 2bba5f
            sm->first = 0;
Packit 2bba5f
            sm->len = 0;
Packit 2bba5f
            sm->map = NULL;
Packit 2bba5f
        }
Packit 2bba5f
        install_mapping(encoding, mapping);
Packit 2bba5f
        mapping = NULL;
Packit 2bba5f
        first = 0xFFFF;
Packit 2bba5f
        last = 0;
Packit 2bba5f
        goto no_mapping;
Packit 2bba5f
Packit 2bba5f
    case CODE_LINE:
Packit 2bba5f
        if (setCode(value1, value2, encoding->row_size,
Packit 2bba5f
                    &first, &last, &encsize, &enc))
Packit 2bba5f
            goto error;
Packit 2bba5f
        goto mapping;
Packit 2bba5f
Packit 2bba5f
    case CODE_RANGE_LINE:
Packit 2bba5f
        if (value1 > 0x10000)
Packit 2bba5f
            value1 = 0x10000;
Packit 2bba5f
        if (value2 > 0x10000)
Packit 2bba5f
            value2 = 0x10000;
Packit 2bba5f
        if (value2 < value1)
Packit 2bba5f
            goto mapping;
Packit 2bba5f
        /* Do the last value first to avoid having to realloc() */
Packit 2bba5f
        if (setCode(value2, value3 + (value2 - value1), encoding->row_size,
Packit 2bba5f
                    &first, &last, &encsize, &enc))
Packit 2bba5f
            goto error;
Packit 2bba5f
        for (i = value1; i < value2; i++) {
Packit 2bba5f
            if (setCode(i, value3 + (i - value1), encoding->row_size,
Packit 2bba5f
                        &first, &last, &encsize, &enc))
Packit 2bba5f
                goto error;
Packit 2bba5f
        }
Packit 2bba5f
        goto mapping;
Packit 2bba5f
Packit 2bba5f
    case CODE_UNDEFINE_LINE:
Packit 2bba5f
        if (value1 > 0x10000)
Packit 2bba5f
            value1 = 0x10000;
Packit 2bba5f
        if (value2 > 0x10000)
Packit 2bba5f
            value2 = 0x10000;
Packit 2bba5f
        if (value2 < value1)
Packit 2bba5f
            goto mapping;
Packit 2bba5f
        /* Do the last value first to avoid having to realloc() */
Packit 2bba5f
        if (setCode(value2, 0, encoding->row_size,
Packit 2bba5f
                    &first, &last, &encsize, &enc))
Packit 2bba5f
            goto error;
Packit 2bba5f
        for (i = value1; i < value2; i++) {
Packit 2bba5f
            if (setCode(i, 0, encoding->row_size,
Packit 2bba5f
                        &first, &last, &encsize, &enc))
Packit 2bba5f
                goto error;
Packit 2bba5f
        }
Packit 2bba5f
        goto mapping;
Packit 2bba5f
Packit 2bba5f
    default:
Packit 2bba5f
        goto mapping;           /* ignore unknown lines */
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
 string_mapping:
Packit 2bba5f
    line = getnextline(f);
Packit 2bba5f
    switch (line) {
Packit 2bba5f
    case EOF_LINE:
Packit 2bba5f
        goto error;
Packit 2bba5f
    case ENDMAPPING_LINE:
Packit 2bba5f
        mapping->recode = FontEncUndefinedRecode;
Packit 2bba5f
        mapping->name = FontEncSimpleName;
Packit 2bba5f
        mapping->client_data = sn = malloc(sizeof(FontEncSimpleNameRec));
Packit 2bba5f
        if (sn == NULL)
Packit 2bba5f
            goto error;
Packit 2bba5f
        if (first > last) {
Packit 2bba5f
            free(sn);
Packit 2bba5f
            mapping->client_data = sn = NULL;
Packit 2bba5f
            goto error;
Packit 2bba5f
        }
Packit 2bba5f
        sn->first = first;
Packit 2bba5f
        sn->len = last - first + 1;
Packit 2bba5f
        sn->map = malloc(sn->len * sizeof(char *));
Packit 2bba5f
        if (sn->map == NULL) {
Packit 2bba5f
            free(sn);
Packit 2bba5f
            mapping->client_data = sn = NULL;
Packit 2bba5f
            goto error;
Packit 2bba5f
        }
Packit 2bba5f
        for (i = 0; i < sn->len; i++)
Packit 2bba5f
            sn->map[i] = nam[first + i];
Packit 2bba5f
        install_mapping(encoding, mapping);
Packit 2bba5f
        mapping = NULL;
Packit 2bba5f
        first = 0xFFFF;
Packit 2bba5f
        last = 0;
Packit 2bba5f
        goto no_mapping;
Packit 2bba5f
    case NAME_LINE:
Packit 2bba5f
        if (value1 >= 0x10000)
Packit 2bba5f
            goto string_mapping;
Packit 2bba5f
        if (namsize == 0) {
Packit 2bba5f
            namsize = (value1) < 256 ? 256 : 0x10000;
Packit 2bba5f
            nam = malloc(namsize * sizeof(char *));
Packit 2bba5f
            if (nam == NULL) {
Packit 2bba5f
                namsize = 0;
Packit 2bba5f
                goto error;
Packit 2bba5f
            }
Packit 2bba5f
        }
Packit 2bba5f
        else if (namsize <= value1) {
Packit 2bba5f
            namsize = 0x10000;
Packit 2bba5f
            if ((newnam = (char **) realloc(nam, namsize)) == NULL)
Packit 2bba5f
                goto error;
Packit 2bba5f
            nam = newnam;
Packit 2bba5f
        }
Packit 2bba5f
        if (first > last) {
Packit 2bba5f
            first = last = value1;
Packit 2bba5f
        }
Packit 2bba5f
        if (value1 < first) {
Packit 2bba5f
            for (i = value1; i < first; i++)
Packit 2bba5f
                nam[i] = NULL;
Packit 2bba5f
            first = value1;
Packit 2bba5f
        }
Packit 2bba5f
        if (value1 > last) {
Packit 2bba5f
            for (i = last + 1; i <= value1; i++)
Packit 2bba5f
                nam[i] = NULL;
Packit 2bba5f
            last = value1;
Packit 2bba5f
        }
Packit 2bba5f
        nam[value1] = strdup(keyword_value);
Packit 2bba5f
        if (nam[value1] == NULL) {
Packit 2bba5f
            goto error;
Packit 2bba5f
        }
Packit 2bba5f
        goto string_mapping;
Packit 2bba5f
Packit 2bba5f
    default:
Packit 2bba5f
        goto string_mapping;    /* ignore unknown lines */
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
 done:
Packit 2bba5f
    if (encsize) {
Packit 2bba5f
        free(enc);
Packit 2bba5f
        encsize = 0;
Packit 2bba5f
        enc = NULL;
Packit 2bba5f
    }
Packit 2bba5f
    if (namsize) {
Packit 2bba5f
        free(nam);             /* don't free entries! */
Packit 2bba5f
        namsize = 0;
Packit 2bba5f
        nam = NULL;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    encoding->aliases = NULL;
Packit 2bba5f
    if (numaliases) {
Packit 2bba5f
        encoding->aliases = malloc((numaliases + 1) * sizeof(char *));
Packit 2bba5f
        if (encoding->aliases == NULL)
Packit 2bba5f
            goto error;
Packit 2bba5f
        for (i = 0; i < numaliases; i++)
Packit 2bba5f
            encoding->aliases[i] = aliases[i];
Packit 2bba5f
        encoding->aliases[numaliases] = NULL;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    return encoding;
Packit 2bba5f
Packit 2bba5f
 error:
Packit 2bba5f
    if (encsize) {
Packit 2bba5f
        free(enc);
Packit 2bba5f
        encsize = 0;
Packit 2bba5f
    }
Packit 2bba5f
    if (namsize) {
Packit 2bba5f
        for (i = first; i <= last; i++)
Packit 2bba5f
            free(nam[i]);
Packit 2bba5f
        free(nam);
Packit 2bba5f
    }
Packit 2bba5f
    if (mapping) {
Packit 2bba5f
        free(mapping->client_data);
Packit 2bba5f
        free(mapping);
Packit 2bba5f
    }
Packit 2bba5f
    if (encoding) {
Packit 2bba5f
        FontMapPtr nextmap;
Packit 2bba5f
Packit 2bba5f
        free(encoding->name);
Packit 2bba5f
        for (mapping = encoding->mappings; mapping; mapping = nextmap) {
Packit 2bba5f
            free(mapping->client_data);
Packit 2bba5f
            nextmap = mapping->next;
Packit 2bba5f
            free(mapping);
Packit 2bba5f
        }
Packit 2bba5f
        free(encoding);
Packit 2bba5f
    }
Packit 2bba5f
    for (i = 0; i < numaliases; i++)
Packit 2bba5f
        free(aliases[i]);
Packit 2bba5f
    /* We don't need to free sn and sm as they handled locally in the body. */
Packit 2bba5f
    return NULL;
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
char *
Packit 2bba5f
FontEncDirectory(void)
Packit 2bba5f
{
Packit 2bba5f
    static char *dir = NULL;
Packit 2bba5f
Packit 2bba5f
    if (dir == NULL) {
Packit 2bba5f
        char *c = getenv("FONT_ENCODINGS_DIRECTORY");
Packit 2bba5f
Packit 2bba5f
        if (c) {
Packit 2bba5f
            dir = strdup(c);
Packit 2bba5f
            if (!dir)
Packit 2bba5f
                return NULL;
Packit 2bba5f
        }
Packit 2bba5f
        else {
Packit 2bba5f
            dir = FONT_ENCODINGS_DIRECTORY;
Packit 2bba5f
        }
Packit 2bba5f
    }
Packit 2bba5f
    return dir;
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
static void
Packit 2bba5f
parseFontFileName(const char *fontFileName, char *buf, char *dir)
Packit 2bba5f
{
Packit 2bba5f
    const char *p;
Packit 2bba5f
    char *q, *lastslash;
Packit 2bba5f
Packit 2bba5f
    for (p = fontFileName, q = dir, lastslash = NULL; *p; p++, q++) {
Packit 2bba5f
        *q = *p;
Packit 2bba5f
        if (*p == '/')
Packit 2bba5f
            lastslash = q + 1;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    if (!lastslash)
Packit 2bba5f
        lastslash = dir;
Packit 2bba5f
Packit 2bba5f
    *lastslash = '\0';
Packit 2bba5f
Packit 2bba5f
    if (buf && strlen(dir) + 14 < MAXFONTFILENAMELEN) {
Packit 2bba5f
        snprintf(buf, MAXFONTFILENAMELEN, "%s%s", dir, "encodings.dir");
Packit 2bba5f
    }
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
static FontEncPtr
Packit 2bba5f
FontEncReallyReallyLoad(const char *charset,
Packit 2bba5f
                        const char *dirname, const char *dir)
Packit 2bba5f
{
Packit 2bba5f
    FontFilePtr f;
Packit 2bba5f
    FILE *file;
Packit 2bba5f
    FontEncPtr encoding;
Packit 2bba5f
    char file_name[MAXFONTFILENAMELEN], encoding_name[MAXFONTNAMELEN],
Packit 2bba5f
        buf[MAXFONTFILENAMELEN];
Packit 2bba5f
    int count, n;
Packit 2bba5f
    static char format[24] = "";
Packit 2bba5f
Packit 2bba5f
    /* As we don't really expect to open encodings that often, we don't
Packit 2bba5f
       take the trouble of caching encodings directories. */
Packit 2bba5f
Packit 2bba5f
    if ((file = fopen(dirname, "r")) == NULL) {
Packit 2bba5f
        return NULL;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    count = fscanf(file, "%d\n", &n);
Packit 2bba5f
    if (count == EOF || count != 1) {
Packit 2bba5f
        fclose(file);
Packit 2bba5f
        return NULL;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    encoding = NULL;
Packit 2bba5f
    if (!format[0]) {
Packit 2bba5f
        snprintf(format, sizeof(format), "%%%ds %%%d[^\n]\n",
Packit 2bba5f
                 (int) sizeof(encoding_name) - 1, (int) sizeof(file_name) - 1);
Packit 2bba5f
    }
Packit 2bba5f
    for (;;) {
Packit 2bba5f
        count = fscanf(file, format, encoding_name, file_name);
Packit 2bba5f
        if (count == EOF)
Packit 2bba5f
            break;
Packit 2bba5f
        if (count != 2)
Packit 2bba5f
            break;
Packit 2bba5f
Packit 2bba5f
        if (!strcasecmp(encoding_name, charset)) {
Packit 2bba5f
            /* Found it */
Packit 2bba5f
            if (file_name[0] != '/') {
Packit 2bba5f
                if (strlen(dir) + strlen(file_name) >= MAXFONTFILENAMELEN) {
Packit 2bba5f
                    fclose(file);
Packit 2bba5f
                    return NULL;
Packit 2bba5f
                }
Packit 2bba5f
                snprintf(buf, MAXFONTFILENAMELEN, "%s%s", dir, file_name);
Packit 2bba5f
            }
Packit 2bba5f
            else {
Packit 2bba5f
                snprintf(buf, MAXFONTFILENAMELEN, "%s", file_name);
Packit 2bba5f
            }
Packit 2bba5f
Packit 2bba5f
            f = FontFileOpen(buf);
Packit 2bba5f
            if (f == NULL) {
Packit 2bba5f
                fclose(file);
Packit 2bba5f
                return NULL;
Packit 2bba5f
            }
Packit 2bba5f
            encoding = parseEncodingFile(f, 0);
Packit 2bba5f
            FontFileClose(f);
Packit 2bba5f
            break;
Packit 2bba5f
        }
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    fclose(file);
Packit 2bba5f
Packit 2bba5f
    return encoding;
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
/* Parser ntrypoint -- used by FontEncLoad */
Packit 2bba5f
FontEncPtr
Packit 2bba5f
FontEncReallyLoad(const char *charset, const char *fontFileName)
Packit 2bba5f
{
Packit 2bba5f
    FontEncPtr encoding;
Packit 2bba5f
    char dir[MAXFONTFILENAMELEN], dirname[MAXFONTFILENAMELEN];
Packit 2bba5f
    char *d;
Packit 2bba5f
Packit 2bba5f
    if (fontFileName) {
Packit 2bba5f
        parseFontFileName(fontFileName, dirname, dir);
Packit 2bba5f
        encoding = FontEncReallyReallyLoad(charset, dirname, dir);
Packit 2bba5f
        if (encoding)
Packit 2bba5f
            return (encoding);
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    d = FontEncDirectory();
Packit 2bba5f
    if (d) {
Packit 2bba5f
        parseFontFileName(d, NULL, dir);
Packit 2bba5f
        encoding = FontEncReallyReallyLoad(charset, d, dir);
Packit 2bba5f
        return encoding;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    return NULL;
Packit 2bba5f
}
Packit 2bba5f
Packit 2bba5f
/* Return a NULL-terminated array of encoding names.  Note that this
Packit 2bba5f
 * function has incestuous knowledge of the allocations done by
Packit 2bba5f
 * parseEncodingFile. */
Packit 2bba5f
Packit 2bba5f
char **
Packit 2bba5f
FontEncIdentify(const char *fileName)
Packit 2bba5f
{
Packit 2bba5f
    FontFilePtr f;
Packit 2bba5f
    FontEncPtr encoding;
Packit 2bba5f
    char **names, **name, **alias;
Packit 2bba5f
    int numaliases;
Packit 2bba5f
Packit 2bba5f
    if ((f = FontFileOpen(fileName)) == NULL) {
Packit 2bba5f
        return NULL;
Packit 2bba5f
    }
Packit 2bba5f
    encoding = parseEncodingFile(f, 1);
Packit 2bba5f
    FontFileClose(f);
Packit 2bba5f
Packit 2bba5f
    if (!encoding)
Packit 2bba5f
        return NULL;
Packit 2bba5f
Packit 2bba5f
    numaliases = 0;
Packit 2bba5f
    if (encoding->aliases)
Packit 2bba5f
        for (alias = encoding->aliases; *alias; alias++)
Packit 2bba5f
            numaliases++;
Packit 2bba5f
Packit 2bba5f
    names = malloc((numaliases + 2) * sizeof(char *));
Packit 2bba5f
    if (names == NULL) {
Packit 2bba5f
        free(encoding->aliases);
Packit 2bba5f
        free(encoding);
Packit 2bba5f
        return NULL;
Packit 2bba5f
    }
Packit 2bba5f
Packit 2bba5f
    name = names;
Packit 2bba5f
    *(name++) = encoding->name;
Packit 2bba5f
    if (numaliases > 0)
Packit 2bba5f
        for (alias = encoding->aliases; *alias; alias++, name++)
Packit 2bba5f
            *name = *alias;
Packit 2bba5f
Packit 2bba5f
    *name = NULL;
Packit 2bba5f
    free(encoding->aliases);
Packit 2bba5f
    free(encoding);
Packit 2bba5f
Packit 2bba5f
    return names;
Packit 2bba5f
}