Back to index

tetex-bin  3.0
fontmap.c
Go to the documentation of this file.
00001 /* fontmap.c: read files for additional font names.
00002 
00003 Copyright (C) 1993, 94, 95, 96, 97 Free Software Foundation, Inc.
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Library General Public
00007 License as published by the Free Software Foundation; either
00008 version 2 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Library General Public License for more details.
00014 
00015 You should have received a copy of the GNU Library General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00018 
00019 #include <kpathsea/config.h>
00020 
00021 #include <kpathsea/c-ctype.h>
00022 #include <kpathsea/c-fopen.h>
00023 #include <kpathsea/fontmap.h>
00024 #include <kpathsea/hash.h>
00025 #include <kpathsea/line.h>
00026 #include <kpathsea/pathsearch.h>
00027 #include <kpathsea/str-list.h>
00028 #include <kpathsea/tex-file.h>
00029 
00030 /* We have one and only one fontmap, so may as well make it static
00031    instead of passing it around.  */
00032 static hash_table_type map;
00033 #ifndef MAP_NAME
00034 #define MAP_NAME "texfonts.map"
00035 #endif
00036 #ifndef MAP_HASH_SIZE
00037 #define MAP_HASH_SIZE 4001
00038 #endif
00039 
00040 static const_string map_path; /* Only want to create this once. */
00041 
00042 /* Return next whitespace-delimited token in STR or NULL if none.  */
00043 
00044 static string
00045 token P1C(const_string, str)
00046 {
00047   unsigned len;
00048   const_string start;
00049   string ret;
00050   
00051   while (*str && ISSPACE (*str))
00052     str++;
00053   
00054   start = str;
00055   while (*str && !ISSPACE (*str))
00056     str++;
00057   
00058   len = str - start;
00059   ret = (string)xmalloc (len + 1);
00060   strncpy (ret, start, len);
00061   ret[len] = 0;
00062   
00063   return ret;
00064 }
00065 
00066 /* Open and read the mapping file MAP_FILENAME, putting its entries into
00067    MAP. Comments begin with % and continue to the end of the line.  Each
00068    line of the file defines an entry: the first word is the real
00069    filename (e.g., `ptmr'), the second word is the alias (e.g.,
00070    `Times-Roman'), and any subsequent words are ignored.  .tfm is added
00071    if either the filename or the alias have no extension.  This is the
00072    same order as in Dvips' psfonts.map.  Perhaps someday the programs
00073    will both read the same file.  */
00074 
00075 static void
00076 map_file_parse P1C(const_string, map_filename)
00077 {
00078   char *orig_l;
00079   unsigned map_lineno = 0;
00080   FILE *f = xfopen (map_filename, FOPEN_R_MODE);
00081   
00082   while ((orig_l = read_line (f)) != NULL) {
00083     string filename;
00084     string l = orig_l;
00085     string comment_loc = strrchr (l, '%');
00086     if (!comment_loc) {
00087       comment_loc = strstr (l, "@c");
00088     }
00089     
00090     /* Ignore anything after a % or @c.  */
00091     if (comment_loc)
00092       *comment_loc = 0;
00093 
00094     map_lineno++;
00095 
00096     /* Skip leading whitespace so we can use strlen below.  Can't use
00097        strtok since this routine is recursive.  */
00098     while (*l && ISSPACE (*l))
00099       l++;
00100       
00101     /* If we don't have any filename, that's ok, the line is blank.  */
00102     filename = token (l);
00103     if (filename) {
00104       string alias = token (l + strlen (filename));
00105 
00106       if (STREQ (filename, "include")) {
00107         if (alias == NULL) {
00108           WARNING2 ("%s:%u: Filename argument for include directive missing",
00109                     map_filename, map_lineno);
00110         } else {
00111           string include_fname = kpse_path_search (map_path, alias, false);
00112           if (include_fname) {
00113             map_file_parse (include_fname);
00114             if (include_fname != alias)
00115               free (include_fname);
00116           } else {
00117             WARNING3 ("%s:%u: Can't find fontname include file `%s'",
00118                       map_filename, map_lineno, alias);
00119           }
00120           free (alias);
00121           free (filename);
00122         }
00123 
00124       /* But if we have a filename and no alias, something's wrong.  */
00125       } else if (alias == NULL) {
00126         WARNING3 ("%s:%u: Fontname alias missing for filename `%s'",
00127                   map_filename, map_lineno, filename);
00128         free (filename);
00129 
00130       } else {
00131         /* We've got everything.  Insert the new entry.  They were
00132            already dynamically allocated, so don't bother with xstrdup.  */
00133         hash_insert_normalized (&map, alias, filename);
00134       }
00135     }
00136 
00137     free (l);
00138   }
00139   
00140   xfclose (f, map_filename);
00141 }
00142 
00143 /* Parse the file MAP_NAME in each of the directories in PATH and
00144    return the resulting structure.  Entries in earlier files override
00145    later files.  */
00146 
00147 static void
00148 read_all_maps P1H(void)
00149 {
00150   string *filenames;
00151   
00152   map_path = kpse_init_format (kpse_fontmap_format);
00153   filenames = kpse_all_path_search (map_path, MAP_NAME);
00154   
00155   map = hash_create (MAP_HASH_SIZE);
00156 
00157   while (*filenames) {
00158     map_file_parse (*filenames);
00159     filenames++;
00160   }
00161 }
00162 
00163 /* Look up KEY in texfonts.map's; if it's not found, remove any suffix
00164    from KEY and try again.  Create the map if necessary.  */
00165 
00166 string *
00167 kpse_fontmap_lookup P1C(const_string, key)
00168 {
00169   string *ret;
00170   string suffix = find_suffix (key);
00171   
00172   if (map.size == 0) {
00173     read_all_maps ();
00174   }
00175 
00176   ret = hash_lookup (map, key);
00177   if (!ret) {
00178     /* OK, the original KEY didn't work.  Let's check for the KEY without
00179        an extension -- perhaps they gave foobar.tfm, but the mapping only
00180        defines `foobar'.  */
00181     if (suffix) {
00182       string base_key = remove_suffix (key);
00183       ret = hash_lookup (map, base_key);
00184       free (base_key);
00185     }
00186   }
00187 
00188   /* Append any original suffix.  */
00189   if (ret && suffix) {
00190     string *elt;
00191     for (elt = ret; *elt; elt++) {
00192       *elt = extend_filename (*elt, suffix);
00193     }
00194   }
00195 
00196   return ret;
00197 }