diff options
Diffstat (limited to 'lib/encoding.c')
| -rw-r--r-- | lib/encoding.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/lib/encoding.c b/lib/encoding.c new file mode 100644 index 0000000..a40d281 --- /dev/null +++ b/lib/encoding.c @@ -0,0 +1,191 @@ +/* encoding.c: read a font encoding (.enc) file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "encoding.h" +#include "libfile.h" +#include "str-lcase.h" +#include "tfm.h" + + +static encoding_char_type parse_encoding_line (string); +static tfm_ligature_type parse_ligature (void); + +/* Look through INFO for NAME. */ + +int +encoding_number (encoding_info_type info, string name) +{ + unsigned code; + + if (name == NULL) + return -1; + + for (code = 0; code <= MAX_CHARCODE; code++) + if (ENCODING_CHAR_NAME (info, code) != NULL + && STREQ (ENCODING_CHAR_NAME (info, code), name)) + return code; + + return -1; +} + +/* Return the basename for the encoding file in which the encoding + CODING_SCHEME can be found. If we can't find CODING_SCHEME, return + DEFAULT_ENCODING. */ + +string +coding_scheme_to_filename (string coding_scheme) +{ + string mapping_line, enc_name; + string lc_coding_scheme = str_to_lower (coding_scheme); + + libfile_start ("encoding", "map"); + + while ((mapping_line = libfile_line ()) != NULL) + { + string test_coding_scheme, lc_test_coding_scheme; + + enc_name = strtok (mapping_line, " \t"); + test_coding_scheme = strtok (NULL, "\t"); + lc_test_coding_scheme = str_to_lower (test_coding_scheme); + + if (STREQ (lc_coding_scheme, lc_test_coding_scheme)) + break; + + free (lc_test_coding_scheme); + free (mapping_line); + } + + libfile_close (); + + if (mapping_line == NULL) + { + WARNING3 ("%s: unknown encoding `%s'; using default `%s'", + "encoding.map", coding_scheme, DEFAULT_ENCODING); + enc_name = DEFAULT_ENCODING; + } + + free (lc_coding_scheme); + + return enc_name; +} + +/* Parse the encoding file `FILENAME.enc' and return a structure + describing what we read. If the file doesn't exist, give a fatal + error. */ + +encoding_info_type +read_encoding_file (string filename) +{ + encoding_info_type info; + string line; + unsigned code; + + /* Prepare to read from FILENAME. */ + libfile_start (filename, "enc"); + + /* Start with an empty encoding. */ + for (code = 0; code <= MAX_CHARCODE; code++) + ENCODING_CHAR_NAME (info, code) = NULL; + + /* The entire first line is the TFM `CODINGSCHEME'. */ + ENCODING_SCHEME_NAME (info) = libfile_line (); + + /* Each remaining line defines one character. */ + code = 0; + while ((line = libfile_line ()) != NULL) + { + ENCODING_CHAR_ELT (info, code) = parse_encoding_line (line); + code++; + free (line); + } + + return info; +} + +/* Parse one line of the encoding file; this specifies one character. + The BNF is: + + <line> ::= <word> <ligatures> + + <ligatures> ::= <ligature> [<ligature>]? + | <empty> + + <ligature> ::= lig <charcode> =: <charcode> + + Whitespace must be between all elements. + + If the line is malformed, we give a fatal error. */ + +#define WORD_SEPARATOR " \t" +#define GET_WORD() strtok (NULL, WORD_SEPARATOR) + +static encoding_char_type +parse_encoding_line (string line) +{ + encoding_char_type c; + + c.name = xstrdup (strtok (line, WORD_SEPARATOR)); + c.ligature = list_init (); + + do + { + tfm_ligature_type *lig; + string t = GET_WORD (); + + if (t == NULL) /* Do we have more ligature specs? */ + break; + + if (!STREQ (t, "lig")) + LIBFILE_ERROR1 ("Expected `lig', found `%s'", t); + + lig = LIST_TAPPEND (&c.ligature, tfm_ligature_type); + *lig = parse_ligature (); + } + while (true); + + return c; +} + + +/* Parse a single ligature: <charcode> =: <charcode>. */ + +static tfm_ligature_type +parse_ligature () +{ + tfm_ligature_type lig; + boolean valid; + string t = GET_WORD (); + + lig.character = parse_charcode (t, &valid); + + if (!valid) + LIBFILE_ERROR1 ("Invalid right character code `%s'", t); + + t = GET_WORD (); + if (!STREQ (t, "=:")) + LIBFILE_ERROR1 ("Expected `=:', found `%s'", t); + + t = GET_WORD (); + lig.ligature = parse_charcode (t, &valid); + if (!valid) + LIBFILE_ERROR1 ("Invalid ligature character code `%s'", t); + + return lig; +} |
