diff options
author | Ulrich Drepper <drepper@cygnus.com> | 2000-06-16 07:49:23 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@cygnus.com> | 2000-06-16 07:49:23 +0000 |
commit | 60d2084de5dc3b65e6657f695f0f26df24b0f565 (patch) | |
tree | 224f21c30351570d6d7f06a385e829d5ab320f67 /doc | |
download | external_gettext-60d2084de5dc3b65e6657f695f0f26df24b0f565.zip external_gettext-60d2084de5dc3b65e6657f695f0f26df24b0f565.tar.gz external_gettext-60d2084de5dc3b65e6657f695f0f26df24b0f565.tar.bz2 |
Initial revision
Diffstat (limited to 'doc')
-rw-r--r-- | doc/Admin/documentation | 1692 | ||||
-rw-r--r-- | doc/Admin/solaris.msgfmt | 21 | ||||
-rw-r--r-- | doc/ChangeLog | 426 | ||||
-rw-r--r-- | doc/ISO_639 | 180 | ||||
-rw-r--r-- | doc/Makefile.am | 32 | ||||
-rw-r--r-- | doc/Makefile.in | 370 | ||||
-rw-r--r-- | doc/gettext.info | 126 | ||||
-rw-r--r-- | doc/gettext.info-1 | 999 | ||||
-rw-r--r-- | doc/gettext.info-2 | 1127 | ||||
-rw-r--r-- | doc/gettext.info-3 | 1072 | ||||
-rw-r--r-- | doc/gettext.info-4 | 1110 | ||||
-rw-r--r-- | doc/gettext.info-5 | 852 | ||||
-rw-r--r-- | doc/gettext.texi | 4820 | ||||
-rw-r--r-- | doc/iso-apdx.sed | 19 | ||||
-rw-r--r-- | doc/iso-apdx.texi | 278 | ||||
-rw-r--r-- | doc/matrix.texi | 75 | ||||
-rwxr-xr-x | doc/mdate-sh | 92 | ||||
-rw-r--r-- | doc/nls.texi | 254 | ||||
-rw-r--r-- | doc/texinfo.tex | 5302 | ||||
-rw-r--r-- | doc/version.texi | 3 |
20 files changed, 18850 insertions, 0 deletions
diff --git a/doc/Admin/documentation b/doc/Admin/documentation new file mode 100644 index 0000000..beb1d47 --- /dev/null +++ b/doc/Admin/documentation @@ -0,0 +1,1692 @@ +BABYL OPTIONS: -*- rmail -*- +Version: 5 +Labels: +Note: This is the header of an rmail file. +Note: If you are seeing it in rmail, +Note: it means the file has no messages in it. + +1, edited,, +From: terrell@druhi.ATT.COM (TerrellE) +Newsgroups: comp.sys.ibm.pc,sci.astro +Subject: Internationalization of Software? +Date: 30 Jun 89 19:05:23 GMT +Reply-To: terrell@druhi.ATT.COM (TerrellE) +Organization: AT&T, Denver, CO + +*** EOOH *** +From: terrell@druhi.ATT.COM (TerrellE) +Newsgroups: comp.sys.ibm.pc,sci.astro +Subject: Internationalization of Software? +Date: 30 Jun 89 19:05:23 GMT +Reply-To: terrell@druhi.ATT.COM (TerrellE) + +I know that there are some modifications that I will have to perform to +"internationalize" software products developed for use in the USA. +These changes include the obvious (translate the program +and documentation into the right language). However, some of the +other changes are more subtle. I'm sure that I've overlooked some, but +here's what I have so far: + +Necessary changes to "internationalize" a software product: + +1. Flexible date format: + + dd/mm/yy + yy/dd/mm + yy/mm/dd + mm/dd/yy + +2. Handle foreign daylight savings time. + +3. Flexible radix (decimal) point (i.e. '.' or ','): + + 3.14159 + 3,14159 + +4. Allow English or Metric units. + +5. Use "one thousand million" rather than "one billion". + +6. Flexible time format: + + hh:mm + hh.mm + hh'mm + +7. Allow either ' ' or ',' for thousands delimiters: + + 1,000,000 + 1 000 000 + + +What else is necessary? Overseas users: what changes would you make +to your "US Version" software to make it approprate for use in other +countries? + +I'll post a summary of the results. Thanks in advance, + + + +Eric Terrell (att!druhi!terrell) + +1,, +Xref: IRO.UMontreal.CA comp.std.c:13991 comp.software.international:607 +Path: IRO.UMontreal.CA!CC.UMontreal.CA!newsflash.concordia.ca!utcsri!utnut!cs.utexas.edu!howland.reston.ans.net!nctuccca.edu.tw!news.cc.nctu.edu.tw!mall!ywliu +From: ywliu@beta.wsl.sinica.edu.tw () +Newsgroups: comp.std.c,comp.software.international +Subject: Re: ANSI C Locale Character Sets +Followup-To: comp.std.c,comp.software.international +Date: 3 Oct 1994 06:39:25 GMT +Organization: Computing Center, Academia Sinica +Lines: 26 +Message-ID: <36o8ut$afu@mall.sinica.edu.tw> +References: <Cx0Mpy.7Lo@actrix.gen.nz> +NNTP-Posting-Host: ywliu%@beta.wsl.sinica.edu.tw +X-Newsreader: TIN [version 1.2 PL0] + +*** EOOH *** +From: ywliu@beta.wsl.sinica.edu.tw () +Newsgroups: comp.std.c,comp.software.international +Subject: Re: ANSI C Locale Character Sets +Followup-To: comp.std.c,comp.software.international +Date: 3 Oct 1994 06:39:25 GMT +Organization: Computing Center, Academia Sinica +References: <Cx0Mpy.7Lo@actrix.gen.nz> +NNTP-Posting-Host: ywliu%@beta.wsl.sinica.edu.tw +X-Newsreader: TIN [version 1.2 PL0] + +Gary Houston (ghouston@actrix.gen.nz) wrote: +: It seems to me there are a couple of details missing from the ANSI C +: locale stuff: + +: 1/ How can a program find out which character set is being used? + + + You may use setlocale(LC_ALL,NULL) to get the language info. + +: 2/ How can a program determine whether text files use multibyte or +: wide characters, or is it to be assumed that multibyte will +: always be used? + + As far as I am concerned, the wide character is used as the representation +inside your program. That is, wide character is your internal data +representatin form, as I/O operates on multi-byte characters. So, I always +read/write mutl-bytes and convert to wide character , and vice versa. + +: Does anyone know of other standards/conventions/plans which fill +: in this missing information? + + You may check out P.J. Plauger's "Standard C" column on CUJ May 1993 - July +1993. There is another one "Internationlization and Localization" in CUJ July + 1993 too. I am looking for more material. + +Yen-Wei Liu + +1, edited, answered,, +Mail-from: From orac.iinet.com.au!pdcruze Thu Nov 24 17:38:19 1994 +Return-Path: <orac.iinet.com.au!pdcruze> +Received: by icule (Smail3.1.28.1 #1) + id m0rAmnw-00009aC; Thu, 24 Nov 94 17:38 EST +Received: from lagrande.iro.umontreal.ca by iros1.IRO.UMontreal.CA (8.6.9) with ESMTP + id LAA06293; Thu, 24 Nov 1994 11:57:58 -0500 +Received: from saguenay.IRO.UMontreal.CA (root@saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id LAA23939 for <pinard@lagrande.IRO.UMontreal.CA>; Thu, 24 Nov 1994 11:57:50 -0500 +Received: from uniwa.uwa.edu.au (root@uniwa.uwa.edu.au [130.95.128.1]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id LAA20957 for <pinard@IRO.UMontreal.CA>; Thu, 24 Nov 1994 11:57:46 -0500 +Received: from orac.iinet.com.au (orac.iinet.com.au [203.0.178.134]) by uniwa.uwa.edu.au (8.6.9/8.6.9) with ESMTP id AAA09394; Fri, 25 Nov 1994 00:57:29 +0800 +Received: from orac.iinet.com.au (pdcruze@localhost [127.0.0.1]) by orac.iinet.com.au (8.6.9/8.6.9) with ESMTP id AAA08605; Fri, 25 Nov 1994 00:57:11 +0800 +Message-Id: <199411241657.AAA08605@orac.iinet.com.au> +To: pinard@IRO.UMontreal.CA +cc: meyering@comco.com +Subject: Re: Starting localization of GNU recode +In-reply-to: Your message of "Thu, 24 Nov 1994 01:11:00 EST." + <m0rAXP2-00008sC@icule> +Date: Fri, 25 Nov 1994 00:57:10 +0800 +From: "Patrick D'Cruze" <pdcruze@li.org> + +*** EOOH *** +To: pinard@IRO.UMontreal.CA +cc: meyering@comco.com +Subject: Re: Starting localization of GNU recode +In-reply-to: Your message of "Thu, 24 Nov 1994 01:11:00 EST." + <m0rAXP2-00008sC@icule> +Date: Fri, 25 Nov 1994 00:57:10 +0800 +From: "Patrick D'Cruze" <pdcruze@li.org> + +> I met a few points of discussion while doing so: +> +> * I got to decide that, even if the program will eventually make +> most of its output in the foreign languages, the input syntax, +> option values, etc., are not to be localized. + +Yes. The purpose of message catalogs was to provide an easy to use method +for displaying language independent messages. Hence little modifications +need to be made to support this. However, no easy method exists for +supporting language-independent inputs. So this will have to be left up to +the developer to decide how they are going to implement this. + +> * it is not useful that I modify the lib/ routines if not done in the +> true sources. How do you/I/they proceed for getting this job done? +> I presume that lib/ routines will all use gettext for the time being. + +Probably Roland (or another volunteer) will internationalize glibc. Linux's +libc has already been internationalised and a few message catalogs +already exist - French, German, Polish. It probably would be useful +modifying the routines in lib/ for those platforms that will be using +the routines located in libc/. + +> I was expecting a problem which I did not met. All localizable +> strings were luckily into executable positions, that is, affected +> to variables or given as parameter to functions. But I will not +> escape this problem in all my things, and will surely hit some +> localizable strings in structured initializations. I'll see once +> there, unless you thought out an all ready solution for this (?). + +I've come across this a few times within diffutils. Particularly struct +definitions and the like. I'll send you a list of guidelines when looking +for output messages. Will send this to you and Jim tommorrow. + +Regards, +Patrick + + + +1, edited,, +Mail-from: From pinard Mon Nov 28 12:15:47 1994 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0rC9fz-00008uC; Mon, 28 Nov 94 12:15 EST +Message-Id: <m0rC9fz-00008uC@icule> +Date: Mon, 28 Nov 94 12:15 EST +From: pinard (Francois Pinard) +To: Richard M. Stallman <rms@prep.ai.mit.edu> +CC: Jim Meyering <meyering@comco.com> +Subject: GNU standards and localized message catalogs +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII + +*** EOOH *** +Date: Mon, 28 Nov 94 12:15 EST +From: pinard (Francois Pinard) +To: Richard M. Stallman <rms@prep.ai.mit.edu> +CC: Jim Meyering <meyering@comco.com> +Subject: GNU standards and localized message catalogs +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII + +* We also need a uniform convention about where, in the installed +hierarchy, to put translations of manuals in long term. The need is +not immediate. One friend volunteered to translate the GNU recode +manual in French. If this happens, I would like to know first *if* +the distribution should install it by default, and where it should +install it then. If not installed by default, what would be the +uniform naming scheme for Makefile goals installing documents? + +1, edited,, +Mail-from: From pinard Sat Dec 24 23:51:00 1994 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0rLkv4-00009AC; Sat, 24 Dec 94 23:50 EST +Message-Id: <m0rLkv4-00009AC@icule> +Date: Sat, 24 Dec 94 23:50 EST +From: pinard (Francois Pinard) +To: rms@gnu.ai.mit.edu +In-reply-to: <199412250445.XAA25324@mole.gnu.ai.mit.edu> (message from Richard Stallman on Sat, 24 Dec 1994 23:45:19 -0500) +Subject: Re: GNU standards and localized message catalogs +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Sat, 24 Dec 94 23:50 EST +From: pinard (Francois Pinard) +To: rms@gnu.ai.mit.edu +In-reply-to: <199412250445.XAA25324@mole.gnu.ai.mit.edu> (message from Richard Stallman on Sat, 24 Dec 1994 23:45:19 -0500) +Subject: Re: GNU standards and localized message catalogs +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + + * We also need a uniform convention about where, in the installed + hierarchy, to put translations of manuals in long term. + + I think they should go in the Info tree just like English manuals. + +Yes, of course. Suppose I have a French recode.info, and an +English one. This kind of thing will not be immediate, but they +will come. We need some convention to install both. We are not +to give them different names, presumably. People will like to +say, on an individual basis: ``if a French version of something is +available, I'll prefer it over the standard English one''. So we +need a convention to stock these, and a convention to select them. + +1,, +Mail-from: From gnu.ai.mit.edu!rms Sun Dec 25 05:16:06 1994 +Return-Path: <gnu.ai.mit.edu!rms> +Received: by icule (Smail3.1.28.1 #1) + id m0rLpze-00009IC; Sun, 25 Dec 94 05:16 EST +Received: from lagrande.iro.umontreal.ca (lagrande.IRO.UMontreal.CA [132.204.32.32]) by iros1.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id AAA12366 for <icule!pinard>; Sun, 25 Dec 1994 00:01:47 -0500 +Received: from saguenay.IRO.UMontreal.CA (root@saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id AAA10584 for <pinard@lagrande.IRO.UMontreal.CA>; Sun, 25 Dec 1994 00:01:46 -0500 +Received: from mole.gnu.ai.mit.edu (rms@mole.gnu.ai.mit.edu [128.52.46.33]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id AAA14869 for <pinard@iro.umontreal.ca>; Sun, 25 Dec 1994 00:01:37 -0500 +Received: by mole.gnu.ai.mit.edu (8.6.9/4.0) + id <AAA25411@mole.gnu.ai.mit.edu>; Sun, 25 Dec 1994 00:01:33 -0500 +Date: Sun, 25 Dec 1994 00:01:33 -0500 +Message-Id: <199412250501.AAA25411@mole.gnu.ai.mit.edu> +From: Richard Stallman <rms@gnu.ai.mit.edu> +To: pinard@iro.umontreal.ca +In-reply-to: <m0rLkv4-00009AC@icule> (pinard@iro.umontreal.ca) +Subject: Re: GNU standards and localized message catalogs + +*** EOOH *** +Date: Sun, 25 Dec 1994 00:01:33 -0500 +From: Richard Stallman <rms@gnu.ai.mit.edu> +To: pinard@iro.umontreal.ca +In-reply-to: <m0rLkv4-00009AC@icule> (pinard@iro.umontreal.ca) +Subject: Re: GNU standards and localized message catalogs + + We need some convention to install both. We are not + to give them different names, presumably. + +I would give them different names. They would have +separate menu items in the Info directory. That is the +easiest way and it seems good enough, so I don't see a reason +to spend time looking for any other way. + + +1, edited,, +Mail-from: From pinard Tue Jan 3 16:17:29 1995 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0rPGbe-00008xC; Tue, 3 Jan 95 16:17 EST +Message-Id: <m0rPGbe-00008xC@icule> +Date: Tue, 3 Jan 95 16:17 EST +From: pinard (Francois Pinard) +To: vern@ee.lbl.gov +In-reply-to: <199501031914.LAA00333@daffy.ee.lbl.gov> (message from Vern Paxson on Tue, 03 Jan 95 11:14:17 PST) +Subject: Re: Internationalization of Flex +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Tue, 3 Jan 95 16:17 EST +From: pinard (Francois Pinard) +To: vern@ee.lbl.gov +In-reply-to: <199501031914.LAA00333@daffy.ee.lbl.gov> (message from Vern Paxson on Tue, 03 Jan 95 11:14:17 PST) +Subject: Re: Internationalization of Flex +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +There are two categories of patches: a grouped set at initialization +time, and all-over-the-place one which marks localizable strings. +We can consider them separately (but I will most probably end up +suggesting we give them the same treatment...). + +What would be easier would be that the original Flex sources already +marks all strings which require localization. The way I do it in my +things is merely replacing each "STRING" by _("STRING") *if* STRING +should be translated. Flex could then be distributed with: + + #define _(String) (String) + +effectively ignoring the marks. I may provide an initial patch +to you for this. Later on, the maintenance would be relatively +easy for you: if you add or modify a string, you will have to +ask yourself if the new or altered string requires translation, +and include it within _() if you think it should be translated. +"%s: %d" is an example of string not requiring translation... + +The remaining work will be handled by group of volunteers from +different countries. I took the responsibility of organizing how +these things will be done. Once in a while, volunteers will provide +you some COUNTRY.tt files which you might accept to distribute +with Flex. (COUNTRY is a two letter code, like `de' for German.) +If the COUNTRY.tt files ever lag with regard to Flex modifications, +this would not break nationalized Flex: the current mechanics will +merely return the original English string if a proper translation +cannot be found. So you do not even have to feel tied to the +translators for releasing new distributions for Flex. And nothing +is subject to the GPL so far :-). + +The initialization is not very complex, and can be done within +less than a dozen easy lines of code, hardly GPL'able. I think +they could be included in standard Flex distribution, while being +conditionalized out. The only harder modifications come from me, +and touch Makefile.in, for including all the machinery to prepare +and install locale message catalogs provided the underlying system +has what is needed. In the way I am now distributing my things, this +machinery automatically cut itself out when GNU locale is not usable. + +Remain only two modules, currently named libintl.h and libintl.c +(this might change), which are covered by the GPL, which you +do not want to distribute with Flex. The Flex README could +suggest installers to grab them from any other GNU distribution. +The configuration machinery might automatically check if they have +been copied by the installer and, if not, forget about localization. + +This way, Flex will be easily and widely nationalized, the GPL +principle will be safe, Flex will stay free of the GPL, and the +burden on the installers, as well as both you and me, will be +minimal in the long run. + +There is a difficulty I have not studied yet, and which comes from +the fact that Flex generates C code (Bison has the same problem). +Flex itself could be nationalized, and this is orthogonal to the fact +Flex could generate nationalizable scanners. Both are desirable. + + +1, edited,, +Mail-from: From pinard Thu Jan 12 07:41:07 1995 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0rSOpt-00007LC; Thu, 12 Jan 95 07:41 EST +Message-Id: <m0rSOpt-00007LC@icule> +Date: Thu, 12 Jan 95 07:41 EST +From: pinard (Francois Pinard) +To: vern@ee.lbl.gov +In-reply-to: <199501051930.LAA04658@daffy.ee.lbl.gov> (message from Vern Paxson on Thu, 05 Jan 95 11:30:54 PST) +Subject: Re: Internationalization of Flex +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Thu, 12 Jan 95 07:41 EST +From: pinard (Francois Pinard) +To: vern@ee.lbl.gov +In-reply-to: <199501051930.LAA04658@daffy.ee.lbl.gov> (message from Vern Paxson on Thu, 05 Jan 95 11:30:54 PST) +Subject: Re: Internationalization of Flex +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +Besides, not long after having started this i18n effort for my +own things, I realized that the i18n attribute should really be +attached to strings themselves, and not to what we do with them. +A blatant example is an error message produced by formatting. +The format string needs i18n, while the result from sprintf may +have so many different instances that it is unpractical to list +them all in some error_string_out() routine. I also got other +cases forcing me to concentrate on strings for i18n. + +There is a stylistic issue here. I use _("hello"), adding three +characters to each localizable string, while you will most probably +use _( "hello" ), adding five characters per localizable string. +Yet, it has the advantage of being shorter than error_string_out, +and be done at the right level. + +By merely defining _(String) to be (String), you just turn off +localization in standard flex, with not a single nanosecond spoiled +on it. But this will then allow me to produce a quite smaller and +maintainable patch for i18n of flex. + + This [error_string_out()] routine could then look up every string + passed it in a translation table that's compiled into flex + like the skel[] array. All that's needed is a public-domain + description of the format of the COUNTRY.tt translation files + and the rest should be easy. + +If I clearly understand your idea, you will compile in flex +a French table, and obtain a French speaking binary. You will +produce different binaries for Catalan, Dutch, etc. That is not +practical on big sites having multinational users. + +Right now in my things, the setting of LANG in the environment +decides the language to use, and there is a single binary to handle +all things. Further, the evolving GNU locale will soon change its +*.tt file format, and will try to use the current system underlying +localization mechanics, if any good one is found at configure time. + +There is no need that you redo all this and throw new solutions to +this whole set of problems. The most workable solution to me looks +like standard flex distribution already have all _() included -- and +that you accept routinely adding _() to new localizable strings when +you are doing flex maintenance, and that a separately distributed +patch attaches flex to GNU locale complexities, without having you +discovering and solving them anew. + + Let me know if this is workable (I'm willing to do the work). + +Let me take one hour this morning to offer you a patch for _() for +2.5.0.6, hoping that you will accept it. That would be a start. Let +me take care of the remaining organizational problems, synchronizing +with other teams, etc. I already do this for other GNU packages +and will eventually help with most of them (I've accepted that role). + +Once we will have had success with i18ned flex for some time, it +would then become easier to convince you to go further for other +aspects (like *producing* i18nable scanners :-). + +Let me hope that my pleading for the cause will touch your heart, +somewhere :-). Keep happy! + +-- +François Pinard ``Happy GNU Year!'' pinard@iro.umontreal.ca +A New Year's gift? Give us Programming Freedom! Write lpf@uunet.uu.net + + +1, edited,, +Mail-from: From pinard Thu Jan 12 16:44:56 1995 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0rSXKA-00007VC; Thu, 12 Jan 95 16:44 EST +Message-Id: <m0rSXKA-00007VC@icule> +Date: Thu, 12 Jan 95 16:44 EST +From: pinard (Francois Pinard) +To: vern@ee.lbl.gov +In-reply-to: <199501121822.KAA21713@daffy.ee.lbl.gov> (message from Vern Paxson on Thu, 12 Jan 95 10:22:40 PST) +Subject: Re: Internationalization of Flex +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Thu, 12 Jan 95 16:44 EST +From: pinard (Francois Pinard) +To: vern@ee.lbl.gov +In-reply-to: <199501121822.KAA21713@daffy.ee.lbl.gov> (message from Vern Paxson on Thu, 12 Jan 95 10:22:40 PST) +Subject: Re: Internationalization of Flex +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + + I'm not sure having to remember to use error_string_out() instead + of fprintf( stderr ... ) is any easier, though. + +Not only error strings are being made localizable by the patch I +shipped this morning, but also statistics, version and help, and +some debug output. These are not always error messages, and not +always sent to stderr. + +Sometimes in flex, messages are constructed in pieces using %s to +insert parts. Translating at the string level is the right approach +in these situations. I'm not sure error_string_out() would have been +satisfying (but I'm not going to argue, since I have your favor! :-) + +1, edited, answered,, +Mail-from: From twinsun.com!eggert Tue Feb 14 05:16:50 1995 +Path: bloom-beacon.mit.edu!senator-bedfellow.mit.edu!faqserv +From: mike@vlsivie.tuwien.ac.at +Newsgroups: comp.unix.questions,comp.std.internat,comp.software.international,comp.lang.c,comp.windows.x,comp.std.c,comp.answers,news.answers +Subject: Programming for Internationalization FAQ +Supersedes: <internationalization/programming-faq_787570857@rtfm.mit.edu> +Followup-To: comp.unix.questions,comp.std.internat,comp.software.international,comp.lang.c,comp.windows.x,comp.std.c +Date: 15 Jan 1995 10:26:57 GMT +Organization: TU Wien +Lines: 564 +Approved: news-answers-request@MIT.EDU +Expires: 28 Feb 1995 10:26:07 GMT +Message-ID: <internationalization/programming-faq_790165567@rtfm.mit.edu> +NNTP-Posting-Host: bloom-picayune.mit.edu +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit +Summary: This FAQ discusses writing programs which can handle + different language conventions/character sets/etc. + Applicable to all character set encodings; with particular + emphasis on ISO-8859-1. +X-Last-Updated: 1994/11/15 +Originator: faqserv@bloom-picayune.MIT.EDU +Xref: bloom-beacon.mit.edu comp.unix.questions:38263 comp.std.internat:2069 comp.software.international:1289 comp.lang.c:65751 comp.windows.x:34580 comp.std.c:7917 comp.answers:9514 news.answers:33146 + +*** EOOH *** +From: mike@vlsivie.tuwien.ac.at +Newsgroups: comp.unix.questions,comp.std.internat,comp.software.international,comp.lang.c,comp.windows.x,comp.std.c,comp.answers,news.answers +Subject: Programming for Internationalization FAQ +Supersedes: <internationalization/programming-faq_787570857@rtfm.mit.edu> +Followup-To: comp.unix.questions,comp.std.internat,comp.software.international,comp.lang.c,comp.windows.x,comp.std.c +Date: 15 Jan 1995 10:26:57 GMT +Organization: TU Wien +Approved: news-answers-request@MIT.EDU +Expires: 28 Feb 1995 10:26:07 GMT +NNTP-Posting-Host: bloom-picayune.mit.edu +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit +Summary: This FAQ discusses writing programs which can handle + different language conventions/character sets/etc. + Applicable to all character set encodings; with particular + emphasis on ISO-8859-1. +X-Last-Updated: 1994/11/15 +Originator: faqserv@bloom-picayune.MIT.EDU + + +Archive-name: internationalization/programming-faq +Posting-Frequency: monthly + + + + Programming for Internationalization + + + +DISCLAIMER: THE AUTHOR MAKES NO WARRANTY OF ANY KIND WITH REGARD TO +THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +Note: Most of this was tested on a Sun 10, running SunOS 4.1.* - other +systems might differ slightly + +This FAQ discusses topics related to the use of ISO 8859-1 based 8 bit +character sets. It discusses how to program applications which support +the use European (Latin American) national character sets on +UNIX-based systems and standard C environments. + + + +1. Which coding should I use for accented characters? +Use the internationally standardized ISO-8859-1 character set to type +accented characters. This character set contains all characters +necessary to type (West) European languages. This encoding is also the +preferred encoding on the Internet (where accepted - see below). + +This character set is also used by AmigaDOS, MS-Windows (Code Page +1252 in Microsoft Speak. This is for Windows versions delivered in +the US, Europe (except Eastern Europe) and Latin America. In Windows +3.1 Microsoft added additional characters in the 0x80-9F range), +VMS (DEC MCS is a draft version of the current ISO 8859-1 character +set standard and differs in only two characters) and (most) UNIX +implementations. MS-DOS uses a different character set and is not +compatible with this character set. + +ISO 8859-X actually is a family of character set standards. Basically +all of the information given here is also valid for these standards. +These standards comprise 8859-X: +8859-1 Europe, Latin America +8859-2 Eastern Europe +8859-3 SE Europe/miscellaneous (Esperanto, Maltese, etc.) +8859-4 Scandinavia/Baltic (mostly covered by 8859-1 also) +8859-5 Cyrillic +8859-6 Arabic +8859-7 Greek +8859-8 Hebrew +8859-9 Latin5, same as 8859-1 except for Turkish instead of Icelandic +8859-10 Latin6, for Eskimo/Scandinavian languages + +Another nascent standard is UNICODE (ISO 10646). UNICODE is an +extension of ISO 8859-1 (which itself is an extension of US-ASCII) to +16 bit characters. Thus most of the world's languages (including +Japanese, Korean, Chinese...) can be covered. + +Most of the information given here is independent of the character +encoding used (e.g. DEC MCS, etc.), but can be applied to any +character set, providing the programming environment has provisions +for this standard. + + + +2. Getting your environment right +To configure your environment such that you can enter, process and +display 8 bit ISO characters, check out the ISO-8859-1 FAQ available +via anonymous ftp from ftp.vlsivie.tuwien.ac.at in +/pub/8bit/FAQ-ISO-8859-1. + + + +3. Setting your environment for ISO-C (ANSI-C) programs +The ISO C Standard (ANSI C Standard 4.4) defines several functions for +supporting localization. To set your international environment on +program startup, you should make one or several calls to the setlocale +functions. Calls to this function will predetermine the reaction of +other localization functions according to your language/country +environment. + +To configure a particular aspect of you environment, say the number +representation, you would call +-- +setlocale (LC_NUMERIC, "Germany"); +-- + +This call would set all number representation functions defined in the +localization set to return numbers in the format used in Germany. If +the call was successful, setlocale will return the name of your +locale. A NULL return value indicates failure. Note that the +environments are predetermined outside your C program by the system +you run on. (So the example given here is likely to fail on all but a +few systems.) Check the setlocale manual page or your system +documentation to find out about the environments available. + +There are several LOCALE types available for different localization +aspects (currency sign, number representation, characters sets). The +value they can take is highly system dependent. Also, it should be up +to the use to define the local environment he needs. + +A C program inherits its locale environment variables when it starts up. +This happens automatically. However, these variables do not +automatically control the locale used by the library functions, because +ISO/ANSI C says that all programs start by default in the standard C +locale. To use the locales specified by the environment, The POSIX +standard defines the following call: +----- +setlocale (LC_ALL, ""); +----- + +Of course, you can only set part of your environment, by calling, say: +---- +setlocale (LC_CTYPE, ""); +---- +This only defines the character classification macros (defined in +ctype.h). + +This is a list of local categories: + + Effect of Specifying Environment Variable + category the Value Affected + __________________________________________________________ + + LC_ALL Sets or queries LANG + entire environment + LC_COLLATE Changes or queries LC_COLLATE + collation sequences + LC_CTYPE Changes or queries LC_CTYPE + character classifi- + cation + LC_NUMERIC Changes or queries LC_NUMERIC + number format infor- + mation + LC_TIME Changes or queries LC_TIME + time conversion + parameters + LC_MONETARY Changes or queries LC_MONETARY + monetary information + + + + +4. Using the locale information for character classification +If you write a program which supports international use, you should +use the available standardized functions, as only these will be +influenced by the setlocale call. Thus, if you want to convert a +capital letter in c to a lower case letter in l, _don't_ write: + +l = c - 'A' + 'a'; + +While this will work for characters in the US-ASCII character set, it +will not work with many other character sets. The following, +standard-conformant code will: + +#include <ctype.h> + +.... + +l = tolower(c); + +Also note that the second code may actually be faster than even the +full "C" locale functionality (for most implementations), as it +replaces a complex expression ( (c<='Z' && c>='A')? c-'A'+a:c; )by a simple +table lookup! + +Note that this ISO standard is independent of the character set +encoding used! + + + +5. Language independent messages +There are two competing standards for language independent messages: +one by X/Open, and another one by POSIX. The X/Open standard seems to +have found a larger following as it has been around for a longer time. + +5.1 X/Open language independent messages +X/Open defines a method for providing language-independent messages. +Error messages are kept in a catalog which is opened upon program +start with a locale specification. Then the message number and a set +specification are used to index the message catalog. A default fourth +argument is specified which will be printed if a particular message +cannot be found in the catalog. + +Here is the world-famous C program using the language-independent +X/Open message standard: +-------------------------------------------------------------------------- +#include <stdio.h> +#include <nl_types.h> + +#define SET 1 +#define MSG_HELLO 1 + +nl_catd catfd; + +int main (int argc, char **argv) { + /* Open the message catalog. We use the basename of the program + * as the catalog name. Of course, several programs can also + * share a common catalog. + */ + catfd = catopen (basename (argv [0]), NL_CAT_LOCALE); + /* catgets returns message MSG_HELLO from set SET from the + * message catalog catfd. If catfd does not refer to a message + * catalog, or the requested message cannot be found, the + * catalog, or the requested message cannot be found, the + * fourth argument is returned. + */ + printf (catgets (catfd, SET, MSG_HELLO, "hello, world\n")); + catclose (catfd); + return 0; +} +------------------------------------------------------------------------- + +For catopen, specify the constant NL_CAT_LOCALE to open the message +catalog for the locale set for the LC_MESSAGES variable; using +NL_CAT_LOCALE conforms to the XPG4 standard. You can specify 0 (zero) +for compatibility with XPG3; when oflag is set to zero, the locale set +for the LANG variable determines the message catalog locale. + +Several utilities exist for generating message catalogs and for +upgrading programs which contain hard-wired strings: +* gencat is used to generate message catalogs +[All other programs are OS-specific:] +* Ultrix and OSF support the extract program which will extract string + constants from the C source code, and has an option to replace these + strings with calls to catgets. +* HP/UX has a similar utility called findmsg. +* Under OSF, message catalogs may be listed with the dspcat utility. +* HP/UX calls a similar utility dumpmsg. + + +5.2 Sun/XView +Sun implements a different set of functions functions to support i18n +of messages (the source is available with the XView code): + +You can either use: +----------------------------------------------- + +main() +{ + // get the message catalog named "helloprogram" + // for the hello world program + textdomain("helloprogram"); + + // get the translation for the "Hello, world\n" string + printf(gettext("Hello, world\n")); +} +----------------------------------------------- + +or you can roll all in one and write + +----------------------------------------------- +main() +{ + // get the translation for the "Hello, world\n" string + // from the message catalog "helloprogram" + printf(dgettext("helloprogram","Hello, world\n")); +} +----------------------------------------------- + +The LC_MESSAGES locale category setting determines the locale of +strings that gettext() returns. The message catalogs are generated +with either the installtxt or gencat commands. + +No opening of files as in the old SYS V and X/Open routines, and no +handling of message numbers that you must have in a database to +administer. + + +5.3 POSIX language independent messages +Neither of the previous two mechanisms is in the POSIX standard. +There was much disagreement in the POSIX.1 committee about using the +gettext routines vs. catgets (XPG). In the end the committee couldn't +agree on anything, so no messaging system was included as part of the +standard. I believe the informative annex of the standard includes the +XPG3 messaging interfaces, "...as an example of a messaging system +that has been implemented..." + +They were very careful not to say anywhere that you should use one set +of interfaces over the other. + + + +6. Other localization aspects in ISO/ANSI C (and POSIX environments) +For a more thorough discussion of localization and +internationalization (aka. i18n), check your system vendors +documentation, and the C library manual which comes with the FSF's +glibc library (Chapter 19, 'Locales and Internationalization'). + + + +7. Internationalization under X11 +7.1 Output +To output text encoded with ISO 8859-1 under X11, simply invoke the X +display routines with 8 bit characters as you would use them with +7-bit ASCII. You should however choose a font which contains bitmaps +for these characters. You can use the xfd utility to display a font +to verify that it contains a full set of characters. + + +7.2 Input +If you use a national keyboard (that is a keyboard, which has distinct +keys for your countries special characters), inputting accents is +straight forward and you'll get the corresponding characters by using +the X11 input functions. + +Sometimes it may be necessary to input characters for which there are +no keys on your keyboard (e.g. if you want to enter the German 'ß' +from a French keyboard). + +X11R5 and X11R6 both have extensive support for i18n, but due to a +variety of factors the R5 i18n was not well understood or widely +used. Many people resorted to a work-around and might have been +disappointed when R6 did not include this misfeature. It is important +to recognize that the correct use of R5 and R6 i18n features will +ensure maximum portability of your program. + +Footnote: Amongst other reasons, the X Consortium decision not to add +support for input methods to the Xaw Athena widget contributes to this +situation. Many users (and much of the PD software) live in an +Xaw-only world, so they will not be able to benefit from this i18n +effort. + +X11 R5 and R6 support input methods for entering non-ASCII, and +displaying and configuring text, menus etc. for a wide variety of +languages. This input method has to be installed by the application +by calls to the Xlib library (or an Xt toolkit call). + +[Under X11R5, some X servers (notably the Xsun server) will let you +enter ISO characters by supplying a built-in escape mechanism, if no +keys for these characters are on your keyboard, and will pass along +and display ISO 8859-1. This hack obviated the need to install an +input method, but was less flexible.] + + +If you are using a toolkit, it is quite simple to support localization +of you X11 code: +If you're using a toolkit -- Xt and a widget set like Motif or R6 Xaw -- +you need only add a single line of code to your source. Before any other +calls to Xt, add a call to XtSetLanguageProc, e.g.: + + int main (int argc, char** argv) + { + ... + XtSetLanguageProc (NULL, NULL, NULL); + top = XtAppInitialize ( ... ); + ... + } + +The LANG and LC_xxx environment variables (see section 3) will then be +used to determine the 'input method' for this X application. This +input method is responsible for managing COMPOSE character sequences +or any other input mechanism for this particular implementation. Also +see section 9 of ftp://ftp.vlsivie.tuwien.ac.at/pub/8bit/FAQ-ISO-8859-1, +the FAQ on ISO 8859-1 usage. + + +7.3 Toolkits, Widgets, and I18N +The preferred way of inputing national characters when a national +keyboard is not available is one/several input methods. These input +methods will then support various kinds of compose sequences to enter +national characters. + +The environment variables LANG and/or LC_xxx select the language for +the Input Method (IM), but if several input methods exist, the +environment variable XMODIFIERS can be used to select a specific input +method. + +Xlib supports IMs +Xt supports IMs +Xaw does not support IMs + +Thus, applications written with Xlib or Xt can support IMs (see +section 7.2 on how to install input methods under Xt), but Xaw based +applications will not. + +Motif 1.2 or greater automatically uses the R5/R6 input method APIs. +Thus applications using Motif 1.2+ can be made to support IMs. +Several Motif 1.[01] versions also had similar functionality added to +them by the respective vendors, but these extensions are +vendor-specific and not portable. + +FOOTNOTE: If you can have comments/corrections for this section and on + OpenLook, please let me know. + + +7.4 I18N under X11R6, General Information +Background information from the X11R6 announcement: +Internationalization (also known as I18N, there being 18 letters between the +i and n) of the X Window System, which was originally introduced in Release +5, has been significantly improved in R6. The R6 I18N architecture follows +that in R5, being based on the locale model used in ANSI C and POSIX, with +most of the I18N capability provided by Xlib. R5 introduced a fundamental +framework for internationalized input and output. It could enable basic +localization for left-to-right, non-context sensitive, 8-bit or multi-byte +codeset languages and cultural conventions. However, it did not deal with +all possible languages and cultural conventions. R6 also does not cover all +possible languages and cultural conventions, but R6 contains substantial new +Xlib interfaces to support I18N enhancements, in order to enable additional +language support and more practical localization. + +The additional support is mainly in the area of text display. In order to +support multi-byte encodings, the concept of a FontSet was introduced in R5. +In R6, Xlib enhances this concept to a more generalized notion of output +methods and output contexts. Just as input methods and input contexts sup- +port complex text input, output methods and output contexts support complex +and more intelligent text display, dealing not only with multiple fonts but +also with context dependencies. The result is a general framework to enable +bi-directional text and context sensitive text display. + +The description of the X11R6 internationalization framework is +available via anonymous ftp from ftp.x.org in +/pub/R6untarred/xc/doc/specs/i18n. + + + +8. Supporting I18N Network Protocols +8.1 MIME +MIME is specified in RFC 1521 and RFC 1522 which are available from +ftp.uu.net. There is also a MIME FAQ which is available via anonymous +ftp from ftp.ics.uci.edu in /mh/contrib/multimedia/mime-faq.txt.gz. +(This file is in compressed format. You will need the GNU gunzip +program to decompress this file.) + +If you want to write applications which support the MIME protocol, +there are several libraries/tools which can ease your task: + + +8.1.1 metamail +Source for supporting MIME (the `metamail' package) in various mail +readers is available via anonymous ftp from thumper.bellcore.com in +/pub/nsb. This distribution consists of several utilities, which can +be called by MIME applications to handle MIME types. + + +8.1.2 MIMElt +A "lightweight" MIME library available via anon ftp from +oslonett.no:Software/MsDos/Comm/Offline/mimeltXX.zip + +It is source code (ANSI C) packaged as a library to facilitate +construction of a limited MIME facility (limited == handling only +character-set aspects of MIME, not the multimedia-aspects). It +includes hooks to recode character sets into whatever system you are +running off (e.g. if you read mail on a MsDos platform using CP-850, +MIMElite may be set up so that QUOTED-PRINTABLE ISO Latin 1 is recoded +into CP-850 for reading and saving to file). + +It's main use is to provide programmers of so-called "off-line +readers" (used by user's who access Internet mail through dial-up +service providers) with the tools needed to include proper support for +QUOTED-PRINTABLE encoding in their product. + +The archive also contain a couple of sample applications that +demonstrates how the library may be used. UNMIME is a stand-alone +utility to decode MIME-encoded messages (e.g. it works like UUDECODE +for binary files with BASE64 encoding), SENDMIME is a simple utility +to send MIME-encoded messages if your service provider doesn't have +PINE or similar tools. + +The current version (2.1) is limited to character set issues. I am +about to release version 2.2, which will support additional +Content-Types (e.g. "application/octet-stream"). + + + +9. Programming in Prolog +SICStus Prolog accepts ISO characters as part of atoms, so you can +even define goal names containing accented characters. I/O of 8 bit +characters is (obviously) also supported. + + + +10. ISO 8859-1 on non-UNIX systems +10.1 MS-DOS +MS-DOS generally uses its own characters set. There are several code +pages (one with the same symbols as ISO 8859-1, albeit at different +character code positions, which can lead to problems with the transfer +of data). + +If interoperability without data conversion is your goal, you can +reconfigure your MS-DOS PC to use an ISO-8859-1 code page. Check out +the anonymous ftp archive ftp.uni-erlangen.de, which contains data on +how to do this (and other ISO-related stuff) in /pub/doc/ISO/charsets. +The README file contains an index of the files you need. + +Most (all?) C compilers/libraries for MS-DOS have only minimal support +for the ANSI/POSIX locale mechanism. The setlocale() and localeconv() +calls (and stuff like strxfrm()) are generally hardwired. + + +10.2 MS Windows +MS-Windows (using code page 1252) normally uses the first 256 +characters of Unicode, which is (for all practical purposes) +equivalent to ISO 8859-1. Thus, data representation and conversion +for interoperability with other ISO 8859-1 compliant systems is not an +issue. + +It seems that C libraries for MS Windows do not support the ANSI/POSIX +locale mechanism. (If you have any experiences with that, please let +me know.) There is a POSIX-like mechanism in some Microsoft platform +services, but none in the compilers from any vendor. + + +10.3 OS/2 +Text mode OS/2 programs generally suffer the same limitations as do +MS-DOS programs, because the display hardware is the same. + +Presentation Manager OS/2 programs using code page 1004 will order +the font glyphs in the same sequence as ISO 8859-1 (although of +course whether the glyphs will actually look anything like those +from ISO 8859-1 depends entirely from the font). + +The IBM CSet++ compiler supports full internationalization, with +several predefined locales. + +The Borland C++ compiler supports only the "C" locale. + +The Watcom C++ compiler supports only the "C" locale. + +The Metaware High C++ compiler supports only the "C" locale. It +does, however, also support UNICODE, providing UNICODE character +types and UNICODE versions of the appropriate parts of the standard +library (including I/O). + + + +10.4 Apple Macintosh +MacIntoshes have their own non-standard character encodings; +the first 128 characters are US-ASCII but the remaining characters are +non-standard. + +I do not know whether C libraries (for which compilers?) for the +MacIntosh support the ANSI/POSIX locale mechanism. If you have any +experiences with that, please let me know. + + +10.5 Amiga +The AmigaOS uses ISO-8859-1. As of OS version 2.1, Amiga-specific +means of localization are available. + + + +11. Home location of this document +The most recent version of this document is available via anonymous +ftp from ftp.vlsivie.tuwien.ac.at under the file name +/pub/8bit/ISO-programming. + +----------------- + +Copyright İ 1994 Michael Gschwind (mike@vlsivie.tuwien.ac.at) + +This document may be copied for non-commercial purposes, provided this +copyright notice appears. Publication in any other form requires the +author's consent. + +Dieses Dokument darf unter Angabe dieser urheberrechtlichen +Bestimmungen zum Zwecke der nicht-kommerziellen Nutzung beliebig +vervielfältigt werden. Die Publikation in jeglicher anderer Form +erfordert die Zustimmung des Autors. + +Michael Gschwind, Institut f. Technische Informatik, TU Wien +snail: Treitlstrasse 3-182-2 || A-1040 Wien || Austria +email: mike@vlsivie.tuwien.ac.at note: real time != real fast +phone: +(43)(1)58801 8156 fax: +(43)(1)586 9697 + + +1, edited, resent,, +Mail-from: From li.org!owner-li-international Fri Jan 20 08:56:04 1995 +Return-Path: <li.org!owner-li-international> +Received: by icule (Smail3.1.28.1 #1) + id m0rVJon-00009Da; Fri, 20 Jan 95 08:56 EST +Sender: li.org!owner-li-international +Received: from lagrande.iro.umontreal.ca (lagrande.IRO.UMontreal.CA [132.204.32.32]) by iros1.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id RAA25970 for <icule!pinard>; Mon, 16 Jan 1995 17:34:02 -0500 +Received: from saguenay.IRO.UMontreal.CA (root@saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id RAA14270 for <pinard@lagrande.IRO.UMontreal.CA>; Mon, 16 Jan 1995 17:33:53 -0500 +Received: from uniwa.uwa.edu.au (root@uniwa.uwa.edu.au [130.95.128.1]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id RAA07348 for <pinard@iro.umontreal.ca>; Mon, 16 Jan 1995 17:33:41 -0500 +Received: from orac.aust.li.org (orac.iinet.com.au [203.0.178.134]) by uniwa.uwa.edu.au (8.6.9/8.6.9) with ESMTP id GAA22040; Tue, 17 Jan 1995 06:29:21 +0800 +Received: (from majordom@localhost) by orac.aust.li.org (8.6.9/8.6.9) id FAA01118 for li-international-list; Tue, 17 Jan 1995 05:34:39 +0800 +Received: from alcor (alcor.twinsun.com [198.147.65.1]) by orac.aust.li.org (8.6.9/8.6.9) with ESMTP id FAA01112 for <li-international@li.org>; Tue, 17 Jan 1995 05:34:28 +0800 +Received: from twinsun.com (twinsun.twinsun.com [192.54.239.2]) by alcor (8.6.5/8.6.5) with SMTP id NAA04793 for <li-international@li.org>; Mon, 16 Jan 1995 13:06:52 -0800 +Received: from spot.twinsun.com by twinsun.com (4.1/SMI-4.1) + id AA06664; Mon, 16 Jan 95 13:33:30 PST +Received: by spot.twinsun.com (4.1/SMI-4.1) + id AA04256; Mon, 16 Jan 95 13:33:30 PST +Old-From: eggert@twinsun.com (Paul Eggert) +Message-Id: <9501162133.AA04256@spot.twinsun.com> +Date: 16 Jan 1995 13:33:28 -0800 +To: li-international@li.org +Subject: ISO Normative Addendum 1 and its effect on the C library +From: International List <li-international@li.org> +Sender: owner-li-international@li.org +Precedence: bulk +Reply-To: LI-international@li.org + +*** EOOH *** +From: eggert@twinsun.com (Paul Eggert) +Date: 16 Jan 1995 13:33:28 -0800 +To: li-international@li.org +Subject: ISO Normative Addendum 1 and its effect on the C library +Reply-To: LI-international@li.org + +Normative Addendum 1 (NA1) to the ISO C standard was approved last year, +and I recently ran across a nice summary written by Clive Feather. +Please see <http://sf.www.lysator.liu.se/c/nal.html> for this; + +Most of the changes required by NA1 are to the C library's wide +character and multibyte string support. I don't see these changes +mentioned in the latest glibc snapshot. I asked Roland McGrath, +glibc's developer, about this, and he replied: + + Date: Mon, 16 Jan 95 15:53:26 -0500 + From: Roland McGrath <roland@gnu.ai.mit.edu> + + I think if you make the specifications available to the Linux community, + the new library functions will get written and contributed to glibc. + Try the mailing list li-international@li.org. + +So I'm sending this message to li-international. I can forward a copy +of the NA1 summary to whoever needs it; just ask. + +Two of the NA1 changes (__STDC_VERSION__ and digraphs) require changes +to GCC itself; I've volunteered to do this. One change (namely +<iso646.h>) can be done either in GCC or in libc, though if GCC does +digraphs it may make more sense for it to do <iso646.h> as well. +But the other changes belong to the C library proper. + + + +1,, +Mail-from: From twinsun.com!eggert Tue Feb 14 05:16:49 1995 +Return-Path: <twinsun.com!eggert> +Received: by icule (Smail3.1.28.1 #1) + id m0reKJK-00009mC; Tue, 14 Feb 95 05:16 EST +Received: from lagrande.iro.umontreal.ca (lagrande.IRO.UMontreal.CA [132.204.32.32]) by iros1.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id CAA00816 for <icule!pinard>; Tue, 14 Feb 1995 02:16:27 -0500 +Received: from saguenay.IRO.UMontreal.CA (root@saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id CAA02807 for <pinard@lagrande.IRO.UMontreal.CA>; Tue, 14 Feb 1995 02:16:20 -0500 +Received: from alcor.twinsun.com (alcor.twinsun.com [198.147.65.1]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id CAA29451 for <pinard@iro.umontreal.ca>; Tue, 14 Feb 1995 02:16:16 -0500 +Received: from twinsun.com (twinsun.twinsun.com [192.54.239.2]) by alcor.twinsun.com (8.6.5/8.6.5) with SMTP id WAA03362 for <pinard@iro.umontreal.ca>; Mon, 13 Feb 1995 22:44:50 -0800 +Received: from spot.twinsun.com by twinsun.com (4.1/SMI-4.1) + id AA08130; Mon, 13 Feb 95 23:15:06 PST +Received: by spot.twinsun.com (4.1/SMI-4.1) + id AA05763; Mon, 13 Feb 95 23:15:05 PST +From: eggert@twinsun.com (Paul Eggert) +Message-Id: <9502140715.AA05763@spot.twinsun.com> +Date: 13 Feb 1995 23:15:04 -0800 +To: pinard@iro.umontreal.ca +In-Reply-To: <m0rdrDE-00009QC@icule> (pinard@iro.umontreal.ca) +Subject: Re: glocale and Uniforum gettext simplicity + +*** EOOH *** +From: eggert@twinsun.com (Paul Eggert) +Date: 13 Feb 1995 23:15:04 -0800 +To: pinard@iro.umontreal.ca +In-Reply-To: <m0rdrDE-00009QC@icule> (pinard@iro.umontreal.ca) +Subject: Re: glocale and Uniforum gettext simplicity + + + Date: Sun, 12 Feb 95 22:12 EST + From: pinard@iro.umontreal.ca (Francois Pinard) + + Hello, Paul. + + For more on this topic please see the Programming + for Internationalization FAQ (Message-ID: + <internationalization/programming-faq_784901999@rtfm.mit.edu>) + which I can forward to you if you like. + + Would you do this, please? + +Sure, the latest revision be in my next message. For future +reference, the coordinates are +<ftp://rtfm.mit.edu/pub/usenet-by-group/comp.answers/internationalization/programming-faq>. + +Alas, I haven't had time to work on this much lately -- beset with hardware +problems at home and no time to fix them.... + + +1, edited,, +Mail-from: From pinard Tue Mar 21 12:53:53 1995 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0rr87q-00009TC; Tue, 21 Mar 95 12:53 EST +Message-Id: <m0rr87q-00009TC@icule> +Date: Tue, 21 Mar 95 12:53 EST +From: pinard (François Pinard) +To: meyering@comco.com +CC: drepper@ipd.info.uni-karlsruhe.de +In-reply-to: <199503211712.LAA25472@idefix.comco.com> (message from Jim Meyering on Tue, 21 Mar 1995 11:12:49 -0600) +Subject: Re: international fileutils +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Tue, 21 Mar 95 12:53 EST +From: pinard (François Pinard) +To: meyering@comco.com +CC: drepper@ipd.info.uni-karlsruhe.de +In-reply-to: <199503211712.LAA25472@idefix.comco.com> (message from Jim Meyering on Tue, 21 Mar 1995 11:12:49 -0600) +Subject: Re: international fileutils +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +There are three things to do for each package: + +* Adjust Autoconf and Makefiles +* Mark all localizable strings in sources and doing other adjustments +* Translating messages for French (and maybe, let's be fair, German :-). + +1, edited,, +Mail-from: From pinard Sun Apr 23 13:26:30 1995 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0s35QR-00008FC; Sun, 23 Apr 95 13:26 EDT +Message-Id: <m0s35QR-00008FC@icule> +Date: Sun, 23 Apr 95 13:26 EDT +From: pinard (François Pinard) +To: Jim Meyering <meyering@comco.com>, + Ulrich Drepper <drepper@gnu.ai.mit.edu>, + Roland McGrath <roland@gnu.ai.mit.edu>, + Paul Eggert <eggert@twinsun.com> +Subject: GNU locale and Ulrich's effort +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Sun, 23 Apr 95 13:26 EDT +From: pinard (François Pinard) +To: Jim Meyering <meyering@comco.com>, + Ulrich Drepper <drepper@gnu.ai.mit.edu>, + Roland McGrath <roland@gnu.ai.mit.edu>, + Paul Eggert <eggert@twinsun.com> +Subject: GNU locale and Ulrich's effort +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +I'm trying to get started the overall effort for GNU localization, +by offering translators GNU packages to translate, and the means +to do so. I also do not want to spoil the energies being offered. +Many pieces of the puzzle are in place already and, as usual, I +contemplate them all trying to see what is missing, and working +towards the complete picture. + +Surely to me, GNU locale (glocale, as a package) has to provide a +fairly complete set of self-contained tools for helping package +maintainers to internationalize their product, and also for +localizers to translate message catalogs. Further, being itself +internationalized, it should be a very carefully crafted example +for maintainers, about how one might set his/her own package to be +easily installed while localization is effective, and portably! + + + +1,, +Mail-from: From pinard Mon May 1 22:16:31 1995 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0s67Vl-00008NC; Mon, 1 May 95 22:16 EDT +Message-Id: <m0s67Vl-00008NC@icule> +Date: Mon, 1 May 95 22:16 EDT +From: pinard (=?ISO-8859-1?Q?Fran=E7ois_Pinard?=) +To: gnu@prep.ai.mit.edu +CC: rms@gnu.ai.mit.edu +In-reply-to: <9505020044.AA12891@pizza> (gnu@ai.mit.edu) +Subject: Re: [pinard@iro.umontreal.ca: Internationalizing GNU: the maintainer side] +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Mon, 1 May 95 22:16 EDT +From: pinard (François Pinard) +To: gnu@prep.ai.mit.edu +CC: rms@gnu.ai.mit.edu +In-reply-to: <9505020044.AA12891@pizza> (gnu@ai.mit.edu) +Subject: Re: [pinard@iro.umontreal.ca: Internationalizing GNU: the maintainer side] +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + + It contains some statements that are harsh and, I believe, + not true. The practice of using gettext to mark strings is + *not* just "for the time being." + + Fran\cois: Could you work with rms to update the GNU coding + standards to describe what GNUers needs to be do to make their + GNU programs use GNU Locale. + +I may try, but do not know exactly how to proceed. I also confess +I've rewritten this paragraph twenty times, to merely censor myself. + + We can then post that section of the GNU coding standards, so + all the GNUers know what to do. + +If GNU ever publishes utilities for Native Language Support, their +own documentation should explain how to proceed, and maintainers +should find in there the information they need about what to do. +GNU standards might state the general principle, something like: +``GNU programs and packages should be opened to Native Language +Support (NLS) and, in particular, be able to write their messages +translated into native languages, as selected at run time by +environment variables''. + +-- +François Pinard ``Vivement GNU!'' <pinard@iro.umontreal.ca> +Email lpf@uunet.uu.net for info about the League for Programming Freedom. + + +1,, +Mail-from: From IRO.UMontreal.CA!pinard Tue May 2 05:16:32 1995 +Return-Path: <IRO.UMontreal.CA!pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0s6E4E-0000CaC; Tue, 2 May 95 05:16 EDT +Received: from lagrande.iro.umontreal.ca (lagrande.IRO.UMontreal.CA [132.204.32.32]) by iros1.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id AAA19507 for <icule!pinard>; Tue, 2 May 1995 00:02:38 -0400 +Received: (from pinard@localhost) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) id AAA00659 for icule!pinard; Tue, 2 May 1995 00:02:37 -0400 +Received: from saguenay.IRO.UMontreal.CA (saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id AAA00657 for <pinard@lagrande.IRO.UMontreal.CA>; Tue, 2 May 1995 00:02:34 -0400 +Received: from mole.gnu.ai.mit.edu (mole.gnu.ai.mit.edu [128.52.46.33]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id AAA08792 for <pinard@iro.umontreal.ca>; Tue, 2 May 1995 00:02:33 -0400 +Received: by mole.gnu.ai.mit.edu (8.6.12/8.6.12GNU) id AAA07143; Tue, 2 May 1995 00:02:31 -0400 +Date: Tue, 2 May 1995 00:02:31 -0400 +Message-Id: <199505020402.AAA07143@mole.gnu.ai.mit.edu> +From: Richard Stallman <rms@gnu.ai.mit.edu> +To: pinard@IRO.UMontreal.CA +In-reply-to: <m0s67Vl-00008NC@icule> (pinard@iro.umontreal.ca) +Subject: Re: [pinard@iro.umontreal.ca: Internationalizing GNU: the maintainer side] + +*** EOOH *** +Date: Tue, 2 May 1995 00:02:31 -0400 +From: Richard Stallman <rms@gnu.ai.mit.edu> +To: pinard@IRO.UMontreal.CA +In-reply-to: <m0s67Vl-00008NC@icule> (pinard@iro.umontreal.ca) +Subject: Re: [pinard@iro.umontreal.ca: Internationalizing GNU: the maintainer side] + + ``GNU programs and packages should be opened to Native Language + Support (NLS) and, in particular, be able to write their messages + translated into native languages, as selected at run time by + environment variables''. + +I think that is too vague to be useful. I'd rather put in some +variant of what you sent before. But I don't have time right now +to fix it. + + +1, answered, edited,, +Mail-from: From IRO.UMontreal.CA!pinard Wed May 3 00:19:10 1995 +Return-Path: <IRO.UMontreal.CA!pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0s6Vty-0000CSC; Wed, 3 May 95 00:19 EDT +Received: from lagrande.iro.umontreal.ca (lagrande.IRO.UMontreal.CA [132.204.32.32]) by iros1.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id XAA19717 for <icule!pinard>; Tue, 2 May 1995 23:51:54 -0400 +Received: (from pinard@localhost) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) id XAA20985 for icule!pinard; Tue, 2 May 1995 23:51:52 -0400 +Received: from saguenay.IRO.UMontreal.CA (saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id XAA20983 for <pinard@lagrande.IRO.UMontreal.CA>; Tue, 2 May 1995 23:51:49 -0400 +Received: from nz11.rz.uni-karlsruhe.de (nz11.rz.uni-karlsruhe.de [129.13.64.7]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id XAA12985 for <pinard@iro.umontreal.ca>; Tue, 2 May 1995 23:51:15 -0400 +Received: from ipd.info.uni-karlsruhe.de (actually i44ms.info.uni-karlsruhe.de) + by nz11.rz.uni-karlsruhe.de with SMTP (PP); + Wed, 3 May 1995 03:54:26 +0200 +Received: from i44pc2.info.uni-karlsruhe.de (i44pc2.info.uni-karlsruhe.de [129.13.171.31]) + by ipd.info.uni-karlsruhe.de (8.6.4/8.6.4) with SMTP id DAA00768; + Wed, 3 May 1995 03:57:08 +0200 +Message-Id: <199505030157.DAA00768@ipd.info.uni-karlsruhe.de> +To: "ois \"Pinard)\""@rz.uni-karlsruhe.de, meyering@comco.com (Jim Meyering), + eggert@twinsun.com (Paul Eggert), + roland@gnu.ai.mit.edu (Roland McGrath) +Original-To: pinard@iro.umontreal.ca (François Pinard), + meyering@comco.com (Jim Meyering), + eggert@twinsun.com (Paul Eggert), + roland@gnu.ai.mit.edu (Roland McGrath) +PP-Warning: Parse error in original version of preceding To line +Subject: nlsutils-0.4.2 +Date: Wed, 03 May 1995 03:56:24 +0200 +From: Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de> + +*** EOOH *** +To: "ois \"Pinard)\""@rz.uni-karlsruhe.de, meyering@comco.com (Jim Meyering), + eggert@twinsun.com (Paul Eggert), + roland@gnu.ai.mit.edu (Roland McGrath) +Original-To: pinard@iro.umontreal.ca (François Pinard), + meyering@comco.com (Jim Meyering), + eggert@twinsun.com (Paul Eggert), + roland@gnu.ai.mit.edu (Roland McGrath) +PP-Warning: Parse error in original version of preceding To line +Subject: nlsutils-0.4.2 +Date: Wed, 03 May 1995 03:56:24 +0200 +From: Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de> + +I tried hard to limit all external things in the libgintl directory. +You have to copy this, some variation of my code in aclocal.m4 +and acconfig.h. This should be all. + +1, answered,, +Mail-from: From IRO.UMontreal.CA!pinard Thu May 4 08:22:15 1995 +Return-Path: <IRO.UMontreal.CA!pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0s6zv4-0000CSC; Thu, 4 May 95 08:22 EDT +Received: from lagrande.iro.umontreal.ca (lagrande.IRO.UMontreal.CA [132.204.32.32]) by iros1.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id HAA19349 for <icule!pinard>; Thu, 4 May 1995 07:48:32 -0400 +Received: (from pinard@localhost) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) id HAA24822 for icule!pinard; Thu, 4 May 1995 07:47:28 -0400 +Received: from saguenay.IRO.UMontreal.CA (saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id HAA24816 for <pinard@lagrande.IRO.UMontreal.CA>; Thu, 4 May 1995 07:47:25 -0400 +Received: from nz11.rz.uni-karlsruhe.de (nz11.rz.uni-karlsruhe.de [129.13.64.7]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id HAA17159 for <pinard@iro.umontreal.ca>; Thu, 4 May 1995 07:48:25 -0400 +Received: from ipd.info.uni-karlsruhe.de (actually i44ms.info.uni-karlsruhe.de) + by nz11.rz.uni-karlsruhe.de with SMTP (PP); + Thu, 4 May 1995 13:45:17 +0200 +Received: from i44pc2.info.uni-karlsruhe.de (i44pc2.info.uni-karlsruhe.de [129.13.171.31]) + by ipd.info.uni-karlsruhe.de (8.6.4/8.6.4) with SMTP id NAA06097 + for <pinard@iro.umontreal.ca>; Thu, 4 May 1995 13:48:06 +0200 +Message-Id: <199505041148.NAA06097@ipd.info.uni-karlsruhe.de> +To: pinard@IRO.UMontreal.CA +Subject: Re: Path to message? +In-Reply-To: Your message of "Thu, 4 May 95 00:45 EDT" +References: <m0s6snG-00008NC@icule> +X-Mailer: Mew beta version 0.89 on Emacs 19.28.1 +Mime-Version: 1.0 +Content-Type: Text/Plain; charset=iso-8859-1 +Date: Thu, 04 May 1995 13:47:46 +0200 +From: Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de> +Content-Transfer-Encoding: 8bit +X-Original-Encoding: quoted-printable + +*** EOOH *** +To: pinard@IRO.UMontreal.CA +Subject: Re: Path to message? +In-Reply-To: Your message of "Thu, 4 May 95 00:45 EDT" +References: <m0s6snG-00008NC@icule> +Mime-Version: 1.0 +Content-Type: Text/Plain; charset=iso-8859-1 +Date: Thu, 04 May 1995 13:47:46 +0200 +From: Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de> +Content-Transfer-Encoding: 8bit +X-Original-Encoding: quoted-printable + +From: pinard@iro.umontreal.ca (François Pinard) +Subject: Path to message? +Date: Thu, 4 May 95 00:45 EDT + +> Ulrich, always me. I do not understand that xgettext --help writes: +> +> Suchpfad ist: /usr/local/share/nls/src +> +> while /usr/local/share/locale/de/LC_MESSAGES is indeed searched. +> Could we solve this inconsistency? +> + +Not quite. /usr/local/share/locale/de/LC_MESSAGES is the path where +the .mo/.cat files will go. The search path (Suchpfad :) represents +the path to additional directories where other .po files can be found. + +I thought to use this feature for standard .po files for, say, libiberty +etc. Each package would have to translate it again and again but if +we could install this somewhere and use the -x option to exclude this +strings from the generation. + +Perhaps I should use a different description? + +-- Uli +________--------------------------------------------------------------- +\ / Ulrich Drepper / Univ. at Karlsruhe, Germany / CS Dept. / IPD +L\inux/ email: drepper@gnu.ai.mit.edu smail: Rubensstr. 5 + \ / drepper@ipd.info.uni-karlsruhe.de 76149 Karlsruhe + \/1.2.7 ------------------------------------------- Germany -------- + + +1, forwarded, edited,, +Mail-from: From pinard Thu May 4 15:27:13 1995 +Return-Path: <pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0s76YH-00008NC; Thu, 4 May 95 15:27 EDT +Message-Id: <m0s76YH-00008NC@icule> +Date: Thu, 4 May 95 15:27 EDT +From: pinard (=?ISO-8859-1?Q?Fran=E7ois_Pinard?=) +To: ajc@di.uminho.pt +In-reply-to: <9505041601.AA20254@shiva.di.uminho.pt> (ajc@di.uminho.pt) +Subject: Re: tar is ready for pt +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +*** EOOH *** +Date: Thu, 4 May 95 15:27 EDT +From: pinard (François Pinard) +To: ajc@di.uminho.pt +In-reply-to: <9505041601.AA20254@shiva.di.uminho.pt> (ajc@di.uminho.pt) +Subject: Re: tar is ready for pt +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit + +Even if it is not completely official yet in GNU, the format of +translation file is being revised, and the extension is being +changed from `.tt' to `.po'. This should bring the format closer +to one of the few standards in existence for translation files. +Hopefully, we think that translation files will be more easily +manageable afterwards. We do not want to make a religious issue of +this format selection, as each standard has proponents and opponents. +Please help us by being receptive to the format GNU uses. + +Existing `.tt' translation files are being converted to `.po' files +by maintainers. Translators should switch to using the `.po' format, +as soon as possible. This is an easy job. The `.po' translation +file format is quite affordable. Schematically, it looks like: + + msgid STRING-TO-TRANSLATE + msgstr TRANSLATED-STRING + + msgid STRING-TO-TRANSLATE + msgstr TRANSLATED-STRING + + msgid STRING-TO-TRANSLATE + msgstr TRANSLATED-STRING + [...] + +`msgid' and `msgstr' are kind of keywords, written at the beginning +of a line. Each STRING-TO-TRANSLATE or TRANSLATED-STRING respects +the C syntax for a character string, including the surrounding +quotes, escape sequences, and usual techniques for writing multi-line +C strings. + +Outside strings, white lines and comments may be used freely. +In the schema, white lines preceding the msgid lines are optional. +Comments start at the beginning of a line with `#' and extend until +the end of line. Comments written by translators should have the +initial `#' immediately followed by some white space. If the `#' +is not immediately followed by white space, this comment is most +likely generated and managed by specialized GNU tools. + +There is a conventional, uniform way of presenting a `.po' file, but +a description of this format is not yet available. It will be all +easy to make suggested adjustements at a later time, so do not worry +right now about precise conventions. Further, there are normalizing +tools automating conformance to a great extent, to be published soon. + + And another question: what happens when new versions of the + program are released, with new messages? + +Usually, most GNU packages are pretested before being released. +All teams of translators are made aware of localizable prereleases. +A special tool regenerates a `.po' file with obsolescent strings +commented out, and new strings put in evidence. + +Further, for those of us using GNU Emacs, a special editing mode is +being written for `.po' files, in which mode translators is able +to navigate easily in the `.po' file, find untranslated entries, +examine at will the context of these strings in the program sources, +and also observe other translations already made in other languages, +for the string being translated. + +Teams members should share their translations and resolve linguistic +or terminological issues. When they reach something satisfying, +the team should formally submit the translation to the package +maintainer for the final release. The precise formalities are not +organized yet, and there are many details to clear up. Some legal +aspects also have to be addressed, this is under study right now. + +Special means should be used for transiting translation files +over email. The simplest way is using GNU shar in default mode, +or else, uuencoding the `.po' file prior to mailing. + +-- +François Pinard ``Vivement GNU!'' <pinard@iro.umontreal.ca> +Email lpf@uunet.uu.net for info about the League for Programming Freedom. + + +1, edited,, +Mail-from: From IRO.UMontreal.CA!pinard Thu Apr 20 16:54:03 1995 +Return-Path: <IRO.UMontreal.CA!pinard> +Received: by icule (Smail3.1.28.1 #1) + id m0s23Ea-0000CxC; Thu, 20 Apr 95 16:53 EDT +Received: from lagrande.iro.umontreal.ca (lagrande.IRO.UMontreal.CA [132.204.32.32]) by iros1.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id KAA12085 for <icule!pinard>; Thu, 20 Apr 1995 10:13:02 -0400 +Received: (from pinard@localhost) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) id KAA08298 for icule!pinard; Thu, 20 Apr 1995 10:12:34 -0400 +Received: from saguenay.IRO.UMontreal.CA (saguenay32.IRO.UMontreal.CA [132.204.32.54]) by lagrande.iro.umontreal.ca (8.6.9/8.6.9) with ESMTP id KAA08254 for <pinard@lagrande.IRO.UMontreal.CA>; Thu, 20 Apr 1995 10:10:49 -0400 +Received: from nz11.rz.uni-karlsruhe.de (nz11.rz.uni-karlsruhe.de [129.13.64.7]) by saguenay.IRO.UMontreal.CA (8.6.9/8.6.9) with ESMTP id KAA20778 for <pinard@iro.umontreal.ca>; Thu, 20 Apr 1995 10:10:25 -0400 +Received: from ipd.info.uni-karlsruhe.de (actually i44ms.info.uni-karlsruhe.de) + by nz11.rz.uni-karlsruhe.de with SMTP (PP); + Thu, 20 Apr 1995 16:05:34 +0200 +Received: from i44pc2.info.uni-karlsruhe.de (i44pc2.info.uni-karlsruhe.de [129.13.171.31]) + by ipd.info.uni-karlsruhe.de (8.6.4/8.6.4) with SMTP id QAA28513; + Thu, 20 Apr 1995 16:08:10 +0200 +Message-Id: <199504201408.QAA28513@ipd.info.uni-karlsruhe.de> +To: pinard@IRO.UMontreal.CA (Francois Pinard), + meyering@comco.com (Jim Meyering), + roland@gnu.ai.mit.edu (Roland McGrath) +Subject: more points to discuss +X-Mailer: Mew beta version 0.89 on Emacs 19.28.1 +Mime-Version: 1.0 +Content-Type: Text/Plain; charset=iso-8859-1 +Date: Thu, 20 Apr 1995 16:08:55 +0200 +From: Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de> +Content-Transfer-Encoding: 8bit +X-Original-Encoding: quoted-printable + +*** EOOH *** +To: pinard@IRO.UMontreal.CA (Francois Pinard), + meyering@comco.com (Jim Meyering), + roland@gnu.ai.mit.edu (Roland McGrath) +Subject: more points to discuss +Mime-Version: 1.0 +Content-Type: Text/Plain; charset=iso-8859-1 +Date: Thu, 20 Apr 1995 16:08:55 +0200 +From: Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de> +Content-Transfer-Encoding: 8bit +X-Original-Encoding: quoted-printable + +BTW my implementation will be able to process a lot of strange situation: +- strings in preprocessor macros +- something like gettext ("jkh" "jkhlk") +or even +- gettext ("jkkjh\ +sdfsdf") + +1, edited,, +Received: from titan.comco.com (root@titan.comco.com [198.214.63.11]) by idefix.comco.com (8.6.9/8.6.9) with ESMTP id QAA16073 for <meyering@idefix.comco.com>; Sat, 19 Nov 1994 16:03:48 -0600 +Received: from alcor.twinsun.com (alcor.twinsun.com [198.147.65.1]) by titan.comco.com (8.6.9/8.6.9) with ESMTP id QAA03006 for <meyering@comco.com>; Sat, 19 Nov 1994 16:04:38 -0600 +Received: from twinsun.com (twinsun.twinsun.com [192.54.239.2]) by alcor.twinsun.com (8.6.5/8.6.5) with SMTP id NAA19013; Sat, 19 Nov 1994 13:55:18 -0800 +Received: from spot.twinsun.com by twinsun.com (4.1/SMI-4.1) + id AA29144; Sat, 19 Nov 94 14:01:01 PST +Received: by spot.twinsun.com (4.1/SMI-4.1) + id AA02990; Sat, 19 Nov 94 14:01:00 PST +From: eggert@twinsun.com (Paul Eggert) +Message-Id: <9411192201.AA02990@spot.twinsun.com> +Date: 19 Nov 1994 14:00:59 -0800 +To: rms@gnu.ai.mit.edu (Richard Stallman) +Cc: meyering@comco.com, pdcruze@orac.iinet.com.au +Subject: Re: glocale and diffutils +Status: RO + +*** EOOH *** +From: eggert@twinsun.com (Paul Eggert) +Date: 19 Nov 1994 14:00:59 -0800 +To: rms@gnu.ai.mit.edu (Richard Stallman) +Cc: meyering@comco.com, pdcruze@orac.iinet.com.au +Subject: Re: glocale and diffutils + +The Uniforum proposal addresses this problem by partitioning message +catalogs into ``textdomains''. Each textdomain can be maintained +separately. Programs can share textdomains. Messages in different +textdomains cannot clash. With diffutils, for example, I would expect +one textdomain for diffutils programs and another for libc. The main +module would use the default textdomain and invoke `gettext ("No +newline at end of file")' just as diffutils-2.7.1 does; libc modules +would use a system textdomain and would invoke something like +`dgettext ("SYS_libc", "No such file or directory")'. + + +
\ No newline at end of file diff --git a/doc/Admin/solaris.msgfmt b/doc/Admin/solaris.msgfmt new file mode 100644 index 0000000..fc46c2d --- /dev/null +++ b/doc/Admin/solaris.msgfmt @@ -0,0 +1,21 @@ +talisker% /usr/bin/msgfmt -h +usage: msgfmt [-v] [-o filename] [files ... ] + + +talisker% /usr/bin/xgettext -h +Usage: xgettext [-a [-x exclude-file]] [-jns][-c comment-tag] + [-d default-domain] [-m prefix] [-M suffix] [-p pathname] files ... + xgettext -h + +-a find ALL strings +-c <comment-tag> get comments containing <flag> +-d <default-domain> use <default-domain> for default domain +-h Help +-j update existing file with the current result +-M <suffix> fill in msgstr with msgid<suffix> +-m <prefix> fill in msgstr with <prefix>msgid +-n line# file name and line number info in output +-p <pathname> use <pathname> for output file directory +-s generate sorted output files +-x <exclude-file> exclude strings in file <exclude-file> from output +- read stdin, use as a filter (input only) diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..3ec5712 --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,426 @@ +2000-05-06 Ulrich Drepper <drepper@redhat.com> + + * nls.texi: Add section about "Using gettext in own code". + +1999-10-11 Ulrich Drepper <drepper@cygnus.com> + + * gettext.texi: Fix use of @xref. + +1997-09-06 02:13 Ulrich Drepper <drepper@cygnus.com> + + * gettext.texi: Fix names of autoconf macros now that they are in + automake. + File NLS is now named ABOUT-NLS. + Reported by Bruno Haible <haible@ilog.fr>. + + * nls.texi: Better description of --with-included-gettext. + +1997-08-01 15:50 Ulrich Drepper <drepper@cygnus.com> + + * Makefile.am (AUTOMAKE_OPTIONS): Require version 1.2. + +1997-04-12 17:45 Ulrich Drepper <drepper@cygnus.com> + + * mdate-sh: Update from libit version. + + * mdate-sh: Handle ls output with file type in ls output is + starting with -. + +1997-04-05 18:14 Ulrich Drepper <drepper@cygnus.com> + + * mdate-sh: Use ls command with -d so that we also can handle + directories. Patch by Bruno Haible. + +1997-03-11 16:24 Ulrich Drepper <drepper@cygnus.com> + + * nls.texi: Don't mention removed translation teams anymore. + +Sat Dec 7 17:53:26 1996 Ulrich Drepper <drepper@cygnus.com> + + * gettext.texi: We don't need the hack for getting the cedille + character anymore. + +Tue Dec 3 15:46:09 1996 Ulrich Drepper <drepper@cygnus.com> + + * Makefile.am (EXTRA_DIST): texinfo.tex is now automatically + distributed. + +Sun Aug 18 16:55:02 1996 Ulrich Drepper <drepper@myware.rz.uni-karlsruhe.de> + + * nls.texi: Set STATUS to August. + +Mon Jun 17 02:29:15 1996 Ulrich Drepper <drepper@myware.rz.uni-karlsruhe.de> + + * gettext.texi: More small fixes. + +Sat Jun 15 16:55:00 1996 Ulrich Drepper <drepper@myware.rz.uni-karlsruhe.de> + + * nls.texi, gettext.texi: Some better words by François Pinard. + +Fri Jun 14 18:47:23 1996 Santiago Vila Doncel <sanvila@unex.es> + + * gettext.texi: Correct a few typos. + +Tue Jun 11 19:31:16 1996 Ulrich Drepper <drepper@cygnus.com> + + * gettext.texi: A few corrections by Thomas Esken. + +Tue Jun 11 15:29:56 1996 Ulrich Drepper <drepper@cygnus.com> + + * Makefile.am (AUTOMAKE_OPTIONS): Add variable. Must be defined + in all subdirs. + +Tue Jun 4 03:43:17 1996 Ulrich Drepper <drepper@cygnus.com> + + * gettext.texi: + Tons of changes. A first step for a real, uptodate manual. + +Sun Jun 2 21:21:18 1996 Ulrich Drepper <drepper@cygnus.com> + + * iso-apdx.sed, Makefile.am, ISO_639: Initial revision. + +Sun May 26 18:21:25 1996 Ulrich Drepper <drepper@cygnus.com> + + * nls.texi: Add Arabic. + +Fri May 24 18:24:56 1996 Ulrich Drepper <drepper@cygnus.com> + + * nls.texi: Add Ukrainian. + +Tue May 21 14:25:02 1996 Ulrich Drepper <drepper@cygnus.com> + + * nls.texi: Fix typo: outself -> ourself. + + * nls.texi: Correct Indonesian. + Add Slovenian and Hungarian. + +Sun May 19 15:08:24 1996 Ulrich Drepper <drepper@cygnus.com> + + * nls.texi: Update language list. Add Hebrew and Latin. + +Sat May 4 00:41:17 1996 Ulrich Drepper <drepper@cygnus.com> + + * nls.texi: Rewording by François Pinard. + + * nls.texi: Change explicitely' to `explicitly'. By François Pinard. + +Fri May 3 17:21:48 1996 Ulrich Drepper <drepper@cygnus.com> + + * matrix.texi: 9605031921 + +Wed Apr 10 22:04:29 1996 Ulrich Drepper <drepper@myware> + + * nls.texi: matrix.texi now contains table commands. + + * matrix.texi: Update for 960410. + +Wed Apr 10 21:58:17 1996 François Pinard <pinard@iro.umontreal.ca> + + * nls.texi: Add Korean to list of languages. + +Tue Apr 9 23:28:08 1996 François Pinard <pinard@iro.umontreal.ca> + + * nls.texi: Some better words. + +Sat Apr 6 11:13:18 1996 Ulrich Drepper <drepper@myware> + + * Makefile.in (DISTFILES): Add matrix.texi. Reported by François + Pinard. + +Wed Apr 3 23:40:29 1996 François Pinard <pinard@iro.umontreal.ca> + + * nls.texi: Correct typo: ones -> one. + +Tue Apr 2 18:53:01 1996 Ulrich Drepper <drepper@myware> + + * Makefile.in (all-gettext): New goal. Same as all. + +Tue Apr 2 16:13:11 1996 Ulrich Drepper <drepper@myware> + + * nls.texi: + Document change in aclocal.m4. Describe --with-catgets option. + +Mon Mar 25 23:21:49 1996 Ulrich Drepper <drepper@myware> + + * Makefile.in (DISTFILES): Append iso-apdx.sed, ISO_639, + iso-apdx.texi. + (gettext.info, gettext.dvi): Depend on iso-apdx.texi. + (iso-apdx.texi): New rules. Create file from ISO_639. + +Mon Mar 25 02:55:23 1996 François Pinard <pinard@iro.umontreal.ca> + + * gettext.texi: Latest update of PO mode documentation. + +Sat Mar 23 14:07:57 1996 François Pinard <pinard@iro.umontreal.ca> + + * gettext.texi: Added changes concerning PO mode changes. + +Sat Mar 23 13:46:49 1996 Frank Donahoe <fdonahoe@wilkes1.wilkes.edu> + + * gettext.texi: Fixed many problems with the English language. + +Wed Mar 13 21:06:17 1996 Ulrich Drepper <drepper@myware> + + * nls.texi: Changed gnu-translation@prep to gnu-translation@gnu. + Suggested by Franc,ois Pinard. + +Fri Mar 1 23:46:28 1996 Ulrich Drepper <drepper@myware> + + * nls.texi: STATUS is 1996, not 1995. + +Thu Feb 15 03:45:30 1996 Ulrich Drepper <drepper@myware> + + * gettext.texi: Update documentation for + - `--force' option + - `-d -' option + - new intl/po subdir handling + +Mon Feb 12 01:33:49 1996 Ulrich Drepper <drepper@myware> + + * nls.texi: STATUS is January. + + * nls.texi: Omitted pl at lower side. + + * nls.texi: Add pl for gettext to matrix. + +Fri Dec 29 14:00:17 1995 Ulrich Drepper <drepper@myware> + + * nls.texi: Incorporate some improvements by Franc,ois Pinard. + +Sun Dec 24 14:30:49 1995 Ulrich Drepper <drepper@myware> + + * nls.texi: Small corrections. + Updte table for ko translation of gettext. + +Tue Dec 19 22:13:40 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (Makefile): Explicitly use $(SHELL) for running + shell scripts. + +Fri Dec 15 19:34:50 1995 Karl Eichwalder <ke@ke.central.de> + + * gettext.texi: Correct list of needed macros form aclocal.m4. + +Mon Dec 4 16:19:29 1995 Ulrich Drepper <drepper@myware> + + * nls.texi (STATUS): Set to November. + +Mon Dec 4 16:14:18 1995 Ulrich Drepper <drepper@myware> + + * nls.texi: Update matrix for official release. + +Sun Nov 26 01:22:07 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Fix some typos. + +Sat Nov 25 02:45:46 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (version.texi): Also depend on ../configure.in. + +Thu Nov 23 01:26:35 1995 Ulrich Drepper <drepper@myware> + + * nls.texi: + Change README.NLS to ABOUT-NLS. Reported by Franc,ois Pinard. + +Tue Nov 14 12:43:22 1995 Ulrich Drepper <drepper@myware> + + * nls.texi: Mention Japanese translation for shar in table. + +Thu Nov 9 01:14:49 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: + Document new option --directory and --files-from of xgettext program. + +Tue Nov 7 10:54:43 1995 Ulrich Drepper <drepper@myware> + + * nls.texi: CLISP now uses GNU gettext. + +Mon Nov 6 17:05:39 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in: Some more cleanups by Franc,ois Pinard. + +Mon Nov 6 00:36:37 1995 Ulrich Drepper <drepper@> + + * nls.texi: Add comment about problems with systems which have GNU + gettext previously installed. + +Sun Nov 5 21:56:51 1995 Ulrich Drepper <drepper@myware> + + * nls.texi: + Advise about always using GNU gettext moved to here from ../README. + + * gettext.texi: Fix some typos reported by Franc,ois Pinard. + In descripton of _N change the name to N_. + + * Makefile.in (gettext.info): + Remove old .info* files before generating new ones. + (stamp-vti): Remove old stamp before generating new one. + +Sun Nov 5 19:40:11 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (dist-gettext): Make synonym for dist. + +Sun Nov 5 17:59:31 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (DISTFILES): Add nls.texi. + + * nls.texi: Initial revision. + + * gettext.texi: Protect RFC and number by @w. + +Sun Nov 5 11:38:00 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (dist): Suppress error message when ln failed. + Remove Emacs local variable definition. + (dist): Get files from $(srcdir) explicitly. + + * gettext.texi: Add some comments about gettext_noop and _N. + Describe defaults keywords for -k option of xgettext. + +Fri Nov 3 00:20:35 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Some small changes by Franc,ois. + +Sat Oct 28 23:26:28 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: + Add warning about language changing and not using GNU gettext library. + +Sat Oct 28 17:15:07 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Run spell checker. :-) It was necessary. + + * gettext.texi: Document usage of libintl in other programs. + Describe changing of language in programs. + +Sun Sep 17 23:16:16 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Remove references to ISO 639 in description of + locale variable settings. + +Wed Aug 23 20:49:57 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Applied Franc,ois' patch from 950821. + +Sat Aug 19 17:41:06 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in: Make only install-data depend on `all'. + + * Makefile.in (install-src): + Make behave like install. I.e. really install the manual. + +Fri Aug 18 12:33:43 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Changes of 950817 by Franc,ois Pinard. + +Mon Aug 14 23:52:20 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (install-src): New no-op goal. + +Tue Aug 8 01:39:45 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: + Add description of dcgettext() optimization for gcc-2.7. + +Fri Aug 4 15:47:10 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (dist): Remove `copying instead' message. + +Tue Aug 1 15:58:17 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Some typos fixed. Email address update for Eugene + H. Dorr. By Franc,ois Pinard. + + * Makefile.in (stamp-vti): + Use $(SHELL) and make compilation offside $(srcdir) possible. + +Tue Aug 1 08:51:30 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (install-data): Use sed instead of expr to get basename. + +Sun Jul 30 22:17:14 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Minor corrections to menus and typos by Franc,ois. + Some more words about LIBS rule in src/Makefile.in. + PO mode file is now installed automatically. + +Wed Jul 26 01:00:11 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: + Includes latest of Franc,ois' changes for the maintainer chapter. + Many little changes and addons. + +Mon Jul 24 00:51:38 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Typo changes by Franc,ois. + Added section about special cases in translatable strings. + Added section about changing Makefiles for Maintainers. + Various minor addons. + +Wed Jul 19 02:05:45 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: + Fix typo: keywoards -> keywords. Reported by Franc,ois Pinard. + + * gettext.texi: + Franc,ois added description of the last changes in Emacs PO mode + which allow marking translatable strings in C sources. + +Tue Jul 18 21:25:44 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (DISTFILES): Now we have again gettext.info-[1-4]. + + * gettext.texi (Comparison): + Some points on comparing catgets vs. gettext are written. + +Mon Jul 17 01:03:49 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: Typo fixed. Reported by Franc,ois Pinard. + +Sun Jul 16 13:25:05 1995 Ulrich Drepper <drepper@myware> + + * gettext.texi: + Latest version for 0.7.4. Changes all by Franc,ois Pinard. + +Sun Jul 16 00:17:28 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (DISTFILES): + With the current makeinfo (1.63) there are only gettext.info-[123] + produced. Remove gettext.info-4. Reported by Erik Backus. + +Thu Jul 13 01:41:14 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (check): New no-op goal. + + * gettext.texi: Version of 950712 by Franc,ois. + +Wed Jul 12 00:32:58 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (DISTFILES): now we have gettext.info{,-[1-4]} + + * gettext.texi: First version after rewrite by Franc,ois Pinard. + +Mon Jul 3 23:36:25 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in: Correct for new manual with NLS and po-mode chapter. + Do construct po-mode.{texi,dvi} use nls.texi. + Last correction on install goal was wrong. + Correct installation and unistallation rules. + + * gettext.texi: Version with po-mode and NLS chapter. + Minor changes by Franc,ois. + + * gettext.texi: Make NLS part an include file. + +Sun Jul 2 12:32:37 1995 Ulrich Drepper <drepper@myware> + + * Makefile.in (DISTFILES): fix typo. + + * gettext.texi: some more things written about using GNU gettext + in own projects. + +Sun Jul 2 01:47:02 1995 Ulrich Drepper <drepper@myware> + + * First official release. This directory now contains a very + preliminary version of the gettext manual with a quite complete + chapter for todays Emacs PO mode by Franc,ois Pinard. diff --git a/doc/ISO_639 b/doc/ISO_639 new file mode 100644 index 0000000..c90684f --- /dev/null +++ b/doc/ISO_639 @@ -0,0 +1,180 @@ +Technical contents of ISO 639:1988 (E/F) +"Code for the representation of names of languages". + +Typed by Keld.Simonsen@dkuug.dk 1990-11-30 +Minor corrections, 1992-09-08 by Keld Simonsen +Sundanese corrected, 1992-11-11 by Keld Simonsen +Telugu corrected, 1995-08-24 by Keld Simonsen +Hebrew, Indonesian, Yiddish corrected 1995-10-10 by Michael Everson +Inuktitut, Uighur, Zhuang added 1995-10-10 by Michael Everson +Sinhalese corrected, 1995-10-10 by Michael Everson +Faeroese corrected to Faroese, 1995-11-18 by Keld Simonsen + +Two-letter lower-case symbols are used. +The Registration Authority for ISO 639 is Infoterm, Osterreichisches +Normungsinstitut (ON), Postfach 130, A-1021 Vienna, Austria. + +aa Afar +ab Abkhazian +af Afrikaans +am Amharic +ar Arabic +as Assamese +ay Aymara +az Azerbaijani + +ba Bashkir +be Byelorussian +bg Bulgarian +bh Bihari +bi Bislama +bn Bengali; Bangla +bo Tibetan +br Breton + +ca Catalan +co Corsican +cs Czech +cy Welsh + +da Danish +de German +dz Bhutani + +el Greek +en English +eo Esperanto +es Spanish +et Estonian +eu Basque + +fa Persian +fi Finnish +fj Fiji +fo Faroese +fr French +fy Frisian + +ga Irish +gd Scots Gaelic +gl Galician +gn Guarani +gu Gujarati + +ha Hausa +he Hebrew (formerly iw) +hi Hindi +hr Croatian +hu Hungarian +hy Armenian + +ia Interlingua +id Indonesian (formerly in) +ie Interlingue +ik Inupiak +is Icelandic +it Italian +iu Inuktitut + +ja Japanese +jw Javanese + +ka Georgian +kk Kazakh +kl Greenlandic +km Cambodian +kn Kannada +ko Korean +ks Kashmiri +ku Kurdish +ky Kirghiz + +la Latin +ln Lingala +lo Laothian +lt Lithuanian +lv Latvian, Lettish + +mg Malagasy +mi Maori +mk Macedonian +ml Malayalam +mn Mongolian +mo Moldavian +mr Marathi +ms Malay +mt Maltese +my Burmese + +na Nauru +ne Nepali +nl Dutch +no Norwegian + +oc Occitan +om (Afan) Oromo +or Oriya + +pa Punjabi +pl Polish +ps Pashto, Pushto +pt Portuguese + +qu Quechua + +rm Rhaeto-Romance +rn Kirundi +ro Romanian +ru Russian +rw Kinyarwanda + +sa Sanskrit +sd Sindhi +sg Sangro +sh Serbo-Croatian +si Sinhalese +sk Slovak +sl Slovenian +sm Samoan +sn Shona +so Somali +sq Albanian +sr Serbian +ss Siswati +st Sesotho +su Sundanese +sv Swedish +sw Swahili + +ta Tamil +te Telugu +tg Tajik +th Thai +ti Tigrinya +tk Turkmen +tl Tagalog +tn Setswana +to Tonga +tr Turkish +ts Tsonga +tt Tatar +tw Twi + +ug Uighur +uk Ukrainian +ur Urdu +uz Uzbek + +vi Vietnamese +vo Volapuk + +wo Wolof + +xh Xhosa + +yi Yiddish (formerly ji) +yo Yoruba + +za Zhuang +zh Chinese +zu Zulu diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..661c978 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,32 @@ +## Makefile for the doc subdirectory of the GNU NLS Utilities +## Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +## +## 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, 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. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +## Process this file with automake to produce Makefile.in. + +AUTOMAKE_OPTIONS = 1.2 gnits + +SED = sed + +info_TEXINFOS = gettext.texi +gettext_TEXINFOS = iso-apdx.texi + +EXTRA_DIST = iso-apdx.sed ISO_639 nls.texi matrix.texi + +iso-apdx.texi: ISO_639 iso-apdx.sed + $(SED) -f $(srcdir)/iso-apdx.sed $(srcdir)/ISO_639 > iso-apdx.tmp + rm -f $(srcdir)/iso-apdx.texi + mv iso-apdx.tmp $(srcdir)/iso-apdx.texi diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..509f1fd --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,370 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +ACLOCAL_VERSION = @ACLOCAL_VERSION@ +AS = @AS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +DATADIRNAME = @DATADIRNAME@ +DLLTOOL = @DLLTOOL@ +EMACS = @EMACS@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LIBOBJS = @LIBOBJS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +aclocaldir = @aclocaldir@ +l = @l@ +lispdir = @lispdir@ + +AUTOMAKE_OPTIONS = 1.2 gnits + +SED = sed + +info_TEXINFOS = gettext.texi +gettext_TEXINFOS = iso-apdx.texi + +EXTRA_DIST = iso-apdx.sed ISO_639 nls.texi matrix.texi +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +TEXI2DVI = texi2dvi +INFO_DEPS = gettext.info +DVIS = gettext.dvi +TEXINFOS = gettext.texi +DIST_COMMON = $(gettext_TEXINFOS) ChangeLog Makefile.am Makefile.in \ +mdate-sh stamp-vti texinfo.tex version.texi + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +.SUFFIXES: .dvi .info .ps .texi .texinfo .txi +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnits doc/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +$(srcdir)/version.texi: stamp-vti + @: + +$(srcdir)/stamp-vti: gettext.texi $(top_srcdir)/configure.in + @echo "@set UPDATED `$(SHELL) $(srcdir)/mdate-sh $(srcdir)/gettext.texi`" > vti.tmp + @echo "@set EDITION $(VERSION)" >> vti.tmp + @echo "@set VERSION $(VERSION)" >> vti.tmp + @cmp -s vti.tmp $(srcdir)/version.texi \ + || (echo "Updating $(srcdir)/version.texi"; \ + cp vti.tmp $(srcdir)/version.texi) + -@rm -f vti.tmp + @cp $(srcdir)/version.texi $@ + +mostlyclean-vti: + -rm -f vti.tmp + +clean-vti: + +distclean-vti: + +maintainer-clean-vti: + -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi + +gettext.info: gettext.texi version.texi $(gettext_TEXINFOS) +gettext.dvi: gettext.texi version.texi $(gettext_TEXINFOS) + + +DVIPS = dvips + +.texi.info: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) `echo $< | sed 's,.*/,,'` + +.texi.dvi: + TEXINPUTS=.:$$TEXINPUTS \ + MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< + +.texi: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) `echo $< | sed 's,.*/,,'` + +.texinfo.info: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) `echo $< | sed 's,.*/,,'` + +.texinfo: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) `echo $< | sed 's,.*/,,'` + +.texinfo.dvi: + TEXINPUTS=.:$$TEXINPUTS \ + MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< + +.txi.info: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) `echo $< | sed 's,.*/,,'` + +.txi.dvi: + TEXINPUTS=.:$$TEXINPUTS \ + MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< + +.txi: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) `echo $< | sed 's,.*/,,'` +.dvi.ps: + $(DVIPS) $< -o $@ + +install-info-am: $(INFO_DEPS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(infodir) + @list='$(INFO_DEPS)'; \ + for file in $$list; do \ + d=$(srcdir); \ + for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \ + if test -f $$d/$$ifile; then \ + echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \ + $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \ + else : ; fi; \ + done; \ + done + @$(POST_INSTALL) + @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\ + install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\ + done; \ + else : ; fi + +uninstall-info: + $(PRE_UNINSTALL) + @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ + ii=yes; \ + else ii=; fi; \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + test -z "$ii" \ + || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; \ + done + @$(NORMAL_UNINSTALL) + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \ + done + +dist-info: $(INFO_DEPS) + list='$(INFO_DEPS)'; \ + for base in $$list; do \ + d=$(srcdir); \ + for file in `cd $$d && eval echo $$base*`; do \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done; \ + done + +mostlyclean-aminfo: + -rm -f gettext.aux gettext.cp gettext.cps gettext.dvi gettext.fn \ + gettext.fns gettext.ky gettext.kys gettext.ps gettext.log \ + gettext.pg gettext.toc gettext.tp gettext.tps gettext.vr \ + gettext.vrs gettext.op gettext.tr gettext.cv gettext.cn + +clean-aminfo: + +distclean-aminfo: + +maintainer-clean-aminfo: + cd $(srcdir) && for i in $(INFO_DEPS); do \ + rm -f $$i; \ + if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \ + rm -f $$i-[0-9]*; \ + fi; \ + done +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = doc + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnits doc/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info +info-am: $(INFO_DEPS) +info: info-am +dvi-am: $(DVIS) +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: install-info-am +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-info +uninstall: uninstall-am +all-am: Makefile $(INFO_DEPS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(infodir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-vti mostlyclean-aminfo mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-vti clean-aminfo clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-vti distclean-aminfo distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-vti maintainer-clean-aminfo \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-vti distclean-vti clean-vti maintainer-clean-vti \ +install-info-am uninstall-info mostlyclean-aminfo distclean-aminfo \ +clean-aminfo maintainer-clean-aminfo tags distdir info-am info dvi-am \ +dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +iso-apdx.texi: ISO_639 iso-apdx.sed + $(SED) -f $(srcdir)/iso-apdx.sed $(srcdir)/ISO_639 > iso-apdx.tmp + rm -f $(srcdir)/iso-apdx.texi + mv iso-apdx.tmp $(srcdir)/iso-apdx.texi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/gettext.info b/doc/gettext.info new file mode 100644 index 0000000..51af348 --- /dev/null +++ b/doc/gettext.info @@ -0,0 +1,126 @@ +This is Info file gettext.info, produced by Makeinfo version 1.68 from +the input file gettext.texi. + +INFO-DIR-SECTION GNU Gettext Utilities +START-INFO-DIR-ENTRY +* Gettext: (gettext). GNU gettext utilities. +* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext. +* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files. +* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one. +* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file. +END-INFO-DIR-ENTRY + + This file provides documentation for GNU `gettext' utilities. It +also serves as a reference for the free Translation Project. + + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +Indirect: +gettext.info-1: 1431 +gettext.info-2: 48351 +gettext.info-3: 95765 +gettext.info-4: 145601 +gettext.info-5: 195230 + +Tag Table: +(Indirect) +Node: Top1431 +Node: Introduction6625 +Node: Why8481 +Node: Concepts11727 +Node: Aspects15140 +Node: Files21196 +Node: Overview23464 +Node: Basics34088 +Node: Installation34918 +Node: PO Files36652 +Node: Main PO Commands43407 +Node: Entry Positioning48351 +Node: Normalizing53603 +Node: Sources58055 +Node: Triggering59326 +Node: Mark Keywords61682 +Node: Marking65232 +Node: c-format72873 +Node: Special cases76624 +Node: Initial79487 +Node: xgettext Invocation79809 +Node: C Sources Context83036 +Node: Compendium88015 +Node: Updating88718 +Node: msgmerge Invocation89358 +Node: Translated Entries89532 +Node: Fuzzy Entries90824 +Node: Untranslated Entries93926 +Node: Obsolete Entries95765 +Node: Modifying Translations98897 +Node: Modifying Comments106715 +Node: Subedit111022 +Node: Auxiliary114800 +Node: Binaries117870 +Node: msgfmt Invocation118134 +Node: MO Files120761 +Node: Users128173 +Node: Matrix129654 +Node: Installers130857 +Node: End Users132045 +Node: Programmers132674 +Node: catgets133848 +Node: Interface to catgets135253 +Node: Problems with catgets137254 +Node: gettext138152 +Node: Interface to gettext139393 +Node: Ambiguities141735 +Node: Locating Catalogs144292 +Node: Optimized gettext145601 +Node: Comparison149189 +Node: Using libintl.a154904 +Node: gettext grok155675 +Node: Temp Programmers158534 +Node: Temp Implementations158974 +Node: Temp catgets160340 +Node: Temp WSI162027 +Node: Temp Notes164015 +Node: Translators164504 +Node: Trans Intro 0164883 +Node: Trans Intro 1167532 +Node: Discussions169396 +Node: Organization172551 +Node: Central Coordination174532 +Node: National Teams175660 +Node: Sub-Cultures178172 +Node: Organizational Ideas179091 +Node: Mailing Lists180093 +Node: Information Flow181896 +Node: Maintainers184029 +Node: Flat and Non-Flat185789 +Node: Prerequisites187550 +Node: gettextize Invocation191658 +Node: Adjusting Files195230 +Node: po/POTFILES.in196453 +Node: configure.in197394 +Node: aclocal199521 +Node: acconfig200700 +Node: Makefile201314 +Node: src/Makefile203502 +Node: Conclusion205899 +Node: History206388 +Node: References209848 +Node: Country Codes211403 + +End Tag Table diff --git a/doc/gettext.info-1 b/doc/gettext.info-1 new file mode 100644 index 0000000..2718d25 --- /dev/null +++ b/doc/gettext.info-1 @@ -0,0 +1,999 @@ +This is Info file gettext.info, produced by Makeinfo version 1.68 from +the input file gettext.texi. + +INFO-DIR-SECTION GNU Gettext Utilities +START-INFO-DIR-ENTRY +* Gettext: (gettext). GNU gettext utilities. +* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext. +* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files. +* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one. +* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file. +END-INFO-DIR-ENTRY + + This file provides documentation for GNU `gettext' utilities. It +also serves as a reference for the free Translation Project. + + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gettext.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) + +GNU `gettext' utilities +*********************** + +* Menu: + +* Introduction:: Introduction +* Basics:: PO Files and PO Mode Basics +* Sources:: Preparing Program Sources +* Initial:: Making the Initial PO File +* Updating:: Updating Existing PO Files +* Binaries:: Producing Binary MO Files +* Users:: The User's View +* Programmers:: The Programmer's View +* Translators:: The Translator's View +* Maintainers:: The Maintainer's View +* Conclusion:: Concluding Remarks + +* Country Codes:: ISO 639 country codes + + -- The Detailed Node Listing -- + +Introduction + +* Why:: The Purpose of GNU `gettext' +* Concepts:: I18n, L10n, and Such +* Aspects:: Aspects in Native Language Support +* Files:: Files Conveying Translations +* Overview:: Overview of GNU `gettext' + +PO Files and PO Mode Basics + +* Installation:: Completing GNU `gettext' Installation +* PO Files:: The Format of PO Files +* Main PO Commands:: Main Commands +* Entry Positioning:: Entry Positioning +* Normalizing:: Normalizing Strings in Entries + +Preparing Program Sources + +* Triggering:: Triggering `gettext' Operations +* Mark Keywords:: How Marks Appears in Sources +* Marking:: Marking Translatable Strings +* c-format:: Telling something about the following string +* Special cases:: Special Cases of Translatable Strings + +Making the Initial PO File + +* xgettext Invocation:: Invoking the `xgettext' Program +* C Sources Context:: C Sources Context +* Compendium:: Using Translation Compendiums + +Updating Existing PO Files + +* msgmerge Invocation:: Invoking the `msgmerge' Program +* Translated Entries:: Translated Entries +* Fuzzy Entries:: Fuzzy Entries +* Untranslated Entries:: Untranslated Entries +* Obsolete Entries:: Obsolete Entries +* Modifying Translations:: Modifying Translations +* Modifying Comments:: Modifying Comments +* Auxiliary:: Consulting Auxiliary PO Files + +Producing Binary MO Files + +* msgfmt Invocation:: Invoking the `msgfmt' Program +* MO Files:: The Format of GNU MO Files + +The User's View + +* Matrix:: The Current `ABOUT-NLS' Matrix +* Installers:: Magic for Installers +* End Users:: Magic for End Users + +The Programmer's View + +* catgets:: About `catgets' +* gettext:: About `gettext' +* Comparison:: Comparing the two interfaces +* Using libintl.a:: Using libintl.a in own programs +* gettext grok:: Being a `gettext' grok +* Temp Programmers:: Temporary Notes for the Programmers Chapter + +About `catgets' + +* Interface to catgets:: The interface +* Problems with catgets:: Problems with the `catgets' interface?! + +About `gettext' + +* Interface to gettext:: The interface +* Ambiguities:: Solving ambiguities +* Locating Catalogs:: Locating message catalog files +* Optimized gettext:: Optimization of the *gettext functions + +Temporary Notes for the Programmers Chapter + +* Temp Implementations:: Temporary - Two Possible Implementations +* Temp catgets:: Temporary - About `catgets' +* Temp WSI:: Temporary - Why a single implementation +* Temp Notes:: Temporary - Notes + +The Translator's View + +* Trans Intro 0:: Introduction 0 +* Trans Intro 1:: Introduction 1 +* Discussions:: Discussions +* Organization:: Organization +* Information Flow:: Information Flow + +Organization + +* Central Coordination:: Central Coordination +* National Teams:: National Teams +* Mailing Lists:: Mailing Lists + +National Teams + +* Sub-Cultures:: Sub-Cultures +* Organizational Ideas:: Organizational Ideas + +The Maintainer's View + +* Flat and Non-Flat:: Flat or Non-Flat Directory Structures +* Prerequisites:: Prerequisite Works +* gettextize Invocation:: Invoking the `gettextize' Program +* Adjusting Files:: Files You Must Create or Alter + +Files You Must Create or Alter + +* po/POTFILES.in:: `POTFILES.in' in `po/' +* configure.in:: `configure.in' at top level +* aclocal:: `aclocal.m4' at top level +* acconfig:: `acconfig.h' at top level +* Makefile:: `Makefile.in' at top level +* src/Makefile:: `Makefile.in' in `src/' + +Concluding Remarks + +* History:: History of GNU `gettext' +* References:: Related Readings + + +File: gettext.info, Node: Introduction, Next: Basics, Prev: Top, Up: Top + +Introduction +************ + + This manual is still in *DRAFT* state. Some sections are still + empty, or almost. We keep merging material from other sources + (essentially e-mail folders) while the proper integration of this + material is delayed. + + In this manual, we use *he* when speaking of the programmer or +maintainer, *she* when speaking of the translator, and *they* when +speaking of the installers or end users of the translated program. +This is only a convenience for clarifying the documentation. It is +*absolutely* not meant to imply that some roles are more appropriate to +males or females. Besides, as you might guess, GNU `gettext' is meant +to be useful for people using computers, whatever their sex, race, +religion or nationality! + + This chapter explains the goals sought in the creation of GNU +`gettext' and the free Translation Project. Then, it explains a few +broad concepts around Native Language Support, and positions message +translation with regard to other aspects of national and cultural +variance, as they apply to to programs. It also surveys those files +used to convey the translations. It explains how the various tools +interact in the initial generation of these files, and later, how the +maintenance cycle should usually operate. + + Please send suggestions and corrections to: + + Internet address: + bug-gnu-utils@gnu.org + +Please include the manual's edition number and update date in your +messages. + +* Menu: + +* Why:: The Purpose of GNU `gettext' +* Concepts:: I18n, L10n, and Such +* Aspects:: Aspects in Native Language Support +* Files:: Files Conveying Translations +* Overview:: Overview of GNU `gettext' + + +File: gettext.info, Node: Why, Next: Concepts, Prev: Introduction, Up: Introduction + +The Purpose of GNU `gettext' +============================ + + Usually, programs are written and documented in English, and use +English at execution time to interact with users. This is true not +only of GNU software, but also of a great deal of commercial and free +software. Using a common language is quite handy for communication +between developers, maintainers and users from all countries. On the +other hand, most people are less comfortable with English than with +their own native language, and would prefer to use their mother tongue +for day to day's work, as far as possible. Many would simply *love* to +see their computer screen showing a lot less of English, and far more +of their own language. + + However, to many people, this dream might appear so far fetched that +they may believe it is not even worth spending time thinking about it. +They have no confidence at all that the dream might ever become true. +Yet some have not lost hope, and have organized themselves. The +Translation Project is a formalization of this hope into a workable +structure, which has a good chance to get all of us nearer the +achievement of a truly multi-lingual set of programs. + + GNU `gettext' is an important step for the Translation Project, as +it is an asset on which we may build many other steps. This package +offers to programmers, translators and even users, a well integrated +set of tools and documentation. Specifically, the GNU `gettext' +utilities are a set of tools that provides a framework within which +other free packages may produce multi-lingual messages. These tools +include a set of conventions about how programs should be written to +support message catalogs, a directory and file naming organization for +the message catalogs themselves, a runtime library supporting the +retrieval of translated messages, and a few stand-alone programs to +massage in various ways the sets of translatable strings, or already +translated strings. A special mode for Emacs(1) also helps ease +interested parties into preparing these sets, or bringing them up to +date. + + GNU `gettext' is designed to minimize the impact of +internationalization on program sources, keeping this impact as small +and hardly noticeable as possible. Internationalization has better +chances of succeeding if it is very light weighted, or at least, appear +to be so, when looking at program sources. + + The Translation Project also uses the GNU `gettext' distribution as +a vehicle for documenting its structure and methods. This goes beyond +the strict technicalities of documenting the GNU `gettext' proper. By +so doing, translators will find in a single place, as far as possible, +all they need to know for properly doing their translating work. Also, +this supplemental documentation might also help programmers, and even +curious users, in understanding how GNU `gettext' is related to the +remainder of the Translation Project, and consequently, have a glimpse +at the *big picture*. + + ---------- Footnotes ---------- + + (1) In this manual, all mentions of Emacs refers to either GNU Emacs +or to XEmacs, which people sometimes call FSF Emacs and Lucid Emacs, +respectively. + + +File: gettext.info, Node: Concepts, Next: Aspects, Prev: Why, Up: Introduction + +I18n, L10n, and Such +==================== + + Two long words appear all the time when we discuss support of native +language in programs, and these words have a precise meaning, worth +being explained here, once and for all in this document. The words are +*internationalization* and *localization*. Many people, tired of +writing these long words over and over again, took the habit of writing +"i18n" and "l10n" instead, quoting the first and last letter of each +word, and replacing the run of intermediate letters by a number merely +telling how many such letters there are. But in this manual, in the +sake of clarity, we will patiently write the names in full, each time... + + By "internationalization", one refers to the operation by which a +program, or a set of programs turned into a package, is made aware of +and able to support multiple languages. This is a generalization +process, by which the programs are untied from calling only English +strings or other English specific habits, and connected to generic ways +of doing the same, instead. Program developers may use various +techniques to internationalize their programs. Some of these have been +standardized. GNU `gettext' offers one of these standards. *Note +Programmers::. + + By "localization", one means the operation by which, in a set of +programs already internationalized, one gives the program all needed +information so that it can adapt itself to handle its input and output +in a fashion which is correct for some native language and cultural +habits. This is a particularisation process, by which generic methods +already implemented in an internationalized program are used in +specific ways. The programming environment puts several functions to +the programmers disposal which allow this runtime configuration. The +formal description of specific set of cultural habits for some country, +together with all associated translations targeted to the same native +language, is called the "locale" for this language or country. Users +achieve localization of programs by setting proper values to special +environment variables, prior to executing those programs, identifying +which locale should be used. + + In fact, locale message support is only one component of the cultural +data that makes up a particular locale. There are a whole host of +routines and functions provided to aid programmers in developing +internationalized software and which allow them to access the data +stored in a particular locale. When someone presently refers to a +particular locale, they are obviously referring to the data stored +within that particular locale. Similarly, if a programmer is referring +to "accessing the locale routines", they are referring to the complete +suite of routines that access all of the locale's information. + + One uses the expression "Native Language Support", or merely NLS, +for speaking of the overall activity or feature encompassing both +internationalization and localization, allowing for multi-lingual +interactions in a program. In a nutshell, one could say that +internationalization is the operation by which further localizations +are made possible. + + Also, very roughly said, when it comes to multi-lingual messages, +internationalization is usually taken care of by programmers, and +localization is usually taken care of by translators. + + +File: gettext.info, Node: Aspects, Next: Files, Prev: Concepts, Up: Introduction + +Aspects in Native Language Support +================================== + + For a totally multi-lingual distribution, there are many things to +translate beyond output messages. + + * As of today, GNU `gettext' offers a complete toolset for + translating messages output by C programs. Perl scripts and shell + scripts will also need to be translated. Even if there are today + some hooks by which this can be done, these hooks are not + integrated as well as they should be. + + * Some programs, like `autoconf' or `bison', are able to produce + other programs (or scripts). Even if the generating programs + themselves are internationalized, the generated programs they + produce may need internationalization on their own, and this + indirect internationalization could be automated right from the + generating program. In fact, quite usually, generating and + generated programs could be internationalized independently, as + the effort needed is fairly orthogonal. + + * A few programs include textual tables which might need translation + themselves, independently of the strings contained in the program + itself. For example, RFC 1345 gives an English description for + each character which the `recode' program is able to reconstruct + at execution. Since these descriptions are extracted from the RFC + by mechanical means, translating them properly would require a + prior translation of the RFC itself. + + * Almost all programs accept options, which are often worded out so + to be descriptive for the English readers; one might want to + consider offering translated versions for program options as well. + + * Many programs read, interpret, compile, or are somewhat driven by + input files which are texts containing keywords, identifiers, or + replies which are inherently translatable. For example, one may + want `gcc' to allow diacriticized characters in identifiers or use + translated keywords; `rm -i' might accept something else than `y' + or `n' for replies, etc. Even if the program will eventually make + most of its output in the foreign languages, one has to decide + whether the input syntax, option values, etc., are to be localized + or not. + + * The manual accompanying a package, as well as all documentation + files in the distribution, could surely be translated, too. + Translating a manual, with the intent of later keeping up with + updates, is a major undertaking in itself, generally. + + As we already stressed, translation is only one aspect of locales. +Other internationalization aspects are not currently handled by GNU +`gettext', but perhaps may be handled in future versions. There are +many attributes that are needed to define a country's cultural +conventions. These attributes include beside the country's native +language, the formatting of the date and time, the representation of +numbers, the symbols for currency, etc. These local "rules" are termed +the country's locale. The locale represents the knowledge needed to +support the country's native attributes. + + There are a few major areas which may vary between countries and +hence, define what a locale must describe. The following list helps +putting multi-lingual messages into the proper context of other tasks +related to locales, and also presents some other areas which GNU +`gettext' might eventually tackle, maybe, one of these days. + +*Characters and Codesets* + The codeset most commonly used through out the USA and most English + speaking parts of the world is the ASCII codeset. However, there + are many characters needed by various locales that are not found + within this codeset. The 8-bit ISO 8859-1 code set has most of + the special characters needed to handle the major European + languages. However, in many cases, the ISO 8859-1 font is not + adequate. Hence each locale will need to specify which codeset + they need to use and will need to have the appropriate character + handling routines to cope with the codeset. + +*Currency* + The symbols used vary from country to country as does the position + used by the symbol. Software needs to be able to transparently + display currency figures in the native mode for each locale. + +*Dates* + The format of date varies between locales. For example, Christmas + day in 1994 is written as 12/25/94 in the USA and as 25/12/94 in + Australia. Other countries might use ISO 8061 dates, etc. + + Time of the day may be noted as HH:MM, HH.MM, or otherwise. Some + locales require time to be specified in 24-hour mode rather than + as AM or PM. Further, the nature and yearly extent of the + Daylight Saving correction vary widely between countries. + +*Numbers* + Numbers can be represented differently in different locales. For + example, the following numbers are all written correctly for their + respective locales: + + 12,345.67 English + 12.345,67 French + 1,2345.67 Asia + + Some programs could go further and use different unit systems, like + English units or Metric units, or even take into account variants + about how numbers are spelled in full. + +*Messages* + The most obvious area is the language support within a locale. + This is where GNU `gettext' provides the means for developers and + users to easily change the language that the software uses to + communicate to the user. + + In the near future we see no chance that components of locale +outside of message handling will be made available for use in other +packages. The reason for this is that most modern systems provide a +more or less reasonable support for at least some of the missing +components. Another point is that the GNU `libc' and Linux will get a +new and complete implementation of the whole locale functionality which +could be adopted by system lacking a reasonable locale support. + + +File: gettext.info, Node: Files, Next: Overview, Prev: Aspects, Up: Introduction + +Files Conveying Translations +============================ + + The letters PO in `.po' files means Portable Object, to distinguish +it from `.mo' files, where MO stands for Machine Object. This +paradigm, as well as the PO file format, is inspired by the NLS +standard developed by Uniforum, and implemented by Sun in their Solaris +system. + + PO files are meant to be read and edited by humans, and associate +each original, translatable string of a given package with its +translation in a particular target language. A single PO file is +dedicated to a single target language. If a package supports many +languages, there is one such PO file per language supported, and each +package has its own set of PO files. These PO files are best created by +the `xgettext' program, and later updated or refreshed through the +`msgmerge' program. Program `xgettext' extracts all marked messages +from a set of C files and initializes a PO file with empty +translations. Program `msgmerge' takes care of adjusting PO files +between releases of the corresponding sources, commenting obsolete +entries, initializing new ones, and updating all source line +references. Files ending with `.pot' are kind of base translation +files found in distributions, in PO file format, and `.pox' files are +often temporary PO files. + + MO files are meant to be read by programs, and are binary in nature. +A few systems already offer tools for creating and handling MO files as +part of the Native Language Support coming with the system, but the +format of these MO files is often different from system to system, and +non-portable. They do not necessary use `.mo' for file extensions, but +since system libraries are also used for accessing these files, it +works as long as the system is self-consistent about it. If GNU +`gettext' is able to interface with the tools already provided with +systems, it will consequently let these provided tools take care of +generating the MO files. Or else, if such tools are not found or do +not seem usable, GNU `gettext' will use its own ways and its own format +for MO files. Files ending with `.gmo' are really MO files, when it is +known that these files use the GNU format. + + +File: gettext.info, Node: Overview, Prev: Files, Up: Introduction + +Overview of GNU `gettext' +========================= + + The following diagram summarizes the relation between the files +handled by GNU `gettext' and the tools acting on these files. It is +followed by a somewhat detailed explanations, which you should read +while keeping an eye on the diagram. Having a clear understanding of +these interrelations would surely help programmers, translators and +maintainers. + + Original C Sources ---> PO mode ---> Marked C Sources ---. + | + .---------<--- GNU gettext Library | + .--- make <---+ | + | `---------<--------------------+-----------' + | | + | .-----<--- PACKAGE.pot <--- xgettext <---' .---<--- PO Compendium + | | | ^ + | | `---. | + | `---. +---> PO mode ---. + | +----> msgmerge ------> LANG.pox --->--------' | + | .---' | + | | | + | `-------------<---------------. | + | +--- LANG.po <--- New LANG.pox <----' + | .--- LANG.gmo <--- msgfmt <---' + | | + | `---> install ---> /.../LANG/PACKAGE.mo ---. + | +---> "Hello world!" + `-------> install ---> /.../bin/PROGRAM -------' + + The indication `PO mode' appears in two places in this picture, and +you may safely read it as merely meaning "hand editing", using any +editor of your choice, really. However, for those of you being the +lucky users of Emacs, PO mode has been specifically created for +providing a cozy environment for editing or modifying PO files. While +editing a PO file, PO mode allows for the easy browsing of auxiliary +and compendium PO files, as well as for following references into the +set of C program sources from which PO files have been derived. It has +a few special features, among which are the interactive marking of +program strings as translatable, and the validatation of PO files with +easy repositioning to PO file lines showing errors. + + As a programmer, the first step to bringing GNU `gettext' into your +package is identifying, right in the C sources, those strings which are +meant to be translatable, and those which are untranslatable. This +tedious job can be done a little more comfortably using emacs PO mode, +but you can use any means familiar to you for modifying your C sources. +Beside this some other simple, standard changes are needed to properly +initialize the translation library. *Note Sources::, for more +information about all this. + + For newly written software the strings of course can and should be +marked while writing the it. The `gettext' approach makes this very +easy. Simply put the following lines at the beginning of each file or +in a central header file: + + #define _(String) (String) + #define N_(String) (String) + #define textdomain(Domain) + #define bindtextdomain(Package, Directory) + +Doing this allows you to prepare the sources for internationalization. +Later when you feel ready for the step to use the `gettext' library +simply remove these definitions, include `libintl.h' and link against +`libintl.a'. That is all you have to change. + + Once the C sources have been modified, the `xgettext' program is +used to find and extract all translatable strings, and create an +initial PO file out of all these. This `PACKAGE.pot' file contains all +original program strings. It has sets of pointers to exactly where in +C sources each string is used. All translations are set to empty. The +letter `t' in `.pot' marks this as a Template PO file, not yet oriented +towards any particular language. *Note xgettext Invocation::, for more +details about how one calls the `xgettext' program. If you are +*really* lazy, you might be interested at working a lot more right +away, and preparing the whole distribution setup (*note +Maintainers::.). By doing so, you spare yourself typing the `xgettext' +command, as `make' should now generate the proper things automatically +for you! + + The first time through, there is no `LANG.po' yet, so the `msgmerge' +step may be skipped and replaced by a mere copy of `PACKAGE.pot' to +`LANG.pox', where LANG represents the target language. + + Then comes the initial translation of messages. Translation in +itself is a whole matter, still exclusively meant for humans, and whose +complexity far overwhelms the level of this manual. Nevertheless, a +few hints are given in some other chapter of this manual (*note +Translators::.). You will also find there indications about how to +contact translating teams, or becoming part of them, for sharing your +translating concerns with others who target the same native language. + + While adding the translated messages into the `LANG.pox' PO file, if +you do not have Emacs handy, you are on your own for ensuring that your +efforts fully respect the PO file format, and quoting conventions +(*note PO Files::.). This is surely not an impossible task, as this is +the way many people have handled PO files already for Uniforum or +Solaris. On the other hand, by using PO mode in Emacs, most details of +PO file format are taken care of for you, but you have to acquire some +familiarity with PO mode itself. Besides main PO mode commands (*note +Main PO Commands::.), you should know how to move between entries +(*note Entry Positioning::.), and how to handle untranslated entries +(*note Untranslated Entries::.). + + If some common translations have already been saved into a compendium +PO file, translators may use PO mode for initializing untranslated +entries from the compendium, and also save selected translations into +the compendium, updating it (*note Compendium::.). Compendium files +are meant to be exchanged between members of a given translation team. + + Programs, or packages of programs, are dynamic in nature: users write +bug reports and suggestion for improvements, maintainers react by +modifying programs in various ways. The fact that a package has +already been internationalized should not make maintainers shy of +adding new strings, or modifying strings already translated. They just +do their job the best they can. For the Translation Project to work +smoothly, it is important that maintainers do not carry translation +concerns on their already loaded shoulders, and that translators be +kept as free as possible of programmatic concerns. + + The only concern maintainers should have is carefully marking new +strings as translatable, when they should be, and do not otherwise +worry about them being translated, as this will come in proper time. +Consequently, when programs and their strings are adjusted in various +ways by maintainers, and for matters usually unrelated to translation, +`xgettext' would construct `PACKAGE.pot' files which are evolving over +time, so the translations carried by `LANG.po' are slowly fading out of +date. + + It is important for translators (and even maintainers) to understand +that package translation is a continuous process in the lifetime of a +package, and not something which is done once and for all at the start. +After an initial burst of translation activity for a given package, +interventions are needed once in a while, because here and there, +translated entries become obsolete, and new untranslated entries +appear, needing translation. + + The `msgmerge' program has the purpose of refreshing an already +existing `LANG.po' file, by comparing it with a newer `PACKAGE.pot' +template file, extracted by `xgettext' out of recent C sources. The +refreshing operation adjusts all references to C source locations for +strings, since these strings move as programs are modified. Also, +`msgmerge' comments out as obsolete, in `LANG.pox', those already +translated entries which are no longer used in the program sources +(*note Obsolete Entries::.). It finally discovers new strings and +inserts them in the resulting PO file as untranslated entries (*note +Untranslated Entries::.). *Note msgmerge Invocation::, for more +information about what `msgmerge' really does. + + Whatever route or means taken, the goal is to obtain an updated +`LANG.pox' file offering translations for all strings. When this is +properly achieved, this file `LANG.pox' may take the place of the +previous official `LANG.po' file. + + The temporal mobility, or fluidity of PO files, is an integral part +of the translation game, and should be well understood, and accepted. +People resisting it will have a hard time participating in the +Translation Project, or will give a hard time to other participants! In +particular, maintainers should relax and include all available official +PO files in their distributions, even if these have not recently been +updated, without banging or otherwise trying to exert pressure on the +translator teams to get the job done. The pressure should rather come +from the community of users speaking a particular language, and +maintainers should consider themselves fairly relieved of any concern +about the adequacy of translation files. On the other hand, translators +should reasonably try updating the PO files they are responsible for, +while the package is undergoing pretest, prior to an official +distribution. + + Once the PO file is complete and dependable, the `msgfmt' program is +used for turning the PO file into a machine-oriented format, which may +yield efficient retrieval of translations by the programs of the +package, whenever needed at runtime (*note MO Files::.). *Note msgfmt +Invocation::, for more information about all modalities of execution +for the `msgfmt' program. + + Finally, the modified and marked C sources are compiled and linked +with the GNU `gettext' library, usually through the operation of +`make', given a suitable `Makefile' exists for the project, and the +resulting executable is installed somewhere users will find it. The MO +files themselves should also be properly installed. Given the +appropriate environment variables are set (*note End Users::.), the +program should localize itself automatically, whenever it executes. + + The remainder of this manual has the purpose of explaining in depth +the various steps outlined above. + + +File: gettext.info, Node: Basics, Next: Sources, Prev: Introduction, Up: Top + +PO Files and PO Mode Basics +*************************** + + The GNU `gettext' toolset helps programmers and translators at +producing, updating and using translation files, mainly those PO files +which are textual, editable files. This chapter stresses the format of +PO files, and contains a PO mode starter. PO mode description is +spread throughout this manual instead of being concentrated in one +place. Here we present only the basics of PO mode. + +* Menu: + +* Installation:: Completing GNU `gettext' Installation +* PO Files:: The Format of PO Files +* Main PO Commands:: Main Commands +* Entry Positioning:: Entry Positioning +* Normalizing:: Normalizing Strings in Entries + + +File: gettext.info, Node: Installation, Next: PO Files, Prev: Basics, Up: Basics + +Completing GNU `gettext' Installation +===================================== + + Once you have received, unpacked, configured and compiled the GNU +`gettext' distribution, the `make install' command puts in place the +programs `xgettext', `msgfmt', `gettext', and `msgmerge', as well as +their available message catalogs. To top off a comfortable +installation, you might also want to make the PO mode available to your +Emacs users. + + During the installation of the PO mode, you might want modify your +file `.emacs', once and for all, so it contains a few lines looking +like: + + (setq auto-mode-alist + (cons '("\\.po[tx]?\\'\\|\\.po\\." . po-mode) auto-mode-alist)) + (autoload 'po-mode "po-mode") + + Later, whenever you edit some `.po', `.pot' or `.pox' file, or any +file having the string `.po.' within its name, Emacs loads +`po-mode.elc' (or `po-mode.el') as needed, and automatically activates +PO mode commands for the associated buffer. The string *PO* appears in +the mode line for any buffer for which PO mode is active. Many PO +files may be active at once in a single Emacs session. + + If you are using Emacs version 20 or better, and have already +installed the appropriate international fonts on your system, you may +also manage for the these fonts to be automatically loaded and used for +displaying the translations on your Emacs screen, whenever necessary. +For this to happen, you might want to add the lines: + + (autoload 'po-find-file-coding-system "po-mode") + (modify-coding-system-alist 'file "\\.po[tx]?\\'\\|\\.po\\." + 'po-find-file-coding-system) + +to your `.emacs' file. + + +File: gettext.info, Node: PO Files, Next: Main PO Commands, Prev: Installation, Up: Basics + +The Format of PO Files +====================== + + A PO file is made up of many entries, each entry holding the relation +between an original untranslated string and its corresponding +translation. All entries in a given PO file usually pertain to a +single project, and all translations are expressed in a single target +language. One PO file "entry" has the following schematic structure: + + WHITE-SPACE + # TRANSLATOR-COMMENTS + #. AUTOMATIC-COMMENTS + #: REFERENCE... + #, FLAG... + msgid UNTRANSLATED-STRING + msgstr TRANSLATED-STRING + + The general structure of a PO file should be well understood by the +translator. When using PO mode, very little has to be known about the +format details, as PO mode takes care of them for her. + + Entries begin with some optional white space. Usually, when +generated through GNU `gettext' tools, there is exactly one blank line +between entries. Then comments follow, on lines all starting with the +character `#'. There are two kinds of comments: those which have some +white space immediately following the `#', which comments are created +and maintained exclusively by the translator, and those which have some +non-white character just after the `#', which comments are created and +maintained automatically by GNU `gettext' tools. All comments, of +either kind, are optional. + + After white space and comments, entries show two strings, giving +first the untranslated string as it appears in the original program +sources, and then, the translation of this string. The original string +is introduced by the keyword `msgid', and the translation, by `msgstr'. +The two strings, untranslated and translated, are quoted in various +ways in the PO file, using `"' delimiters and `\' escapes, but the +translator does not really have to pay attention to the precise quoting +format, as PO mode fully intend to take care of quoting for her. + + The `msgid' strings, as well as automatic comments, are produced and +managed by other GNU `gettext' tools, and PO mode does not provide +means for the translator to alter these. The most she can do is merely +deleting them, and only by deleting the whole entry. On the other +hand, the `msgstr' string, as well as translator comments, are really +meant for the translator, and PO mode gives her the full control she +needs. + + The comment lines beginning with `#,' are special because they are +not completely ignored by the programs as comments generally are. The +comma separated list of FLAGs is used by the `msgfmt' program to give +the user some better disgnostic messages. Currently there are two +forms of flags defined: + +`fuzzy' + This flag can be generated by the `msgmerge' program or it can be + inserted by the translator herself. It shows that the `msgstr' + string might not be a correct translation (anymore). Only the + translator can judge if the translation requires further + modification, or is acceptable as is. Once satisfied with the + translation, she then removes this `fuzzy' attribute. The + `msgmerge' programs inserts this when it combined the `msgid' and + `msgstr' entries after fuzzy search only. *Note Fuzzy Entries::. + +`c-format' +`no-c-format' + These flags should not be added by a human. Instead only the + `xgettext' program adds them. In an automatized PO file processing + system as proposed here the user changes would be thrown away + again as soon as the `xgettext' program generates a new template + file. + + In case the `c-format' flag is given for a string the `msgfmt' + does some more tests to check to validity of the translation. + *Note msgfmt Invocation::. + + It happens that some lines, usually whitespace or comments, follow +the very last entry of a PO file. Such lines are not part of any entry, +and PO mode is unable to take action on those lines. By using the PO +mode function `M-x po-normalize', the translator may get rid of those +spurious lines. *Note Normalizing::. + + The remainder of this section may be safely skipped by those using +PO mode, yet it may be interesting for everybody to have a better idea +of the precise format of a PO file. On the other hand, those not +having Emacs handy should carefully continue reading on. + + Each of UNTRANSLATED-STRING and TRANSLATED-STRING respects the C +syntax for a character string, including the surrounding quotes and +imbedded backslashed escape sequences. When the time comes to write +multi-line strings, one should not use escaped newlines. Instead, a +closing quote should follow the last character on the line to be +continued, and an opening quote should resume the string at the +beginning of the following PO file line. For example: + + msgid "" + "Here is an example of how one might continue a very long string\n" + "for the common case the string represents multi-line output.\n" + +In this example, the empty string is used on the first line, to allow +better alignment of the `H' from the word `Here' over the `f' from the +word `for'. In this example, the `msgid' keyword is followed by three +strings, which are meant to be concatenated. Concatenating the empty +string does not change the resulting overall string, but it is a way +for us to comply with the necessity of `msgid' to be followed by a +string on the same line, while keeping the multi-line presentation +left-justified, as we find this to be a cleaner disposition. The empty +string could have been omitted, but only if the string starting with +`Here' was promoted on the first line, right after `msgid'.(1) It was +not really necessary either to switch between the two last quoted +strings immediately after the newline `\n', the switch could have +occurred after *any* other character, we just did it this way because +it is neater. + + One should carefully distinguish between end of lines marked as `\n' +*inside* quotes, which are part of the represented string, and end of +lines in the PO file itself, outside string quotes, which have no +incidence on the represented string. + + Outside strings, white lines and comments may be used freely. +Comments start at the beginning of a line with `#' and extend until the +end of the PO file line. Comments written by translators should have +the initial `#' immediately followed by some white space. If the `#' +is not immediately followed by white space, this comment is most likely +generated and managed by specialized GNU tools, and might disappear or +be replaced unexpectedly when the PO file is given to `msgmerge'. + + ---------- Footnotes ---------- + + (1) This limitation is not imposed by GNU `gettext', but comes from +the `msgfmt' implementation on Solaris. + + +File: gettext.info, Node: Main PO Commands, Next: Entry Positioning, Prev: PO Files, Up: Basics + +Main PO mode Commands +===================== + + After setting up Emacs with something similar to the lines in *Note +Installation::, PO mode is activated for a window when Emacs finds a PO +file in that window. This puts the window read-only and establishes a +po-mode-map, which is a genuine Emacs mode, in a way that is not derived +from text mode in any way. Functions found on `po-mode-hook', if any, +will be executed. + + When PO mode is active in a window, the letters `PO' appear in the +mode line for that window. The mode line also displays how many +entries of each kind are held in the PO file. For example, the string +`132t+3f+10u+2o' would tell the translator that the PO mode contains +132 translated entries (*note Translated Entries::., 3 fuzzy entries +(*note Fuzzy Entries::.), 10 untranslated entries (*note Untranslated +Entries::.) and 2 obsolete entries (*note Obsolete Entries::.). +Zero-coefficients items are not shown. So, in this example, if the +fuzzy entries were unfuzzied, the untranslated entries were translated +and the obsolete entries were deleted, the mode line would merely +display `145t' for the counters. + + The main PO commands are those which do not fit into the other +categories of subsequent sections. These allow for quitting PO mode or +for managing windows in special ways. + +`U' + Undo last modification to the PO file. + +`Q' + Quit processing and save the PO file. + +`q' + Quit processing, possibly after confirmation. + +`O' + Temporary leave the PO file window. + +`?' +`h' + Show help about PO mode. + +`=' + Give some PO file statistics. + +`V' + Batch validate the format of the whole PO file. + + The command `U' (`po-undo') interfaces to the Emacs *undo* facility. +*Note Undoing Changes: (emacs)Undo. Each time `U' is typed, +modifications which the translator did to the PO file are undone a +little more. For the purpose of undoing, each PO mode command is +atomic. This is especially true for the `<RET>' command: the whole +edition made by using a single use of this command is undone at once, +even if the edition itself implied several actions. However, while in +the editing window, one can undo the edition work quite parsimoniously. + + The commands `Q' (`po-quit') and `q' (`po-confirm-and-quit') are +used when the translator is done with the PO file. The former is a bit +less verbose than the latter. If the file has been modified, it is +saved to disk first. In both cases, and prior to all this, the +commands check if some untranslated message remains in the PO file and, +if yes, the translator is asked if she really wants to leave off +working with this PO file. This is the preferred way of getting rid of +an Emacs PO file buffer. Merely killing it through the usual command +`C-x k' (`kill-buffer') is not the tidiest way to proceed. + + The command `O' (`po-other-window') is another, softer way, to leave +PO mode, temporarily. It just moves the cursor to some other Emacs +window, and pops one if necessary. For example, if the translator just +got PO mode to show some source context in some other, she might +discover some apparent bug in the program source that needs correction. +This command allows the translator to change sex, become a programmer, +and have the cursor right into the window containing the program she +(or rather *he*) wants to modify. By later getting the cursor back in +the PO file window, or by asking Emacs to edit this file once again, PO +mode is then recovered. + + The command `h' (`po-help') displays a summary of all available PO +mode commands. The translator should then type any character to resume +normal PO mode operations. The command `?' has the same effect as `h'. + + The command `=' (`po-statistics') computes the total number of +entries in the PO file, the ordinal of the current entry (counted from +1), the number of untranslated entries, the number of obsolete entries, +and displays all these numbers. + + The command `V' (`po-validate') launches `msgfmt' in verbose mode +over the current PO file. This command first offers to save the +current PO file on disk. The `msgfmt' tool, from GNU `gettext', has +the purpose of creating a MO file out of a PO file, and PO mode uses +the features of this program for checking the overall format of a PO +file, as well as all individual entries. + + The program `msgfmt' runs asynchronously with Emacs, so the +translator regains control immediately while her PO file is being +studied. Error output is collected in the Emacs `*compilation*' buffer, +displayed in another window. The regular Emacs command `C-x`' +(`next-error'), as well as other usual compile commands, allow the +translator to reposition quickly to the offending parts of the PO file. +Once the cursor is on the line in error, the translator may decide on +any PO mode action which would help correcting the error. + diff --git a/doc/gettext.info-2 b/doc/gettext.info-2 new file mode 100644 index 0000000..20de9bc --- /dev/null +++ b/doc/gettext.info-2 @@ -0,0 +1,1127 @@ +This is Info file gettext.info, produced by Makeinfo version 1.68 from +the input file gettext.texi. + +INFO-DIR-SECTION GNU Gettext Utilities +START-INFO-DIR-ENTRY +* Gettext: (gettext). GNU gettext utilities. +* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext. +* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files. +* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one. +* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file. +END-INFO-DIR-ENTRY + + This file provides documentation for GNU `gettext' utilities. It +also serves as a reference for the free Translation Project. + + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gettext.info, Node: Entry Positioning, Next: Normalizing, Prev: Main PO Commands, Up: Basics + +Entry Positioning +================= + + The cursor in a PO file window is almost always part of an entry. +The only exceptions are the special case when the cursor is after the +last entry in the file, or when the PO file is empty. The entry where +the cursor is found to be is said to be the current entry. Many PO +mode commands operate on the current entry, so moving the cursor does +more than allowing the translator to browse the PO file, this also +selects on which entry commands operate. + + Some PO mode commands alter the position of the cursor in a +specialized way. A few of those special purpose positioning are +described here, the others are described in following sections. + +`.' + Redisplay the current entry. + +`n' +`n' + Select the entry after the current one. + +`p' +`p' + Select the entry before the current one. + +`<' + Select the first entry in the PO file. + +`>' + Select the last entry in the PO file. + +`m' + Record the location of the current entry for later use. + +`l' + Return to a previously saved entry location. + +`x' + Exchange the current entry location with the previously saved one. + + Any Emacs command able to reposition the cursor may be used to +select the current entry in PO mode, including commands which move by +characters, lines, paragraphs, screens or pages, and search commands. +However, there is a kind of standard way to display the current entry +in PO mode, which usual Emacs commands moving the cursor do not +especially try to enforce. The command `.' (`po-current-entry') has +the sole purpose of redisplaying the current entry properly, after the +current entry has been changed by means external to PO mode, or the +Emacs screen otherwise altered. + + It is yet to be decided if PO mode helps the translator, or otherwise +irritates her, by forcing a rigid window disposition while she is doing +her work. We originally had quite precise ideas about how windows +should behave, but on the other hand, anyone used to Emacs is often +happy to keep full control. Maybe a fixed window disposition might be +offered as a PO mode option that the translator might activate or +deactivate at will, so it could be offered on an experimental basis. +If nobody feels a real need for using it, or a compulsion for writing +it, we should drop this whole idea. The incentive for doing it should +come from translators rather than programmers, as opinions from an +experienced translator are surely more worth to me than opinions from +programmers *thinking* about how *others* should do translation. + + The commands `n' (`po-next-entry') and `p' (`po-previous-entry') +move the cursor the entry following, or preceding, the current one. If +`n' is given while the cursor is on the last entry of the PO file, or +if `p' is given while the cursor is on the first entry, no move is done. + + The commands `<' (`po-first-entry') and `>' (`po-last-entry') move +the cursor to the first entry, or last entry, of the PO file. When the +cursor is located past the last entry in a PO file, most PO mode +commands will return an error saying `After last entry'. Moreover, the +commands `<' and `>' have the special property of being able to work +even when the cursor is not into some PO file entry, and one may use +them for nicely correcting this situation. But even these commands +will fail on a truly empty PO file. There are development plans for +the PO mode for it to interactively fill an empty PO file from sources. +*Note Marking::. + + The translator may decide, before working at the translation of a +particular entry, that she needs to browse the remainder of the PO +file, maybe for finding the terminology or phraseology used in related +entries. She can of course use the standard Emacs idioms for saving +the current cursor location in some register, and use that register for +getting back, or else, use the location ring. + + PO mode offers another approach, by which cursor locations may be +saved onto a special stack. The command `m' (`po-push-location') +merely adds the location of current entry to the stack, pushing the +already saved locations under the new one. The command `r' +(`po-pop-location') consumes the top stack element and reposition the +cursor to the entry associated with that top element. This position is +then lost, for the next `r' will move the cursor to the previously +saved location, and so on until no locations remain on the stack. + + If the translator wants the position to be kept on the location +stack, maybe for taking a look at the entry associated with the top +element, then go elsewhere with the intent of getting back later, she +ought to use `m' immediately after `r'. + + The command `x' (`po-exchange-location') simultaneously reposition +the cursor to the entry associated with the top element of the stack of +saved locations, and replace that top element with the location of the +current entry before the move. Consequently, repeating the `x' command +toggles alternatively between two entries. For achieving this, the +translator will position the cursor on the first entry, use `m', then +position to the second entry, and merely use `x' for making the switch. + + +File: gettext.info, Node: Normalizing, Prev: Entry Positioning, Up: Basics + +Normalizing Strings in Entries +============================== + + There are many different ways for encoding a particular string into a +PO file entry, because there are so many different ways to split and +quote multi-line strings, and even, to represent special characters by +backslahsed escaped sequences. Some features of PO mode rely on the +ability for PO mode to scan an already existing PO file for a +particular string encoded into the `msgid' field of some entry. Even +if PO mode has internally all the built-in machinery for implementing +this recognition easily, doing it fast is technically difficult. To +facilitate a solution to this efficiency problem, we decided on a +canonical representation for strings. + + A conventional representation of strings in a PO file is currently +under discussion, and PO mode experiments with a canonical +representation. Having both `xgettext' and PO mode converging towards +a uniform way of representing equivalent strings would be useful, as +the internal normalization needed by PO mode could be automatically +satisfied when using `xgettext' from GNU `gettext'. An explicit PO +mode normalization should then be only necessary for PO files imported +from elsewhere, or for when the convention itself evolves. + + So, for achieving normalization of at least the strings of a given +PO file needing a canonical representation, the following PO mode +command is available: + +`M-x po-normalize' + Tidy the whole PO file by making entries more uniform. + + The special command `M-x po-normalize', which has no associate keys, +revises all entries, ensuring that strings of both original and +translated entries use uniform internal quoting in the PO file. It +also removes any crumb after the last entry. This command may be +useful for PO files freshly imported from elsewhere, or if we ever +improve on the canonical quoting format we use. This canonical format +is not only meant for getting cleaner PO files, but also for greatly +speeding up `msgid' string lookup for some other PO mode commands. + + `M-x po-normalize' presently makes three passes over the entries. +The first implements heuristics for converting PO files for GNU +`gettext' 0.6 and earlier, in which `msgid' and `msgstr' fields were +using K&R style C string syntax for multi-line strings. These +heuristics may fail for comments not related to obsolete entries and +ending with a backslash; they also depend on subsequent passes for +finalizing the proper commenting of continued lines for obsolete +entries. This first pass might disappear once all oldish PO files +would have been adjusted. The second and third pass normalize all +`msgid' and `msgstr' strings respectively. They also clean out those +trailing backslashes used by XView's `msgfmt' for continued lines. + + Having such an explicit normalizing command allows for importing PO +files from other sources, but also eases the evolution of the current +convention, evolution driven mostly by aesthetic concerns, as of now. +It is easy to make suggested adjustments at a later time, as the +normalizing command and eventually, other GNU `gettext' tools should +greatly automate conformance. A description of the canonical string +format is given below, for the particular benefit of those not having +Emacs handy, and who would nevertheless want to handcraft their PO +files in nice ways. + + Right now, in PO mode, strings are single line or multi-line. A +string goes multi-line if and only if it has *embedded* newlines, that +is, if it matches `[^\n]\n+[^\n]'. So, we would have: + + msgstr "\n\nHello, world!\n\n\n" + + but, replacing the space by a newline, this becomes: + + msgstr "" + "\n" + "\n" + "Hello,\n" + "world!\n" + "\n" + "\n" + + We are deliberately using a caricatural example, here, to make the +point clearer. Usually, multi-lines are not that bad looking. It is +probable that we will implement the following suggestion. We might +lump together all initial newlines into the empty string, and also all +newlines introducing empty lines (that is, for N > 1, the N-1'th last +newlines would go together on a separate string), so making the +previous example appear: + + msgstr "\n\n" + "Hello,\n" + "world!\n" + "\n\n" + + There are a few yet undecided little points about string +normalization, to be documented in this manual, once these questions +settle. + + +File: gettext.info, Node: Sources, Next: Initial, Prev: Basics, Up: Top + +Preparing Program Sources +************************* + + For the programmer, changes to the C source code fall into three +categories. First, you have to make the localization functions known +to all modules needing message translation. Second, you should +properly trigger the operation of GNU `gettext' when the program +initializes, usually from the `main' function. Last, you should +identify and especially mark all constant strings in your program +needing translation. + + Presuming that your set of programs, or package, has been adjusted +so all needed GNU `gettext' files are available, and your `Makefile' +files are adjusted (*note Maintainers::.), each C module having +translated C strings should contain the line: + + #include <libintl.h> + + The remaining changes to your C sources are discussed in the further +sections of this chapter. + +* Menu: + +* Triggering:: Triggering `gettext' Operations +* Mark Keywords:: How Marks Appears in Sources +* Marking:: Marking Translatable Strings +* c-format:: Telling something about the following string +* Special cases:: Special Cases of Translatable Strings + + +File: gettext.info, Node: Triggering, Next: Mark Keywords, Prev: Sources, Up: Sources + +Triggering `gettext' Operations +=============================== + + The initialization of locale data should be done with more or less +the same code in every program, as demonstrated below: + + int + main (argc, argv) + int argc; + char argv; + { + ... + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + ... + } + + PACKAGE and LOCALEDIR should be provided either by `config.h' or by +the Makefile. For now consult the `gettext' sources for more +information. + + The use of `LC_ALL' might not be appropriate for you. `LC_ALL' +includes all locale categories and especially `LC_CTYPE'. This later +category is responsible for determining character classes with the +`isalnum' etc. functions from `ctype.h' which could especially for +programs, which process some kind of input language, be wrong. For +example this would mean that a source code using the c, (c-cedilla +character) is runnable in France but not in the U.S. + + Some systems also have problems with parsing number using the +`scanf' functions if an other but the `LC_ALL' locale is used. The +standards say that additional formats but the one known in the `"C"' +locale might be recognized. But some systems seem to reject numbers in +the `"C"' locale format. In some situation, it might also be a problem +with the notation itself which makes it impossible to recognize whether +the number is in the `"C"' locale or the local format. This can happen +if thousands separator characters are used. Some locales define this +character accordfing to the national conventions to `'.'' which is the +same character used in the `"C"' locale to denote the decimal point. + + So it is sometimes necessary to replace the `LC_ALL' line in the +code above by a sequence of `setlocale' lines + + { + ... + setlocale (LC_TIME, ""); + setlocale (LC_MESSAGES, ""); + ... + } + +or to switch for and back to the character class in question. On all +POSIX conformant systems the locale categories `LC_CTYPE', +`LC_COLLATE', `LC_MONETARY', `LC_NUMERIC', and `LC_TIME' are available. +On some modern systems there is also a locale `LC_MESSAGES' which is +called on some old, XPG2 compliant systems `LC_RESPONSES'. + + +File: gettext.info, Node: Mark Keywords, Next: Marking, Prev: Triggering, Up: Sources + +How Marks Appears in Sources +============================ + + All strings requiring translation should be marked in the C sources. +Marking is done in such a way that each translatable string appears to +be the sole argument of some function or preprocessor macro. There are +only a few such possible functions or macros meant for translation, and +their names are said to be marking keywords. The marking is attached +to strings themselves, rather than to what we do with them. This +approach has more uses. A blatant example is an error message produced +by formatting. The format string needs translation, as well as some +strings inserted through some `%s' specification in the format, while +the result from `sprintf' may have so many different instances that it +is impractical to list them all in some `error_string_out()' routine, +say. + + This marking operation has two goals. The first goal of marking is +for triggering the retrieval of the translation, at run time. The +keyword are possibly resolved into a routine able to dynamically return +the proper translation, as far as possible or wanted, for the argument +string. Most localizable strings are found in executable positions, +that is, attached to variables or given as parameters to functions. +But this is not universal usage, and some translatable strings appear +in structured initializations. *Note Special cases::. + + The second goal of the marking operation is to help `xgettext' at +properly extracting all translatable strings when it scans a set of +program sources and produces PO file templates. + + The canonical keyword for marking translatable strings is `gettext', +it gave its name to the whole GNU `gettext' package. For packages +making only light use of the `gettext' keyword, macro or function, it +is easily used *as is*. However, for packages using the `gettext' +interface more heavily, it is usually more convenient to give the main +keyword a shorter, less obtrusive name. Indeed, the keyword might +appear on a lot of strings all over the package, and programmers +usually do not want nor need their program sources to remind them +forcefully, all the time, that they are internationalized. Further, a +long keyword has the disadvantage of using more horizontal space, +forcing more indentation work on sources for those trying to keep them +within 79 or 80 columns. + + Many packages use `_' (a simple underline) as a keyword, and write +`_("Translatable string")' instead of `gettext ("Translatable +string")'. Further, the coding rule, from GNU standards, wanting that +there is a space between the keyword and the opening parenthesis is +relaxed, in practice, for this particular usage. So, the textual +overhead per translatable string is reduced to only three characters: +the underline and the two parentheses. However, even if GNU `gettext' +uses this convention internally, it does not offer it officially. The +real, genuine keyword is truly `gettext' indeed. It is fairly easy for +those wanting to use `_' instead of `gettext' to declare: + + #include <libintl.h> + #define _(String) gettext (String) + +instead of merely using `#include <libintl.h>'. + + Later on, the maintenance is relatively easy. If, as a programmer, +you add or modify a string, you will have to ask yourself if the new or +altered string requires translation, and include it within `_()' if you +think it should be translated. `"%s: %d"' is an example of string +*not* requiring translation! + + +File: gettext.info, Node: Marking, Next: c-format, Prev: Mark Keywords, Up: Sources + +Marking Translatable Strings +============================ + + In PO mode, one set of features is meant more for the programmer than +for the translator, and allows him to interactively mark which strings, +in a set of program sources, are translatable, and which are not. Even +if it is a fairly easy job for a programmer to find and mark such +strings by other means, using any editor of his choice, PO mode makes +this work more comfortable. Further, this gives translators who feel a +little like programmers, or programmers who feel a little like +translators, a tool letting them work at marking translatable strings +in the program sources, while simultaneously producing a set of +translation in some language, for the package being internationalized. + + The set of program sources, targetted by the PO mode commands +describe here, should have an Emacs tags table constructed for your +project, prior to using these PO file commands. This is easy to do. +In any shell window, change the directory to the root of your project, +then execute a command resembling: + + etags src/*.[hc] lib/*.[hc] + +presuming here you want to process all `.h' and `.c' files from the +`src/' and `lib/' directories. This command will explore all said +files and create a `TAGS' file in your root directory, somewhat +summarizing the contents using a special file format Emacs can +understand. + + For packages following the GNU coding standards, there is a make +goal `tags' or `TAGS' which construct the tag files in all directories +and for all files containing source code. + + Once your `TAGS' file is ready, the following commands assist the +programmer at marking translatable strings in his set of sources. But +these commands are necessarily driven from within a PO file window, and +it is likely that you do not even have such a PO file yet. This is not +a problem at all, as you may safely open a new, empty PO file, mainly +for using these commands. This empty PO file will slowly fill in while +you mark strings as translatable in your program sources. + +`,' + Search through program sources for a string which looks like a + candidate for translation. + +`M-,' + Mark the last string found with `_()'. + +`M-.' + Mark the last string found with a keyword taken from a set of + possible keywords. This command with a prefix allows some + management of these keywords. + + The `,' (`po-tags-search') command search for the next occurrence of +a string which looks like a possible candidate for translation, and +displays the program source in another Emacs window, positioned in such +a way that the string is near the top of this other window. If the +string is too big to fit whole in this window, it is positioned so only +its end is shown. In any case, the cursor is left in the PO file +window. If the shown string would be better presented differently in +different native languages, you may mark it using `M-,' or `M-.'. +Otherwise, you might rather ignore it and skip to the next string by +merely repeating the `,' command. + + A string is a good candidate for translation if it contains a +sequence of three or more letters. A string containing at most two +letters in a row will be considered as a candidate if it has more +letters than non-letters. The command disregards strings containing no +letters, or isolated letters only. It also disregards strings within +comments, or strings already marked with some keyword PO mode knows +(see below). + + If you have never told Emacs about some `TAGS' file to use, the +command will request that you specify one from the minibuffer, the +first time you use the command. You may later change your `TAGS' file +by using the regular Emacs command `M-x visit-tags-table', which will +ask you to name the precise `TAGS' file you want to use. *Note Tag +Tables: (emacs)Tags. + + Each time you use the `,' command, the search resumes from where it +was left by the previous search, and goes through all program sources, +obeying the `TAGS' file, until all sources have been processed. +However, by giving a prefix argument to the command (`C-u ,'), you may +request that the search be restarted all over again from the first +program source; but in this case, strings that you recently marked as +translatable will be automatically skipped. + + Using this `,' command does not prevent using of other regular Emacs +tags commands. For example, regular `tags-search' or +`tags-query-replace' commands may be used without disrupting the +independent `,' search sequence. However, as implemented, the +*initial* `,' command (or the `,' command is used with a prefix) might +also reinitialize the regular Emacs tags searching to the first tags +file, this reinitialization might be considered spurious. + + The `M-,' (`po-mark-translatable') command will mark the recently +found string with the `_' keyword. The `M-.' +(`po-select-mark-and-mark') command will request that you type one +keyword from the minibuffer and use that keyword for marking the +string. Both commands will automatically create a new PO file +untranslated entry for the string being marked, and make it the current +entry (making it easy for you to immediately proceed to its +translation, if you feel like doing it right away). It is possible +that the modifications made to the program source by `M-,' or `M-.' +render some source line longer than 80 columns, forcing you to break +and re-indent this line differently. You may use the `O' command from +PO mode, or any other window changing command from Emacs, to break out +into the program source window, and do any needed adjustments. You +will have to use some regular Emacs command to return the cursor to the +PO file window, if you want command `,' for the next string, say. + + The `M-.' command has a few built-in speedups, so you do not have to +explicitly type all keywords all the time. The first such speedup is +that you are presented with a *preferred* keyword, which you may accept +by merely typing `<RET>' at the prompt. The second speedup is that you +may type any non-ambiguous prefix of the keyword you really mean, and +the command will complete it automatically for you. This also means +that PO mode has to *know* all your possible keywords, and that it will +not accept mistyped keywords. + + If you reply `?' to the keyword request, the command gives a list of +all known keywords, from which you may choose. When the command is +prefixed by an argument (`C-u M-.'), it inhibits updating any program +source or PO file buffer, and does some simple keyword management +instead. In this case, the command asks for a keyword, written in +full, which becomes a new allowed keyword for later `M-.' commands. +Moreover, this new keyword automatically becomes the *preferred* +keyword for later commands. By typing an already known keyword in +response to `C-u M-.', one merely changes the *preferred* keyword and +does nothing more. + + All keywords known for `M-.' are recognized by the `,' command when +scanning for strings, and strings already marked by any of those known +keywords are automatically skipped. If many PO files are opened +simultaneously, each one has its own independent set of known keywords. +There is no provision in PO mode, currently, for deleting a known +keyword, you have to quit the file (maybe using `q') and reopen it +afresh. When a PO file is newly brought up in an Emacs window, only +`gettext' and `_' are known as keywords, and `gettext' is preferred for +the `M-.' command. In fact, this is not useful to prefer `_', as this +one is already built in the `M-,' command. + + +File: gettext.info, Node: c-format, Next: Special cases, Prev: Marking, Up: Sources + +Special Comments preceding Keywords +=================================== + + In C programs strings are often used within calls of functions from +the `printf' family. The special thing about these format strings is +that they can contain format specifiers introduced with `%'. Assume we +have the code + + printf (gettext ("String `%s' has %d characters\n"), s, strlen (s)); + +A possible German translation for the above string might be: + + "%d Zeichen lang ist die Zeichenkette `%s'" + + A C programmer, even if he cannot speak German, will recognize that +there is something wrong here. The order of the two format specifiers +is changed but of course the arguments in the `printf' don't have. +This will most probably lead to problems because now the length of the +string is regarded as the address. + + To prevent errors at runtime caused by translations the `msgfmt' +tool can check statically whether the arguments in the original and the +translation string match in type and number. If this is not the case a +warning will be given and the error cannot causes problems at runtime. + +If the word order in the above German translation would be correct one +would have to write + + "%2$d Zeichen lang ist die Zeichenkette `%1$s'" + +The routines in `msgfmt' know about this special notation. + + Because not all strings in a program must be format strings it is not +useful for `msgfmt' to test all the strings in the `.po' file. This +might cause problems because the string might contain what looks like a +format specifier, but the string is not used in `printf'. + + Therefore the `xgettext' adds a special tag to those messages it +thinks might be a format string. There is no absolute rule for this, +only a heuristic. In the `.po' file the entry is marked using the +`c-format' flag in the `#,' comment line (*note PO Files::.). + + The careful reader now might say that this again can cause problems. +The heuristic might guess it wrong. This is true and therefore +`xgettext' knows about special kind of comment which lets the +programmer take over the decision. If in the same line or the +immediately preceding line of the `gettext' keyword the `xgettext' +program find a comment containing the words `xgettext:c-format' it will +mark the string in any case with the `c-format' flag. This kind of +comment should be used when `xgettext' does not recognize the string as +a format string but is really is one and it should be tested. Please +note that when the comment is in the same line of the `gettext' +keyword, it must be before the string to be translated. + + This situation happens quite often. The `printf' function is often +called with strings which do not contain a format specifier. Of course +one would normally use `fputs' but it does happen. In this case +`xgettext' does not recognize this as a format string but what happens +if the translation introduces a valid format specifier? The `printf' +function will try to access one of the parameter but none exists +because the original code does not refer to any parameter. + + `xgettext' of course could make a wrong decision the other way +round. A string marked as a format string is not really a format +string. In this case the `msgfmt' might give too many warnings and +would prevent translating the `.po' file. The method to prevent this +wrong decision is similar to the one used above, only the comment to +use must contain the string `xgettext:no-c-format'. + + If a string is marked with `c-format' and this is not correct the +user can find out who is responsible for the decision. See *Note +xgettext Invocation:: to see how the `--debug' option can be used for +solving this problem. + + +File: gettext.info, Node: Special cases, Prev: c-format, Up: Sources + +Special Cases of Translatable Strings +===================================== + + The attentive reader might now point out that it is not always +possible to mark translatable string with `gettext' or something like +this. Consider the following case: + + { + static const char *messages[] = { + "some very meaningful message", + "and another one" + }; + const char *string; + ... + string + = index > 1 ? "a default message" : messages[index]; + + fputs (string); + ... + } + + While it is no problem to mark the string `"a default message"' it +is not possible to mark the string initializers for `messages'. What +is to be done? We have to fulfill two tasks. First we have to mark the +strings so that the `xgettext' program (*note xgettext Invocation::.) +can find them, and second we have to translate the string at runtime +before printing them. + + The first task can be fulfilled by creating a new keyword, which +names a no-op. For the second we have to mark all access points to a +string from the array. So one solution can look like this: + + #define gettext_noop(String) (String) + + { + static const char *messages[] = { + gettext_noop ("some very meaningful message"), + gettext_noop ("and another one") + }; + const char *string; + ... + string + = index > 1 ? gettext ("a default message") : gettext (messages[index]); + + fputs (string); + ... + } + + Please convince yourself that the string which is written by `fputs' +is translated in any case. How to get `xgettext' know the additional +keyword `gettext_noop' is explained in *Note xgettext Invocation::. + + The above is of course not the only solution. You could also come +along with the following one: + + #define gettext_noop(String) (String) + + { + static const char *messages[] = { + gettext_noop ("some very meaningful message", + gettext_noop ("and another one") + }; + const char *string; + ... + string + = index > 1 ? gettext_noop ("a default message") : messages[index]; + + fputs (gettext (string)); + ... + } + + But this has some drawbacks. First the programmer has to take care +that he uses `gettext_noop' for the string `"a default message"'. A +use of `gettext' could have in rare cases unpredictable results. The +second reason is found in the internals of the GNU `gettext' Library +which will make this solution less efficient. + + One advantage is that you need not make control flow analysis to make +sure the output is really translated in any case. But this analysis is +generally not very difficult. If it should be in any situation you can +use this second method in this situation. + + +File: gettext.info, Node: Initial, Next: Updating, Prev: Sources, Up: Top + +Making the Initial PO File +************************** + +* Menu: + +* xgettext Invocation:: Invoking the `xgettext' Program +* C Sources Context:: C Sources Context +* Compendium:: Using Translation Compendiums + + +File: gettext.info, Node: xgettext Invocation, Next: C Sources Context, Prev: Initial, Up: Initial + +Invoking the `xgettext' Program +=============================== + + xgettext [OPTION] INPUTFILE ... + +`-a' +`--extract-all' + Extract all strings. + +`-c [TAG]' +`--add-comments[=TAG]' + Place comment block with TAG (or those preceding keyword lines) in + output file. + +`-C' +`--c++' + Recognize C++ style comments. + +`--debug' + Use the flags `c-format' and `possible-c-format' to show who was + responsible for marking a message as a format string. The later + form is used if the `xgettext' program decided, the format form is + used if the programmer prescribed it. + + By default only the `c-format' form is used. The translator should + not have to care about these details. + +`-d NAME' +`--default-domain=NAME' + Use `NAME.po' for output (instead of `messages.po'). + + The special domain name `-' or `/dev/stdout' means to write the + output to `stdout'. + +`-D DIRECTORY' +`--directory=DIRECTORY' + Change to DIRECTORY before beginning to search and scan source + files. The resulting `.po' file will be written relative to the + original directory, though. + +`-f FILE' +`--files-from=FILE' + Read the names of the input files from FILE instead of getting + them from the command line. + +`--force' + Always write output file even if no message is defined. + +`-h' +`--help' + Display this help and exit. + +`-I LIST' +`--input-path=LIST' + List of directories searched for input files. + +`-j' +`--join-existing' + Join messages with existing file. + +`-k WORD' +`--keyword[=WORD]' + Additonal keyword to be looked for (without WORD means not to use + default keywords). + + The default keywords, which are always looked for if not explicitly + disabled, are `gettext', `dgettext', `dcgettext' and + `gettext_noop'. + +`-m [STRING]' +`--msgstr-prefix[=STRING]' + Use STRING or "" as prefix for msgstr entries. + +`-M [STRING]' +`--msgstr-suffix[=STRING]' + Use STRING or "" as suffix for msgstr entries. + +`--no-location' + Do not write `#: FILENAME:LINE' lines. + +`-n' +`--add-location' + Generate `#: FILENAME:LINE' lines (default). + +`--omit-header' + Don't write header with `msgid ""' entry. + + This is useful for testing purposes because it eliminates a source + of variance for generated `.gmo' files. We can ship some of these + files in the GNU `gettext' package, and the result of regenerating + them through `msgfmt' should yield the same values. + +`-p DIR' +`--output-dir=DIR' + Output files will be placed in directory DIR. + +`-s' +`--sort-output' + Generate sorted output and remove duplicates. + +`--strict' + Write out strict Uniforum conforming PO file. + +`-v' +`--version' + Output version information and exit. + +`-x FILE' +`--exclude-file=FILE' + Entries from FILE are not extracted. + + Search path for supplementary PO files is: +`/usr/local/share/nls/src/'. + + If INPUTFILE is `-', standard input is read. + + This implementation of `xgettext' is able to process a few awkward +cases, like strings in preprocessor macros, ANSI concatenation of +adjacent strings, and escaped end of lines for continued strings. + + +File: gettext.info, Node: C Sources Context, Next: Compendium, Prev: xgettext Invocation, Up: Initial + +C Sources Context +================= + + PO mode is particularily powerful when used with PO files created +through GNU `gettext' utilities, as those utilities insert special +comments in the PO files they generate. Some of these special comments +relate the PO file entry to exactly where the untranslated string +appears in the program sources. + + When the translator gets to an untranslated entry, she is fairly +often faced with an original string which is not as informative as it +normally should be, being succinct, cryptic, or otherwise ambiguous. +Before chosing how to translate the string, she needs to understand +better what the string really means and how tight the translation has +to be. Most of times, when problems arise, the only way left to make +her judgment is looking at the true program sources from where this +string originated, searching for surrounding comments the programmer +might have put in there, and looking around for helping clues of *any* +kind. + + Surely, when looking at program sources, the translator will receive +more help if she is a fluent programmer. However, even if she is not +versed in programming and feels a little lost in C code, the translator +should not be shy at taking a look, once in a while. It is most +probable that she will still be able to find some of the hints she +needs. She will learn quickly to not feel uncomfortable in program +code, paying more attention to programmer's comments, variable and +function names (if he dared chosing them well), and overall +organization, than to programmation itself. + + The following commands are meant to help the translator at getting +program source context for a PO file entry. + +`s' + Resume the display of a program source context, or cycle through + them. + +`M-s' + Display of a program source context selected by menu. + +`S' + Add a directory to the search path for source files. + +`M-S' + Delete a directory from the search path for source files. + + The commands `s' (`po-cycle-reference') and `M-s' +(`po-select-source-reference') both open another window displaying some +source program file, and already positioned in such a way that it shows +an actual use of the string to be translated. By doing so, the command +gives source program context for the string. But if the entry has no +source context references, or if all references are unresolved along +the search path for program sources, then the command diagnoses this as +an error. + + Even if `s' (or `M-s') opens a new window, the cursor stays in the +PO file window. If the translator really wants to get into the program +source window, she ought to do it explicitly, maybe by using command +`O'. + + When `s' is typed for the first time, or for a PO file entry which +is different of the last one used for getting source context, then the +command reacts by giving the first context available for this entry, if +any. If some context has already been recently displayed for the +current PO file entry, and the translator wandered off to do other +things, typing `s' again will merely resume, in another window, the +context last displayed. In particular, if the translator moved the +cursor away from the context in the source file, the command will bring +the cursor back to the context. By using `s' many times in a row, with +no other commands intervening, PO mode will cycle to the next available +contexts for this particular entry, getting back to the first context +once the last has been shown. + + The command `M-s' behaves differently. Instead of cycling through +references, it lets the translator choose of particular reference among +many, and displays that reference. It is best used with completion, if +the translator types `<TAB>' immediately after `M-s', in response to +the question, she will be offered a menu of all possible references, as +a reminder of which are the acceptable answers. This command is useful +only where there are really many contexts available for a single string +to translate. + + Program source files are usually found relative to where the PO file +stands. As a special provision, when this fails, the file is also +looked for, but relative to the directory immediately above it. Those +two cases take proper care of most PO files. However, it might happen +that a PO file has been moved, or is edited in a different place than +its normal location. When this happens, the translator should tell PO +mode in which directory normally sits the genuine PO file. Many such +directories may be specified, and all together, they constitute what is +called the "search path" for program sources. The command `S' +(`po-consider-source-path') is used to interactively enter a new +directory at the front of the search path, and the command `M-S' +(`po-ignore-source-path') is used to select, with completion, one of +the directories she does not want anymore on the search path. + + +File: gettext.info, Node: Compendium, Prev: C Sources Context, Up: Initial + +Using Translation Compendiums +============================= + + Compendiums are yet to be implemented. + + An incoming PO mode feature will let the translator maintain a +compendium of already achieved translations. A "compendium" is a +special PO file containing a set of translations recurring in many +different packages. The translator will be given commands for adding +entries to her compendium, and later initializing untranslated entries, +or updating already translated entries, from translations kept in the +compendium. For this to work, however, the compendium would have to be +normalized. *Note Normalizing::. + + +File: gettext.info, Node: Updating, Next: Binaries, Prev: Initial, Up: Top + +Updating Existing PO Files +************************** + +* Menu: + +* msgmerge Invocation:: Invoking the `msgmerge' Program +* Translated Entries:: Translated Entries +* Fuzzy Entries:: Fuzzy Entries +* Untranslated Entries:: Untranslated Entries +* Obsolete Entries:: Obsolete Entries +* Modifying Translations:: Modifying Translations +* Modifying Comments:: Modifying Comments +* Subedit:: Mode for Editing Translations +* Auxiliary:: Consulting Auxiliary PO Files + + +File: gettext.info, Node: msgmerge Invocation, Next: Translated Entries, Prev: Updating, Up: Updating + +Invoking the `msgmerge' Program +=============================== + + +File: gettext.info, Node: Translated Entries, Next: Fuzzy Entries, Prev: msgmerge Invocation, Up: Updating + +Translated Entries +================== + + Each PO file entry for which the `msgstr' field has been filled with +a translation, and which is not marked as fuzzy (*note Fuzzy +Entries::.), is a said to be a "translated" entry. Only translated +entries will later be compiled by GNU `msgfmt' and become usable in +programs. Other entry types will be excluded; translation will not +occur for them. + + Some commands are more specifically related to translated entry +processing. + +`t' + Find the next translated entry. + +`M-t' + Find the previous translated entry. + + The commands `t' (`po-next-translated-entry') and `M-t' +(`po-previous-transted-entry') move forwards or backwards, chasing for +an translated entry. If none is found, the search is extended and +wraps around in the PO file buffer. + + Translated entries usually result from the translator having edited +in a translation for them, *Note Modifying Translations::. However, if +the variable `po-auto-fuzzy-on-edit' is not `nil', the entry having +received a new translation first becomes a fuzzy entry, which ought to +be later unfuzzied before becoming an official, genuine translated +entry. *Note Fuzzy Entries::. + + +File: gettext.info, Node: Fuzzy Entries, Next: Untranslated Entries, Prev: Translated Entries, Up: Updating + +Fuzzy Entries +============= + + Each PO file entry may have a set of "attributes", which are +qualities given an name and explicitely associated with the entry +translation, using a special system comment. One of these attributes +has the name `fuzzy', and entries having this attribute are said to +have a fuzzy translation. They are called fuzzy entries, for short. + + Fuzzy entries, even if they account for translated entries for most +other purposes, usually call for revision by the translator. Those may +be produced by applying the program `msgmerge' to update an older +translated PO files according to a new PO template file, when this tool +hypothesises that some new `msgid' has been modified only slightly out +of an older one, and chooses to pair what it thinks to be the old +translation for the new modified entry. The slight alteration in the +original string (the `msgid' string) should often be reflected in the +translated string, and this requires the intervention of the +translator. For this reason, `msgmerge' might mark some entries as +being fuzzy. + + Also, the translator may decide herself to mark an entry as fuzzy +for her own convenience, when she wants to remember that the entry has +to be later revisited. So, some commands are more specifically related +to fuzzy entry processing. + +`f' + Find the next fuzzy entry. + +`M-f' + Find the previous fuzzy entry. + +`<TAB>' + Remove the fuzzy attribute of the current entry. + + The commands `f' (`po-next-fuzzy') and `M-f' (`po-previous-fuzzy') +move forwards or backwards, chasing for a fuzzy entry. If none is +found, the search is extended and wraps around in the PO file buffer. + + The command `<TAB>' (`po-unfuzzy') removes the fuzzy attribute +associated with an entry, usually leaving it translated. Further, if +the variable `po-auto-select-on-unfuzzy' has not the `nil' value, the +`<TAB>' command will automatically chase for another interesting entry +to work on. The initial value of `po-auto-select-on-unfuzzy' is `nil'. + + The initial value of `po-auto-fuzzy-on-edit' is `nil'. However, if +the variable `po-auto-fuzzy-on-edit' is set to `t', any entry edited +through the `<RET>' command is marked fuzzy, as a way to ensure some +kind of double check, later. In this case, the usual paradigm is that +an entry becomes fuzzy (if not already) whenever the translator +modifies it. If she is satisfied with the translation, she then uses +`<TAB>' to pick another entry to work on, clearing the fuzzy attribute +on the same blow. If she is not satisfied yet, she merely uses `<SPC>' +to chase another entry, leaving the entry fuzzy. + + The translator may also use the `<DEL>' command +(`po-fade-out-entry') over any translated entry to mark it as being +fuzzy, when she wants to easily leave a trace she wants to later return +working at this entry. + + Also, when time comes to quit working on a PO file buffer with the +`q' command, the translator is asked for confirmation, if fuzzy string +still exists. + + +File: gettext.info, Node: Untranslated Entries, Next: Obsolete Entries, Prev: Fuzzy Entries, Up: Updating + +Untranslated Entries +==================== + + When `xgettext' originally creates a PO file, unless told otherwise, +it initializes the `msgid' field with the untranslated string, and +leaves the `msgstr' string to be empty. Such entries, having an empty +translation, are said to be "untranslated" entries. Later, when the +programmer slightly modifies some string right in the program, this +change is later reflected in the PO file by the appearance of a new +untranslated entry for the modified string. + + The usual commands moving from entry to entry consider untranslated +entries on the same level as active entries. Untranslated entries are +easily recognizable by the fact they end with `msgstr ""'. + + The work of the translator might be (quite naively) seen as the +process of seeking after an untranslated entry, editing a translation +for it, and repeating these actions until no untranslated entries +remain. Some commands are more specifically related to untranslated +entry processing. + +`u' + Find the next untranslated entry. + +`M-u' + Find the previous untranslated entry. + +`k' + Turn the current entry into an untranslated one. + + The commands `u' (`po-next-untranslated-entry') and `M-u' +(`po-previous-untransted-entry') move forwards or backwards, chasing +for an untranslated entry. If none is found, the search is extended +and wraps around in the PO file buffer. + + An entry can be turned back into an untranslated entry by merely +emptying its translation, using the command `k' (`po-kill-msgstr'). +*Note Modifying Translations::. + + Also, when time comes to quit working on a PO file buffer with the +`q' command, the translator is asked for confirmation, if some +untranslated string still exists. + diff --git a/doc/gettext.info-3 b/doc/gettext.info-3 new file mode 100644 index 0000000..cd5db2b --- /dev/null +++ b/doc/gettext.info-3 @@ -0,0 +1,1072 @@ +This is Info file gettext.info, produced by Makeinfo version 1.68 from +the input file gettext.texi. + +INFO-DIR-SECTION GNU Gettext Utilities +START-INFO-DIR-ENTRY +* Gettext: (gettext). GNU gettext utilities. +* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext. +* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files. +* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one. +* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file. +END-INFO-DIR-ENTRY + + This file provides documentation for GNU `gettext' utilities. It +also serves as a reference for the free Translation Project. + + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gettext.info, Node: Obsolete Entries, Next: Modifying Translations, Prev: Untranslated Entries, Up: Updating + +Obsolete Entries +================ + + By "obsolete" PO file entries, we mean those entries which are +commented out, usually by `msgmerge' when it found that the translation +is not needed anymore by the package being localized. + + The usual commands moving from entry to entry consider obsolete +entries on the same level as active entries. Obsolete entries are +easily recognizable by the fact that all their lines start with `#', +even those lines containing `msgid' or `msgstr'. + + Commands exist for emptying the translation or reinitializing it to +the original untranslated string. Commands interfacing with the kill +ring may force some previously saved text into the translation. The +user may interactively edit the translation. All these commands may +apply to obsolete entries, carefully leaving the entry obsolete after +the fact. + + Moreover, some commands are more specifically related to obsolete +entry processing. + +`o' + Find the next obsolete entry. + +`M-o' + Find the previous obsolete entry. + +`<DEL>' + Make an active entry obsolete, or zap out an obsolete entry. + + The commands `o' (`po-next-obsolete-entry') and `M-o' +(`po-previous-obsolete-entry') move forwards or backwards, chasing for +an obsolete entry. If none is found, the search is extended and wraps +around in the PO file buffer. + + PO mode does not provide ways for un-commenting an obsolete entry +and making it active, because this would reintroduce an original +untranslated string which does not correspond to any marked string in +the program sources. This goes with the philosophy of never +introducing useless `msgid' values. + + However, it is possible to comment out an active entry, so making it +obsolete. GNU `gettext' utilities will later react to the +disappearance of a translation by using the untranslated string. The +command `<DEL>' (`po-fade-out-entry') pushes the current entry a little +further towards annihilation. If the entry is active (it is a +translated entry), then it is first made fuzzy. If it is already fuzzy, +then the entry is merely commented out, with confirmation. If the entry +is already obsolete, then it is completely deleted from the PO file. +It is easy to recycle the translation so deleted into some other PO file +entry, usually one which is untranslated. *Note Modifying +Translations::. + + Here is a quite interesting problem to solve for later development of +PO mode, for those nights you are not sleepy. The idea would be that +PO mode might become bright enough, one of these days, to make good +guesses at retrieving the most probable candidate, among all obsolete +entries, for initializing the translation of a newly appeared string. +I think it might be a quite hard problem to do this algorithmically, as +we have to develop good and efficient measures of string similarity. +Right now, PO mode completely lets the decision to the translator, when +the time comes to find the adequate obsolete translation, it merely +tries to provide handy tools for helping her to do so. + + +File: gettext.info, Node: Modifying Translations, Next: Modifying Comments, Prev: Obsolete Entries, Up: Updating + +Modifying Translations +====================== + + PO mode prevents direct edition of the PO file, by the usual means +Emacs give for altering a buffer's contents. By doing so, it pretends +helping the translator to avoid little clerical errors about the +overall file format, or the proper quoting of strings, as those errors +would be easily made. Other kinds of errors are still possible, but +some may be caught and diagnosed by the batch validation process, which +the translator may always trigger by the `V' command. For all other +errors, the translator has to rely on her own judgment, and also on the +linguistic reports submitted to her by the users of the translated +package, having the same mother tongue. + + When the time comes to create a translation, correct an error +diagnosed mechanically or reported by a user, the translators have to +resort to using the following commands for modifying the translations. + +`<RET>' + Interactively edit the translation. + +`<LFD>' + Reinitialize the translation with the original, untranslated + string. + +`k' + Save the translation on the kill ring, and delete it. + +`w' + Save the translation on the kill ring, without deleting it. + +`y' + Replace the translation, taking the new from the kill ring. + + The command `<RET>' (`po-edit-msgstr') opens a new Emacs window +meant to edit in a new translation, or to modify an already existing +translation. The new window contains a copy of the translation taken +from the current PO file entry, all ready for edition, expunged of all +quoting marks, fully modifiable and with the complete extent of Emacs +modifying commands. When the translator is done with her +modifications, she may use `C-c C-c' to close the subedit window with +the automatically requoted results, or `C-c C-k' to abort her +modifications. *Note Subedit::, for more information. + + The command `<LFD>' (`po-msgid-to-msgstr') initializes, or +reinitializes the translation with the original string. This command is +normally used when the translator wants to redo a fresh translation of +the original string, disregarding any previous work. + + It is possible to arrange so, whenever editing an untranslated +entry, the `<LFD>' command be automatically executed. If you set +`po-auto-edit-with-msgid' to `t', the translation gets initialised with +the original string, in case none exist already. The default value for +`po-auto-edit-with-msgid' is `nil'. + + In fact, whether it is best to start a translation with an empty +string, or rather with a copy of the original string, is a matter of +taste or habit. Sometimes, the source language and the target language +are so different that is simply best to start writing on an empty page. +At other times, the source and target languages are so close that it +would be a waste to retype a number of words already being written in +the original string. A translator may also like having the original +string right under her eyes, as she will progressively overwrite the +original text with the translation, even if this requires some extra +editing work to get rid of the original. + + The command `k' (`po-kill-msgstr') merely empties the translation +string, so turning the entry into an untranslated one. But while doing +so, its previous contents is put apart in a special place, known as the +kill ring. The command `w' (`po-kill-ring-save-msgstr') has also the +effect of taking a copy of the translation onto the kill ring, but it +otherwise leaves the entry alone, and does *not* remove the translation +from the entry. Both commands use exactly the Emacs kill ring, which +is shared between buffers, and which is well known already to Emacs +lovers. + + The translator may use `k' or `w' many times in the course of her +work, as the kill ring may hold several saved translations. From the +kill ring, strings may later be reinserted in various Emacs buffers. +In particular, the kill ring may be used for moving translation strings +between different entries of a single PO file buffer, or if the +translator is handling many such buffers at once, even between PO files. + + To facilitate exchanges with buffers which are not in PO mode, the +translation string put on the kill ring by the `k' command is fully +unquoted before being saved: external quotes are removed, multi-lines +strings are concatenated, and backslashed escaped sequences are turned +into their corresponding characters. In the special case of obsolete +entries, the translation is also uncommented prior to saving. + + The command `y' (`po-yank-msgstr') completely replaces the +translation of the current entry by a string taken from the kill ring. +Following Emacs terminology, we then say that the replacement string is +"yanked" into the PO file buffer. *Note Yanking: (emacs)Yanking. The +first time `y' is used, the translation receives the value of the most +recent addition to the kill ring. If `y' is typed once again, +immediately, without intervening keystrokes, the translation just +inserted is taken away and replaced by the second most recent addition +to the kill ring. By repeating `y' many times in a row, the translator +may travel along the kill ring for saved strings, until she finds the +string she really wanted. + + When a string is yanked into a PO file entry, it is fully and +automatically requoted for complying with the format PO files should +have. Further, if the entry is obsolete, PO mode then appropriately +push the inserted string inside comments. Once again, translators +should not burden themselves with quoting considerations besides, of +course, the necessity of the translated string itself respective to the +program using it. + + Note that `k' or `w' are not the only commands pushing strings on +the kill ring, as almost any PO mode command replacing translation +strings (or the translator comments) automatically save the old string +on the kill ring. The main exceptions to this general rule are the +yanking commands themselves. + + To better illustrate the operation of killing and yanking, let's use +an actual example, taken from a common situation. When the programmer +slightly modifies some string right in the program, his change is later +reflected in the PO file by the appearance of a new untranslated entry +for the modified string, and the fact that the entry translating the +original or unmodified string becomes obsolete. In many cases, the +translator might spare herself some work by retrieving the unmodified +translation from the obsolete entry, then initializing the untranslated +entry `msgstr' field with this retrieved translation. Once this done, +the obsolete entry is not wanted anymore, and may be safely deleted. + + When the translator finds an untranslated entry and suspects that a +slight variant of the translation exists, she immediately uses `m' to +mark the current entry location, then starts chasing obsolete entries +with `o', hoping to find some translation corresponding to the +unmodified string. Once found, she uses the `<DEL>' command for +deleting the obsolete entry, knowing that `<DEL>' also *kills* the +translation, that is, pushes the translation on the kill ring. Then, +`r' returns to the initial untranslated entry, `y' then *yanks* the +saved translation right into the `msgstr' field. The translator is +then free to use `<RET>' for fine tuning the translation contents, and +maybe to later use `u', then `m' again, for going on with the next +untranslated string. + + When some sequence of keys has to be typed over and over again, the +translator may find it useful to become better acquainted with the Emacs +capability of learning these sequences and playing them back under +request. *Note Keyboard Macros: (emacs)Keyboard Macros. + + +File: gettext.info, Node: Modifying Comments, Next: Subedit, Prev: Modifying Translations, Up: Updating + +Modifying Comments +================== + + Any translation work done seriously will raise many linguistic +difficulties, for which decisions have to be made, and the choices +further documented. These documents may be saved within the PO file in +form of translator comments, which the translator is free to create, +delete, or modify at will. These comments may be useful to herself +when she returns to this PO file after a while. + + Comments not having whitespace after the initial `#', for example, +those beginning with `#.' or `#:', are *not* translator comments, they +are exclusively created by other `gettext' tools. So, the commands +below will never alter such system added comments, they are not meant +for the translator to modify. *Note PO Files::. + + The following commands are somewhat similar to those modifying +translations, so the general indications given for those apply here. +*Note Modifying Translations::. + +`#' + Interactively edit the translator comments. + +`K' + Save the translator comments on the kill ring, and delete it. + +`W' + Save the translator comments on the kill ring, without deleting it. + +`Y' + Replace the translator comments, taking the new from the kill ring. + + These commands parallel PO mode commands for modifying the +translation strings, and behave much the same way as they do, except +that they handle this part of PO file comments meant for translator +usage, rather than the translation strings. So, if the descriptions +given below are slightly succinct, it is because the full details have +already been given. *Note Modifying Translations::. + + The command `#' (`po-edit-comment') opens a new Emacs window +containing a copy of the translator comments on the current PO file +entry. If there are no such comments, PO mode understands that the +translator wants to add a comment to the entry, and she is presented +with an empty screen. Comment marks (`#') and the space following them +are automatically removed before edition, and reinstated after. For +translator comments pertaining to obsolete entries, the uncommenting +and recommenting operations are done twice. Once in the editing +window, the keys `C-c C-c' allow the translator to tell she is finished +with editing the comment. *Note Subedit::, for further details. + + Functions found on `po-subedit-mode-hook', if any, are executed after +the string has been inserted in the edit buffer. + + The command `K' (`po-kill-comment') get rid of all translator +comments, while saving those comments on the kill ring. The command +`W' (`po-kill-ring-save-comment') takes a copy of the translator +comments on the kill ring, but leaves them undisturbed in the current +entry. The command `Y' (`po-yank-comment') completely replaces the +translator comments by a string taken at the front of the kill ring. +When this command is immediately repeated, the comments just inserted +are withdrawn, and replaced by other strings taken along the kill ring. + + On the kill ring, all strings have the same nature. There is no +distinction between *translation* strings and *translator comments* +strings. So, for example, let's presume the translator has just +finished editing a translation, and wants to create a new translator +comment to document why the previous translation was not good, just to +remember what was the problem. Foreseeing that she will do that in her +documentation, the translator may want to quote the previous +translation in her translator comments. To do so, she may initialize +the translator comments with the previous translation, still at the +head of the kill ring. Because editing already pushed the previous +translation on the kill ring, she merely has to type `M-w' prior to +`#', and the previous translation will be right there, all ready for +being introduced by some explanatory text. + + On the other hand, presume there are some translator comments already +and that the translator wants to add to those comments, instead of +wholly replacing them. Then, she should edit the comment right away +with `#'. Once inside the editing window, she can use the regular +Emacs commands `C-y' (`yank') and `M-y' (`yank-pop') to get the +previous translation where she likes. + + +File: gettext.info, Node: Subedit, Next: Auxiliary, Prev: Modifying Comments, Up: Updating + +Details of Sub Edition +====================== + + The PO subedit minor mode has a few peculiarities worth being +described in fuller detail. It installs a few commands over the usual +editing set of Emacs, which are described below. + +`C-c C-c' + Complete edition. + +`C-c C-k' + Abort edition. + +`C-c C-a' + Consult auxiliary PO files. + + The windows contents represents a translation for a given message, +or a translator comment. The translator may modify this window to her +heart's content. Once this done, the command `C-c C-c' +(`po-subedit-exit') may be used to return the edited translation into +the PO file, replacing the original translation, even if it moved out of +sight or if buffers were switched. + + If the translator becomes unsatisfied with her translation or +comment, to the extent she prefers keeping what was existent prior to +the `<RET>' or `#' command, she may use the command `C-c C-k' +(`po-subedit-abort') to merely get rid of edition, while preserving the +original translation or comment. Another way would be for her to exit +normally with `C-c C-c', then type `U' once for undoing the whole +effect of last edition. + + The command `C-c C-a' allows for glancing through translations +already achieved in other languages, directly while editing the current +translation. This may be quite convenient when the translator is fluent +at many languages, but of course, only makes sense when such completed +auxiliary PO files are already available to her (*note Auxiliary::.). + + Functions found on `po-subedit-mode-hook', if any, are executed after +the string has been inserted in the edit buffer. + + While editing her translation, the translator should pay attention +to not inserting unwanted `<RET>' (carriage returns) characters at the +end of the translated string if those are not meant to be there, or to +removing such characters when they are required. Since these +characters are not visible in the editing buffer, they are easily +introduced by mistake. To help her, `<RET>' automatically puts the +character `<' at the end of the string being edited, but this `<' is +not really part of the string. On exiting the editing window with +`C-c C-c', PO mode automatically removes such `<' and all whitespace +added after it. If the translator adds characters after the +terminating `<', it looses its delimiting property and integrally +becomes part of the string. If she removes the delimiting `<', then +the edited string is taken *as is*, with all trailing newlines, even if +invisible. Also, if the translated string ought to end itself with a +genuine `<', then the delimiting `<' may not be removed; so the string +should appear, in the editing window, as ending with two `<' in a row. + + When a translation (or a comment) is being edited, the translator +may move the cursor back into the PO file buffer and freely move to +other entries, browsing at will. If, with an edition pending, the +translator wanders in the PO file buffer, she may decide to start +modifying another entry. Each entry being edited has its own subedit +buffer. It is possible to simultaneously edit the translation *and* +the comment of a single entry, or to edit entries in different PO +files, all at once. Typing `<RET>' on a field already being edited +merely resume that particular edit. Yet, the translator should better +be comfortable at handling many Emacs windows! + + Pending subedits may be completed or aborted in any order, regardless +of how or when they were started. When many subedits are pending and +the translator asks for quitting the PO file (with the `q' command), +subedits are automatically resumed one at a time, so she may decide for +each of them. + + +File: gettext.info, Node: Auxiliary, Prev: Subedit, Up: Updating + +Consulting Auxiliary PO Files +============================= + + PO mode is able to help the knowledgeable translator, being fluent in +many languages, at taking advantage of translations already achieved in +other languages she just happens to know. It provides these other +language translations as additional context for her own work. Moreover, +it has features to ease the production of translations for many +languages at once, for translators preferring to work in this way. + + An "auxiliary" PO file is an existing PO file meant for the same +package the translator is working on, but targeted to a different mother +tongue language. Commands exist for declaring and handling auxiliary +PO files, and also for showing contexts for the entry under work. + + Here are the auxiliary file commands available in PO mode. + +`a' + Seek auxiliary files for another translation for the same entry. + +`M-a' + Switch to a particular auxiliary file. + +`A' + Declare this PO file as an auxiliary file. + +`M-A' + Remove this PO file from the list of auxiliary files. + + Command `A' (`po-consider-as-auxiliary') adds the current PO file to +the list of auxiliary files, while command `M-A' +(`po-ignore-as-auxiliary' just removes it. + + The command `a' (`po-cycle-auxiliary') seeks all auxiliary PO files, +round-robin, searching for a translated entry in some other language +having an `msgid' field identical as the one for the current entry. +The found PO file, if any, takes the place of the current PO file in +the display (its window gets on top). Before doing so, the current PO +file is also made into an auxiliary file, if not already. So, `a' in +this newly displayed PO file will seek another PO file, and so on, so +repeating `a' will eventually yield back the original PO file. + + The command `M-a' (`po-select-auxiliary') asks the translator for +her choice of a particular auxiliary file, with completion, and then +switches to that selected PO file. The command also checks if the +selected file has an `msgid' field identical as the one for the current +entry, and if yes, this entry becomes current. Otherwise, the cursor +of the selected file is left undisturbed. + + For all this to work fully, auxiliary PO files will have to be +normalized, in that way that `msgid' fields should be written *exactly* +the same way. It is possible to write `msgid' fields in various ways +for representing the same string, different writing would break the +proper behaviour of the auxiliary file commands of PO mode. This is not +expected to be much a problem in practice, as most existing PO files +have their `msgid' entries written by the same GNU `gettext' tools. + + However, PO files initially created by PO mode itself, while marking +strings in source files, are normalised differently. So are PO files +resulting of the the `M-x normalize' command. Until these +discrepancies between PO mode and other GNU `gettext' tools get fully +resolved, the translator should stay aware of normalisation issues. + + +File: gettext.info, Node: Binaries, Next: Users, Prev: Updating, Up: Top + +Producing Binary MO Files +************************* + +* Menu: + +* msgfmt Invocation:: Invoking the `msgfmt' Program +* MO Files:: The Format of GNU MO Files + + +File: gettext.info, Node: msgfmt Invocation, Next: MO Files, Prev: Binaries, Up: Binaries + +Invoking the `msgfmt' Program +============================= + + Usage: msgfmt [OPTION] FILENAME.po ... + +`-a NUMBER' +`--alignment=NUMBER' + Align strings to NUMBER bytes (default: 1). + +`-h' +`--help' + Display this help and exit. + +`--no-hash' + Binary file will not include the hash table. + +`-o FILE' +`--output-file=FILE' + Specify output file name as FILE. + +`--strict' + Direct the program to work strictly following the Uniforum/Sun + implementation. Currently this only affects the naming of the + output file. If this option is not given the name of the output + file is the same as the domain name. If the strict Uniforum mode + is enable the suffix `.mo' is added to the file name if it is not + already present. + + We find this behaviour of Sun's implementation rather silly and so + by default this mode is *not* selected. + +`-v' +`--verbose' + Detect and diagnose input file anomalies which might represent + translation errors. The `msgid' and `msgstr' strings are studied + and compared. It is considered abnormal that one string starts or + ends with a newline while the other does not. + + Also, if the string represents a format sring used in a + `printf'-like function both strings should have the same number of + `%' format specifiers, with matching types. If the flag + `c-format' or `possible-c-format' appears in the special comment + <#,> for this entry a check is performed. For example, the check + will diagnose using `%.*s' against `%s', or `%d' against `%s', or + `%d' against `%x'. It can even handle positional parameters. + + Normally the `xgettext' program automatically decides whether a + string is a format string or not. This algorithm is not perfect, + though. It might regard a string as a format string though it is + not used in a `printf'-like function and so `msgfmt' might report + errors where there are none. Or the other way round: a string is + not regarded as a format string but it is used in a `printf'-like + function. + + So solve this problem the programmer can dictate the decision to + the `xgettext' program (*note c-format::.). The translator should + not consider removing the flag from the <#,> line. This "fix" + would be reversed again as soon as `msgmerge' is called the next + time. + +`-V' +`--version' + Output version information and exit. + + If input file is `-', standard input is read. If output file is +`-', output is written to standard output. + + +File: gettext.info, Node: MO Files, Prev: msgfmt Invocation, Up: Binaries + +The Format of GNU MO Files +========================== + + The format of the generated MO files is best described by a picture, +which appears below. + + The first two words serve the identification of the file. The magic +number will always signal GNU MO files. The number is stored in the +byte order of the generating machine, so the magic number really is two +numbers: `0x950412de' and `0xde120495'. The second word describes the +current revision of the file format. For now the revision is 0. This +might change in future versions, and ensures that the readers of MO +files can distinguish new formats from old ones, so that both can be +handled correctly. The version is kept separate from the magic number, +instead of using different magic numbers for different formats, mainly +because `/etc/magic' is not updated often. It might be better to have +magic separated from internal format version identification. + + Follow a number of pointers to later tables in the file, allowing +for the extension of the prefix part of MO files without having to +recompile programs reading them. This might become useful for later +inserting a few flag bits, indication about the charset used, new +tables, or other things. + + Then, at offset O and offset T in the picture, two tables of string +descriptors can be found. In both tables, each string descriptor uses +two 32 bits integers, one for the string length, another for the offset +of the string in the MO file, counting in bytes from the start of the +file. The first table contains descriptors for the original strings, +and is sorted so the original strings are in increasing lexicographical +order. The second table contains descriptors for the translated +strings, and is parallel to the first table: to find the corresponding +translation one has to access the array slot in the second array with +the same index. + + Having the original strings sorted enables the use of simple binary +search, for when the MO file does not contain an hashing table, or for +when it is not practical to use the hashing table provided in the MO +file. This also has another advantage, as the empty string in a PO +file GNU `gettext' is usually *translated* into some system information +attached to that particular MO file, and the empty string necessarily +becomes the first in both the original and translated tables, making +the system information very easy to find. + + The size S of the hash table can be zero. In this case, the hash +table itself is not contained in the MO file. Some people might prefer +this because a precomputed hashing table takes disk space, and does not +win *that* much speed. The hash table contains indices to the sorted +array of strings in the MO file. Conflict resolution is done by double +hashing. The precise hashing algorithm used is fairly dependent of GNU +`gettext' code, and is not documented here. + + As for the strings themselves, they follow the hash file, and each +is terminated with a <NUL>, and this <NUL> is not counted in the length +which appears in the string descriptor. The `msgfmt' program has an +option selecting the alignment for MO file strings. With this option, +each string is separately aligned so it starts at an offset which is a +multiple of the alignment value. On some RISC machines, a correct +alignment will speed things up. + + Nothing prevents a MO file from having embedded <NUL>s in strings. +However, the program interface currently used already presumes that +strings are <NUL> terminated, so embedded <NUL>s are somewhat useless. +But MO file format is general enough so other interfaces would be later +possible, if for example, we ever want to implement wide characters +right in MO files, where <NUL> bytes may accidently appear. + + This particular issue has been strongly debated in the GNU `gettext' +development forum, and it is expectable that MO file format will evolve +or change over time. It is even possible that many formats may later +be supported concurrently. But surely, we have to start somewhere, and +the MO file format described here is a good start. Nothing is cast in +concrete, and the format may later evolve fairly easily, so we should +feel comfortable with the current approach. + + byte + +------------------------------------------+ + 0 | magic number = 0x950412de | + | | + 4 | file format revision = 0 | + | | + 8 | number of strings | == N + | | + 12 | offset of table with original strings | == O + | | + 16 | offset of table with translation strings | == T + | | + 20 | size of hashing table | == S + | | + 24 | offset of hashing table | == H + | | + . . + . (possibly more entries later) . + . . + | | + O | length & offset 0th string ----------------. + O + 8 | length & offset 1st string ------------------. + ... ... | | + O + ((N-1)*8)| length & offset (N-1)th string | | | + | | | | + T | length & offset 0th translation ---------------. + T + 8 | length & offset 1st translation -----------------. + ... ... | | | | + T + ((N-1)*8)| length & offset (N-1)th translation | | | | | + | | | | | | + H | start hash table | | | | | + ... ... | | | | + H + S * 4 | end hash table | | | | | + | | | | | | + | NUL terminated 0th string <----------------' | | | + | | | | | + | NUL terminated 1st string <------------------' | | + | | | | + ... ... | | + | | | | + | NUL terminated 0th translation <---------------' | + | | | + | NUL terminated 1st translation <-----------------' + | | + ... ... + | | + +------------------------------------------+ + + +File: gettext.info, Node: Users, Next: Programmers, Prev: Binaries, Up: Top + +The User's View +*************** + + When GNU `gettext' will truly have reached is goal, average users +should feel some kind of astonished pleasure, seeing the effect of that +strange kind of magic that just makes their own native language appear +everywhere on their screens. As for naive users, they would ideally +have no special pleasure about it, merely taking their own language for +*granted*, and becoming rather unhappy otherwise. + + So, let's try to describe here how we would like the magic to +operate, as we want the users' view to be the simplest, among all ways +one could look at GNU `gettext'. All other software engineers: +programmers, translators, maintainers, should work together in such a +way that the magic becomes possible. This is a long and progressive +undertaking, and information is available about the progress of the +Translation Project. + + When a package is distributed, there are two kind of users: +"installers" who fetch the distribution, unpack it, configure it, +compile it and install it for themselves or others to use; and "end +users" that call programs of the package, once these have been +installed at their site. GNU `gettext' is offering magic for both +installers and end users. + +* Menu: + +* Matrix:: The Current `ABOUT-NLS' Matrix +* Installers:: Magic for Installers +* End Users:: Magic for End Users + + +File: gettext.info, Node: Matrix, Next: Installers, Prev: Users, Up: Users + +The Current `ABOUT-NLS' Matrix +============================== + + Languages are not equally supported in all packages using GNU +`gettext'. To know if some package uses GNU `gettext', one may check +the distribution for the `ABOUT-NLS' information file, for some `LL.po' +files, often kept together into some `po/' directory, or for an `intl/' +directory. Internationalized packages have usually many `LL.po' files, +where LL represents the language. *Note End Users:: for a complete +description of the format for LL. + + More generally, a matrix is available for showing the current state +of the Translation Project, listing which packages are prepared for +multi-lingual messages, and which languages is supported by each. +Because this information changes often, this matrix is not kept within +this GNU `gettext' manual. This information is often found in file +`ABOUT-NLS' from various distributions, but is also as old as the +distribution itself. A recent copy of this `ABOUT-NLS' file, +containing up-to-date information, should generally be found on the +Translation Project sites, and also on most GNU archive sites. + + +File: gettext.info, Node: Installers, Next: End Users, Prev: Matrix, Up: Users + +Magic for Installers +==================== + + By default, packages fully using GNU `gettext', internally, are +installed in such a way that they to allow translation of messages. At +*configuration* time, those packages should automatically detect +whether the underlying host system provides usable `catgets' or +`gettext' functions. If neither is present, the GNU `gettext' library +should be automatically prepared and used. Installers may use special +options at configuration time for changing this behavior. The command +`./configure --with-included-gettext' bypasses system `catgets' or +`gettext' to use GNU `gettext' instead, while `./configure +--disable-nls' produces program totally unable to translate messages. + + Internationalized packages have usually many `LL.po' files. Unless +translations are disabled, all those available are installed together +with the package. However, the environment variable `LINGUAS' may be +set, prior to configuration, to limit the installed set. `LINGUAS' +should then contain a space separated list of two-letter codes, stating +which languages are allowed. + + +File: gettext.info, Node: End Users, Prev: Installers, Up: Users + +Magic for End Users +=================== + + We consider here those packages using GNU `gettext' internally, and +for which the installers did not disable translation at *configure* +time. Then, users only have to set the `LANG' environment variable to +the appropriate `LL' prior to using the programs in the package. *Note +Matrix::. For example, let's presume a German site. At the shell +prompt, users merely have to execute `setenv LANG de' (in `csh') or +`export LANG; LANG=de' (in `sh'). They could even do this from their +`.login' or `.profile' file. + + +File: gettext.info, Node: Programmers, Next: Translators, Prev: Users, Up: Top + +The Programmer's View +********************* + + One aim of the current message catalog implementation provided by +GNU `gettext' was to use the systems message catalog handling, if the +installer wishes to do so. So we perhaps should first take a look at +the solutions we know about. The people in the POSIX committee does not +manage to agree on one of the semi-official standards which we'll +describe below. In fact they couldn't agree on anything, so nothing +decide only to include an example of an interface. The major Unix +vendors are split in the usage of the two most important +specifications: X/Opens catgets vs. Uniforums gettext interface. We'll +describe them both and later explain our solution of this dilemma. + +* Menu: + +* catgets:: About `catgets' +* gettext:: About `gettext' +* Comparison:: Comparing the two interfaces +* Using libintl.a:: Using libintl.a in own programs +* gettext grok:: Being a `gettext' grok +* Temp Programmers:: Temporary Notes for the Programmers Chapter + + +File: gettext.info, Node: catgets, Next: gettext, Prev: Programmers, Up: Programmers + +About `catgets' +=============== + + The `catgets' implementation is defined in the X/Open Portability +Guide, Volume 3, XSI Supplementary Definitions, Chapter 5. But the +process of creating this standard seemed to be too slow for some of the +Unix vendors so they created their implementations on preliminary +versions of the standard. Of course this leads again to problems while +writing platform independent programs: even the usage of `catgets' does +not guarantee a unique interface. + + Another, personal comment on this that only a bunch of committee +members could have made this interface. They never really tried to +program using this interface. It is a fast, memory-saving +implementation, an user can happily live with it. But programmers hate +it (at least me and some others do...) + + But we must not forget one point: after all the trouble with +transfering the rights on Unix(tm) they at last came to X/Open, the +very same who published this specifications. This leads me to making +the prediction that this interface will be in future Unix standards +(e.g. Spec1170) and therefore part of all Unix implementation +(implementations, which are *allowed* to wear this name). + +* Menu: + +* Interface to catgets:: The interface +* Problems with catgets:: Problems with the `catgets' interface?! + + +File: gettext.info, Node: Interface to catgets, Next: Problems with catgets, Prev: catgets, Up: catgets + +The Interface +------------- + + The interface to the `catgets' implementation consists of three +functions which correspond to those used in file access: `catopen' to +open the catalog for using, `catgets' for accessing the message tables, +and `catclose' for closing after work is done. Prototypes for the +functions and the needed definitions are in the `<nl_types.h>' header +file. + + `catopen' is used like in this: + + nl_catd catd = catopen ("catalog_name", 0); + + The function takes as the argument the name of the catalog. This +usual refers to the name of the program or the package. The second +parameter is not further specified in the standard. I don't even know +whether it is implemented consistently among various systems. So the +common advice is to use `0' as the value. The return value is a handle +to the message catalog, equivalent to handles to file returned by +`open'. + + This handle is of course used in the `catgets' function which can be +used like this: + + char *translation = catgets (catd, set_no, msg_id, "original string"); + + The first parameter is this catalog descriptor. The second parameter +specifies the set of messages in this catalog, in which the message +described by `msg_id' is obtained. `catgets' therefore uses a +three-stage addressing: + + catalog name => set number => message ID => translation + + The fourth argument is not used to address the translation. It is +given as a default value in case when one of the addressing stages +fail. One important thing to remember is that although the return type +of catgets is `char *' the resulting string *must not* be changed. It +should better `const char *', but the standard is published in 1988, +one year before ANSI C. + +The last of these function functions is used and behaves as expected: + + catclose (catd); + + After this no `catgets' call using the descriptor is legal anymore. + + +File: gettext.info, Node: Problems with catgets, Prev: Interface to catgets, Up: catgets + +Problems with the `catgets' Interface?! +--------------------------------------- + + Now that this descriptions seemed to be really easy where are the +problem we speak of. In fact the interface could be used in a +reasonable way, but constructing the message catalogs is a pain. The +reason for this lies in the third argument of `catgets': the unique +message ID. This has to be a numeric value for all messages in a single +set. Perhaps you could imagine the problems keeping such list while +changing the source code. Add a new message here, remove one there. Of +course there have been developed a lot of tools helping to organize this +chaos but one as the other fails in one aspect or the other. We don't +want to say that the other approach has no problems but they are far +more easily to manage. + + +File: gettext.info, Node: gettext, Next: Comparison, Prev: catgets, Up: Programmers + +About `gettext' +=============== + + The definition of the `gettext' interface comes from a Uniforum +proposal and it is followed by at least one major Unix vendor (Sun) in +its last developments. It is not specified in any official standard, +though. + + The main points about this solution is that it does not follow the +method of normal file handling (open-use-close) and that it does not +burden the programmer so many task, especially the unique key handling. +Of course here is also a unique key needed, but this key is the message +itself (how long or short it is). See *Note Comparison:: for a more +detailed comparison of the two methods. + + The following section contains a rather detailed description of the +interface. We make it that detailed because this is the interface we +chose for the GNU `gettext' Library. Programmers interested in using +this library will be interested in this description. + +* Menu: + +* Interface to gettext:: The interface +* Ambiguities:: Solving ambiguities +* Locating Catalogs:: Locating message catalog files +* Optimized gettext:: Optimization of the *gettext functions + + +File: gettext.info, Node: Interface to gettext, Next: Ambiguities, Prev: gettext, Up: gettext + +The Interface +------------- + + The minimal functionality an interface must have is a) to select a +domain the strings are coming from (a single domain for all programs is +not reasonable because its construction and maintenance is difficult, +perhaps impossible) and b) to access a string in a selected domain. + + This is principally the description of the `gettext' interface. It +has an global domain which unqualified usages reference. Of course this +domain is selectable by the user. + + char *textdomain (const char *domain_name); + + This provides the possibility to change or query the current status +of the current global domain of the `LC_MESSAGE' category. The +argument is a null-terminated string, whose characters must be legal in +the use in filenames. If the DOMAIN_NAME argument is `NULL', the +function return the current value. If no value has been set before, +the name of the default domain is returned: *messages*. Please note +that although the return value of `textdomain' is of type `char *' no +changing is allowed. It is also important to know that no checks of +the availability are made. If the name is not available you will see +this by the fact that no translations are provided. + +To use a domain set by `textdomain' the function + + char *gettext (const char *msgid); + + is to be used. This is the simplest reasonable form one can imagine. +The translation of the string MSGID is returned if it is available in +the current domain. If not available the argument itself is returned. +If the argument is `NULL' the result is undefined. + + One things which should come into mind is that no explicit +dependency to the used domain is given. The current value of the +domain for the `LC_MESSAGES' locale is used. If this changes between +two executions of the same `gettext' call in the program, both calls +reference a different message catalog. + + For the easiest case, which is normally used in internationalized +packages, once at the beginning of execution a call to `textdomain' is +issued, setting the domain to a unique name, normally the package name. +In the following code all strings which have to be translated are +filtered through the gettext function. That's all, the package speaks +your language. + + +File: gettext.info, Node: Ambiguities, Next: Locating Catalogs, Prev: Interface to gettext, Up: gettext + +Solving Ambiguities +------------------- + + While this single name domain work good for most applications there +might be the need to get translations from more than one domain. Of +course one could switch between different domains with calls to +`textdomain', but this is really not convenient nor is it fast. A +possible situation could be one case discussing while this writing: all +error messages of functions in the set of common used functions should +go into a separate domain `error'. By this mean we would only need to +translate them once. + +For this reasons there are two more functions to retrieve strings: + + char *dgettext (const char *domain_name, const char *msgid); + char *dcgettext (const char *domain_name, const char *msgid, + int category); + + Both take an additional argument at the first place, which +corresponds to the argument of `textdomain'. The third argument of +`dcgettext' allows to use another locale but `LC_MESSAGES'. But I +really don't know where this can be useful. If the DOMAIN_NAME is +`NULL' or CATEGORY has an value beside the known ones, the result is +undefined. It should also be noted that this function is not part of +the second known implementation of this function family, the one found +in Solaris. + + A second ambiguity can arise by the fact, that perhaps more than one +domain has the same name. This can be solved by specifying where the +needed message catalog files can be found. + + char *bindtextdomain (const char *domain_name, + const char *dir_name); + + Calling this function binds the given domain to a file in the +specified directory (how this file is determined follows below). +Especially a file in the systems default place is not favored against +the specified file anymore (as it would be by solely using +`textdomain'). A `NULL' pointer for the DIR_NAME parameter returns the +binding associated with DOMAIN_NAME. If DOMAIN_NAME itself is `NULL' +nothing happens and a `NULL' pointer is returned. Here again as for +all the other functions is true that none of the return value must be +changed! + + It is important to remember that relative path names for the +DIR_NAME parameter can be trouble. Since the path is always computed +relative to the current directory different results will be achieved +when the program executes a `chdir' command. Relative paths should +always be avoided to avoid dependencies and unreliabilities. + + +File: gettext.info, Node: Locating Catalogs, Next: Optimized gettext, Prev: Ambiguities, Up: gettext + +Locating Message Catalog Files +------------------------------ + + Because many different languages for many different packages have to +be stored we need some way to add these information to file message +catalog files. The way usually used in Unix environments is have this +encoding in the file name. This is also done here. The directory name +given in `bindtextdomain's second argument (or the default directory), +followed by the value and name of the locale and the domain name are +concatenated: + + DIR_NAME/LOCALE/LC_CATEGORY/DOMAIN_NAME.mo + + The default value for DIR_NAME is system specific. For the GNU +library, and for packages adhering to its conventions, it's: + /usr/local/share/locale + +LOCALE is the value of the locale whose name is this `LC_CATEGORY'. +For `gettext' and `dgettext' this locale is always `LC_MESSAGES'. +`dcgettext' specifies the locale by the third argument.(1) (2) + + ---------- Footnotes ---------- + + (1) Some system, eg Ultrix, don't have `LC_MESSAGES'. Here we use a +more or less arbitrary value for it. + + (2) When the system does not support `setlocale' its behavior in +setting the locale values is simulated by looking at the environment +variables. + diff --git a/doc/gettext.info-4 b/doc/gettext.info-4 new file mode 100644 index 0000000..21f46dd --- /dev/null +++ b/doc/gettext.info-4 @@ -0,0 +1,1110 @@ +This is Info file gettext.info, produced by Makeinfo version 1.68 from +the input file gettext.texi. + +INFO-DIR-SECTION GNU Gettext Utilities +START-INFO-DIR-ENTRY +* Gettext: (gettext). GNU gettext utilities. +* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext. +* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files. +* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one. +* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file. +END-INFO-DIR-ENTRY + + This file provides documentation for GNU `gettext' utilities. It +also serves as a reference for the free Translation Project. + + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gettext.info, Node: Optimized gettext, Prev: Locating Catalogs, Up: gettext + +Optimization of the *gettext functions +-------------------------------------- + + At this point of the discussion we should talk about an advantage of +the GNU `gettext' implementation. Some readers might have pointed out +that an internationalized program might have a poor performance if some +string has to be translated in an inner loop. While this is unavoidable +when the string varies from one run of the loop to the other it is +simply a waste of time when the string is always the same. Take the +following example: + + { + while (...) + { + puts (gettext ("Hello world")); + } + } + +When the locale selection does not change between two runs the resulting +string is always the same. One way to use this is: + + { + str = gettext ("Hello world"); + while (...) + { + puts (str); + } + } + +But this solution is not usable in all situation (e.g. when the locale +selection changes) nor is it good readable. + + The GNU C compiler, version 2.7 and above, provide another solution +for this. To describe this we show here some lines of the +`intl/libgettext.h' file. For an explanation of the expression command +block see *Note Statements and Declarations in Expressions: +(gcc)Statement Exprs. + + # if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + extern int _nl_msg_cat_cntr; + # define dcgettext(domainname, msgid, category) \ + (__extension__ \ + ({ \ + char *result; \ + if (__builtin_constant_p (msgid)) \ + { \ + static char *__translation__; \ + static int __catalog_counter__; \ + if (! __translation__ \ + || __catalog_counter__ != _nl_msg_cat_cntr) \ + { \ + __translation__ = \ + dcgettext__ ((domainname), (msgid), (category)); \ + __catalog_counter__ = _nl_msg_cat_cntr; \ + } \ + result = __translation__; \ + } \ + else \ + result = dcgettext__ ((domainname), (msgid), (category)); \ + result; \ + })) + # endif + + The interesting thing here is the `__builtin_constant_p' predicate. +This is evaluated at compile time and so optimization can take place +immediately. Here two cases are distinguished: the argument to +`gettext' is not a constant value in which case simply the function +`dcgettext__' is called, the real implementation of the `dcgettext' +function. + + If the string argument *is* constant we can reuse the once gained +translation when the locale selection has not changed. This is exactly +what is done here. The `_nl_msg_cat_cntr' variable is defined in the +`loadmsgcat.c' which is available in `libintl.a' and is changed +whenever a new message catalog is loaded. + + +File: gettext.info, Node: Comparison, Next: Using libintl.a, Prev: gettext, Up: Programmers + +Comparing the Two Interfaces +============================ + + The following discussion is perhaps a little bit colored. As said +above we implemented GNU `gettext' following the Uniforum proposal and +this surely has its reasons. But it should show how we came to this +decision. + + First we take a look at the developing process. When we write an +application using NLS provided by `gettext' we proceed as always. Only +when we come to a string which might be seen by the users and thus has +to be translated we use `gettext("...")' instead of `"..."'. At the +beginning of each source file (or in a central header file) we define + + #define gettext(String) (String) + + Even this definition can be avoided when the system supports the +`gettext' function in its C library. When we compile this code the +result is the same as if no NLS code is used. When you take a look at +the GNU `gettext' code you will see that we use `_("...")' instead of +`gettext("...")'. This reduces the number of additional characters per +translatable string to *3* (in words: three). + + When now a production version of the program is needed we simply +replace the definition + + #define _(String) (String) + +by + + #include <libintl.h> + #define _(String) gettext (String) + +Additionally we run the program `xgettext' on all source code file +which contain translatable strings and that's it: we have a running +program which does not depend on translations to be available, but which +can use any that becomes available. + + The same procedure can be done for the `gettext_noop' invocations +(*note Special cases::.). First you can define `gettext_noop' to a +no-op macro and later use the definition from `libintl.h'. Because +this name is not used in Suns implementation of `libintl.h', you should +consider the following code for your project: + + #ifdef gettext_noop + # define N_(String) gettext_noop (String) + #else + # define N_(String) (String) + #endif + + `N_' is a short form similar to `_'. The `Makefile' in the `po/' +directory of GNU `gettext' knows by default both of the mentioned short +forms so you are invited to follow this proposal for your own ease. + + Now to `catgets'. The main problem is the work for the programmer. +Every time he comes to a translatable string he has to define a number +(or a symbolic constant) which has also be defined in the message +catalog file. He also has to take care for duplicate entries, +duplicate message IDs etc. If he wants to have the same quality in the +message catalog as the GNU `gettext' program provides he also has to +put the descriptive comments for the strings and the location in all +source code files in the message catalog. This is nearly a Mission: +Impossible. + + But there are also some points people might call advantages speaking +for `catgets'. If you have a single word in a string and this string +is used in different contexts it is likely that in one or the other +language the word has different translations. Example: + + printf ("%s: %d", gettext ("number"), number_of_errors) + + printf ("you should see %d %s", number_count, + number_count == 1 ? gettext ("number") : gettext ("numbers")) + + Here we have to translate two times the string `"number"'. Even if +you do not speak a language beside English it might be possible to +recognize that the two words have a different meaning. In German the +first appearance has to be translated to `"Anzahl"' and the second to +`"Zahl"'. + + Now you can say that this example is really esoteric. And you are +right! This is exactly how we felt about this problem and decide that +it does not weight that much. The solution for the above problem could +be very easy: + + printf ("%s %d", gettext ("number:"), number_of_errors) + + printf (number_count == 1 ? gettext ("you should see %d number") + : gettext ("you should see %d numbers"), + number_count) + + We believe that we can solve all conflicts with this method. If it +is difficult one can also consider changing one of the conflicting +string a little bit. But it is not impossible to overcome. + + Translator note: It is perhaps appropriate here to tell those English +speaking programmers that the plural form of a noun cannot be formed by +appending a single `s'. Most other languages use different methods. +Even the above form is not general enough to cope with all languages. +Rafal Maszkowski <rzm@mat.uni.torun.pl> reports: + + In Polish we use e.g. plik (file) this way: + 1 plik + 2,3,4 pliki + 5-21 pliko'w + 22-24 pliki + 25-31 pliko'w + and so on (o' means 8859-2 oacute which should be rather okreska, + similar to aogonek). + + A workable approach might be to consider methods like the one used +for `LC_TIME' in the POSIX.2 standard. The value of the `alt_digits' +field can be up to 100 strings which represent the numbers 1 to 100. +Using this in a situation of an internationalized program means that an +array of translatable strings should be indexed by the number which +should represent. A small example: + + void + print_month_info (int month) + { + const char *month_pos[12] = + { N_("first"), N_("second"), N_("third"), N_("fourth"), + N_("fifth"), N_("sixth"), N_("seventh"), N_("eighth"), + N_("ninth"), N_("tenth"), N_("eleventh"), N_("twelfth") }; + printf (_("%s is the %s month\n"), nl_langinfo (MON_1 + month), + _(month_pos[month])); + } + +It should be obvious that this method is only reasonable for small +ranges of numbers. + + +File: gettext.info, Node: Using libintl.a, Next: gettext grok, Prev: Comparison, Up: Programmers + +Using libintl.a in own programs +=============================== + + Starting with version 0.9.4 the library `libintl.h' should be +self-contained. I.e., you can use it in your own programs without +providing additional functions. The `Makefile' will put the header and +the library in directories selected using the `$(prefix)'. + + One exception of the above is found on HP-UX systems. Here the C +library does not contain the `alloca' function (and the HP compiler does +not generate it inlined). But it is not intended to rewrite the whole +library just because of this dumb system. Instead include the `alloca' +function in all package you use the `libintl.a' in. + + +File: gettext.info, Node: gettext grok, Next: Temp Programmers, Prev: Using libintl.a, Up: Programmers + +Being a `gettext' grok +====================== + + To fully exploit the functionality of the GNU `gettext' library it +is surely helpful to read the source code. But for those who don't want +to spend that much time in reading the (sometimes complicated) code here +is a list comments: + + * Changing the language at runtime + + For interactive programs it might be useful to offer a selection + of the used language at runtime. To understand how to do this one + need to know how the used language is determined while executing + the `gettext' function. The method which is presented here only + works correctly with the GNU implementation of the `gettext' + functions. It is not possible with underlying `catgets' functions + or `gettext' functions from the systems C library. The exception + is of course the GNU C Library which uses the GNU `gettext' + Library for message handling. + + In the function `dcgettext' at every call the current setting of + the highest priority environment variable is determined and used. + Highest priority means here the following list with decreasing + priority: + + 1. `LANGUAGE' + + 2. `LC_ALL' + + 3. `LC_xxx', according to selected locale + + 4. `LANG' + + Afterwards the path is constructed using the found value and the + translation file is loaded if available. + + What is now when the value for, say, `LANGUAGE' changes. According + to the process explained above the new value of this variable is + found as soon as the `dcgettext' function is called. But this + also means the (perhaps) different message catalog file is loaded. + In other words: the used language is changed. + + But there is one little hook. The code for gcc-2.7.0 and up + provides some optimization. This optimization normally prevents + the calling of the `dcgettext' function as long as no new catalog + is loaded. But if `dcgettext' is not called the program also + cannot find the `LANGUAGE' variable be changed (*note Optimized + gettext::.). A solution for this is very easy. Include the + following code in the language switching function. + + /* Change language. */ + setenv ("LANGUAGE", "fr", 1); + + /* Make change known. */ + { + extern int _nl_msg_cat_cntr; + ++_nl_msg_cat_cntr; + } + + The variable `_nl_msg_cat_cntr' is defined in `loadmsgcat.c'. The + programmer will find himself in need for a construct like this only + when developing programs which do run longer and provide the user + to select the language at runtime. Non-interactive programs (like + all these little Unix tools) should never need this. + + +File: gettext.info, Node: Temp Programmers, Prev: gettext grok, Up: Programmers + +Temporary Notes for the Programmers Chapter +=========================================== + +* Menu: + +* Temp Implementations:: Temporary - Two Possible Implementations +* Temp catgets:: Temporary - About `catgets' +* Temp WSI:: Temporary - Why a single implementation +* Temp Notes:: Temporary - Notes + + +File: gettext.info, Node: Temp Implementations, Next: Temp catgets, Prev: Temp Programmers, Up: Temp Programmers + +Temporary - Two Possible Implementations +---------------------------------------- + + There are two competing methods for language independent messages: +the X/Open `catgets' method, and the Uniforum `gettext' method. The +`catgets' method indexes messages by integers; the `gettext' method +indexes them by their English translations. The `catgets' method has +been around longer and is supported by more vendors. The `gettext' +method is supported by Sun, and it has been heard that the COSE +multi-vendor initiative is supporting it. Neither method is a POSIX +standard; the POSIX.1 committee had a lot of disagreement in this area. + + Neither one is in the POSIX standard. There was much disagreement +in the POSIX.1 committee about using the `gettext' routines vs. +`catgets' (XPG). In the end the committee couldn't agree on anything, +so no messaging system was included as part of the standard. I believe +the informative annex of the standard includes the XPG3 messaging +interfaces, "...as an example of a messaging system that has been +implemented..." + + They were very careful not to say anywhere that you should use one +set of interfaces over the other. For more on this topic please see +the Programming for Internationalization FAQ. + + +File: gettext.info, Node: Temp catgets, Next: Temp WSI, Prev: Temp Implementations, Up: Temp Programmers + +Temporary - About `catgets' +--------------------------- + + There have been a few discussions of late on the use of `catgets' as +a base. I think it important to present both sides of the argument and +hence am opting to play devil's advocate for a little bit. + + I'll not deny the fact that `catgets' could have been designed a lot +better. It currently has quite a number of limitations and these have +already been pointed out. + + However there is a great deal to be said for consistency and +standardization. A common recurring problem when writing Unix software +is the myriad portability problems across Unix platforms. It seems as +if every Unix vendor had a look at the operating system and found parts +they could improve upon. Undoubtedly, these modifications are probably +innovative and solve real problems. However, software developers have +a hard time keeping up with all these changes across so many platforms. + + And this has prompted the Unix vendors to begin to standardize their +systems. Hence the impetus for Spec1170. Every major Unix vendor has +committed to supporting this standard and every Unix software developer +waits with glee the day they can write software to this standard and +simply recompile (without having to use autoconf) across different +platforms. + + As I understand it, Spec1170 is roughly based upon version 4 of the +X/Open Portability Guidelines (XPG4). Because `catgets' and friends +are defined in XPG4, I'm led to believe that `catgets' is a part of +Spec1170 and hence will become a standardized component of all Unix +systems. + + +File: gettext.info, Node: Temp WSI, Next: Temp Notes, Prev: Temp catgets, Up: Temp Programmers + +Temporary - Why a single implementation +--------------------------------------- + + Now it seems kind of wasteful to me to have two different systems +installed for accessing message catalogs. If we do want to remedy +`catgets' deficiencies why don't we try to expand `catgets' (in a +compatible manner) rather than implement an entirely new system. +Otherwise, we'll end up with two message catalog access systems +installed with an operating system - one set of routines for packages +using GNU `gettext' for their internationalization, and another set of +routines (catgets) for all other software. Bloated? + + Supposing another catalog access system is implemented. Which do we +recommend? At least for Linux, we need to attract as many software +developers as possible. Hence we need to make it as easy for them to +port their software as possible. Which means supporting `catgets'. We +will be implementing the `glocale' code within our `libc', but does +this mean we also have to incorporate another message catalog access +scheme within our `libc' as well? And what about people who are going +to be using the `glocale' + non-`catgets' routines. When they port +their software to other platforms, they're now going to have to include +the front-end (`glocale') code plus the back-end code (the non-`catgets' +access routines) with their software instead of just including the +`glocale' code with their software. + + Message catalog support is however only the tip of the iceberg. +What about the data for the other locale categories. They also have a +number of deficiencies. Are we going to abandon them as well and +develop another duplicate set of routines (should `glocale' expand +beyond message catalog support)? + + Like many parts of Unix that can be improved upon, we're stuck with +balancing compatibility with the past with useful improvements and +innovations for the future. + + +File: gettext.info, Node: Temp Notes, Prev: Temp WSI, Up: Temp Programmers + +Temporary - Notes +----------------- + + X/Open agreed very late on the standard form so that many +implementations differ from the final form. Both of my system (old +Linux catgets and Ultrix-4) have a strange variation. + + OK. After incorporating the last changes I have to spend some time +on making the GNU/Linux `libc' `gettext' functions. So in future +Solaris is not the only system having `gettext'. + + +File: gettext.info, Node: Translators, Next: Maintainers, Prev: Programmers, Up: Top + +The Translator's View +********************* + +* Menu: + +* Trans Intro 0:: Introduction 0 +* Trans Intro 1:: Introduction 1 +* Discussions:: Discussions +* Organization:: Organization +* Information Flow:: Information Flow + + +File: gettext.info, Node: Trans Intro 0, Next: Trans Intro 1, Prev: Translators, Up: Translators + +Introduction 0 +============== + + Free software is going international! The Translation Project is a +way to get maintainers, translators and users all together, so free +software will gradually become able to speak many native languages. + + The GNU `gettext' tool set contains *everything* maintainers need +for internationalizing their packages for messages. It also contains +quite useful tools for helping translators at localizing messages to +their native language, once a package has already been +internationalized. + + To achieve the Translation Project, we need many interested people +who like their own language and write it well, and who are also able to +synergize with other translators speaking the same language. If you'd +like to volunteer to *work* at translating messages, please send mail +to your translating team. + + Each team has its own mailing list, courtesy of Linux International. +You may reach your translating team at the address `LL@li.org', +replacing LL by the two-letter ISO 639 code for your language. +Language codes are *not* the same as country codes given in ISO 3166. +The following translating teams exist: + + Chinese `zh', Czech `cs', Danish `da', Dutch `nl', Esperanto `eo', + Finnish `fi', French `fr', Irish `ga', German `de', Greek `el', + Italian `it', Japanese `ja', Indonesian `in', Norwegian `no', + Polish `pl', Portuguese `pt', Russian `ru', Spanish `es', Swedish + `sv' and Turkish `tr'. + +For example, you may reach the Chinese translating team by writing to +`zh@li.org'. When you become a member of the translating team for your +own language, you may subscribe to its list. For example, Swedish +people can send a message to `sv-request@li.org', having this message +body: + + subscribe + + Keep in mind that team members should be interested in *working* at +translations, or at solving translational difficulties, rather than +merely lurking around. If your team does not exist yet and you want to +start one, please write to `translation@iro.umontreal.ca'; you will +then reach the coordinator for all translator teams. + + A handful of GNU packages have already been adapted and provided +with message translations for several languages. Translation teams +have begun to organize, using these packages as a starting point. But +there are many more packages and many languages for which we have no +volunteer translators. If you would like to volunteer to work at +translating messages, please send mail to +`translation@iro.umontreal.ca' indicating what language(s) you can work +on. + + +File: gettext.info, Node: Trans Intro 1, Next: Discussions, Prev: Trans Intro 0, Up: Translators + +Introduction 1 +============== + + This is now official, GNU is going international! Here is the +announcement submitted for the January 1995 GNU Bulletin: + + A handful of GNU packages have already been adapted and provided + with message translations for several languages. Translation + teams have begun to organize, using these packages as a starting + point. But there are many more packages and many languages for + which we have no volunteer translators. If you'd like to + volunteer to work at translating messages, please send mail to + `translation@iro.umontreal.ca' indicating what language(s) you can + work on. + + This document should answer many questions for those who are curious +about the process or would like to contribute. Please at least skim +over it, hoping to cut down a little of the high volume of e-mail +generated by this collective effort towards internationalization of +free software. + + Most free programming which is widely shared is done in English, and +currently, English is used as the main communicating language between +national communities collaborating to free software. This very document +is written in English. This will not change in the foreseeable future. + + However, there is a strong appetite from national communities for +having more software able to write using national language and habits, +and there is an on-going effort to modify free software in such a way +that it becomes able to do so. The experiments driven so far raised an +enthusiastic response from pretesters, so we believe that +internationalization of free software is dedicated to succeed. + + For suggestion clarifications, additions or corrections to this +document, please e-mail to `translation@iro.umontreal.ca'. + + +File: gettext.info, Node: Discussions, Next: Organization, Prev: Trans Intro 1, Up: Translators + +Discussions +=========== + + Facing this internationalization effort, a few users expressed their +concerns. Some of these doubts are presented and discussed, here. + + * Smaller groups + + Some languages are not spoken by a very large number of people, so + people speaking them sometimes consider that there may not be all + that much demand such versions of free software packages. + Moreover, many people being *into computers*, in some countries, + generally seem to prefer English versions of their software. + + On the other end, people might enjoy their own language a lot, and + be very motivated at providing to themselves the pleasure of + having their beloved free software speaking their mother tongue. + They do themselves a personal favor, and do not pay that much + attention to the number of people beneficiating of their work. + + * Misinterpretation + + Other users are shy to push forward their own language, seeing in + this some kind of misplaced propaganda. Someone thought there + must be some users of the language over the networks pestering + other people with it. + + But any spoken language is worth localization, because there are + people behind the language for whom the language is important and + dear to their hearts. + + * Odd translations + + The biggest problem is to find the right translations so that + everybody can understand the messages. Translations are usually a + little odd. Some people get used to English, to the extent they + may find translations into their own language "rather pushy, + obnoxious and sometimes even hilarious." As a French speaking + man, I have the experience of those instruction manuals for goods, + so poorly translated in French in Korea or Taiwan... + + The fact is that we sometimes have to create a kind of national + computer culture, and this is not easy without the collaboration of + many people liking their mother tongue. This is why translations + are better achieved by people knowing and loving their own + language, and ready to work together at improving the results they + obtain. + + * Dependencies over the GPL + + Some people wonder if using GNU `gettext' necessarily brings their + package under the protective wing of the GNU General Public + License, when they do not want to make their program free, or want + other kinds of freedom. The simplest answer is yes. + + The mere marking of localizable strings in a package, or + conditional inclusion of a few lines for initialization, is not + really including GPL'ed code. However, the localization routines + themselves are under the GPL and would bring the remainder of the + package under the GPL if they were distributed with it. So, I + presume that, for those for which this is a problem, it could be + circumvented by letting to the end installers the burden of + assembling a package prepared for localization, but not providing + the localization routines themselves. + + +File: gettext.info, Node: Organization, Next: Information Flow, Prev: Discussions, Up: Translators + +Organization +============ + + On a larger scale, the true solution would be to organize some kind +of fairly precise set up in which volunteers could participate. I gave +some thought to this idea lately, and realize there will be some touchy +points. I thought of writing to Richard Stallman to launch such a +project, but feel it might be good to shake out the ideas between +ourselves first. Most probably that Linux International has some +experience in the field already, or would like to orchestrate the +volunteer work, maybe. Food for thought, in any case! + + I guess we have to setup something early, somehow, that will help +many possible contributors of the same language to interlock and avoid +work duplication, and further be put in contact for solving together +problems particular to their tongue (in most languages, there are many +difficulties peculiar to translating technical English). My Swedish +contributor acknowledged these difficulties, and I'm well aware of them +for French. + + This is surely not a technical issue, but we should manage so the +effort of locale contributors be maximally useful, despite the national +team layer interface between contributors and maintainers. + + The Translation Project needs some setup for coordinating language +coordinators. Localizing evolving programs will surely become a +permanent and continuous activity in the free software community, once +well started. The setup should be minimally completed and tested +before GNU `gettext' becomes an official reality. The e-mail address +`translation@iro.umontreal.ca' has been setup for receiving offers from +volunteers and general e-mail on these topics. This address reaches +the Translation Project coordinator. + +* Menu: + +* Central Coordination:: Central Coordination +* National Teams:: National Teams +* Mailing Lists:: Mailing Lists + + +File: gettext.info, Node: Central Coordination, Next: National Teams, Prev: Organization, Up: Organization + +Central Coordination +-------------------- + + I also think GNU will need sooner than it thinks, that someone setup +a way to organize and coordinate these groups. Some kind of group of +groups. My opinion is that it would be good that GNU delegates this +task to a small group of collaborating volunteers, shortly. Perhaps in +`gnu.announce' a list of this national committee's can be published. + + My role as coordinator would simply be to refer to Ulrich any German +speaking volunteer interested to localization of free software +packages, and maybe helping national groups to initially organize, +while maintaining national registries for until national groups are +ready to take over. In fact, the coordinator should ease volunteers to +get in contact with one another for creating national teams, which +should then select one coordinator per language, or country +(regionalized language). If well done, the coordination should be +useful without being an overwhelming task, the time to put delegations +in place. + + +File: gettext.info, Node: National Teams, Next: Mailing Lists, Prev: Central Coordination, Up: Organization + +National Teams +-------------- + + I suggest we look for volunteer coordinators/editors for individual +languages. These people will scan contributions of translation files +for various programs, for their own languages, and will ensure high and +uniform standards of diction. + + From my current experience with other people in these days, those who +provide localizations are very enthusiastic about the process, and are +more interested in the localization process than in the program they +localize, and want to do many programs, not just one. This seems to +confirm that having a coordinator/editor for each language is a good +idea. + + We need to choose someone who is good at writing clear and concise +prose in the language in question. That is hard--we can't check it +ourselves. So we need to ask a few people to judge each others' +writing and select the one who is best. + + I announce my prerelease to a few dozen people, and you would not +believe all the discussions it generated already. I shudder to think +what will happen when this will be launched, for true, officially, +world wide. Who am I to arbitrate between two Czekolsovak users +contradicting each other, for example? + + I assume that your German is not much better than my French so that +I would not be able to judge about these formulations. What I would +suggest is that for each language there is a group for people who +maintain the PO files and judge about changes. I suspect there will be +cultural differences between how such groups of people will behave. +Some will have relaxed ways, reach consensus easily, and have anyone of +the group relate to the maintainers, while others will fight to death, +organize heavy administrations up to national standards, and use strict +channels. + + The German team is putting out a good example. Right now, they are +maybe half a dozen people revising translations of each other and +discussing the linguistic issues. I do not even have all the names. +Ulrich Drepper is taking care of coordinating the German team. He +subscribed to all my pretest lists, so I do not even have to warn him +specifically of incoming releases. + + I'm sure, that is a good idea to get teams for each language working +on translations. That will make the translations better and more +consistent. + +* Menu: + +* Sub-Cultures:: Sub-Cultures +* Organizational Ideas:: Organizational Ideas + + +File: gettext.info, Node: Sub-Cultures, Next: Organizational Ideas, Prev: National Teams, Up: National Teams + +Sub-Cultures +............ + + Taking French for example, there are a few sub-cultures around +computers which developed diverging vocabularies. Picking volunteers +here and there without addressing this problem in an organized way, +soon in the project, might produce a distasteful mix of +internationalized programs, and possibly trigger endless quarrels among +those who really care. + + Keeping some kind of unity in the way French localization of +internationalized programs is achieved is a difficult (and delicate) +job. Knowing the latin character of French people (:-), if we take this +the wrong way, we could end up nowhere, or spoil a lot of energies. +Maybe we should begin to address this problem seriously *before* GNU +`gettext' become officially published. And I suspect that this means +soon! + + +File: gettext.info, Node: Organizational Ideas, Prev: Sub-Cultures, Up: National Teams + +Organizational Ideas +.................... + + I expect the next big changes after the official release. Please +note that I use the German translation of the short GPL message. We +need to set a few good examples before the localization goes out for +true in the free software community. Here are a few points to discuss: + + * Each group should have one FTP server (at least one master). + + * The files on the server should reflect the latest version (of + course!) and it should also contain a RCS directory with the + corresponding archives (I don't have this now). + + * There should also be a ChangeLog file (this is more useful than the + RCS archive but can be generated automatically from the later by + Emacs). + + * A "core group" should judge about questionable changes (for now + this group consists solely by me but I ask some others + occasionally; this also seems to work). + + +File: gettext.info, Node: Mailing Lists, Prev: National Teams, Up: Organization + +Mailing Lists +------------- + + If we get any inquiries about GNU `gettext', send them on to: + + `translation@iro.umontreal.ca' + + The `*-pretest' lists are quite useful to me, maybe the idea could +be generalized to many GNU, and non-GNU packages. But each maintainer +his/her way! + + Franc,ois, we have a mechanism in place here at `gnu.ai.mit.edu' to +track teams, support mailing lists for them and log members. We have a +slight preference that you use it. If this is OK with you, I can get +you clued in. + + Things are changing! A few years ago, when Daniel Fekete and I +asked for a mailing list for GNU localization, nested at the FSF, we +were politely invited to organize it anywhere else, and so did we. For +communicating with my pretesters, I later made a handful of mailing +lists located at iro.umontreal.ca and administrated by `majordomo'. +These lists have been *very* dependable so far... + + I suspect that the German team will organize itself a mailing list +located in Germany, and so forth for other countries. But before they +organize for true, it could surely be useful to offer mailing lists +located at the FSF to each national team. So yes, please explain me +how I should proceed to create and handle them. + + We should create temporary mailing lists, one per country, to help +people organize. Temporary, because once regrouped and structured, it +would be fair the volunteers from country bring back *their* list in +there and manage it as they want. My feeling is that, in the long run, +each team should run its own list, from within their country. There +also should be some central list to which all teams could subscribe as +they see fit, as long as each team is represented in it. + + +File: gettext.info, Node: Information Flow, Prev: Organization, Up: Translators + +Information Flow +================ + + There will surely be some discussion about this messages after the +packages are finally released. If people now send you some proposals +for better messages, how do you proceed? Jim, please note that right +now, as I put forward nearly a dozen of localizable programs, I receive +both the translations and the coordination concerns about them. + + If I put one of my things to pretest, Ulrich receives the +announcement and passes it on to the German team, who make last minute +revisions. Then he submits the translation files to me *as the +maintainer*. For free packages I do not maintain, I would not even +hear about it. This scheme could be made to work for the whole +Translation Project, I think. For security reasons, maybe Ulrich +(national coordinators, in fact) should update central registry kept at +the Translation Project (Jim, me, or Len's recruits) once in a while. + + In December/January, I was aggressively ready to internationalize +all of GNU, giving myself the duty of one small GNU package per week or +so, taking many weeks or months for bigger packages. But it does not +work this way. I first did all the things I'm responsible for. I've +nothing against some missionary work on other maintainers, but I'm also +loosing a lot of energy over it--same debates over again. + + And when the first localized packages are released we'll get a lot of +responses about ugly translations :-). Surely, and we need to have +beforehand a fairly good idea about how to handle the information flow +between the national teams and the package maintainers. + + Please start saving somewhere a quick history of each PO file. I +know for sure that the file format will change, allowing for comments. +It would be nice that each file has a kind of log, and references for +those who want to submit comments or gripes, or otherwise contribute. +I sent a proposal for a fast and flexible format, but it is not +receiving acceptance yet by the GNU deciders. I'll tell you when I +have more information about this. + + +File: gettext.info, Node: Maintainers, Next: Conclusion, Prev: Translators, Up: Top + +The Maintainer's View +********************* + + The maintainer of a package has many responsibilities. One of them +is ensuring that the package will install easily on many platforms, and +that the magic we described earlier (*note Users::.) will work for +installers and end users. + + Of course, there are many possible ways by which GNU `gettext' might +be integrated in a distribution, and this chapter does not cover them +in all generality. Instead, it details one possible approach which is +especially adequate for many free software distributions following GNU +standards, or even better, Gnits standards, because GNU `gettext' is +purposely for helping the internationalization of the whole GNU +project, and as many other good free packages as possible. So, the +maintainer's view presented here presumes that the package already has +a `configure.in' file and uses GNU Autoconf. + + Nevertheless, GNU `gettext' may surely be useful for free packages +not following GNU standards and conventions, but the maintainers of such +packages might have to show imagination and initiative in organizing +their distributions so `gettext' work for them in all situations. +There are surely many, out there. + + Even if `gettext' methods are now stabilizing, slight adjustments +might be needed between successive `gettext' versions, so you should +ideally revise this chapter in subsequent releases, looking for changes. + +* Menu: + +* Flat and Non-Flat:: Flat or Non-Flat Directory Structures +* Prerequisites:: Prerequisite Works +* gettextize Invocation:: Invoking the `gettextize' Program +* Adjusting Files:: Files You Must Create or Alter + + +File: gettext.info, Node: Flat and Non-Flat, Next: Prerequisites, Prev: Maintainers, Up: Maintainers + +Flat or Non-Flat Directory Structures +===================================== + + Some free software packages are distributed as `tar' files which +unpack in a single directory, these are said to be "flat" distributions. +Other free software packages have a one level hierarchy of +subdirectories, using for example a subdirectory named `doc/' for the +Texinfo manual and man pages, another called `lib/' for holding +functions meant to replace or complement C libraries, and a +subdirectory `src/' for holding the proper sources for the package. +These other distributions are said to be "non-flat". + + For now, we cannot say much about flat distributions. A flat +directory structure has the disadvantage of increasing the difficulty +of updating to a new version of GNU `gettext'. Also, if you have many +PO files, this could somewhat pollute your single directory. In the +GNU `gettext' distribution, the `misc/' directory contains a shell +script named `combine-sh'. That script may be used for combining all +the C files of the `intl/' directory into a pair of C files (one `.c' +and one `.h'). Those two generated files would fit more easily in a +flat directory structure, and you will then have to add these two files +to your project. + + Maybe because GNU `gettext' itself has a non-flat structure, we have +more experience with this approach, and this is what will be described +in the remaining of this chapter. Some maintainers might use this as +an opportunity to unflatten their package structure. Only later, once +gained more experience adapting GNU `gettext' to flat distributions, we +might add some notes about how to proceed in flat situations. + + +File: gettext.info, Node: Prerequisites, Next: gettextize Invocation, Prev: Flat and Non-Flat, Up: Maintainers + +Prerequisite Works +================== + + There are some works which are required for using GNU `gettext' in +one of your package. These works have some kind of generality that +escape the point by point descriptions used in the remainder of this +chapter. So, we describe them here. + + * Before attempting to use you should install some other packages + first. Ensure that recent versions of GNU `m4', GNU Autoconf and + GNU `gettext' are already installed at your site, and if not, + proceed to do this first. If you got to install these things, + beware that GNU `m4' must be fully installed before GNU Autoconf + is even *configured*. + + To further ease the task of a package maintainer the `automake' + package was designed and implemented. GNU `gettext' now uses this + tool and the `Makefile's in the `intl/' and `po/' therefore know + about all the goals necessary for using `automake' and `libintl' + in one project. + + Those four packages are only needed to you, as a maintainer; the + installers of your own package and end users do not really need + any of GNU `m4', GNU Autoconf, GNU `gettext', or GNU `automake' + for successfully installing and running your package, with messages + properly translated. But this is not completely true if you + provide internationalized shell scripts within your own package: + GNU `gettext' shall then be installed at the user site if the end + users want to see the translation of shell script messages. + + * Your package should use Autoconf and have a `configure.in' file. + If it does not, you have to learn how. The Autoconf documentation + is quite well written, it is a good idea that you print it and get + familiar with it. + + * Your C sources should have already been modified according to + instructions given earlier in this manual. *Note Sources::. + + * Your `po/' directory should receive all PO files submitted to you + by the translator teams, each having `LL.po' as a name. This is + not usually easy to get translation work done before your package + gets internationalized and available! Since the cycle has to + start somewhere, the easiest for the maintainer is to start with + absolutely no PO files, and wait until various translator teams + get interested in your package, and submit PO files. + + It is worth adding here a few words about how the maintainer should +ideally behave with PO files submissions. As a maintainer, your role is +to authentify the origin of the submission as being the representative +of the appropriate translating teams of the Translation Project (forward +the submission to `translation@iro.umontreal.ca' in case of doubt), to +ensure that the PO file format is not severely broken and does not +prevent successful installation, and for the rest, to merely to put +these PO files in `po/' for distribution. + + As a maintainer, you do not have to take on your shoulders the +responsibility of checking if the translations are adequate or +complete, and should avoid diving into linguistic matters. Translation +teams drive themselves and are fully responsible of their linguistic +choices for the Translation Project. Keep in mind that translator +teams are *not* driven by maintainers. You can help by carefully +redirecting all communications and reports from users about linguistic +matters to the appropriate translation team, or explain users how to +reach or join their team. The simplest might be to send them the +`ABOUT-NLS' file. + + Maintainers should *never ever* apply PO file bug reports +themselves, short-cutting translation teams. If some translator has +difficulty to get some of her points through her team, it should not be +an issue for her to directly negotiate translations with maintainers. +Teams ought to settle their problems themselves, if any. If you, as a +maintainer, ever think there is a real problem with a team, please +never try to *solve* a team's problem on your own. + + +File: gettext.info, Node: gettextize Invocation, Next: Adjusting Files, Prev: Prerequisites, Up: Maintainers + +Invoking the `gettextize' Program +================================= + + Some files are consistently and identically needed in every package +internationalized through GNU `gettext'. As a matter of convenience, +the `gettextize' program puts all these files right in your package. +This program has the following synopsis: + + gettextize [ OPTION... ] [ DIRECTORY ] + +and accepts the following options: + +`-c' +`--copy' + Copy the needed files instead of making symbolic links. Using + links would allow the package to always use the latest `gettext' + code available on the system, but it might disturb some mechanism + the maintainer is used to apply to the sources. Because running + `gettextize' is easy there shouldn't be problems with using copies. + +`-f' +`--force' + Force replacement of files which already exist. + +`-h' +`--help' + Display this help and exit. + +`--version' + Output version information and exit. + + If DIRECTORY is given, this is the top level directory of a package +to prepare for using GNU `gettext'. If not given, it is assumed that +the current directory is the top level directory of such a package. + + The program `gettextize' provides the following files. However, no +existing file will be replaced unless the option `--force' (`-f') is +specified. + + 1. The `ABOUT-NLS' file is copied in the main directory of your + package, the one being at the top level. This file gives the main + indications about how to install and use the Native Language + Support features of your program. You might elect to use a more + recent copy of this `ABOUT-NLS' file than the one provided through + `gettextize', if you have one handy. You may also fetch a more + recent copy of file `ABOUT-NLS' from Translation Project sites, + and from most GNU archive sites. + + 2. A `po/' directory is created for eventually holding all + translation files, but initially only containing the file + `po/Makefile.in.in' from the GNU `gettext' distribution. (beware + the double `.in' in the file name). If the `po/' directory already + exists, it will be preserved along with the files it contains, and + only `Makefile.in.in' will be overwritten. + + 3. A `intl/' directory is created and filled with most of the files + originally in the `intl/' directory of the GNU `gettext' + distribution. Also, if option `--force' (`-f') is given, the + `intl/' directory is emptied first. + + + If your site support symbolic links, `gettextize' will not actually +copy the files into your package, but establish symbolic links instead. +This avoids duplicating the disk space needed in all packages. Merely +using the `-h' option while creating the `tar' archive of your +distribution will resolve each link by an actual copy in the +distribution archive. So, to insist, you really should use `-h' option +with `tar' within your `dist' goal of your main `Makefile.in'. + + It is interesting to understand that most new files for supporting +GNU `gettext' facilities in one package go in `intl/' and `po/' +subdirectories. One distinction between these two directories is that +`intl/' is meant to be completely identical in all packages using GNU +`gettext', while all newly created files, which have to be different, +go into `po/'. There is a common `Makefile.in.in' in `po/', because +the `po/' directory needs its own `Makefile', and it has been designed +so it can be identical in all packages. + diff --git a/doc/gettext.info-5 b/doc/gettext.info-5 new file mode 100644 index 0000000..0279fa5 --- /dev/null +++ b/doc/gettext.info-5 @@ -0,0 +1,852 @@ +This is Info file gettext.info, produced by Makeinfo version 1.68 from +the input file gettext.texi. + +INFO-DIR-SECTION GNU Gettext Utilities +START-INFO-DIR-ENTRY +* Gettext: (gettext). GNU gettext utilities. +* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext. +* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files. +* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one. +* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file. +END-INFO-DIR-ENTRY + + This file provides documentation for GNU `gettext' utilities. It +also serves as a reference for the free Translation Project. + + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gettext.info, Node: Adjusting Files, Prev: gettextize Invocation, Up: Maintainers + +Files You Must Create or Alter +============================== + + Besides files which are automatically added through `gettextize', +there are many files needing revision for properly interacting with GNU +`gettext'. If you are closely following GNU standards for Makefile +engineering and auto-configuration, the adaptations should be easier to +achieve. Here is a point by point description of the changes needed in +each. + + So, here comes a list of files, each one followed by a description of +all alterations it needs. Many examples are taken out from the GNU +`gettext' 0.10.36 distribution itself. You may indeed refer to the +source code of the GNU `gettext' package, as it is intended to be a +good example and master implementation for using its own functionality. + +* Menu: + +* po/POTFILES.in:: `POTFILES.in' in `po/' +* configure.in:: `configure.in' at top level +* aclocal:: `aclocal.m4' at top level +* acconfig:: `acconfig.h' at top level +* Makefile:: `Makefile.in' at top level +* src/Makefile:: `Makefile.in' in `src/' + + +File: gettext.info, Node: po/POTFILES.in, Next: configure.in, Prev: Adjusting Files, Up: Adjusting Files + +`POTFILES.in' in `po/' +---------------------- + + The `po/' directory should receive a file named `POTFILES.in'. This +file tells which files, among all program sources, have marked strings +needing translation. Here is an example of such a file: + + # List of source files containing translatable strings. + # Copyright (C) 1995 Free Software Foundation, Inc. + + # Common library files + lib/error.c + lib/getopt.c + lib/xmalloc.c + + # Package source files + src/gettextp.c + src/msgfmt.c + src/xgettext.c + +Dashed comments and white lines are ignored. All other lines list +those source files containing strings marked for translation (*note +Mark Keywords::.), in a notation relative to the top level of your +whole distribution, rather than the location of the `POTFILES.in' file +itself. + + +File: gettext.info, Node: configure.in, Next: aclocal, Prev: po/POTFILES.in, Up: Adjusting Files + +`configure.in' at top level +--------------------------- + + 1. Declare the package and version. + + This is done by a set of lines like these: + + PACKAGE=gettext + VERSION=0.10.36 + AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") + AC_DEFINE_UNQUOTED(VERSION, "$VERSION") + AC_SUBST(PACKAGE) + AC_SUBST(VERSION) + + Of course, you replace `gettext' with the name of your package, + and `0.10.36' by its version numbers, exactly as they should + appear in the packaged `tar' file name of your distribution + (`gettext-0.10.36.tar.gz', here). + + 2. Declare the available translations. + + This is done by defining `ALL_LINGUAS' to the white separated, + quoted list of available languages, in a single line, like this: + + ALL_LINGUAS="de fr" + + This example means that German and French PO files are available, + so that these languages are currently supported by your package. + If you want to further restrict, at installation time, the set of + installed languages, this should not be done by modifying + `ALL_LINGUAS' in `configure.in', but rather by using the `LINGUAS' + environment variable (*note Installers::.). + + 3. Check for internationalization support. + + Here is the main `m4' macro for triggering internationalization + support. Just add this line to `configure.in': + + AM_GNU_GETTEXT + + This call is purposely simple, even if it generates a lot of + configure time checking and actions. + + 4. Have output files created. + + The `AC_OUTPUT' directive, at the end of your `configure.in' file, + needs to be modified in two ways: + + AC_OUTPUT([EXISTING CONFIGURATION FILES intl/Makefile po/Makefile.in], + EXISTING ADDITIONAL ACTIONS]) + + The modification to the first argument to `AC_OUTPUT' asks for + substitution in the `intl/' and `po/' directories. Note the `.in' + suffix used for `po/' only. This is because the distributed file + is really `po/Makefile.in.in'. + + + +File: gettext.info, Node: aclocal, Next: acconfig, Prev: configure.in, Up: Adjusting Files + +`aclocal.m4' at top level +------------------------- + + If you do not have an `aclocal.m4' file in your distribution, the +simplest is taking a copy of `aclocal.m4' from GNU `gettext'. But to +be precise, you only need macros `AM_LC_MESSAGES', `AM_WITH_NLS' and +`AM_GNU_GETTEXT', and `AM_PATH_PROG_WITH_TEST', which is called by +`AM_WITH_NLS', so you may use an editor and remove macros you do not +need. + + If you already have an `aclocal.m4' file, then you will have to +merge the said macros into your `aclocal.m4'. Note that if you are +upgrading from a previous release of GNU `gettext', you should most +probably *replace* the said macros, as they usually change a little +from one release of GNU `gettext' to the next. Their contents may vary +as we get more experience with strange systems out there. + + These macros check for the internationalization support functions +and related informations. Hopefully, once stabilized, these macros +might be integrated in the standard Autoconf set, because this piece of +`m4' code will be the same for all projects using GNU `gettext'. + + +File: gettext.info, Node: acconfig, Next: Makefile, Prev: aclocal, Up: Adjusting Files + +`acconfig.h' at top level +------------------------- + + If you do not have an `acconfig.h' file in your distribution, the +simplest is use take a copy of `acconfig.h' from GNU `gettext'. But to +be precise, you only need the lines and comments for `ENABLE_NLS', +`HAVE_CATGETS', `HAVE_GETTEXT' and `HAVE_LC_MESSAGES', `HAVE_STPCPY', +`PACKAGE' and `VERSION', so you may use an editor and remove everything +else. If you already have an `acconfig.h' file, then you should merge +the said definitions into your `acconfig.h'. + + +File: gettext.info, Node: Makefile, Next: src/Makefile, Prev: acconfig, Up: Adjusting Files + +`Makefile.in' at top level +-------------------------- + + Here are a few modifications you need to make to your main, top-level +`Makefile.in' file. + + 1. Add the following lines near the beginning of your `Makefile.in', + so the `dist:' goal will work properly (as explained further down): + + PACKAGE = @PACKAGE@ + VERSION = @VERSION@ + + 2. Add file `ABOUT-NLS' to the `DISTFILES' definition, so the file + gets distributed. + + 3. Wherever you process subdirectories in your `Makefile.in', be sure + you also process dir subdirectories `intl' and `po'. Special + rules in the `Makefiles' take care for the case where no + internationalization is wanted. + + If you are using Makefiles, either generated by automake, or + hand-written so they carefully follow the GNU coding standards, + the effected goals for which the new subdirectories must be + handled include `installdirs', `install', `uninstall', `clean', + `distclean'. + + Here is an example of a canonical order of processing. In this + example, we also define `SUBDIRS' in `Makefile.in' for it to be + further used in the `dist:' goal. + + SUBDIRS = doc lib @INTLSUB@ src @POSUB@ + + that you will have to adapt to your own package. + + 4. A delicate point is the `dist:' goal, as both `intl/Makefile' and + `po/Makefile' will later assume that the proper directory has been + set up from the main `Makefile'. Here is an example at what the + `dist:' goal might look like: + + distdir = $(PACKAGE)-$(VERSION) + dist: Makefile + rm -fr $(distdir) + mkdir $(distdir) + chmod 777 $(distdir) + for file in $(DISTFILES); do \ + ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir); \ + done + for subdir in $(SUBDIRS); do \ + mkdir $(distdir)/$$subdir || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $@) || exit 1; \ + done + tar chozf $(distdir).tar.gz $(distdir) + rm -fr $(distdir) + + + +File: gettext.info, Node: src/Makefile, Prev: Makefile, Up: Adjusting Files + +`Makefile.in' in `src/' +----------------------- + + Some of the modifications made in the main `Makefile.in' will also +be needed in the `Makefile.in' from your package sources, which we +assume here to be in the `src/' subdirectory. Here are all the +modifications needed in `src/Makefile.in': + + 1. In view of the `dist:' goal, you should have these lines near the + beginning of `src/Makefile.in': + + PACKAGE = @PACKAGE@ + VERSION = @VERSION@ + + 2. If not done already, you should guarantee that `top_srcdir' gets + defined. This will serve for `cpp' include files. Just add the + line: + + top_srcdir = @top_srcdir@ + + 3. You might also want to define `subdir' as `src', later allowing + for almost uniform `dist:' goals in all your `Makefile.in'. At + list, the `dist:' goal below assume that you used: + + subdir = src + + 4. You should ensure that the final linking will use `@INTLLIBS@' as + a library. An easy way to achieve this is to manage that it gets + into `LIBS', like this: + + LIBS = @INTLLIBS@ @LIBS@ + + In most packages internationalized with GNU `gettext', one will + find a directory `lib/' in which a library containing some helper + functions will be build. (You need at least the few functions + which the GNU `gettext' Library itself needs.) However some of + the functions in the `lib/' also give messages to the user which + of course should be translated, too. Taking care of this it is + not enough to place the support library (say `libsupport.a') just + between the `@INTLLIBS@' and `@LIBS@' in the above example. + Instead one has to write this: + + LIBS = ../lib/libsupport.a @INTLLIBS@ ../lib/libsupport.a @LIBS@ + + 5. You should also ensure that directory `intl/' will be searched for + C preprocessor include files in all circumstances. So, you have to + manage so both `-I../intl' and `-I$(top_srcdir)/intl' will be + given to the C compiler. + + 6. Your `dist:' goal has to conform with others. Here is a + reasonable definition for it: + + distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) + dist: Makefile $(DISTFILES) + for file in $(DISTFILES); do \ + ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir); \ + done + + + +File: gettext.info, Node: Conclusion, Next: Country Codes, Prev: Maintainers, Up: Top + +Concluding Remarks +****************** + + We would like to conclude this GNU `gettext' manual by presenting an +history of the Translation Project so far. We finally give a few +pointers for those who want to do further research or readings about +Native Language Support matters. + +* Menu: + +* History:: History of GNU `gettext' +* References:: Related Readings + + +File: gettext.info, Node: History, Next: References, Prev: Conclusion, Up: Conclusion + +History of GNU `gettext' +======================== + + Internationalization concerns and algorithms have been informally +and casually discussed for years in GNU, sometimes around GNU `libc', +maybe around the incoming `Hurd', or otherwise (nobody clearly +remembers). And even then, when the work started for real, this was +somewhat independently of these previous discussions. + + This all began in July 1994, when Patrick D'Cruze had the idea and +initiative of internationalizing version 3.9.2 of GNU `fileutils'. He +then asked Jim Meyering, the maintainer, how to get those changes +folded into an official release. That first draft was full of +`#ifdef's and somewhat disconcerting, and Jim wanted to find nicer +ways. Patrick and Jim shared some tries and experimentations in this +area. Then, feeling that this might eventually have a deeper impact on +GNU, Jim wanted to know what standards were, and contacted Richard +Stallman, who very quickly and verbally described an overall design for +what was meant to become `glocale', at that time. + + Jim implemented `glocale' and got a lot of exhausting feedback from +Patrick and Richard, of course, but also from Mitchum DSouza (who wrote +a `catgets'-like package), Roland McGrath, maybe David MacKenzie, +Franc,ois Pinard, and Paul Eggert, all pushing and pulling in various +directions, not always compatible, to the extent that after a couple of +test releases, `glocale' was torn apart. + + While Jim took some distance and time and became dad for a second +time, Roland wanted to get GNU `libc' internationalized, and got Ulrich +Drepper involved in that project. Instead of starting from `glocale', +Ulrich rewrote something from scratch, but more conformant to the set +of guidelines who emerged out of the `glocale' effort. Then, Ulrich +got people from the previous forum to involve themselves into this new +project, and the switch from `glocale' to what was first named +`msgutils', renamed `nlsutils', and later `gettext', became officially +accepted by Richard in May 1995 or so. + + Let's summarize by saying that Ulrich Drepper wrote GNU `gettext' in +April 1995. The first official release of the package, including PO +mode, occurred in July 1995, and was numbered 0.7. Other people +contributed to the effort by providing a discussion forum around +Ulrich, writing little pieces of code, or testing. These are quoted in +the `THANKS' file which comes with the GNU `gettext' distribution. + + While this was being done, Franc,ois adapted half a dozen of GNU +packages to `glocale' first, then later to `gettext', putting them in +pretest, so providing along the way an effective user environment for +fine tuning the evolving tools. He also took the responsibility of +organizing and coordinating the Translation Project. After nearly a +year of informal exchanges between people from many countries, +translator teams started to exist in May 1995, through the creation and +support by Patrick D'Cruze of twenty unmoderated mailing lists for that +many native languages, and two moderated lists: one for reaching all +teams at once, the other for reaching all willing maintainers of +internationalized free software packages. + + Franc,ois also wrote PO mode in June 1995 with the collaboration of +Greg McGary, as a kind of contribution to Ulrich's package. He also +gave a hand with the GNU `gettext' Texinfo manual. + + +File: gettext.info, Node: References, Prev: History, Up: Conclusion + +Related Readings +================ + + Eugene H. Dorr (`dorre@well.com') maintains an interesting +bibliography on internationalization matters, called +`Internationalization Reference List', which is available as: + ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/i18n-books.txt + + Michael Gschwind (`mike@vlsivie.tuwien.ac.at') maintains a +Frequently Asked Questions (FAQ) list, entitled `Programming for +Internationalisation'. This FAQ discusses writing programs which can +handle different language conventions, character sets, etc.; and is +applicable to all character set encodings, with particular emphasis on +ISO 8859-1. It is regularly published in Usenet groups +`comp.unix.questions', `comp.std.internat', +`comp.software.international', `comp.lang.c', `comp.windows.x', +`comp.std.c', `comp.answers' and `news.answers'. The home location of +this document is: + ftp://ftp.vlsivie.tuwien.ac.at/pub/8bit/ISO-programming + + Patrick D'Cruze (`pdcruze@li.org') wrote a tutorial about NLS +matters, and Jochen Hein (`Hein@student.tu-clausthal.de') took over the +responsibility of maintaining it. It may be found as: + ftp://sunsite.unc.edu/pub/Linux/utils/nls/catalogs/Incoming/... + ...locale-tutorial-0.8.txt.gz + +This site is mirrored in: + ftp://ftp.ibp.fr/pub/linux/sunsite/ + + A French version of the same tutorial should be findable at: + ftp://ftp.ibp.fr/pub/linux/french/docs/ + +together with French translations of many Linux-related documents. + + +File: gettext.info, Node: Country Codes, Prev: Conclusion, Up: Top + +Country Codes +************* + + The ISO 639 standard defines two character codes for many countries. +All abreviations for countries or languages used in the Translation +Project should come from this standard. + +`aa' + Afar. + +`ab' + Abkhazian. + +`af' + Afrikaans. + +`am' + Amharic. + +`ar' + Arabic. + +`as' + Assamese. + +`ay' + Aymara. + +`az' + Azerbaijani. + +`ba' + Bashkir. + +`be' + Byelorussian. + +`bg' + Bulgarian. + +`bh' + Bihari. + +`bi' + Bislama. + +`bn' + Bengali; Bangla. + +`bo' + Tibetan. + +`br' + Breton. + +`ca' + Catalan. + +`co' + Corsican. + +`cs' + Czech. + +`cy' + Welsh. + +`da' + Danish. + +`de' + German. + +`dz' + Bhutani. + +`el' + Greek. + +`en' + English. + +`eo' + Esperanto. + +`es' + Spanish. + +`et' + Estonian. + +`eu' + Basque. + +`fa' + Persian. + +`fi' + Finnish. + +`fj' + Fiji. + +`fo' + Faroese. + +`fr' + French. + +`fy' + Frisian. + +`ga' + Irish. + +`gd' + Scots Gaelic. + +`gl' + Galician. + +`gn' + Guarani. + +`gu' + Gujarati. + +`ha' + Hausa. + +`he' + Hebrew (formerly iw). + +`hi' + Hindi. + +`hr' + Croatian. + +`hu' + Hungarian. + +`hy' + Armenian. + +`ia' + Interlingua. + +`id' + Indonesian (formerly in). + +`ie' + Interlingue. + +`ik' + Inupiak. + +`is' + Icelandic. + +`it' + Italian. + +`iu' + Inuktitut. + +`ja' + Japanese. + +`jw' + Javanese. + +`ka' + Georgian. + +`kk' + Kazakh. + +`kl' + Greenlandic. + +`km' + Cambodian. + +`kn' + Kannada. + +`ko' + Korean. + +`ks' + Kashmiri. + +`ku' + Kurdish. + +`ky' + Kirghiz. + +`la' + Latin. + +`ln' + Lingala. + +`lo' + Laothian. + +`lt' + Lithuanian. + +`lv' + Latvian, Lettish. + +`mg' + Malagasy. + +`mi' + Maori. + +`mk' + Macedonian. + +`ml' + Malayalam. + +`mn' + Mongolian. + +`mo' + Moldavian. + +`mr' + Marathi. + +`ms' + Malay. + +`mt' + Maltese. + +`my' + Burmese. + +`na' + Nauru. + +`ne' + Nepali. + +`nl' + Dutch. + +`no' + Norwegian. + +`oc' + Occitan. + +`om' + (Afan) Oromo. + +`or' + Oriya. + +`pa' + Punjabi. + +`pl' + Polish. + +`ps' + Pashto, Pushto. + +`pt' + Portuguese. + +`qu' + Quechua. + +`rm' + Rhaeto-Romance. + +`rn' + Kirundi. + +`ro' + Romanian. + +`ru' + Russian. + +`rw' + Kinyarwanda. + +`sa' + Sanskrit. + +`sd' + Sindhi. + +`sg' + Sangro. + +`sh' + Serbo-Croatian. + +`si' + Sinhalese. + +`sk' + Slovak. + +`sl' + Slovenian. + +`sm' + Samoan. + +`sn' + Shona. + +`so' + Somali. + +`sq' + Albanian. + +`sr' + Serbian. + +`ss' + Siswati. + +`st' + Sesotho. + +`su' + Sundanese. + +`sv' + Swedish. + +`sw' + Swahili. + +`ta' + Tamil. + +`te' + Telugu. + +`tg' + Tajik. + +`th' + Thai. + +`ti' + Tigrinya. + +`tk' + Turkmen. + +`tl' + Tagalog. + +`tn' + Setswana. + +`to' + Tonga. + +`tr' + Turkish. + +`ts' + Tsonga. + +`tt' + Tatar. + +`tw' + Twi. + +`ug' + Uighur. + +`uk' + Ukrainian. + +`ur' + Urdu. + +`uz' + Uzbek. + +`vi' + Vietnamese. + +`vo' + Volapuk. + +`wo' + Wolof. + +`xh' + Xhosa. + +`yi' + Yiddish (formerly ji). + +`yo' + Yoruba. + +`za' + Zhuang. + +`zh' + Chinese. + +`zu' + Zulu. + + diff --git a/doc/gettext.texi b/doc/gettext.texi new file mode 100644 index 0000000..343ffb4 --- /dev/null +++ b/doc/gettext.texi @@ -0,0 +1,4820 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename gettext.info +@settitle GNU @code{gettext} utilities +@finalout +@c %**end of header + +@include version.texi + +@dircategory GNU Gettext Utilities +@direntry +* Gettext: (gettext). GNU gettext utilities. +* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext. +* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files. +* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one. +* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file. +@end direntry + +@ifinfo +This file provides documentation for GNU @code{gettext} utilities. +It also serves as a reference for the free Translation Project. + +Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end ifinfo + +@titlepage +@title GNU gettext tools, version @value{VERSION} +@subtitle Native Language Support Library and Tools +@subtitle Edition @value{EDITION}, @value{UPDATED} +@author Ulrich Drepper +@author Jim Meyering +@author Fran@,{c}ois Pinard + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end titlepage + +@ifinfo +@node Top, Introduction, (dir), (dir) +@top GNU @code{gettext} utilities + +@menu +* Introduction:: Introduction +* Basics:: PO Files and PO Mode Basics +* Sources:: Preparing Program Sources +* Initial:: Making the Initial PO File +* Updating:: Updating Existing PO Files +* Binaries:: Producing Binary MO Files +* Users:: The User's View +* Programmers:: The Programmer's View +* Translators:: The Translator's View +* Maintainers:: The Maintainer's View +* Conclusion:: Concluding Remarks + +* Country Codes:: ISO 639 country codes + +@detailmenu + --- The Detailed Node Listing --- + +Introduction + +* Why:: The Purpose of GNU @code{gettext} +* Concepts:: I18n, L10n, and Such +* Aspects:: Aspects in Native Language Support +* Files:: Files Conveying Translations +* Overview:: Overview of GNU @code{gettext} + +PO Files and PO Mode Basics + +* Installation:: Completing GNU @code{gettext} Installation +* PO Files:: The Format of PO Files +* Main PO Commands:: Main Commands +* Entry Positioning:: Entry Positioning +* Normalizing:: Normalizing Strings in Entries + +Preparing Program Sources + +* Triggering:: Triggering @code{gettext} Operations +* Mark Keywords:: How Marks Appears in Sources +* Marking:: Marking Translatable Strings +* c-format:: Telling something about the following string +* Special cases:: Special Cases of Translatable Strings + +Making the Initial PO File + +* xgettext Invocation:: Invoking the @code{xgettext} Program +* C Sources Context:: C Sources Context +* Compendium:: Using Translation Compendiums + +Updating Existing PO Files + +* msgmerge Invocation:: Invoking the @code{msgmerge} Program +* Translated Entries:: Translated Entries +* Fuzzy Entries:: Fuzzy Entries +* Untranslated Entries:: Untranslated Entries +* Obsolete Entries:: Obsolete Entries +* Modifying Translations:: Modifying Translations +* Modifying Comments:: Modifying Comments +* Auxiliary:: Consulting Auxiliary PO Files + +Producing Binary MO Files + +* msgfmt Invocation:: Invoking the @code{msgfmt} Program +* MO Files:: The Format of GNU MO Files + +The User's View + +* Matrix:: The Current @file{ABOUT-NLS} Matrix +* Installers:: Magic for Installers +* End Users:: Magic for End Users + +The Programmer's View + +* catgets:: About @code{catgets} +* gettext:: About @code{gettext} +* Comparison:: Comparing the two interfaces +* Using libintl.a:: Using libintl.a in own programs +* gettext grok:: Being a @code{gettext} grok +* Temp Programmers:: Temporary Notes for the Programmers Chapter + +About @code{catgets} + +* Interface to catgets:: The interface +* Problems with catgets:: Problems with the @code{catgets} interface?! + +About @code{gettext} + +* Interface to gettext:: The interface +* Ambiguities:: Solving ambiguities +* Locating Catalogs:: Locating message catalog files +* Optimized gettext:: Optimization of the *gettext functions + +Temporary Notes for the Programmers Chapter + +* Temp Implementations:: Temporary - Two Possible Implementations +* Temp catgets:: Temporary - About @code{catgets} +* Temp WSI:: Temporary - Why a single implementation +* Temp Notes:: Temporary - Notes + +The Translator's View + +* Trans Intro 0:: Introduction 0 +* Trans Intro 1:: Introduction 1 +* Discussions:: Discussions +* Organization:: Organization +* Information Flow:: Information Flow + +Organization + +* Central Coordination:: Central Coordination +* National Teams:: National Teams +* Mailing Lists:: Mailing Lists + +National Teams + +* Sub-Cultures:: Sub-Cultures +* Organizational Ideas:: Organizational Ideas + +The Maintainer's View + +* Flat and Non-Flat:: Flat or Non-Flat Directory Structures +* Prerequisites:: Prerequisite Works +* gettextize Invocation:: Invoking the @code{gettextize} Program +* Adjusting Files:: Files You Must Create or Alter + +Files You Must Create or Alter + +* po/POTFILES.in:: @file{POTFILES.in} in @file{po/} +* configure.in:: @file{configure.in} at top level +* aclocal:: @file{aclocal.m4} at top level +* acconfig:: @file{acconfig.h} at top level +* Makefile:: @file{Makefile.in} at top level +* src/Makefile:: @file{Makefile.in} in @file{src/} + +Concluding Remarks + +* History:: History of GNU @code{gettext} +* References:: Related Readings + +@end detailmenu +@end menu + +@end ifinfo + +@node Introduction, Basics, Top, Top +@chapter Introduction + +@quotation +This manual is still in @emph{DRAFT} state. Some sections are still +empty, or almost. We keep merging material from other sources +(essentially e-mail folders) while the proper integration of this +material is delayed. +@end quotation + +In this manual, we use @emph{he} when speaking of the programmer or +maintainer, @emph{she} when speaking of the translator, and @emph{they} +when speaking of the installers or end users of the translated program. +This is only a convenience for clarifying the documentation. It is +@emph{absolutely} not meant to imply that some roles are more appropriate +to males or females. Besides, as you might guess, GNU @code{gettext} +is meant to be useful for people using computers, whatever their sex, +race, religion or nationality! + +This chapter explains the goals sought in the creation +of GNU @code{gettext} and the free Translation Project. +Then, it explains a few broad concepts around +Native Language Support, and positions message translation with regard +to other aspects of national and cultural variance, as they apply to +to programs. It also surveys those files used to convey the +translations. It explains how the various tools interact in the +initial generation of these files, and later, how the maintenance +cycle should usually operate. + +Please send suggestions and corrections to: + +@example +@group +@r{Internet address:} + bug-gnu-utils@@gnu.org +@end group +@end example + +@noindent +Please include the manual's edition number and update date in your messages. + +@menu +* Why:: The Purpose of GNU @code{gettext} +* Concepts:: I18n, L10n, and Such +* Aspects:: Aspects in Native Language Support +* Files:: Files Conveying Translations +* Overview:: Overview of GNU @code{gettext} +@end menu + +@node Why, Concepts, Introduction, Introduction +@section The Purpose of GNU @code{gettext} + +Usually, programs are written and documented in English, and use +English at execution time to interact with users. This is true +not only of GNU software, but also of a great deal of commercial +and free software. Using a common language is quite handy for +communication between developers, maintainers and users from all +countries. On the other hand, most people are less comfortable with +English than with their own native language, and would prefer to +use their mother tongue for day to day's work, as far as possible. +Many would simply @emph{love} to see their computer screen showing +a lot less of English, and far more of their own language. + +However, to many people, this dream might appear so far fetched that +they may believe it is not even worth spending time thinking about +it. They have no confidence at all that the dream might ever +become true. Yet some have not lost hope, and have organized themselves. +The Translation Project is a formalization of this hope into a +workable structure, which has a good chance to get all of us nearer +the achievement of a truly multi-lingual set of programs. + +GNU @code{gettext} is an important step for the Translation Project, +as it is an asset on which we may build many other steps. This package +offers to programmers, translators and even users, a well integrated +set of tools and documentation. Specifically, the GNU @code{gettext} +utilities are a set of tools that provides a framework within which +other free packages may produce multi-lingual messages. These tools +include a set of conventions about how programs should be written to +support message catalogs, a directory and file naming organization for the +message catalogs themselves, a runtime library supporting the retrieval of +translated messages, and a few stand-alone programs to massage in various +ways the sets of translatable strings, or already translated strings. +A special mode for Emacs@footnote{In this manual, all mentions of Emacs +refers to either GNU Emacs or to XEmacs, which people sometimes call FSF +Emacs and Lucid Emacs, respectively.} also helps ease interested parties +into preparing these sets, or bringing them up to date. + +GNU @code{gettext} is designed to minimize the impact of +internationalization on program sources, keeping this impact as small +and hardly noticeable as possible. Internationalization has better +chances of succeeding if it is very light weighted, or at least, +appear to be so, when looking at program sources. + +The Translation Project also uses the GNU @code{gettext} +distribution as a vehicle for documenting its structure and methods. +This goes beyond the strict technicalities of documenting the GNU @code{gettext} +proper. By so doing, translators will find in a single place, as +far as possible, all they need to know for properly doing their +translating work. Also, this supplemental documentation might also +help programmers, and even curious users, in understanding how GNU +@code{gettext} is related to the remainder of the Translation +Project, and consequently, have a glimpse at the @emph{big picture}. + +@node Concepts, Aspects, Why, Introduction +@section I18n, L10n, and Such + +Two long words appear all the time when we discuss support of native +language in programs, and these words have a precise meaning, worth +being explained here, once and for all in this document. The words are +@emph{internationalization} and @emph{localization}. Many people, +tired of writing these long words over and over again, took the +habit of writing @dfn{i18n} and @dfn{l10n} instead, quoting the first +and last letter of each word, and replacing the run of intermediate +letters by a number merely telling how many such letters there are. +But in this manual, in the sake of clarity, we will patiently write +the names in full, each time@dots{} + +By @dfn{internationalization}, one refers to the operation by which a +program, or a set of programs turned into a package, is made aware of and +able to support multiple languages. This is a generalization process, +by which the programs are untied from calling only English strings or +other English specific habits, and connected to generic ways of doing +the same, instead. Program developers may use various techniques to +internationalize their programs. Some of these have been standardized. +GNU @code{gettext} offers one of these standards. @xref{Programmers}. + +By @dfn{localization}, one means the operation by which, in a set +of programs already internationalized, one gives the program all +needed information so that it can adapt itself to handle its input +and output in a fashion which is correct for some native language and +cultural habits. This is a particularisation process, by which generic +methods already implemented in an internationalized program are used +in specific ways. The programming environment puts several functions +to the programmers disposal which allow this runtime configuration. +The formal description of specific set of cultural habits for some +country, together with all associated translations targeted to the +same native language, is called the @dfn{locale} for this language +or country. Users achieve localization of programs by setting proper +values to special environment variables, prior to executing those +programs, identifying which locale should be used. + +In fact, locale message support is only one component of the cultural +data that makes up a particular locale. There are a whole host of +routines and functions provided to aid programmers in developing +internationalized software and which allow them to access the data +stored in a particular locale. When someone presently refers to a +particular locale, they are obviously referring to the data stored +within that particular locale. Similarly, if a programmer is referring +to ``accessing the locale routines'', they are referring to the +complete suite of routines that access all of the locale's information. + +One uses the expression @dfn{Native Language Support}, or merely NLS, +for speaking of the overall activity or feature encompassing both +internationalization and localization, allowing for multi-lingual +interactions in a program. In a nutshell, one could say that +internationalization is the operation by which further localizations +are made possible. + +Also, very roughly said, when it comes to multi-lingual messages, +internationalization is usually taken care of by programmers, and +localization is usually taken care of by translators. + +@node Aspects, Files, Concepts, Introduction +@section Aspects in Native Language Support + +For a totally multi-lingual distribution, there are many things to +translate beyond output messages. + +@itemize @bullet +@item +As of today, GNU @code{gettext} offers a complete toolset for +translating messages output by C programs. Perl scripts and shell +scripts will also need to be translated. Even if there are today some hooks +by which this can be done, these hooks are not integrated as well as they +should be. + +@item +Some programs, like @code{autoconf} or @code{bison}, are able +to produce other programs (or scripts). Even if the generating +programs themselves are internationalized, the generated programs they +produce may need internationalization on their own, and this indirect +internationalization could be automated right from the generating +program. In fact, quite usually, generating and generated programs +could be internationalized independently, as the effort needed is +fairly orthogonal. + +@item +A few programs include textual tables which might need translation +themselves, independently of the strings contained in the program +itself. For example, @w{RFC 1345} gives an English description for each +character which the @code{recode} program is able to reconstruct at execution. +Since these descriptions are extracted from the RFC by mechanical means, +translating them properly would require a prior translation of the RFC +itself. + +@item +Almost all programs accept options, which are often worded out so to +be descriptive for the English readers; one might want to consider +offering translated versions for program options as well. + +@item +Many programs read, interpret, compile, or are somewhat driven by +input files which are texts containing keywords, identifiers, or +replies which are inherently translatable. For example, one may want +@code{gcc} to allow diacriticized characters in identifiers or use +translated keywords; @samp{rm -i} might accept something else than +@samp{y} or @samp{n} for replies, etc. Even if the program will +eventually make most of its output in the foreign languages, one has +to decide whether the input syntax, option values, etc., are to be +localized or not. + +@item +The manual accompanying a package, as well as all documentation files +in the distribution, could surely be translated, too. Translating a +manual, with the intent of later keeping up with updates, is a major +undertaking in itself, generally. + +@end itemize + +As we already stressed, translation is only one aspect of locales. +Other internationalization aspects are not currently handled by GNU +@code{gettext}, but perhaps may be handled in future versions. There +are many attributes that are needed to define a country's cultural +conventions. These attributes include beside the country's native +language, the formatting of the date and time, the representation of +numbers, the symbols for currency, etc. These local @dfn{rules} are +termed the country's locale. The locale represents the knowledge +needed to support the country's native attributes. + +There are a few major areas which may vary between countries and +hence, define what a locale must describe. The following list helps +putting multi-lingual messages into the proper context of other tasks +related to locales, and also presents some other areas which GNU +@code{gettext} might eventually tackle, maybe, one of these days. + +@table @emph + +@item Characters and Codesets + +The codeset most commonly used through out the USA and most English +speaking parts of the world is the ASCII codeset. However, there are +many characters needed by various locales that are not found within +this codeset. The 8-bit @w{ISO 8859-1} code set has most of the special +characters needed to handle the major European languages. However, in +many cases, the @w{ISO 8859-1} font is not adequate. Hence each locale +will need to specify which codeset they need to use and will need +to have the appropriate character handling routines to cope with +the codeset. + +@item Currency + +The symbols used vary from country to country as does the position +used by the symbol. Software needs to be able to transparently +display currency figures in the native mode for each locale. + +@item Dates + +The format of date varies between locales. For example, Christmas day +in 1994 is written as 12/25/94 in the USA and as 25/12/94 in Australia. +Other countries might use @w{ISO 8061} dates, etc. + +Time of the day may be noted as @var{hh}:@var{mm}, @var{hh}.@var{mm}, +or otherwise. Some locales require time to be specified in 24-hour +mode rather than as AM or PM. Further, the nature and yearly extent +of the Daylight Saving correction vary widely between countries. + +@item Numbers + +Numbers can be represented differently in different locales. +For example, the following numbers are all written correctly for +their respective locales: + +@example +12,345.67 English +12.345,67 French +1,2345.67 Asia +@end example + +Some programs could go further and use different unit systems, like +English units or Metric units, or even take into account variants +about how numbers are spelled in full. + +@item Messages + +The most obvious area is the language support within a locale. This is +where GNU @code{gettext} provides the means for developers and users to +easily change the language that the software uses to communicate to +the user. + +@end table + +In the near future we see no chance that components of locale outside of +message handling will be made available for use in other +packages. The reason for this is that most modern systems provide +a more or less reasonable support for at least some of the missing +components. Another point is that the GNU @code{libc} and Linux will get +a new and complete implementation of the whole locale functionality +which could be adopted by system lacking a reasonable locale support. + +@node Files, Overview, Aspects, Introduction +@section Files Conveying Translations + +The letters PO in @file{.po} files means Portable Object, to +distinguish it from @file{.mo} files, where MO stands for Machine +Object. This paradigm, as well as the PO file format, is inspired +by the NLS standard developed by Uniforum, and implemented by Sun +in their Solaris system. + +PO files are meant to be read and edited by humans, and associate each +original, translatable string of a given package with its translation +in a particular target language. A single PO file is dedicated to +a single target language. If a package supports many languages, +there is one such PO file per language supported, and each package +has its own set of PO files. These PO files are best created by +the @code{xgettext} program, and later updated or refreshed through +the @code{msgmerge} program. Program @code{xgettext} extracts all +marked messages from a set of C files and initializes a PO file with +empty translations. Program @code{msgmerge} takes care of adjusting +PO files between releases of the corresponding sources, commenting +obsolete entries, initializing new ones, and updating all source +line references. Files ending with @file{.pot} are kind of base +translation files found in distributions, in PO file format, and +@file{.pox} files are often temporary PO files. + +MO files are meant to be read by programs, and are binary in nature. +A few systems already offer tools for creating and handling MO files +as part of the Native Language Support coming with the system, but the +format of these MO files is often different from system to system, +and non-portable. They do not necessary use @file{.mo} for file +extensions, but since system libraries are also used for accessing +these files, it works as long as the system is self-consistent about +it. If GNU @code{gettext} is able to interface with the tools already +provided with systems, it will consequently let these provided tools +take care of generating the MO files. Or else, if such tools are not +found or do not seem usable, GNU @code{gettext} will use its own ways +and its own format for MO files. Files ending with @file{.gmo} are +really MO files, when it is known that these files use the GNU format. + +@node Overview, , Files, Introduction +@section Overview of GNU @code{gettext} + +The following diagram summarizes the relation between the files +handled by GNU @code{gettext} and the tools acting on these files. +It is followed by a somewhat detailed explanations, which you should +read while keeping an eye on the diagram. Having a clear understanding +of these interrelations would surely help programmers, translators +and maintainers. + +@example +@group +Original C Sources ---> PO mode ---> Marked C Sources ---. + | + .---------<--- GNU gettext Library | +.--- make <---+ | +| `---------<--------------------+-----------' +| | +| .-----<--- PACKAGE.pot <--- xgettext <---' .---<--- PO Compendium +| | | ^ +| | `---. | +| `---. +---> PO mode ---. +| +----> msgmerge ------> LANG.pox --->--------' | +| .---' | +| | | +| `-------------<---------------. | +| +--- LANG.po <--- New LANG.pox <----' +| .--- LANG.gmo <--- msgfmt <---' +| | +| `---> install ---> /.../LANG/PACKAGE.mo ---. +| +---> "Hello world!" +`-------> install ---> /.../bin/PROGRAM -------' +@end group +@end example + +The indication @samp{PO mode} appears in two places in this picture, +and you may safely read it as merely meaning ``hand editing'', using +any editor of your choice, really. However, for those of you being +the lucky users of Emacs, PO mode has been specifically created +for providing a cozy environment for editing or modifying PO files. +While editing a PO file, PO mode allows for the easy browsing of +auxiliary and compendium PO files, as well as for following references into +the set of C program sources from which PO files have been derived. +It has a few special features, among which are the interactive marking +of program strings as translatable, and the validatation of PO files +with easy repositioning to PO file lines showing errors. + +As a programmer, the first step to bringing GNU @code{gettext} +into your package is identifying, right in the C sources, those strings +which are meant to be translatable, and those which are untranslatable. +This tedious job can be done a little more comfortably using emacs PO +mode, but you can use any means familiar to you for modifying your +C sources. Beside this some other simple, standard changes are needed to +properly initialize the translation library. @xref{Sources}, for +more information about all this. + +For newly written software the strings of course can and should be +marked while writing the it. The @code{gettext} approach makes this +very easy. Simply put the following lines at the beginning of each file +or in a central header file: + +@example +@group +#define _(String) (String) +#define N_(String) (String) +#define textdomain(Domain) +#define bindtextdomain(Package, Directory) +@end group +@end example + +@noindent +Doing this allows you to prepare the sources for internationalization. +Later when you feel ready for the step to use the @code{gettext} library +simply remove these definitions, include @file{libintl.h} and link +against @file{libintl.a}. That is all you have to change. + +Once the C sources have been modified, the @code{xgettext} program +is used to find and extract all translatable strings, and create an +initial PO file out of all these. This @file{@var{package}.pot} file +contains all original program strings. It has sets of pointers to +exactly where in C sources each string is used. All translations +are set to empty. The letter @kbd{t} in @file{.pot} marks this as +a Template PO file, not yet oriented towards any particular language. +@xref{xgettext Invocation}, for more details about how one calls the +@code{xgettext} program. If you are @emph{really} lazy, you might +be interested at working a lot more right away, and preparing the +whole distribution setup (@pxref{Maintainers}). By doing so, you +spare yourself typing the @code{xgettext} command, as @code{make} +should now generate the proper things automatically for you! + +The first time through, there is no @file{@var{lang}.po} yet, so the +@code{msgmerge} step may be skipped and replaced by a mere copy of +@file{@var{package}.pot} to @file{@var{lang}.pox}, where @var{lang} +represents the target language. + +Then comes the initial translation of messages. Translation in +itself is a whole matter, still exclusively meant for humans, +and whose complexity far overwhelms the level of this manual. +Nevertheless, a few hints are given in some other chapter of this +manual (@pxref{Translators}). You will also find there indications +about how to contact translating teams, or becoming part of them, +for sharing your translating concerns with others who target the same +native language. + +While adding the translated messages into the @file{@var{lang}.pox} +PO file, if you do not have Emacs handy, you are on your own +for ensuring that your efforts fully respect the PO file format, and quoting +conventions (@pxref{PO Files}). This is surely not an impossible task, +as this is the way many people have handled PO files already for Uniforum or +Solaris. On the other hand, by using PO mode in Emacs, most details +of PO file format are taken care of for you, but you have to acquire +some familiarity with PO mode itself. Besides main PO mode commands +(@pxref{Main PO Commands}), you should know how to move between entries +(@pxref{Entry Positioning}), and how to handle untranslated entries +(@pxref{Untranslated Entries}). + +If some common translations have already been saved into a compendium +PO file, translators may use PO mode for initializing untranslated +entries from the compendium, and also save selected translations into +the compendium, updating it (@pxref{Compendium}). Compendium files +are meant to be exchanged between members of a given translation team. + +Programs, or packages of programs, are dynamic in nature: users write +bug reports and suggestion for improvements, maintainers react by +modifying programs in various ways. The fact that a package has +already been internationalized should not make maintainers shy +of adding new strings, or modifying strings already translated. +They just do their job the best they can. For the Translation +Project to work smoothly, it is important that maintainers do not +carry translation concerns on their already loaded shoulders, and that +translators be kept as free as possible of programmatic concerns. + +The only concern maintainers should have is carefully marking new +strings as translatable, when they should be, and do not otherwise +worry about them being translated, as this will come in proper time. +Consequently, when programs and their strings are adjusted in various +ways by maintainers, and for matters usually unrelated to translation, +@code{xgettext} would construct @file{@var{package}.pot} files which are +evolving over time, so the translations carried by @file{@var{lang}.po} +are slowly fading out of date. + +It is important for translators (and even maintainers) to understand +that package translation is a continuous process in the lifetime of a +package, and not something which is done once and for all at the start. +After an initial burst of translation activity for a given package, +interventions are needed once in a while, because here and there, +translated entries become obsolete, and new untranslated entries +appear, needing translation. + +The @code{msgmerge} program has the purpose of refreshing an already +existing @file{@var{lang}.po} file, by comparing it with a newer +@file{@var{package}.pot} template file, extracted by @code{xgettext} +out of recent C sources. The refreshing operation adjusts all +references to C source locations for strings, since these strings +move as programs are modified. Also, @code{msgmerge} comments out as +obsolete, in @file{@var{lang}.pox}, those already translated entries +which are no longer used in the program sources (@pxref{Obsolete +Entries}). It finally discovers new strings and inserts them in +the resulting PO file as untranslated entries (@pxref{Untranslated +Entries}). @xref{msgmerge Invocation}, for more information about what +@code{msgmerge} really does. + +Whatever route or means taken, the goal is to obtain an updated +@file{@var{lang}.pox} file offering translations for all strings. +When this is properly achieved, this file @file{@var{lang}.pox} may +take the place of the previous official @file{@var{lang}.po} file. + +The temporal mobility, or fluidity of PO files, is an integral part of +the translation game, and should be well understood, and accepted. +People resisting it will have a hard time participating in the +Translation Project, or will give a hard time to other participants! In +particular, maintainers should relax and include all available official +PO files in their distributions, even if these have not recently been +updated, without banging or otherwise trying to exert pressure on the +translator teams to get the job done. The pressure should rather come +from the community of users speaking a particular language, and +maintainers should consider themselves fairly relieved of any concern +about the adequacy of translation files. On the other hand, translators +should reasonably try updating the PO files they are responsible for, +while the package is undergoing pretest, prior to an official +distribution. + +Once the PO file is complete and dependable, the @code{msgfmt} program +is used for turning the PO file into a machine-oriented format, which +may yield efficient retrieval of translations by the programs of the +package, whenever needed at runtime (@pxref{MO Files}). @xref{msgfmt +Invocation}, for more information about all modalities of execution +for the @code{msgfmt} program. + +Finally, the modified and marked C sources are compiled and linked +with the GNU @code{gettext} library, usually through the operation of +@code{make}, given a suitable @file{Makefile} exists for the project, +and the resulting executable is installed somewhere users will find it. +The MO files themselves should also be properly installed. Given the +appropriate environment variables are set (@pxref{End Users}), the +program should localize itself automatically, whenever it executes. + +The remainder of this manual has the purpose of explaining in depth the various +steps outlined above. + +@node Basics, Sources, Introduction, Top +@chapter PO Files and PO Mode Basics + +The GNU @code{gettext} toolset helps programmers and translators +at producing, updating and using translation files, mainly those +PO files which are textual, editable files. This chapter stresses +the format of PO files, and contains a PO mode starter. PO mode +description is spread throughout this manual instead of being concentrated +in one place. Here we present only the basics of PO mode. + +@menu +* Installation:: Completing GNU @code{gettext} Installation +* PO Files:: The Format of PO Files +* Main PO Commands:: Main Commands +* Entry Positioning:: Entry Positioning +* Normalizing:: Normalizing Strings in Entries +@end menu + +@node Installation, PO Files, Basics, Basics +@section Completing GNU @code{gettext} Installation + +Once you have received, unpacked, configured and compiled the GNU +@code{gettext} distribution, the @samp{make install} command puts in +place the programs @code{xgettext}, @code{msgfmt}, @code{gettext}, and +@code{msgmerge}, as well as their available message catalogs. To +top off a comfortable installation, you might also want to make the +PO mode available to your Emacs users. + +During the installation of the PO mode, you might want modify your +file @file{.emacs}, once and for all, so it contains a few lines looking +like: + +@example +(setq auto-mode-alist + (cons '("\\.po[tx]?\\'\\|\\.po\\." . po-mode) auto-mode-alist)) +(autoload 'po-mode "po-mode") +@end example + +Later, whenever you edit some @file{.po}, @file{.pot} or @file{.pox} +file, or any file having the string @samp{.po.} within its name, +Emacs loads @file{po-mode.elc} (or @file{po-mode.el}) as needed, and +automatically activates PO mode commands for the associated buffer. +The string @emph{PO} appears in the mode line for any buffer for +which PO mode is active. Many PO files may be active at once in a +single Emacs session. + +If you are using Emacs version 20 or better, and have already installed +the appropriate international fonts on your system, you may also manage +for the these fonts to be automatically loaded and used for displaying +the translations on your Emacs screen, whenever necessary. For this to +happen, you might want to add the lines: + +@example +(autoload 'po-find-file-coding-system "po-mode") +(modify-coding-system-alist 'file "\\.po[tx]?\\'\\|\\.po\\." + 'po-find-file-coding-system) +@end example + +@noindent +to your @file{.emacs} file. + +@node PO Files, Main PO Commands, Installation, Basics +@section The Format of PO Files + +A PO file is made up of many entries, each entry holding the relation +between an original untranslated string and its corresponding +translation. All entries in a given PO file usually pertain +to a single project, and all translations are expressed in a single +target language. One PO file @dfn{entry} has the following schematic +structure: + +@example +@var{white-space} +# @var{translator-comments} +#. @var{automatic-comments} +#: @var{reference}@dots{} +#, @var{flag}@dots{} +msgid @var{untranslated-string} +msgstr @var{translated-string} +@end example + +The general structure of a PO file should be well understood by +the translator. When using PO mode, very little has to be known +about the format details, as PO mode takes care of them for her. + +Entries begin with some optional white space. Usually, when generated +through GNU @code{gettext} tools, there is exactly one blank line +between entries. Then comments follow, on lines all starting with the +character @kbd{#}. There are two kinds of comments: those which have +some white space immediately following the @kbd{#}, which comments are +created and maintained exclusively by the translator, and those which +have some non-white character just after the @kbd{#}, which comments +are created and maintained automatically by GNU @code{gettext} tools. +All comments, of either kind, are optional. + +After white space and comments, entries show two strings, giving +first the untranslated string as it appears in the original program +sources, and then, the translation of this string. The original +string is introduced by the keyword @code{msgid}, and the translation, +by @code{msgstr}. The two strings, untranslated and translated, +are quoted in various ways in the PO file, using @kbd{"} +delimiters and @kbd{\} escapes, but the translator does not really +have to pay attention to the precise quoting format, as PO mode fully +intend to take care of quoting for her. + +The @code{msgid} strings, as well as automatic comments, are produced +and managed by other GNU @code{gettext} tools, and PO mode does not +provide means for the translator to alter these. The most she can +do is merely deleting them, and only by deleting the whole entry. +On the other hand, the @code{msgstr} string, as well as translator +comments, are really meant for the translator, and PO mode gives her +the full control she needs. + +The comment lines beginning with @kbd{#,} are special because they are +not completely ignored by the programs as comments generally are. The +comma separated list of @var{flag}s is used by the @code{msgfmt} +program to give the user some better disgnostic messages. Currently +there are two forms of flags defined: + +@table @kbd +@item fuzzy +This flag can be generated by the @code{msgmerge} program or it can be +inserted by the translator herself. It shows that the @code{msgstr} +string might not be a correct translation (anymore). Only the translator +can judge if the translation requires further modification, or is +acceptable as is. Once satisfied with the translation, she then removes +this @kbd{fuzzy} attribute. The @code{msgmerge} programs inserts this +when it combined the @code{msgid} and @code{msgstr} entries after fuzzy +search only. @xref{Fuzzy Entries}. + +@item c-format +@itemx no-c-format +These flags should not be added by a human. Instead only the +@code{xgettext} program adds them. In an automatized PO file processing +system as proposed here the user changes would be thrown away again as +soon as the @code{xgettext} program generates a new template file. + +In case the @kbd{c-format} flag is given for a string the @code{msgfmt} +does some more tests to check to validity of the translation. +@xref{msgfmt Invocation}. + +@end table + +It happens that some lines, usually whitespace or comments, follow the +very last entry of a PO file. Such lines are not part of any entry, +and PO mode is unable to take action on those lines. By using the +PO mode function @w{@kbd{M-x po-normalize}}, the translator may get +rid of those spurious lines. @xref{Normalizing}. + +The remainder of this section may be safely skipped by those using +PO mode, yet it may be interesting for everybody to have a better +idea of the precise format of a PO file. On the other hand, those +not having Emacs handy should carefully continue reading on. + +Each of @var{untranslated-string} and @var{translated-string} respects +the C syntax for a character string, including the surrounding quotes +and imbedded backslashed escape sequences. When the time comes +to write multi-line strings, one should not use escaped newlines. +Instead, a closing quote should follow the last character on the +line to be continued, and an opening quote should resume the string +at the beginning of the following PO file line. For example: + +@example +msgid "" +"Here is an example of how one might continue a very long string\n" +"for the common case the string represents multi-line output.\n" +@end example + +@noindent +In this example, the empty string is used on the first line, to +allow better alignment of the @kbd{H} from the word @samp{Here} +over the @kbd{f} from the word @samp{for}. In this example, the +@code{msgid} keyword is followed by three strings, which are meant +to be concatenated. Concatenating the empty string does not change +the resulting overall string, but it is a way for us to comply with +the necessity of @code{msgid} to be followed by a string on the same +line, while keeping the multi-line presentation left-justified, as +we find this to be a cleaner disposition. The empty string could have +been omitted, but only if the string starting with @samp{Here} was +promoted on the first line, right after @code{msgid}.@footnote{This +limitation is not imposed by GNU @code{gettext}, but comes from the +@code{msgfmt} implementation on Solaris.} It was not really necessary +either to switch between the two last quoted strings immediately after +the newline @samp{\n}, the switch could have occurred after @emph{any} +other character, we just did it this way because it is neater. + +One should carefully distinguish between end of lines marked as +@samp{\n} @emph{inside} quotes, which are part of the represented +string, and end of lines in the PO file itself, outside string quotes, +which have no incidence on the represented string. + +Outside strings, white lines and comments may be used freely. +Comments start at the beginning of a line with @samp{#} and extend +until the end of the PO file line. Comments written by translators +should have the initial @samp{#} immediately followed by some white +space. If the @samp{#} is not immediately followed by white space, +this comment is most likely generated and managed by specialized GNU +tools, and might disappear or be replaced unexpectedly when the PO +file is given to @code{msgmerge}. + +@node Main PO Commands, Entry Positioning, PO Files, Basics +@section Main PO mode Commands + +After setting up Emacs with something similar to the lines in +@ref{Installation}, PO mode is activated for a window when Emacs finds a +PO file in that window. This puts the window read-only and establishes a +po-mode-map, which is a genuine Emacs mode, in a way that is not derived +from text mode in any way. Functions found on @code{po-mode-hook}, +if any, will be executed. + +When PO mode is active in a window, the letters @samp{PO} appear +in the mode line for that window. The mode line also displays how +many entries of each kind are held in the PO file. For example, +the string @samp{132t+3f+10u+2o} would tell the translator that the +PO mode contains 132 translated entries (@pxref{Translated Entries}, +3 fuzzy entries (@pxref{Fuzzy Entries}), 10 untranslated entries +(@pxref{Untranslated Entries}) and 2 obsolete entries (@pxref{Obsolete +Entries}). Zero-coefficients items are not shown. So, in this example, if +the fuzzy entries were unfuzzied, the untranslated entries were translated +and the obsolete entries were deleted, the mode line would merely display +@samp{145t} for the counters. + +The main PO commands are those which do not fit into the other categories of +subsequent sections. These allow for quitting PO mode or for managing windows +in special ways. + +@table @kbd +@item U +Undo last modification to the PO file. + +@item Q +Quit processing and save the PO file. + +@item q +Quit processing, possibly after confirmation. + +@item O +Temporary leave the PO file window. + +@item ? +@itemx h +Show help about PO mode. + +@item = +Give some PO file statistics. + +@item V +Batch validate the format of the whole PO file. + +@end table + +The command @kbd{U} (@code{po-undo}) interfaces to the Emacs +@emph{undo} facility. @xref{Undo, , Undoing Changes, emacs, The Emacs +Editor}. Each time @kbd{U} is typed, modifications which the translator +did to the PO file are undone a little more. For the purpose of +undoing, each PO mode command is atomic. This is especially true for +the @kbd{@key{RET}} command: the whole edition made by using a single +use of this command is undone at once, even if the edition itself +implied several actions. However, while in the editing window, one +can undo the edition work quite parsimoniously. + +The commands @kbd{Q} (@code{po-quit}) and @kbd{q} +(@code{po-confirm-and-quit}) are used when the translator is done with the +PO file. The former is a bit less verbose than the latter. If the file +has been modified, it is saved to disk first. In both cases, and prior to +all this, the commands check if some untranslated message remains in the +PO file and, if yes, the translator is asked if she really wants to leave +off working with this PO file. This is the preferred way of getting rid +of an Emacs PO file buffer. Merely killing it through the usual command +@w{@kbd{C-x k}} (@code{kill-buffer}) is not the tidiest way to proceed. + +The command @kbd{O} (@code{po-other-window}) is another, softer way, +to leave PO mode, temporarily. It just moves the cursor to some other +Emacs window, and pops one if necessary. For example, if the translator +just got PO mode to show some source context in some other, she might +discover some apparent bug in the program source that needs correction. +This command allows the translator to change sex, become a programmer, +and have the cursor right into the window containing the program she +(or rather @emph{he}) wants to modify. By later getting the cursor back +in the PO file window, or by asking Emacs to edit this file once again, +PO mode is then recovered. + +The command @kbd{h} (@code{po-help}) displays a summary of all available PO +mode commands. The translator should then type any character to resume +normal PO mode operations. The command @kbd{?} has the same effect +as @kbd{h}. + +The command @kbd{=} (@code{po-statistics}) computes the total number of +entries in the PO file, the ordinal of the current entry (counted from +1), the number of untranslated entries, the number of obsolete entries, +and displays all these numbers. + +The command @kbd{V} (@code{po-validate}) launches @code{msgfmt} in verbose +mode over the current PO file. This command first offers to save the +current PO file on disk. The @code{msgfmt} tool, from GNU @code{gettext}, +has the purpose of creating a MO file out of a PO file, and PO mode uses +the features of this program for checking the overall format of a PO file, +as well as all individual entries. + +The program @code{msgfmt} runs asynchronously with Emacs, so the +translator regains control immediately while her PO file is being studied. +Error output is collected in the Emacs @samp{*compilation*} buffer, +displayed in another window. The regular Emacs command @kbd{C-x`} +(@code{next-error}), as well as other usual compile commands, allow the +translator to reposition quickly to the offending parts of the PO file. +Once the cursor is on the line in error, the translator may decide on +any PO mode action which would help correcting the error. + +@node Entry Positioning, Normalizing, Main PO Commands, Basics +@section Entry Positioning + +The cursor in a PO file window is almost always part of +an entry. The only exceptions are the special case when the cursor +is after the last entry in the file, or when the PO file is +empty. The entry where the cursor is found to be is said to be the +current entry. Many PO mode commands operate on the current entry, +so moving the cursor does more than allowing the translator to browse +the PO file, this also selects on which entry commands operate. + +Some PO mode commands alter the position of the cursor in a specialized +way. A few of those special purpose positioning are described here, +the others are described in following sections. + +@table @kbd + +@item . +Redisplay the current entry. + +@item n +@itemx n +Select the entry after the current one. + +@item p +@itemx p +Select the entry before the current one. + +@item < +Select the first entry in the PO file. + +@item > +Select the last entry in the PO file. + +@item m +Record the location of the current entry for later use. + +@item l +Return to a previously saved entry location. + +@item x +Exchange the current entry location with the previously saved one. + +@end table + +Any Emacs command able to reposition the cursor may be used +to select the current entry in PO mode, including commands which +move by characters, lines, paragraphs, screens or pages, and search +commands. However, there is a kind of standard way to display the +current entry in PO mode, which usual Emacs commands moving +the cursor do not especially try to enforce. The command @kbd{.} +(@code{po-current-entry}) has the sole purpose of redisplaying the +current entry properly, after the current entry has been changed by +means external to PO mode, or the Emacs screen otherwise altered. + +It is yet to be decided if PO mode helps the translator, or otherwise +irritates her, by forcing a rigid window disposition while she +is doing her work. We originally had quite precise ideas about +how windows should behave, but on the other hand, anyone used to +Emacs is often happy to keep full control. Maybe a fixed window +disposition might be offered as a PO mode option that the translator +might activate or deactivate at will, so it could be offered on an +experimental basis. If nobody feels a real need for using it, or +a compulsion for writing it, we should drop this whole idea. +The incentive for doing it should come from translators rather than +programmers, as opinions from an experienced translator are surely +more worth to me than opinions from programmers @emph{thinking} about +how @emph{others} should do translation. + +The commands @kbd{n} (@code{po-next-entry}) and @kbd{p} +(@code{po-previous-entry}) move the cursor the entry following, +or preceding, the current one. If @kbd{n} is given while the +cursor is on the last entry of the PO file, or if @kbd{p} +is given while the cursor is on the first entry, no move is done. + +The commands @kbd{<} (@code{po-first-entry}) and @kbd{>} +(@code{po-last-entry}) move the cursor to the first entry, or last +entry, of the PO file. When the cursor is located past the last +entry in a PO file, most PO mode commands will return an error saying +@samp{After last entry}. Moreover, the commands @kbd{<} and @kbd{>} +have the special property of being able to work even when the cursor +is not into some PO file entry, and one may use them for nicely +correcting this situation. But even these commands will fail on a +truly empty PO file. There are development plans for the PO mode for it +to interactively fill an empty PO file from sources. @xref{Marking}. + +The translator may decide, before working at the translation of +a particular entry, that she needs to browse the remainder of the +PO file, maybe for finding the terminology or phraseology used +in related entries. She can of course use the standard Emacs idioms +for saving the current cursor location in some register, and use that +register for getting back, or else, use the location ring. + +PO mode offers another approach, by which cursor locations may be saved +onto a special stack. The command @kbd{m} (@code{po-push-location}) +merely adds the location of current entry to the stack, pushing +the already saved locations under the new one. The command +@kbd{r} (@code{po-pop-location}) consumes the top stack element and +reposition the cursor to the entry associated with that top element. +This position is then lost, for the next @kbd{r} will move the cursor +to the previously saved location, and so on until no locations remain +on the stack. + +If the translator wants the position to be kept on the location stack, +maybe for taking a look at the entry associated with the top +element, then go elsewhere with the intent of getting back later, she +ought to use @kbd{m} immediately after @kbd{r}. + +The command @kbd{x} (@code{po-exchange-location}) simultaneously +reposition the cursor to the entry associated with the top element of +the stack of saved locations, and replace that top element with the +location of the current entry before the move. Consequently, repeating +the @kbd{x} command toggles alternatively between two entries. +For achieving this, the translator will position the cursor on the +first entry, use @kbd{m}, then position to the second entry, and +merely use @kbd{x} for making the switch. + +@node Normalizing, , Entry Positioning, Basics +@section Normalizing Strings in Entries + +There are many different ways for encoding a particular string into a +PO file entry, because there are so many different ways to split and +quote multi-line strings, and even, to represent special characters +by backslahsed escaped sequences. Some features of PO mode rely on +the ability for PO mode to scan an already existing PO file for a +particular string encoded into the @code{msgid} field of some entry. +Even if PO mode has internally all the built-in machinery for +implementing this recognition easily, doing it fast is technically +difficult. To facilitate a solution to this efficiency problem, +we decided on a canonical representation for strings. + +A conventional representation of strings in a PO file is currently +under discussion, and PO mode experiments with a canonical representation. +Having both @code{xgettext} and PO mode converging towards a uniform +way of representing equivalent strings would be useful, as the internal +normalization needed by PO mode could be automatically satisfied +when using @code{xgettext} from GNU @code{gettext}. An explicit +PO mode normalization should then be only necessary for PO files +imported from elsewhere, or for when the convention itself evolves. + +So, for achieving normalization of at least the strings of a given +PO file needing a canonical representation, the following PO mode +command is available: + +@table @kbd +@item M-x po-normalize +Tidy the whole PO file by making entries more uniform. + +@end table + +The special command @kbd{M-x po-normalize}, which has no associate +keys, revises all entries, ensuring that strings of both original +and translated entries use uniform internal quoting in the PO file. +It also removes any crumb after the last entry. This command may be +useful for PO files freshly imported from elsewhere, or if we ever +improve on the canonical quoting format we use. This canonical format +is not only meant for getting cleaner PO files, but also for greatly +speeding up @code{msgid} string lookup for some other PO mode commands. + +@kbd{M-x po-normalize} presently makes three passes over the entries. +The first implements heuristics for converting PO files for GNU +@code{gettext} 0.6 and earlier, in which @code{msgid} and @code{msgstr} +fields were using K&R style C string syntax for multi-line strings. +These heuristics may fail for comments not related to obsolete +entries and ending with a backslash; they also depend on subsequent +passes for finalizing the proper commenting of continued lines for +obsolete entries. This first pass might disappear once all oldish PO +files would have been adjusted. The second and third pass normalize +all @code{msgid} and @code{msgstr} strings respectively. They also +clean out those trailing backslashes used by XView's @code{msgfmt} +for continued lines. + +Having such an explicit normalizing command allows for importing PO +files from other sources, but also eases the evolution of the current +convention, evolution driven mostly by aesthetic concerns, as of now. +It is easy to make suggested adjustments at a later time, as the +normalizing command and eventually, other GNU @code{gettext} tools +should greatly automate conformance. A description of the canonical +string format is given below, for the particular benefit of those not +having Emacs handy, and who would nevertheless want to handcraft +their PO files in nice ways. + +Right now, in PO mode, strings are single line or multi-line. A string +goes multi-line if and only if it has @emph{embedded} newlines, that +is, if it matches @samp{[^\n]\n+[^\n]}. So, we would have: + +@example +msgstr "\n\nHello, world!\n\n\n" +@end example + +but, replacing the space by a newline, this becomes: + +@example +msgstr "" +"\n" +"\n" +"Hello,\n" +"world!\n" +"\n" +"\n" +@end example + +We are deliberately using a caricatural example, here, to make the +point clearer. Usually, multi-lines are not that bad looking. +It is probable that we will implement the following suggestion. +We might lump together all initial newlines into the empty string, +and also all newlines introducing empty lines (that is, for @w{@var{n} +> 1}, the @var{n}-1'th last newlines would go together on a separate +string), so making the previous example appear: + +@example +msgstr "\n\n" +"Hello,\n" +"world!\n" +"\n\n" +@end example + +There are a few yet undecided little points about string normalization, +to be documented in this manual, once these questions settle. + +@node Sources, Initial, Basics, Top +@chapter Preparing Program Sources + +@c FIXME: Rewrite (the whole chapter). + +For the programmer, changes to the C source code fall into three +categories. First, you have to make the localization functions +known to all modules needing message translation. Second, you should +properly trigger the operation of GNU @code{gettext} when the program +initializes, usually from the @code{main} function. Last, you should +identify and especially mark all constant strings in your program +needing translation. + +Presuming that your set of programs, or package, has been adjusted +so all needed GNU @code{gettext} files are available, and your +@file{Makefile} files are adjusted (@pxref{Maintainers}), each C module +having translated C strings should contain the line: + +@example +#include <libintl.h> +@end example + +The remaining changes to your C sources are discussed in the further +sections of this chapter. + +@menu +* Triggering:: Triggering @code{gettext} Operations +* Mark Keywords:: How Marks Appears in Sources +* Marking:: Marking Translatable Strings +* c-format:: Telling something about the following string +* Special cases:: Special Cases of Translatable Strings +@end menu + +@node Triggering, Mark Keywords, Sources, Sources +@section Triggering @code{gettext} Operations + +The initialization of locale data should be done with more or less +the same code in every program, as demonstrated below: + +@example +@group +int +main (argc, argv) + int argc; + char argv; +@{ + @dots{} + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + @dots{} +@} +@end group +@end example + +@var{PACKAGE} and @var{LOCALEDIR} should be provided either by +@file{config.h} or by the Makefile. For now consult the @code{gettext} +sources for more information. + +The use of @code{LC_ALL} might not be appropriate for you. +@code{LC_ALL} includes all locale categories and especially +@code{LC_CTYPE}. This later category is responsible for determining +character classes with the @code{isalnum} etc. functions from +@file{ctype.h} which could especially for programs, which process some +kind of input language, be wrong. For example this would mean that a +source code using the @,{c} (c-cedilla character) is runnable in +France but not in the U.S. + +Some systems also have problems with parsing number using the +@code{scanf} functions if an other but the @code{LC_ALL} locale is used. +The standards say that additional formats but the one known in the +@code{"C"} locale might be recognized. But some systems seem to reject +numbers in the @code{"C"} locale format. In some situation, it might +also be a problem with the notation itself which makes it impossible to +recognize whether the number is in the @code{"C"} locale or the local +format. This can happen if thousands separator characters are used. +Some locales define this character accordfing to the national +conventions to @code{'.'} which is the same character used in the +@code{"C"} locale to denote the decimal point. + +So it is sometimes necessary to replace the @code{LC_ALL} line in the +code above by a sequence of @code{setlocale} lines + +@example +@group +@{ + @dots{} + setlocale (LC_TIME, ""); + setlocale (LC_MESSAGES, ""); + @dots{} +@} +@end group +@end example + +@noindent +or to switch for and back to the character class in question. On all +POSIX conformant systems the locale categories @code{LC_CTYPE}, +@code{LC_COLLATE}, @code{LC_MONETARY}, @code{LC_NUMERIC}, and +@code{LC_TIME} are available. On some modern systems there is also a +locale @code{LC_MESSAGES} which is called on some old, XPG2 compliant +systems @code{LC_RESPONSES}. + +@node Mark Keywords, Marking, Triggering, Sources +@section How Marks Appears in Sources + +All strings requiring translation should be marked in the C sources. Marking +is done in such a way that each translatable string appears to be +the sole argument of some function or preprocessor macro. There are +only a few such possible functions or macros meant for translation, +and their names are said to be marking keywords. The marking is +attached to strings themselves, rather than to what we do with them. +This approach has more uses. A blatant example is an error message +produced by formatting. The format string needs translation, as +well as some strings inserted through some @samp{%s} specification +in the format, while the result from @code{sprintf} may have so many +different instances that it is impractical to list them all in some +@samp{error_string_out()} routine, say. + +This marking operation has two goals. The first goal of marking +is for triggering the retrieval of the translation, at run time. +The keyword are possibly resolved into a routine able to dynamically +return the proper translation, as far as possible or wanted, for the +argument string. Most localizable strings are found in executable +positions, that is, attached to variables or given as parameters to +functions. But this is not universal usage, and some translatable +strings appear in structured initializations. @xref{Special cases}. + +The second goal of the marking operation is to help @code{xgettext} +at properly extracting all translatable strings when it scans a set +of program sources and produces PO file templates. + +The canonical keyword for marking translatable strings is +@samp{gettext}, it gave its name to the whole GNU @code{gettext} +package. For packages making only light use of the @samp{gettext} +keyword, macro or function, it is easily used @emph{as is}. However, +for packages using the @code{gettext} interface more heavily, it +is usually more convenient to give the main keyword a shorter, less +obtrusive name. Indeed, the keyword might appear on a lot of strings +all over the package, and programmers usually do not want nor need +their program sources to remind them forcefully, all the time, that they +are internationalized. Further, a long keyword has the disadvantage +of using more horizontal space, forcing more indentation work on +sources for those trying to keep them within 79 or 80 columns. + +Many packages use @samp{_} (a simple underline) as a keyword, +and write @samp{_("Translatable string")} instead of @samp{gettext +("Translatable string")}. Further, the coding rule, from GNU standards, +wanting that there is a space between the keyword and the opening +parenthesis is relaxed, in practice, for this particular usage. +So, the textual overhead per translatable string is reduced to +only three characters: the underline and the two parentheses. +However, even if GNU @code{gettext} uses this convention internally, +it does not offer it officially. The real, genuine keyword is truly +@samp{gettext} indeed. It is fairly easy for those wanting to use +@samp{_} instead of @samp{gettext} to declare: + +@example +#include <libintl.h> +#define _(String) gettext (String) +@end example + +@noindent +instead of merely using @samp{#include <libintl.h>}. + +Later on, the maintenance is relatively easy. If, as a programmer, +you add or modify a string, you will have to ask yourself if the +new or altered string requires translation, and include it within +@samp{_()} if you think it should be translated. @samp{"%s: %d"} is +an example of string @emph{not} requiring translation! + +@node Marking, c-format, Mark Keywords, Sources +@section Marking Translatable Strings + +In PO mode, one set of features is meant more for the programmer than +for the translator, and allows him to interactively mark which strings, +in a set of program sources, are translatable, and which are not. +Even if it is a fairly easy job for a programmer to find and mark +such strings by other means, using any editor of his choice, PO mode +makes this work more comfortable. Further, this gives translators +who feel a little like programmers, or programmers who feel a little +like translators, a tool letting them work at marking translatable +strings in the program sources, while simultaneously producing a set of +translation in some language, for the package being internationalized. + +The set of program sources, targetted by the PO mode commands describe +here, should have an Emacs tags table constructed for your project, +prior to using these PO file commands. This is easy to do. In any +shell window, change the directory to the root of your project, then +execute a command resembling: + +@example +etags src/*.[hc] lib/*.[hc] +@end example + +@noindent +presuming here you want to process all @file{.h} and @file{.c} files +from the @file{src/} and @file{lib/} directories. This command will +explore all said files and create a @file{TAGS} file in your root +directory, somewhat summarizing the contents using a special file +format Emacs can understand. + +For packages following the GNU coding standards, there is +a make goal @code{tags} or @code{TAGS} which construct the tag files in +all directories and for all files containing source code. + +Once your @file{TAGS} file is ready, the following commands assist +the programmer at marking translatable strings in his set of sources. +But these commands are necessarily driven from within a PO file +window, and it is likely that you do not even have such a PO file yet. +This is not a problem at all, as you may safely open a new, empty PO +file, mainly for using these commands. This empty PO file will slowly +fill in while you mark strings as translatable in your program sources. + +@table @kbd +@item , +Search through program sources for a string which looks like a +candidate for translation. + +@item M-, +Mark the last string found with @samp{_()}. + +@item M-. +Mark the last string found with a keyword taken from a set of possible +keywords. This command with a prefix allows some management of these +keywords. + +@end table + +The @kbd{,} (@code{po-tags-search}) command search for the next +occurrence of a string which looks like a possible candidate for +translation, and displays the program source in another Emacs window, +positioned in such a way that the string is near the top of this other +window. If the string is too big to fit whole in this window, it is +positioned so only its end is shown. In any case, the cursor +is left in the PO file window. If the shown string would be better +presented differently in different native languages, you may mark it +using @kbd{M-,} or @kbd{M-.}. Otherwise, you might rather ignore it +and skip to the next string by merely repeating the @kbd{,} command. + +A string is a good candidate for translation if it contains a sequence +of three or more letters. A string containing at most two letters in +a row will be considered as a candidate if it has more letters than +non-letters. The command disregards strings containing no letters, +or isolated letters only. It also disregards strings within comments, +or strings already marked with some keyword PO mode knows (see below). + +If you have never told Emacs about some @file{TAGS} file to use, the +command will request that you specify one from the minibuffer, the +first time you use the command. You may later change your @file{TAGS} +file by using the regular Emacs command @w{@kbd{M-x visit-tags-table}}, +which will ask you to name the precise @file{TAGS} file you want +to use. @xref{Tags, , Tag Tables, emacs, The Emacs Editor}. + +Each time you use the @kbd{,} command, the search resumes from where it was +left by the previous search, and goes through all program sources, +obeying the @file{TAGS} file, until all sources have been processed. +However, by giving a prefix argument to the command @w{(@kbd{C-u +,})}, you may request that the search be restarted all over again +from the first program source; but in this case, strings that you +recently marked as translatable will be automatically skipped. + +Using this @kbd{,} command does not prevent using of other regular +Emacs tags commands. For example, regular @code{tags-search} or +@code{tags-query-replace} commands may be used without disrupting the +independent @kbd{,} search sequence. However, as implemented, the +@emph{initial} @kbd{,} command (or the @kbd{,} command is used with a +prefix) might also reinitialize the regular Emacs tags searching to the +first tags file, this reinitialization might be considered spurious. + +The @kbd{M-,} (@code{po-mark-translatable}) command will mark the +recently found string with the @samp{_} keyword. The @kbd{M-.} +(@code{po-select-mark-and-mark}) command will request that you type +one keyword from the minibuffer and use that keyword for marking +the string. Both commands will automatically create a new PO file +untranslated entry for the string being marked, and make it the +current entry (making it easy for you to immediately proceed to its +translation, if you feel like doing it right away). It is possible +that the modifications made to the program source by @kbd{M-,} or +@kbd{M-.} render some source line longer than 80 columns, forcing you +to break and re-indent this line differently. You may use the @kbd{O} +command from PO mode, or any other window changing command from +Emacs, to break out into the program source window, and do any +needed adjustments. You will have to use some regular Emacs command +to return the cursor to the PO file window, if you want command +@kbd{,} for the next string, say. + +The @kbd{M-.} command has a few built-in speedups, so you do not +have to explicitly type all keywords all the time. The first such +speedup is that you are presented with a @emph{preferred} keyword, +which you may accept by merely typing @kbd{@key{RET}} at the prompt. +The second speedup is that you may type any non-ambiguous prefix of the +keyword you really mean, and the command will complete it automatically +for you. This also means that PO mode has to @emph{know} all +your possible keywords, and that it will not accept mistyped keywords. + +If you reply @kbd{?} to the keyword request, the command gives a +list of all known keywords, from which you may choose. When the +command is prefixed by an argument @w{(@kbd{C-u M-.})}, it inhibits +updating any program source or PO file buffer, and does some simple +keyword management instead. In this case, the command asks for a +keyword, written in full, which becomes a new allowed keyword for +later @kbd{M-.} commands. Moreover, this new keyword automatically +becomes the @emph{preferred} keyword for later commands. By typing +an already known keyword in response to @w{@kbd{C-u M-.}}, one merely +changes the @emph{preferred} keyword and does nothing more. + +All keywords known for @kbd{M-.} are recognized by the @kbd{,} command +when scanning for strings, and strings already marked by any of those +known keywords are automatically skipped. If many PO files are opened +simultaneously, each one has its own independent set of known keywords. +There is no provision in PO mode, currently, for deleting a known +keyword, you have to quit the file (maybe using @kbd{q}) and reopen +it afresh. When a PO file is newly brought up in an Emacs window, only +@samp{gettext} and @samp{_} are known as keywords, and @samp{gettext} +is preferred for the @kbd{M-.} command. In fact, this is not useful to +prefer @samp{_}, as this one is already built in the @kbd{M-,} command. + +@node c-format, Special cases, Marking, Sources +@section Special Comments preceding Keywords + +@c FIXME document c-format and no-c-format. + +In C programs strings are often used within calls of functions from the +@code{printf} family. The special thing about these format strings is +that they can contain format specifiers introduced with @kbd{%}. Assume +we have the code + +@example +printf (gettext ("String `%s' has %d characters\n"), s, strlen (s)); +@end example + +@noindent +A possible German translation for the above string might be: + +@example +"%d Zeichen lang ist die Zeichenkette `%s'" +@end example + +A C programmer, even if he cannot speak German, will recognize that +there is something wrong here. The order of the two format specifiers +is changed but of course the arguments in the @code{printf} don't have. +This will most probably lead to problems because now the length of the +string is regarded as the address. + +To prevent errors at runtime caused by translations the @code{msgfmt} +tool can check statically whether the arguments in the original and the +translation string match in type and number. If this is not the case a +warning will be given and the error cannot causes problems at runtime. + +@noindent +If the word order in the above German translation would be correct one +would have to write + +@example +"%2$d Zeichen lang ist die Zeichenkette `%1$s'" +@end example + +@noindent +The routines in @code{msgfmt} know about this special notation. + +Because not all strings in a program must be format strings it is not +useful for @code{msgfmt} to test all the strings in the @file{.po} file. +This might cause problems because the string might contain what looks +like a format specifier, but the string is not used in @code{printf}. + +Therefore the @code{xgettext} adds a special tag to those messages it +thinks might be a format string. There is no absolute rule for this, +only a heuristic. In the @file{.po} file the entry is marked using the +@code{c-format} flag in the @kbd{#,} comment line (@pxref{PO Files}). + +The careful reader now might say that this again can cause problems. +The heuristic might guess it wrong. This is true and therefore +@code{xgettext} knows about special kind of comment which lets +the programmer take over the decision. If in the same line or +the immediately preceding line of the @code{gettext} keyword +the @code{xgettext} program find a comment containing the words +@kbd{xgettext:c-format} it will mark the string in any case with +the @kbd{c-format} flag. This kind of comment should be used when +@code{xgettext} does not recognize the string as a format string but +is really is one and it should be tested. Please note that when the +comment is in the same line of the @code{gettext} keyword, it must be +before the string to be translated. + +This situation happens quite often. The @code{printf} function is often +called with strings which do not contain a format specifier. Of course +one would normally use @code{fputs} but it does happen. In this case +@code{xgettext} does not recognize this as a format string but what +happens if the translation introduces a valid format specifier? The +@code{printf} function will try to access one of the parameter but none +exists because the original code does not refer to any parameter. + +@code{xgettext} of course could make a wrong decision the other way +round. A string marked as a format string is not really a format +string. In this case the @code{msgfmt} might give too many warnings and +would prevent translating the @file{.po} file. The method to prevent +this wrong decision is similar to the one used above, only the comment +to use must contain the string @kbd{xgettext:no-c-format}. + +If a string is marked with @kbd{c-format} and this is not correct the +user can find out who is responsible for the decision. See +@ref{xgettext Invocation} to see how the @kbd{--debug} option can be +used for solving this problem. + +@node Special cases, , c-format, Sources +@section Special Cases of Translatable Strings + +The attentive reader might now point out that it is not always possible +to mark translatable string with @code{gettext} or something like this. +Consider the following case: + +@example +@group +@{ + static const char *messages[] = @{ + "some very meaningful message", + "and another one" + @}; + const char *string; + @dots{} + string + = index > 1 ? "a default message" : messages[index]; + + fputs (string); + @dots{} +@} +@end group +@end example + +While it is no problem to mark the string @code{"a default message"} it +is not possible to mark the string initializers for @code{messages}. +What is to be done? We have to fulfill two tasks. First we have to mark the +strings so that the @code{xgettext} program (@pxref{xgettext Invocation}) +can find them, and second we have to translate the string at runtime +before printing them. + +The first task can be fulfilled by creating a new keyword, which names a +no-op. For the second we have to mark all access points to a string +from the array. So one solution can look like this: + +@example +@group +#define gettext_noop(String) (String) + +@{ + static const char *messages[] = @{ + gettext_noop ("some very meaningful message"), + gettext_noop ("and another one") + @}; + const char *string; + @dots{} + string + = index > 1 ? gettext ("a default message") : gettext (messages[index]); + + fputs (string); + @dots{} +@} +@end group +@end example + +Please convince yourself that the string which is written by +@code{fputs} is translated in any case. How to get @code{xgettext} know +the additional keyword @code{gettext_noop} is explained in @ref{xgettext +Invocation}. + +The above is of course not the only solution. You could also come along +with the following one: + +@example +@group +#define gettext_noop(String) (String) + +@{ + static const char *messages[] = @{ + gettext_noop ("some very meaningful message", + gettext_noop ("and another one") + @}; + const char *string; + @dots{} + string + = index > 1 ? gettext_noop ("a default message") : messages[index]; + + fputs (gettext (string)); + @dots{} +@} +@end group +@end example + +But this has some drawbacks. First the programmer has to take care that +he uses @code{gettext_noop} for the string @code{"a default message"}. +A use of @code{gettext} could have in rare cases unpredictable results. +The second reason is found in the internals of the GNU @code{gettext} +Library which will make this solution less efficient. + +One advantage is that you need not make control flow analysis to make +sure the output is really translated in any case. But this analysis is +generally not very difficult. If it should be in any situation you can +use this second method in this situation. + +@node Initial, Updating, Sources, Top +@chapter Making the Initial PO File + +@c FIXME: Rewrite. + +@menu +* xgettext Invocation:: Invoking the @code{xgettext} Program +* C Sources Context:: C Sources Context +* Compendium:: Using Translation Compendiums +@end menu + +@node xgettext Invocation, C Sources Context, Initial, Initial +@section Invoking the @code{xgettext} Program + +@c FIXME: Rewrite. + +@example +xgettext [@var{option}] @var{inputfile} @dots{} +@end example + +@table @samp +@item -a +@itemx --extract-all +Extract all strings. + +@item -c [@var{tag}] +@itemx --add-comments[=@var{tag}] +Place comment block with @var{tag} (or those preceding keyword lines) +in output file. + +@item -C +@itemx --c++ +Recognize C++ style comments. + +@itemx --debug +Use the flags @kbd{c-format} and @kbd{possible-c-format} to show who was +responsible for marking a message as a format string. The later form is +used if the @code{xgettext} program decided, the format form is used if +the programmer prescribed it. + +By default only the @kbd{c-format} form is used. The translator should +not have to care about these details. + +@item -d @var{name} +@itemx --default-domain=@var{name} +Use @file{@var{name}.po} for output (instead of @file{messages.po}). + +The special domain name @file{-} or @file{/dev/stdout} means to write +the output to @file{stdout}. + +@item -D @var{directory} +@itemx --directory=@var{directory} +Change to @var{directory} before beginning to search and scan source +files. The resulting @file{.po} file will be written relative to the +original directory, though. + +@item -f @var{file} +@itemx --files-from=@var{file} +Read the names of the input files from @var{file} instead of getting +them from the command line. + +@itemx --force +Always write output file even if no message is defined. + +@item -h +@itemx --help +Display this help and exit. + +@item -I @var{list} +@itemx --input-path=@var{list} +List of directories searched for input files. + +@item -j +@itemx --join-existing +Join messages with existing file. + +@item -k @var{word} +@itemx --keyword[=@var{word}] +Additonal keyword to be looked for (without @var{word} means not to +use default keywords). + +The default keywords, which are always looked for if not explicitly +disabled, are @code{gettext}, @code{dgettext}, @code{dcgettext} and +@code{gettext_noop}. + +@item -m [@var{string}] +@itemx --msgstr-prefix[=@var{string}] +Use @var{string} or "" as prefix for msgstr entries. + +@item -M [@var{string}] +@itemx --msgstr-suffix[=@var{string}] +Use @var{string} or "" as suffix for msgstr entries. + +@item --no-location +Do not write @samp{#: @var{filename}:@var{line}} lines. + +@item -n +@itemx --add-location +Generate @samp{#: @var{filename}:@var{line}} lines (default). + +@item --omit-header +Don't write header with @samp{msgid ""} entry. + +This is useful for testing purposes because it eliminates a source +of variance for generated @code{.gmo} files. We can ship some of +these files in the GNU @code{gettext} package, and the result of +regenerating them through @code{msgfmt} should yield the same values. + +@item -p @var{dir} +@itemx --output-dir=@var{dir} +Output files will be placed in directory @var{dir}. + +@item -s +@itemx --sort-output +Generate sorted output and remove duplicates. + +@item --strict +Write out strict Uniforum conforming PO file. + +@item -v +@itemx --version +Output version information and exit. + +@item -x @var{file} +@itemx --exclude-file=@var{file} +Entries from @var{file} are not extracted. + +@end table + +Search path for supplementary PO files is: +@file{/usr/local/share/nls/src/}. + +If @var{inputfile} is @samp{-}, standard input is read. + +This implementation of @code{xgettext} is able to process a few awkward +cases, like strings in preprocessor macros, ANSI concatenation of +adjacent strings, and escaped end of lines for continued strings. + +@node C Sources Context, Compendium, xgettext Invocation, Initial +@section C Sources Context + +PO mode is particularily powerful when used with PO files +created through GNU @code{gettext} utilities, as those utilities +insert special comments in the PO files they generate. +Some of these special comments relate the PO file entry to +exactly where the untranslated string appears in the program sources. + +When the translator gets to an untranslated entry, she is fairly +often faced with an original string which is not as informative as +it normally should be, being succinct, cryptic, or otherwise ambiguous. +Before chosing how to translate the string, she needs to understand +better what the string really means and how tight the translation has +to be. Most of times, when problems arise, the only way left to make +her judgment is looking at the true program sources from where this +string originated, searching for surrounding comments the programmer +might have put in there, and looking around for helping clues of +@emph{any} kind. + +Surely, when looking at program sources, the translator will receive +more help if she is a fluent programmer. However, even if she is +not versed in programming and feels a little lost in C code, the +translator should not be shy at taking a look, once in a while. +It is most probable that she will still be able to find some of the +hints she needs. She will learn quickly to not feel uncomfortable +in program code, paying more attention to programmer's comments, +variable and function names (if he dared chosing them well), and +overall organization, than to programmation itself. + +The following commands are meant to help the translator at getting +program source context for a PO file entry. + +@table @kbd +@item s +Resume the display of a program source context, or cycle through them. + +@item M-s +Display of a program source context selected by menu. + +@item S +Add a directory to the search path for source files. + +@item M-S +Delete a directory from the search path for source files. + +@end table + +The commands @kbd{s} (@code{po-cycle-reference}) and @kbd{M-s} +(@code{po-select-source-reference}) both open another window displaying +some source program file, and already positioned in such a way that +it shows an actual use of the string to be translated. By doing +so, the command gives source program context for the string. But if +the entry has no source context references, or if all references +are unresolved along the search path for program sources, then the +command diagnoses this as an error. + +Even if @kbd{s} (or @kbd{M-s}) opens a new window, the cursor stays +in the PO file window. If the translator really wants to +get into the program source window, she ought to do it explicitly, +maybe by using command @kbd{O}. + +When @kbd{s} is typed for the first time, or for a PO file entry which +is different of the last one used for getting source context, then the +command reacts by giving the first context available for this entry, +if any. If some context has already been recently displayed for the +current PO file entry, and the translator wandered off to do other +things, typing @kbd{s} again will merely resume, in another window, +the context last displayed. In particular, if the translator moved +the cursor away from the context in the source file, the command will +bring the cursor back to the context. By using @kbd{s} many times +in a row, with no other commands intervening, PO mode will cycle to +the next available contexts for this particular entry, getting back +to the first context once the last has been shown. + +The command @kbd{M-s} behaves differently. Instead of cycling through +references, it lets the translator choose of particular reference among +many, and displays that reference. It is best used with completion, +if the translator types @kbd{@key{TAB}} immediately after @kbd{M-s}, in +response to the question, she will be offered a menu of all possible +references, as a reminder of which are the acceptable answers. +This command is useful only where there are really many contexts +available for a single string to translate. + +Program source files are usually found relative to where the PO +file stands. As a special provision, when this fails, the file is +also looked for, but relative to the directory immediately above it. +Those two cases take proper care of most PO files. However, it might +happen that a PO file has been moved, or is edited in a different +place than its normal location. When this happens, the translator +should tell PO mode in which directory normally sits the genuine PO +file. Many such directories may be specified, and all together, they +constitute what is called the @dfn{search path} for program sources. +The command @kbd{S} (@code{po-consider-source-path}) is used to interactively +enter a new directory at the front of the search path, and the command +@kbd{M-S} (@code{po-ignore-source-path}) is used to select, with completion, +one of the directories she does not want anymore on the search path. + +@node Compendium, , C Sources Context, Initial +@section Using Translation Compendiums + +@c FIXME: Rewrite. + +Compendiums are yet to be implemented. + +An incoming PO mode feature will let the translator maintain a +compendium of already achieved translations. A @dfn{compendium} +is a special PO file containing a set of translations recurring in +many different packages. The translator will be given commands for +adding entries to her compendium, and later initializing untranslated +entries, or updating already translated entries, from translations +kept in the compendium. For this to work, however, the compendium +would have to be normalized. @xref{Normalizing}. + +@c It is not useful that I modify the @file{lib/} routines if not done in +@c the true sources. How do you/I/they proceed for getting this job done? +@c I presume that @file{lib/} routines will all use @code{gettext} for +@c the time being. + +@node Updating, Binaries, Initial, Top +@chapter Updating Existing PO Files + +@c FIXME: Rewrite. + +@menu +* msgmerge Invocation:: Invoking the @code{msgmerge} Program +* Translated Entries:: Translated Entries +* Fuzzy Entries:: Fuzzy Entries +* Untranslated Entries:: Untranslated Entries +* Obsolete Entries:: Obsolete Entries +* Modifying Translations:: Modifying Translations +* Modifying Comments:: Modifying Comments +* Subedit:: Mode for Editing Translations +* Auxiliary:: Consulting Auxiliary PO Files +@end menu + +@node msgmerge Invocation, Translated Entries, Updating, Updating +@section Invoking the @code{msgmerge} Program + +@c FIXME: Rewrite. + +@c @example +@c tupdate --help +@c tupdate --version +@c tupdate @var{new} @var{old} +@c @end example + +@c File @var{new} is the last created PO file (generally by +@c @code{xgettext}). It need not contain any translations. File +@c @var{old} is the PO file including the old translations which will +@c be taken over to the newly created file as long as they still match. + +@c When English messages change in the programs, this is reflected in +@c the PO file as extracted by @code{xgettext}. In large messages, that +@c can be hard to detect, and will obviously result in an incomplete +@c translation. One of the virtues of @code{tupdate} is that it detects +@c such changes, saving the previous translation into a PO file comment, +@c so marking the entry as obsolete, and giving the modified string with +@c an empty translation, that is, marking the entry as untranslated. + +@node Translated Entries, Fuzzy Entries, msgmerge Invocation, Updating +@section Translated Entries + +Each PO file entry for which the @code{msgstr} field has been filled with +a translation, and which is not marked as fuzzy (@pxref{Fuzzy Entries}), +is a said to be a @dfn{translated} entry. Only translated entries will +later be compiled by GNU @code{msgfmt} and become usable in programs. +Other entry types will be excluded; translation will not occur for them. + +Some commands are more specifically related to translated entry processing. + +@table @kbd +@item t +Find the next translated entry. + +@item M-t +Find the previous translated entry. + +@end table + +The commands @kbd{t} (@code{po-next-translated-entry}) and @kbd{M-t} +(@code{po-previous-transted-entry}) move forwards or backwards, chasing +for an translated entry. If none is found, the search is extended and +wraps around in the PO file buffer. + +Translated entries usually result from the translator having edited in +a translation for them, @ref{Modifying Translations}. However, if the +variable @code{po-auto-fuzzy-on-edit} is not @code{nil}, the entry having +received a new translation first becomes a fuzzy entry, which ought to +be later unfuzzied before becoming an official, genuine translated entry. +@xref{Fuzzy Entries}. + +@node Fuzzy Entries, Untranslated Entries, Translated Entries, Updating +@section Fuzzy Entries + +Each PO file entry may have a set of @dfn{attributes}, which are +qualities given an name and explicitely associated with the entry +translation, using a special system comment. One of these attributes +has the name @code{fuzzy}, and entries having this attribute are said +to have a fuzzy translation. They are called fuzzy entries, for short. + +Fuzzy entries, even if they account for translated entries for +most other purposes, usually call for revision by the translator. +Those may be produced by applying the program @code{msgmerge} to +update an older translated PO files according to a new PO template +file, when this tool hypothesises that some new @code{msgid} has +been modified only slightly out of an older one, and chooses to pair +what it thinks to be the old translation for the new modified entry. +The slight alteration in the original string (the @code{msgid} string) +should often be reflected in the translated string, and this requires +the intervention of the translator. For this reason, @code{msgmerge} +might mark some entries as being fuzzy. + +Also, the translator may decide herself to mark an entry as fuzzy +for her own convenience, when she wants to remember that the entry +has to be later revisited. So, some commands are more specifically +related to fuzzy entry processing. + +@table @kbd +@item f +Find the next fuzzy entry. + +@item M-f +Find the previous fuzzy entry. + +@item @key{TAB} +Remove the fuzzy attribute of the current entry. + +@end table + +The commands @kbd{f} (@code{po-next-fuzzy}) and @kbd{M-f} +(@code{po-previous-fuzzy}) move forwards or backwards, chasing for +a fuzzy entry. If none is found, the search is extended and wraps +around in the PO file buffer. + +The command @kbd{@key{TAB}} (@code{po-unfuzzy}) removes the fuzzy +attribute associated with an entry, usually leaving it translated. +Further, if the variable @code{po-auto-select-on-unfuzzy} has not +the @code{nil} value, the @kbd{@key{TAB}} command will automatically chase +for another interesting entry to work on. The initial value of +@code{po-auto-select-on-unfuzzy} is @code{nil}. + +The initial value of @code{po-auto-fuzzy-on-edit} is @code{nil}. However, +if the variable @code{po-auto-fuzzy-on-edit} is set to @code{t}, any entry +edited through the @kbd{@key{RET}} command is marked fuzzy, as a way to +ensure some kind of double check, later. In this case, the usual paradigm +is that an entry becomes fuzzy (if not already) whenever the translator +modifies it. If she is satisfied with the translation, she then uses +@kbd{@key{TAB}} to pick another entry to work on, clearing the fuzzy attribute +on the same blow. If she is not satisfied yet, she merely uses @kbd{@key{SPC}} +to chase another entry, leaving the entry fuzzy. + +The translator may also use the @kbd{@key{DEL}} command +(@code{po-fade-out-entry}) over any translated entry to mark it as being +fuzzy, when she wants to easily leave a trace she wants to later return +working at this entry. + +Also, when time comes to quit working on a PO file buffer with the @kbd{q} +command, the translator is asked for confirmation, if fuzzy string +still exists. + +@node Untranslated Entries, Obsolete Entries, Fuzzy Entries, Updating +@section Untranslated Entries + +When @code{xgettext} originally creates a PO file, unless told +otherwise, it initializes the @code{msgid} field with the untranslated +string, and leaves the @code{msgstr} string to be empty. Such entries, +having an empty translation, are said to be @dfn{untranslated} entries. +Later, when the programmer slightly modifies some string right in +the program, this change is later reflected in the PO file +by the appearance of a new untranslated entry for the modified string. + +The usual commands moving from entry to entry consider untranslated +entries on the same level as active entries. Untranslated entries +are easily recognizable by the fact they end with @w{@samp{msgstr ""}}. + +The work of the translator might be (quite naively) seen as the process +of seeking after an untranslated entry, editing a translation for +it, and repeating these actions until no untranslated entries remain. +Some commands are more specifically related to untranslated entry +processing. + +@table @kbd +@item u +Find the next untranslated entry. + +@item M-u +Find the previous untranslated entry. + +@item k +Turn the current entry into an untranslated one. + +@end table + +The commands @kbd{u} (@code{po-next-untranslated-entry}) and @kbd{M-u} +(@code{po-previous-untransted-entry}) move forwards or backwards, +chasing for an untranslated entry. If none is found, the search is +extended and wraps around in the PO file buffer. + +An entry can be turned back into an untranslated entry by +merely emptying its translation, using the command @kbd{k} +(@code{po-kill-msgstr}). @xref{Modifying Translations}. + +Also, when time comes to quit working on a PO file buffer +with the @kbd{q} command, the translator is asked for confirmation, +if some untranslated string still exists. + +@node Obsolete Entries, Modifying Translations, Untranslated Entries, Updating +@section Obsolete Entries + +By @dfn{obsolete} PO file entries, we mean those entries which are +commented out, usually by @code{msgmerge} when it found that the +translation is not needed anymore by the package being localized. + +The usual commands moving from entry to entry consider obsolete +entries on the same level as active entries. Obsolete entries are +easily recognizable by the fact that all their lines start with +@kbd{#}, even those lines containing @code{msgid} or @code{msgstr}. + +Commands exist for emptying the translation or reinitializing it +to the original untranslated string. Commands interfacing with the +kill ring may force some previously saved text into the translation. +The user may interactively edit the translation. All these commands +may apply to obsolete entries, carefully leaving the entry obsolete +after the fact. + +Moreover, some commands are more specifically related to obsolete +entry processing. + +@table @kbd +@item o +Find the next obsolete entry. + +@item M-o +Find the previous obsolete entry. + +@item @key{DEL} +Make an active entry obsolete, or zap out an obsolete entry. + +@end table + +The commands @kbd{o} (@code{po-next-obsolete-entry}) and @kbd{M-o} +(@code{po-previous-obsolete-entry}) move forwards or backwards, +chasing for an obsolete entry. If none is found, the search is +extended and wraps around in the PO file buffer. + +PO mode does not provide ways for un-commenting an obsolete entry +and making it active, because this would reintroduce an original +untranslated string which does not correspond to any marked string +in the program sources. This goes with the philosophy of never +introducing useless @code{msgid} values. + +However, it is possible to comment out an active entry, so making +it obsolete. GNU @code{gettext} utilities will later react to the +disappearance of a translation by using the untranslated string. +The command @kbd{@key{DEL}} (@code{po-fade-out-entry}) pushes the current entry +a little further towards annihilation. If the entry is active (it is a +translated entry), then it is first made fuzzy. If it is already fuzzy, +then the entry is merely commented out, with confirmation. If the entry +is already obsolete, then it is completely deleted from the PO file. +It is easy to recycle the translation so deleted into some other PO file +entry, usually one which is untranslated. @xref{Modifying Translations}. + +Here is a quite interesting problem to solve for later development of +PO mode, for those nights you are not sleepy. The idea would be that +PO mode might become bright enough, one of these days, to make good +guesses at retrieving the most probable candidate, among all obsolete +entries, for initializing the translation of a newly appeared string. +I think it might be a quite hard problem to do this algorithmically, as +we have to develop good and efficient measures of string similarity. +Right now, PO mode completely lets the decision to the translator, +when the time comes to find the adequate obsolete translation, it +merely tries to provide handy tools for helping her to do so. + +@node Modifying Translations, Modifying Comments, Obsolete Entries, Updating +@section Modifying Translations + +PO mode prevents direct edition of the PO file, by the usual +means Emacs give for altering a buffer's contents. By doing so, +it pretends helping the translator to avoid little clerical errors +about the overall file format, or the proper quoting of strings, +as those errors would be easily made. Other kinds of errors are +still possible, but some may be caught and diagnosed by the batch +validation process, which the translator may always trigger by the +@kbd{V} command. For all other errors, the translator has to rely on +her own judgment, and also on the linguistic reports submitted to her +by the users of the translated package, having the same mother tongue. + +When the time comes to create a translation, correct an error diagnosed +mechanically or reported by a user, the translators have to resort to +using the following commands for modifying the translations. + +@table @kbd +@item @key{RET} +Interactively edit the translation. + +@item @key{LFD} +Reinitialize the translation with the original, untranslated string. + +@item k +Save the translation on the kill ring, and delete it. + +@item w +Save the translation on the kill ring, without deleting it. + +@item y +Replace the translation, taking the new from the kill ring. + +@end table + +The command @kbd{@key{RET}} (@code{po-edit-msgstr}) opens a new Emacs +window meant to edit in a new translation, or to modify an already existing +translation. The new window contains a copy of the translation taken from +the current PO file entry, all ready for edition, expunged of all quoting +marks, fully modifiable and with the complete extent of Emacs modifying +commands. When the translator is done with her modifications, she may use +@w{@kbd{C-c C-c}} to close the subedit window with the automatically requoted +results, or @w{@kbd{C-c C-k}} to abort her modifications. @xref{Subedit}, +for more information. + +The command @kbd{@key{LFD}} (@code{po-msgid-to-msgstr}) initializes, or +reinitializes the translation with the original string. This command is +normally used when the translator wants to redo a fresh translation of +the original string, disregarding any previous work. + +It is possible to arrange so, whenever editing an untranslated +entry, the @kbd{@key{LFD}} command be automatically executed. If you set +@code{po-auto-edit-with-msgid} to @code{t}, the translation gets +initialised with the original string, in case none exist already. +The default value for @code{po-auto-edit-with-msgid} is @code{nil}. + +In fact, whether it is best to start a translation with an empty +string, or rather with a copy of the original string, is a matter of +taste or habit. Sometimes, the source language and the +target language are so different that is simply best to start writing +on an empty page. At other times, the source and target languages +are so close that it would be a waste to retype a number of words +already being written in the original string. A translator may also +like having the original string right under her eyes, as she will +progressively overwrite the original text with the translation, even +if this requires some extra editing work to get rid of the original. + +The command @kbd{k} (@code{po-kill-msgstr}) merely empties the +translation string, so turning the entry into an untranslated +one. But while doing so, its previous contents is put apart in +a special place, known as the kill ring. The command @kbd{w} +(@code{po-kill-ring-save-msgstr}) has also the effect of taking a +copy of the translation onto the kill ring, but it otherwise leaves +the entry alone, and does @emph{not} remove the translation from the +entry. Both commands use exactly the Emacs kill ring, which is shared +between buffers, and which is well known already to Emacs lovers. + +The translator may use @kbd{k} or @kbd{w} many times in the course +of her work, as the kill ring may hold several saved translations. +From the kill ring, strings may later be reinserted in various +Emacs buffers. In particular, the kill ring may be used for moving +translation strings between different entries of a single PO file +buffer, or if the translator is handling many such buffers at once, +even between PO files. + +To facilitate exchanges with buffers which are not in PO mode, the +translation string put on the kill ring by the @kbd{k} command is fully +unquoted before being saved: external quotes are removed, multi-lines +strings are concatenated, and backslashed escaped sequences are turned +into their corresponding characters. In the special case of obsolete +entries, the translation is also uncommented prior to saving. + +The command @kbd{y} (@code{po-yank-msgstr}) completely replaces the +translation of the current entry by a string taken from the kill ring. +Following Emacs terminology, we then say that the replacement +string is @dfn{yanked} into the PO file buffer. +@xref{Yanking, , , emacs, The Emacs Editor}. +The first time @kbd{y} is used, the translation receives the value of +the most recent addition to the kill ring. If @kbd{y} is typed once +again, immediately, without intervening keystrokes, the translation +just inserted is taken away and replaced by the second most recent +addition to the kill ring. By repeating @kbd{y} many times in a row, +the translator may travel along the kill ring for saved strings, +until she finds the string she really wanted. + +When a string is yanked into a PO file entry, it is fully and +automatically requoted for complying with the format PO files should +have. Further, if the entry is obsolete, PO mode then appropriately +push the inserted string inside comments. Once again, translators +should not burden themselves with quoting considerations besides, of +course, the necessity of the translated string itself respective to +the program using it. + +Note that @kbd{k} or @kbd{w} are not the only commands pushing strings +on the kill ring, as almost any PO mode command replacing translation +strings (or the translator comments) automatically save the old string +on the kill ring. The main exceptions to this general rule are the +yanking commands themselves. + +To better illustrate the operation of killing and yanking, let's +use an actual example, taken from a common situation. When the +programmer slightly modifies some string right in the program, his +change is later reflected in the PO file by the appearance +of a new untranslated entry for the modified string, and the fact +that the entry translating the original or unmodified string becomes +obsolete. In many cases, the translator might spare herself some work +by retrieving the unmodified translation from the obsolete entry, +then initializing the untranslated entry @code{msgstr} field with +this retrieved translation. Once this done, the obsolete entry is +not wanted anymore, and may be safely deleted. + +When the translator finds an untranslated entry and suspects that a +slight variant of the translation exists, she immediately uses @kbd{m} +to mark the current entry location, then starts chasing obsolete +entries with @kbd{o}, hoping to find some translation corresponding +to the unmodified string. Once found, she uses the @kbd{@key{DEL}} command +for deleting the obsolete entry, knowing that @kbd{@key{DEL}} also @emph{kills} +the translation, that is, pushes the translation on the kill ring. +Then, @kbd{r} returns to the initial untranslated entry, @kbd{y} +then @emph{yanks} the saved translation right into the @code{msgstr} +field. The translator is then free to use @kbd{@key{RET}} for fine +tuning the translation contents, and maybe to later use @kbd{u}, +then @kbd{m} again, for going on with the next untranslated string. + +When some sequence of keys has to be typed over and over again, the +translator may find it useful to become better acquainted with the Emacs +capability of learning these sequences and playing them back under request. +@xref{Keyboard Macros, , , emacs, The Emacs Editor}. + +@node Modifying Comments, Subedit, Modifying Translations, Updating +@section Modifying Comments + +Any translation work done seriously will raise many linguistic +difficulties, for which decisions have to be made, and the choices +further documented. These documents may be saved within the +PO file in form of translator comments, which the translator +is free to create, delete, or modify at will. These comments may +be useful to herself when she returns to this PO file after a while. + +Comments not having whitespace after the initial @samp{#}, for example, +those beginning with @samp{#.} or @samp{#:}, are @emph{not} translator +comments, they are exclusively created by other @code{gettext} tools. +So, the commands below will never alter such system added comments, +they are not meant for the translator to modify. @xref{PO Files}. + +The following commands are somewhat similar to those modifying translations, +so the general indications given for those apply here. @xref{Modifying +Translations}. + +@table @kbd + +@item # +Interactively edit the translator comments. + +@item K +Save the translator comments on the kill ring, and delete it. + +@item W +Save the translator comments on the kill ring, without deleting it. + +@item Y +Replace the translator comments, taking the new from the kill ring. + +@end table + +These commands parallel PO mode commands for modifying the translation +strings, and behave much the same way as they do, except that they handle +this part of PO file comments meant for translator usage, rather +than the translation strings. So, if the descriptions given below are +slightly succinct, it is because the full details have already been given. +@xref{Modifying Translations}. + +The command @kbd{#} (@code{po-edit-comment}) opens a new Emacs window +containing a copy of the translator comments on the current PO file entry. +If there are no such comments, PO mode understands that the translator wants +to add a comment to the entry, and she is presented with an empty screen. +Comment marks (@kbd{#}) and the space following them are automatically +removed before edition, and reinstated after. For translator comments +pertaining to obsolete entries, the uncommenting and recommenting operations +are done twice. Once in the editing window, the keys @w{@kbd{C-c C-c}} +allow the translator to tell she is finished with editing the comment. +@xref{Subedit}, for further details. + +Functions found on @code{po-subedit-mode-hook}, if any, are executed after +the string has been inserted in the edit buffer. + +The command @kbd{K} (@code{po-kill-comment}) get rid of all +translator comments, while saving those comments on the kill ring. +The command @kbd{W} (@code{po-kill-ring-save-comment}) takes +a copy of the translator comments on the kill ring, but leaves +them undisturbed in the current entry. The command @kbd{Y} +(@code{po-yank-comment}) completely replaces the translator comments +by a string taken at the front of the kill ring. When this command +is immediately repeated, the comments just inserted are withdrawn, +and replaced by other strings taken along the kill ring. + +On the kill ring, all strings have the same nature. There is no +distinction between @emph{translation} strings and @emph{translator +comments} strings. So, for example, let's presume the translator +has just finished editing a translation, and wants to create a new +translator comment to document why the previous translation was +not good, just to remember what was the problem. Foreseeing that she +will do that in her documentation, the translator may want to quote +the previous translation in her translator comments. To do so, she +may initialize the translator comments with the previous translation, +still at the head of the kill ring. Because editing already pushed the +previous translation on the kill ring, she merely has to type @kbd{M-w} +prior to @kbd{#}, and the previous translation will be right there, +all ready for being introduced by some explanatory text. + +On the other hand, presume there are some translator comments already +and that the translator wants to add to those comments, instead +of wholly replacing them. Then, she should edit the comment right +away with @kbd{#}. Once inside the editing window, she can use the +regular Emacs commands @kbd{C-y} (@code{yank}) and @kbd{M-y} +(@code{yank-pop}) to get the previous translation where she likes. + +@node Subedit, Auxiliary, Modifying Comments, Updating +@section Details of Sub Edition + +The PO subedit minor mode has a few peculiarities worth being described +in fuller detail. It installs a few commands over the usual editing set +of Emacs, which are described below. + +@table @kbd +@item C-c C-c +Complete edition. + +@item C-c C-k +Abort edition. + +@item C-c C-a +Consult auxiliary PO files. + +@end table + +The windows contents represents a translation for a given message, +or a translator comment. The translator may modify this window to +her heart's content. Once this done, the command @w{@kbd{C-c C-c}} +(@code{po-subedit-exit}) may be used to return the edited translation into +the PO file, replacing the original translation, even if it moved out of +sight or if buffers were switched. + +If the translator becomes unsatisfied with her translation or comment, +to the extent she prefers keeping what was existent prior to the +@kbd{@key{RET}} or @kbd{#} command, she may use the command @w{@kbd{C-c C-k}} +(@code{po-subedit-abort}) to merely get rid of edition, while preserving +the original translation or comment. Another way would be for her to exit +normally with @w{@kbd{C-c C-c}}, then type @code{U} once for undoing the +whole effect of last edition. + +The command @w{@kbd{C-c C-a}} allows for glancing through translations +already achieved in other languages, directly while editing the current +translation. This may be quite convenient when the translator is fluent +at many languages, but of course, only makes sense when such completed +auxiliary PO files are already available to her (@pxref{Auxiliary}). + +Functions found on @code{po-subedit-mode-hook}, if any, are executed after +the string has been inserted in the edit buffer. + +While editing her translation, the translator should pay attention to not +inserting unwanted @kbd{@key{RET}} (carriage returns) characters at the end +of the translated string if those are not meant to be there, or to removing +such characters when they are required. Since these characters are not +visible in the editing buffer, they are easily introduced by mistake. +To help her, @kbd{@key{RET}} automatically puts the character @kbd{<} +at the end of the string being edited, but this @kbd{<} is not really +part of the string. On exiting the editing window with @w{@kbd{C-c C-c}}, +PO mode automatically removes such @kbd{<} and all whitespace added after +it. If the translator adds characters after the terminating @kbd{<}, it +looses its delimiting property and integrally becomes part of the string. +If she removes the delimiting @kbd{<}, then the edited string is taken +@emph{as is}, with all trailing newlines, even if invisible. Also, if +the translated string ought to end itself with a genuine @kbd{<}, then +the delimiting @kbd{<} may not be removed; so the string should appear, +in the editing window, as ending with two @kbd{<} in a row. + +When a translation (or a comment) is being edited, the translator may move +the cursor back into the PO file buffer and freely move to other entries, +browsing at will. If, with an edition pending, the translator wanders in the +PO file buffer, she may decide to start modifying another entry. Each entry +being edited has its own subedit buffer. It is possible to simultaneously +edit the translation @emph{and} the comment of a single entry, or to +edit entries in different PO files, all at once. Typing @kbd{@key{RET}} +on a field already being edited merely resume that particular edit. Yet, +the translator should better be comfortable at handling many Emacs windows! + +Pending subedits may be completed or aborted in any order, regardless +of how or when they were started. When many subedits are pending and the +translator asks for quitting the PO file (with the @kbd{q} command), subedits +are automatically resumed one at a time, so she may decide for each of them. + +@node Auxiliary, , Subedit, Updating +@section Consulting Auxiliary PO Files + +PO mode is able to help the knowledgeable translator, being fluent in +many languages, at taking advantage of translations already achieved +in other languages she just happens to know. It provides these other +language translations as additional context for her own work. Moreover, +it has features to ease the production of translations for many languages +at once, for translators preferring to work in this way. + +An @dfn{auxiliary} PO file is an existing PO file meant for the same +package the translator is working on, but targeted to a different mother +tongue language. Commands exist for declaring and handling auxiliary +PO files, and also for showing contexts for the entry under work. + +Here are the auxiliary file commands available in PO mode. + +@table @kbd +@item a +Seek auxiliary files for another translation for the same entry. + +@item M-a +Switch to a particular auxiliary file. + +@item A +Declare this PO file as an auxiliary file. + +@item M-A +Remove this PO file from the list of auxiliary files. + +@end table + +Command @kbd{A} (@code{po-consider-as-auxiliary}) adds the current +PO file to the list of auxiliary files, while command @kbd{M-A} +(@code{po-ignore-as-auxiliary} just removes it. + +The command @kbd{a} (@code{po-cycle-auxiliary}) seeks all auxiliary PO +files, round-robin, searching for a translated entry in some other language +having an @code{msgid} field identical as the one for the current entry. +The found PO file, if any, takes the place of the current PO file in +the display (its window gets on top). Before doing so, the current PO +file is also made into an auxiliary file, if not already. So, @kbd{a} +in this newly displayed PO file will seek another PO file, and so on, +so repeating @kbd{a} will eventually yield back the original PO file. + +The command @kbd{M-a} (@code{po-select-auxiliary}) asks the translator +for her choice of a particular auxiliary file, with completion, and +then switches to that selected PO file. The command also checks if +the selected file has an @code{msgid} field identical as the one for +the current entry, and if yes, this entry becomes current. Otherwise, +the cursor of the selected file is left undisturbed. + +For all this to work fully, auxiliary PO files will have to be normalized, +in that way that @code{msgid} fields should be written @emph{exactly} +the same way. It is possible to write @code{msgid} fields in various +ways for representing the same string, different writing would break the +proper behaviour of the auxiliary file commands of PO mode. This is not +expected to be much a problem in practice, as most existing PO files have +their @code{msgid} entries written by the same GNU @code{gettext} tools. + +However, PO files initially created by PO mode itself, while marking +strings in source files, are normalised differently. So are PO +files resulting of the the @samp{M-x normalize} command. Until these +discrepancies between PO mode and other GNU @code{gettext} tools get +fully resolved, the translator should stay aware of normalisation issues. + +@node Binaries, Users, Updating, Top +@chapter Producing Binary MO Files + +@c FIXME: Rewrite. + +@menu +* msgfmt Invocation:: Invoking the @code{msgfmt} Program +* MO Files:: The Format of GNU MO Files +@end menu + +@node msgfmt Invocation, MO Files, Binaries, Binaries +@section Invoking the @code{msgfmt} Program + +@c FIXME: Rewrite. + +@example +Usage: msgfmt [@var{option}] @var{filename}.po @dots{} +@end example + +@table @samp +@item -a @var{number} +@itemx --alignment=@var{number} +Align strings to @var{number} bytes (default: 1). +@c Currently the README mentions that this constant could be changed by +@c the installer by changing the value in config.h. Should this go away? + +@item -h +@itemx --help +Display this help and exit. + +@item --no-hash +Binary file will not include the hash table. + +@item -o @var{file} +@itemx --output-file=@var{file} +Specify output file name as @var{file}. + +@itemx --strict +Direct the program to work strictly following the Uniforum/Sun +implementation. Currently this only affects the naming of the output +file. If this option is not given the name of the output file is the +same as the domain name. If the strict Uniforum mode is enable the +suffix @file{.mo} is added to the file name if it is not already +present. + +We find this behaviour of Sun's implementation rather silly and so by +default this mode is @emph{not} selected. + +@item -v +@itemx --verbose +Detect and diagnose input file anomalies which might represent +translation errors. The @code{msgid} and @code{msgstr} strings are +studied and compared. It is considered abnormal that one string +starts or ends with a newline while the other does not. + +Also, if the string represents a format sring used in a +@code{printf}-like function both strings should have the same number of +@samp{%} format specifiers, with matching types. If the flag +@code{c-format} or @code{possible-c-format} appears in the special +comment @key{#,} for this entry a check is performed. For example, the +check will diagnose using @samp{%.*s} against @samp{%s}, or @samp{%d} +against @samp{%s}, or @samp{%d} against @samp{%x}. It can even handle +positional parameters. + +Normally the @code{xgettext} program automatically decides whether a +string is a format string or not. This algorithm is not perfect, +though. It might regard a string as a format string though it is not +used in a @code{printf}-like function and so @code{msgfmt} might report +errors where there are none. Or the other way round: a string is not +regarded as a format string but it is used in a @code{printf}-like +function. + +So solve this problem the programmer can dictate the decision to the +@code{xgettext} program (@pxref{c-format}). The translator should not +consider removing the flag from the @key{#,} line. This "fix" would be +reversed again as soon as @code{msgmerge} is called the next time. + +@item -V +@itemx --version +Output version information and exit. + +@end table + +If input file is @samp{-}, standard input is read. If output file +is @samp{-}, output is written to standard output. + +@node MO Files, , msgfmt Invocation, Binaries +@section The Format of GNU MO Files + +The format of the generated MO files is best described by a picture, +which appears below. + +The first two words serve the identification of the file. The magic +number will always signal GNU MO files. The number is stored in the +byte order of the generating machine, so the magic number really is +two numbers: @code{0x950412de} and @code{0xde120495}. The second +word describes the current revision of the file format. For now the +revision is 0. This might change in future versions, and ensures +that the readers of MO files can distinguish new formats from old +ones, so that both can be handled correctly. The version is kept +separate from the magic number, instead of using different magic +numbers for different formats, mainly because @file{/etc/magic} is +not updated often. It might be better to have magic separated from +internal format version identification. + +Follow a number of pointers to later tables in the file, allowing +for the extension of the prefix part of MO files without having to +recompile programs reading them. This might become useful for later +inserting a few flag bits, indication about the charset used, new +tables, or other things. + +Then, at offset @var{O} and offset @var{T} in the picture, two tables +of string descriptors can be found. In both tables, each string +descriptor uses two 32 bits integers, one for the string length, +another for the offset of the string in the MO file, counting in bytes +from the start of the file. The first table contains descriptors +for the original strings, and is sorted so the original strings +are in increasing lexicographical order. The second table contains +descriptors for the translated strings, and is parallel to the first +table: to find the corresponding translation one has to access the +array slot in the second array with the same index. + +Having the original strings sorted enables the use of simple binary +search, for when the MO file does not contain an hashing table, or +for when it is not practical to use the hashing table provided in +the MO file. This also has another advantage, as the empty string +in a PO file GNU @code{gettext} is usually @emph{translated} into +some system information attached to that particular MO file, and the +empty string necessarily becomes the first in both the original and +translated tables, making the system information very easy to find. + +The size @var{S} of the hash table can be zero. In this case, the +hash table itself is not contained in the MO file. Some people might +prefer this because a precomputed hashing table takes disk space, and +does not win @emph{that} much speed. The hash table contains indices +to the sorted array of strings in the MO file. Conflict resolution is +done by double hashing. The precise hashing algorithm used is fairly +dependent of GNU @code{gettext} code, and is not documented here. + +As for the strings themselves, they follow the hash file, and each +is terminated with a @key{NUL}, and this @key{NUL} is not counted in +the length which appears in the string descriptor. The @code{msgfmt} +program has an option selecting the alignment for MO file strings. +With this option, each string is separately aligned so it starts at +an offset which is a multiple of the alignment value. On some RISC +machines, a correct alignment will speed things up. + +Nothing prevents a MO file from having embedded @key{NUL}s in strings. +However, the program interface currently used already presumes +that strings are @key{NUL} terminated, so embedded @key{NUL}s are +somewhat useless. But MO file format is general enough so other +interfaces would be later possible, if for example, we ever want to +implement wide characters right in MO files, where @key{NUL} bytes may +accidently appear. + +This particular issue has been strongly debated in the GNU +@code{gettext} development forum, and it is expectable that MO file +format will evolve or change over time. It is even possible that many +formats may later be supported concurrently. But surely, we have to +start somewhere, and the MO file format described here is a good start. +Nothing is cast in concrete, and the format may later evolve fairly +easily, so we should feel comfortable with the current approach. + +@example +@group + byte + +------------------------------------------+ + 0 | magic number = 0x950412de | + | | + 4 | file format revision = 0 | + | | + 8 | number of strings | == N + | | + 12 | offset of table with original strings | == O + | | + 16 | offset of table with translation strings | == T + | | + 20 | size of hashing table | == S + | | + 24 | offset of hashing table | == H + | | + . . + . (possibly more entries later) . + . . + | | + O | length & offset 0th string ----------------. + O + 8 | length & offset 1st string ------------------. + ... ... | | +O + ((N-1)*8)| length & offset (N-1)th string | | | + | | | | + T | length & offset 0th translation ---------------. + T + 8 | length & offset 1st translation -----------------. + ... ... | | | | +T + ((N-1)*8)| length & offset (N-1)th translation | | | | | + | | | | | | + H | start hash table | | | | | + ... ... | | | | + H + S * 4 | end hash table | | | | | + | | | | | | + | NUL terminated 0th string <----------------' | | | + | | | | | + | NUL terminated 1st string <------------------' | | + | | | | + ... ... | | + | | | | + | NUL terminated 0th translation <---------------' | + | | | + | NUL terminated 1st translation <-----------------' + | | + ... ... + | | + +------------------------------------------+ +@end group +@end example + +@node Users, Programmers, Binaries, Top +@chapter The User's View + +When GNU @code{gettext} will truly have reached is goal, average users +should feel some kind of astonished pleasure, seeing the effect of +that strange kind of magic that just makes their own native language +appear everywhere on their screens. As for naive users, they would +ideally have no special pleasure about it, merely taking their own +language for @emph{granted}, and becoming rather unhappy otherwise. + +So, let's try to describe here how we would like the magic to operate, +as we want the users' view to be the simplest, among all ways one +could look at GNU @code{gettext}. All other software engineers: +programmers, translators, maintainers, should work together in such a +way that the magic becomes possible. This is a long and progressive +undertaking, and information is available about the progress of the +Translation Project. + +When a package is distributed, there are two kind of users: +@dfn{installers} who fetch the distribution, unpack it, configure +it, compile it and install it for themselves or others to use; and +@dfn{end users} that call programs of the package, once these have +been installed at their site. GNU @code{gettext} is offering magic +for both installers and end users. + +@menu +* Matrix:: The Current @file{ABOUT-NLS} Matrix +* Installers:: Magic for Installers +* End Users:: Magic for End Users +@end menu + +@node Matrix, Installers, Users, Users +@section The Current @file{ABOUT-NLS} Matrix + +Languages are not equally supported in all packages using GNU +@code{gettext}. To know if some package uses GNU @code{gettext}, one +may check the distribution for the @file{ABOUT-NLS} information file, for +some @file{@var{ll}.po} files, often kept together into some @file{po/} +directory, or for an @file{intl/} directory. Internationalized packages +have usually many @file{@var{ll}.po} files, where @var{ll} represents +the language. @ref{End Users} for a complete description of the format +for @var{ll}. + +More generally, a matrix is available for showing the current state +of the Translation Project, listing which packages are prepared for +multi-lingual messages, and which languages is supported by each. +Because this information changes often, this matrix is not kept within +this GNU @code{gettext} manual. This information is often found in +file @file{ABOUT-NLS} from various distributions, but is also as old as +the distribution itself. A recent copy of this @file{ABOUT-NLS} file, +containing up-to-date information, should generally be found on the +Translation Project sites, and also on most GNU archive sites. + +@node Installers, End Users, Matrix, Users +@section Magic for Installers + +By default, packages fully using GNU @code{gettext}, internally, +are installed in such a way that they to allow translation of +messages. At @emph{configuration} time, those packages should +automatically detect whether the underlying host system provides usable +@code{catgets} or @code{gettext} functions. If neither is present, +the GNU @code{gettext} library should be automatically prepared +and used. Installers may use special options at configuration +time for changing this behavior. The command @samp{./configure +--with-included-gettext} bypasses system @code{catgets} or @code{gettext} to +use GNU @code{gettext} instead, while @samp{./configure --disable-nls} +produces program totally unable to translate messages. + +Internationalized packages have usually many @file{@var{ll}.po} +files. Unless +translations are disabled, all those available are installed together +with the package. However, the environment variable @code{LINGUAS} +may be set, prior to configuration, to limit the installed set. +@code{LINGUAS} should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +@node End Users, , Installers, Users +@section Magic for End Users + +We consider here those packages using GNU @code{gettext} internally, +and for which the installers did not disable translation at +@emph{configure} time. Then, users only have to set the @code{LANG} +environment variable to the appropriate @samp{@var{ll}} prior to +using the programs in the package. @xref{Matrix}. For example, +let's presume a German site. At the shell prompt, users merely have to +execute @w{@samp{setenv LANG de}} (in @code{csh}) or @w{@samp{export +LANG; LANG=de}} (in @code{sh}). They could even do this from their +@file{.login} or @file{.profile} file. + +@node Programmers, Translators, Users, Top +@chapter The Programmer's View + +@c FIXME: Reorganize whole chapter. + +One aim of the current message catalog implementation provided by +GNU @code{gettext} was to use the systems message catalog handling, if the +installer wishes to do so. So we perhaps should first take a look at +the solutions we know about. The people in the POSIX committee does not +manage to agree on one of the semi-official standards which we'll +describe below. In fact they couldn't agree on anything, so nothing +decide only to include an example of an interface. The major Unix vendors +are split in the usage of the two most important specifications: X/Opens +catgets vs. Uniforums gettext interface. We'll describe them both and +later explain our solution of this dilemma. + +@menu +* catgets:: About @code{catgets} +* gettext:: About @code{gettext} +* Comparison:: Comparing the two interfaces +* Using libintl.a:: Using libintl.a in own programs +* gettext grok:: Being a @code{gettext} grok +* Temp Programmers:: Temporary Notes for the Programmers Chapter +@end menu + +@node catgets, gettext, Programmers, Programmers +@section About @code{catgets} + +The @code{catgets} implementation is defined in the X/Open Portability +Guide, Volume 3, XSI Supplementary Definitions, Chapter 5. But the +process of creating this standard seemed to be too slow for some of +the Unix vendors so they created their implementations on preliminary +versions of the standard. Of course this leads again to problems while +writing platform independent programs: even the usage of @code{catgets} +does not guarantee a unique interface. + +Another, personal comment on this that only a bunch of committee members +could have made this interface. They never really tried to program +using this interface. It is a fast, memory-saving implementation, an +user can happily live with it. But programmers hate it (at least me and +some others do@dots{}) + +But we must not forget one point: after all the trouble with transfering +the rights on Unix(tm) they at last came to X/Open, the very same who +published this specifications. This leads me to making the prediction +that this interface will be in future Unix standards (e.g. Spec1170) and +therefore part of all Unix implementation (implementations, which are +@emph{allowed} to wear this name). + +@menu +* Interface to catgets:: The interface +* Problems with catgets:: Problems with the @code{catgets} interface?! +@end menu + +@node Interface to catgets, Problems with catgets, catgets, catgets +@subsection The Interface + +The interface to the @code{catgets} implementation consists of three +functions which correspond to those used in file access: @code{catopen} +to open the catalog for using, @code{catgets} for accessing the message +tables, and @code{catclose} for closing after work is done. Prototypes +for the functions and the needed definitions are in the +@code{<nl_types.h>} header file. + +@code{catopen} is used like in this: + +@example +nl_catd catd = catopen ("catalog_name", 0); +@end example + +The function takes as the argument the name of the catalog. This usual +refers to the name of the program or the package. The second parameter +is not further specified in the standard. I don't even know whether it +is implemented consistently among various systems. So the common advice +is to use @code{0} as the value. The return value is a handle to the +message catalog, equivalent to handles to file returned by @code{open}. + +This handle is of course used in the @code{catgets} function which can +be used like this: + +@example +char *translation = catgets (catd, set_no, msg_id, "original string"); +@end example + +The first parameter is this catalog descriptor. The second parameter +specifies the set of messages in this catalog, in which the message +described by @code{msg_id} is obtained. @code{catgets} therefore uses a +three-stage addressing: + +@display +catalog name @result{} set number @result{} message ID @result{} translation +@end display + +@c Anybody else loving Haskell??? :-) -- Uli + +The fourth argument is not used to address the translation. It is given +as a default value in case when one of the addressing stages fail. One +important thing to remember is that although the return type of catgets +is @code{char *} the resulting string @emph{must not} be changed. It +should better @code{const char *}, but the standard is published in +1988, one year before ANSI C. + +@noindent +The last of these function functions is used and behaves as expected: + +@example +catclose (catd); +@end example + +After this no @code{catgets} call using the descriptor is legal anymore. + +@node Problems with catgets, , Interface to catgets, catgets +@subsection Problems with the @code{catgets} Interface?! + +Now that this descriptions seemed to be really easy where are the +problem we speak of. In fact the interface could be used in a +reasonable way, but constructing the message catalogs is a pain. The +reason for this lies in the third argument of @code{catgets}: the unique +message ID. This has to be a numeric value for all messages in a single +set. Perhaps you could imagine the problems keeping such list while +changing the source code. Add a new message here, remove one there. Of +course there have been developed a lot of tools helping to organize this +chaos but one as the other fails in one aspect or the other. We don't +want to say that the other approach has no problems but they are far +more easily to manage. + +@node gettext, Comparison, catgets, Programmers +@section About @code{gettext} + +The definition of the @code{gettext} interface comes from a Uniforum +proposal and it is followed by at least one major Unix vendor +(Sun) in its last developments. It is not specified in any official +standard, though. + +The main points about this solution is that it does not follow the +method of normal file handling (open-use-close) and that it does not +burden the programmer so many task, especially the unique key handling. +Of course here is also a unique key needed, but this key is the message +itself (how long or short it is). See @ref{Comparison} for a more +detailed comparison of the two methods. + +The following section contains a rather detailed description of the +interface. We make it that detailed because this is the interface +we chose for the GNU @code{gettext} Library. Programmers interested +in using this library will be interested in this description. + +@menu +* Interface to gettext:: The interface +* Ambiguities:: Solving ambiguities +* Locating Catalogs:: Locating message catalog files +* Optimized gettext:: Optimization of the *gettext functions +@end menu + +@node Interface to gettext, Ambiguities, gettext, gettext +@subsection The Interface + +The minimal functionality an interface must have is a) to select a +domain the strings are coming from (a single domain for all programs is +not reasonable because its construction and maintenance is difficult, +perhaps impossible) and b) to access a string in a selected domain. + +This is principally the description of the @code{gettext} interface. It +has an global domain which unqualified usages reference. Of course this +domain is selectable by the user. + +@example +char *textdomain (const char *domain_name); +@end example + +This provides the possibility to change or query the current status of +the current global domain of the @code{LC_MESSAGE} category. The +argument is a null-terminated string, whose characters must be legal in +the use in filenames. If the @var{domain_name} argument is @code{NULL}, +the function return the current value. If no value has been set +before, the name of the default domain is returned: @emph{messages}. +Please note that although the return value of @code{textdomain} is of +type @code{char *} no changing is allowed. It is also important to know +that no checks of the availability are made. If the name is not +available you will see this by the fact that no translations are provided. + +@noindent +To use a domain set by @code{textdomain} the function + +@example +char *gettext (const char *msgid); +@end example + +is to be used. This is the simplest reasonable form one can imagine. +The translation of the string @var{msgid} is returned if it is available +in the current domain. If not available the argument itself is +returned. If the argument is @code{NULL} the result is undefined. + +One things which should come into mind is that no explicit dependency to +the used domain is given. The current value of the domain for the +@code{LC_MESSAGES} locale is used. If this changes between two +executions of the same @code{gettext} call in the program, both calls +reference a different message catalog. + +For the easiest case, which is normally used in internationalized +packages, once at the beginning of execution a call to @code{textdomain} +is issued, setting the domain to a unique name, normally the package +name. In the following code all strings which have to be translated are +filtered through the gettext function. That's all, the package speaks +your language. + +@node Ambiguities, Locating Catalogs, Interface to gettext, gettext +@subsection Solving Ambiguities + +While this single name domain work good for most applications there +might be the need to get translations from more than one domain. Of +course one could switch between different domains with calls to +@code{textdomain}, but this is really not convenient nor is it fast. A +possible situation could be one case discussing while this writing: all +error messages of functions in the set of common used functions should +go into a separate domain @code{error}. By this mean we would only need +to translate them once. + +@noindent +For this reasons there are two more functions to retrieve strings: + +@example +char *dgettext (const char *domain_name, const char *msgid); +char *dcgettext (const char *domain_name, const char *msgid, + int category); +@end example + +Both take an additional argument at the first place, which corresponds +to the argument of @code{textdomain}. The third argument of +@code{dcgettext} allows to use another locale but @code{LC_MESSAGES}. +But I really don't know where this can be useful. If the +@var{domain_name} is @code{NULL} or @var{category} has an value beside +the known ones, the result is undefined. It should also be noted that +this function is not part of the second known implementation of this +function family, the one found in Solaris. + +A second ambiguity can arise by the fact, that perhaps more than one +domain has the same name. This can be solved by specifying where the +needed message catalog files can be found. + +@example +char *bindtextdomain (const char *domain_name, + const char *dir_name); +@end example + +Calling this function binds the given domain to a file in the specified +directory (how this file is determined follows below). Especially a +file in the systems default place is not favored against the specified +file anymore (as it would be by solely using @code{textdomain}). A +@code{NULL} pointer for the @var{dir_name} parameter returns the binding +associated with @var{domain_name}. If @var{domain_name} itself is +@code{NULL} nothing happens and a @code{NULL} pointer is returned. Here +again as for all the other functions is true that none of the return +value must be changed! + +It is important to remember that relative path names for the +@var{dir_name} parameter can be trouble. Since the path is always +computed relative to the current directory different results will be +achieved when the program executes a @code{chdir} command. Relative +paths should always be avoided to avoid dependencies and +unreliabilities. + +@node Locating Catalogs, Optimized gettext, Ambiguities, gettext +@subsection Locating Message Catalog Files + +Because many different languages for many different packages have to be +stored we need some way to add these information to file message catalog +files. The way usually used in Unix environments is have this encoding +in the file name. This is also done here. The directory name given in +@code{bindtextdomain}s second argument (or the default directory), +followed by the value and name of the locale and the domain name are +concatenated: + +@example +@var{dir_name}/@var{locale}/LC_@var{category}/@var{domain_name}.mo +@end example + +The default value for @var{dir_name} is system specific. For the GNU +library, and for packages adhering to its conventions, it's: +@example +/usr/local/share/locale +@end example + +@noindent +@var{locale} is the value of the locale whose name is this +@code{LC_@var{category}}. For @code{gettext} and @code{dgettext} this +locale is always @code{LC_MESSAGES}. @code{dcgettext} specifies the +locale by the third argument.@footnote{Some +system, eg Ultrix, don't have @code{LC_MESSAGES}. Here we use a more or +less arbitrary value for it.} @footnote{When the system does not support +@code{setlocale} its behavior in setting the locale values is simulated +by looking at the environment variables.} + +@node Optimized gettext, , Locating Catalogs, gettext +@subsection Optimization of the *gettext functions + +At this point of the discussion we should talk about an advantage of the +GNU @code{gettext} implementation. Some readers might have pointed out +that an internationalized program might have a poor performance if some +string has to be translated in an inner loop. While this is unavoidable +when the string varies from one run of the loop to the other it is +simply a waste of time when the string is always the same. Take the +following example: + +@example +@group +@{ + while (@dots{}) + @{ + puts (gettext ("Hello world")); + @} +@} +@end group +@end example + +@noindent +When the locale selection does not change between two runs the resulting +string is always the same. One way to use this is: + +@example +@group +@{ + str = gettext ("Hello world"); + while (@dots{}) + @{ + puts (str); + @} +@} +@end group +@end example + +@noindent +But this solution is not usable in all situation (e.g. when the locale +selection changes) nor is it good readable. + +The GNU C compiler, version 2.7 and above, provide another solution for +this. To describe this we show here some lines of the +@file{intl/libgettext.h} file. For an explanation of the expression +command block see @ref{Statement Exprs, , Statements and Declarations in +Expressions, gcc, The GNU CC Manual}. + +@example +@group +# if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ >= 7 +extern int _nl_msg_cat_cntr; +# define dcgettext(domainname, msgid, category) \ + (__extension__ \ + (@{ \ + char *result; \ + if (__builtin_constant_p (msgid)) \ + @{ \ + static char *__translation__; \ + static int __catalog_counter__; \ + if (! __translation__ \ + || __catalog_counter__ != _nl_msg_cat_cntr) \ + @{ \ + __translation__ = \ + dcgettext__ ((domainname), (msgid), (category)); \ + __catalog_counter__ = _nl_msg_cat_cntr; \ + @} \ + result = __translation__; \ + @} \ + else \ + result = dcgettext__ ((domainname), (msgid), (category)); \ + result; \ + @})) +# endif +@end group +@end example + +The interesting thing here is the @code{__builtin_constant_p} predicate. +This is evaluated at compile time and so optimization can take place +immediately. Here two cases are distinguished: the argument to +@code{gettext} is not a constant value in which case simply the function +@code{dcgettext__} is called, the real implementation of the +@code{dcgettext} function. + +If the string argument @emph{is} constant we can reuse the once gained +translation when the locale selection has not changed. This is exactly +what is done here. The @code{_nl_msg_cat_cntr} variable is defined in +the @file{loadmsgcat.c} which is available in @file{libintl.a} and is +changed whenever a new message catalog is loaded. + +@node Comparison, Using libintl.a, gettext, Programmers +@section Comparing the Two Interfaces + +@c FIXME: arguments to catgets vs. gettext +@c Partly done 950718 -- drepper + +The following discussion is perhaps a little bit colored. As said +above we implemented GNU @code{gettext} following the Uniforum +proposal and this surely has its reasons. But it should show how we +came to this decision. + +First we take a look at the developing process. When we write an +application using NLS provided by @code{gettext} we proceed as always. +Only when we come to a string which might be seen by the users and thus +has to be translated we use @code{gettext("@dots{}")} instead of +@code{"@dots{}"}. At the beginning of each source file (or in a central +header file) we define + +@example +#define gettext(String) (String) +@end example + +Even this definition can be avoided when the system supports the +@code{gettext} function in its C library. When we compile this code the +result is the same as if no NLS code is used. When you take a look at +the GNU @code{gettext} code you will see that we use @code{_("@dots{}")} +instead of @code{gettext("@dots{}")}. This reduces the number of +additional characters per translatable string to @emph{3} (in words: +three). + +When now a production version of the program is needed we simply replace +the definition + +@example +#define _(String) (String) +@end example + +@noindent +by + +@example +#include <libintl.h> +#define _(String) gettext (String) +@end example + +@noindent +Additionally we run the program @file{xgettext} on all source code file +which contain translatable strings and that's it: we have a running +program which does not depend on translations to be available, but which +can use any that becomes available. + +The same procedure can be done for the @code{gettext_noop} invocations +(@pxref{Special cases}). First you can define @code{gettext_noop} to a +no-op macro and later use the definition from @file{libintl.h}. Because +this name is not used in Suns implementation of @file{libintl.h}, +you should consider the following code for your project: + +@example +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +# define N_(String) (String) +#endif +@end example + +@code{N_} is a short form similar to @code{_}. The @file{Makefile} in +the @file{po/} directory of GNU @code{gettext} knows by default both of the +mentioned short forms so you are invited to follow this proposal for +your own ease. + +Now to @code{catgets}. The main problem is the work for the +programmer. Every time he comes to a translatable string he has to +define a number (or a symbolic constant) which has also be defined in +the message catalog file. He also has to take care for duplicate +entries, duplicate message IDs etc. If he wants to have the same +quality in the message catalog as the GNU @code{gettext} program +provides he also has to put the descriptive comments for the strings and +the location in all source code files in the message catalog. This is +nearly a Mission: Impossible. + +But there are also some points people might call advantages speaking for +@code{catgets}. If you have a single word in a string and this string +is used in different contexts it is likely that in one or the other +language the word has different translations. Example: + +@example +printf ("%s: %d", gettext ("number"), number_of_errors) + +printf ("you should see %d %s", number_count, + number_count == 1 ? gettext ("number") : gettext ("numbers")) +@end example + +Here we have to translate two times the string @code{"number"}. Even +if you do not speak a language beside English it might be possible to +recognize that the two words have a different meaning. In German the +first appearance has to be translated to @code{"Anzahl"} and the second +to @code{"Zahl"}. + +Now you can say that this example is really esoteric. And you are +right! This is exactly how we felt about this problem and decide that +it does not weight that much. The solution for the above problem could +be very easy: + +@example +printf ("%s %d", gettext ("number:"), number_of_errors) + +printf (number_count == 1 ? gettext ("you should see %d number") + : gettext ("you should see %d numbers"), + number_count) +@end example + +We believe that we can solve all conflicts with this method. If it is +difficult one can also consider changing one of the conflicting string a +little bit. But it is not impossible to overcome. + +@c Should this be here? +Translator note: It is perhaps appropriate here to tell those English +speaking programmers that the plural form of a noun cannot be formed by +appending a single `s'. Most other languages use different methods. +Even the above form is not general enough to cope with all languages. +Rafal Maszkowski <rzm@@mat.uni.torun.pl> reports: + +@quotation +In Polish we use e.g. plik (file) this way: +@example +1 plik +2,3,4 pliki +5-21 pliko'w +22-24 pliki +25-31 pliko'w +@end example +and so on (o' means 8859-2 oacute which should be rather okreska, +similar to aogonek). +@end quotation + +A workable approach might be to consider methods like the one used for +@code{LC_TIME} in the POSIX.2 standard. The value of the +@code{alt_digits} field can be up to 100 strings which represent the +numbers 1 to 100. Using this in a situation of an internationalized +program means that an array of translatable strings should be indexed by +the number which should represent. A small example: + +@example +@group +void +print_month_info (int month) +@{ + const char *month_pos[12] = + @{ N_("first"), N_("second"), N_("third"), N_("fourth"), + N_("fifth"), N_("sixth"), N_("seventh"), N_("eighth"), + N_("ninth"), N_("tenth"), N_("eleventh"), N_("twelfth") @}; + printf (_("%s is the %s month\n"), nl_langinfo (MON_1 + month), + _(month_pos[month])); +@} +@end group +@end example + +@noindent +It should be obvious that this method is only reasonable for small +ranges of numbers. + +@c catgets allows same original entry to have different translations + +@node Using libintl.a, gettext grok, Comparison, Programmers +@section Using libintl.a in own programs + +Starting with version 0.9.4 the library @code{libintl.h} should be +self-contained. I.e., you can use it in your own programs without +providing additional functions. The @file{Makefile} will put the header +and the library in directories selected using the @code{$(prefix)}. + +One exception of the above is found on HP-UX systems. Here the C library +does not contain the @code{alloca} function (and the HP compiler does +not generate it inlined). But it is not intended to rewrite the whole +library just because of this dumb system. Instead include the +@code{alloca} function in all package you use the @code{libintl.a} in. + +@node gettext grok, Temp Programmers, Using libintl.a, Programmers +@section Being a @code{gettext} grok + +To fully exploit the functionality of the GNU @code{gettext} library it +is surely helpful to read the source code. But for those who don't want +to spend that much time in reading the (sometimes complicated) code here +is a list comments: + +@itemize @bullet +@item Changing the language at runtime + +For interactive programs it might be useful to offer a selection of the +used language at runtime. To understand how to do this one need to know +how the used language is determined while executing the @code{gettext} +function. The method which is presented here only works correctly +with the GNU implementation of the @code{gettext} functions. It is not +possible with underlying @code{catgets} functions or @code{gettext} +functions from the systems C library. The exception is of course the +GNU C Library which uses the GNU @code{gettext} Library for message handling. + +In the function @code{dcgettext} at every call the current setting of +the highest priority environment variable is determined and used. +Highest priority means here the following list with decreasing +priority: + +@enumerate +@item @code{LANGUAGE} +@item @code{LC_ALL} +@item @code{LC_xxx}, according to selected locale +@item @code{LANG} +@end enumerate + +Afterwards the path is constructed using the found value and the +translation file is loaded if available. + +What is now when the value for, say, @code{LANGUAGE} changes. According +to the process explained above the new value of this variable is found +as soon as the @code{dcgettext} function is called. But this also means +the (perhaps) different message catalog file is loaded. In other +words: the used language is changed. + +But there is one little hook. The code for gcc-2.7.0 and up provides +some optimization. This optimization normally prevents the calling of +the @code{dcgettext} function as long as no new catalog is loaded. But +if @code{dcgettext} is not called the program also cannot find the +@code{LANGUAGE} variable be changed (@pxref{Optimized gettext}). A +solution for this is very easy. Include the following code in the +language switching function. + +@example + /* Change language. */ + setenv ("LANGUAGE", "fr", 1); + + /* Make change known. */ + @{ + extern int _nl_msg_cat_cntr; + ++_nl_msg_cat_cntr; + @} +@end example + +The variable @code{_nl_msg_cat_cntr} is defined in @file{loadmsgcat.c}. +The programmer will find himself in need for a construct like this only +when developing programs which do run longer and provide the user to +select the language at runtime. Non-interactive programs (like all +these little Unix tools) should never need this. + +@end itemize + +@node Temp Programmers, , gettext grok, Programmers +@section Temporary Notes for the Programmers Chapter + +@menu +* Temp Implementations:: Temporary - Two Possible Implementations +* Temp catgets:: Temporary - About @code{catgets} +* Temp WSI:: Temporary - Why a single implementation +* Temp Notes:: Temporary - Notes +@end menu + +@node Temp Implementations, Temp catgets, Temp Programmers, Temp Programmers +@subsection Temporary - Two Possible Implementations + +There are two competing methods for language independent messages: +the X/Open @code{catgets} method, and the Uniforum @code{gettext} +method. The @code{catgets} method indexes messages by integers; the +@code{gettext} method indexes them by their English translations. +The @code{catgets} method has been around longer and is supported +by more vendors. The @code{gettext} method is supported by Sun, +and it has been heard that the COSE multi-vendor initiative is +supporting it. Neither method is a POSIX standard; the POSIX.1 +committee had a lot of disagreement in this area. + +Neither one is in the POSIX standard. There was much disagreement +in the POSIX.1 committee about using the @code{gettext} routines +vs. @code{catgets} (XPG). In the end the committee couldn't +agree on anything, so no messaging system was included as part +of the standard. I believe the informative annex of the standard +includes the XPG3 messaging interfaces, ``@dots{}as an example of +a messaging system that has been implemented@dots{}'' + +They were very careful not to say anywhere that you should use one +set of interfaces over the other. For more on this topic please +see the Programming for Internationalization FAQ. + +@node Temp catgets, Temp WSI, Temp Implementations, Temp Programmers +@subsection Temporary - About @code{catgets} + +There have been a few discussions of late on the use of +@code{catgets} as a base. I think it important to present both +sides of the argument and hence am opting to play devil's advocate +for a little bit. + +I'll not deny the fact that @code{catgets} could have been designed +a lot better. It currently has quite a number of limitations and +these have already been pointed out. + +However there is a great deal to be said for consistency and +standardization. A common recurring problem when writing Unix +software is the myriad portability problems across Unix platforms. +It seems as if every Unix vendor had a look at the operating system +and found parts they could improve upon. Undoubtedly, these +modifications are probably innovative and solve real problems. +However, software developers have a hard time keeping up with all +these changes across so many platforms. + +And this has prompted the Unix vendors to begin to standardize their +systems. Hence the impetus for Spec1170. Every major Unix vendor +has committed to supporting this standard and every Unix software +developer waits with glee the day they can write software to this +standard and simply recompile (without having to use autoconf) +across different platforms. + +As I understand it, Spec1170 is roughly based upon version 4 of the +X/Open Portability Guidelines (XPG4). Because @code{catgets} and +friends are defined in XPG4, I'm led to believe that @code{catgets} +is a part of Spec1170 and hence will become a standardized component +of all Unix systems. + +@node Temp WSI, Temp Notes, Temp catgets, Temp Programmers +@subsection Temporary - Why a single implementation + +Now it seems kind of wasteful to me to have two different systems +installed for accessing message catalogs. If we do want to remedy +@code{catgets} deficiencies why don't we try to expand @code{catgets} +(in a compatible manner) rather than implement an entirely new system. +Otherwise, we'll end up with two message catalog access systems installed +with an operating system - one set of routines for packages using GNU +@code{gettext} for their internationalization, and another set of routines +(catgets) for all other software. Bloated? + +Supposing another catalog access system is implemented. Which do +we recommend? At least for Linux, we need to attract as many +software developers as possible. Hence we need to make it as easy +for them to port their software as possible. Which means supporting +@code{catgets}. We will be implementing the @code{glocale} code +within our @code{libc}, but does this mean we also have to incorporate +another message catalog access scheme within our @code{libc} as well? +And what about people who are going to be using the @code{glocale} ++ non-@code{catgets} routines. When they port their software to +other platforms, they're now going to have to include the front-end +(@code{glocale}) code plus the back-end code (the non-@code{catgets} +access routines) with their software instead of just including the +@code{glocale} code with their software. + +Message catalog support is however only the tip of the iceberg. +What about the data for the other locale categories. They also have +a number of deficiencies. Are we going to abandon them as well and +develop another duplicate set of routines (should @code{glocale} +expand beyond message catalog support)? + +Like many parts of Unix that can be improved upon, we're stuck with balancing +compatibility with the past with useful improvements and innovations for +the future. + +@node Temp Notes, , Temp WSI, Temp Programmers +@subsection Temporary - Notes + +X/Open agreed very late on the standard form so that many +implementations differ from the final form. Both of my system (old +Linux catgets and Ultrix-4) have a strange variation. + +OK. After incorporating the last changes I have to spend some time on +making the GNU/Linux @code{libc} @code{gettext} functions. So in future +Solaris is not the only system having @code{gettext}. + +@node Translators, Maintainers, Programmers, Top +@chapter The Translator's View + +@c FIXME: Reorganize whole chapter. + +@menu +* Trans Intro 0:: Introduction 0 +* Trans Intro 1:: Introduction 1 +* Discussions:: Discussions +* Organization:: Organization +* Information Flow:: Information Flow +@end menu + +@node Trans Intro 0, Trans Intro 1, Translators, Translators +@section Introduction 0 + +Free software is going international! The Translation Project is a way +to get maintainers, translators and users all together, so free software +will gradually become able to speak many native languages. + +The GNU @code{gettext} tool set contains @emph{everything} maintainers +need for internationalizing their packages for messages. It also +contains quite useful tools for helping translators at localizing +messages to their native language, once a package has already been +internationalized. + +To achieve the Translation Project, we need many interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +If you'd like to volunteer to @emph{work} at translating messages, +please send mail to your translating team. + +Each team has its own mailing list, courtesy of Linux +International. You may reach your translating team at the address +@file{@var{ll}@@li.org}, replacing @var{ll} by the two-letter @w{ISO 639} +code for your language. Language codes are @emph{not} the same as +country codes given in @w{ISO 3166}. The following translating teams +exist: + +@quotation +Chinese @code{zh}, Czech @code{cs}, Danish @code{da}, Dutch @code{nl}, +Esperanto @code{eo}, Finnish @code{fi}, French @code{fr}, Irish +@code{ga}, German @code{de}, Greek @code{el}, Italian @code{it}, +Japanese @code{ja}, Indonesian @code{in}, Norwegian @code{no}, Polish +@code{pl}, Portuguese @code{pt}, Russian @code{ru}, Spanish @code{es}, +Swedish @code{sv} and Turkish @code{tr}. +@end quotation + +@noindent +For example, you may reach the Chinese translating team by writing to +@file{zh@@li.org}. When you become a member of the translating team +for your own language, you may subscribe to its list. For example, +Swedish people can send a message to @w{@file{sv-request@@li.org}}, +having this message body: + +@example +subscribe +@end example + +Keep in mind that team members should be interested in @emph{working} +at translations, or at solving translational difficulties, rather than +merely lurking around. If your team does not exist yet and you want to +start one, please write to @w{@file{translation@@iro.umontreal.ca}}; +you will then reach the coordinator for all translator teams. + +A handful of GNU packages have already been adapted and provided +with message translations for several languages. Translation +teams have begun to organize, using these packages as a starting +point. But there are many more packages and many languages for +which we have no volunteer translators. If you would like to +volunteer to work at translating messages, please send mail to +@file{translation@@iro.umontreal.ca} indicating what language(s) +you can work on. + +@node Trans Intro 1, Discussions, Trans Intro 0, Translators +@section Introduction 1 + +This is now official, GNU is going international! Here is the +announcement submitted for the January 1995 GNU Bulletin: + +@quotation +A handful of GNU packages have already been adapted and provided +with message translations for several languages. Translation +teams have begun to organize, using these packages as a starting +point. But there are many more packages and many languages +for which we have no volunteer translators. If you'd like to +volunteer to work at translating messages, please send mail to +@samp{translation@@iro.umontreal.ca} indicating what language(s) +you can work on. +@end quotation + +This document should answer many questions for those who are curious about +the process or would like to contribute. Please at least skim over it, +hoping to cut down a little of the high volume of e-mail generated by this +collective effort towards internationalization of free software. + +Most free programming which is widely shared is done in English, and +currently, English is used as the main communicating language between +national communities collaborating to free software. This very document +is written in English. This will not change in the foreseeable future. + +However, there is a strong appetite from national communities for +having more software able to write using national language and habits, +and there is an on-going effort to modify free software in such a way +that it becomes able to do so. The experiments driven so far raised +an enthusiastic response from pretesters, so we believe that +internationalization of free software is dedicated to succeed. + +For suggestion clarifications, additions or corrections to this +document, please e-mail to @file{translation@@iro.umontreal.ca}. + +@node Discussions, Organization, Trans Intro 1, Translators +@section Discussions + +Facing this internationalization effort, a few users expressed their +concerns. Some of these doubts are presented and discussed, here. + +@itemize @bullet +@item Smaller groups + +Some languages are not spoken by a very large number of people, so people +speaking them sometimes consider that there may not be all that much +demand such versions of free software packages. Moreover, many people +being @emph{into computers}, in some countries, generally seem to prefer +English versions of their software. + +On the other end, people might enjoy their own language a lot, and be +very motivated at providing to themselves the pleasure of having their +beloved free software speaking their mother tongue. They do themselves +a personal favor, and do not pay that much attention to the number of +people beneficiating of their work. + +@item Misinterpretation + +Other users are shy to push forward their own language, seeing in this +some kind of misplaced propaganda. Someone thought there must be some +users of the language over the networks pestering other people with it. + +But any spoken language is worth localization, because there are +people behind the language for whom the language is important and +dear to their hearts. + +@item Odd translations + +The biggest problem is to find the right translations so that +everybody can understand the messages. Translations are usually a +little odd. Some people get used to English, to the extent they may +find translations into their own language ``rather pushy, obnoxious +and sometimes even hilarious.'' As a French speaking man, I have +the experience of those instruction manuals for goods, so poorly +translated in French in Korea or Taiwan@dots{} + +The fact is that we sometimes have to create a kind of national +computer culture, and this is not easy without the collaboration of +many people liking their mother tongue. This is why translations are +better achieved by people knowing and loving their own language, and +ready to work together at improving the results they obtain. + +@item Dependencies over the GPL + +Some people wonder if using GNU @code{gettext} necessarily brings their package +under the protective wing of the GNU General Public License, when they +do not want to make their program free, or want other kinds of freedom. +The simplest answer is yes. + +The mere marking of localizable strings in a package, or conditional +inclusion of a few lines for initialization, is not really including +GPL'ed code. However, the localization routines themselves are under +the GPL and would bring the remainder of the package under the GPL +if they were distributed with it. So, I presume that, for those +for which this is a problem, it could be circumvented by letting to +the end installers the burden of assembling a package prepared for +localization, but not providing the localization routines themselves. + +@end itemize + +@node Organization, Information Flow, Discussions, Translators +@section Organization + +On a larger scale, the true solution would be to organize some kind of +fairly precise set up in which volunteers could participate. I gave +some thought to this idea lately, and realize there will be some +touchy points. I thought of writing to Richard Stallman to launch +such a project, but feel it might be good to shake out the ideas +between ourselves first. Most probably that Linux International has +some experience in the field already, or would like to orchestrate +the volunteer work, maybe. Food for thought, in any case! + +I guess we have to setup something early, somehow, that will help +many possible contributors of the same language to interlock and avoid +work duplication, and further be put in contact for solving together +problems particular to their tongue (in most languages, there are many +difficulties peculiar to translating technical English). My Swedish +contributor acknowledged these difficulties, and I'm well aware of +them for French. + +This is surely not a technical issue, but we should manage so the +effort of locale contributors be maximally useful, despite the national +team layer interface between contributors and maintainers. + +The Translation Project needs some setup for coordinating language +coordinators. Localizing evolving programs will surely +become a permanent and continuous activity in the free software community, +once well started. +The setup should be minimally completed and tested before GNU +@code{gettext} becomes an official reality. The e-mail address +@file{translation@@iro.umontreal.ca} has been setup for receiving +offers from volunteers and general e-mail on these topics. This address +reaches the Translation Project coordinator. + +@menu +* Central Coordination:: Central Coordination +* National Teams:: National Teams +* Mailing Lists:: Mailing Lists +@end menu + +@node Central Coordination, National Teams, Organization, Organization +@subsection Central Coordination + +I also think GNU will need sooner than it thinks, that someone setup +a way to organize and coordinate these groups. Some kind of group +of groups. My opinion is that it would be good that GNU delegates +this task to a small group of collaborating volunteers, shortly. +Perhaps in @file{gnu.announce} a list of this national committee's +can be published. + +My role as coordinator would simply be to refer to Ulrich any German +speaking volunteer interested to localization of free software packages, and +maybe helping national groups to initially organize, while maintaining +national registries for until national groups are ready to take over. +In fact, the coordinator should ease volunteers to get in contact with +one another for creating national teams, which should then select +one coordinator per language, or country (regionalized language). +If well done, the coordination should be useful without being an +overwhelming task, the time to put delegations in place. + +@node National Teams, Mailing Lists, Central Coordination, Organization +@subsection National Teams + +I suggest we look for volunteer coordinators/editors for individual +languages. These people will scan contributions of translation files +for various programs, for their own languages, and will ensure high +and uniform standards of diction. + +From my current experience with other people in these days, those who +provide localizations are very enthusiastic about the process, and are +more interested in the localization process than in the program they +localize, and want to do many programs, not just one. This seems +to confirm that having a coordinator/editor for each language is a +good idea. + +We need to choose someone who is good at writing clear and concise +prose in the language in question. That is hard---we can't check +it ourselves. So we need to ask a few people to judge each others' +writing and select the one who is best. + +I announce my prerelease to a few dozen people, and you would not +believe all the discussions it generated already. I shudder to think +what will happen when this will be launched, for true, officially, +world wide. Who am I to arbitrate between two Czekolsovak users +contradicting each other, for example? + +I assume that your German is not much better than my French so that +I would not be able to judge about these formulations. What I would +suggest is that for each language there is a group for people who +maintain the PO files and judge about changes. I suspect there will +be cultural differences between how such groups of people will behave. +Some will have relaxed ways, reach consensus easily, and have anyone +of the group relate to the maintainers, while others will fight to +death, organize heavy administrations up to national standards, and +use strict channels. + +The German team is putting out a good example. Right now, they are +maybe half a dozen people revising translations of each other and +discussing the linguistic issues. I do not even have all the names. +Ulrich Drepper is taking care of coordinating the German team. +He subscribed to all my pretest lists, so I do not even have to warn +him specifically of incoming releases. + +I'm sure, that is a good idea to get teams for each language working +on translations. That will make the translations better and more +consistent. + +@menu +* Sub-Cultures:: Sub-Cultures +* Organizational Ideas:: Organizational Ideas +@end menu + +@node Sub-Cultures, Organizational Ideas, National Teams, National Teams +@subsubsection Sub-Cultures + +Taking French for example, there are a few sub-cultures around computers +which developed diverging vocabularies. Picking volunteers here and +there without addressing this problem in an organized way, soon in the +project, might produce a distasteful mix of internationalized programs, +and possibly trigger endless quarrels among those who really care. + +Keeping some kind of unity in the way French localization of +internationalized programs is achieved is a difficult (and delicate) job. +Knowing the latin character of French people (:-), if we take this +the wrong way, we could end up nowhere, or spoil a lot of energies. +Maybe we should begin to address this problem seriously @emph{before} +GNU @code{gettext} become officially published. And I suspect that this +means soon! + +@node Organizational Ideas, , Sub-Cultures, National Teams +@subsubsection Organizational Ideas + +I expect the next big changes after the official release. Please note +that I use the German translation of the short GPL message. We need +to set a few good examples before the localization goes out for true +in the free software community. Here are a few points to discuss: + +@itemize @bullet +@item +Each group should have one FTP server (at least one master). + +@item +The files on the server should reflect the latest version (of +course!) and it should also contain a RCS directory with the +corresponding archives (I don't have this now). + +@item +There should also be a ChangeLog file (this is more useful than the +RCS archive but can be generated automatically from the later by +Emacs). + +@item +A @dfn{core group} should judge about questionable changes (for now +this group consists solely by me but I ask some others occasionally; +this also seems to work). + +@end itemize + +@node Mailing Lists, , National Teams, Organization +@subsection Mailing Lists + +If we get any inquiries about GNU @code{gettext}, send them on to: + +@example +@file{translation@@iro.umontreal.ca} +@end example + +The @file{*-pretest} lists are quite useful to me, maybe the idea could +be generalized to many GNU, and non-GNU packages. But each maintainer +his/her way! + +Fran@,{c}ois, we have a mechanism in place here at +@file{gnu.ai.mit.edu} to track teams, support mailing lists for +them and log members. We have a slight preference that you use it. +If this is OK with you, I can get you clued in. + +Things are changing! A few years ago, when Daniel Fekete and I +asked for a mailing list for GNU localization, nested at the FSF, we +were politely invited to organize it anywhere else, and so did we. +For communicating with my pretesters, I later made a handful of +mailing lists located at iro.umontreal.ca and administrated by +@code{majordomo}. These lists have been @emph{very} dependable +so far@dots{} + +I suspect that the German team will organize itself a mailing list +located in Germany, and so forth for other countries. But before they +organize for true, it could surely be useful to offer mailing lists +located at the FSF to each national team. So yes, please explain me +how I should proceed to create and handle them. + +We should create temporary mailing lists, one per country, to help +people organize. Temporary, because once regrouped and structured, it +would be fair the volunteers from country bring back @emph{their} list +in there and manage it as they want. My feeling is that, in the long +run, each team should run its own list, from within their country. +There also should be some central list to which all teams could +subscribe as they see fit, as long as each team is represented in it. + +@node Information Flow, , Organization, Translators +@section Information Flow + +There will surely be some discussion about this messages after the +packages are finally released. If people now send you some proposals +for better messages, how do you proceed? Jim, please note that +right now, as I put forward nearly a dozen of localizable programs, I +receive both the translations and the coordination concerns about them. + +If I put one of my things to pretest, Ulrich receives the announcement +and passes it on to the German team, who make last minute revisions. +Then he submits the translation files to me @emph{as the maintainer}. +For free packages I do not maintain, I would not even hear about it. +This scheme could be made to work for the whole Translation Project, +I think. For security reasons, maybe Ulrich (national coordinators, +in fact) should update central registry kept at the Translation Project +(Jim, me, or Len's recruits) once in a while. + +In December/January, I was aggressively ready to internationalize +all of GNU, giving myself the duty of one small GNU package per week +or so, taking many weeks or months for bigger packages. But it does +not work this way. I first did all the things I'm responsible for. +I've nothing against some missionary work on other maintainers, but +I'm also loosing a lot of energy over it---same debates over again. + +And when the first localized packages are released we'll get a lot of +responses about ugly translations :-). Surely, and we need to have +beforehand a fairly good idea about how to handle the information +flow between the national teams and the package maintainers. + +Please start saving somewhere a quick history of each PO file. I know +for sure that the file format will change, allowing for comments. +It would be nice that each file has a kind of log, and references for +those who want to submit comments or gripes, or otherwise contribute. +I sent a proposal for a fast and flexible format, but it is not +receiving acceptance yet by the GNU deciders. I'll tell you when I +have more information about this. + +@node Maintainers, Conclusion, Translators, Top +@chapter The Maintainer's View + +The maintainer of a package has many responsibilities. One of them +is ensuring that the package will install easily on many platforms, +and that the magic we described earlier (@pxref{Users}) will work +for installers and end users. + +Of course, there are many possible ways by which GNU @code{gettext} +might be integrated in a distribution, and this chapter does not cover +them in all generality. Instead, it details one possible approach which +is especially adequate for many free software distributions following GNU +standards, or even better, Gnits standards, because GNU @code{gettext} +is purposely for helping the internationalization of the whole GNU +project, and as many other good free packages as possible. So, the +maintainer's view presented here presumes that the package already has +a @file{configure.in} file and uses GNU Autoconf. + +Nevertheless, GNU @code{gettext} may surely be useful for free packages +not following GNU standards and conventions, but the maintainers of such +packages might have to show imagination and initiative in organizing +their distributions so @code{gettext} work for them in all situations. +There are surely many, out there. + +Even if @code{gettext} methods are now stabilizing, slight adjustments +might be needed between successive @code{gettext} versions, so you +should ideally revise this chapter in subsequent releases, looking +for changes. + +@menu +* Flat and Non-Flat:: Flat or Non-Flat Directory Structures +* Prerequisites:: Prerequisite Works +* gettextize Invocation:: Invoking the @code{gettextize} Program +* Adjusting Files:: Files You Must Create or Alter +@end menu + +@node Flat and Non-Flat, Prerequisites, Maintainers, Maintainers +@section Flat or Non-Flat Directory Structures + +Some free software packages are distributed as @code{tar} files which unpack +in a single directory, these are said to be @dfn{flat} distributions. +Other free software packages have a one level hierarchy of subdirectories, using +for example a subdirectory named @file{doc/} for the Texinfo manual and +man pages, another called @file{lib/} for holding functions meant to +replace or complement C libraries, and a subdirectory @file{src/} for +holding the proper sources for the package. These other distributions +are said to be @dfn{non-flat}. + +For now, we cannot say much about flat distributions. A flat +directory structure has the disadvantage of increasing the difficulty +of updating to a new version of GNU @code{gettext}. Also, if you have +many PO files, this could somewhat pollute your single directory. +In the GNU @code{gettext} distribution, the @file{misc/} directory +contains a shell script named @file{combine-sh}. That script may +be used for combining all the C files of the @file{intl/} directory +into a pair of C files (one @file{.c} and one @file{.h}). Those two +generated files would fit more easily in a flat directory structure, +and you will then have to add these two files to your project. + +Maybe because GNU @code{gettext} itself has a non-flat structure, +we have more experience with this approach, and this is what will be +described in the remaining of this chapter. Some maintainers might +use this as an opportunity to unflatten their package structure. +Only later, once gained more experience adapting GNU @code{gettext} +to flat distributions, we might add some notes about how to proceed +in flat situations. + +@node Prerequisites, gettextize Invocation, Flat and Non-Flat, Maintainers +@section Prerequisite Works + +There are some works which are required for using GNU @code{gettext} +in one of your package. These works have some kind of generality +that escape the point by point descriptions used in the remainder +of this chapter. So, we describe them here. + +@itemize @bullet +@item +Before attempting to use you should install some other packages first. +Ensure that recent versions of GNU @code{m4}, GNU Autoconf and GNU +@code{gettext} are already installed at your site, and if not, proceed +to do this first. If you got to install these things, beware that +GNU @code{m4} must be fully installed before GNU Autoconf is even +@emph{configured}. + +To further ease the task of a package maintainer the @code{automake} +package was designed and implemented. GNU @code{gettext} now uses this +tool and the @file{Makefile}s in the @file{intl/} and @file{po/} +therefore know about all the goals necessary for using @code{automake} +and @file{libintl} in one project. + +Those four packages are only needed to you, as a maintainer; the +installers of your own package and end users do not really need any of +GNU @code{m4}, GNU Autoconf, GNU @code{gettext}, or GNU @code{automake} +for successfully installing and running your package, with messages +properly translated. But this is not completely true if you provide +internationalized shell scripts within your own package: GNU +@code{gettext} shall then be installed at the user site if the end users +want to see the translation of shell script messages. + +@item +Your package should use Autoconf and have a @file{configure.in} file. +If it does not, you have to learn how. The Autoconf documentation +is quite well written, it is a good idea that you print it and get +familiar with it. + +@item +Your C sources should have already been modified according to +instructions given earlier in this manual. @xref{Sources}. + +@item +Your @file{po/} directory should receive all PO files submitted to you +by the translator teams, each having @file{@var{ll}.po} as a name. +This is not usually easy to get translation +work done before your package gets internationalized and available! +Since the cycle has to start somewhere, the easiest for the maintainer +is to start with absolutely no PO files, and wait until various +translator teams get interested in your package, and submit PO files. + +@end itemize + +It is worth adding here a few words about how the maintainer should +ideally behave with PO files submissions. As a maintainer, your role is +to authentify the origin of the submission as being the representative +of the appropriate translating teams of the Translation Project (forward +the submission to @file{translation@@iro.umontreal.ca} in case of doubt), +to ensure that the PO file format is not severely broken and does not +prevent successful installation, and for the rest, to merely to put these +PO files in @file{po/} for distribution. + +As a maintainer, you do not have to take on your shoulders the +responsibility of checking if the translations are adequate or +complete, and should avoid diving into linguistic matters. Translation +teams drive themselves and are fully responsible of their linguistic +choices for the Translation Project. Keep in mind that translator teams are @emph{not} +driven by maintainers. You can help by carefully redirecting all +communications and reports from users about linguistic matters to the +appropriate translation team, or explain users how to reach or join +their team. The simplest might be to send them the @file{ABOUT-NLS} file. + +Maintainers should @emph{never ever} apply PO file bug reports +themselves, short-cutting translation teams. If some translator has +difficulty to get some of her points through her team, it should not be +an issue for her to directly negotiate translations with maintainers. +Teams ought to settle their problems themselves, if any. If you, as +a maintainer, ever think there is a real problem with a team, please +never try to @emph{solve} a team's problem on your own. + +@node gettextize Invocation, Adjusting Files, Prerequisites, Maintainers +@section Invoking the @code{gettextize} Program + +Some files are consistently and identically needed in every package +internationalized through GNU @code{gettext}. As a matter of +convenience, the @code{gettextize} program puts all these files right +in your package. This program has the following synopsis: + +@example +gettextize [ @var{option}@dots{} ] [ @var{directory} ] +@end example + +@noindent +and accepts the following options: + +@table @samp +@item -c +@itemx --copy +Copy the needed files instead of making symbolic links. Using links +would allow the package to always use the latest @code{gettext} code +available on the system, but it might disturb some mechanism the +maintainer is used to apply to the sources. Because running +@code{gettextize} is easy there shouldn't be problems with using copies. + +@item -f +@itemx --force +Force replacement of files which already exist. + +@item -h +@itemx --help +Display this help and exit. + +@item --version +Output version information and exit. + +@end table + +If @var{directory} is given, this is the top level directory of a +package to prepare for using GNU @code{gettext}. If not given, it +is assumed that the current directory is the top level directory of +such a package. + +The program @code{gettextize} provides the following files. However, +no existing file will be replaced unless the option @code{--force} +(@code{-f}) is specified. + +@enumerate +@item +The @file{ABOUT-NLS} file is copied in the main directory of your package, +the one being at the top level. This file gives the main indications +about how to install and use the Native Language Support features +of your program. You might elect to use a more recent copy of this +@file{ABOUT-NLS} file than the one provided through @code{gettextize}, +if you have one handy. You may also fetch a more recent copy of file +@file{ABOUT-NLS} from Translation Project sites, and from most GNU +archive sites. + +@item +A @file{po/} directory is created for eventually holding +all translation files, but initially only containing the file +@file{po/Makefile.in.in} from the GNU @code{gettext} distribution. +(beware the double @samp{.in} in the file name). If the @file{po/} +directory already exists, it will be preserved along with the files +it contains, and only @file{Makefile.in.in} will be overwritten. + +@item +A @file{intl/} directory is created and filled with most of the files +originally in the @file{intl/} directory of the GNU @code{gettext} +distribution. Also, if option @code{--force} (@code{-f}) is given, +the @file{intl/} directory is emptied first. + +@end enumerate + +If your site support symbolic links, @code{gettextize} will not +actually copy the files into your package, but establish symbolic +links instead. This avoids duplicating the disk space needed in +all packages. Merely using the @samp{-h} option while creating the +@code{tar} archive of your distribution will resolve each link by an +actual copy in the distribution archive. So, to insist, you really +should use @samp{-h} option with @code{tar} within your @code{dist} +goal of your main @file{Makefile.in}. + +It is interesting to understand that most new files for supporting +GNU @code{gettext} facilities in one package go in @file{intl/} +and @file{po/} subdirectories. One distinction between these two +directories is that @file{intl/} is meant to be completely identical +in all packages using GNU @code{gettext}, while all newly created +files, which have to be different, go into @file{po/}. There is a +common @file{Makefile.in.in} in @file{po/}, because the @file{po/} +directory needs its own @file{Makefile}, and it has been designed so +it can be identical in all packages. + +@node Adjusting Files, , gettextize Invocation, Maintainers +@section Files You Must Create or Alter + +Besides files which are automatically added through @code{gettextize}, +there are many files needing revision for properly interacting with +GNU @code{gettext}. If you are closely following GNU standards for +Makefile engineering and auto-configuration, the adaptations should +be easier to achieve. Here is a point by point description of the +changes needed in each. + +So, here comes a list of files, each one followed by a description of +all alterations it needs. Many examples are taken out from the GNU +@code{gettext} @value{VERSION} distribution itself. You may indeed +refer to the source code of the GNU @code{gettext} package, as it +is intended to be a good example and master implementation for using +its own functionality. + +@menu +* po/POTFILES.in:: @file{POTFILES.in} in @file{po/} +* configure.in:: @file{configure.in} at top level +* aclocal:: @file{aclocal.m4} at top level +* acconfig:: @file{acconfig.h} at top level +* Makefile:: @file{Makefile.in} at top level +* src/Makefile:: @file{Makefile.in} in @file{src/} +@end menu + +@node po/POTFILES.in, configure.in, Adjusting Files, Adjusting Files +@subsection @file{POTFILES.in} in @file{po/} + +The @file{po/} directory should receive a file named +@file{POTFILES.in}. This file tells which files, among all program +sources, have marked strings needing translation. Here is an example +of such a file: + +@example +@group +# List of source files containing translatable strings. +# Copyright (C) 1995 Free Software Foundation, Inc. + +# Common library files +lib/error.c +lib/getopt.c +lib/xmalloc.c + +# Package source files +src/gettextp.c +src/msgfmt.c +src/xgettext.c +@end group +@end example + +@noindent +Dashed comments and white lines are ignored. All other lines +list those source files containing strings marked for translation +(@pxref{Mark Keywords}), in a notation relative to the top level +of your whole distribution, rather than the location of the +@file{POTFILES.in} file itself. + +@node configure.in, aclocal, po/POTFILES.in, Adjusting Files +@subsection @file{configure.in} at top level + +@enumerate +@item Declare the package and version. + +This is done by a set of lines like these: + +@example +PACKAGE=gettext +VERSION=@value{VERSION} +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") +AC_DEFINE_UNQUOTED(VERSION, "$VERSION") +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) +@end example + +@noindent +Of course, you replace @samp{gettext} with the name of your package, +and @samp{@value{VERSION}} by its version numbers, exactly as they +should appear in the packaged @code{tar} file name of your distribution +(@file{gettext-@value{VERSION}.tar.gz}, here). + +@item Declare the available translations. + +This is done by defining @code{ALL_LINGUAS} to the white separated, +quoted list of available languages, in a single line, like this: + +@example +ALL_LINGUAS="de fr" +@end example + +@noindent +This example means that German and French PO files are available, so +that these languages are currently supported by your package. If you +want to further restrict, at installation time, the set of installed +languages, this should not be done by modifying @code{ALL_LINGUAS} in +@file{configure.in}, but rather by using the @code{LINGUAS} environment +variable (@pxref{Installers}). + +@item Check for internationalization support. + +Here is the main @code{m4} macro for triggering internationalization +support. Just add this line to @file{configure.in}: + +@example +AM_GNU_GETTEXT +@end example + +@noindent +This call is purposely simple, even if it generates a lot of configure +time checking and actions. + +@item Have output files created. + +The @code{AC_OUTPUT} directive, at the end of your @file{configure.in} +file, needs to be modified in two ways: + +@example +AC_OUTPUT([@var{existing configuration files} intl/Makefile po/Makefile.in], +@var{existing additional actions}]) +@end example + +The modification to the first argument to @code{AC_OUTPUT} asks +for substitution in the @file{intl/} and @file{po/} directories. +Note the @samp{.in} suffix used for @file{po/} only. This is because +the distributed file is really @file{po/Makefile.in.in}. + +@end enumerate + +@node aclocal, acconfig, configure.in, Adjusting Files +@subsection @file{aclocal.m4} at top level + +If you do not have an @file{aclocal.m4} file in your distribution, +the simplest is taking a copy of @file{aclocal.m4} from +GNU @code{gettext}. But to be precise, you only need macros +@code{AM_LC_MESSAGES}, @code{AM_WITH_NLS} and @code{AM_GNU_GETTEXT}, +and @code{AM_PATH_PROG_WITH_TEST}, which is called by @code{AM_WITH_NLS}, +so you may use an editor and remove macros you do not need. + +If you already have an @file{aclocal.m4} file, then you will have +to merge the said macros into your @file{aclocal.m4}. Note that if +you are upgrading from a previous release of GNU @code{gettext}, you +should most probably @emph{replace} the said macros, as they usually +change a little from one release of GNU @code{gettext} to the next. +Their contents may vary as we get more experience with strange systems +out there. + +These macros check for the internationalization support functions +and related informations. Hopefully, once stabilized, these macros +might be integrated in the standard Autoconf set, because this +piece of @code{m4} code will be the same for all projects using GNU +@code{gettext}. + +@node acconfig, Makefile, aclocal, Adjusting Files +@subsection @file{acconfig.h} at top level + +If you do not have an @file{acconfig.h} file in your distribution, the +simplest is use take a copy of @file{acconfig.h} from GNU +@code{gettext}. But to be precise, you only need the lines and comments +for @code{ENABLE_NLS}, @code{HAVE_CATGETS}, @code{HAVE_GETTEXT} and +@code{HAVE_LC_MESSAGES}, @code{HAVE_STPCPY}, @code{PACKAGE} and +@code{VERSION}, so you may use an editor and remove everything else. If +you already have an @file{acconfig.h} file, then you should merge the +said definitions into your @file{acconfig.h}. + +@node Makefile, src/Makefile, acconfig, Adjusting Files +@subsection @file{Makefile.in} at top level + +Here are a few modifications you need to make to your main, top-level +@file{Makefile.in} file. + +@enumerate +@item +Add the following lines near the beginning of your @file{Makefile.in}, +so the @samp{dist:} goal will work properly (as explained further down): + +@example +PACKAGE = @@PACKAGE@@ +VERSION = @@VERSION@@ +@end example + +@item +Add file @file{ABOUT-NLS} to the @code{DISTFILES} definition, so the file gets +distributed. + +@item +Wherever you process subdirectories in your @file{Makefile.in}, be sure +you also process dir subdirectories @samp{intl} and @samp{po}. Special +rules in the @file{Makefiles} take care for the case where no +internationalization is wanted. + +If you are using Makefiles, either generated by automake, or hand-written +so they carefully follow the GNU coding standards, the effected goals for +which the new subdirectories must be handled include @samp{installdirs}, +@samp{install}, @samp{uninstall}, @samp{clean}, @samp{distclean}. + +Here is an example of a canonical order of processing. In this +example, we also define @code{SUBDIRS} in @code{Makefile.in} for it +to be further used in the @samp{dist:} goal. + +@example +SUBDIRS = doc lib @@INTLSUB@@ src @@POSUB@@ +@end example + +@noindent +that you will have to adapt to your own package. + +@item +A delicate point is the @samp{dist:} goal, as both +@file{intl/Makefile} and @file{po/Makefile} will later assume that the +proper directory has been set up from the main @file{Makefile}. Here is +an example at what the @samp{dist:} goal might look like: + +@example +distdir = $(PACKAGE)-$(VERSION) +dist: Makefile + rm -fr $(distdir) + mkdir $(distdir) + chmod 777 $(distdir) + for file in $(DISTFILES); do \ + ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir); \ + done + for subdir in $(SUBDIRS); do \ + mkdir $(distdir)/$$subdir || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $@@) || exit 1; \ + done + tar chozf $(distdir).tar.gz $(distdir) + rm -fr $(distdir) +@end example + +@end enumerate + +@node src/Makefile, , Makefile, Adjusting Files +@subsection @file{Makefile.in} in @file{src/} + +Some of the modifications made in the main @file{Makefile.in} will +also be needed in the @file{Makefile.in} from your package sources, +which we assume here to be in the @file{src/} subdirectory. Here are +all the modifications needed in @file{src/Makefile.in}: + +@enumerate +@item +In view of the @samp{dist:} goal, you should have these lines near the +beginning of @file{src/Makefile.in}: + +@example +PACKAGE = @@PACKAGE@@ +VERSION = @@VERSION@@ +@end example + +@item +If not done already, you should guarantee that @code{top_srcdir} +gets defined. This will serve for @code{cpp} include files. Just add +the line: + +@example +top_srcdir = @@top_srcdir@@ +@end example + +@item +You might also want to define @code{subdir} as @samp{src}, later +allowing for almost uniform @samp{dist:} goals in all your +@file{Makefile.in}. At list, the @samp{dist:} goal below assume that +you used: + +@example +subdir = src +@end example + +@item +You should ensure that the final linking will use @code{@@INTLLIBS@@} as +a library. An easy way to achieve this is to manage that it gets into +@code{LIBS}, like this: + +@example +LIBS = @@INTLLIBS@@ @@LIBS@@ +@end example + +In most packages internationalized with GNU @code{gettext}, one will +find a directory @file{lib/} in which a library containing some helper +functions will be build. (You need at least the few functions which the +GNU @code{gettext} Library itself needs.) However some of the functions +in the @file{lib/} also give messages to the user which of course should be +translated, too. Taking care of this it is not enough to place the support +library (say @file{libsupport.a}) just between the @code{@@INTLLIBS@@} +and @code{@@LIBS@@} in the above example. Instead one has to write this: + +@example +LIBS = ../lib/libsupport.a @@INTLLIBS@@ ../lib/libsupport.a @@LIBS@@ +@end example + +@item +You should also ensure that directory @file{intl/} will be searched for +C preprocessor include files in all circumstances. So, you have to +manage so both @samp{-I../intl} and @samp{-I$(top_srcdir)/intl} will +be given to the C compiler. + +@item +Your @samp{dist:} goal has to conform with others. Here is a +reasonable definition for it: + +@example +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist: Makefile $(DISTFILES) + for file in $(DISTFILES); do \ + ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir); \ + done +@end example + +@end enumerate + +@node Conclusion, Country Codes, Maintainers, Top +@chapter Concluding Remarks + +We would like to conclude this GNU @code{gettext} manual by presenting +an history of the Translation Project so far. We finally give +a few pointers for those who want to do further research or readings +about Native Language Support matters. + +@menu +* History:: History of GNU @code{gettext} +* References:: Related Readings +@end menu + +@node History, References, Conclusion, Conclusion +@section History of GNU @code{gettext} + +Internationalization concerns and algorithms have been informally +and casually discussed for years in GNU, sometimes around GNU +@code{libc}, maybe around the incoming @code{Hurd}, or otherwise +(nobody clearly remembers). And even then, when the work started for +real, this was somewhat independently of these previous discussions. + +This all began in July 1994, when Patrick D'Cruze had the idea and +initiative of internationalizing version 3.9.2 of GNU @code{fileutils}. +He then asked Jim Meyering, the maintainer, how to get those changes +folded into an official release. That first draft was full of +@code{#ifdef}s and somewhat disconcerting, and Jim wanted to find +nicer ways. Patrick and Jim shared some tries and experimentations +in this area. Then, feeling that this might eventually have a deeper +impact on GNU, Jim wanted to know what standards were, and contacted +Richard Stallman, who very quickly and verbally described an overall +design for what was meant to become @code{glocale}, at that time. + +Jim implemented @code{glocale} and got a lot of exhausting feedback +from Patrick and Richard, of course, but also from Mitchum DSouza +(who wrote a @code{catgets}-like package), Roland McGrath, maybe David +MacKenzie, Fran@,{c}ois Pinard, and Paul Eggert, all pushing and +pulling in various directions, not always compatible, to the extent +that after a couple of test releases, @code{glocale} was torn apart. + +While Jim took some distance and time and became dad for a second +time, Roland wanted to get GNU @code{libc} internationalized, and +got Ulrich Drepper involved in that project. Instead of starting +from @code{glocale}, Ulrich rewrote something from scratch, but +more conformant to the set of guidelines who emerged out of the +@code{glocale} effort. Then, Ulrich got people from the previous +forum to involve themselves into this new project, and the switch +from @code{glocale} to what was first named @code{msgutils}, renamed +@code{nlsutils}, and later @code{gettext}, became officially accepted +by Richard in May 1995 or so. + +Let's summarize by saying that Ulrich Drepper wrote GNU @code{gettext} +in April 1995. The first official release of the package, including +PO mode, occurred in July 1995, and was numbered 0.7. Other people +contributed to the effort by providing a discussion forum around +Ulrich, writing little pieces of code, or testing. These are quoted +in the @code{THANKS} file which comes with the GNU @code{gettext} +distribution. + +While this was being done, Fran@,{c}ois adapted half a dozen of +GNU packages to @code{glocale} first, then later to @code{gettext}, +putting them in pretest, so providing along the way an effective +user environment for fine tuning the evolving tools. He also took +the responsibility of organizing and coordinating the Translation +Project. After nearly a year of informal exchanges between people from +many countries, translator teams started to exist in May 1995, through +the creation and support by Patrick D'Cruze of twenty unmoderated +mailing lists for that many native languages, and two moderated +lists: one for reaching all teams at once, the other for reaching +all willing maintainers of internationalized free software packages. + +Fran@,{c}ois also wrote PO mode in June 1995 with the collaboration +of Greg McGary, as a kind of contribution to Ulrich's package. +He also gave a hand with the GNU @code{gettext} Texinfo manual. + +@node References, , History, Conclusion +@section Related Readings + +Eugene H. Dorr (@file{dorre@@well.com}) maintains an interesting +bibliography on internationalization matters, called +@cite{Internationalization Reference List}, which is available as: +@example +ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/i18n-books.txt +@end example + +Michael Gschwind (@file{mike@@vlsivie.tuwien.ac.at}) maintains a +Frequently Asked Questions (FAQ) list, entitled @cite{Programming for +Internationalisation}. This FAQ discusses writing programs which +can handle different language conventions, character sets, etc.; +and is applicable to all character set encodings, with particular +emphasis on @w{ISO 8859-1}. It is regularly published in Usenet +groups @file{comp.unix.questions}, @file{comp.std.internat}, +@file{comp.software.international}, @file{comp.lang.c}, +@file{comp.windows.x}, @file{comp.std.c}, @file{comp.answers} +and @file{news.answers}. The home location of this document is: +@example +ftp://ftp.vlsivie.tuwien.ac.at/pub/8bit/ISO-programming +@end example + +Patrick D'Cruze (@file{pdcruze@@li.org}) wrote a tutorial about NLS +matters, and Jochen Hein (@file{Hein@@student.tu-clausthal.de}) took +over the responsibility of maintaining it. It may be found as: +@example +ftp://sunsite.unc.edu/pub/Linux/utils/nls/catalogs/Incoming/... + ...locale-tutorial-0.8.txt.gz +@end example +@noindent +This site is mirrored in: +@example +ftp://ftp.ibp.fr/pub/linux/sunsite/ +@end example + +A French version of the same tutorial should be findable at: +@example +ftp://ftp.ibp.fr/pub/linux/french/docs/ +@end example +@noindent +together with French translations of many Linux-related documents. + +@node Country Codes, , Conclusion, Top +@appendix Country Codes + +The @w{ISO 639} standard defines two character codes for many countries. +All abreviations for countries or languages used in the Translation +Project should come from this standard. + +@table @samp +@include iso-apdx.texi +@end table + +@contents +@bye + +@c Local variables: +@c texinfo-column-for-description: 32 +@c End: diff --git a/doc/iso-apdx.sed b/doc/iso-apdx.sed new file mode 100644 index 0000000..1f9948b --- /dev/null +++ b/doc/iso-apdx.sed @@ -0,0 +1,19 @@ +#! /usr/bin/sed -f +# +# each line of the form ^.. .* contains the code for a country. +# +/^.. / { + h + s/^.. \(.*\)/\1./ + x + s/^\(..\).*/@item \1/ + G + p +} +# +# delete the rest +# +d + + + diff --git a/doc/iso-apdx.texi b/doc/iso-apdx.texi new file mode 100644 index 0000000..df50921 --- /dev/null +++ b/doc/iso-apdx.texi @@ -0,0 +1,278 @@ +@item aa +Afar. +@item ab +Abkhazian. +@item af +Afrikaans. +@item am +Amharic. +@item ar +Arabic. +@item as +Assamese. +@item ay +Aymara. +@item az +Azerbaijani. +@item ba +Bashkir. +@item be +Byelorussian. +@item bg +Bulgarian. +@item bh +Bihari. +@item bi +Bislama. +@item bn +Bengali; Bangla. +@item bo +Tibetan. +@item br +Breton. +@item ca +Catalan. +@item co +Corsican. +@item cs +Czech. +@item cy +Welsh. +@item da +Danish. +@item de +German. +@item dz +Bhutani. +@item el +Greek. +@item en +English. +@item eo +Esperanto. +@item es +Spanish. +@item et +Estonian. +@item eu +Basque. +@item fa +Persian. +@item fi +Finnish. +@item fj +Fiji. +@item fo +Faroese. +@item fr +French. +@item fy +Frisian. +@item ga +Irish. +@item gd +Scots Gaelic. +@item gl +Galician. +@item gn +Guarani. +@item gu +Gujarati. +@item ha +Hausa. +@item he +Hebrew (formerly iw). +@item hi +Hindi. +@item hr +Croatian. +@item hu +Hungarian. +@item hy +Armenian. +@item ia +Interlingua. +@item id +Indonesian (formerly in). +@item ie +Interlingue. +@item ik +Inupiak. +@item is +Icelandic. +@item it +Italian. +@item iu +Inuktitut. +@item ja +Japanese. +@item jw +Javanese. +@item ka +Georgian. +@item kk +Kazakh. +@item kl +Greenlandic. +@item km +Cambodian. +@item kn +Kannada. +@item ko +Korean. +@item ks +Kashmiri. +@item ku +Kurdish. +@item ky +Kirghiz. +@item la +Latin. +@item ln +Lingala. +@item lo +Laothian. +@item lt +Lithuanian. +@item lv +Latvian, Lettish. +@item mg +Malagasy. +@item mi +Maori. +@item mk +Macedonian. +@item ml +Malayalam. +@item mn +Mongolian. +@item mo +Moldavian. +@item mr +Marathi. +@item ms +Malay. +@item mt +Maltese. +@item my +Burmese. +@item na +Nauru. +@item ne +Nepali. +@item nl +Dutch. +@item no +Norwegian. +@item oc +Occitan. +@item om +(Afan) Oromo. +@item or +Oriya. +@item pa +Punjabi. +@item pl +Polish. +@item ps +Pashto, Pushto. +@item pt +Portuguese. +@item qu +Quechua. +@item rm +Rhaeto-Romance. +@item rn +Kirundi. +@item ro +Romanian. +@item ru +Russian. +@item rw +Kinyarwanda. +@item sa +Sanskrit. +@item sd +Sindhi. +@item sg +Sangro. +@item sh +Serbo-Croatian. +@item si +Sinhalese. +@item sk +Slovak. +@item sl +Slovenian. +@item sm +Samoan. +@item sn +Shona. +@item so +Somali. +@item sq +Albanian. +@item sr +Serbian. +@item ss +Siswati. +@item st +Sesotho. +@item su +Sundanese. +@item sv +Swedish. +@item sw +Swahili. +@item ta +Tamil. +@item te +Telugu. +@item tg +Tajik. +@item th +Thai. +@item ti +Tigrinya. +@item tk +Turkmen. +@item tl +Tagalog. +@item tn +Setswana. +@item to +Tonga. +@item tr +Turkish. +@item ts +Tsonga. +@item tt +Tatar. +@item tw +Twi. +@item ug +Uighur. +@item uk +Ukrainian. +@item ur +Urdu. +@item uz +Uzbek. +@item vi +Vietnamese. +@item vo +Volapuk. +@item wo +Wolof. +@item xh +Xhosa. +@item yi +Yiddish (formerly ji). +@item yo +Yoruba. +@item za +Zhuang. +@item zh +Chinese. +@item zu +Zulu. diff --git a/doc/matrix.texi b/doc/matrix.texi new file mode 100644 index 0000000..c3b8995 --- /dev/null +++ b/doc/matrix.texi @@ -0,0 +1,75 @@ +@example +@group +Ready PO files cs da de el en es fi fr it + .----------------------------. +bash | [] [] | +bison | [] [] | +clisp | [] [] [] [] | +cpio | [] [] [] | +diffutils | [] [] [] | +enscript | [] [] [] [] | +fileutils | [] [] [] [] | +findutils | [] [] [] [] | +flex | [] [] | +gcal | [] [] | +gettext | [] [] [] [] [] | +grep | [] [] [] [] | +hello | [] [] [] [] [] | +id-utils | [] [] | +indent | [] [] | +libc | [] [] [] | +m4 | [] [] | +make | [] [] [] | +music | [] | +ptx | [] [] [] | +recode | [] [] [] [] | +sed | | +sh-utils | [] [] [] | +sharutils | [] [] [] [] [] | +tar | [] [] [] [] | +texinfo | [] [] [] | +textutils | [] [] [] [] | +wdiff | [] [] [] [] | +wget | [] [] [] [] | + `----------------------------' + cs da de el en es fi fr it + 7 4 26 4 1 18 1 26 4 +@end group + +@group + ja ko nl no pl pt ru sl sv + .----------------------------. +bash | [] | 3 +bison | [] | 3 +clisp | | 4 +cpio | [] [] [] | 6 +diffutils | [] [] | 5 +enscript | [] [] | 6 +fileutils | [] [] [] [] [] [] [] | 11 +findutils | [] [] [] [] [] | 9 +flex | [] [] | 4 +gcal | [] [] [] | 5 +gettext | [] [] [] [] [] [] [] | 13 +grep | [] [] [] [] [] [] [] | 11 +hello | [] [] [] [] [] [] [] | 12 +id-utils | [] | 3 +indent | [] [] [] | 5 +libc | [] [] [] [] [] | 8 +m4 | [] [] [] [] | 6 +make | [] [] [] | 6 +music | [] | 2 +ptx | [] [] [] [] [] | 8 +recode | [] [] [] [] [] | 9 +sed | | 0 +sh-utils | [] [] [] [] [] | 8 +sharutils | [] [] | 7 +tar | [] [] [] [] [] [] [] | 11 +texinfo | [] | 4 +textutils | [] [] [] [] [] | 9 +wdiff | [] [] [] [] | 8 +wget | [] | 5 + `----------------------------' + 18 teams ja ko nl no pl pt ru sl sv + 29 domains 1 12 21 11 19 7 5 7 17 191 +@end group +@end example diff --git a/doc/mdate-sh b/doc/mdate-sh new file mode 100755 index 0000000..37171f2 --- /dev/null +++ b/doc/mdate-sh @@ -0,0 +1,92 @@ +#!/bin/sh +# Get modification time of a file or directory and pretty-print it. +# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995 +# +# 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, 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Prevent date giving response in another language. +LANG=C +export LANG +LC_ALL=C +export LC_ALL +LC_TIME=C +export LC_TIME + +# Get the extended ls output of the file or directory. +# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. +if ls -L /dev/null 1>/dev/null 2>&1; then + set - x`ls -L -l -d $1` +else + set - x`ls -l -d $1` +fi +# The month is at least the fourth argument +# (3 shifts here, the next inside the loop). +shift +shift +shift + +# Find the month. Next argument is day, followed by the year or time. +month= +until test $month +do + shift + case $1 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; + esac +done + +day=$2 + +# Here we have to deal with the problem that the ls output gives either +# the time of day or the year. +case $3 in + *:*) set `date`; eval year=\$$# + case $2 in + Jan) nummonthtod=1;; + Feb) nummonthtod=2;; + Mar) nummonthtod=3;; + Apr) nummonthtod=4;; + May) nummonthtod=5;; + Jun) nummonthtod=6;; + Jul) nummonthtod=7;; + Aug) nummonthtod=8;; + Sep) nummonthtod=9;; + Oct) nummonthtod=10;; + Nov) nummonthtod=11;; + Dec) nummonthtod=12;; + esac + # For the first six month of the year the time notation can also + # be used for files modified in the last year. + if (expr $nummonth \> $nummonthtod) > /dev/null; + then + year=`expr $year - 1` + fi;; + *) year=$3;; +esac + +# The result. +echo $day $month $year diff --git a/doc/nls.texi b/doc/nls.texi new file mode 100644 index 0000000..a7797e8 --- /dev/null +++ b/doc/nls.texi @@ -0,0 +1,254 @@ +@node Translation Intro +@chapter Notes on the Free Translation Project + +@set STATUS August 1998 + +Free software is going international! The Free Translation Project is +a way to get maintainers of free software, translators, and users all +together, so that will gradually become able to speak many languages. +A few packages already provide translations for their messages. + +If you found this @file{ABOUT-NLS} file inside a distribution, you +may assume that the distributed package does use GNU @code{gettext} +internally, itself available at your nearest GNU archive site. But you +do @emph{not} need to install GNU @code{gettext} prior to configuring, +installing or using this package with messages translated. + +Installers will find here some useful hints. These notes also explain +how users should proceed for getting the programs to use the available +translations. They tell how people wanting to contribute and work +at translations should contact the appropriate team. + +When reporting bugs in the @file{intl/} directory or bugs which may +be related to internationalization, you should tell about the version +of @code{gettext} which is used. The information can be found in +the @file{intl/VERSION} file, in internationalized packages. + +@menu +* One advise:: +* INSTALL Matters:: +* Using This Package:: +* Translating Teams:: +* Available Packages:: +* Using gettext in own code:: +@end menu + +@node One advise +@section One advise in advance + +If you want to exploit the full power of internationalization, you +should configure it using + +@example +./configure --with-included-gettext +@end example + +@noindent +to force usage of internationalizing routines provided within this +package, despite the existence of internationalizing capabilities in the +operating system where this package is being installed. So far, only +the @code{gettext} implementation in the GNU C library version 2 +provides as many features (such as locale alias or message inheritance) +as the implementation here. It is also not possible to offer this +additional functionality on top of a @code{catgets} implementation. +Future versions of GNU @code{gettext} will very likely convey even more +functionality. So it might be a good idea to change to GNU +@code{gettext} as soon as possible. + +So you need not provide this option if you are using GNU libc 2 or you +have installed a recent copy of the GNU gettext package with the +included @file{libintl}. + + +@node INSTALL Matters +@section INSTALL Matters + +Some packages are @dfn{localizable} when properly installed; the +programs they contain can be made to speak your own native language. +Most such packages use GNU @code{gettext}. Other packages have their +own ways to internationalization, predating GNU @code{gettext}. + +By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system provides +usable @code{catgets} (if using this is selected by the installer) or +@code{gettext} functions. If neither is available, the GNU +@code{gettext} own library will be used. This library is wholly +contained within this package, usually in the @file{intl/} subdirectory, +so prior installation of the GNU @code{gettext} package is @emph{not} +required. Installers may use special options at configuration time for +changing the default behaviour. The commands: + +@example +./configure --with-included-gettext +./configure --with-catgets +./configure --disable-nls +@end example + +@noindent +will respectively bypass any pre-existing @code{catgets} or +@code{gettext} to use the internationalizing routines provided within +this package, enable the use of the @code{catgets} functions (if found +on the locale system), or else, @emph{totally} disable translation of +messages. + +When you already have GNU @code{gettext} installed on your system and +run configure without an option for your new package, @code{configure} +will probably detect the previously built and installed @file{libintl.a} +file and will decide to use this. This might be not what is desirable. +You should use the more recent version of the GNU @code{gettext} +library. I.e. if the file @file{intl/VERSION} shows that the library +which comes with this package is more recent, you should use + +@example +./configure --with-included-gettext +@end example + +@noindent +to prevent auto-detection. + +By default the configuration process will not test for the +@code{catgets} function and therefore they will not be used. The +reasons are already given above: the emulation on top of @code{catgets} +cannot provide all the extensions provided by the GNU @code{gettext} +library. If you nevertheless want to use the @code{catgets} functions +use + +@example +./configure --with-catgets +@end example + +@noindent +to enable the test for @code{catgets} (this causes no harm if +@code{catgets} is not available on your system). If you really select +this option we would like to hear about the reasons because we cannot +think of any good one ourself. + +Internationalized packages have usually many @file{po/@var{ll}.po} +files, where @var{ll} gives an @w{ISO 639} two-letter code +identifying the language. Unless translations have been forbidden +at @code{configure} time by using the @samp{--disable-nls} switch, +all available translations are installed together with the package. +However, the environment variable @code{LINGUAS} may be set, prior +to configuration, to limit the installed set. @code{LINGUAS} should +then contain a space separated list of two-letter codes, stating +which languages are allowed. + +@node Using This Package +@section Using This Package + +@c -- +@c FIXME: rewrite to document LANGUAGE, the long names, and aliases. +@c -- +As a user, if your language has been installed for this package, you +only have to set the @code{LANG} environment variable to the appropriate +@w{ISO 639} @samp{@var{ll}} two-letter code prior to using the programs +in the package. For example, let's suppose that you speak German. At +the shell prompt, merely execute @w{@samp{setenv LANG de}} (in +@code{csh}), @w{@samp{export LANG; LANG=de}} (in @code{sh}) or +@w{@samp{export LANG=de}} (in @code{bash}). This can be done from your +@file{.login} or @file{.profile} file, once and for all. +@c Packages which are not internationalized will merely ignore the +@c setting of this variable. +@c FIXME: This last sentence is not true!! --drepper + +An operating system might already offer message localization for many of +its programs, while other programs have been +installed locally with the full capabilities of GNU @code{gettext}. +Just using @code{gettext} extended syntax for @code{LANG} would break +proper localization of already available operating system programs. In +this case, users should set both @code{LANGUAGE} and @code{LANG} +variables in their environment, as programs using GNU @code{gettext} +give preference to @code{LANGUAGE}. For example, some Swedish users +would rather read translations in German than English for when Swedish +is not available. This is easily accomplished by setting +@code{LANGUAGE} to @samp{sv:de} while leaving @code{LANG} to @samp{sv}. + + +@node Translating Teams +@section Translating Teams + +For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list, courtesy of Linux +International. You may reach your translation team at the address +@file{@var{ll}@@li.org}, replacing @var{ll} by the two-letter @w{ISO +639} code for your language. Language codes are @emph{not} the same as +the country codes given in @w{ISO 3166}. The following translation +teams exist, as of @value{STATUS}: + +@quotation +Chinese @code{zh}, Czech @code{cs}, Danish @code{da}, Dutch @code{nl}, +English @code{en}, Esperanto @code{eo}, Finnish @code{fi}, French +@code{fr}, German @code{de}, Hungarian @code{hu}, Irish @code{ga}, +Italian @code{it}, Indonesian @code{id}, Japanese @code{ja}, Korean +@code{ko}, Latin @code{la}, Norwegian @code{no}, Persian @code{fa}, +Polish @code{pl}, Portuguese @code{pt}, Russian @code{ru}, Slovenian +@code{sl}, Spanish @code{es}, Swedish @code{sv}, and Turkish @code{tr}. +@end quotation + +@noindent +For example, you may reach the Chinese translation team by writing to +@file{zh@@li.org}. + +If you'd like to volunteer to @emph{work} at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is @emph{not} the same as the list itself, it +has @samp{-request} appended. For example, speakers of Swedish can send +a message to @w{@file{sv-request@@li.org}}, having this message body: + +@example +subscribe +@end example + +Keep in mind that team members are expected to participate +@emph{actively} in translations, or at solving translational +difficulties, rather than merely lurking around. If your team does not +exist yet and you want to start one, or if you are unsure about what to +do or how to get started, please write to +@w{@file{translation@@iro.umontreal.ca}} to reach the +coordinator for all translator teams. + +The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skill are praised +more than programming skill, here. + +@node Available Packages +@section Available Packages + +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of +@value{STATUS}. The matrix shows, in regard of each package, for which +languages PO files have been submitted to translation coordination. + +@include matrix.texi + +Some counters in the preceding matrix are higher than the number of visible +blocks let us expect. This is because a few extra PO files are used for +implementing regional variants of languages, or language dialects. + +For a PO file in the matrix above to be effective, the package to which +it applies should also have been internationalized and distributed as +such by its maintainer. There might be an observable lag between the +mere existence a PO file and its wide availability in a distribution. + +If @value{STATUS} seems to be old, you may fetch a more recent copy +of this @file{ABOUT-NLS} file on most GNU archive sites. + + +@node Using gettext in own code +@section Using @code{gettext} in new packages + +If you are writing a freely available program and want to +internationalize it you are welcome to use GNU @file{gettext} in your +package. Of course the GNU Public License applies to your sources from +then if you include @code{gettext} directly in your distribution on but +since you are writing free software anyway this is no restriction. + +Once the sources are change appropriately and the setup can handle to +use of @code{gettext} the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +@w{@file{translation@@iro.umontreal.ca}} to make the @file{.pot} files +available to the translation teams. diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..5469103 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,5302 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% $Id: texinfo.tex,v 1.1 2000/06/16 07:49:23 drepper Exp $ +% +% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98 +% Free Software Foundation, Inc. +% +% This texinfo.tex file 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, or (at +% your option) any later version. +% +% This texinfo.tex file 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. +% +% You should have received a copy of the GNU General Public License +% along with this texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +% In other words, you are welcome to use, share and improve this program. +% You are forbidden to forbid anyone else to use, share and improve +% what you give them. Help stamp out software-hoarding! +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% /home/gd/gnu/doc/texinfo.tex on the GNU machines. +% ftp://ftp.gnu.org/pub/gnu/texinfo.tex +% (and all GNU mirrors, see ftp://ftp.gnu.org/pub/gnu/README.mirrors) +% ftp://tug.org/tex/texinfo.tex +% ftp://ctan.org/macros/texinfo/texinfo.tex +% (and all CTAN mirrors, finger ctan@tug.org for a list). +% +% Send bug reports to bug-texinfo@gnu.org. +% Please include a precise test case in each bug report, +% including a complete document with which we can reproduce the problem. +% +% Texinfo macros (with @macro) are *not* supported by texinfo.tex. You +% have to run makeinfo -E to expand macros first; the texi2dvi script +% does this. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For simple +% manuals, you can get away with: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever, to process the dvi file. +% The extra runs of TeX get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. + + +% Make it possible to create a .fmt file just by loading this file: +% if the underlying format is not loaded, start by loading it now. +% Added by gildea November 1993. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi + +% This automatically updates the version number based on RCS. +\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}} +\deftexinfoversion$Revision: 1.1 $ +\message{Loading texinfo package [Version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}\message{} + \catcode`+=\active \catcode`\_=\active} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexi=\i +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexstar=\* +\let\ptext=\t + +% We never want plain's outer \+ definition in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordInfo\undefined \gdef\putwordfile{Info}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortContents\undefined \gdef\putwordShortContents{Short Contents}\fi +\ifx\putwordTableofContents\undefined\gdef\putwordTableofContents{Table of Contents}\fi + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} +\hyphenation{white-space} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset +\newdimen \normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\cornerlong \newdimen\cornerthick +\newdimen\topandbottommargin +\newdimen\outerhsize \newdimen\outervsize +\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks +\outerhsize=7in +%\outervsize=9.5in +% Alternative @smallbook page size is 9.25in +\outervsize=9.25in +\topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \escapechar = `\\ % use backslash in output files. + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + \shipout\vbox{% + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \turnoffactive + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment. Type Return to continue.} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Type <Return> to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = 12.5pt +\def\singlespace{% + % Why was this kern here? It messes up equalizing space above and below + % environments. --karl, 6may93 + %{\advance \baselineskip by -\singlespaceskip + %\kern \baselineskip}% + \setleading \singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce actual \{ & \} command in an index. + \catcode`\{ = 12 \catcode`\} = 12 + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\@ = 0 \catcode`\\ = 12 + @gdef@lbracecmd[\{]% + @gdef@rbracecmd[\}]% +@endgroup + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown +% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000 +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Go into vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % Don't add any leading before our big empty box, but allow a page + % break, since the best break might be right here. + \allowbreak + \nointerlineskip + \vtop to #1\mil{\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in a typewriter +% font as three actual period characters. +% +\def\dots{\hbox to 1.5em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil +}} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \hbox to 2em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% + \spacefactor=3000 +} + + +% @page forces the start of a new page + +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph. + +\def\inmargin#1{% +\strut\vadjust{\nobreak\kern-\strutdepth + \vtop to \strutdepth{\baselineskip\strutdepth\vss + \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}} +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=12 + \catcode`~=12 + \catcode`^=12 + \catcode`_=12 + \catcode`|=12 + \catcode`<=12 + \catcode`>=12 + \catcode`+=12 + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other% +\parsearg \commentxxx} + +\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 } + +\let\c=\comment + +% @paragraphindent is defined for the Info formatting commands only. +\let\paragraphindent=\comment + +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% +\let\chapter=\relax +\let\unnumbered=\relax +\let\top=\relax +\let\unnumberedsec=\relax +\let\unnumberedsection=\relax +\let\unnumberedsubsec=\relax +\let\unnumberedsubsection=\relax +\let\unnumberedsubsubsec=\relax +\let\unnumberedsubsubsection=\relax +\let\section=\relax +\let\subsec=\relax +\let\subsubsec=\relax +\let\subsection=\relax +\let\subsubsection=\relax +\let\appendix=\relax +\let\appendixsec=\relax +\let\appendixsection=\relax +\let\appendixsubsec=\relax +\let\appendixsubsection=\relax +\let\appendixsubsubsec=\relax +\let\appendixsubsubsection=\relax +\let\contents=\relax +\let\smallbook=\relax +\let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcodeindex = \relax + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\everyheading = \relax + \let\evenheading = \relax + \let\oddheading = \relax + \let\everyfooting = \relax + \let\evenfooting = \relax + \let\oddfooting = \relax + \let\headings = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax + \let\item = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifnottex{\doignore{ifnottex}} +\def\html{\doignore{html}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% Also ignore @macro ... @end macro. The user must run texi2dvi, +% which runs makeinfo to do macro expansion. Ignore @unmacro, too. +\def\macro{\doignore{macro}} +\def\macrocsname{macro} +\let\unmacro = \comment + + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory = \comment + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + % This @ is a catcode 12 token (that is the normal catcode of @ in + % this texinfo.tex file). We change the catcode of @ below to match. + \long\def\doignoretext##1@end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % Ignore braces, too, so mismatched braces don't cause trouble. + \catcode`\{ = 9 + \catcode`\} = 9 + % + % We must not have @c interpreted as a control sequence. + \catcode`\@ = 12 + % + % Make the letter c a comment character so that the rest of the line + % will be ignored. This way, the document can have (for example) + % @c @end ifinfo + % and the @end ifinfo will be properly ignored. + % (We've just changed @ to catcode 12.) + % + % But we can't do this if #1 is `macro', since that actually contains a c. + % Happily, none of the other conditionals have the letter `c' in their names! + \def\temp{#1}% + \ifx\temp\macrocsname \else + \catcode`\c = 14 + \fi + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{ (See ftp://ftp.gnu.ai.mit.edu/pub/gnu/TeX.README.)} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont + \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont + \let\tensf = \nullfont + % Similarly for index fonts (mostly for their use in + % smallexample) + \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont + \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont + \let\indsf = \nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}}% +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 + \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. + \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +% +\def\value{\begingroup + \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. + \valuexxx} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we \let\value to this in \indexdummies). Ones +% whose names contain - or _ still won't work, but we can't do anything +% about that. The command has to be fully expandable, since the result +% winds up in the index file. This means that if the variable's value +% contains other Texinfo commands, it's almost certain it will fail +% (although perhaps we could fix that with sufficient work to do a +% one-level expansion on the result, instead of complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']v}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text +% following, through the first @end iftex (etc.). Make `@end iftex' +% (etc.) valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\def\ifnothtml{\conditionalsucceed{ifnothtml}} +\def\ifnotinfo{\conditionalsucceed{ifnotinfo}} +\defineunmatchedend{iftex} +\defineunmatchedend{ifnothtml} +\defineunmatchedend{ifnotinfo} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +\def\donoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\setref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\unnumbnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\appendixnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \iflinks + \readauxfile + \opencontents + \fi % \openindices needs to do some work in any case. + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + % Just to be on the safe side, close the input stream before the \input. + \openin 1 texinfo.cnf + \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi + \closein1 + \temp + % + \comment % Ignore the actual filename. +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + +% \def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx} +% \def\macroxxx#1#2 \end macro{% +% \expandafter\gdef\macrotemp#1{#2}% +% \endgroup} + +%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx} +%\def\linemacroxxx#1#2 \end linemacro{% +%\let\parsearg=\relax +%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}% +%\expandafter\xdef\macrotemp{\parsearg\macrotempx}% +%\expandafter\gdef\macrotempx#1{#2}% +%\endgroup} + +%\def\butfirst#1{} + + +\message{fonts,} + +% Font-change commands. + +% Texinfo supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +% Use Computer Modern fonts at \magstephalf (11pt). +\newcount\mainmagstep +\mainmagstep=\magstephalf + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\setfont\textrm\rmshape{12}{1000} +\setfont\texttt\ttshape{12}{1000} +\else +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples (9pt). +% We actually use the slanted font rather than the italic, +% because texinfo normally uses the slanted fonts for that. +% Do not make many font distinctions in general in the index, since they +% aren't very useful. +\setfont\ninett\ttshape{9}{1000} +\setfont\indrm\rmshape{9}{1000} +\setfont\indit\slshape{9}{1000} +\let\indsl=\indit +\let\indtt=\ninett +\let\indttsl=\ninett +\let\indsf=\indrm +\let\indbf=\indrm +\setfont\indsc\scshape{10}{900} +\font\indi=cmmi9 +\font\indsy=cmsy9 + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} + +% Chapter (and unnumbered) fonts (17.28pt). +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad. +% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded. +% \setfont\ssecsl\slshape{10}{\magstep1} +% \setfont\ssectt\ttshape{10}{\magstep1} +% \setfont\ssecsf\sfshape{10}{\magstep1} + +%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx. +%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than +%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1. +%\setfont\ssectt\ttshape{10}{1315} +%\setfont\ssecsf\sfshape{10}{1315} + +%\let\ssecbf=\ssecrm + +% Subsection fonts (13.15pt). +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts, we +% don't bother to reset \scriptfont and \scriptscriptfont (which would +% also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? +\def\indexfonts{% + \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl + \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc + \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl + \resetmathfonts \setleading{12pt}} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartitalic +\let\dfn=\smartitalic +\let\emph=\smartitalic +\let\cite=\smartitalic + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp#1{`\tclose{#1}'\null} +\setfont\smallrm\rmshape{8}{1000} +\font\smallsy=cmsy9 +\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +\let\file=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ +\catcode`\-=\active +\catcode`\_=\active +\catcode`\|=\active +\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex} +% The following is used by \doprintindex to insure that long function names +% wrap around. It is necessary for - and _ to be active before the index is +% read from the file, as \entry parses the arguments long before \code is +% ever called. -- mycroft +% _ is always active; and it shouldn't be \let = to an _ that is a +% subscript character anyway. Then, @cindex @samp{_} (for example) +% fails. --karl +\global\def\indexbreaks{% + \catcode`\-=\active \let-\realdash +} +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\def\kbdinputstyle{\parsearg\kbdinputstylexxx} +\def\kbdinputstylexxx#1{% + \def\arg{#1}% + \ifx\arg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\arg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\arg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is kbdinputdistinct. (Too much of a hassle to call the macro, +% the catcodes are wrong for parsearg to work.) +\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl} + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% @url. Quotes do not seem necessary, so use \code. +\let\url=\code + +% @uref (abbreviation for `urlref') takes an optional second argument +% specifying the text to display. First (mandatory) arg is the url. +% Perhaps eventually put in a hypertex \special here. +% +\def\uref#1{\urefxxx #1,,\finish} +\def\urefxxx#1,#2,#3\finish{% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \unhbox0\ (\code{#1})% + \else + \code{#1}% + \fi +} + +% rms does not like the angle brackets --karl, 17may97. +% So now @email is just like @uref. +%\def\email#1{\angleleft{\tt #1}\angleright} +\let\email=\uref + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of +% @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +\def\r#1{{\rm #1}} % roman font +% Use of \lowercase was suggested. +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @pounds{} is a sterling sign. +\def\pounds{{\it\$}} + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm +% I deinstalled the following change because \cmr12 is undefined. +% This change was not in the ChangeLog anyway. --rms. +% \let\subtitlerm=\cmr12 + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefonts\rm ##1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks \evenheadline % Token sequence for heading line of even pages +\newtoks \oddheadline % Token sequence for heading line of odd pages +\newtoks \evenfootline % Token sequence for footing line of even pages +\newtoks \oddfootline % Token sequence for footing line of odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -\baselineskip + \global\advance\vsize by -\baselineskip +} + +\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{\number\day\space +\ifcase\month\or +January\or February\or March\or April\or May\or June\or +July\or August\or September\or October\or November\or December\fi +\space\number\year} + +% Use this if you want the Month Day, Year style of output. +%\def\today{\ifcase\month\or +%January\or February\or March\or April\or May\or June\or +%July\or August\or September\or October\or November\or December\fi +%\space\number\day, \number\year} + +% @settitle line... specifies the title of the document, for headings +% It generates no output of its own + +\def\thistitle{No Title} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % Be sure we are not still in the middle of a paragraph. + %{\parskip = 0in + %\par + %}% + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. Since that + % text will be indented by \tableindent, we make the item text be in + % a zero-width box. + \noindent + \rlap{\hskip -\tableindent\box0}\ignorespaces% + \endgroup% + \itemxneedsnegativevskiptrue% + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +%% Contains a kludge to get @end[description] to work +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a <number>. + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{In hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multitable or @end multitable do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% 2/1/96, to allow fractions to be given with more than one digit. +\def\pickupwholefraction#1 {\global\advance\colcount by1 % +\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}% +\setuptable} + +\newcount\colcount +\def\setuptable#1{\def\firstarg{#1}% +\ifx\firstarg\xendsetuptable\let\go\relax% +\else + \ifx\firstarg\xcolumnfractions\global\setpercenttrue% + \else + \ifsetpercent + \let\go\pickupwholefraction % In this case arg of setuptable + % is the decimal point before the + % number given in percent of hsize. + % We don't need this so we don't use it. + \else + \global\advance\colcount by1 + \setbox0=\hbox{#1 }% Add a normal word space as a separator; + % typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi% + \fi% +\ifx\go\pickupwholefraction\else\let\go\setuptable\fi% +\fi\go} + +% multitable syntax +\def\tab{&\hskip1sp\relax} % 2/2/96 + % tiny skip here makes sure this column space is + % maintained, even if it is never used. + +% @multitable ... @end multitable definitions: + +\def\multitable{\parsearg\dotable} +\def\dotable#1{\bgroup + \vskip\parskip + \let\item\crcr + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}% + % + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. + \everycr{\noalign{% + % + % \filbreak%% keeps underfull box messages off when table breaks over pages. + % Maybe so, but it also creates really weird page breaks when the table + % breaks over pages. Wouldn't \vfil be better? Wait until the problem + % manifests itself, so it can be fixed for real --karl. + \global\colcount=0\relax}}% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup&\global\advance\colcount by 1\relax + \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively marking + % characters. + \noindent\ignorespaces##\unskip\multistrut}\cr +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\ifdim\multitablelinespace=0pt +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\let\multistrut = \strut +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\else +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% The \closeout helps reduce unnecessary open files; the limit on the +% Acorn RISC OS is a mere 16 files. +\def\synindex#1 #2 {% + \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname + \expandafter\closeout\csname#1indfile\endcsname + \expandafter\let\csname#1indfile\endcsname=\synindexfoo + \expandafter\xdef\csname#1index\endcsname{% define \xxxindex + \noexpand\doindex{#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex#1 #2 {% + \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname + \expandafter\closeout\csname#1indfile\endcsname + \expandafter\let\csname#1indfile\endcsname=\synindexfoo + \expandafter\xdef\csname#1index\endcsname{% define \xxxindex + \noexpand\docodeindex{#2}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +\def\indexdummies{% +\def\ { }% +% Take care of the plain tex accent commands. +\def\"{\realbackslash "}% +\def\`{\realbackslash `}% +\def\'{\realbackslash '}% +\def\^{\realbackslash ^}% +\def\~{\realbackslash ~}% +\def\={\realbackslash =}% +\def\b{\realbackslash b}% +\def\c{\realbackslash c}% +\def\d{\realbackslash d}% +\def\u{\realbackslash u}% +\def\v{\realbackslash v}% +\def\H{\realbackslash H}% +% Take care of the plain tex special European modified letters. +\def\oe{\realbackslash oe}% +\def\ae{\realbackslash ae}% +\def\aa{\realbackslash aa}% +\def\OE{\realbackslash OE}% +\def\AE{\realbackslash AE}% +\def\AA{\realbackslash AA}% +\def\o{\realbackslash o}% +\def\O{\realbackslash O}% +\def\l{\realbackslash l}% +\def\L{\realbackslash L}% +\def\ss{\realbackslash ss}% +% Take care of texinfo commands likely to appear in an index entry. +% (Must be a way to avoid doing expansion at all, and thus not have to +% laboriously list every single command here.) +\def\@{@}% will be @@ when we switch to @ as escape char. +%\let\{ = \lbracecmd +%\let\} = \rbracecmd +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +%\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\result{\realbackslash result}% +\def\equiv{\realbackslash equiv}% +\def\expansion{\realbackslash expansion}% +\def\print{\realbackslash print}% +\def\error{\realbackslash error}% +\def\point{\realbackslash point}% +\def\copyright{\realbackslash copyright}% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\dotless##1{\realbackslash dotless {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\,##1{\realbackslash ,{##1}}% +\def\t##1{\realbackslash t {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\sc##1{\realbackslash sc {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +% +% Handle some cases of @value -- where the variable name does not +% contain - or _, and the value does not contain any +% (non-fully-expandable) commands. +\let\value = \expandablevalue +% +\unsepspaces +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +% Just ignore accents. +\let\,=\indexdummyfont +\let\"=\indexdummyfont +\let\`=\indexdummyfont +\let\'=\indexdummyfont +\let\^=\indexdummyfont +\let\~=\indexdummyfont +\let\==\indexdummyfont +\let\b=\indexdummyfont +\let\c=\indexdummyfont +\let\d=\indexdummyfont +\let\u=\indexdummyfont +\let\v=\indexdummyfont +\let\H=\indexdummyfont +\let\dotless=\indexdummyfont +% Take care of the plain tex special European modified letters. +\def\oe{oe}% +\def\ae{ae}% +\def\aa{aa}% +\def\OE{OE}% +\def\AE{AE}% +\def\AA{AA}% +\def\o{o}% +\def\O{O}% +\def\l{l}% +\def\L{L}% +\def\ss{ss}% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +\def\@{@}% +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other + @gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% For \ifx comparisons. +\def\emptymacro{\empty} + +% Most index entries go through here, but \dosubind is the general case. +% +\def\doind#1#2{\dosubind{#1}{#2}\empty} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% \empty if called from \doind, as we usually are. The main exception +% is with defuns, which call us directly. +% +\def\dosubind#1#2#3{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% + \fi + {% + \count255=\lastpenalty + {% + \indexdummies % Must do this here, since \bf, etc expand at this stage + \escapechar=`\\ + {% + \let\folio = 0% We will expand all macros now EXCEPT \folio. + \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + \def\thirdarg{#3}% + % + % If third arg is present, precede it with space in sort key. + \ifx\thirdarg\emptymacro + \let\subentry = \empty + \else + \def\subentry{ #3}% + \fi + % + % First process the index-string with all font commands turned off + % to get the string to sort by. + {\indexnofonts \xdef\indexsorttmp{#2\subentry}}% + % + % Now produce the complete index entry, with both the sort key and the + % original text, including any font commands. + \toks0 = {#2}% + \edef\temp{% + \write\csname#1indfile\endcsname{% + \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% + }% + % + % If third (subentry) arg is present, add it to the index string. + \ifx\thirdarg\emptymacro \else + \toks0 = {#3}% + \edef\temp{\temp{\the\toks0}}% + \fi + % + % If a skip is the last thing on the list now, preserve it + % by backing up by \lastskip, doing the \write, then inserting + % the skip again. Otherwise, the whatsit generated by the + % \write will make \lastskip zero. The result is that sequences + % like this: + % @end defun + % @tindex whatever + % @defun ... + % will have extra space inserted, because the \medbreak in the + % start of the @defun won't see the skip inserted by the @end of + % the previous defun. + \iflinks + \skip0 = \lastskip \ifdim\lastskip = 0pt \else \vskip-\lastskip \fi + \temp + \ifdim\skip0 = 0pt \else \vskip\skip0 \fi + \fi + }% + }% + \penalty\count255 + }% +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\def\printindex{\parsearg\doprintindex} +\def\doprintindex#1{\begingroup + \dobreak \chapheadingskip{10000}% + % + \indexfonts \rm + \tolerance = 9500 + \indexbreaks + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + (Index is nonexistent) + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + (Index is empty) + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\rawbackslashxx}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +% Same as \bigskipamount except no shrink. +% \balancecolumns gets confused if there is any shrink. +\newskip\initialskipamount \initialskipamount 12pt plus4pt + +\def\initial #1{% +{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +\ifdim\lastskip<\initialskipamount +\removelastskip \penalty-200 \vskip \initialskipamount\fi +\line{\secbf#1\hfill}\kern 2pt\penalty10000}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry #1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent=2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ #2% The page number ends the paragraph. + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {\global\setbox\partialpage = \vbox{% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case, we must prevent the second \partialpage from + % simply overwriting the first, causing us to lose the page. + % This will preserve it until a real output routine can ship it + % out. Generally, \partialpage will be empty when this runs and + % this will be a no-op. + \unvbox\partialpage + % + % Unvbox the main output page. + \unvbox255 + \kern-\topskip \kern\baselineskip + }}% + \eject + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +\def\pagesofar{% + % Re-output the contents of the output page -- any previous material, + % followed by the two boxes we just split. + \unvbox\partialpage + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}% +} +\def\enddoublecolumns{% + \output = {\balancecolumns}\eject % split what we have + \endgroup % started in \begindoublecolumns + % + % Back to normal single-column typesetting, but take account of the + % fact that we just accumulated some stuff on the output page. + \pagegoal = \vsize +} +\def\balancecolumns{% + % Called at the end of the double column material. + \setbox0 = \vbox{\unvbox255}% + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {\vbadness=10000 \loop + \global\setbox3=\copy0 + \global\setbox1=\vsplit3 to\dimen@ + \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt + \repeat}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Define chapters, sections, etc. + +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +\def\appendixletter{\char\the\appendixno} + +\newwrite\contentsfile +% This is called from \setfilename. +\def\opencontents{\openout\contentsfile = \jobname.toc } + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise + +\def\thischapter{} \def\thissection{} +\def\seccheck#1{\ifnum \pageno<0 + \errmessage{@#1 not allowed after generating table of contents}% +\fi} + +\def\chapternofonts{% + \let\rawbackslash=\relax + \let\frenchspacing=\relax + \def\result{\realbackslash result}% + \def\equiv{\realbackslash equiv}% + \def\expansion{\realbackslash expansion}% + \def\print{\realbackslash print}% + \def\TeX{\realbackslash TeX}% + \def\dots{\realbackslash dots}% + \def\result{\realbackslash result}% + \def\equiv{\realbackslash equiv}% + \def\expansion{\realbackslash expansion}% + \def\print{\realbackslash print}% + \def\error{\realbackslash error}% + \def\point{\realbackslash point}% + \def\copyright{\realbackslash copyright}% + \def\tt{\realbackslash tt}% + \def\bf{\realbackslash bf}% + \def\w{\realbackslash w}% + \def\less{\realbackslash less}% + \def\gtr{\realbackslash gtr}% + \def\hat{\realbackslash hat}% + \def\char{\realbackslash char}% + \def\tclose##1{\realbackslash tclose{##1}}% + \def\code##1{\realbackslash code{##1}}% + \def\samp##1{\realbackslash samp{##1}}% + \def\r##1{\realbackslash r{##1}}% + \def\b##1{\realbackslash b{##1}}% + \def\key##1{\realbackslash key{##1}}% + \def\file##1{\realbackslash file{##1}}% + \def\kbd##1{\realbackslash kbd{##1}}% + % These are redefined because @smartitalic wouldn't work inside xdef. + \def\i##1{\realbackslash i{##1}}% + \def\cite##1{\realbackslash cite{##1}}% + \def\var##1{\realbackslash var{##1}}% + \def\emph##1{\realbackslash emph{##1}}% + \def\dfn##1{\realbackslash dfn{##1}}% +} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + + +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{\seccheck{chapter}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{\putwordChapter \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash chapentry{\the\toks0}{\the\chapno}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\donoderef % +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{\seccheck{appendix}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 \message{Appendix \appendixletter}% +\chapmacro {#1}{\putwordAppendix{} \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash chapentry{\the\toks0}% + {\putwordAppendix{} \appendixletter}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\appendixnoderef % +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +}} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +\outer\def\top{\parsearg\unnumberedyyy} +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{\seccheck{unnumbered}% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% This used to be simply \message{#1}, but TeX fully expands the +% argument to \message. Therefore, if #1 contained @-commands, TeX +% expanded them. For example, in `@unnumbered The @cite{Book}', TeX +% expanded @cite (which turns out to cause errors because \cite is meant +% to be executed, not expanded). +% +% Anyway, we don't want the fully-expanded definition of @cite to appear +% as a result of the \message, we just want `@cite' itself. We use +% \the<toks register> to achieve this: TeX expands \the<toks> only once, +% simply yielding the contents of the <toks register>. +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash unnumbchapentry{\the\toks0}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\unnumbnoderef % +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +}} + +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{\seccheck{section}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash secentry % +{\the\toks0}{\the\chapno}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{\seccheck{appendixsection}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash secentry % +{\the\toks0}{\appendixletter}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{\seccheck{unnumberedsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash unnumbsecentry{\the\toks0}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{\seccheck{subsection}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash subsecentry % +{\the\toks0}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{\seccheck{appendixsubsec}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash subsecentry % +{\the\toks0}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}% +\plainsubsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash unnumbsubsecentry{\the\toks0}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{\seccheck{subsubsection}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash subsubsecentry{\the\toks0} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno} + {\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash subsubsecentry{\the\toks0}% + {\appendixletter} + {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}% +\plainsubsubsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\toks0 = {#1}% +\edef\temp{{\realbackslash unnumbsubsubsecentry{\the\toks0}{\noexpand\folio}}}% +\escapechar=`\\% +\iflinks \write\contentsfile\temp \fi +\unnumbnoderef % +\penalty 10000 % +}} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and +% such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +% @heading, @subheading, @subsubheading. +\def\heading{\parsearg\plainsecheading} +\def\subheading{\parsearg\plainsubsecheading} +\def\subsubheading{\parsearg\plainsubsubsecheading} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{ +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{ +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +% Plain chapter opening. +% #1 is the text, #2 the chapter number or empty if unnumbered. +\def\chfplain#1#2{% + \pchapsepmacro + {% + \chapfonts \rm + \def\chapnum{#2}% + \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% Plain opening for unnumbered. +\def\unnchfplain#1{\chfplain{#1}{}} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerchfplain#1{{% + \def\centerparametersmaybe{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt + }% + \chfplain{#1}{}% +}} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 % +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + + +% Section titles. +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} +\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} +\def\plainsecheading#1{\sectionheading{sec}{}{#1}} + +% Subsection titles. +\newskip \subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} +\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} +\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} + +% Subsubsection titles. +\let\subsubsecheadingskip = \subsecheadingskip +\let\subsubsecheadingbreak = \subsecheadingbreak +\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} +\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} + + +% Print any size section title. +% +% #1 is the section type (sec/subsec/subsubsec), #2 is the section +% number (maybe empty), #3 the text. +\def\sectionheading#1#2#3{% + {% + \expandafter\advance\csname #1headingskip\endcsname by \parskip + \csname #1headingbreak\endcsname + }% + {% + % Switch to the right set of fonts. + \csname #1fonts\endcsname \rm + % + % Only insert the separating space if we have a section number. + \def\secnum{#2}% + \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 % zero if no section number + \unhbox0 #3}% + }% + \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak +} + + +\message{toc printing,} +% Finish up the main text and prepare to read what we've written +% to \contentsfile. + +\newskip\contentsrightmargin \contentsrightmargin=1in +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund <tege@matematik.su.se> + \contentsalignmacro + \immediate\closeout \contentsfile + \ifnum \pageno>0 + \pageno = -1 % Request roman numbered pages. + \fi + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + % We can't do this, because then an actual ^ in a section + % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. + %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. +} + + +% Normal (long) toc. +\outer\def\contents{% + \startcontents{\putwordTableofContents}% + \input \jobname.toc + \endgroup + \vfill \eject +} + +% And just the chapters. +\outer\def\summarycontents{% + \startcontents{\putwordShortContents}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \input \jobname.toc + \endgroup + \vfill \eject +} +\let\shortcontents = \summarycontents + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +\setbox0 = \hbox{\shortcontrm \putwordAppendix } +\newdimen\shortappendixwidth \shortappendixwidth = \wd0 + +\def\shortchaplabel#1{% + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +\def\tocentry#1#2{\begingroup + \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks + % Do not use \turnoffactive in these arguments. Since the toc is + % typeset in cmr, so characters such as _ would come out wrong; we + % have to do the usual translation tricks. + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% Adapted from the TeXbook's \boxit. +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} + +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} + +% The @error{} command. +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie + \catcode `\%=14 + \catcode 43=12 % plus + \catcode`\"=12 + \catcode`\==12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\*=\ptexstar + \let\t=\ptext + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\long\def\cartouche{% +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% To ending an @example-like environment, we first end the paragraph +% (via \afterenvbreak's vertical glue), and then the group. That way we +% keep the zero \parskip that the environments set -- \parskip glue +% will be inserted at the beginning of the next paragraph in the +% document, after the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup}% + +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + % Make @kbd do something special, if requested. + \let\kbdfont\kbdexamplefont + \rawbackslash % have \ input char produce \ char from current font + \gobble +} + +% Define the \E... control sequence only if we are inside the +% environment, so the error checking in \end will work. +% +% We must call \lisp last in the definition, since it reads the +% return following the @example (or whatever) command. +% +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} +\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp. This is not used unless the @smallbook +% command is given. Originally contributed by Pavel@xerox. +% +\def\smalllispx{\begingroup + \nonfillstart + \let\Esmalllisp = \nonfillfinish + \let\Esmallexample = \nonfillfinish + % + % Smaller fonts for small examples. + \indexfonts \tt + \rawbackslash % make \ output the \ character from the current font (tt) + \gobble +} + +% This is @display; same as @lisp except use roman font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% This is @format; same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @flushleft (same as @format) and @flushright. +% +\def\flushleft{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushleft = \nonfillfinish + \gobble +} +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble} + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \singlespace + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active +\catcode`\[=\active \catcode`\]=\active} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested + \global\advance\parencount by 1 +} +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. + % also in that case restore the outer-level definition of (. + \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi + \global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 } +\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 } +\def\ampnr{\&} +\def\lbrb{{\bf\char`\[}} +\def\rbrb{{\bf\char`\]}} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\dimen3=\rightskip +\advance\dimen3 by -\defbodyindent +\noindent % +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 % +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 \advance \hsize by -\dimen3 +\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % 61 is `=' +\obeylines\activeparens\spacesplit#3} + +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence for consecutive fns (which we define). +% #3 is the control sequence to call to resume processing. +% #4, delimited by the space, is the class name. +% +\def\defmethparsebody#1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +% @deftypemethod has an extra argument that nothing else does. Sigh. +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence for consecutive fns (which we define). +% #3 is the control sequence to call to resume processing. +% #4, delimited by the space, is the class name. +% #5 is the method's return type. +% +\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +% This is used for \def{tp,vr}parsebody. It could probably be used for +% some of the others, too, with some judicious conditionals. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does. +% +\def\removeemptybraces\empty#1\relax{#1} + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + #1{\removeemptybraces#2\relax}{#3}% +}% + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs #1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\hyphenchar\tensl=0 +#1% +\hyphenchar\tensl=45 +\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Function}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}% +\deftypefunargs {#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$$$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$$$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Macro}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Special Form}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% This definition is run if you use @defunx +% anywhere other than immediately after a @defun or @defunx. + +\def\deffnx #1 {\errmessage{@deffnx in invalid context}} +\def\defunx #1 {\errmessage{@defunx in invalid context}} +\def\defmacx #1 {\errmessage{@defmacx in invalid context}} +\def\defspecx #1 {\errmessage{@defspecx in invalid context}} +\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypemethodx #1 {\errmessage{@deftypemethodx in invalid context}} +\def\deftypefunx #1 {\errmessage{@deftypeunx in invalid context}} + +% @defmethod, and so on + +% @defop CATEGORY CLASS OPERATION ARG... + +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} + +\def\defopheader #1#2#3{% +\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index +\begingroup\defname {#2}{\defoptype{} on #1}% +\defunargs {#3}\endgroup % +} + +% @deftypemethod CLASS RETURN-TYPE METHOD ARG... +% +\def\deftypemethod{% + \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} +% +% #1 is the class name, #2 the data type, #3 the method name, #4 the args. +\def\deftypemethodheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @defmethod == @defop Method +% +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} +% +% #1 is the class name, #2 the method name, #3 the args. +\def\defmethodheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{#2}{\putwordMethodon\ \code{#1}}% + \defunargs{#3}% + \endgroup +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype{} of #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar == @defcv {Instance Variable} + +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} + +\def\defivarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{Instance Variable of #1}% +\defvarargs {#3}\endgroup % +} + +% These definitions are run if you use @defmethodx, etc., +% anywhere other than immediately after a @defmethod, etc. + +\def\defopx #1 {\errmessage{@defopx in invalid context}} +\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} +\def\defcvx #1 {\errmessage{@defcvx in invalid context}} +\def\defivarx #1 {\errmessage{@defivarx in invalid context}} + +% Now @defvar + +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{Variable}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{User Option}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name, perhaps followed by text that +% is actually part of the data type, which should not be put into the index. +\def\deftypevarheader #1#2{% +\dovarind#2 \relax% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} +\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\dovarind#3 \relax% +\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% This definition is run if you use @defvarx +% anywhere other than immediately after a @defvar or @defvarx. + +\def\defvrx #1 {\errmessage{@defvrx in invalid context}} +\def\defvarx #1 {\errmessage{@defvarx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% This definition is run if you use @deftpx, etc +% anywhere other than immediately after a @deftp, etc. + +\def\deftpx #1 {\errmessage{@deftpx in invalid context}} + + +\message{macros,} +% @macro. +% The basic scheme is as follows: +% We read the first line and split it up into macro name and parameter +% list. We then walk the parameter list defining control sequences +% named \MAC@<macro name><parameter name>. Each expands to another +% control sequence named \MAC@<macro name>.<parameter number>. Those +% control sequences will be defined at macro runtime to be the +% parameter expansion text. +% +% The body is then read in as a single argument in a context where \ +% is an active character, and the cs \MACb.<macro name> is defined as +% the macro body. The active character \ takes one argument delimited +% by another \, and uses it to index the table of macro arguments +% described above. +% +% Finally, we define a control sequence \<macro name> which calls one +% of the six (!) macro execution commands. These six commands +% correspond to recursive and nonrecursive macros with no, one, and +% many arguments. They all take one argument, <macro name>, set up +% the environment appropriately, and call the real macro. +% +% \macsave@<macro name> holds the old definition of \<macro name>. + +\newcount\paramno +\newtoks\macname + +% This does \let #1 = #2, except with \csnames. +\def\cslet#1#2{% +\expandafter\expandafter\expandafter +\let +\expandafter\expandafter +\csname#1\endcsname +\csname#2\endcsname} + +% We have to play lots of games with the catcodes. Initially { and } +% are made `other' so that \splitarg (below) can use them as argument +% delimiters. Then - is made a letter so that \iimacro can recognize +% @allow-recursion. +\def\macro{\bgroup\catcode`\{=\other\catcode`\}=\other\parsearg\imacro} +\def\imacro#1{\egroup % started in \macro + \splitarg{#1}% now \macname is the macname and \toks0 the arglist + \paramno=0% + \edef\tmp{\the\toks0}% + \ifx\tmp\empty % no arguments + \else + \expandafter\parsemargdef \the\toks0;% + \fi + \bgroup\catcode`\-=11\global\futurelet\nxt\iimacro} + +% \imacro has noted whether the macro takes one, two, or many +% arguments (in \paramno). \iimacro figures out whether it's +% recursive, and then uses the argument count and the recursivity to +% select one of the six macro execution sequences. Then we save the +% original definition of @foo in \macsave@foo, and define @foo to call +% the selected execution sequence. \edef conveniently just expands +% the token registers, not the deep structure. +\def\iimacro{% + \egroup % started in \imacro + \ifx\nxt\allowrecur + \let\next\parserbody + \toks0=\expandafter{\csname dormacro\ifcase\paramno na\or oa\fi\endcsname}% + \else + \let\next\parsebody + \toks0=\expandafter{\csname domacro\ifcase\paramno na\or oa\fi\endcsname}% + \fi + \expandafter\ifx \csname macsave@\the\macname\endcsname \relax + \cslet{macsave@\the\macname}{\the\macname}% + \else + \errmessage{warning: redefining macro \the\macname}% + \fi + \expandafter\edef\csname\the\macname\endcsname{\the\toks0{\the\macname}}% +\next} + +% @allow-recursion is noticed and handled by \iimacro. It should +% never actually be executed. It has two names so we don't need +% strange catcodes while defining \iimacro. +\def\allowrecur{\errmessage{Internal error: \noexpand\allowrecur executed}} +{\catcode`\-=11\global\let\allow-recursion\allowrecur} + +% unmacro just restores the old meaning; the MAC@<macname> macros +% remain defined. (Memory leak!) \norecurse is defined below, near +% the execution commands. +\def\unmacro{\parsearg\iunmacro} +\def\iunmacro#1{\macname={#1} \norecurse} + +% We need {} to be ordinary inside these commands. [] are temporary +% grouping symbols. +\begingroup +\catcode`\{=\other \catcode`\}=\other +\catcode`\[=1 \catcode`\]=2 + +% @macro can be called with or without a brace-surrounded macro +% argument list. These three sequences extract the macro name and arg +% list in hopefully all cases. *Note, anything on the line after the +% first pair of braces will be thrown out. +\gdef\splitarg#1[\isplitarg|#1 {}|] +\gdef\isplitarg|#1 {#2}#3|[% + \toks0=[#2]% + \edef\tmp[\the\toks0]% + \ifx\tmp\empty + \isplitargnospaces|#1{}|% + \else + \macname=[#1]% + \fi] +\gdef\isplitargnospaces|#1{#2}#3|[\macname=[#1] \toks0=[#2]] + +% \parsebrace gets around the situation produced by \braceorline +% (below) where the { has the wrong catcode because of \futurelet. +% The \egroup matches a \bgroup in \braceorline. +\gdef\parsebrace#1{#2}[\egroup\let\next=#1\next[#2]] + +\global\let\brace={ % used by \braceorline, below + +\endgroup + + +% Argument parsing. +% These routines iterate over a comma-separated list defining +% tokens that map macro formal to actual parameters. +% \parsemargdef sets the formal -> positional correspondence at macro +% definition time; \parsemarg sets positional -> actual at runtime. +% +% The definitions are not symmetric because the callers have the +% argument list in different places (token register and #arg) +\def\parsemargdef#1;{\paramno=0\iparsemargdef#1,;,} +\def\iparsemargdef#1,{% + \if#1;\let\next=\relax + \else \let\next=\iparsemargdef + \advance\paramno by 1% + \expandafter\edef\csname MAC@\the\macname#1\endcsname + {\csname MAC@\the\macname.\the\paramno\endcsname}% + \fi\next} + +\def\parsemarg#1{\paramno=1\iparsemarg#1,;,} +\def\iparsemarg#1,{% + \if#1;\let\next=\relax + \else \let\next=\iparsemarg + \expandafter\def\csname MAC@\the\macname.\the\paramno\endcsname{#1}% + \advance\paramno by 1% + \fi\next} + +% Argument substitution. +% \ is active when the body is read and tokenized; it converts its +% argument to a macro-argument name and expands it. We use | as a +% temporary escape character. +{ +\catcode`\|=0 |catcode`|\=|active +|gdef\#1\{|csname MAC@|the|macname#1|endcsname} +} + +% These sequences read and save the macro body. \parserbody absorbs +% the @allow-recursion in its argument, and then falls through to +% \parsebody. +\def\parsebody{\begingroup\catcode`\\=\active\iparsebody} +\def\parserbody#1{\parsebody} + +% \iparsebody reads the entire macro in as an argument. \ was made +% active by \parsebody while the reading occurs. +\long\def\iparsebody#1 \end macro% The space eats the final CR. +{\endgroup % started in \parsebody +\expandafter\def\csname MACb.\the\macname \endcsname{#1}} + +% These six sequences execute recursive and nonrecursive macros of no, +% one, and many arguments. We need to distinguish one arg from many +% args because a one-argument macro invoked with no arguments gets the +% rest of the line as its argument. +% +% Please note that all macros are executed inside a group, so any +% changes made by a macro (@set, etc.) won't stick. +\def\dormacrona#1{\begingroup\macname={#1}\idomacro{}} +\def\dormacrooa#1{\begingroup\macname={#1}\braceorline} +\def\dormacro#1{\begingroup\macname={#1}\idomacro} + +\def\domacrona#1{\begingroup\macname={#1}\norecurse\idomacro{}} +\def\domacrooa#1{\begingroup\macname={#1}\norecurse\braceorline} +\def\domacro#1{\begingroup\macname={#1}\norecurse\idomacro} + +% some helpers: +\def\norecurse{\cslet{\the\macname}{macsave@\the\macname}} +\def\idomacro#1{\parsemarg{#1}\csname MACb.\the\macname\endcsname\endgroup} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to \idomacro. \parsebrace is +% defined above, near \splitarg, in a strange catcode environment; +% this is necessary because \futurelet freezes the catcode of the +% peeked-at character. +\def\braceorline{\bgroup +\catcode`\{=\other\catcode`\}=\other \futurelet\nxt\ibraceorline} +\def\ibraceorline{% +\ifx\nxt\brace + \expandafter\parsebrace + \else + \egroup \expandafter\parsearg + \fi \idomacro} + + +\message{cross references,} +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @setref{foo} defines a cross-reference point named foo. + +\def\setref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ysectionnumberandtype}} + +\def\unnumbsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ynothing}} + +\def\appendixsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Yappendixletterandtype}} + +% \xref, \pxref, and \ref generate cross-references to specified points. +% For \xrefX, #1 is the node name, #2 the name of the Info +% cross-reference, #3 the printed node name, #4 the name of the Info +% file, #5 the name of the printed manual. All but the node name can be +% omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1>0pt% + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' in \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\normalturnoffactive \refx{#1-snt}{}}% + \space [\printednodename],\space + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \normalturnoffactive so that punctuation chars such as underscore +% and backslash work in node names. (\turnoffactive doesn't do \.) +\def\dosetq#1#2{% + {\let\folio=0 + \normalturnoffactive + \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}% + \iflinks + \next + \fi + }% +} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thissection} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. +% +\def\xrdef#1{\begingroup + % Reenable \ as an escape while reading the second argument. + \catcode`\\ = 0 + \afterassignment\endgroup + \expandafter\gdef\csname X#1\endcsname +} + +% Read the last existing aux file, if any. No error if none exists. +\def\readauxfile{\begingroup + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + \catcode`\@=\other + \catcode`\^=\other + % It was suggested to define this as 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % Make the characters 128-255 be printing characters + {% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% + }% + % The aux file uses ' as the escape (for now). + % Turn off \ as an escape so we do not lose on + % entries which were dumped with control sequences in their names. + % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ + % Reference to such entries still does not work the way one would wish, + % but at least they do not bomb out when the aux file is read in. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\%=\other + \catcode`\'=0 + \catcode`\\=\other + % + \openin 1 \jobname.aux + \ifeof 1 \else + \closein 1 + \input \jobname.aux + \global\havexrefstrue + \global\warnedobstrue + \fi + % Open the new aux file. TeX will close it automatically at exit. + \openout\auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset and anything else that uses +% \parseargline fail inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +\long\gdef\footnotezzz{\insert\footins\bgroup + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + % Hang the footnote text off the number. + \hang + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t + \else\let\next\f@t\fi \next} +\def\f@@t{\bgroup\aftergroup\@foot\let\next} +\def\f@t#1{#1\@foot} +\def\@foot{\strut\egroup} + +}%end \catcode `\@=11 + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + \closein 1 + % Do not bother showing banner with post-v2.7 epsf.tex (available in + % doc/epsf.tex until it shows up on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +% +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://ftp.tug.org/tex/epsf.tex.} +% +% Only complain once about lack of epsf.tex. +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is just the usual extra ignored arg for parsing this stuff. +\def\imagexxx#1,#2,#3,#4\finish{% + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + % If the image is by itself, center it. + \ifvmode + \centerline{\epsfbox{#1.eps}}% + \else + \epsfbox{#1.eps}% + \fi +} + +% End of control word definitions. + + +\message{and turning on texinfo input format.} + +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% Set some numeric style parameters, for 8.5 x 11 format. + +\hsize = 6in +\hoffset = .25in +\newdimen\defaultparindent \defaultparindent = 15pt +\parindent = \defaultparindent +\parskip 3pt plus 2pt minus 1pt +\setleading{13.2pt} +\advance\topskip by 1.2cm + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness=10000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. This makes it come to about 9pt for the 8.5x11 format. +% +\ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% +\else + \emergencystretch = \hsize + \divide\emergencystretch by 45 +\fi + +% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) +\def\smallbook{ + \global\chapheadingskip = 15pt plus 4pt minus 2pt + \global\secheadingskip = 12pt plus 3pt minus 2pt + \global\subsecheadingskip = 9pt plus 2pt minus 2pt + % + \global\lispnarrowing = 0.3in + \setleading{12pt} + \advance\topskip by -1cm + \global\parskip 2pt plus 1pt + \global\hsize = 5in + \global\vsize=7.5in + \global\tolerance=700 + \global\hfuzz=1pt + \global\contentsrightmargin=0pt + \global\deftypemargin=0pt + \global\defbodyindent=.5cm + % + \global\pagewidth=\hsize + \global\pageheight=\vsize + % + \global\let\smalllisp=\smalllispx + \global\let\smallexample=\smalllispx + \global\def\Esmallexample{\Esmalllisp} +} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{ +\global\tolerance=700 +\global\hfuzz=1pt +\setleading{12pt} +\global\parskip 15pt plus 1pt + +\global\vsize= 53\baselineskip +\advance\vsize by \topskip +%\global\hsize= 5.85in % A4 wide 10pt +\global\hsize= 6.5in +\global\outerhsize=\hsize +\global\advance\outerhsize by 0.5in +\global\outervsize=\vsize +\global\advance\outervsize by 0.6in + +\global\pagewidth=\hsize +\global\pageheight=\vsize +} + +\bindingoffset=0pt +\normaloffset=\hoffset +\pagewidth=\hsize +\pageheight=\vsize + +% Allow control of the text dimensions. Parameters in order: textheight; +% textwidth; voffset; hoffset; binding offset; topskip. +% All require a dimension; +% header is additional; added length extends the bottom of the page. + +\def\changepagesizes#1#2#3#4#5#6{ + \global\vsize= #1 + \global\topskip= #6 + \advance\vsize by \topskip + \global\voffset= #3 + \global\hsize= #2 + \global\outerhsize=\hsize + \global\advance\outerhsize by 0.5in + \global\outervsize=\vsize + \global\advance\outervsize by 0.6in + \global\pagewidth=\hsize + \global\pageheight=\vsize + \global\normaloffset= #4 + \global\bindingoffset= #5} + +% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin +% 29mm, hence bottom margin 28mm, nominal side margin 3cm. +\def\afourlatex + {\global\tolerance=700 + \global\hfuzz=1pt + \setleading{12pt} + \global\parskip 15pt plus 1pt + \advance\baselineskip by 1.6pt + \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm} + } + +% Use @afourwide to print on European A4 paper in wide format. +\def\afourwide{\afourpaper +\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{@let"=@normaldoublequote +@let\=@realbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +@def@normalturnoffactive{@let"=@normaldoublequote +@let\=@normalbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active @catcode`@_=@active} + +% These look ok in all fonts, so just make them not special. The @rm below +% makes sure that the current font starts out as the newly loaded cmr10 +@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other + +@textfonts +@rm + +@c Local variables: +@c page-delimiter: "^\\\\message" +@c End: diff --git a/doc/version.texi b/doc/version.texi new file mode 100644 index 0000000..4e5b91a --- /dev/null +++ b/doc/version.texi @@ -0,0 +1,3 @@ +@set UPDATED 6 May 2000 +@set EDITION 0.10.36 +@set VERSION 0.10.36 |