aboutsummaryrefslogtreecommitdiff
path: root/mkfontscale/ident.c
diff options
context:
space:
mode:
Diffstat (limited to 'mkfontscale/ident.c')
-rw-r--r--mkfontscale/ident.c910
1 files changed, 452 insertions, 458 deletions
diff --git a/mkfontscale/ident.c b/mkfontscale/ident.c
index 544583398..6143a0e3f 100644
--- a/mkfontscale/ident.c
+++ b/mkfontscale/ident.c
@@ -1,458 +1,452 @@
-/*
- Copyright (c) 2003 by Juliusz Chroboczek
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-*/
-/* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, and/or sell copies of the Software, and to permit persons
- * to whom the Software is furnished to do so, provided that the above
- * copyright notice(s) and this permission notice appear in all copies of
- * the Software and that both the above copyright notice(s) and this
- * permission notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
- * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
- * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder
- * shall not be used in advertising or otherwise to promote the sale, use
- * or other dealings in this Software without prior written authorization
- * of the copyright holder.
- */
-/* $XFree86: xc/programs/mkfontscale/ident.c,v 1.3tsi Exp $ */
-
-/* The function identifyBitmap returns -1 if filename is definitively not
- a font file, 1 if it is a single-face bitmap font with a XLFD name,
- and 0 if it should be processed normally. identifyBitmap is
- much faster than parsing the whole font. */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include "zlib.h"
-#include "ident.h"
-
-#ifdef X_BZIP2_FONT_COMPRESSION
-# include <bzlib.h>
-#endif
-
-#define PCF_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1)
-#define PCF_PROPERTIES (1 << 0)
-
-typedef struct _Prop {
- unsigned name;
- int isString;
- unsigned value;
-} PropRec, *PropPtr;
-
-#ifdef X_BZIP2_FONT_COMPRESSION
-typedef struct {
- enum { gzFontFile, bz2FontFile } type;
- union {
- gzFile gz;
- BZFILE *bz2;
- } f;
- unsigned pos;
-} fontFile;
-
-static inline void *
-fontFileOpen(fontFile *ff, const char *filename) {
- int n = strlen(filename);
-
- if (strcmp(filename + n - 4, ".bz2") == 0) {
- ff->type = bz2FontFile;
- ff->f.bz2 = BZ2_bzopen(filename, "rb");
- ff->pos = 0;
- return ff->f.bz2;
- } else {
- ff->type = gzFontFile;
- ff->f.gz = gzopen(filename, "rb");
- return ff->f.gz;
- }
-}
-
-static inline int
-fontFileRead(fontFile *ff, void *buf, unsigned len)
-{
- if (ff->type == gzFontFile) {
- return gzread(ff->f.gz, buf, len);
- } else {
- int r = BZ2_bzread(ff->f.bz2, buf, len);
- ff->pos += r;
- return r;
- }
-}
-
-static inline int
-fontFileGetc(fontFile *ff)
-{
- if (ff->type == gzFontFile) {
- return gzgetc(ff->f.gz);
- } else {
- char buf;
- if (BZ2_bzread(ff->f.bz2, &buf, 1) != 1) {
- return -1;
- } else {
- ff->pos += 1;
- return (int) buf;
- }
- }
-}
-
-static int
-fontFileSeek(fontFile *ff, z_off_t offset, int whence)
-{
- if (ff->type == gzFontFile) {
- return gzseek(ff->f.gz, offset, whence);
- } else {
- /* bzlib has no easy equivalent so we have to fake it,
- * fortunately, we only have to handle a couple of cases
- */
- int n;
- char buf[BUFSIZ];
-
- switch (whence) {
- case SEEK_SET:
- n = offset - ff->pos;
- break;
- case SEEK_CUR:
- n = offset;
- break;
- default:
- return -1;
- }
-
- while (n > BUFSIZ) {
- if (BZ2_bzread(ff->f.bz2, buf, BUFSIZ) != BUFSIZ)
- return -1;
- n -= BUFSIZ;
- }
- if (BZ2_bzread(ff->f.bz2, buf, n) != n)
- return -1;
- ff->pos = offset;
- return offset;
- }
-}
-
-
-static inline int
-fontFileClose(fontFile *ff)
-{
- if (ff->type == gzFontFile) {
- return gzclose(ff->f.gz);
- } else {
- BZ2_bzclose(ff->f.bz2);
- return 0;
- }
-}
-
-#else /* no bzip2, only gzip */
-typedef gzFile fontFile;
-# define fontFileOpen(ff, filename) (*(ff) = gzopen(filename, "rb"))
-# define fontFileRead(ff, buf, len) gzread(*(ff), buf, len)
-# define fontFileGetc(ff) gzgetc(*(ff))
-# define fontFileSeek(ff, off, whence) gzseek(*(ff), off, whence)
-# define fontFileClose(ff) gzclose(*(ff))
-#endif
-
-static int pcfIdentify(fontFile *f, char **name);
-static int bdfIdentify(fontFile *f, char **name);
-
-static int
-getLSB32(fontFile *f)
-{
- int rc;
- unsigned char c[4];
-
- rc = fontFileRead(f, c, 4);
- if(rc != 4)
- return -1;
- return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
-}
-
-static int
-getInt8(fontFile *f, int format)
-{
- unsigned char c;
- int rc;
-
- rc = fontFileRead(f, &c, 1);
- if(rc != 1)
- return -1;
- return c;
-}
-
-static int
-getInt32(fontFile *f, int format)
-{
- int rc;
- unsigned char c[4];
-
- rc = fontFileRead(f, c, 4);
- if(rc != 4)
- return -1;
-
- if(format & (1 << 2)) {
- return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3]);
- } else {
- return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
- }
-}
-
-int
-bitmapIdentify(const char *filename, char **name)
-{
- fontFile ff;
- int magic;
-
- if (fontFileOpen(&ff, filename) == NULL)
- return -1;
-
- magic = getLSB32(&ff);
- if(magic == PCF_VERSION)
- return pcfIdentify(&ff, name);
- else if(magic == ('S' | ('T' << 8) | ('A' << 16) | ('R') << 24))
- return bdfIdentify(&ff, name);
-
- fontFileClose(&ff);
- return 0;
-}
-
-static int
-pcfIdentify(fontFile *f, char **name)
-{
- int prop_position;
- PropPtr props = NULL;
- int format, count, nprops, i, string_size, rc;
- char *strings = NULL, *s;
-
- count = getLSB32(f);
- if(count <= 0)
- goto fail;
-
- prop_position = -1;
- for(i = 0; i < count; i++) {
- int type, offset;
- type = getLSB32(f);
- (void) getLSB32(f);
- (void) getLSB32(f);
- offset = getLSB32(f);
- if(type == PCF_PROPERTIES) {
- prop_position = offset;
- break;
- }
- }
- if(prop_position < 0)
- goto fail;
-
- rc = fontFileSeek(f, prop_position, SEEK_SET);
- if(rc < 0)
- goto fail;
-
- format = getLSB32(f);
- if((format & 0xFFFFFF00) != 0)
- goto fail;
- nprops = getInt32(f, format);
- if(nprops <= 0 || nprops > 1000)
- goto fail;
- props = malloc(nprops * sizeof(PropRec));
- if(props == NULL)
- goto fail;
-
- for(i = 0; i < nprops; i++) {
- props[i].name = getInt32(f, format);
- props[i].isString = getInt8(f, format);
- props[i].value = getInt32(f, format);
- }
- if(nprops & 3) {
- rc = fontFileSeek(f, 4 - (nprops & 3), SEEK_CUR);
- if(rc < 0)
- goto fail;
- }
-
- string_size = getInt32(f, format);
- if(string_size < 0 || string_size > 100000)
- goto fail;
- strings = malloc(string_size);
- if(!strings)
- goto fail;
-
- rc = fontFileRead(f, strings, string_size);
- if(rc != string_size)
- goto fail;
-
- for(i = 0; i < nprops; i++) {
- if(!props[i].isString ||
- props[i].name >= string_size - 4 ||
- props[i].value >= string_size)
- continue;
- if(strcmp(strings + props[i].name, "FONT") == 0)
- break;
- }
-
- if(i >= nprops)
- goto fail;
-
- s = malloc(strlen(strings + props[i].value) + 1);
- if(s == NULL)
- goto fail;
- strcpy(s, strings + props[i].value);
- *name = s;
- free(strings);
- free(props);
- fontFileClose(f);
- return 1;
-
- fail:
- if(strings) free(strings);
- if(props) free(props);
- fontFileClose(f);
- return 0;
-}
-
-#define NKEY 20
-
-static char*
-getKeyword(fontFile *f, int *eol)
-{
- static char keyword[NKEY + 1];
- int c, i;
- i = 0;
- while(i < NKEY) {
- c = fontFileGetc(f);
- if(c == ' ' || c == '\n') {
- if(i <= 0)
- return NULL;
- if(eol)
- *eol = (c == '\n');
- keyword[i] = '\0';
- return keyword;
- }
- if(c < 'A' || c > 'Z')
- return NULL;
- keyword[i++] = c;
- }
- return NULL;
-}
-
-static int
-bdfskip(fontFile *f)
-{
- int c;
- do {
- c = fontFileGetc(f);
- } while(c >= 0 && c != '\n');
- if(c < 0)
- return -1;
- return 1;
-}
-
-static char *
-bdfend(fontFile *f)
-{
- int c;
- char *buf = NULL;
- int bufsize = 0;
- int i = 0;
-
- do {
- c = fontFileGetc(f);
- } while (c == ' ');
-
- while(i < 1000) {
- if(c < 0 || (c == '\n' && i == 0)) {
- goto fail;
- }
- if(bufsize < i + 1) {
- char *newbuf;
- if(bufsize == 0) {
- bufsize = 20;
- newbuf = malloc(bufsize);
- } else {
- bufsize = 2 * bufsize;
- newbuf = realloc(buf, bufsize);
- }
- if(newbuf == NULL)
- goto fail;
- buf = newbuf;
- }
- if(c == '\n') {
- buf[i] = '\0';
- return buf;
- }
- buf[i++] = c;
- c = fontFileGetc(f);
- }
-
- fail:
- if(buf)
- free(buf);
- return NULL;
-}
-
-static int
-bdfIdentify(fontFile *f, char **name)
-{
- char *k;
- int rc;
- int eol;
- /* bitmapIdentify already read "STAR", so we need to check for
- "TFONT" */
- k = getKeyword(f, &eol);
- if(k == NULL || eol)
- goto fail;
- if(strcmp(k, "TFONT") != 0)
- goto fail;
- while(1) {
- if(!eol) {
- rc = bdfskip(f);
- if(rc < 0)
- goto fail;
- }
- k = getKeyword(f, &eol);
- if(k == NULL)
- goto fail;
- else if(strcmp(k, "FONT") == 0) {
- if(eol)
- goto fail;
- k = bdfend(f);
- if(k == NULL)
- goto fail;
- *name = k;
- fontFileClose(f);
- return 1;
- } else if(strcmp(k, "CHARS") == 0)
- goto fail;
- }
- fail:
- fontFileClose(f);
- return 0;
-}
+/*
+ Copyright (c) 2003 by Juliusz Chroboczek
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* The function identifyBitmap returns -1 if filename is definitively not
+ a font file, 1 if it is a single-face bitmap font with a XLFD name,
+ and 0 if it should be processed normally. identifyBitmap is
+ much faster than parsing the whole font. */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+#include "ident.h"
+
+#ifdef X_BZIP2_FONT_COMPRESSION
+# include <bzlib.h>
+#endif
+
+#define PCF_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1)
+#define PCF_PROPERTIES (1 << 0)
+
+typedef struct _Prop {
+ unsigned name;
+ int isString;
+ unsigned value;
+} PropRec, *PropPtr;
+
+#ifdef X_BZIP2_FONT_COMPRESSION
+typedef struct {
+ enum { gzFontFile, bz2FontFile } type;
+ union {
+ gzFile gz;
+ BZFILE *bz2;
+ } f;
+ unsigned pos;
+} fontFile;
+
+static inline void *
+fontFileOpen(fontFile *ff, const char *filename) {
+ int n = strlen(filename);
+
+ if (strcmp(filename + n - 4, ".bz2") == 0) {
+ ff->type = bz2FontFile;
+ ff->f.bz2 = BZ2_bzopen(filename, "rb");
+ ff->pos = 0;
+ return ff->f.bz2;
+ } else {
+ ff->type = gzFontFile;
+ ff->f.gz = gzopen(filename, "rb");
+ return ff->f.gz;
+ }
+}
+
+static inline int
+fontFileRead(fontFile *ff, void *buf, unsigned len)
+{
+ if (ff->type == gzFontFile) {
+ return gzread(ff->f.gz, buf, len);
+ } else {
+ int r = BZ2_bzread(ff->f.bz2, buf, len);
+ ff->pos += r;
+ return r;
+ }
+}
+
+static inline int
+fontFileGetc(fontFile *ff)
+{
+ if (ff->type == gzFontFile) {
+ return gzgetc(ff->f.gz);
+ } else {
+ char buf;
+ if (BZ2_bzread(ff->f.bz2, &buf, 1) != 1) {
+ return -1;
+ } else {
+ ff->pos += 1;
+ return (int) buf;
+ }
+ }
+}
+
+static int
+fontFileSeek(fontFile *ff, z_off_t offset, int whence)
+{
+ if (ff->type == gzFontFile) {
+ return gzseek(ff->f.gz, offset, whence);
+ } else {
+ /* bzlib has no easy equivalent so we have to fake it,
+ * fortunately, we only have to handle a couple of cases
+ */
+ int n;
+ char buf[BUFSIZ];
+
+ switch (whence) {
+ case SEEK_SET:
+ n = offset - ff->pos;
+ break;
+ case SEEK_CUR:
+ n = offset;
+ break;
+ default:
+ return -1;
+ }
+
+ while (n > BUFSIZ) {
+ if (BZ2_bzread(ff->f.bz2, buf, BUFSIZ) != BUFSIZ)
+ return -1;
+ n -= BUFSIZ;
+ }
+ if (BZ2_bzread(ff->f.bz2, buf, n) != n)
+ return -1;
+ ff->pos = offset;
+ return offset;
+ }
+}
+
+
+static inline int
+fontFileClose(fontFile *ff)
+{
+ if (ff->type == gzFontFile) {
+ return gzclose(ff->f.gz);
+ } else {
+ BZ2_bzclose(ff->f.bz2);
+ return 0;
+ }
+}
+
+#else /* no bzip2, only gzip */
+typedef gzFile fontFile;
+# define fontFileOpen(ff, filename) (*(ff) = gzopen(filename, "rb"))
+# define fontFileRead(ff, buf, len) gzread(*(ff), buf, len)
+# define fontFileGetc(ff) gzgetc(*(ff))
+# define fontFileSeek(ff, off, whence) gzseek(*(ff), off, whence)
+# define fontFileClose(ff) gzclose(*(ff))
+#endif
+
+static int pcfIdentify(fontFile *f, char **name);
+static int bdfIdentify(fontFile *f, char **name);
+
+static int
+getLSB32(fontFile *f)
+{
+ int rc;
+ unsigned char c[4];
+
+ rc = fontFileRead(f, c, 4);
+ if(rc != 4)
+ return -1;
+ return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
+}
+
+static int
+getInt8(fontFile *f, int format)
+{
+ unsigned char c;
+ int rc;
+
+ rc = fontFileRead(f, &c, 1);
+ if(rc != 1)
+ return -1;
+ return c;
+}
+
+static int
+getInt32(fontFile *f, int format)
+{
+ int rc;
+ unsigned char c[4];
+
+ rc = fontFileRead(f, c, 4);
+ if(rc != 4)
+ return -1;
+
+ if(format & (1 << 2)) {
+ return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3]);
+ } else {
+ return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
+ }
+}
+
+int
+bitmapIdentify(const char *filename, char **name)
+{
+ fontFile ff;
+ int magic;
+
+ if (fontFileOpen(&ff, filename) == NULL)
+ return -1;
+
+ magic = getLSB32(&ff);
+ if(magic == PCF_VERSION)
+ return pcfIdentify(&ff, name);
+ else if(magic == ('S' | ('T' << 8) | ('A' << 16) | ('R') << 24))
+ return bdfIdentify(&ff, name);
+
+ fontFileClose(&ff);
+ return 0;
+}
+
+static int
+pcfIdentify(fontFile *f, char **name)
+{
+ int prop_position;
+ PropPtr props = NULL;
+ int format, count, nprops, i, string_size, rc;
+ char *strings = NULL, *s;
+
+ count = getLSB32(f);
+ if(count <= 0)
+ goto fail;
+
+ prop_position = -1;
+ for(i = 0; i < count; i++) {
+ int type, offset;
+ type = getLSB32(f);
+ (void) getLSB32(f);
+ (void) getLSB32(f);
+ offset = getLSB32(f);
+ if(type == PCF_PROPERTIES) {
+ prop_position = offset;
+ break;
+ }
+ }
+ if(prop_position < 0)
+ goto fail;
+
+ rc = fontFileSeek(f, prop_position, SEEK_SET);
+ if(rc < 0)
+ goto fail;
+
+ format = getLSB32(f);
+ if((format & 0xFFFFFF00) != 0)
+ goto fail;
+ nprops = getInt32(f, format);
+ if(nprops <= 0 || nprops > 1000)
+ goto fail;
+ props = malloc(nprops * sizeof(PropRec));
+ if(props == NULL)
+ goto fail;
+
+ for(i = 0; i < nprops; i++) {
+ props[i].name = getInt32(f, format);
+ props[i].isString = getInt8(f, format);
+ props[i].value = getInt32(f, format);
+ }
+ if(nprops & 3) {
+ rc = fontFileSeek(f, 4 - (nprops & 3), SEEK_CUR);
+ if(rc < 0)
+ goto fail;
+ }
+
+ string_size = getInt32(f, format);
+ if(string_size < 0 || string_size > 100000)
+ goto fail;
+ strings = malloc(string_size);
+ if(!strings)
+ goto fail;
+
+ rc = fontFileRead(f, strings, string_size);
+ if(rc != string_size)
+ goto fail;
+
+ for(i = 0; i < nprops; i++) {
+ if(!props[i].isString ||
+ props[i].name >= string_size - 4 ||
+ props[i].value >= string_size)
+ continue;
+ if(strcmp(strings + props[i].name, "FONT") == 0)
+ break;
+ }
+
+ if(i >= nprops)
+ goto fail;
+
+ s = malloc(strlen(strings + props[i].value) + 1);
+ if(s == NULL)
+ goto fail;
+ strcpy(s, strings + props[i].value);
+ *name = s;
+ free(strings);
+ free(props);
+ fontFileClose(f);
+ return 1;
+
+ fail:
+ if(strings) free(strings);
+ if(props) free(props);
+ fontFileClose(f);
+ return 0;
+}
+
+#define NKEY 20
+
+static char*
+getKeyword(fontFile *f, int *eol)
+{
+ static char keyword[NKEY + 1];
+ int c, i;
+ i = 0;
+ while(i < NKEY) {
+ c = fontFileGetc(f);
+ if(c == ' ' || c == '\n') {
+ if(i <= 0)
+ return NULL;
+ if(eol)
+ *eol = (c == '\n');
+ keyword[i] = '\0';
+ return keyword;
+ }
+ if(c < 'A' || c > 'Z')
+ return NULL;
+ keyword[i++] = c;
+ }
+ return NULL;
+}
+
+static int
+bdfskip(fontFile *f)
+{
+ int c;
+ do {
+ c = fontFileGetc(f);
+ } while(c >= 0 && c != '\n');
+ if(c < 0)
+ return -1;
+ return 1;
+}
+
+static char *
+bdfend(fontFile *f)
+{
+ int c;
+ char *buf = NULL;
+ int bufsize = 0;
+ int i = 0;
+
+ do {
+ c = fontFileGetc(f);
+ } while (c == ' ');
+
+ while(i < 1000) {
+ if(c < 0 || (c == '\n' && i == 0)) {
+ goto fail;
+ }
+ if(bufsize < i + 1) {
+ char *newbuf;
+ if(bufsize == 0) {
+ bufsize = 20;
+ newbuf = malloc(bufsize);
+ } else {
+ bufsize = 2 * bufsize;
+ newbuf = realloc(buf, bufsize);
+ }
+ if(newbuf == NULL)
+ goto fail;
+ buf = newbuf;
+ }
+ if(c == '\n') {
+ buf[i] = '\0';
+ return buf;
+ }
+ buf[i++] = c;
+ c = fontFileGetc(f);
+ }
+
+ fail:
+ if(buf)
+ free(buf);
+ return NULL;
+}
+
+static int
+bdfIdentify(fontFile *f, char **name)
+{
+ char *k;
+ int rc;
+ int eol;
+ /* bitmapIdentify already read "STAR", so we need to check for
+ "TFONT" */
+ k = getKeyword(f, &eol);
+ if(k == NULL || eol)
+ goto fail;
+ if(strcmp(k, "TFONT") != 0)
+ goto fail;
+ while(1) {
+ if(!eol) {
+ rc = bdfskip(f);
+ if(rc < 0)
+ goto fail;
+ }
+ k = getKeyword(f, &eol);
+ if(k == NULL)
+ goto fail;
+ else if(strcmp(k, "FONT") == 0) {
+ if(eol)
+ goto fail;
+ k = bdfend(f);
+ if(k == NULL)
+ goto fail;
+ *name = k;
+ fontFileClose(f);
+ return 1;
+ } else if(strcmp(k, "CHARS") == 0)
+ goto fail;
+ }
+ fail:
+ fontFileClose(f);
+ return 0;
+}