Follow-up Comment #9, bug #61423 (project groff): This ticket appears to have turned over a very old rock with some very ugly creatures living beneath it.
It appears that the argument to the `name` directive isn't necessarily a file name. It's an "external name". Both CSTR #54 and existing _groff_ documentation are pretty vague about what that _means_. CSTR #54, on the `fp` request: > This is a statement that a font named _F_ is associated with position _N_. It is a fatal error if _F_ is not known. For fonts with names longer than two characters, _L_ refers to the long name, and _F_ becomes a synonym. (I note as an aside that _groff_ does not treat the foregoing failure mode as a _fatal_ error, nor in my opinion should it.) Regarding the font description file itself, CSTR #54 is hopelessly circular. > name _str_ <tab> name of font is _str_ Wow, thanks. _groff_'s own Texinfo manual says this: The 'fp' request has an optional third argument. This argument gives the external name of the font, which is used for finding the font description file. The second argument gives the internal name of the font, which is used to refer to the font in 'gtroff' after it has been mounted. If there is no third argument then the internal name is used as the external name. This feature makes it possible to use fonts with long names in compatibility mode. If the above were completely true, then there would be no reason for font description files to have an `internalname` directive; a font's internal name would be completely document-dependent. Indeed, I can say: .fp 5 Normal R .fp 6 Slanted I .fp 7 Heavy B .fp 8 Emphatic BI .ft Normal Hello, Joe. What .ft Slanted do .ft Heavy you .ft Emphatic know? And it works as you would expect in groff 1.22.4 and Git HEAD. (Hooray, something I didn't regress.) But if a font's internal name is document-dependent, what are we to make of `internalname` as used (only) by grodvi, grops, and grotty? It seems like we're using the highly specific jargon "internal[ ]name" to mean two completely different things. One is a within-document alias for a font name (or for a font mounting position, for that matter, which is what a font name already is); the other is a driver-specific tag used only for communications between _groff_ objects of the class `font` and the output drivers. I note that the member function `font::get_internal_name`, which refers _only_ to this latter concept, has _no_ call sites outside of specific output drivers. $ git grep get_internal_name src/devices/grodvi/dvi.cpp: const char *nm = f->get_internal_name(); src/devices/grops/ps.cpp: .put_literal_symbol(f->get_internal_name()) src/devices/grops/ps.cpp: const char *psname = sty.f->get_internal_name(); src/devices/grops/ps.cpp: rm.need_font(psf->get_internal_name()); src/devices/grops/ps.cpp: .put_literal_symbol(tem->p->get_internal_name()) src/devices/grotty/tty.cpp: const char *num = f->get_internal_name(); src/include/font.h: const char *get_internal_name(); // Return the 'internalname' src/include/font.h: // a null pointer. Used by get_internal_name(). src/libs/libgroff/font.cpp:const char *font::get_internal_name() This member function accesses a member variable called `internalname`. *These member names are very confusing*. They have to do _only_ with the device-specific internal name. The `internalname` member variable is never read by any code elsewhere in libgroff; its accessor member function is called _only_ by output drivers. For grodvi, it's supposed to refer to the name of the corresponding TFM file. For grotty, it's a bit mask, for Christ's sake. I think we have a choice ahead of us: 1. Validate the font description file's `name` directive upon attempted load against the "internal name" (note the space), the mandatory 2nd argument to `fp`. If we do this, slashes are indeed prohibited. it will also serve to verify that this internal name is obviously related to the name of the font description file on the file system. This "internal name" (mind the gap) is what is referred to as `name` in the `font` class, and it is what is ultimately passed to `font::open_file` in fontfile.cpp <https://git.savannah.gnu.org/cgit/groff.git/tree/src/libs/libgroff/fontfile.cpp#n61>. (One might reasonably ask why this `name` (really, `nm`) is being passed to `open_file` when `name` is a member variable of an object of the very class whose member function this is. Why do we pass it when we should already know it? The answer is that an object of class `font` is not completely initialized until the font description file has been read, and that hasn't happened yet before the file has been opened. In fact, there's a lot of validation that has to happen before a font object can be assumed valid. It is my recent addition of more such validation that prompted Dave to file this ticket.) But maybe no one actually needs validation of this sort. If they `cp A B` inside a font directory, maybe we shouldn't stop them from loading the font description file `B` without changes. 2. Another possibility is to validate the value of the `name` directive against the external name supplied to the `fp` request. Since that external name is an optional argument, the validation would only be performed if it were present. Assuming that a disciplined name space grew up around external font names in the groff ecosystem, documents and macro packages could then use the `fp` request to ensure that they're getting exactly the fonts they wanted. (A discipline of syncing this external name and `name` directive contents with _actual_ font files, like version x.y.z of font FooBar from Foundry BigCorp, is a necessary but independent prerequisite for this benefit to be realized.) One of the things TeX touts about itself is its core principle of never regressing the renderability of anything. Knuth and his descendants took this principle so seriously that they leveraged the file system as a registry and wrote filename invariance into their software licenses, eventually leading to tension <https://www.researchgate.net/publication/236552996_Reflections_on_the_history_of_the_LaTeX_Project_Public_License_LPPL_---_A_software_license_for_LaTeX_and_more> with the Free Software movement's equally deep dedication to the principles of modularity and interchangeability. The file system was used as a registry because it was guaranteed to be there (in a rare move, Knuth kept his yak-shaving clippers <https://yakshav.es/the-patron-saint-of-yakshaves/> in his pocket). I disagree with that choice but sympathize with the motives behind it. _groff_ could do worse than to offer one, for fonts, via this mechanism. For an example of how _not_ to do a font registry in a way that humans want to deal with, see X (Window System) logical font descriptions <https://en.wikipedia.org/wiki/X_logical_font_description>. I think option #2 would be more in line with what Dave was already doing. Another independent but important issue in my view is to deprecate that driver-specific `internalname` member variable as soon as possible in favor of some other name. The design of the font description file format suggests that a driver could pick any usefully descriptive name it wanted, however I don't think libgroff offers the font description as a general key/value store. This `FONT_COMMAND_HANDLER` business <https://git.savannah.gnu.org/cgit/groff.git/tree/src/libs/libgroff/font.cpp#n1283> appears to be the correct the mechanism, so that output drivers would extend the class and supply their own member functions, and grodvi, grolbp, grolj4, and grops all seem to have done so for other directive names. But this wasn't done for `internalname`. For some reason, the `internalname` member variable became an ersatz union--in other words, a junk box. In the short term I propose to rename the `internalname` and `get_internal_name` members of `font` to something else--almost _anything else_, even arrant nonsense, like "mxyzptlk", would be an improvement because at least then it would be impossible to infer identity with the other, much higher-profile, thing groff calls an "internal name". For compatibility with old font files, recognition of the `internalname` directive name would have to be retained. But we can use the new name going forward. Right now I don't have a better idea for a new name than "disambiguator" or "classifier", which are pretty weak...I challenge the reader to come up with a term that can encompass grodvi, grops, and grotty's usages (TFM file name, PostScript font name, bit mask). In the longer term, I guess the `FONT_COMMAND_HANDLER` thing should actually be exercised on the output driver side of things as seems to have been originally intended. Then the `font` class wouldn't need the `get_internal_name` member function at all. A lot of this comment will need to be copied to a Savannah ticket, but I wanted to get this down while the result of my investigations was fresh in my head. The scope of _this_ ticket remains deciding between the 2 options above in `fp` request handling. Whew. I think I'm going to pour myself a drink. _______________________________________________________ Reply to this item at: <https://savannah.gnu.org/bugs/?61423> _______________________________________________ Message sent via Savannah https://savannah.gnu.org/
