TeX 系统的演变 (转载)

Leon posted @ 2007年8月26日 06:18 in Latex with tags latex , 1510 阅读

TeX 系统的演变 (转载)

lyanry posted @ 2007年08月25日 10:21AM in 文档标记语言 with tags web2c tex

原文见王越的 google pages,本文仅将其原有繁体中文转换为简体,把原文中的英文标点转换为中文标点,原文中一些词句,我认为有错误,就对其进行修订。

当年,高爷爷发现出版社将他的巨著 TAOCP 排版得乱七八糟,因此,立志编写出一套计算机排版系统,来发挥计算机排印的潜能。这套系统,就被他称作为 TeX。如今,TeX 已经在全世界得到广泛的应用,和高爷爷高超的技术是分不开的。

TeX 系统的思想,起源于高爷爷在斯坦福大学的一个叫做文学编程的试验。所谓文学编程,和今天的 python 编程类似,也就是说,编写程序和编写文档是一个统一的过程,编写完的程序,通过编译器,就能够被编译执行;同时,如果通过一个文本生成程序,就能够得到该 程序的技术资料。

TeX就是在这种环境下,被高爷爷弄出来的。而这种编程思想,就是体现在一种叫做 WEB 的语言上。WEB 语言的特别之处,就是当 WEB 文件通过不同的命令,就能够生成不同的东西。经过几年的发展,WEB 语言成型,同时 TEX 系统成型。

WEB 语言究竟是什么东西?事实上,就是一个 WEB 文件同时包含了 TEX 文档和 Pascal 语言,当 WEB 文件被 tangle 命令处理的时候,我们就得到了一个 pascal 语言文件,这个文件,可以直接被 pascal 编译器编译后执行。而对 WEB 文件使用 weave 命令进行处理,可得到 TeX 文档,这个文档由 tex 命令处理后,生成 dvi 文件,可用于打印。

TeX 系统,就是用这么一个 WEB 语言写就的,如果您对于这个怎么互相循环感到奇怪,那您不妨想象 C 语言编译器也是用 C 语言写就的。这是一个循序渐进、不断添加新指令的过程。

当今的 TeX 系统,事实上就是一个 web 文件,这个文件可是高爷爷亲手编写的,当你得到这个文件以后,对其执行 tangle 命令,你就可以得到一个叫做 tex.p 的文档,对这个文档,使用 pascal 编译器进行编译,就得到了一个 TeX 系统。而 web 文件由 weave 命令处理后,可得到一个 tex 文件,当你运行 tex 来编译这个文件的时候,你得到的是讲述 TeX 系统所有实现的文档。

整个 TeX 系统共有 300 个基本指令。使用这些指令,我们可以排版任何文档。当然,由于这些指令比较底层,用起来比较复杂,于是我们的高爷爷又基于这些指令,添加了 600 个指令,这就是我们今天的 TeX 系统。详细的指令用法,高爷爷都写到了他的 The TeXbook 中,这个可是他的一笔重要收入。

Pascal 语言是学院派的典范 (我承认最典范的学院派语言是 scheme),但是在实际生产中,pascal 语言自然就不能胜任了。20 世纪 80 年代随着苹果机的流行,使得 pascal 语言被很广泛地使用,以至于苹果公司需要把其他语言写的程序改成 pascal 代码,再在苹果机中运行。但是在 20 世纪 90 年代,网络迅速发展,导致 Unix 系统的需求迅速扩大,C 语言开始登上编程舞台,pascal 就不再吃香了。一大群学校纷纷改授 C 语言,同时 C 语言编译器的进步也异常迅猛,此时的大型应用也大都使用 C 语言编写。TeX 作为最牛 B 的排版软件,自然也应当使用 C 语言咯。因此,需要把 WEB 代码中的 pascal 换成 C 代码的想法付出水面,实现这个想法的的 WEB 系统就叫做 WEB2C。

事实上,这个是一个不得已的决定,由于大家对于高爷爷期望很高,一直认为他会不断地修改 TeX 系统,使之变得更加强大,因此本来一些手动地把 WEB 语言改变到 C 语言的计划,比如 Common TeX ,都无法成功,因为这使得 C 代码无法和高爷爷的 WEB 代码同时修正发布。因此只能够选择由机器自动地转码。而不幸的是,后来高爷爷认为 TeX 不需要再做任何修改了,当然这个是后话。 WEB2C 就在这种被动的想法下面被提出来了。

WEB2C 事实上就是 Lex 和 Yacc 写的一个语法转换器,尝试把 pascal 语言转换到 C 语言。中途会经历各种恶心的过程,当 pascal 语言变到了 C 语言以后,一群计算机专家们就很高兴地能够 make 它们,在浪费办公室电费和打法自己的时间中享受独特的乐趣。事实上这个也是一个无奈的决定。因为转好的代码,基本上不能用肉眼进行分析。

不管怎么样,我们的 WEB 语言终于到 C 语言了。接下来,由于 TeX 太伟大,所以,有了很多的基于 TeX 的包,包括字体,有用的宏。因此,我们的目录结构变得越来越复杂,如果当年的高爷爷乘坐时光机器看看今天的 TDS,一定会使他大开眼界。同时,网络的发展,导致可能本机器上的 TeX 需要搜索其他机器上的文件。这个就导致了一个严重的问题,就是 TeX 需要在许多的目录中找文件,需要耗费非常长的时间,而且如果一到网络上查找文件,速度还要降得更加慢。

因此,我们需要改动原先仅仅在当前目录或者由用户声名路径的目录下面找文件的架构。而此时的问题是,不能在 TeX 上面改,因为 metapost 等诸多的 TeX 相关软件也需要找文件,在 TeX 中实现一次再在 metapost 中实现一次,是一个错误的决定。因此,TUG 的 Karl 老大有了一个办法。首先开发了一个库,叫做 kpathsea,然后让 TeX 和它的相关软体,通过 kpathsea 查找文件。而查找文件的数量庞大导致的速度慢,就采用数据库的方法解决。先查找一次,记录下来,以后慢慢享用。这个数据库,就是 ls-R。

最早的 WEB2C 的查找方案,就是定义了一个叫做 TEXINPUTS 的环境变量,告诉 kpathsea 在TEXINPUTS 所定义的环境下,找到文件。但是这个导致了一个新的问题,也就是不同的 TeX 需要寻找不同的东西,而一个 TEXINPUTS 无法把它们区分开来。因此,我们这才想到,应该使用不同的路径,比如,TEXINPUTS.latex 变量,来给 LaTeX 查找路径,TEXINPUTS.context 变量给 ConTeXt 查找。而这些变量,就定义在 texmf.cnf 当中。

这个文件,还定义了许多的 TeX 的目录树,比如 texmf 目录,可以给整套的 TeX 系统查;texmf.os,可以给特性的系统查。当我们的系统添加了什么新的东西,就放在 texmf-local 吧。而用户自己的东西,嗯,规定他们在$HOME/texmf。

还有最后一个问题,那就是 kpathsea 如何查找 texmf.cnf 呢?事实上是通过定义环境变量达到目的的。这个变量叫做 TEXMFCNF,所有在这个环境变量中的 texmf.cnf 都被搜索到。这也使得,用户可以自己写一个 texmf.cnf,把所在路径加入到自己的 TEXMFCNF,而不需要重写整个 texmf.cnf。如果这个变量没有定义,那么默认我们找 texmf/web2c 这个路径下的 texmf.cnf。

整个 TeX 系统的实现过程到目前的科技发展水平为止,就是这个样子,说不定过了几年 C 语言不再吃香,因此搞出一个 web2python。又过了几年 pascal 复苏,大家又重新使用 WEB 语言写东西,或者过了几年网络和硬盘速度足够快,我们扔掉了 kpathsea。这些事情或许都会发生,谁也不知道。

但是这一切的被动,都是由于高爷爷大师光环的光芒,使得 tex.web 这个文件成为永恒。 1990 年 TeX 系统发布了 3.1 版本,高爷爷兴奋地表示, tex.web 是一个好东西,没有 bug,我们不要再改动 tex.web 了,大家一定要改,那我也没办法,但是不要和我争哦,一定要改名。 TeX 在 20 世纪 80 年代末虽然做了一次大的改动,可以处理 8 位的字符,而Unix Plan 9 系统的发布,奠定了 Unicode 编码方案的基础。 TeX 在目前的情况下,是落后于整个时代的。

如今,TeX 在多国语言的支持上,始终处于半吊子的状态,需要一大批黑客们日夜 hack 才可以被更多的场合支持。 TeX 使用的字体、输出,也受到时代的局限。 TeX 所用到的各种字体文件的庞杂程度,可能一个熟悉这个系统的人也不能完全讲明白。而同时发展起来的 X Window 系统,却对当今流行的字体和当今的字体渲染技术,拿捏非常到位。

显然,我们本来可以修改而使得 TeX 变得更好,但是高爷爷大师形象的光芒,使得各种尝试 (pdftex, etex, xetex, luatex,omega,aleph, ant, etc.),都不能算是正统。一方面,由于没有现成的由手工转换得到的 C 代码,修改 TeX 并不简单。许多的新 TeX 实现,都是给高爷爷的 tex.web 加上一串的 ch 和 fix 文件,这就使得他们严重地依赖原本的 TeX,使之变得异常复杂,好比于 C++ 对于 C 的扩充。另一方面,这些诸多的新时期的 TeX 实现,种类繁多,虽然大多数对于老的 TeX 的功能都尽量做到不变,但是新添加的功能,却导致彼此的不兼容。我们都不知道,更加漂亮的 TeX 架构,路在何方。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter