add: else sa << " <<" << pathname_filename(input_filename);
context: do_file(const String &input_filename, const OpenType::Font &otf,	const DvipsEncoding &dvipsenc_in, bool dvipsenc_literal,	ErrorHandler *errh){    // get font    Cff cff(otf.table("CFF"), errh);    if (!cff.ok())	return;    Cff::Font font(&cff, PermString(), errh);    if (!font.ok())	return;    // save glyph names    Vector<PermString> glyph_names;    font.glyph_names(glyph_names);    OpenType::debug_glyph_names = glyph_names;    // set typeface name from font family name    {	String typeface = font.dict_string(Cff::oFamilyName);	// make it reasonable for the shell	StringAccum sa;	for (int i = 0; i < typeface.length(); i++)	    if (isalnum(typeface[i]) || typeface[i] == '_' || typeface[i] == '-' || typeface[i] == '.' || typeface[i] == ',' || typeface[i] == '+')		sa << typeface[i];	set_typeface(sa.length() ? sa.take_string() : font_name, false);    }    // initialize encoding    DvipsEncoding dvipsenc(dvipsenc_in); // make copy    Metrics encoding(font.nglyphs());    OpenType::Cmap cmap(otf.table("cmap"), errh);    assert(cmap.ok());    if (dvipsenc_literal)	dvipsenc.make_literal_metrics(encoding, &font);    else {	T1Secondary secondary(&font, cmap);	dvipsenc.make_metrics(encoding, cmap, &font, &secondary);    }    // encode boundary glyph at 256    encoding.encode(256, encoding.boundary_glyph());        // maintain statistics about features    HashMap<uint32_t, int> feature_usage(0);        // apply activated GSUB features    OpenType::Gsub gsub(otf.table("GSUB"), errh);    Vector<Lookup> lookups(gsub.nlookups(), Lookup());    find_lookups(gsub.script_list(), gsub.feature_list(), lookups, errh);    Vector<OpenType::Substitution> subs;    for (int i = 0; i < lookups.size(); i++)	if (lookups[i].used) {	    OpenType::GsubLookup l = gsub.lookup(i);	    subs.clear();	    bool understood = l.unparse_automatics(gsub, subs);	    // check for -ffina, which should apply only at the ends of words,	    // and -finit, which should apply only at the beginnings.	    OpenType::Tag feature = (lookups[i].features.size() == 1 ? lookups[i].features[0] : OpenType::Tag());	    if (feature == OpenType::Tag("fina") || feature == OpenType::Tag("fin2") || feature == OpenType::Tag("fin3")) {		if (dvipsenc.boundary_char() < 0)		    errh->warning("'-ffina' requires a boundary character\n(The input encoding didn't specify a boundary character, but\nI need one to implement '-ffina' features correctly. Add one\nwith a \"%% LIGKERN || = <slot> ;\" command in the encoding.)");		else {		    int bg = encoding.boundary_glyph();		    for (int j = 0; j < subs.size(); j++)			subs[j].add_outer_right(bg);		}	    } else if (feature == OpenType::Tag("init")) {		int bg = encoding.boundary_glyph();		for (int j = 0; j < subs.size(); j++)		    subs[j].add_outer_left(bg);	    }	    //for (int subno = 0; subno < subs.size(); subno++) fprintf(stderr, "%5d\t%s\n", i, subs[subno].unparse().c_str());	    	    int nunderstood = encoding.apply(subs, !dvipsenc_literal, i);	    // mark as used	    int d = (understood && nunderstood == subs.size() ? F_GSUB_ALL : (nunderstood ? F_GSUB_PART : 0)) + F_GSUB_TRY;	    for (int j = 0; j < lookups[i].features.size(); j++)		feature_usage.find_force(lookups[i].features[j].value()) |= d;	}    // apply LIGKERN ligature commands to the result    dvipsenc.apply_ligkern_lig(encoding, errh);    // test fake ligature mechanism    //encoding.add_threeligature('T', 'h', 'e', '0');        // reencode characters to fit within 8 bytes (+ 1 for the boundary)    if (!dvipsenc_literal)	encoding.shrink_encoding(257, dvipsenc_in, errh);        // apply activated GPOS features    OpenType::Gpos gpos(otf.table("GPOS"), errh);    lookups.assign(gpos.nlookups(), Lookup());    find_lookups(gpos.script_list(), gpos.feature_list(), lookups, errh);    Vector<OpenType::Positioning> poss;    for (int i = 0; i < lookups.size(); i++)	if (lookups[i].used) {	    OpenType::GposLookup l = gpos.lookup(i);	    poss.clear();	    bool understood = l.unparse_automatics(poss);	    int nunderstood = encoding.apply(poss);	    // mark as used	    int d = (understood && nunderstood == poss.size() ? F_GPOS_ALL : (nunderstood ? F_GPOS_PART : 0)) + F_GPOS_TRY;	    for (int j = 0; j < lookups[i].features.size(); j++)		feature_usage.find_force(lookups[i].features[j].value()) |= d;	}    // apply LIGKERN kerning commands to the result    dvipsenc.apply_ligkern_kern(encoding, errh);    // remove extra characters    encoding.cut_encoding(257);    //encoding.unparse();    // apply letterspacing, if any    if (letterspace) {	for (int code = 0; code < 256; code++) {	    int g = encoding.glyph(code);	    if (g != 0 && g != Metrics::VIRTUAL_GLYPH && code != dvipsenc.boundary_char()) {		encoding.add_single_positioning(code, letterspace / 2, 0, letterspace);		encoding.add_kern(code, 256, -letterspace / 2);		encoding.add_kern(256, code, -letterspace / 2);	    }	}    }    // reencode right components of boundary_glyph as boundary_char    int boundary_char = dvipsenc.boundary_char();    if (encoding.reencode_right_ligkern(256, boundary_char) > 0	&& boundary_char < 0)	errh->warning("no boundary character, removed some ligatures and/or kerns\n(You may want to try the --boundary-char option.)");    // report unused and underused features if any    report_underused_features(feature_usage, errh);    // figure out our FONTNAME    if (!font_name) {	// derive font name from OpenType font name	font_name = font.font_name();	if (encoding_file) {	    int slash = encoding_file.find_right('/') + 1;	    int dot = encoding_file.find_right('.');	    if (dot < slash)	// includes dot < 0 case		dot = encoding_file.length();	    font_name += String("--") + encoding_file.substring(slash, dot - slash);	}	if (interesting_scripts.size() != 2 || interesting_scripts[0] != OpenType::Tag("latn") || interesting_scripts[1].valid())	    for (int i = 0; i < interesting_scripts.size(); i += 2) {		font_name += String("--S") + interesting_scripts[i].text();		if (interesting_scripts[i+1].valid())		    font_name += String(".") + interesting_scripts[i+1].text();	    }	for (int i = 0; i < interesting_features.size(); i++)	    if (feature_usage[interesting_features[i].value()])		font_name += String("--F") + interesting_features[i].text();    }        // output encoding    if (dvipsenc_literal) {	out_encoding_name = dvipsenc_in.name();	out_encoding_file = dvipsenc_in.filename();    } else	output_encoding(encoding, glyph_names, errh);    // check whether virtual metrics are necessary    String metrics_suffix;    bool need_virtual = encoding.need_virtual(257);    if (need_virtual) {	if (output_flags & G_VMETRICS)	    metrics_suffix = "--base";	else	    errh->warning("features require virtual fonts");    }        // output virtual metrics    if (!(output_flags & G_VMETRICS))	/* do nothing */;    else if (!need_virtual) {	if (automatic) {	    // erase old virtual font	    String vf = getodir(O_VF, errh) + "/" + font_name + ".vf";	    if (verbose)		errh->message("removing potential VF file '%s'", vf.c_str());	    if (unlink(vf.c_str()) < 0 && errno != ENOENT)		errh->error("removing %s: %s", vf.c_str(), strerror(errno));	}    } else {	if (output_flags & G_BINARY) {	    String tfm = getodir(O_TFM, errh) + "/" + font_name + ".tfm";	    String vf = getodir(O_VF, errh) + "/" + font_name + ".vf";	    write_tfm(&font, cmap, encoding, dvipsenc.boundary_char(), glyph_names, tfm, vf, errh);	} else {	    String outfile = getodir(O_VPL, errh) + "/" + font_name + ".vpl";	    output_pl(&font, cmap, encoding, dvipsenc.boundary_char(), glyph_names, true, outfile, errh);	    update_odir(O_VPL, outfile, errh);	}	encoding.make_base(257);    }    // output metrics    if (!(output_flags & G_METRICS))	/* do nothing */;    else if (output_flags & G_BINARY) {	String tfm = getodir(O_TFM, errh) + "/" + font_name + metrics_suffix + ".tfm";	write_tfm(&font, cmap, encoding, dvipsenc.boundary_char(), glyph_names, tfm, String(), errh);    } else {	String outfile = getodir(O_PL, errh) + "/" + font_name + metrics_suffix + ".pl";	output_pl(&font, cmap, encoding, dvipsenc.boundary_char(), glyph_names, false, outfile, errh);	update_odir(O_PL, outfile, errh);    }    // print DVIPS map line    if (errh->nerrors() == 0 && (output_flags & G_PSFONTSMAP)) {	StringAccum sa;	sa << font_name << metrics_suffix << ' ' << font.font_name() << " \"";	if (extend)	    sa << extend << " ExtendFont ";	if (slant)	    sa << slant << " SlantFont ";	sa << out_encoding_name << " ReEncodeFont\" <[" << pathname_filename(out_encoding_file);	if (String fn = installed_type1(input_filename, font.font_name(), (output_flags & G_TYPE1), errh))	    sa << " <" << pathname_filename(fn);	sa << '\n';	update_autofont_map(font_name + metrics_suffix, sa.take_string(), errh);	// if virtual font, remove any map line for base font name	if (metrics_suffix)	    update_autofont_map(font_name, "", errh);    }}