summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/lcdf-typetools-src/otftotfm/automatic.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-src/otftotfm/automatic.cc')
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-src/otftotfm/automatic.cc816
1 files changed, 0 insertions, 816 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/otftotfm/automatic.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-src/otftotfm/automatic.cc
deleted file mode 100644
index 0567de51e2c..00000000000
--- a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/otftotfm/automatic.cc
+++ /dev/null
@@ -1,816 +0,0 @@
-/* automatic.{cc,hh} -- code for automatic mode and interfacing with kpathsea
- *
- * Copyright (c) 2003-2019 Eddie Kohler
- *
- * 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 of the License, 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.
- */
-
-#include <config.h>
-#include "automatic.hh"
-#include "kpseinterface.h"
-#include "util.hh"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#if HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#if HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#include <lcdf/error.hh>
-#include <lcdf/straccum.hh>
-#if HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-#include <algorithm>
-
-#ifdef WIN32
-# include <io.h>
-# include <direct.h>
-# define mkdir(dir, access) _mkdir(dir)
-# define COPY_CMD "copy"
-# define CMD_SEP "&"
-#else
-# define COPY_CMD "cp"
-# define CMD_SEP ";"
-#endif
-
-/* kpathsea may already have defined this */
-#ifndef DEV_NULL
-# ifdef WIN32
-# define DEV_NULL "NUL"
-# else
-# define DEV_NULL "/dev/null"
-# endif
-#endif
-
-#if HAVE_AUTO_T1DOTLESSJ
-enum { T1DOTLESSJ_EXIT_J_NODOT = 2 };
-#endif
-
-static String odir[NUMODIR];
-static String typeface;
-static String vendor;
-static String map_file;
-#define DEFAULT_VENDOR "lcdftools"
-#define DEFAULT_TYPEFACE "unknown"
-
-static const struct {
- const char *name;
- const char *envvar;
- const char *texdir;
-} odir_info[] = {
- { "encoding", "ENCODINGDESTDIR", "#fonts/enc/dvips/@#dvips/@" },
- { "TFM", "TFMDESTDIR", "fonts/tfm/%" },
- { "PL", "PLDESTDIR", "fonts/pl/%" },
- { "VF", "VFDESTDIR", "fonts/vf/%" },
- { "VPL", "VPLDESTDIR", "fonts/vpl/%" },
- { "Type 1", "T1DESTDIR", "fonts/type1/%" },
- { "DVIPS map", "DVIPS directory", "#fonts/map/dvips/@#dvips/@" },
- { "DVIPS updmap", "DVIPS directory", "dvips" },
- { "TrueType", "TTFDESTDIR", "fonts/truetype/%" },
- { "OpenType", "OPENTYPEDESTDIR", "fonts/opentype/%" },
- { "Type 42", "T42DESTDIR", "fonts/type42/%" }
-};
-
-#if HAVE_KPATHSEA
-static String odir_kpathsea[NUMODIR];
-
-static bool writable_texdir_tried = false;
-static String writable_texdir; // always ends with directory separator
-static int tds_1_1 = -1;
-
-static bool mktexupd_tried = false;
-static String mktexupd;
-
-static String
-kpsei_string(char* x)
-{
- String s(x);
- free((void*)x);
- return s;
-}
-
-static void
-look_for_writable_texdir(const char *path_variable, bool create)
-{
- String path = kpsei_string(kpsei_path_expand(path_variable));
- while (path && !writable_texdir) {
- const char* colon = std::find(path.begin(), path.end(), kpsei_env_sep_char);
- String texdir = path.substring(path.begin(), colon);
- path = path.substring(colon + 1, path.end());
- if (access(texdir.c_str(), W_OK) >= 0)
- writable_texdir = texdir;
- else if (create && errno != EACCES && mkdir(texdir.c_str(), 0777) >= 0)
- // create file if it doesn't exist already
- writable_texdir = texdir;
- }
- if (writable_texdir && writable_texdir.back() != '/')
- writable_texdir += "/";
-}
-
-static void
-find_writable_texdir(ErrorHandler *errh, const char *)
-{
-#if defined(W32TEX)
-// W32TeX does not have TEXMFVAR
- char *p = kpsei_var_value("TEXMFVAR");
- if (p == NULL) // W32TeX
- look_for_writable_texdir("$TEXMFLOCAL", true);
- else { // TeXLive
- free (p);
- look_for_writable_texdir("$TEXMFVAR", true);
- }
-#else
- look_for_writable_texdir("$TEXMFVAR", true);
-#endif
- if (!writable_texdir)
- look_for_writable_texdir("$VARTEXMF", false);
- if (!writable_texdir)
- look_for_writable_texdir("$TEXMF", false);
- if (!writable_texdir) {
- errh->warning("no writable directory found in $TEXMFVAR or $TEXMF");
- errh->message("(You probably need to set your TEXMF environment variable; see\n\
-the manual for more information. The current TEXMF path is\n\
-%<%s%>.)", kpsei_string(kpsei_path_expand("$TEXMF")).c_str());
- }
- writable_texdir_tried = true;
-}
-
-static String
-get_vendor()
-{
- return (vendor ? vendor : String(DEFAULT_VENDOR));
-}
-
-static String
-get_typeface()
-{
- return (typeface ? typeface : String(DEFAULT_TYPEFACE));
-}
-#endif
-
-bool
-set_vendor(const String &s)
-{
- bool had = (bool) vendor;
- vendor = s;
- return !had;
-}
-
-bool
-set_typeface(const String &s, bool override)
-{
- bool had = (bool) typeface;
- if (!had || override)
- typeface = s;
- return !had;
-}
-
-String
-getodir(int o, ErrorHandler *errh)
-{
- assert(o >= 0 && o < NUMODIR);
-
- if (!odir[o] && automatic && odir_info[o].envvar)
- odir[o] = getenv(odir_info[o].envvar);
-
-#if HAVE_KPATHSEA
- if (!odir[o] && automatic && !writable_texdir_tried)
- find_writable_texdir(errh, odir_info[o].name);
-
- if (!odir[o] && automatic && writable_texdir) {
- String suffix = odir_info[o].texdir;
-
- // May need to behave differently on TDS 1.1 rather than TDS 1.0.
- if (suffix[0] == '#') {
- // check type of TDS
- if (tds_1_1 < 0) {
- // using a procedure suggested by Olaf Weber
- String encfonts = kpsei_string(kpsei_path_expand("$TEXMFMAIN/fonts/enc"));
- if (!encfonts)
- encfonts = kpsei_string(kpsei_path_expand("$TEXMFDIST/fonts/enc"));
- tds_1_1 = (encfonts != String());
- }
- if (tds_1_1 == 0)
- suffix = suffix.substring(std::find(suffix.begin() + 1, suffix.end(), '#') + 1, suffix.end());
- else
- suffix = suffix.substring(suffix.begin() + 1, std::find(suffix.begin() + 1, suffix.end(), '#'));
- }
-
- String dir = writable_texdir + suffix;
-
- if (dir.back() == '%')
- dir = dir.substring(0, -1) + get_vendor() + "/" + get_typeface();
- else if (dir.back() == '@')
- dir = dir.substring(0, -1) + get_vendor();
-
- // create parent directories as appropriate
- int slash = writable_texdir.length() - 1;
- while (access(dir.c_str(), F_OK) < 0 && slash < dir.length()) {
- if ((slash = dir.find_left('/', slash + 1)) < 0)
- slash = dir.length();
- String subdir = dir.substring(0, slash);
- if (access(subdir.c_str(), F_OK) < 0
- && !no_create
- && mkdir(subdir.c_str(), 0777) < 0)
- goto kpathsea_done;
- }
-
- // that's our answer
- odir[o] = dir;
- odir_kpathsea[o] = dir;
- }
- kpathsea_done:
-#endif
-
- if (!odir[o]) {
- if (automatic) {
- errh->warning("%s not specified, placing %s files in %<.%>", odir_info[o].envvar, odir_info[o].name);
-#if !HAVE_KPATHSEA
- static int kpathsea_warning = 0;
- if (++kpathsea_warning == 1)
- errh->message("(This version of otftotfm lacks $TEXMF directory support.)");
-#endif
- }
- odir[o] = ".";
- }
-
- while (odir[o].length() && odir[o].back() == '/')
- odir[o] = odir[o].substring(0, -1);
-
- if (verbose)
- errh->message("placing %s files in %<%s%>", odir_info[o].name, odir[o].c_str());
- return odir[o];
-}
-
-void
-setodir(int o, const String &value)
-{
- assert(o >= 0 && o < NUMODIR);
- odir[o] = value;
-}
-
-const char *
-odirname(int o)
-{
- if (o == NUMODIR) {
- return "default";
- } else {
- assert(o >= 0 && o < NUMODIR);
- return odir_info[o].name;
- }
-}
-
-#if HAVE_KPATHSEA
-static bool
-file_in_kpathsea_odir(int o, const String &file)
-{
- return odir_kpathsea[o]
- && file.length() > odir[o].length()
- && memcmp(file.data(), odir[o].data(), odir[o].length()) == 0
- && file[odir[o].length()] == '/';
-}
-#endif
-
-void
-update_odir(int o, String file, ErrorHandler *errh)
-{
- assert(o >= 0 && o < NUMODIR);
-#if HAVE_KPATHSEA
- if (file.find_left('/') < 0)
- file = odir[o] + "/" + file;
-
- // exit if this directory was not found via kpathsea, or the file is not
- // in the kpathsea directory
- if (!file_in_kpathsea_odir(o, file))
- return;
-
- assert(writable_texdir && writable_texdir.length() <= odir[o].length()
- && memcmp(file.data(), writable_texdir.data(), writable_texdir.length()) == 0);
-
- // divide the filename into portions
- // file == writable_texdir + directory + file
- file = file.substring(writable_texdir.length());
- while (file && file[0] == '/')
- file = file.substring(1);
- int last_slash = file.find_right('/');
- String directory = (last_slash >= 0 ? file.substring(0, last_slash) : String());
- file = file.substring(last_slash >= 0 ? last_slash + 1 : 0);
- if (!file) // no filename to update
- return;
-
- // return if nocreate
- if (no_create) {
- errh->message("would update %sls-R for %s/%s", writable_texdir.c_str(), directory.c_str(), file.c_str());
- return;
- } else if (verbose)
- errh->message("updating %sls-R for %s/%s", writable_texdir.c_str(), directory.c_str(), file.c_str());
-
- // try to update ls-R ourselves, rather than running mktexupd --
- // mktexupd's runtime is painful: a half second to update a file
- String ls_r = writable_texdir + "ls-R";
- bool success = false;
- if (access(ls_r.c_str(), R_OK) >= 0) // make sure it already exists
- if (FILE *f = fopen(ls_r.c_str(), "ab")) {
- fprintf(f, "./%s:\n%s\n", directory.c_str(), file.c_str());
- success = true;
- fclose(f);
- }
-
- // otherwise, run mktexupd
- if (!success && writable_texdir.find_left('\'') < 0 && directory.find_left('\'') < 0 && file.find_left('\'') < 0) {
- // look for mktexupd script
- if (!mktexupd_tried) {
-#ifdef _WIN32
- mktexupd = "mktexupd.exe";
-#else
- mktexupd = kpsei_string(kpsei_find_file("mktexupd", KPSEI_FMT_WEB2C));
-#endif
- mktexupd_tried = true;
- }
-
- // run script
- if (mktexupd) {
- String command = mktexupd + " " + shell_quote(writable_texdir + directory) + " " + shell_quote(file);
- int retval = system(command.c_str());
- if (retval == 127)
- errh->error("could not run %<%s%>", command.c_str());
- else if (retval < 0)
- errh->error("could not run %<%s%>: %s", command.c_str(), strerror(errno));
- else if (retval != 0)
- errh->error("%<%s%> failed", command.c_str());
- }
- }
-#else
- (void) file, (void) errh;
-#endif
-}
-
-bool
-set_map_file(const String &s)
-{
- bool had = (bool) map_file;
- map_file = s;
- return !had;
-}
-
-String
-installed_type1(const String &otf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh)
-{
- (void) otf_filename, (void) allow_generate, (void) errh;
-
- if (!ps_fontname)
- return String();
-
-#if HAVE_KPATHSEA
-# if HAVE_AUTO_CFFTOT1
- if (!(force && allow_generate && otf_filename && otf_filename != "-" && getodir(O_TYPE1, errh))) {
-# endif
- // look for .pfb and .pfa
- String file, path;
- if ((file = ps_fontname + ".pfb", path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TYPE1)))
- || (file = ps_fontname + ".pfa", path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TYPE1)))) {
- if (path == "./" + file || path == file) {
- if (verbose)
- errh->message("ignoring Type 1 file %s found with kpathsea in %<.%>", path.c_str());
- } else {
- if (verbose)
- errh->message("Type 1 file %s found with kpathsea at %s", file.c_str(), path.c_str());
- return path;
- }
- }
-# if HAVE_AUTO_CFFTOT1
- }
-# endif
-#endif
-
-#if HAVE_AUTO_CFFTOT1
- // if not found, and can generate on the fly, run cfftot1
- if (allow_generate && otf_filename && otf_filename != "-" && getodir(O_TYPE1, errh)) {
- String pfb_filename = odir[O_TYPE1] + "/" + ps_fontname + ".pfb";
- if (pfb_filename.find_left('\'') >= 0 || otf_filename.find_left('\'') >= 0)
- return String();
- String command = "cfftot1 " + shell_quote(otf_filename) + " -n " + shell_quote(ps_fontname) + " " + shell_quote(pfb_filename);
- int retval = mysystem(command.c_str(), errh);
- if (retval == 127)
- errh->error("could not run %<%s%>", command.c_str());
- else if (retval < 0)
- errh->error("could not run %<%s%>: %s", command.c_str(), strerror(errno));
- else if (retval != 0)
- errh->error("%<%s%> failed", command.c_str());
- if (retval == 0) {
- update_odir(O_TYPE1, pfb_filename, errh);
- return pfb_filename;
- }
- }
-#endif
-
- return String();
-}
-
-String
-installed_type1_dotlessj(const String &otf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh)
-{
- (void) otf_filename, (void) allow_generate, (void) errh;
-
- if (!ps_fontname)
- return String();
- if (verbose)
- errh->message("searching for dotless-j font for %s", ps_fontname.c_str());
-
- String j_ps_fontname = ps_fontname + "LCDFJ";
-
-#if HAVE_KPATHSEA
-# if HAVE_AUTO_T1DOTLESSJ
- if (!(force && allow_generate && getodir(O_TYPE1, errh))) {
-# endif
- // look for existing .pfb or .pfa
- String file, path;
- if ((file = j_ps_fontname + ".pfb", path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TYPE1)))
- || (file = j_ps_fontname + ".pfa", path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TYPE1)))) {
- // ignore versions in the current directory
- if (path == "./" + file || path == file) {
- if (verbose)
- errh->message("ignoring Type 1 file %s found with kpathsea in %<.%>", path.c_str());
- } else {
- if (verbose)
- errh->message("Type 1 file %s found with kpathsea at %s", file.c_str(), path.c_str());
- return path;
- }
- }
-# if HAVE_AUTO_T1DOTLESSJ
- }
-# endif
-#endif
-
-#if HAVE_AUTO_T1DOTLESSJ
- // if not found, and can generate on the fly, try running t1dotlessj
- if (allow_generate && getodir(O_TYPE1, errh)) {
- if (String base_filename = installed_type1(otf_filename, ps_fontname, allow_generate, errh)) {
- String pfb_filename = odir[O_TYPE1] + "/" + j_ps_fontname + ".pfb";
- if (pfb_filename.find_left('\'') >= 0 || base_filename.find_left('\'') >= 0)
- return String();
- String command = "t1dotlessj " + shell_quote(base_filename) + " -n " + shell_quote(j_ps_fontname) + " " + shell_quote(pfb_filename);
- int retval = mysystem(command.c_str(), errh);
- if (retval == 127)
- errh->warning("could not run %<%s%>", command.c_str());
- else if (retval < 0)
- errh->warning("could not run %<%s%>: %s", command.c_str(), strerror(errno));
- else if (WEXITSTATUS(retval) == T1DOTLESSJ_EXIT_J_NODOT)
- return String("\0", 1);
- else if (retval != 0)
- errh->warning("%<%s%> failed (%d)", command.c_str(), retval);
- if (retval == 0) {
- update_odir(O_TYPE1, pfb_filename, errh);
- return pfb_filename;
- } else
- errh->warning("output font will not contain a dotless-j character");
- }
- }
-#endif
-
- return String();
-}
-
-String
-installed_truetype(const String &ttf_filename, bool allow_generate, ErrorHandler *errh)
-{
- String file = pathname_filename(ttf_filename);
-
-#if HAVE_KPATHSEA
- if (!(force && allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TRUETYPE, errh))) {
- if (String path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TRUETYPE))) {
- if (path == "./" + file || path == file) {
- if (verbose)
- errh->message("ignoring TrueType file %s found with kpathsea in %<.%>", path.c_str());
- } else {
- if (verbose)
- errh->message("TrueType file %s found with kpathsea at %s", file.c_str(), path.c_str());
- return path;
- }
- }
- }
-#endif
-
- // perhaps generate type 42 in the future, for now just copy
- if (allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TRUETYPE, errh)) {
- String installed_ttf_filename = odir[O_TRUETYPE] + "/" + file;
- if (installed_ttf_filename.find_left('\'') >= 0 || installed_ttf_filename.find_left('\"') >= 0)
- return String();
-
- int retval;
- if (!same_filename(ttf_filename, installed_ttf_filename)) {
- String command = COPY_CMD " " + shell_quote(ttf_filename) + " " + shell_quote(installed_ttf_filename);
- retval = mysystem(command.c_str(), errh);
- if (retval == 127)
- errh->error("could not run %<%s%>", command.c_str());
- else if (retval < 0)
- errh->error("could not run %<%s%>: %s", command.c_str(), strerror(errno));
- else if (retval != 0)
- errh->error("%<%s%> failed", command.c_str());
- } else {
- if (verbose)
- errh->message("TrueType file %s already located in output directory", installed_ttf_filename.c_str());
- retval = 0;
- }
-
- if (retval == 0) {
- update_odir(O_TRUETYPE, installed_ttf_filename, errh);
- return installed_ttf_filename;
- }
- }
-
- return String();
-}
-
-String
-installed_type42(const String &ttf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh)
-{
- (void) allow_generate, (void) ttf_filename, (void) errh;
-
- if (!ps_fontname)
- return String();
-
-#if HAVE_KPATHSEA
-# if HAVE_AUTO_TTFTOTYPE42
- if (!(force && allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TYPE42, errh))) {
-# endif
- // look for .pfb and .pfa
- String file, path;
- if ((file = ps_fontname + ".t42", path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TYPE42)))) {
- if (path == "./" + file || path == file) {
- if (verbose)
- errh->message("ignoring Type 42 file %s found with kpathsea in %<.%>", path.c_str());
- } else {
- if (verbose)
- errh->message("Type 42 file %s found with kpathsea at %s", file.c_str(), path.c_str());
- return path;
- }
- }
-# if HAVE_AUTO_TTFTOTYPE42
- }
-# endif
-#endif
-
-#if HAVE_AUTO_TTFTOTYPE42
- // if not found, and can generate on the fly, run ttftotype42
- if (allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TYPE42, errh)) {
- String t42_filename = odir[O_TYPE42] + "/" + ps_fontname + ".t42";
- if (t42_filename.find_left('\'') >= 0 || ttf_filename.find_left('\'') >= 0)
- return String();
- String command = "ttftotype42 " + shell_quote(ttf_filename) + " " + shell_quote(t42_filename);
- int retval = mysystem(command.c_str(), errh);
- if (retval == 127)
- errh->error("could not run %<%s%>", command.c_str());
- else if (retval < 0)
- errh->error("could not run %<%s%>: %s", command.c_str(), strerror(errno));
- else if (retval != 0)
- errh->error("%<%s%> failed", command.c_str());
- if (retval == 0) {
- update_odir(O_TYPE42, t42_filename, errh);
- return t42_filename;
- }
- }
-#endif
-
- return String();
-}
-
-int
-update_autofont_map(const String &fontname, String mapline, ErrorHandler *errh)
-{
-#if HAVE_KPATHSEA
- if (automatic && !map_file && getodir(O_MAP, errh))
- map_file = odir[O_MAP] + "/" + get_vendor() + ".map";
-#endif
-
- if (map_file == "" || map_file == "-")
- fputs(mapline.c_str(), stdout);
- else {
- // report no_create/verbose
- if (no_create) {
- errh->message("would update %s for %s", map_file.c_str(), String(fontname).c_str());
- return 0;
- } else if (verbose)
- errh->message("updating %s for %s", map_file.c_str(), String(fontname).c_str());
-
- int fd = open(map_file.c_str(), O_RDWR | O_CREAT, 0666);
- if (fd < 0)
- return errh->lerror(map_file, "%s", strerror(errno));
- FILE *f = fdopen(fd, "r+");
- // NB: also change encoding logic if you change this code
-
-#if defined(F_SETLKW) && defined(HAVE_FTRUNCATE)
- {
- struct flock lock;
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
- int result;
- while ((result = fcntl(fd, F_SETLKW, &lock)) < 0 && errno == EINTR)
- /* try again */;
- if (result < 0) {
- result = errno;
- fclose(f);
- return errh->error("locking %s: %s", map_file.c_str(), strerror(result));
- }
- }
-#endif
-
- // read old data from map file
- StringAccum sa;
- int amt;
- do {
- if (char *x = sa.reserve(8192)) {
- amt = fread(x, 1, 8192, f);
- sa.adjust_length(amt);
- } else
- amt = 0;
- } while (amt != 0);
- if (!feof(f))
- return errh->error("%s: %s", map_file.c_str(), strerror(errno));
- String text = sa.take_string();
-
- // add comment if necessary
- bool created = (!text);
- if (created)
- text = "% Automatically maintained by otftotfm or other programs. Do not edit.\n\n";
- if (text.back() != '\n')
- text += "\n";
-
- // append old encodings
- int fl = 0;
- int nl = text.find_left('\n') + 1;
- bool changed = created;
- while (fl < text.length()) {
- if (fl + fontname.length() + 1 < nl
- && memcmp(text.data() + fl, fontname.data(), fontname.length()) == 0
- && text[fl + fontname.length()] == ' ') {
- // found the old name
- if (text.substring(fl, nl - fl) == mapline) {
- // duplicate of old name, don't change it
- fclose(f);
- if (verbose)
- errh->message("%s unchanged", map_file.c_str());
- return 0;
- } else {
- text = text.substring(0, fl) + text.substring(nl);
- nl = fl;
- changed = true;
- }
- }
- fl = nl;
- nl = text.find_left('\n', fl) + 1;
- }
-
- if (!mapline && !changed) {
- // special case: empty mapline, unchanged file
- if (verbose)
- errh->message("%s unchanged", map_file.c_str());
- } else {
- // add our text
- text += mapline;
-
- // rewind file
-#if HAVE_FTRUNCATE
- rewind(f);
- if (ftruncate(fd, 0) < 0)
-#endif
- {
- fclose(f);
- f = fopen(map_file.c_str(), "wb");
- fd = fileno(f);
- }
-
- // write data
- ignore_result(fwrite(text.data(), 1, text.length(), f));
- }
-
- fclose(f);
-
- // inform about the new file if necessary
- if (created)
- update_odir(O_MAP, map_file, errh);
-
-#if HAVE_KPATHSEA && !WIN32
- // run 'updmap' if present
- String updmap_prog = output_flags & G_UPDMAP_USER ? "updmap-user" : "updmap-sys";
- String updmap_dir, updmap_file;
- if (automatic && (output_flags & G_UPDMAP))
- updmap_dir = getodir(O_MAP_PARENT, errh);
- if (updmap_dir
- && (updmap_file = updmap_dir + "/" + updmap_prog)
- && access(updmap_file.c_str(), X_OK) >= 0) {
- // want to run `updmap` from its directory, can't use system()
- if (verbose)
- errh->message("running %s", updmap_file.c_str());
-
- pid_t child = fork();
- if (child < 0)
- errh->fatal("%s during fork", strerror(errno));
- else if (child == 0) {
- // change to updmap directory, run it
- if (chdir(updmap_dir.c_str()) < 0)
- errh->fatal("%s: %s during chdir", updmap_dir.c_str(), strerror(errno));
- if (execl(output_flags & G_UPDMAP_USER ? "./updmap-user" : "./updmap-sys",
- updmap_file.c_str(),
- (const char*) 0) < 0)
- errh->fatal("%s: %s during exec", updmap_file.c_str(), strerror(errno));
- exit(1); // should never get here
- }
-
-# if HAVE_WAITPID
- // wait for updmap to finish
- int status;
- while (1) {
- pid_t answer = waitpid(child, &status, 0);
- if (answer >= 0)
- break;
- else if (errno != EINTR)
- errh->fatal("%s during wait", strerror(errno));
- }
- if (!WIFEXITED(status))
- errh->warning("%s exited abnormally", updmap_file.c_str());
- else if (WEXITSTATUS(status) != 0)
- errh->warning("%s exited with status %d", updmap_file.c_str(), WEXITSTATUS(status));
-# else
-# error "need waitpid() support: report this bug to the maintainer"
-# endif
- goto ran_updmap;
- }
-
-# if HAVE_AUTO_UPDMAP
- // run system updmap
- if (output_flags & G_UPDMAP) {
- String filename = map_file;
- int slash = filename.find_right('/');
- if (slash >= 0)
- filename = filename.substring(slash + 1);
- String redirect = verbose ? " 1>&2" : " >" DEV_NULL " 2>&1";
- String command = updmap_prog + " --nomkmap --enable Map " + shell_quote(filename) + redirect
- + CMD_SEP " " + updmap_prog + redirect;
- int retval = mysystem(command.c_str(), errh);
- if (retval == 127)
- errh->warning("could not run %<%s%>", command.c_str());
- else if (retval < 0)
- errh->warning("could not run %<%s%>: %s", command.c_str(), strerror(errno));
- else if (retval != 0)
- errh->warning("%<%s%> exited with status %d;\nrun it manually to check for errors", command.c_str(), WEXITSTATUS(retval));
- goto ran_updmap;
- }
-# endif
-
- if (verbose)
- errh->message("not running updmap");
-
- ran_updmap: ;
-#endif
- }
-
- return 0;
-}
-
-String
-locate_encoding(String encfile, ErrorHandler *errh, bool literal)
-{
- if (!encfile || encfile == "-")
- return encfile;
-
- if (!literal) {
- int slash = encfile.find_right('/');
- int dot = encfile.find_left('.', slash >= 0 ? slash : 0);
- if (dot < 0)
- if (String file = locate_encoding(encfile + ".enc", errh, true))
- return file;
- }
-
-#if HAVE_KPATHSEA
- if (String file = kpsei_string(kpsei_find_file(encfile.c_str(), KPSEI_FMT_ENCODING))) {
- if (verbose)
- errh->message("encoding file %s found with kpathsea at %s", encfile.c_str(), file.c_str());
- return file;
- } else if (verbose)
- errh->message("encoding file %s not found with kpathsea", encfile.c_str());
-#endif
-
- if (access(encfile.c_str(), R_OK) >= 0)
- return encfile;
- else
- return String();
-}