ident.c revision 45a6f659
1ea6ae205Smrg/*
2ea6ae205Smrg  Copyright (c) 2003 by Juliusz Chroboczek
3ea6ae205Smrg
4ea6ae205Smrg  Permission is hereby granted, free of charge, to any person obtaining a copy
5ea6ae205Smrg  of this software and associated documentation files (the "Software"), to deal
6ea6ae205Smrg  in the Software without restriction, including without limitation the rights
7ea6ae205Smrg  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8ea6ae205Smrg  copies of the Software, and to permit persons to whom the Software is
9ea6ae205Smrg  furnished to do so, subject to the following conditions:
10ea6ae205Smrg
11ea6ae205Smrg  The above copyright notice and this permission notice shall be included in
12ea6ae205Smrg  all copies or substantial portions of the Software.
13ea6ae205Smrg
14ea6ae205Smrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ea6ae205Smrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ea6ae205Smrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17ea6ae205Smrg  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18ea6ae205Smrg  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19ea6ae205Smrg  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20ea6ae205Smrg  THE SOFTWARE.
21ea6ae205Smrg*/
227978d3cdSmrg/* Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237978d3cdSmrg *
247978d3cdSmrg * Permission is hereby granted, free of charge, to any person obtaining a
257978d3cdSmrg * copy of this software and associated documentation files (the
267978d3cdSmrg * "Software"), to deal in the Software without restriction, including
277978d3cdSmrg * without limitation the rights to use, copy, modify, merge, publish,
287978d3cdSmrg * distribute, and/or sell copies of the Software, and to permit persons
297978d3cdSmrg * to whom the Software is furnished to do so, provided that the above
307978d3cdSmrg * copyright notice(s) and this permission notice appear in all copies of
317978d3cdSmrg * the Software and that both the above copyright notice(s) and this
327978d3cdSmrg * permission notice appear in supporting documentation.
337978d3cdSmrg *
347978d3cdSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
357978d3cdSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
367978d3cdSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
377978d3cdSmrg * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
387978d3cdSmrg * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
397978d3cdSmrg * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
407978d3cdSmrg * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
417978d3cdSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
427978d3cdSmrg * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
437978d3cdSmrg *
447978d3cdSmrg * Except as contained in this notice, the name of a copyright holder
457978d3cdSmrg * shall not be used in advertising or otherwise to promote the sale, use
467978d3cdSmrg * or other dealings in this Software without prior written authorization
477978d3cdSmrg * of the copyright holder.
487978d3cdSmrg */
49ea6ae205Smrg/* $XFree86: xc/programs/mkfontscale/ident.c,v 1.3tsi Exp $ */
50ea6ae205Smrg
51ea6ae205Smrg/* The function identifyBitmap returns -1 if filename is definitively not
52ea6ae205Smrg   a font file, 1 if it is a single-face bitmap font with a XLFD name,
53ea6ae205Smrg   and 0 if it should be processed normally.  identifyBitmap is
54ea6ae205Smrg   much faster than parsing the whole font. */
55ea6ae205Smrg
5645a6f659Smrg#ifdef HAVE_CONFIG_H
577978d3cdSmrg#include "config.h"
5845a6f659Smrg#endif
597978d3cdSmrg
60ea6ae205Smrg#include <stdlib.h>
61ea6ae205Smrg#include <string.h>
62ea6ae205Smrg#include "zlib.h"
63ea6ae205Smrg#include "ident.h"
64ea6ae205Smrg
657978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION
667978d3cdSmrg# include <bzlib.h>
677978d3cdSmrg#endif
687978d3cdSmrg
69ea6ae205Smrg#define PCF_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1)
70ea6ae205Smrg#define PCF_PROPERTIES (1 << 0)
71ea6ae205Smrg
72ea6ae205Smrgtypedef struct _Prop {
73ea6ae205Smrg    unsigned name;
74ea6ae205Smrg    int isString;
75ea6ae205Smrg    unsigned value;
76ea6ae205Smrg} PropRec, *PropPtr;
77ea6ae205Smrg
787978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION
797978d3cdSmrgtypedef struct {
807978d3cdSmrg    enum { gzFontFile, bz2FontFile } type;
817978d3cdSmrg    union {
827978d3cdSmrg	gzFile gz;
837978d3cdSmrg	BZFILE *bz2;
847978d3cdSmrg    } f;
857978d3cdSmrg    unsigned pos;
867978d3cdSmrg} fontFile;
877978d3cdSmrg
887978d3cdSmrgstatic inline void *
897978d3cdSmrgfontFileOpen(fontFile *ff, const char *filename) {
907978d3cdSmrg    int n = strlen(filename);
917978d3cdSmrg
927978d3cdSmrg    if (strcmp(filename + n - 4, ".bz2") == 0) {
937978d3cdSmrg	ff->type = bz2FontFile;
947978d3cdSmrg	ff->f.bz2 = BZ2_bzopen(filename, "rb");
957978d3cdSmrg	ff->pos = 0;
967978d3cdSmrg	return ff->f.bz2;
977978d3cdSmrg    } else {
987978d3cdSmrg	ff->type = gzFontFile;
997978d3cdSmrg	ff->f.gz = gzopen(filename, "rb");
1007978d3cdSmrg	return ff->f.gz;
1017978d3cdSmrg    }
1027978d3cdSmrg}
1037978d3cdSmrg
1047978d3cdSmrgstatic inline int
1057978d3cdSmrgfontFileRead(fontFile *ff, void *buf, unsigned len)
1067978d3cdSmrg{
1077978d3cdSmrg    if (ff->type == gzFontFile) {
1087978d3cdSmrg	return gzread(ff->f.gz, buf, len);
1097978d3cdSmrg    } else {
1107978d3cdSmrg	int r = BZ2_bzread(ff->f.bz2, buf, len);
1117978d3cdSmrg	ff->pos += r;
1127978d3cdSmrg	return r;
1137978d3cdSmrg    }
1147978d3cdSmrg}
1157978d3cdSmrg
1167978d3cdSmrgstatic inline int
1177978d3cdSmrgfontFileGetc(fontFile *ff)
1187978d3cdSmrg{
1197978d3cdSmrg    if (ff->type == gzFontFile) {
1207978d3cdSmrg	return gzgetc(ff->f.gz);
1217978d3cdSmrg    } else {
1227978d3cdSmrg	char buf;
1237978d3cdSmrg	if (BZ2_bzread(ff->f.bz2, &buf, 1) != 1) {
1247978d3cdSmrg	    return -1;
1257978d3cdSmrg	} else {
1267978d3cdSmrg	    ff->pos += 1;
1277978d3cdSmrg	    return (int) buf;
1287978d3cdSmrg	}
1297978d3cdSmrg    }
1307978d3cdSmrg}
1317978d3cdSmrg
1327978d3cdSmrgstatic int
1337978d3cdSmrgfontFileSeek(fontFile *ff, z_off_t offset, int whence)
1347978d3cdSmrg{
1357978d3cdSmrg    if (ff->type == gzFontFile) {
1367978d3cdSmrg	return gzseek(ff->f.gz, offset, whence);
1377978d3cdSmrg    } else {
1387978d3cdSmrg	/* bzlib has no easy equivalent so we have to fake it,
1397978d3cdSmrg	 * fortunately, we only have to handle a couple of cases
1407978d3cdSmrg	 */
1417978d3cdSmrg	int n;
1427978d3cdSmrg	char buf[BUFSIZ];
1437978d3cdSmrg
1447978d3cdSmrg	switch (whence) {
1457978d3cdSmrg	  case SEEK_SET:
1467978d3cdSmrg	    n = offset - ff->pos;
1477978d3cdSmrg	    break;
1487978d3cdSmrg	  case SEEK_CUR:
1497978d3cdSmrg	    n = offset;
1507978d3cdSmrg	    break;
1517978d3cdSmrg	  default:
1527978d3cdSmrg	    return -1;
1537978d3cdSmrg	}
1547978d3cdSmrg
1557978d3cdSmrg	while (n > BUFSIZ) {
1567978d3cdSmrg	    if (BZ2_bzread(ff->f.bz2, buf, BUFSIZ) != BUFSIZ)
1577978d3cdSmrg		return -1;
1587978d3cdSmrg	    n -= BUFSIZ;
1597978d3cdSmrg	}
1607978d3cdSmrg	if (BZ2_bzread(ff->f.bz2, buf, n) != n)
1617978d3cdSmrg	    return -1;
1627978d3cdSmrg	ff->pos = offset;
1637978d3cdSmrg	return offset;
1647978d3cdSmrg    }
1657978d3cdSmrg}
1667978d3cdSmrg
1677978d3cdSmrg
1687978d3cdSmrgstatic inline int
1697978d3cdSmrgfontFileClose(fontFile *ff)
1707978d3cdSmrg{
1717978d3cdSmrg    if (ff->type == gzFontFile) {
1727978d3cdSmrg	return gzclose(ff->f.gz);
1737978d3cdSmrg    } else {
1747978d3cdSmrg	BZ2_bzclose(ff->f.bz2);
1757978d3cdSmrg	return 0;
1767978d3cdSmrg    }
1777978d3cdSmrg}
1787978d3cdSmrg
1797978d3cdSmrg#else /* no bzip2, only gzip */
1807978d3cdSmrgtypedef gzFile fontFile;
1817978d3cdSmrg# define fontFileOpen(ff, filename)	(*(ff) = gzopen(filename, "rb"))
1827978d3cdSmrg# define fontFileRead(ff, buf, len)	gzread(*(ff), buf, len)
1837978d3cdSmrg# define fontFileGetc(ff)		gzgetc(*(ff))
1847978d3cdSmrg# define fontFileSeek(ff, off, whence)	gzseek(*(ff), off, whence)
1857978d3cdSmrg# define fontFileClose(ff)		gzclose(*(ff))
1867978d3cdSmrg#endif
1877978d3cdSmrg
1887978d3cdSmrgstatic int pcfIdentify(fontFile *f, char **name);
1897978d3cdSmrgstatic int bdfIdentify(fontFile *f, char **name);
190ea6ae205Smrg
191ea6ae205Smrgstatic int
1927978d3cdSmrggetLSB32(fontFile *f)
193ea6ae205Smrg{
194ea6ae205Smrg    int rc;
195ea6ae205Smrg    unsigned char c[4];
196ea6ae205Smrg
1977978d3cdSmrg    rc = fontFileRead(f, c, 4);
198ea6ae205Smrg    if(rc != 4)
199ea6ae205Smrg        return -1;
200ea6ae205Smrg    return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
201ea6ae205Smrg}
202ea6ae205Smrg
203ea6ae205Smrgstatic int
2047978d3cdSmrggetInt8(fontFile *f, int format)
205ea6ae205Smrg{
206ea6ae205Smrg    unsigned char c;
207ea6ae205Smrg    int rc;
208ea6ae205Smrg
2097978d3cdSmrg    rc = fontFileRead(f, &c, 1);
210ea6ae205Smrg    if(rc != 1)
211ea6ae205Smrg        return -1;
212ea6ae205Smrg    return c;
213ea6ae205Smrg}
214ea6ae205Smrg
215ea6ae205Smrgstatic int
2167978d3cdSmrggetInt32(fontFile *f, int format)
217ea6ae205Smrg{
218ea6ae205Smrg    int rc;
219ea6ae205Smrg    unsigned char c[4];
220ea6ae205Smrg
2217978d3cdSmrg    rc = fontFileRead(f, c, 4);
222ea6ae205Smrg    if(rc != 4)
223ea6ae205Smrg        return -1;
224ea6ae205Smrg
225ea6ae205Smrg    if(format & (1 << 2)) {
226ea6ae205Smrg        return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3]);
227ea6ae205Smrg    } else {
228ea6ae205Smrg        return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
229ea6ae205Smrg    }
230ea6ae205Smrg}
231ea6ae205Smrg
232ea6ae205Smrgint
2337978d3cdSmrgbitmapIdentify(const char *filename, char **name)
234ea6ae205Smrg{
2357978d3cdSmrg    fontFile ff;
236ea6ae205Smrg    int magic;
237ea6ae205Smrg
2387978d3cdSmrg    if (fontFileOpen(&ff, filename) == NULL)
2397978d3cdSmrg	return -1;
240ea6ae205Smrg
2417978d3cdSmrg    magic = getLSB32(&ff);
242ea6ae205Smrg    if(magic == PCF_VERSION)
2437978d3cdSmrg        return pcfIdentify(&ff, name);
244ea6ae205Smrg    else if(magic == ('S' | ('T' << 8) | ('A' << 16) | ('R') << 24))
2457978d3cdSmrg        return bdfIdentify(&ff, name);
246ea6ae205Smrg
2477978d3cdSmrg    fontFileClose(&ff);
248ea6ae205Smrg    return 0;
249ea6ae205Smrg}
250ea6ae205Smrg
251ea6ae205Smrgstatic int
2527978d3cdSmrgpcfIdentify(fontFile *f, char **name)
253ea6ae205Smrg{
254ea6ae205Smrg    int prop_position;
255ea6ae205Smrg    PropPtr props = NULL;
256ea6ae205Smrg    int format, count, nprops, i, string_size, rc;
257ea6ae205Smrg    char *strings = NULL, *s;
258ea6ae205Smrg
259ea6ae205Smrg    count = getLSB32(f);
260ea6ae205Smrg    if(count <= 0)
261ea6ae205Smrg        goto fail;
262ea6ae205Smrg
263ea6ae205Smrg    prop_position = -1;
264ea6ae205Smrg    for(i = 0; i < count; i++) {
265ea6ae205Smrg        int type, offset;
266ea6ae205Smrg        type = getLSB32(f);
267ea6ae205Smrg        (void) getLSB32(f);
268ea6ae205Smrg        (void) getLSB32(f);
269ea6ae205Smrg        offset = getLSB32(f);
270ea6ae205Smrg        if(type == PCF_PROPERTIES) {
271ea6ae205Smrg            prop_position = offset;
272ea6ae205Smrg            break;
273ea6ae205Smrg        }
274ea6ae205Smrg    }
275ea6ae205Smrg    if(prop_position < 0)
276ea6ae205Smrg        goto fail;
277ea6ae205Smrg
2787978d3cdSmrg    rc = fontFileSeek(f, prop_position, SEEK_SET);
279ea6ae205Smrg    if(rc < 0)
280ea6ae205Smrg        goto fail;
281ea6ae205Smrg
282ea6ae205Smrg    format = getLSB32(f);
283ea6ae205Smrg    if((format & 0xFFFFFF00) != 0)
284ea6ae205Smrg        goto fail;
285ea6ae205Smrg    nprops = getInt32(f, format);
286ea6ae205Smrg    if(nprops <= 0 || nprops > 1000)
287ea6ae205Smrg        goto fail;
288ea6ae205Smrg    props = malloc(nprops * sizeof(PropRec));
289ea6ae205Smrg    if(props == NULL)
290ea6ae205Smrg        goto fail;
291ea6ae205Smrg
292ea6ae205Smrg    for(i = 0; i < nprops; i++) {
293ea6ae205Smrg        props[i].name = getInt32(f, format);
294ea6ae205Smrg        props[i].isString = getInt8(f, format);
295ea6ae205Smrg        props[i].value = getInt32(f, format);
296ea6ae205Smrg    }
297ea6ae205Smrg    if(nprops & 3) {
2987978d3cdSmrg	rc = fontFileSeek(f, 4 - (nprops & 3), SEEK_CUR);
299ea6ae205Smrg        if(rc < 0)
300ea6ae205Smrg            goto fail;
301ea6ae205Smrg    }
302ea6ae205Smrg
303ea6ae205Smrg    string_size = getInt32(f, format);
304ea6ae205Smrg    if(string_size < 0 || string_size > 100000)
305ea6ae205Smrg        goto fail;
306ea6ae205Smrg    strings = malloc(string_size);
307ea6ae205Smrg    if(!strings)
308ea6ae205Smrg        goto fail;
309ea6ae205Smrg
3107978d3cdSmrg    rc = fontFileRead(f, strings, string_size);
311ea6ae205Smrg    if(rc != string_size)
312ea6ae205Smrg        goto fail;
313ea6ae205Smrg
314ea6ae205Smrg    for(i = 0; i < nprops; i++) {
315ea6ae205Smrg        if(!props[i].isString ||
316ea6ae205Smrg           props[i].name >= string_size - 4 ||
317ea6ae205Smrg           props[i].value >= string_size)
318ea6ae205Smrg            continue;
319ea6ae205Smrg        if(strcmp(strings + props[i].name, "FONT") == 0)
320ea6ae205Smrg            break;
321ea6ae205Smrg    }
322ea6ae205Smrg
323ea6ae205Smrg    if(i >= nprops)
324ea6ae205Smrg        goto fail;
325ea6ae205Smrg
326ea6ae205Smrg    s = malloc(strlen(strings + props[i].value) + 1);
327ea6ae205Smrg    if(s == NULL)
328ea6ae205Smrg        goto fail;
329ea6ae205Smrg    strcpy(s, strings + props[i].value);
330ea6ae205Smrg    *name = s;
331ea6ae205Smrg    free(strings);
332ea6ae205Smrg    free(props);
3337978d3cdSmrg    fontFileClose(f);
334ea6ae205Smrg    return 1;
335ea6ae205Smrg
336ea6ae205Smrg fail:
337ea6ae205Smrg    if(strings) free(strings);
338ea6ae205Smrg    if(props) free(props);
3397978d3cdSmrg    fontFileClose(f);
340ea6ae205Smrg    return 0;
341ea6ae205Smrg}
342ea6ae205Smrg
343ea6ae205Smrg#define NKEY 20
344ea6ae205Smrg
345ea6ae205Smrgstatic char*
3467978d3cdSmrggetKeyword(fontFile *f, int *eol)
347ea6ae205Smrg{
348ea6ae205Smrg    static char keyword[NKEY + 1];
349ea6ae205Smrg    int c, i;
350ea6ae205Smrg    i = 0;
351ea6ae205Smrg    while(i < NKEY) {
3527978d3cdSmrg        c = fontFileGetc(f);
353ea6ae205Smrg        if(c == ' ' || c == '\n') {
354ea6ae205Smrg            if(i <= 0)
355ea6ae205Smrg                return NULL;
356ea6ae205Smrg            if(eol)
357ea6ae205Smrg                *eol = (c == '\n');
358ea6ae205Smrg            keyword[i] = '\0';
359ea6ae205Smrg            return keyword;
360ea6ae205Smrg        }
361ea6ae205Smrg        if(c < 'A' || c > 'Z')
362ea6ae205Smrg            return NULL;
363ea6ae205Smrg        keyword[i++] = c;
364ea6ae205Smrg    }
365ea6ae205Smrg    return NULL;
366ea6ae205Smrg}
367ea6ae205Smrg
368ea6ae205Smrgstatic int
3697978d3cdSmrgbdfskip(fontFile *f)
370ea6ae205Smrg{
371ea6ae205Smrg    int c;
372ea6ae205Smrg    do {
3737978d3cdSmrg        c = fontFileGetc(f);
374ea6ae205Smrg    } while(c >= 0 && c != '\n');
375ea6ae205Smrg    if(c < 0)
376ea6ae205Smrg        return -1;
377ea6ae205Smrg    return 1;
378ea6ae205Smrg}
379ea6ae205Smrg
380ea6ae205Smrgstatic char *
3817978d3cdSmrgbdfend(fontFile *f)
382ea6ae205Smrg{
383ea6ae205Smrg    int c;
384ea6ae205Smrg    char *buf = NULL;
385ea6ae205Smrg    int bufsize = 0;
386ea6ae205Smrg    int i = 0;
387ea6ae205Smrg
388ea6ae205Smrg    do {
3897978d3cdSmrg        c = fontFileGetc(f);
390ea6ae205Smrg    } while (c == ' ');
391ea6ae205Smrg
392ea6ae205Smrg    while(i < 1000) {
393ea6ae205Smrg        if(c < 0 || (c == '\n' && i == 0)) {
394ea6ae205Smrg            goto fail;
395ea6ae205Smrg        }
396ea6ae205Smrg        if(bufsize < i + 1) {
397ea6ae205Smrg            char *newbuf;
398ea6ae205Smrg            if(bufsize == 0) {
399ea6ae205Smrg                bufsize = 20;
400ea6ae205Smrg                newbuf = malloc(bufsize);
401ea6ae205Smrg            } else {
402ea6ae205Smrg                bufsize = 2 * bufsize;
403ea6ae205Smrg                newbuf = realloc(buf, bufsize);
404ea6ae205Smrg            }
405ea6ae205Smrg            if(newbuf == NULL)
406ea6ae205Smrg                goto fail;
407ea6ae205Smrg            buf = newbuf;
408ea6ae205Smrg        }
409ea6ae205Smrg        if(c == '\n') {
410ea6ae205Smrg            buf[i] = '\0';
411ea6ae205Smrg            return buf;
412ea6ae205Smrg        }
413ea6ae205Smrg        buf[i++] = c;
4147978d3cdSmrg        c = fontFileGetc(f);
415ea6ae205Smrg    }
416ea6ae205Smrg
417ea6ae205Smrg fail:
418ea6ae205Smrg    if(buf)
419ea6ae205Smrg        free(buf);
420ea6ae205Smrg    return NULL;
421ea6ae205Smrg}
422ea6ae205Smrg
423ea6ae205Smrgstatic int
4247978d3cdSmrgbdfIdentify(fontFile *f, char **name)
425ea6ae205Smrg{
426ea6ae205Smrg    char *k;
427ea6ae205Smrg    int rc;
428ea6ae205Smrg    int eol;
429ea6ae205Smrg    /* bitmapIdentify already read "STAR", so we need to check for
430ea6ae205Smrg       "TFONT" */
431ea6ae205Smrg    k = getKeyword(f, &eol);
432ea6ae205Smrg    if(k == NULL || eol)
433ea6ae205Smrg        goto fail;
434ea6ae205Smrg    if(strcmp(k, "TFONT") != 0)
435ea6ae205Smrg        goto fail;
436ea6ae205Smrg    while(1) {
437ea6ae205Smrg        if(!eol) {
438ea6ae205Smrg            rc = bdfskip(f);
439ea6ae205Smrg            if(rc < 0)
440ea6ae205Smrg                goto fail;
441ea6ae205Smrg        }
442ea6ae205Smrg        k = getKeyword(f, &eol);
443ea6ae205Smrg        if(k == NULL)
444ea6ae205Smrg            goto fail;
445ea6ae205Smrg        else if(strcmp(k, "FONT") == 0) {
446ea6ae205Smrg            if(eol)
447ea6ae205Smrg                goto fail;
448ea6ae205Smrg            k = bdfend(f);
449ea6ae205Smrg            if(k == NULL)
450ea6ae205Smrg                goto fail;
451ea6ae205Smrg            *name = k;
4527978d3cdSmrg            fontFileClose(f);
453ea6ae205Smrg            return 1;
454ea6ae205Smrg        } else if(strcmp(k, "CHARS") == 0)
455ea6ae205Smrg            goto fail;
456ea6ae205Smrg    }
457ea6ae205Smrg fail:
4587978d3cdSmrg    fontFileClose(f);
459ea6ae205Smrg    return 0;
460ea6ae205Smrg}
461