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