1 /*@z01.c:Supervise:StartSym, AllowCrossDb, etc.@******************************/
2 /*                                                                           */
3 /*  THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.39)                       */
4 /*  COPYRIGHT (C) 1991, 2008 Jeffrey H. Kingston                             */
5 /*                                                                           */
6 /*  Jeffrey H. Kingston (jeff@it.usyd.edu.au)                                */
7 /*  School of Information Technologies                                       */
8 /*  The University of Sydney 2006                                            */
9 /*  AUSTRALIA                                                                */
10 /*                                                                           */
11 /*  This program is free software; you can redistribute it and/or modify     */
12 /*  it under the terms of the GNU General Public License as published by     */
13 /*  the Free Software Foundation; either Version 3, or (at your option)      */
14 /*  any later version.                                                       */
15 /*                                                                           */
16 /*  This program is distributed in the hope that it will be useful,          */
17 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
18 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
19 /*  GNU General Public License for more details.                             */
20 /*                                                                           */
21 /*  You should have received a copy of the GNU General Public License        */
22 /*  along with this program; if not, write to the Free Software              */
23 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA   */
24 /*                                                                           */
25 /*  FILE:         z01.c                                                      */
26 /*  MODULE:       Supervise                                                  */
27 /*  EXTERNS:      main(), StartSym, GalleySym, ForceGalleySym, InputSym,     */
28 /*                PrintSym, AllowCrossDb                                     */
29 /*                                                                           */
30 /*****************************************************************************/
31 #include "externs.h"
32 #include <signal.h>
33 
34 /* On DOS/Win32 we need to set binary mode on stdout (Uwe) */
35 #if OS_DOS
36 #include <io.h>
37 #include <fcntl.h>
38 #ifdef __DJGPP__
39 #define _setmode(fd, mode)     setmode((fd), (mode))
40 #define _fileno(stream)        fileno((stream))
41 #endif
42 #endif
43 
44 /*****************************************************************************/
45 /*                                                                           */
46 /*  MemCheck - check this memory location                                    */
47 /*                                                                           */
48 /*****************************************************************************/
49 
50 POINTER MemCheck = 0;
51 
52 
53 /*****************************************************************************/
54 /*                                                                           */
55 /*  StartSym        the symbol table entry for \Start (overall scope)        */
56 /*  GalleySym       the symbol table entry for @Galley                       */
57 /*  ForceGalleySym  the symbol table entry for @ForceGalley                  */
58 /*  InputSym        the symbol table entry for @LInput                       */
59 /*  PrintSym        the symbol table entry for \Print (root target)          */
60 /*  OptGallSym      the symbol table entry for @OptGall (optimal galley rec) */
61 /*  FilterInSym     the symbol table entry for @FilterIn                     */
62 /*  FilterOutSym    the symbol table entry for @FilterOut                    */
63 /*  FilterErrSym    the symbol table entry for @FilterErr                    */
64 /*                                                                           */
65 /*****************************************************************************/
66 
67 OBJECT StartSym, GalleySym, ForceGalleySym, InputSym, PrintSym, OptGallSym,
68        FilterInSym, FilterOutSym, FilterErrSym, VerbatimSym, RawVerbatimSym;
69 
70 
71 /*****************************************************************************/
72 /*                                                                           */
73 /*  BackEnd             The back end (PostScript, PDF, etc.) to use          */
74 /*  CommandOptions      Command-line options (ACAT of objects)               */
75 /*  UseCollate          Use local collation sequence rather than ASCII       */
76 /*  AllowCrossDb        Allow references to OldCrossDb and NewCrossDb        */
77 /*  InMemoryDbIndexes   True if cr database index file is to be in-memory    */
78 /*  Kern                Do kerning                                           */
79 /*  SafeExecution       Execute safely, i.e. prohibit system() calls         */
80 /*  AltErrorFormat      Use alternative error message format                 */
81 /*  InitializeAll       TRUE if this is an initializing run.                 */
82 /*  MsgCat              category for locale-specific messages                */
83 /*  TotalWordCount      total number of words printed                        */
84 /*                                                                           */
85 /*****************************************************************************/
86 
87 BACK_END BackEnd;
88 OBJECT CommandOptions;
89 BOOLEAN UseCollate;
90 BOOLEAN AllowCrossDb;
91 BOOLEAN InMemoryDbIndexes;
92 BOOLEAN Kern;
93 BOOLEAN SafeExecution;
94 BOOLEAN	AltErrorFormat;
95 BOOLEAN InitializeAll;
96 #if LOCALE_ON
97 nl_catd MsgCat;
98 #endif
99 int TotalWordCount;
100 
101 
102 /*****************************************************************************/
103 /*                                                                           */
104 /*  static OBJECT load(xstr, xpredefined, xleft, xright, xindef, xprec)      */
105 /*                                                                           */
106 /*  Load a predefined operator with these attributes into the symbol table.  */
107 /*  If the operator has parameters, load symbols for those also.             */
108 /*                                                                           */
109 /*****************************************************************************/
110 
load(FULL_CHAR * xstr,unsigned xpre,BOOLEAN xleft,BOOLEAN xright,BOOLEAN xindef,unsigned char xprec)111 static OBJECT load(FULL_CHAR *xstr, unsigned xpre,
112 BOOLEAN xleft, BOOLEAN xright, BOOLEAN xindef, unsigned char xprec)
113 { OBJECT s;
114   s = InsertSym(xstr, LOCAL, no_fpos, xprec, xindef, FALSE, xpre,
115 	StartSym, nilobj);
116   if( xleft )  InsertSym( AsciiToFull("pa"), LPAR, no_fpos, DEFAULT_PREC,
117     FALSE, FALSE, 0, s, nilobj);
118   if( xright )  InsertSym( AsciiToFull("pb"), RPAR, no_fpos, DEFAULT_PREC,
119     FALSE, FALSE, 0, s, nilobj);
120   if( xleft && xright && xpre != PLUS && xpre != MINUS )
121     right_assoc(s) = TRUE;
122   return s;
123 } /* end load */
124 
125 
126 /*****************************************************************************/
127 /*                                                                           */
128 /*  void PrintUsage(fp)                                                      */
129 /*  static void PrintVersion(lib, fp)                                        */
130 /*                                                                           */
131 /*  Print usage information / version information on file fp.                */
132 /*                                                                           */
133 /*****************************************************************************/
134 #define lputnl fputs( (char *) STR_NEWLINE, fp)
135 #define lput0(fmt)                { fprintf(fp,fmt);                 lputnl; }
136 #define lput1(fmt, p1)            { fprintf(fp,fmt, p1);             lputnl; }
137 #define lput2(fmt, p1, p2)        { fprintf(fp,fmt, p1, p2);         lputnl; }
138 #define lput3(fmt, p1, p2, p3)    { fprintf(fp,fmt, p1, p2, p3);     lputnl; }
139 #define lput4(fmt, p1, p2, p3, p4){ fprintf(fp,fmt, p1, p2, p3, p4); lputnl; }
140 
PrintUsage(FILE * fp)141 void PrintUsage(FILE *fp)
142 {
143   lputnl;
144   lput0("usage:  lout options files"					    );
145   lputnl;
146   lput0("  -a              alternative error format:  file:line:col ..."    );
147   lput0("  -c file         use file.li instead of lout.li for crossrefs"    );
148   lput0("  -C directory    add directory to LCM file search path"	    );
149   lput0("  -d<various>     debug the Lout run (if enabled in binary)"	    );
150   lput0("  -D directory    add directory to database file search path"	    );
151   lput0("  -e file         error messages to file instead of stderr"	    );
152   lput0("  -EPS            EPS (Encapsulated PostScript) output"	    );
153   lput0("  -F directory    add directory to font metrics file search path"  );
154   lput0("  -h file         use hyphenation file"                            );
155   lput0("  -H directory    add directory to hyphenation file search path"   );
156   lput0("  -i file         like @SysInclude { file }; not recommended"	    );
157   lput0("  -I directory    add directory to include file search path"	    );
158   lput0("  -k              suppress all kerning"                            );
159   lput0("  -l              ASCII collation order when sorting indexes etc." );
160   lput0("  -L              locale collation order when sorting indexes etc.");
161   lput0("  -m<addr>        monitor address during Lout run (for debugging)" );
162   lput0("  -M              save memory (don't read in database indexes)"    );
163   lput0("  -o file         output to file instead of stdout"		    );
164   lput0("  -p              plain text output instead of PostScript"	    );
165   lput0("  -P              like -p but with form-feed char between pages"   );
166   lput0("  -PDF or -Z      PDF (Adobe Portable Document Format) output"     );
167   lput0("  -r<integer>     run Lout <integer> times; print on last run only");
168   lput0("  -s              suppress access to cross reference database"	    );
169   lput0("  -S              safe execution (disable calls to system(3))"	    );
170   lput0("  -t              ignore texture changes, always use solid colour" );
171   lput0("  -u              print this usage message on stderr and exit"	    );
172   lput0("  -U              unsafe execution (allow calls to system(3))"	    );
173   lput0("  -V              print version and configuration information"	    );
174   lput0("  -w              print total number of words in output"	    );
175   lput0("  -x              initializing run, not for ordinary use"	    );
176   lput0("  -Z              PDF (Adobe Portable Document Format) output"     );
177   lput0("  --option{value} set option e.g. --'@InitialFont{Times Base 10p}'");
178   lput0("  -               a file name denoting standard input"		    );
179   lputnl;
180 } /* end PrintUsage */
181 
PrintVersion(FULL_CHAR * lib,FILE * fp)182 static void PrintVersion(FULL_CHAR *lib, FILE *fp)
183 {
184   lput1("%s", LOUT_VERSION);
185   lput2("%-28s %s",
186     "Basser Lout written by:", "Jeffrey H. Kingston (jeff@it.usyd.edu.au)");
187   lput2("%-28s %s",
188     "Free source available from:", "ftp://ftp.it.usyd.edu.au/jeff/lout");
189   lput3("%-28s %s %s",
190     "This executable compiled:", __TIME__, __DATE__);
191   lput4("%-28s %s%s%s", "System include directory:", lib, STR_DIR, INCL_DIR);
192   lput4("%-28s %s%s%s", "System database directory:", lib, STR_DIR, DATA_DIR);
193   lput1("Database index files created afresh automatically:%s",
194     USE_STAT ? " yes" : " no");
195   lput1("Safe execution (disabling system()) is default:%s",
196     SAFE_DFT ? " yes" : " no");
197   lput1("strcoll() used for sorting by default:%s", COLLATE ? " yes" : " no");
198   lput1("PDF compression on:%s", PDF_COMPRESSION ? " yes" : " no");
199   lput1("Debugging (-d, -dd, -ddd flags) available:%s", DEBUG_ON ?" yes":" no");
200   lputnl;
201   lput0("Basser Lout comes with ABSOLUTELY NO WARRANTY.");
202   lput0("This is free software, and you are welcome to");
203   lput0("redistribute it under certain conditions.  For");
204   lput0("details on both points, consult the GNU General");
205   lput0("Public License (distributed with this software).");
206 } /* end PrintVersion */
207 
208 
209 /*@::GetArg(), main()@********************************************************/
210 /*                                                                           */
211 /*  GetArg(argv, argc, i)                                                    */
212 /*                                                                           */
213 /*  Get the next argument from the command line and return it.               */
214 /*  Return NULL if it isn't there.                                           */
215 /*                                                                           */
216 /*****************************************************************************/
217 
GetArg(char * argv[],int argc,int * i)218 static FULL_CHAR *GetArg(char *argv[], int argc, int *i)
219 { if( !StringEqual(AsciiToFull(argv[*i]+2), STR_EMPTY) )
220     return AsciiToFull(argv[*i]+2);
221   else if( *i < argc-1 && *argv[*i + 1] != CH_HYPHEN )
222     return AsciiToFull(argv[(*i)++ +1]);
223   else
224     return (FULL_CHAR *) NULL;
225 } /* end GetArg */
226 
227 
228 /*****************************************************************************/
229 /*                                                                           */
230 /*  void run(int argc, char *argv[], int *runs_to_do, FULL_CHAR *lib)        */
231 /*                                                                           */
232 /*  Carry out one run of Lout.  If *runs_to_do is -1, set it.                */
233 /*                                                                           */
234 /*****************************************************************************/
235 
236 typedef enum {
237   BE_PLAIN,
238   BE_PS,
239   BE_PDF
240 } BE_TYPE;
241 
run(int argc,char * argv[],int run_num,int * runs_to_do,FULL_CHAR * lib)242 static void run(int argc, char *argv[], int run_num, int *runs_to_do,
243   FULL_CHAR *lib)
244 { int i, len;  FULL_CHAR *arg;
245   OBJECT t, y, res, s;			/* current token, parser output      */
246   BOOLEAN stdin_seen;			/* TRUE when stdin file seen         */
247   int source_file_count;		/* number of source files in command */
248   FULL_CHAR *cross_db;			/* name of cross reference database  */
249   FULL_CHAR *outfile;			/* name of output file               */
250   FILE *out_fp;
251   long MemCheckLong;
252   FULL_CHAR oname[MAX_BUFF], oval[MAX_BUFF], buff[MAX_BUFF], *p;
253   int bp, runcount;  OBJECT z;
254   BOOLEAN seen_wordcount, encapsulated;
255   BE_TYPE be_type;
256 
257   /* initialise various modules, add current directory to search paths */
258   TotalWordCount = 0;
259   seen_wordcount = FALSE;
260   be_type = BE_PS;
261   PlainCharWidth = PLAIN_WIDTH;
262   PlainCharHeight = PLAIN_HEIGHT;
263   PlainFormFeed = FALSE;
264   InitializeAll = FALSE;
265   UseCollate = COLLATE;
266   AllowCrossDb = TRUE;
267   InMemoryDbIndexes = TRUE;
268   encapsulated = FALSE;
269   SafeExecution = SAFE_DFT ? TRUE : FALSE;
270   Kern = TRUE;
271   ErrorInit();
272   MemInit();
273   InitSym();
274   LexInit();
275   InitFiles();
276   AddToPath(SOURCE_PATH,   MakeWord(WORD, STR_EMPTY, no_fpos));
277   AddToPath(DATABASE_PATH, MakeWord(WORD, STR_EMPTY, no_fpos));
278   AddToPath(INCLUDE_PATH,  MakeWord(WORD, STR_EMPTY, no_fpos));
279 
280   /* read command line */
281   stdin_seen = FALSE;
282   AltErrorFormat = FALSE;
283   cross_db = CROSS_DB;
284   outfile = STR_STDOUT;
285   source_file_count = 0;
286   New(CommandOptions, ACAT);
287   for( i = 1;  i < argc;  i++ )
288   {
289     if( *argv[i] == CH_HYPHEN ) switch( *(argv[i]+1) )
290     {
291       case CH_FLAG_OUTFILE:
292 
293 	/* read name of output file */
294 	if( (outfile = GetArg(argv, argc, &i)) == NULL )
295 	  Error(1, 7, "usage: -o <filename>", FATAL_WITH_USAGE, no_fpos);
296 	if( StringEndsWith(outfile, SOURCE_SUFFIX) )
297 	  Error(1, 28, "-o: output file name %s ends with %s",
298 	    FATAL, no_fpos, outfile, SOURCE_SUFFIX);
299 	break;
300 
301 
302       case CH_FLAG_RUNS:
303 
304 	/* multiple runs */
305 	if( sscanf(argv[i]+2, "%d", &runcount) != 1 )
306 	  Error(1, 32, "usage: -r<integer>", FATAL_WITH_USAGE, no_fpos);
307 	if( runcount <= 0 || runcount > 20 )
308 	  Error(1, 33, "invalid value of -r", FATAL_WITH_USAGE, no_fpos);
309 	assert(*runs_to_do == -1 || *runs_to_do == runcount, "-r");
310 	*runs_to_do = runcount;
311 	break;
312 
313 
314       case CH_FLAG_SUPPRESS:
315 
316 	/* suppress references to OldCrossDb and NewCrossDb */
317 	AllowCrossDb = FALSE;
318 	break;
319 
320 
321       case CH_FLAG_MEMCR:
322 
323 	/* don't use in-memory database indexes */
324 	InMemoryDbIndexes = FALSE;
325 	break;
326 
327 
328       case CH_FLAG_NOKERN:
329 
330 	/* suppress kerning */
331 	Kern = FALSE;
332 	break;
333 
334 
335       case CH_FLAG_NOCOLLATE:
336 
337 	/* suppress local collation */
338 	UseCollate = FALSE;
339 	break;
340 
341 
342       case CH_FLAG_COLLATE:
343 
344 	/* invoke local collation */
345 	UseCollate = TRUE;
346 	break;
347 
348 
349       case CH_FLAG_CROSS:
350 
351 	/* read name of cross reference database */
352 	if( (cross_db = GetArg(argv, argc, &i)) == NULL )
353 	  Error(1, 8, "usage: -c <filename>", FATAL_WITH_USAGE, no_fpos);
354 	break;
355 
356 
357       case CH_FLAG_ERRFILE:
358 
359 	/* read log file name */
360 	if( (arg = GetArg(argv, argc, &i)) == NULL )
361 	  Error(1, 9, "usage: -e <filename>", FATAL_WITH_USAGE, no_fpos);
362 	ErrorSetFile(arg);
363 	break;
364 
365 
366       case CH_FLAG_ALTERR:
367 
368 	/* alternative error message format */
369 	AltErrorFormat = TRUE;
370 	break;
371 
372 
373       case CH_FLAG_EPSFIRST:
374 
375 	/* -EPS produces encapsulated PostScript output */
376 	if( !StringEqual(AsciiToFull(argv[i]+1), STR_EPS) )
377 	  Error(1, 10, "usage: -EPS", FATAL_WITH_USAGE, no_fpos);
378 	encapsulated = TRUE;
379 	break;
380 
381 
382       case CH_FLAG_DIRPATH:
383 
384 	/* add directory to database and sysdatabase paths */
385 	if( (arg = GetArg(argv, argc, &i)) == NULL )
386 	  Error(1, 11, "usage: -D <directoryname>", FATAL_WITH_USAGE, no_fpos);
387 	AddToPath(DATABASE_PATH, MakeWord(WORD, arg, no_fpos));
388 	AddToPath(SYSDATABASE_PATH, MakeWord(WORD, arg, no_fpos));
389 	break;
390 
391 
392       case CH_FLAG_ENCPATH:
393 
394 	/* add directory to character mapping path */
395 	if( (arg = GetArg(argv, argc, &i)) == NULL )
396 	  Error(1, 12, "usage: -C <directoryname>", FATAL_WITH_USAGE, no_fpos);
397 	AddToPath(MAPPING_PATH, MakeWord(WORD, arg, no_fpos));
398 	break;
399 
400 
401       case CH_FLAG_FNTPATH:
402 
403 	/* add directory to font path */
404 	if( (arg = GetArg(argv, argc, &i)) == NULL )
405 	  Error(1, 13, "usage: -F <directoryname>", FATAL_WITH_USAGE, no_fpos);
406 	AddToPath(FONT_PATH, MakeWord(WORD, arg, no_fpos));
407 	break;
408 
409 
410       case CH_FLAG_HYPPATH:
411 
412 	/* add directory to hyph path */
413 	if( (arg = GetArg(argv, argc, &i)) == NULL )
414 	  Error(1, 14, "usage: -H <directoryname>", FATAL_WITH_USAGE, no_fpos);
415 	AddToPath(HYPH_PATH, MakeWord(WORD, arg, no_fpos));
416 	break;
417 
418 
419       case CH_FLAG_INCPATH:
420 
421 	/* add directory to include and sysinclude paths */
422 	if( (arg = GetArg(argv, argc, &i)) == NULL )
423 	  Error(1, 15, "usage: -I <directoryname>", FATAL_WITH_USAGE, no_fpos);
424 	AddToPath(INCLUDE_PATH, MakeWord(WORD, arg, no_fpos));
425 	AddToPath(SYSINCLUDE_PATH, MakeWord(WORD, arg, no_fpos));
426 	break;
427 
428 
429       case CH_FLAG_INCLUDE:
430 
431 	/* read sysinclude file and strip any .lt suffix */
432 	if( (arg = GetArg(argv, argc, &i)) == NULL )
433 	  Error(1, 16, "usage: -i <filename>", FATAL_WITH_USAGE, no_fpos);
434 	len = StringLength(arg) - StringLength(SOURCE_SUFFIX);
435 	if( len >= 0 && StringEqual(&arg[len], SOURCE_SUFFIX) )
436 	  StringCopy(&arg[len], STR_EMPTY);
437 	debug0(DFS, D, "  calling DefineFile from main (1)");
438 	DefineFile(arg, STR_EMPTY, no_fpos, SOURCE_FILE, SYSINCLUDE_PATH);
439 	break;
440 
441 
442       case CH_FLAG_HYPHEN:
443 
444 	/* declare hyphenation file */
445 	if( FirstFile(HYPH_FILE) != NO_FILE )
446 	  Error(1, 17, "two -h options illegal", FATAL_WITH_USAGE, no_fpos);
447 	if( (arg = GetArg(argv, argc, &i)) == NULL )
448 	  Error(1, 18, "usage: -h <filename>", FATAL_WITH_USAGE, no_fpos);
449 	debug0(DFS, D, "  calling DefineFile from main (2)");
450 	DefineFile(arg, STR_EMPTY, no_fpos, HYPH_FILE, INCLUDE_PATH);
451 	DefineFile(arg, HYPH_SUFFIX, no_fpos, HYPH_PACKED_FILE, INCLUDE_PATH);
452 	break;
453 
454 
455       case CH_FLAG_NOTEXTURE:
456 
457 	UseTexture = FALSE;
458 	break;
459 
460 
461       case CH_FLAG_VERSION:
462 
463 	PrintVersion(lib, stderr);
464 	exit(0);
465 	break;
466 
467 
468       case CH_FLAG_WORDS:
469 
470 	seen_wordcount = TRUE;
471 	break;
472 
473 
474       case CH_FLAG_PDF:
475 
476 	be_type = BE_PDF;
477 	break;
478 
479 
480       case CH_FLAG_FFPLAIN:
481 
482 	if( StringEqual(AsciiToFull(argv[i]+1), STR_PDF) )
483 	{
484 	  be_type = BE_PDF;
485 	  break;
486 	}
487 	PlainFormFeed = TRUE;
488 	/* NB NO BREAK */
489 
490 
491       case CH_FLAG_PLAIN:
492 
493 	be_type = BE_PLAIN;
494 	if( *(argv[i]+2) != '\0' )
495 	{ float len1, len2;  FULL_CHAR units1, units2;
496 	  if( sscanf(argv[i]+2, "%f%c%f%c",&len1,&units1,&len2,&units2) != 4 )
497 	  { Error(1, 19, "usage: lout -%c<length><length>",
498 	      FATAL, no_fpos, *(argv[i]+1));
499 	  }
500 	  switch( units1 )
501 	  {
502 	    case CH_UNIT_CM:	PlainCharWidth = len1 * CM; break;
503 	    case CH_UNIT_IN:	PlainCharWidth = len1 * IN; break;
504 	    case CH_UNIT_PT:	PlainCharWidth = len1 * PT; break;
505 	    case CH_UNIT_EM:	PlainCharWidth = len1 * EM; break;
506 
507 	    default:	Error(1, 20, "lout -%c: units must be c, i, p, or m",
508 				  FATAL, no_fpos, *(argv[i]+1));
509 				break;
510 	  }
511 	  switch( units2 )
512 	  {
513 	    case CH_UNIT_CM:	PlainCharHeight = len2 * CM; break;
514 	    case CH_UNIT_IN:	PlainCharHeight = len2 * IN; break;
515 	    case CH_UNIT_PT:	PlainCharHeight = len2 * PT; break;
516 	    case CH_UNIT_EM:	PlainCharHeight = len2 * EM; break;
517 
518 	    default:	Error(1, 21, "lout -%c: units must be c, i, p, or m",
519 				  FATAL, no_fpos, *(argv[i]+1));
520 				break;
521 	  }
522 	}
523 	break;
524 
525 
526       case CH_FLAG_INITALL:
527 
528 	InitializeAll = TRUE;
529 	AllowCrossDb = FALSE;
530 	break;
531 
532 
533       case CH_FLAG_USAGE:
534 
535 	PrintUsage(stderr);
536 	exit(0);
537 	break;
538 
539 
540       case CH_FLAG_DEBUG:
541 
542 	debug_init(AsciiToFull(argv[i]));
543 	break;
544 
545 
546       case CH_FLAG_MEMCHECK:
547 
548 	sscanf(argv[i], "-m%ld", &MemCheckLong);
549 	MemCheck = (POINTER) MemCheckLong;
550 	fprintf(stderr, "checking memory location %ld%s",
551 	  (long) MemCheck, (char *) STR_NEWLINE);
552 	break;
553 
554 
555       case '\0':
556 
557 	/* read stdin as file name */
558 	if( stdin_seen )
559 	  Error(1, 23, "standard input specified twice", FATAL, no_fpos);
560 	stdin_seen = TRUE;
561 	debug0(DFS, D, "  calling DefineFile from main (3)");
562 	DefineFile(STR_STDIN, STR_EMPTY, no_fpos, SOURCE_FILE, SOURCE_PATH);
563 	break;
564 
565 
566       case CH_FLAG_OPTION:
567 
568 	/* read command-line document option */
569 	if( sscanf(argv[i]+2, "%[^{ ] { %[^}] }", oname, oval) != 2 ||
570 	  StringLength(oname) == 0 || StringLength(oval) == 0 )
571 	  Error(1, 24, "error in command-line option %s", FATAL, no_fpos,
572 	    argv[i]+2);
573 	debug2(DSP, D, "  command line option [%s] [%s]", oname, oval);
574 	y = MakeWord(WORD, oname, no_fpos);
575 	Link(CommandOptions, y);
576 	New(y, ACAT);
577 	Link(CommandOptions, y);
578 	bp = 0;
579 	for( p = oval;  *p != '\0';  p++ )  switch( *p )
580 	{
581 	  case ' ':
582 	  case '\t':
583 	  case CH_CR:
584 	  case CH_LF:
585 	  case '{':
586 	  case '}':
587 
588 	    if( bp > 0 )
589 	    { buff[bp++] = '\0';
590 	      if( Down(y) != y )
591 	      { OBJECT g;
592 		New(g, GAP_OBJ);
593 		hspace(g) = 1;  vspace(g) = 0;
594 		FposCopy(fpos(g), *no_fpos);
595 		Link(y, g);
596 	      }
597 	      z = MakeWord(WORD, buff, no_fpos);
598 	      Link(y, z);
599 	      bp = 0;
600 	    }
601 	    break;
602 
603 
604 	  default:
605 
606 	    buff[bp++] = *p;
607 	    break;
608 	}
609 	if( bp > 0 )
610 	{ buff[bp++] = '\0';
611 	  if( Down(y) != y )
612 	  { OBJECT g;
613 	    New(g, GAP_OBJ);
614 	    hspace(g) = 1;  vspace(g) = 0;
615 	    FposCopy(fpos(g), *no_fpos);
616 	    Link(y, g);
617 	  }
618 	  z = MakeWord(WORD, buff, no_fpos);
619 	  Link(y, z);
620 	}
621 	if( Down(y) == y )
622 	  Error(1, 25, "error in command-line option %s", FATAL, no_fpos,
623 	    argv[i]+2);
624 	break;
625 
626 
627       case CH_FLAG_SAFE:
628 
629 	/* ensure safe execution by disabling system calls */
630 	SafeExecution = TRUE;
631 	break;
632 
633       case CH_FLAG_UNSAFE:
634 
635 	/* allow unsafe execution */
636 	SafeExecution = FALSE;
637 	break;
638 
639       default:
640 
641 	Error(1, 26, "unknown command line flag %s", FATAL_WITH_USAGE,
642 	  no_fpos, argv[i]);
643 	break;
644 
645     }
646     else
647     {   /* argument is source file, strip any .lout suffix and define it */
648 	arg = AsciiToFull(argv[i]);
649 	len = StringLength(arg) - StringLength(SOURCE_SUFFIX);
650 	if( len >= 0 && StringEqual(&arg[len], SOURCE_SUFFIX) )
651 	  StringCopy(&arg[len], STR_EMPTY);
652 	debug0(DFS, D, "  calling DefineFile from main (4)");
653 	DefineFile(AsciiToFull(argv[i]), STR_EMPTY, no_fpos,
654 	    SOURCE_FILE, SOURCE_PATH);
655 	source_file_count++;
656     }
657   } /* for */
658   if( *runs_to_do == -1 )
659     *runs_to_do = 1;
660 
661   if( UseCollate )
662   {
663     if (!setlocale (LC_COLLATE, ""))
664       Error(1, 30, "unable to initialize collation", WARN, no_fpos);
665   }
666 
667   /* start timing if required */
668   ifdebug(DPP, D, ProfileOn("main"));
669 
670   /* sort out output file and back end */
671   if( run_num == *runs_to_do )
672   {
673     /* last run, so open output file (or stdout if none specified) */
674     if( StringEqual(outfile, STR_STDOUT) )
675     {
676 #if OS_DOS
677       /* For DOS/Win32 we need to set binary mode on stdout to prevent
678 	 PDF compressed streams and xrefs from being corrupted - Uwe 12/98 */
679       if( be_type != BE_PLAIN && _setmode(_fileno(stdout), _O_BINARY) == -1 )
680 	Error(1, 31, "cannot set binary mode on stdout", FATAL, no_fpos);
681 #endif
682       out_fp = stdout;
683     }
684     else
685     { out_fp = StringFOpen(outfile, WRITE_FILE);
686       if( out_fp == null )
687 	Error(1, 27, "cannot open output file %s", FATAL, no_fpos, outfile);
688     }
689     if( be_type == BE_PLAIN )
690       BackEnd = Plain_BackEnd;
691     else if( be_type == BE_PS )
692       BackEnd = PS_BackEnd;
693     else
694       BackEnd = PDF_BackEnd;
695     BackEnd->PrintInitialize(out_fp, encapsulated);
696   }
697   else
698   {
699     /* not last run, so use a null backend */
700     if( be_type == BE_PLAIN )
701       BackEnd = Plain_NullBackEnd;
702     else
703       BackEnd = PS_NullBackEnd;
704     BackEnd->PrintInitialize(NULL, encapsulated);
705   }
706 
707   /* initialize miscellaneous modules */
708   ColourInit();
709   TextureInit();
710   LanguageInit();
711 
712   /* append default directories to file search paths */
713   AddToPath(FONT_PATH,      MakeWordThree(lib, STR_DIR, AsciiToFull(FONT_DIR)));
714   AddToPath(HYPH_PATH,      MakeWordThree(lib, STR_DIR, AsciiToFull(HYPH_DIR)));
715   AddToPath(MAPPING_PATH,   MakeWordThree(lib, STR_DIR, AsciiToFull(MAPS_DIR)));
716   AddToPath(SYSDATABASE_PATH,MakeWordThree(lib,STR_DIR, AsciiToFull(DATA_DIR)));
717   AddToPath(DATABASE_PATH,  MakeWordThree(lib, STR_DIR, AsciiToFull(DATA_DIR)));
718   AddToPath(SYSINCLUDE_PATH,MakeWordThree(lib, STR_DIR, AsciiToFull(INCL_DIR)));
719   AddToPath(INCLUDE_PATH,   MakeWordThree(lib, STR_DIR, AsciiToFull(INCL_DIR)));
720 
721   /* use stdin if no source files were mentioned */
722   if( source_file_count == 0 )
723   { debug0(DFS, D, "  calling DefineFile from main (5)");
724     DefineFile(STR_STDIN, STR_EMPTY, no_fpos, SOURCE_FILE, SOURCE_PATH);
725   }
726 
727   /* load predefined symbols into symbol table */
728   StartSym      = nilobj;  /* Not a mistake */
729   StartSym      = load(KW_START,        0, FALSE,  FALSE,  TRUE,  NO_PREC     );
730   GalleySym     = load(KW_GALLEY,       0, FALSE,  FALSE,  TRUE,  NO_PREC     );
731   ForceGalleySym= load(KW_FORCE_GALLEY, 0, FALSE,  FALSE,  TRUE,  NO_PREC     );
732   InputSym      = load(KW_INPUT,        0, FALSE,  FALSE,  TRUE,  NO_PREC     );
733   PrintSym      = load(KW_PRINT,        0, FALSE,  FALSE,  TRUE,  NO_PREC     );
734   FilterInSym   = load(KW_FILTERIN,     0, FALSE,  FALSE,  FALSE, NO_PREC     );
735   FilterOutSym  = load(KW_FILTEROUT,    0, FALSE,  FALSE,  FALSE, NO_PREC     );
736   FilterErrSym  = load(KW_FILTERERR,    0, FALSE,  FALSE,  FALSE, NO_PREC     );
737   OptGallSym    = load(KW_OPTGALL,      0, FALSE,  TRUE,   FALSE, DEFAULT_PREC);
738   VerbatimSym   = load(KW_VERBATIM,VERBATIM,FALSE, TRUE,   FALSE, DEFAULT_PREC);
739   RawVerbatimSym= load(KW_RAWVERBATIM,RAW_VERBATIM,FALSE,TRUE,FALSE,DEFAULT_PREC);
740 
741 
742   load(KW_BEGIN,        BEGIN,          FALSE,  FALSE,  FALSE, BEGIN_PREC  );
743   load(KW_END,          END,            FALSE,  FALSE,  FALSE, END_PREC    );
744   load(KW_ENV,          ENV,            FALSE,  FALSE,  FALSE, NO_PREC     );
745   load(KW_ENVA,         ENVA,           FALSE,  FALSE,  FALSE, NO_PREC     );
746   load(KW_ENVB,         ENVB,           FALSE,  FALSE,  FALSE, NO_PREC     );
747   load(KW_ENVC,         ENVC,           FALSE,  FALSE,  FALSE, NO_PREC     );
748   load(KW_ENVD,         ENVD,           FALSE,  FALSE,  FALSE, NO_PREC     );
749   load(KW_CENV,         CENV,           FALSE,  FALSE,  FALSE, NO_PREC     );
750   load(KW_CLOS,         CLOS,           FALSE,  FALSE,  FALSE, NO_PREC     );
751   load(KW_LVIS,         LVIS,           FALSE,  FALSE,  FALSE, NO_PREC     );
752   load(KW_LUSE,         LUSE,           FALSE,  FALSE,  FALSE, NO_PREC     );
753   load(KW_LEO,          LEO,            FALSE,  FALSE,  FALSE, NO_PREC     );
754   load(KW_LBR,          LBR,            FALSE,  FALSE,  FALSE, LBR_PREC    );
755   load(KW_RBR,          RBR,            FALSE,  FALSE,  FALSE, RBR_PREC    );
756   load(KW_INCLUDE,      INCLUDE,        FALSE,  FALSE,  FALSE, NO_PREC     );
757   load(KW_SYSINCLUDE,   SYS_INCLUDE,    FALSE,  FALSE,  FALSE, NO_PREC     );
758   load(KW_PREPEND,      PREPEND,        FALSE,  FALSE,  FALSE, NO_PREC     );
759   load(KW_SYSPREPEND,   SYS_PREPEND,    FALSE,  FALSE,  FALSE, NO_PREC     );
760   load(KW_INCG_REPEATED,INCG_REPEATED,  FALSE,  FALSE,  FALSE, NO_PREC     );
761   load(KW_SINCG_REPEATED,SINCG_REPEATED,FALSE,  FALSE,  FALSE, NO_PREC     );
762   load(KW_DATABASE,     DATABASE,       FALSE,  FALSE,  FALSE, NO_PREC     );
763   load(KW_SYSDATABASE,  SYS_DATABASE,   FALSE,  FALSE,  FALSE, NO_PREC     );
764   load(KW_USE,          USE,            FALSE,  FALSE,  FALSE, NO_PREC     );
765   load(KW_NOT_REVEALED, NOT_REVEALED,   FALSE,  FALSE,  FALSE, NO_PREC     );
766   load(KW_CASE,         CASE,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
767   load(KW_YIELD,        YIELD,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
768   load(KW_BACKEND,      BACKEND,        FALSE,  FALSE,  FALSE, DEFAULT_PREC);
769   load(KW_XCHAR,        XCHAR,          FALSE,  TRUE,   FALSE, DEFAULT_PREC);
770   load(KW_FONT,         FONT,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
771   load(KW_SPACE,        SPACE,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
772   load(KW_YUNIT,        YUNIT,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
773   load(KW_ZUNIT,        ZUNIT,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
774   load(KW_BREAK,        BREAK,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
775   load(KW_UNDERLINE,    UNDERLINE,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
776   load(KW_UNDERLINE_COLOUR, UNDERLINE_COLOUR,TRUE,TRUE, FALSE, DEFAULT_PREC);
777   load(KW_UNDERLINE_COLOR, UNDERLINE_COLOUR,TRUE,TRUE,  FALSE, DEFAULT_PREC);
778   load(KW_COLOUR,       COLOUR,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
779   load(KW_COLOR,        COLOUR,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
780   load(KW_TEXTURE,      TEXTURE,        TRUE,   TRUE,   FALSE, DEFAULT_PREC);
781   load(KW_OUTLINE,      OUTLINE,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
782   load(KW_LANGUAGE,     LANGUAGE,       TRUE,   TRUE,   FALSE, DEFAULT_PREC);
783   load(KW_CURR_LANG,    CURR_LANG,      FALSE,  FALSE,  FALSE, DEFAULT_PREC);
784   load(KW_CURR_FAMILY,  CURR_FAMILY,    FALSE,  FALSE,  FALSE, DEFAULT_PREC);
785   load(KW_CURR_FACE,    CURR_FACE,      FALSE,  FALSE,  FALSE, DEFAULT_PREC);
786   load(KW_CURR_YUNIT,   CURR_YUNIT,     FALSE,  FALSE,  FALSE, DEFAULT_PREC);
787   load(KW_CURR_ZUNIT,   CURR_ZUNIT,     FALSE,  FALSE,  FALSE, DEFAULT_PREC);
788   load(KW_COMMON,       COMMON,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
789   load(KW_RUMP,         RUMP,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
790   load(KW_MELD,         MELD,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
791   load(KW_INSERT,       INSERT,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
792   load(KW_ONE_OF,       ONE_OF,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
793   load(KW_NEXT,         NEXT,           FALSE,  TRUE,   FALSE, DEFAULT_PREC);
794   load(KW_PLUS,         PLUS,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
795   load(KW_MINUS,        MINUS,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
796   load(KW_OPEN,         OPEN,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
797   load(KW_TAGGED,       TAGGED,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
798   load(KW_WIDE,         WIDE,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
799   load(KW_HIGH,         HIGH,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
800   load(KW_HSHIFT,       HSHIFT,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
801   load(KW_VSHIFT,       VSHIFT,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
802   load(KW_BEGIN_HEADER, BEGIN_HEADER,   TRUE,   TRUE,   FALSE, DEFAULT_PREC);
803   load(KW_END_HEADER,   END_HEADER,     FALSE,  FALSE,  FALSE, DEFAULT_PREC);
804   load(KW_SET_HEADER,   SET_HEADER,     TRUE,   TRUE,   FALSE, DEFAULT_PREC);
805   load(KW_CLEAR_HEADER, CLEAR_HEADER,   FALSE,  FALSE,  FALSE, DEFAULT_PREC);
806   load(KW_ONE_COL,      ONE_COL,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
807   load(KW_ONE_ROW,      ONE_ROW,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
808   load(KW_HMIRROR,      HMIRROR,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
809   load(KW_VMIRROR,      VMIRROR,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
810   load(KW_HSCALE,       HSCALE,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
811   load(KW_VSCALE,       VSCALE,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
812   load(KW_HCOVER,       HCOVER,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
813   load(KW_VCOVER,       VCOVER,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
814   load(KW_KERN_SHRINK,  KERN_SHRINK,    TRUE,   TRUE,   FALSE, DEFAULT_PREC);
815   load(KW_SCALE,        SCALE,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
816   load(KW_HCONTRACT,    HCONTRACT,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
817   load(KW_VCONTRACT,    VCONTRACT,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
818   load(KW_HLIMITED,     HLIMITED,       FALSE,  TRUE,   FALSE, DEFAULT_PREC);
819   load(KW_VLIMITED,     VLIMITED,       FALSE,  TRUE,   FALSE, DEFAULT_PREC);
820   load(KW_HEXPAND,      HEXPAND,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
821   load(KW_VEXPAND,      VEXPAND,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
822   load(KW_STARTHVSPAN,  START_HVSPAN,   FALSE,  TRUE,   FALSE, DEFAULT_PREC);
823   load(KW_STARTHSPAN,   START_HSPAN,    FALSE,  TRUE,   FALSE, DEFAULT_PREC);
824   load(KW_STARTVSPAN,   START_VSPAN,    FALSE,  TRUE,   FALSE, DEFAULT_PREC);
825   load(KW_HSPAN,        HSPAN,          FALSE,  FALSE,  FALSE, DEFAULT_PREC);
826   load(KW_VSPAN,        VSPAN,          FALSE,  FALSE,  FALSE, DEFAULT_PREC);
827   load(KW_PADJUST,      PADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
828   load(KW_HADJUST,      HADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
829   load(KW_VADJUST,      VADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
830   load(KW_ROTATE,       ROTATE,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
831   load(KW_BACKGROUND,   BACKGROUND,     TRUE,   TRUE,   FALSE, DEFAULT_PREC);
832   load(KW_INCGRAPHIC,   INCGRAPHIC,     FALSE,  TRUE,   FALSE, DEFAULT_PREC);
833   load(KW_SINCGRAPHIC,  SINCGRAPHIC,    FALSE,  TRUE,   FALSE, DEFAULT_PREC);
834   load(KW_PLAINGRAPHIC, PLAIN_GRAPHIC,  TRUE,   TRUE,   FALSE, DEFAULT_PREC);
835   load(KW_GRAPHIC,      GRAPHIC,        TRUE,   TRUE,   FALSE, DEFAULT_PREC);
836   load(KW_LINK_SOURCE,  LINK_SOURCE,    TRUE,   TRUE,   FALSE, DEFAULT_PREC);
837   load(KW_LINK_DEST,    LINK_DEST,      TRUE,   TRUE,   FALSE, DEFAULT_PREC);
838   load(KW_LINK_URL,     LINK_URL,       TRUE,   TRUE,   FALSE, DEFAULT_PREC);
839   load(KW_CROSS,        CROSS,          TRUE,   TRUE,   FALSE, CROSSOP_PREC);
840   load(KW_FORCE_CROSS,  FORCE_CROSS,    TRUE,   TRUE,   FALSE, CROSSOP_PREC);
841   load(KW_NULL,         NULL_CLOS,      FALSE,  FALSE,  TRUE,  NO_PREC     );
842   load(KW_PAGE_LABEL,   PAGE_LABEL,     FALSE,  TRUE,   TRUE,  DEFAULT_PREC);
843   load(KW_SET_CONTEXT,  SET_CONTEXT,    TRUE,   TRUE,   FALSE, DEFAULT_PREC);
844   load(KW_GET_CONTEXT,  GET_CONTEXT,    FALSE,   TRUE,   FALSE, DEFAULT_PREC);
845 
846 #define setcat(s, mk, jn)  has_mark(s)=mk, has_join(s)=jn
847 
848   s=load(KW_VCAT_NN, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,FALSE,FALSE);
849   s=load(KW_VCAT_MN, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,TRUE, FALSE);
850   s=load(KW_VCAT_NJ, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,FALSE,TRUE);
851   s=load(KW_VCAT_MJ, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,TRUE, TRUE);
852   s=load(KW_HCAT_NN, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,FALSE,FALSE);
853   s=load(KW_HCAT_MN, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,TRUE, FALSE);
854   s=load(KW_HCAT_NJ, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,FALSE,TRUE);
855   s=load(KW_HCAT_MJ, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,TRUE, TRUE);
856   s=load(KW_ACAT_NJ, ACAT, TRUE, TRUE, FALSE, ACAT_PREC); setcat(s,FALSE,TRUE);
857   s=load(KW_ACAT_MJ, ACAT, TRUE, TRUE, FALSE, ACAT_PREC); setcat(s,TRUE, TRUE);
858 
859   /* intialize fonts and load @FontDef symbol */
860   FontInit();
861 
862   /* intialize current time and load @Moment symbol */
863   InitTime();
864 
865   /* initialize filter module */
866   FilterInit();
867 
868   /* initialize enviroment table module, etc. */
869   CrossInitModule();
870   EnvInit();
871   DbInit();
872   HyphInit();
873   MapInit();
874   ReadFromFileInit();
875   PromoteInit();
876 
877   /* initialise scope chain to <StartSym> */
878   PushScope(StartSym, FALSE, FALSE);
879 
880   /* initialise lexical analyser */
881   LexPush(FirstFile(SOURCE_FILE), 0, SOURCE_FILE, 1, FALSE);
882 
883   /* alternative processing which tests running time of lexer+parser only */
884   /* ***
885   if( TRUE )
886   {
887     InitParser(cross_db);
888     t = NewToken(BEGIN, no_fpos, 0, 0, BEGIN_PREC, StartSym);
889     res = Parse(&t, StartSym, TRUE, FALSE);
890     exit(0);
891     return 0;
892   }
893   *** */
894 
895   /* process input files */
896   InitParser(cross_db);
897   t = NewToken(BEGIN, no_fpos, 0, 0, BEGIN_PREC, StartSym);
898   res = Parse(&t, StartSym, TRUE, TRUE);
899   DisposeObject(CommandOptions);
900   debug0(DGT, D, "calling TransferEnd(res) from main()");
901   TransferEnd(res);
902   TransferClose();
903 
904   /* close various modules */
905   BackEnd->PrintAfterLastPage();
906   BackEnd->LinkCheck();
907   CrossClose();
908   CloseFiles();
909 
910   /* remove any leftover filter temporary files */
911   FilterScavenge(TRUE);
912 
913   /* print word count, if required */
914   if( seen_wordcount && run_num == *runs_to_do )
915     Error(1, 29, "total of all words printed: %d", WARN,no_fpos,TotalWordCount);
916 
917   /* check for unbalanced error blocks */
918   CheckErrorBlocks();
919 
920   /* wrapup */
921   ifdebug(DST, D, CheckSymSpread() );
922   ifdebug(ANY, D, DeleteEverySym() );
923   debug0(DMA, D, "at end of run:");
924   ifdebug(DMA, D, DebugMemory() );
925   ifdebug(DPP, D, ProfileOff("main"));
926   ifdebug(DPP, D, ProfilePrint());
927   ifdebug(DET, D, EnvDebug());
928 
929 } /* end run */
930 
931 
932 /*****************************************************************************/
933 /*                                                                           */
934 /*  main(argc, argv)                                                         */
935 /*                                                                           */
936 /*  Read command line, initialise everything, read definitions, read         */
937 /*  galleys, clean up and exit.                                              */
938 /*                                                                           */
939 /*****************************************************************************/
940 
main(int argc,char * argv[])941 int main(int argc, char *argv[])
942 {
943   FULL_CHAR *lib;			/* name of library directory         */
944   int run_num, runs_to_do;
945 #if LOCALE_ON
946   char catname[MAX_BUFF], *loc;
947 #endif
948 
949   /* find the name of the library directory, from envt or else from -D */
950   lib = AsciiToFull(getenv("LOUTLIB"));
951   if( lib == (FULL_CHAR *) NULL )
952     lib = AsciiToFull(LIB_DIR);
953 
954   /* set locale if that's what we are doing */
955 #if LOCALE_ON
956   loc = setlocale(LC_MESSAGES, "");
957   if( loc == (char *) NULL )
958   { Error(1, 6, "unable to initialize locale", WARN, no_fpos);
959     loc = "C";
960   }
961   sprintf(catname, "%s/%s/%s/LC_MESSAGES/errors.%s",
962     lib, LOCALE_DIR, loc, loc);
963   MsgCat = catopen(catname, 0);
964 #endif
965 
966   run_num = 1;  runs_to_do = -1;
967   do
968   {
969     if( run_num > 1 )
970       Error(1, 34, "lout -r beginning run %d:", WARN, no_fpos, run_num);
971     run(argc, argv, run_num, &runs_to_do, lib);
972     run_num++;
973   }
974   while( run_num <= runs_to_do );
975 
976 #if LOCALE_ON
977   catclose(MsgCat);
978 #endif
979 
980   exit(0);
981   return 0;
982 } /* end main */
983