home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume37 / lout / part13 < prev    next >
Encoding:
Text File  |  1993-06-19  |  81.3 KB  |  2,168 lines

  1. Newsgroups: comp.sources.misc
  2. From: jeff@joyce.cs.su.oz.au (Jeff Kingston)
  3. Subject: v37i111:  lout - Lout document formatting system, v2, Part13/30
  4. Message-ID: <1993Jun1.051942.26053@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4f219d964b1b30a73e632f65f4ac04f7
  6. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Tue, 1 Jun 1993 05:19:42 GMT
  9. Approved: kent@sparky.imd.sterling.com
  10.  
  11. Submitted-by: jeff@joyce.cs.su.oz.au (Jeff Kingston)
  12. Posting-number: Volume 37, Issue 111
  13. Archive-name: lout/part13
  14. Environment: UNIX
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  lout/z01.c lout/z04.c lout/z05.c lout/z12.c lout/z18.c
  21. # Wrapped by kent@sparky on Sun May 30 19:43:57 1993
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 13 (of 30)."'
  25. if test -f 'lout/z01.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'lout/z01.c'\"
  27. else
  28.   echo shar: Extracting \"'lout/z01.c'\" \(16696 characters\)
  29.   sed "s/^X//" >'lout/z01.c' <<'END_OF_FILE'
  30. X/*@z01.c:Supervise:main()@****************************************************/
  31. X/*                                                                           */
  32. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.03)       */
  33. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  34. X/*                                                                           */
  35. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  36. X/*  Basser Department of Computer Science                                    */
  37. X/*  The University of Sydney 2006                                            */
  38. X/*  AUSTRALIA                                                                */
  39. X/*                                                                           */
  40. X/*  This program is free software; you can redistribute it and/or modify     */
  41. X/*  it under the terms of the GNU General Public License as published by     */
  42. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  43. X/*  any later version.                                                       */
  44. X/*                                                                           */
  45. X/*  This program is distributed in the hope that it will be useful,          */
  46. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  47. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  48. X/*  GNU General Public License for more details.                             */
  49. X/*                                                                           */
  50. X/*  You should have received a copy of the GNU General Public License        */
  51. X/*  along with this program; if not, write to the Free Software              */
  52. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  53. X/*                                                                           */
  54. X/*  FILE:         z01.c                                                      */
  55. X/*  MODULE:       Supervise                                                  */
  56. X/*  EXTERNS:      main()                                                     */
  57. X/*                                                                           */
  58. X/*****************************************************************************/
  59. X#include "externs"
  60. X
  61. X/*****************************************************************************/
  62. X/*                                                                           */
  63. X/*  BOOLEAN StringBeginsWith(str, pattern)                                   */
  64. X/*  BOOLEAN StringContains(str, pattern)                                     */
  65. X/*                                                                           */
  66. X/*  Check whether str begins with (or contains within it) pattern.  This     */
  67. X/*  could be done by the standard function "strstr" except that not all      */
  68. X/*  systems have it and in at least one case the implementation has a bug.   */
  69. X/*                                                                           */
  70. X/*****************************************************************************/
  71. X
  72. XBOOLEAN StringBeginsWith(str, pattern)
  73. Xunsigned char *str, *pattern;
  74. X{ unsigned char *sp, *pp;
  75. X  sp = str;  pp = pattern;
  76. X  while( *sp != '\0' && *pp != '\0' )
  77. X  { if( *sp++ != *pp++ )  return FALSE;
  78. X  }
  79. X  return (*pp == '\0');
  80. X} /* end StringBeginsWith */
  81. X
  82. XBOOLEAN StringContains(str, pattern)
  83. Xunsigned char *str, *pattern;
  84. X{ unsigned char *sp;
  85. X  for( sp = str;  *sp != '\0';  sp++ )
  86. X  { if( StringBeginsWith(sp, pattern) )  return TRUE;
  87. X  }
  88. X  return FALSE;
  89. X} /* end StringContains */
  90. X
  91. X
  92. X/*****************************************************************************/
  93. X/*                                                                           */
  94. X/*  StartSym      the symbol table entry for \Start (overall scope)          */
  95. X/*  GalleySym     the symbol table entry for @Galley                         */
  96. X/*  InputSym      the symbol table entry for @Input@                         */
  97. X/*  PrintSym      the symbol table entry for \Print (root target)            */
  98. X/*                                                                           */
  99. X/*****************************************************************************/
  100. X
  101. XOBJECT StartSym, GalleySym, InputSym, PrintSym;
  102. X
  103. X/*****************************************************************************/
  104. X/*                                                                           */
  105. X/*  AllowCrossDb        Allow references to OldCrossDb and NewCrossDb        */
  106. X/*                                                                           */
  107. X/*****************************************************************************/
  108. X
  109. XBOOLEAN AllowCrossDb;
  110. X
  111. X/*****************************************************************************/
  112. X/*                                                                           */
  113. X/*  Encapsulated        Produce a one-page encapsulated PostScript file      */
  114. X/*                                                                           */
  115. X/*****************************************************************************/
  116. X
  117. XBOOLEAN Encapsulated;
  118. X
  119. X
  120. X/*****************************************************************************/
  121. X/*                                                                           */
  122. X/*  OBJECT load(xstr, xpredefined, xleft, xright, xindef, xprec)             */
  123. X/*                                                                           */
  124. X/*  Load a predefined operator with these attributes into the symbol table.  */
  125. X/*  If the operator has parameters, load symbols for those also.             */
  126. X/*                                                                           */
  127. X/*****************************************************************************/
  128. X
  129. Xstatic OBJECT load(xstr, xpre, xleft, xright, xindef, xprec)
  130. Xunsigned char *xstr;  unsigned  xpre;  BOOLEAN xleft, xright, xindef;
  131. Xunsigned char xprec;
  132. X{ OBJECT s;
  133. X  s = InsertSym(xstr, LOCAL, no_fpos, xprec, xindef, FALSE, xpre, StartSym,nil);
  134. X  if( xleft )
  135. X    InsertSym("pa", LPAR, no_fpos, DEFAULT_PREC, FALSE, FALSE, 0, s, nil);
  136. X  if( xright )
  137. X    InsertSym("pb", RPAR, no_fpos, DEFAULT_PREC, FALSE, FALSE, 0, s, nil);
  138. X  if( xleft && xright )  right_assoc(s) = TRUE;
  139. X  return s;
  140. X} /* end load */
  141. X
  142. X
  143. X/*@@**************************************************************************/
  144. X/*                                                                           */
  145. X/*  main(argc, argv)                                                         */
  146. X/*                                                                           */
  147. X/*  Read command line, initialise everything, read definitions, read         */
  148. X/*  galleys, clean up and exit.                                              */
  149. X/*                                                                           */
  150. X/*****************************************************************************/
  151. X
  152. Xmain(argc, argv)
  153. Xint argc; unsigned char *argv[];
  154. X{ int i;
  155. X  OBJECT t, res, s;                /* current token, parser o/p */
  156. X  BOOLEAN stdin_seen;                /* TRUE when stdin file seen */
  157. X  unsigned char *cross_db;            /* name of cross ref database*/
  158. X  unsigned char *outfile;            /* name of output file       */
  159. X  FILE *out_fp;
  160. X
  161. X  /* initialise various modules, add current directory to search paths */
  162. X  AllowCrossDb = TRUE;
  163. X  Encapsulated = FALSE;
  164. X  InitSym();
  165. X  LexInit();
  166. X  MemInit();
  167. X  InitFiles();
  168. X  AddToPath(FONT_PATH,     "");
  169. X  AddToPath(SOURCE_PATH,   "");
  170. X  AddToPath(DATABASE_PATH, "");
  171. X  AddToPath(INCLUDE_PATH,  "");
  172. X
  173. X  /* read command line */
  174. X  stdin_seen = FALSE;
  175. X  cross_db = (unsigned char *) CROSS_DB;
  176. X  outfile = (unsigned char *) "-";
  177. X  for( i = 1;  i < argc;  i++ )
  178. X  {  if( *argv[i] == '-' ) switch( *(argv[i]+1) )
  179. X     {
  180. X    case 'o':    /* read name of output file */
  181. X            if( *(argv[i]+2) == '\0' )
  182. X                Error(FATAL, no_fpos, "usage: -o<filename>");
  183. X            outfile = argv[i]+2;
  184. X            break;
  185. X
  186. X    case 's':    /* suppress references to OldCrossDb and NewCrossDb */
  187. X            AllowCrossDb = FALSE;
  188. X            break;
  189. X
  190. X    case 'c':    /* read name of cross reference database */
  191. X            cross_db = argv[i]+2;
  192. X            break;
  193. X
  194. X    case 'e':    /* read log file name */
  195. X            if( *(argv[i]+2) == '\0' )
  196. X                Error(FATAL, no_fpos, "usage: -e<filename>");
  197. X            ErrorInit(argv[i]+2);
  198. X            break;
  199. X
  200. X    case 'E':    /* -EPS produces encapsulated PostScript output */
  201. X            if( strcmp(argv[i]+1, "EPS") != 0 )
  202. X              Error(FATAL, no_fpos, "usage: -EPS");
  203. X            Encapsulated = TRUE;
  204. X            break;
  205. X
  206. X    case 'D':    /* add directory to database and sysdatabase paths */
  207. X            if( *(argv[i]+2) == '\0' )
  208. X                Error(FATAL, no_fpos, "usage: -D<dirname>");
  209. X            AddToPath(DATABASE_PATH, argv[i]+2);
  210. X            AddToPath(SYSDATABASE_PATH, argv[i]+2);
  211. X            break;
  212. X
  213. X    case 'F':    /* add directory to font path */
  214. X            if( *(argv[i]+2) == '\0' )
  215. X                Error(FATAL, no_fpos, "usage: -F<dirname>");
  216. X            AddToPath(FONT_PATH, argv[i]+2);
  217. X            break;
  218. X
  219. X    case 'I':    /* add directory to include and sysinclude paths */
  220. X            if( *(argv[i]+2) == '\0' )
  221. X                Error(FATAL, no_fpos, "usage: -I<dirname>");
  222. X            AddToPath(INCLUDE_PATH, argv[i]+2);
  223. X            AddToPath(SYSINCLUDE_PATH, argv[i]+2);
  224. X            break;
  225. X
  226. X    case 'i':    /* read sysinclude file */
  227. X            if( *(argv[i]+2) == '\0' )
  228. X                Error(FATAL, no_fpos, "usage: -i<filename>");
  229. X            t = MakeWord(argv[i]+2, no_fpos);
  230. X            DefineFile(t, SOURCE_FILE, SYSINCLUDE_PATH);
  231. X            break;
  232. X
  233. X    case 'h':    /* declare hyphenation file */
  234. X            if( FirstFile(HYPH_FILE) != NO_FILE )
  235. X              Error(FATAL, no_fpos, "two -h options illegal");
  236. X            if( *(argv[i]+2) == '\0' )
  237. X              Error(FATAL, no_fpos, "usage: -h<filename>");
  238. X            if( strlen(argv[i]+2) + strlen(HYPH_SUFFIX) >= MAX_LINE)              Error(FATAL, no_fpos, "-h option too long");
  239. X            t = MakeWord(argv[i] + 2, no_fpos);
  240. X            DefineFile(t, HYPH_FILE, INCLUDE_PATH);
  241. X            t = MakeWordTwo(string(t), HYPH_SUFFIX, no_fpos);
  242. X            DefineFile(t, HYPH_PACKED_FILE, INCLUDE_PATH);
  243. X            break;
  244. X
  245. X    case 'V':    fprintf(stderr, "%s\n", LOUT_VERSION);
  246. X            break;
  247. X
  248. X    case 'd':    debug_init(argv[i]);
  249. X            break;
  250. X
  251. X    case '\0':    /* read stdin as file name */
  252. X            if( stdin_seen )
  253. X                Error(FATAL, no_fpos, "stdin read twice!");
  254. X            stdin_seen = TRUE;
  255. X            t = MakeWord("-", no_fpos);
  256. X            DefineFile(t, SOURCE_FILE, SOURCE_PATH);
  257. X            break;
  258. X
  259. X    default:    Error(FATAL, no_fpos,
  260. X                "unknown command line flag %s", argv[i]);
  261. X            break;
  262. X     }
  263. X     else DefineFile(MakeWord(argv[i], no_fpos), SOURCE_FILE, SOURCE_PATH);
  264. X  } /* for */
  265. X
  266. X  /* define hyphenation file if not done already by -h flag */
  267. X  if( FirstFile(HYPH_FILE) == NO_FILE )
  268. X  { t = MakeWord(HYPH_FILENAME, no_fpos);
  269. X    DefineFile(t, HYPH_FILE, SYSINCLUDE_PATH);
  270. X    t = MakeWordTwo(HYPH_FILENAME, HYPH_SUFFIX, no_fpos);
  271. X    DefineFile(t, HYPH_PACKED_FILE, SYSINCLUDE_PATH);
  272. X  }
  273. X
  274. X  /* start timing if required */
  275. X  ifdebug(DPP, D, ProfileOn("main"));
  276. X
  277. X  /* open output file, or stdout if none specified, and initialize printer */
  278. X  if( strcmp(outfile, "-") == 0 )  out_fp = stdout;
  279. X  else if( (out_fp = fopen(outfile, "w")) == null )
  280. X    Error(FATAL, no_fpos, "cannot open output file %s", outfile);
  281. X  PrintInit(out_fp);
  282. X
  283. X  /* append default directories to file search paths */
  284. X  AddToPath(FONT_PATH,         FONT_DIR);
  285. X  AddToPath(SYSDATABASE_PATH,  DATA_DIR);
  286. X  AddToPath(DATABASE_PATH,     DATA_DIR);
  287. X  AddToPath(SYSINCLUDE_PATH,   INCL_DIR);
  288. X  AddToPath(INCLUDE_PATH,      INCL_DIR);
  289. X
  290. X  /* use stdin if no source files were mentioned */
  291. X  if( FirstFile(SOURCE_FILE) == NO_FILE )
  292. X    DefineFile(MakeWord("-", no_fpos), SOURCE_FILE, SOURCE_PATH);
  293. X
  294. X  /* load predefined symbols into symbol table */
  295. X  StartSym = nil;
  296. X  StartSym  = load("\\Start",   0,     FALSE,  FALSE,  TRUE,  NO_PREC     );
  297. X  GalleySym = load(KW_GALLEY,   0,     FALSE,  FALSE,  TRUE,  NO_PREC     );
  298. X  InputSym  = load(KW_INPUT,    0,     FALSE,  FALSE,  TRUE,  NO_PREC     );
  299. X  PrintSym  = load("\\Print",   0,     FALSE,  FALSE,  TRUE,  NO_PREC     );
  300. X
  301. X  load(KW_BEGIN,       BEGIN,          FALSE,  FALSE,  FALSE, BEGIN_PREC  );
  302. X  load(KW_END,         END,            FALSE,  FALSE,  FALSE, END_PREC    );
  303. X  load(KW_ENV,         ENV,            FALSE,  FALSE,  FALSE, NO_PREC     );
  304. X  load(KW_CLOS,        CLOS,           FALSE,  FALSE,  FALSE, NO_PREC     );
  305. X  load(KW_LVIS,        LVIS,           FALSE,  FALSE,  FALSE, NO_PREC     );
  306. X  load(KW_LBR,         LBR,            FALSE,  FALSE,  FALSE, LBR_PREC    );
  307. X  load(KW_RBR,         RBR,            FALSE,  FALSE,  FALSE, RBR_PREC    );
  308. X  load(KW_INCLUDE,     INCLUDE,        FALSE,  FALSE,  FALSE, NO_PREC     );
  309. X  load(KW_SYSINCLUDE,  SYS_INCLUDE,    FALSE,  FALSE,  FALSE, NO_PREC     );
  310. X  load(KW_PREPEND,     PREPEND,        FALSE,  FALSE,  FALSE, NO_PREC     );
  311. X  load(KW_SYSPREPEND,  SYS_PREPEND,    FALSE,  FALSE,  FALSE, NO_PREC     );
  312. X  load(KW_DATABASE,    DATABASE,       FALSE,  FALSE,  FALSE, NO_PREC     );
  313. X  load(KW_SYSDATABASE, SYS_DATABASE,   FALSE,  FALSE,  FALSE, NO_PREC     );
  314. X  load(KW_USE,         USE,            FALSE,  FALSE,  FALSE, NO_PREC     );
  315. X  load(KW_CASE,        CASE,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  316. X  load(KW_YIELD,       YIELD,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  317. X  load(KW_FONT,        FONT,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  318. X  load(KW_SPACE,       SPACE,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  319. X  load(KW_BREAK,       BREAK,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  320. X  load(KW_NEXT,        NEXT,           FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  321. X  load(KW_OPEN,        OPEN,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  322. X  load(KW_TAGGED,      TAGGED,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  323. X  load(KW_HIGH,        HIGH,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  324. X  load(KW_WIDE,        WIDE,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  325. X  load(KW_ONE_COL,     ONE_COL,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  326. X  load(KW_ONE_ROW,     ONE_ROW,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  327. X  load(KW_HSCALE,      HSCALE,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  328. X  load(KW_VSCALE,      VSCALE,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  329. X  load(KW_SCALE,       SCALE,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  330. X  load(KW_HCONTRACT,   HCONTRACT,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  331. X  load(KW_VCONTRACT,   VCONTRACT,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  332. X  load(KW_HEXPAND,     HEXPAND,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  333. X  load(KW_VEXPAND,     VEXPAND,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  334. X  load(KW_PADJUST,     PADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  335. X  load(KW_HADJUST,     HADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  336. X  load(KW_VADJUST,     VADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  337. X  load(KW_ROTATE,      ROTATE,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  338. X  load(KW_INCGRAPHIC,  INCGRAPHIC,     FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  339. X  load(KW_SINCGRAPHIC, SINCGRAPHIC,    FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  340. X  load(KW_GRAPHIC,     GRAPHIC,        TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  341. X  load(KW_CROSS,       CROSS,          TRUE,   TRUE,   FALSE, CROSSOP_PREC);
  342. X  load(KW_NULL,        NULL_CLOS,      FALSE,  FALSE,  TRUE,  NO_PREC     );
  343. X
  344. X#define setcat(s, mk, jn)  has_mark(s)=mk, has_join(s)=jn
  345. X
  346. X  s=load(KW_VCAT_NN, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,FALSE,FALSE);
  347. X  s=load(KW_VCAT_MN, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,TRUE, FALSE);
  348. X  s=load(KW_VCAT_NJ, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,FALSE,TRUE);
  349. X  s=load(KW_VCAT_MJ, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,TRUE, TRUE);
  350. X  s=load(KW_HCAT_NN, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,FALSE,FALSE);
  351. X  s=load(KW_HCAT_MN, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,TRUE, FALSE);
  352. X  s=load(KW_HCAT_NJ, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,FALSE,TRUE);
  353. X  s=load(KW_HCAT_MJ, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,TRUE, TRUE);
  354. X  s=load(KW_ACAT_NJ, ACAT, TRUE, TRUE, FALSE, ACAT_PREC); setcat(s,FALSE,TRUE);
  355. X  s=load(KW_ACAT_MJ, ACAT, TRUE, TRUE, FALSE, ACAT_PREC); setcat(s,TRUE, TRUE);
  356. X
  357. X  /* intialize current time and load @Moment symbol */
  358. X  InitTime();
  359. X
  360. X  /* initialise scope chain to <StartSym> */
  361. X  PushScope(StartSym, FALSE, FALSE);
  362. X
  363. X  /* initialise lexical analyser */
  364. X  LexPush(FirstFile(SOURCE_FILE), 0, SOURCE_FILE);
  365. X
  366. X  /* process input files */
  367. X  InitParser(cross_db);
  368. X  t = NewToken(BEGIN, no_fpos, 0, 0, BEGIN_PREC, StartSym);
  369. X  res = Parse(&t, StartSym, TRUE, TRUE);
  370. X  TransferEnd(res);
  371. X  TransferClose();
  372. X
  373. X  /* close various  modules */
  374. X  PrintClose();
  375. X  CrossClose();
  376. X  CloseFiles();
  377. X
  378. X  /* wrapup */
  379. X  ifdebug(DST, D, CheckSymSpread() );
  380. X  debug0(ANY, D, "commencing deletes");
  381. X  ifdebug(ANY, D, DeleteEverySym() );
  382. X  ifdebug(DMA, D, DebugMemory() );
  383. X  ifdebug(DPP, D, ProfileOff("main"));
  384. X  ifdebug(DPP, D, ProfilePrint());
  385. X  exit(0);
  386. X  return 0;
  387. X} /* end main */
  388. END_OF_FILE
  389.   if test 16696 -ne `wc -c <'lout/z01.c'`; then
  390.     echo shar: \"'lout/z01.c'\" unpacked with wrong size!
  391.   fi
  392.   # end of 'lout/z01.c'
  393. fi
  394. if test -f 'lout/z04.c' -a "${1}" != "-c" ; then 
  395.   echo shar: Will not clobber existing file \"'lout/z04.c'\"
  396. else
  397.   echo shar: Extracting \"'lout/z04.c'\" \(7382 characters\)
  398.   sed "s/^X//" >'lout/z04.c' <<'END_OF_FILE'
  399. X/*@z04.c:Token Service:NewToken(), CopyTokenList(), EchoToken()@**************/
  400. X/*                                                                           */
  401. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.03)       */
  402. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  403. X/*                                                                           */
  404. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  405. X/*  Basser Department of Computer Science                                    */
  406. X/*  The University of Sydney 2006                                            */
  407. X/*  AUSTRALIA                                                                */
  408. X/*                                                                           */
  409. X/*  This program is free software; you can redistribute it and/or modify     */
  410. X/*  it under the terms of the GNU General Public License as published by     */
  411. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  412. X/*  any later version.                                                       */
  413. X/*                                                                           */
  414. X/*  This program is distributed in the hope that it will be useful,          */
  415. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  416. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  417. X/*  GNU General Public License for more details.                             */
  418. X/*                                                                           */
  419. X/*  You should have received a copy of the GNU General Public License        */
  420. X/*  along with this program; if not, write to the Free Software              */
  421. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  422. X/*                                                                           */
  423. X/*  FILE:         z04.c                                                      */
  424. X/*  MODULE:       Token Service                                              */
  425. X/*  EXTERNS:      NewToken(), CopyTokenList(), EchoCatOp(), EchoToken()      */
  426. X/*                                                                           */
  427. X/*****************************************************************************/
  428. X#include "externs"
  429. X
  430. X
  431. X/*****************************************************************************/
  432. X/*                                                                           */
  433. X/*  OBJECT NewToken(xtype, xfpos, xvspace, xhspace, xprec, xactual)          */
  434. X/*                                                                           */
  435. X/*  Returns a new non-WORD token initialised as the parameters indicate.     */
  436. X/*                                                                           */
  437. X/*****************************************************************************/
  438. X
  439. XOBJECT NewToken(xtype, xfpos, xvspace, xhspace, xprec, xactual)
  440. Xunsigned char xtype;  FILE_POS *xfpos;  unsigned char xvspace, xhspace;  unsigned char xprec;
  441. XOBJECT xactual;
  442. X{ OBJECT res;
  443. X  debug1(DTS, DDD, "NewToken(%s, ...)", Image(xtype));
  444. X  res = New(xtype);
  445. X  FposCopy(fpos(res), *xfpos);
  446. X  vspace(res) = xvspace;
  447. X  hspace(res) = xhspace;
  448. X  precedence(res) = xprec;
  449. X  actual(res) = xactual;
  450. X  debug1(DTS, DDD, "NewToken returning %s", EchoToken(res));
  451. X  return res;
  452. X} /* end NewToken */
  453. X
  454. X
  455. X/*****************************************************************************/
  456. X/*                                                                           */
  457. X/*  OBJECT CopyTokenList(x, pos)                                             */
  458. X/*                                                                           */
  459. X/*  Returns a copy of the list of tokens pointed to by x.                    */
  460. X/*  All file positions in the copy are set to *pos.                          */
  461. X/*                                                                           */
  462. X/*****************************************************************************/
  463. X
  464. XOBJECT CopyTokenList(x, pos)
  465. XOBJECT x;  FILE_POS *pos;
  466. X{ OBJECT y, z, res;
  467. X  res = nil;
  468. X  y = x;
  469. X  if( x != nil )
  470. X  do
  471. X  { if( type(y) == WORD )
  472. X    { z = MakeWord(string(y), pos);
  473. X      vspace(z) = vspace(y);
  474. X      hspace(z) = hspace(y);
  475. X    }
  476. X    else z = NewToken(type(y), pos,vspace(y),hspace(y),precedence(y),actual(y));
  477. X    res = Append(res, z, PARENT);
  478. X    y = succ(y, PARENT);
  479. X  } while( y != x );
  480. X  return res;
  481. X} /* end CopyTokenList */
  482. X
  483. X
  484. X/*@@**************************************************************************/
  485. X/*                                                                           */
  486. X/*  unsigned char *EchoCatOp(xtype, xmark, xjoin)                            */
  487. X/*                                                                           */
  488. X/*  Return the catenation operator with this type, mark and join.            */
  489. X/*                                                                           */
  490. X/*****************************************************************************/
  491. X
  492. Xunsigned char *EchoCatOp(xtype, xmark, xjoin)
  493. Xunsigned xtype;  BOOLEAN xmark, xjoin;
  494. X{ switch( xtype )
  495. X  {
  496. X      case VCAT:   return (unsigned char *)
  497. X            (xmark    ? xjoin    ? KW_VCAT_MJ : KW_VCAT_MN
  498. X                : xjoin    ? KW_VCAT_NJ : KW_VCAT_NN);
  499. X
  500. X      case HCAT:   return (unsigned char *)
  501. X            (xmark    ? xjoin    ? KW_HCAT_MJ : KW_HCAT_MN
  502. X                : xjoin    ? KW_HCAT_NJ : KW_HCAT_NN);
  503. X
  504. X      case ACAT:   return (unsigned char *)
  505. X            (xmark    ? xjoin    ? KW_ACAT_MJ : "??"
  506. X                : xjoin    ? KW_ACAT_NJ : "??");
  507. X
  508. X      default:       Error(INTERN, no_fpos, "EchoCatOp: xtype = %d", xtype);
  509. X           return (unsigned char *) "";
  510. X
  511. X  } /* end switch */
  512. X} /* end EchoCatOp */
  513. X
  514. X
  515. X#if DEBUG_ON
  516. X/*****************************************************************************/
  517. X/*                                                                           */
  518. X/*  unsigned char *EchoToken(x)                                              */
  519. X/*                                                                           */
  520. X/*  Return an image of token x.  Do not worry about preceding space.         */
  521. X/*                                                                           */
  522. X/*****************************************************************************/
  523. X
  524. Xunsigned char *EchoToken(x)
  525. XOBJECT x;
  526. X{ switch( type(x) )
  527. X  {
  528. X    case WORD:
  529. X    
  530. X      return string(x);
  531. X      break;
  532. X
  533. X
  534. X    case TSPACE:
  535. X    case TJUXTA:
  536. X    case USE:
  537. X    case GSTUB_EXT:
  538. X    case GSTUB_INT:
  539. X    case GSTUB_NONE:
  540. X    
  541. X      return Image(type(x));
  542. X      break;
  543. X
  544. X
  545. X    case BEGIN:
  546. X    case END:
  547. X    case ENV:
  548. X    case CLOS:
  549. X    case LBR:
  550. X    case RBR:
  551. X    case NULL_CLOS:
  552. X    case CROSS:
  553. X    case ONE_COL:
  554. X    case ONE_ROW:
  555. X    case WIDE:
  556. X    case HIGH:
  557. X    case HSCALE:
  558. X    case VSCALE:
  559. X    case SCALE:
  560. X    case HCONTRACT:
  561. X    case VCONTRACT:
  562. X    case HEXPAND:
  563. X    case VEXPAND:
  564. X    case PADJUST:
  565. X    case HADJUST:
  566. X    case VADJUST:
  567. X    case ROTATE:
  568. X    case CASE:
  569. X    case YIELD:
  570. X    case FONT:
  571. X    case SPACE:
  572. X    case BREAK:
  573. X    case NEXT:
  574. X    case OPEN:
  575. X    case TAGGED:
  576. X    case INCGRAPHIC:
  577. X    case SINCGRAPHIC:
  578. X    case GRAPHIC:
  579. X    case ACAT:
  580. X    case HCAT:
  581. X    case VCAT:
  582. X    case CLOSURE:
  583. X    
  584. X      return SymName(actual(x));
  585. X      break;
  586. X
  587. X
  588. X    default:
  589. X    
  590. X      Error(INTERN, &fpos(x), "EchoToken: %s", Image(type(x)));
  591. X      break;
  592. X  }
  593. X  return (unsigned char *) "";
  594. X} /* end EchoToken */
  595. X#endif
  596. END_OF_FILE
  597.   if test 7382 -ne `wc -c <'lout/z04.c'`; then
  598.     echo shar: \"'lout/z04.c'\" unpacked with wrong size!
  599.   fi
  600.   # end of 'lout/z04.c'
  601. fi
  602. if test -f 'lout/z05.c' -a "${1}" != "-c" ; then 
  603.   echo shar: Will not clobber existing file \"'lout/z05.c'\"
  604. else
  605.   echo shar: Extracting \"'lout/z05.c'\" \(18300 characters\)
  606.   sed "s/^X//" >'lout/z05.c' <<'END_OF_FILE'
  607. X/*@z05.c:Read Definitions:ReadDefinitions()@**********************************/
  608. X/*                                                                           */
  609. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.03)       */
  610. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  611. X/*                                                                           */
  612. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  613. X/*  Basser Department of Computer Science                                    */
  614. X/*  The University of Sydney 2006                                            */
  615. X/*  AUSTRALIA                                                                */
  616. X/*                                                                           */
  617. X/*  This program is free software; you can redistribute it and/or modify     */
  618. X/*  it under the terms of the GNU General Public License as published by     */
  619. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  620. X/*  any later version.                                                       */
  621. X/*                                                                           */
  622. X/*  This program is distributed in the hope that it will be useful,          */
  623. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  624. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  625. X/*  GNU General Public License for more details.                             */
  626. X/*                                                                           */
  627. X/*  You should have received a copy of the GNU General Public License        */
  628. X/*  along with this program; if not, write to the Free Software              */
  629. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  630. X/*                                                                           */
  631. X/*  FILE:         z05.c                                                      */
  632. X/*  MODULE:       Read Definitions                                           */
  633. X/*  EXTERNS:      ReadDefinitions()                                          */
  634. X/*                                                                           */
  635. X/*****************************************************************************/
  636. X#include "externs"
  637. X
  638. X/*****************************************************************************/
  639. X/*                                                                           */
  640. X/*  check(typ, str, arg1, arg2)                                              */
  641. X/*                                                                           */
  642. X/*  If type(t) != typ, exit with error message.                              */
  643. X/*                                                                           */
  644. X/*****************************************************************************/
  645. X
  646. X#define check(typ, str, arg1, arg2)                    \
  647. Xif( type(t) != typ )                            \
  648. X{ Error(WARN, &fpos(t), str, arg1, arg2);                \
  649. X  debug1(ANY, D, "offending type is %s", Image(type(t)));        \
  650. X  UnSuppressScope();                            \
  651. X  *token = t;                                \
  652. X  return;                                \
  653. X} else
  654. X
  655. X
  656. X/*****************************************************************************/
  657. X/*                                                                           */
  658. X/*  word_check(word, str, arg1, arg2)                                        */
  659. X/*                                                                           */
  660. X/*  If t is not the given word, exit with error message.                     */
  661. X/*                                                                           */
  662. X/*****************************************************************************/
  663. X
  664. X#define word_check(word, str, arg1, arg2)                \
  665. Xif( type(t) != WORD || strcmp(string(t), word) != 0 )            \
  666. X{ Error(WARN, &fpos(t), str, arg1, arg2);                \
  667. X  debug1(ANY, D, "offending object is %s",                \
  668. X    type(t) == WORD ? string(t) : Image(type(t)));            \
  669. X  UnSuppressScope();                            \
  670. X  *token = t;                                \
  671. X  return;                                \
  672. X} else
  673. X
  674. X
  675. X/*****************************************************************************/
  676. X/*                                                                           */
  677. X/*  is_word(t, str)                                                          */
  678. X/*                                                                           */
  679. X/*  If t is a token denoting word str, return TRUE.                          */
  680. X/*                                                                           */
  681. X/*****************************************************************************/
  682. X
  683. X#define is_word(t, str)        (type(t) == WORD && strcmp(string(t), str) == 0)
  684. X
  685. X
  686. X/*****************************************************************************/
  687. X/*                                                                           */
  688. X/*  static ReadFontDef(token, encl)                                          */
  689. X/*                                                                           */
  690. X/*  Read one font definition and pass it on to the font module.  The         */
  691. X/*  syntax is  fontdef <family> <face> { <word> }.                           */
  692. X/*                                                                           */
  693. X/*****************************************************************************/
  694. X
  695. Xstatic ReadFontDef(token, encl)
  696. XOBJECT *token, encl;
  697. X{ OBJECT t, res[5];  int i;
  698. X  
  699. X  Dispose(*token);
  700. X  SuppressScope();
  701. X  for( i = 0;  i < 5;  i++ )
  702. X  { t = LexGetToken();
  703. X    check(WORD, "syntax error in %s", KW_FONTDEF, 0);
  704. X    if( type(t) == WORD && string(t)[0] == '"' )
  705. X      FontStripQuotes(string(t), &fpos(t));
  706. X    res[i] = t;
  707. X  }
  708. X  if( strcmp(string(res[2]), KW_LBR) != 0 )
  709. X    Error(WARN, &fpos(res[2]), "missing %s in fontdef", KW_LBR);
  710. X  if( strcmp(string(res[4]), KW_RBR) != 0 )
  711. X    Error(WARN, &fpos(res[4]), "missing %s in fontdef", KW_RBR);
  712. X  Dispose(res[2]);  Dispose(res[4]);
  713. X  FontDefine(res[0], res[1], res[3]);
  714. X  *token = nil;
  715. X  UnSuppressScope();
  716. X  return;
  717. X} /* end ReadFontDef */
  718. X
  719. X
  720. X/*@@**************************************************************************/
  721. X/*                                                                           */
  722. X/*  static ReadTokenList(res)                                                */
  723. X/*                                                                           */
  724. X/*  Read a list of tokens from input and append them to sym_body(res).       */
  725. X/*  The list is assumed to begin immediately after an LBR, and input is      */
  726. X/*  to be read up to and including the matching RBR.                         */
  727. X/*                                                                           */
  728. X/*****************************************************************************/
  729. X#define NextToken(t, res)                        \
  730. X  t = LexGetToken(); sym_body(res) = Append(sym_body(res), t, PARENT);
  731. X
  732. Xstatic ReadTokenList(res)
  733. XOBJECT res;
  734. X{ OBJECT t, xsym, new_par;
  735. X  NextToken(t, res);
  736. X  for(;;) switch(type(t))
  737. X  {
  738. X    case WORD:
  739. X
  740. X      if( string(t)[0] == '@' )
  741. X    Error(WARN, &fpos(t), "symbol %s unknown", string(t));
  742. X      NextToken(t, res);
  743. X      break;
  744. X
  745. X
  746. X    case VCAT:
  747. X    case HCAT:
  748. X    case ACAT:
  749. X    case CROSS:
  750. X    case NULL_CLOS:
  751. X    case ONE_COL:
  752. X    case ONE_ROW:
  753. X    case WIDE:
  754. X    case HIGH:
  755. X    case HSCALE:
  756. X    case VSCALE:
  757. X    case SCALE:
  758. X    case HCONTRACT:
  759. X    case VCONTRACT:
  760. X    case HEXPAND:
  761. X    case VEXPAND:
  762. X    case PADJUST:
  763. X    case HADJUST:
  764. X    case VADJUST:
  765. X    case ROTATE:
  766. X    case CASE:
  767. X    case YIELD:
  768. X    case FONT:
  769. X    case SPACE:
  770. X    case BREAK:
  771. X    case NEXT:
  772. X    case TAGGED:
  773. X    case INCGRAPHIC:
  774. X    case SINCGRAPHIC:
  775. X    case GRAPHIC:
  776. X
  777. X      NextToken(t, res);
  778. X      break;
  779. X
  780. X
  781. X    case LVIS:
  782. X    case ENV:
  783. X    case USE:
  784. X    case BEGIN:
  785. X    case END:
  786. X    case OPEN:
  787. X
  788. X      Error(WARN,&fpos(t),"symbol %s not allowed in macro", SymName(actual(t)));
  789. X      NextToken(t, res);
  790. X      break;
  791. X
  792. X
  793. X    case LBR:
  794. X
  795. X      ReadTokenList(res);
  796. X      NextToken(t, res);
  797. X      break;
  798. X
  799. X
  800. X    case RBR:
  801. X
  802. X      return;
  803. X
  804. X
  805. X    case CLOSURE:
  806. X
  807. X      xsym = actual(t);
  808. X      PushScope(xsym, TRUE, FALSE);
  809. X      NextToken(t, res);
  810. X      PopScope();
  811. X      if( type(t) == CROSS )
  812. X      { NextToken(t, res);
  813. X    break;
  814. X      }
  815. X
  816. X      /* read named parameters */
  817. X      while( type(t) == CLOSURE && enclosing(actual(t)) == xsym &&
  818. X         type(actual(t)) == NPAR )
  819. X      {    new_par = t;
  820. X    NextToken(t, res);
  821. X    if( type(t) != LBR )
  822. X    { Error(WARN, &fpos(new_par), "%s must follow name parameter %s",
  823. X        KW_LBR, SymName(actual(new_par)));
  824. X      break;
  825. X    }
  826. X    PushScope(actual(new_par), FALSE, FALSE);
  827. X    ReadTokenList(res);
  828. X    PopScope();
  829. X
  830. X    /* get next token, possibly another named parameter */
  831. X    PushScope(xsym, TRUE, FALSE);
  832. X    NextToken(t, res);
  833. X    PopScope();
  834. X      }
  835. X
  836. X      /* read body parameter, if any */
  837. X      if( has_body(xsym) )
  838. X      {    if( type(t) == LBR )
  839. X    { PushScope(xsym, FALSE, TRUE);
  840. X      PushScope(ChildSym(xsym, RPAR), FALSE, FALSE);
  841. X      ReadTokenList(res);
  842. X      PopScope();
  843. X      PopScope();
  844. X      NextToken(t, res);
  845. X    }
  846. X    else Error(WARN, &fpos(t), "right parameter of %s must begin with %s",
  847. X        SymName(xsym), KW_LBR);
  848. X      }
  849. X      break;
  850. X
  851. X    default:
  852. X
  853. X
  854. X      Error(INTERN, &fpos(t), "unknown token type %s", Image(type(t)));
  855. X      break;
  856. X
  857. X  }
  858. X} /* end ReadTokenList */
  859. X
  860. X
  861. X/*@@**************************************************************************/
  862. X/*                                                                           */
  863. X/*  static ReadMacro(token, encl)                                            */
  864. X/*                                                                           */
  865. X/*  Read a macro from input and insert into symbol table.                    */
  866. X/*  Token *token contains the "macro" keyword.  Input is read up to and      */
  867. X/*  including the closing right brace, and nil is returned in *token if OK.  */
  868. X/*  The proper scope for reading the macro body is open at entry and exit.   */
  869. X/*                                                                           */
  870. X/*****************************************************************************/
  871. X
  872. Xstatic OBJECT ReadMacro(token, encl)
  873. XOBJECT *token, encl;
  874. X{ OBJECT t, res;  int depth;
  875. X
  876. X  /* find macro name and insert into symbol table */
  877. X  SuppressScope();
  878. X  Dispose(*token);  t = LexGetToken();
  879. X  check(WORD, "%s ignored - can't find name", KW_MACRO, 0);
  880. X  res = InsertSym(string(t), MACRO, &fpos(t), 0, FALSE, TRUE, 0, encl, nil);
  881. X
  882. X  /* find opening left brace */
  883. X  t = LexGetToken();
  884. X  word_check(KW_LBR, "%s ignored - can't find opening %s", KW_MACRO, KW_LBR);
  885. X  Dispose(t);
  886. X  
  887. X  /* read macro body */
  888. X  UnSuppressScope();
  889. X  ReadTokenList(res);
  890. X
  891. X  /* clean up (kill final RBR, dispose macro name) and exit */
  892. X  sym_body(res) = DeleteAndDispose(pred(sym_body(res), PARENT), PARENT);
  893. X  recursive(res) = FALSE;
  894. X  *token = nil;
  895. X  return res;
  896. X} /* end ReadMacro */
  897. X
  898. X
  899. X/*@@**************************************************************************/
  900. X/*                                                                           */
  901. X/*  ReadDefinitions(token, encl, res_type)                                   */
  902. X/*                                                                           */
  903. X/*  Read a sequence of definitions and insert them into the symbol table.    */
  904. X/*  Either a sequence of local definitions (res_type == LOCAL) or named      */
  905. X/*  parameters (res_type == NPAR) is expected; *token is the first def etc.  */
  906. X/*  A scope appropriate for reading the bodies of the definitions is open.   */
  907. X/*  The parent definition is encl.                                           */
  908. X/*                                                                           */
  909. X/*****************************************************************************/
  910. X
  911. XReadDefinitions(token, encl, res_type)
  912. XOBJECT *token, encl;  unsigned char res_type;
  913. X{ OBJECT t, res, res_target, export_list, import_list, link, y, z;
  914. X  t = *token;
  915. X
  916. X  
  917. X  while( res_type != LOCAL ? is_word(t, KW_NAMED) :
  918. X        is_word(t, KW_DEF) || is_word(t, KW_MACRO) || is_word(t, KW_FONTDEF)
  919. X      || is_word(t, KW_IMPORT) || is_word(t, KW_EXPORT) )
  920. X  {
  921. X    if( is_word(t, KW_FONTDEF) )
  922. X    { ReadFontDef(&t, encl);
  923. X      if( t == nil ) t = LexGetToken();
  924. X      continue;  /* next definition */
  925. X    }
  926. X
  927. X    /* get import list and change scope appropriately */
  928. X    BodyParNotAllowed();
  929. X    import_list = New(ACAT);
  930. X    if( is_word(t, KW_IMPORT) )
  931. X    { Dispose(t);
  932. X      t = LexGetToken();
  933. X      while( type(t) == CLOSURE ||
  934. X           (type(t)==WORD && !is_word(t,KW_EXPORT) && !is_word(t,KW_DEF)
  935. X           && !is_word(t, KW_MACRO)) )
  936. X      {    if( type(t) == CLOSURE )
  937. X    { if( type(actual(t)) == LOCAL )
  938. X      { PushScope(actual(t), FALSE, TRUE);
  939. X        Link(import_list, t);
  940. X      }
  941. X      else
  942. X      { Error(WARN, &fpos(t), "import name expected here");
  943. X        Dispose(t);
  944. X      }
  945. X    }
  946. X    else
  947. X    { Error(WARN, &fpos(t), "import %s not in scope", string(t));
  948. X      Dispose(t);
  949. X    }
  950. X    t = LexGetToken();
  951. X      }
  952. X    }
  953. X
  954. X    /* get export list and store for setting visible flags below */
  955. X    export_list = New(ACAT);
  956. X    if( is_word(t, KW_EXPORT) )
  957. X    { Dispose(t);
  958. X      SuppressScope();
  959. X      t = LexGetToken();
  960. X      while( type(t) == WORD && !is_word(t, KW_DEF) )
  961. X      {    if( string(t)[0] == '"' )  FontStripQuotes(string(t), &fpos(t));
  962. X    Link(export_list, t);
  963. X    t = LexGetToken();
  964. X      }
  965. X      UnSuppressScope();
  966. X    }
  967. X
  968. X
  969. X    if( res_type == LOCAL && !is_word(t, KW_DEF) && !is_word(t, KW_MACRO) )
  970. X    { Error(WARN,&fpos(t),"keyword %s or %s expected here", KW_DEF, KW_MACRO);
  971. X      break;
  972. X    }
  973. X    if( res_type == NPAR && !is_word(t, KW_NAMED) )
  974. X    { Error(WARN, &fpos(t), "keyword %s expected here", KW_NAMED);
  975. X      break;
  976. X    }
  977. X
  978. X    if( is_word(t, KW_MACRO) )
  979. X    { if( Down(export_list) != export_list )
  980. X    Error(WARN, &fpos(t), "ignoring %s list of %s", KW_EXPORT, KW_MACRO);
  981. X      res = ReadMacro(&t, encl);
  982. X    }
  983. X    else
  984. X    {
  985. X      SuppressScope();  Dispose(t);  t = LexGetToken();
  986. X
  987. X      /* find name of symbol and insert it */
  988. X      check(WORD, "can't find symbol name", 0, 0);
  989. X      res = InsertSym(string(t), res_type, &fpos(t), DEFAULT_PREC,
  990. X        FALSE, FALSE, 0, encl, nil);
  991. X      t = LexGetToken();
  992. X
  993. X      /* find force, if any */
  994. X      if( is_word(t, KW_FORCE) )
  995. X      {    force_target(res) = TRUE;
  996. X    Dispose(t);  t = LexGetToken();
  997. X    if( !is_word(t, KW_INTO) )
  998. X       Error(WARN, &fpos(t), "%s expected after %s", KW_INTO, KW_FORCE);
  999. X      }
  1000. X    
  1001. X      /* find into clause, if any */
  1002. X      res_target = nil;
  1003. X      if( is_word(t, KW_INTO) )
  1004. X      { UnSuppressScope();
  1005. X    Dispose(t);  t = LexGetToken();
  1006. X    check(LBR, "%s expected after %s", KW_LBR, KW_INTO);
  1007. X    res_target = Parse(&t, encl, FALSE, FALSE);
  1008. X    SuppressScope();
  1009. X    if( t == nil )  t = LexGetToken();
  1010. X      }
  1011. X
  1012. X      /* find precedence clause, if any */
  1013. X      if( is_word(t, KW_PRECEDENCE) )
  1014. X      {    int prec = 0;
  1015. X    Dispose(t);
  1016. X    t = LexGetToken();
  1017. X    while( type(t) == WORD && string(t)[0] >= '0' && string(t)[0] <= '9' )
  1018. X    {
  1019. X      /* check(WORD, "can't find value of %s", KW_PRECEDENCE, 0); */
  1020. X      prec = prec * 10 + string(t)[0] - '0';
  1021. X      Dispose(t);  t = LexGetToken();
  1022. X    }
  1023. X
  1024. X    if( prec < MIN_PREC )
  1025. X    { Error(WARN, &fpos(t), "%s is too low - %d substituted",
  1026. X        KW_PRECEDENCE, MIN_PREC );
  1027. X      prec = MIN_PREC;
  1028. X    }
  1029. X    else if( prec > MAX_PREC )
  1030. X    { Error(WARN, &fpos(t), "%s is too high - %d substituted",
  1031. X            KW_PRECEDENCE, MAX_PREC );
  1032. X      prec = MAX_PREC;
  1033. X    }
  1034. X    precedence(res) = prec;
  1035. X      }
  1036. X
  1037. X      /* find associativity clause, if any */
  1038. X      if( is_word(t, KW_ASSOC) )
  1039. X      {    Dispose(t);  t = LexGetToken();
  1040. X    if( is_word(t, KW_LEFT) )  right_assoc(res) = FALSE;
  1041. X    else if( !is_word(t, KW_RIGHT) )
  1042. X      Error(WARN, &fpos(t), "%s replaced by %s", KW_ASSOC, KW_RIGHT);
  1043. X    Dispose(t);  t = LexGetToken();
  1044. X      }
  1045. X
  1046. X      /* find left parameter, if any */
  1047. X      if( is_word(t, KW_LEFT) )
  1048. X      {    Dispose(t);  t = LexGetToken();
  1049. X    check(WORD, "can't find %s parameter name", KW_LEFT, 0);
  1050. X    InsertSym(string(t), LPAR, &fpos(t), DEFAULT_PREC, 
  1051. X      FALSE, FALSE, 0, res, nil);
  1052. X    Dispose(t);  t = LexGetToken();
  1053. X      }
  1054. X
  1055. X      /* find named parameters, if any */
  1056. X      UnSuppressScope();
  1057. X      ReadDefinitions(&t, res, NPAR);
  1058. X
  1059. X      /* find right or body parameter, if any */
  1060. X      if( is_word(t, KW_RIGHT) || is_word(t, KW_BODY) )
  1061. X      {    has_body(res) = is_word(t, KW_BODY);
  1062. X    SuppressScope();
  1063. X    Dispose(t);  t = LexGetToken();
  1064. X    check(WORD, "can't find %s parameter name", KW_RIGHT, 0);
  1065. X    InsertSym(string(t), RPAR, &fpos(t), DEFAULT_PREC,
  1066. X      FALSE, FALSE, 0, res, nil);
  1067. X    UnSuppressScope();
  1068. X    Dispose(t);  t = LexGetToken();
  1069. X      }
  1070. X
  1071. X      /* read local definitions and body */
  1072. X      if( res_target != nil )
  1073. X    InsertSym(KW_TARGET, LOCAL, &fpos(res_target), DEFAULT_PREC,
  1074. X            FALSE, FALSE, 0, res, res_target);
  1075. X      if( type(t) == WORD && strcmp(string(t), KW_LBR) == 0 )
  1076. X      {    z = NewToken(LBR, &fpos(t), 0, 0, LBR_PREC, StartSym);
  1077. X    Dispose(t);
  1078. X    t = z;
  1079. X      }
  1080. X      else if( type(t) == WORD && strcmp(string(t), KW_BEGIN) == 0 )
  1081. X      {    z = NewToken(BEGIN, &fpos(t), 0, 0, BEGIN_PREC, StartSym);
  1082. X    Dispose(t);
  1083. X    t = z;
  1084. X      }
  1085. X      else if( type(t) != LBR && type(t) != BEGIN )
  1086. X    Error(FATAL, &fpos(t), "opening %s or %s of %s expected",
  1087. X      KW_LBR, KW_BEGIN, SymName(res));
  1088. X      if( type(t) == BEGIN )  actual(t) = res;
  1089. X      PushScope(res, FALSE, FALSE);
  1090. X      BodyParAllowed();
  1091. X      sym_body(res) = Parse(&t, res, TRUE, FALSE);
  1092. X
  1093. X      /* set visible flag of the exported symbols */
  1094. X      for( link=Down(export_list);  link != export_list;  link=NextDown(link) )
  1095. X      {    Child(y, link);
  1096. X    z = SearchSym(string(y), strlen(string(y)));
  1097. X    if( z == nil || enclosing(z) != res )
  1098. X      Error(WARN, &fpos(y), "exported symbol %s not defined in %s",
  1099. X        string(y), SymName(res));
  1100. X    else if( has_body(res) && type(z) == RPAR )
  1101. X      Error(WARN, &fpos(y), "body parameter %s may not be exported",
  1102. X        string(y));
  1103. X    else if( visible(z) )
  1104. X      Error(WARN, &fpos(y), "symbol %s exported twice", string(y));
  1105. X    else visible(z) = TRUE;
  1106. X      }
  1107. X      DisposeObject(export_list);
  1108. X
  1109. X      /* pop scope of res */
  1110. X      PopScope();
  1111. X    }
  1112. X
  1113. X    /* pop import scopes and store imports in sym tab */
  1114. X    for( link=Down(import_list);  link != import_list;  link=NextDown(link) )
  1115. X      PopScope();
  1116. X    if( Down(import_list) == import_list )
  1117. X    { Dispose(import_list);
  1118. X      import_list = nil;
  1119. X    }
  1120. X    imports(res) = import_list;
  1121. X
  1122. X    BodyParAllowed();
  1123. X    if( t == nil ) t = LexGetToken();
  1124. X
  1125. X  } /* end while */
  1126. X
  1127. X  *token = t;
  1128. X  return;
  1129. X} /* end ReadDefinitions */
  1130. END_OF_FILE
  1131.   if test 18300 -ne `wc -c <'lout/z05.c'`; then
  1132.     echo shar: \"'lout/z05.c'\" unpacked with wrong size!
  1133.   fi
  1134.   # end of 'lout/z05.c'
  1135. fi
  1136. if test -f 'lout/z12.c' -a "${1}" != "-c" ; then 
  1137.   echo shar: Will not clobber existing file \"'lout/z12.c'\"
  1138. else
  1139.   echo shar: Extracting \"'lout/z12.c'\" \(18672 characters\)
  1140.   sed "s/^X//" >'lout/z12.c' <<'END_OF_FILE'
  1141. X/*@z12.c:Size Finder:MinSize()@***********************************************/
  1142. X/*                                                                           */
  1143. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.03)       */
  1144. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  1145. X/*                                                                           */
  1146. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  1147. X/*  Basser Department of Computer Science                                    */
  1148. X/*  The University of Sydney 2006                                            */
  1149. X/*  AUSTRALIA                                                                */
  1150. X/*                                                                           */
  1151. X/*  This program is free software; you can redistribute it and/or modify     */
  1152. X/*  it under the terms of the GNU General Public License as published by     */
  1153. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  1154. X/*  any later version.                                                       */
  1155. X/*                                                                           */
  1156. X/*  This program is distributed in the hope that it will be useful,          */
  1157. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  1158. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  1159. X/*  GNU General Public License for more details.                             */
  1160. X/*                                                                           */
  1161. X/*  You should have received a copy of the GNU General Public License        */
  1162. X/*  along with this program; if not, write to the Free Software              */
  1163. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  1164. X/*                                                                           */
  1165. X/*  FILE:         z12.c                                                      */
  1166. X/*  MODULE:       Size Finder                                                */
  1167. X/*  EXTERNS:      MinSize()                                                  */
  1168. X/*                                                                           */
  1169. X/*****************************************************************************/
  1170. X#include "externs"
  1171. X#define IG_LOOKING    0
  1172. X#define IG_NOFILE    1
  1173. X#define IG_BADFILE    2
  1174. X#define IG_BADSIZE    3
  1175. X#define    IG_OK        4
  1176. X
  1177. X
  1178. X/*****************************************************************************/
  1179. X/*                                                                           */
  1180. X/*  OBJECT MinSize(x, dim, extras)                                           */
  1181. X/*                                                                           */
  1182. X/*  Set fwd(x, dim) and back(x, dim) to their minimum possible values.       */
  1183. X/*  If dim == ROW, construct an extras list and return it in *extras.        */
  1184. X/*                                                                           */
  1185. X/*****************************************************************************/
  1186. X
  1187. XOBJECT MinSize(x, dim, extras)
  1188. XOBJECT x;  int dim;  OBJECT *extras;
  1189. X{ OBJECT y, z, link, prev, t, g, full_name;
  1190. X  int b, f, dble_fwd, llx, lly, urx, ury, status;
  1191. X  float fllx, flly, furx, fury;
  1192. X  BOOLEAN dble_found, found, will_expand, first_line;
  1193. X  FILE *fp;  float scale_factor; unsigned char buff[MAX_LINE];
  1194. X
  1195. X  debug2(DSF, DD, "[ MinSize( %s, %s, extras )", EchoObject(null,x),dimen(dim));
  1196. X  ifdebug(DSF, DDD, EchoObject(stderr, x));
  1197. X
  1198. X  switch( type(x) )
  1199. X  {
  1200. X
  1201. X    case WORD:
  1202. X    
  1203. X      if( dim == COL )  FontAtomSize(x);
  1204. X      break;
  1205. X
  1206. X
  1207. X    case CROSS:
  1208. X
  1209. X      /* add index to the cross-ref */
  1210. X      if( dim == ROW )
  1211. X      {    z = New( (int) cross_type(x));
  1212. X    actual(z) = x;
  1213. X    Link(*extras, z);
  1214. X    debug1(DCR, DDD, "  MinSize: %s", EchoObject(null, z));
  1215. X      }
  1216. X      back(x, dim) = fwd(x, dim) = 0;
  1217. X      break;
  1218. X
  1219. X
  1220. X    case NULL_CLOS:
  1221. X    
  1222. X      back(x, dim) = fwd(x, dim) = 0;
  1223. X      break;
  1224. X
  1225. X
  1226. X    case HEAD:
  1227. X
  1228. X      if( dim == ROW )
  1229. X      {    
  1230. X    /* replace the galley x by a dummy closure y */
  1231. X    y = New(NULL_CLOS);
  1232. X    FposCopy(fpos(y), fpos(x));
  1233. X    ReplaceNode(y, x);
  1234. X
  1235. X    if( has_key(actual(x)) )
  1236. X    {
  1237. X      /* galley is sorted, make insinuated cross-reference */
  1238. X      z = backward(x) ? New(GALL_PREC) : New(GALL_FOLL);
  1239. X      Child(t, Down(x));
  1240. X      actual(z) = CrossMake(whereto(x), t, (int) type(z));
  1241. X      Link(*extras, z);
  1242. X      DisposeObject(x);
  1243. X      debug1(DCR, DDD, "  MinSize: %s", EchoObject(null, z));
  1244. X    }
  1245. X    else
  1246. X    {
  1247. X      /* galley is following, make UNATTACHED */
  1248. X      z = New(UNATTACHED);  Link(z, x);
  1249. X      Link(*extras, z);
  1250. X      debug1(DCR, DDD, "  MinSize: %s", EchoObject(null, z));
  1251. X    }
  1252. X    x = y;    /* now sizing y, not x */
  1253. X      }
  1254. X      else external(x) = FALSE;
  1255. X      back(x, dim) = fwd(x, dim) = 0;
  1256. X      break;
  1257. X
  1258. X
  1259. X    case CLOSURE:
  1260. X
  1261. X      assert( !has_target(actual(x)), "MinSize: CLOSURE has target!" );
  1262. X      if( dim == ROW )
  1263. X      { if( indefinite(actual(x)) )
  1264. X    { z = New(RECEPTIVE);
  1265. X      actual(z) = x;
  1266. X      Link(*extras, z);
  1267. X      debug1(DCR, DDD, "  MinSize: %s", EchoObject(null, z));
  1268. X    }
  1269. X    else if( recursive(actual(x)) )
  1270. X    { z = New(RECURSIVE);
  1271. X      actual(z) = x;
  1272. X      Link(*extras, z);
  1273. X      debug1(DCR, DDD, "  MinSize: %s", EchoObject(null, z));
  1274. X    }
  1275. X    else Error(INTERN,&fpos(x), "MinSize: definite non-recursive CLOSURE!");
  1276. X      }
  1277. X      else external(x) = FALSE;        /*  nb must be done just here! */
  1278. X      back(x, dim) = fwd(x, dim) = 0;
  1279. X      break;
  1280. X
  1281. X
  1282. X    case ONE_COL:
  1283. X    case ONE_ROW:
  1284. X    case PADJUST:
  1285. X    case HADJUST:
  1286. X    case VADJUST:
  1287. X    case HCONTRACT:
  1288. X    case VCONTRACT:
  1289. X    
  1290. X      Child(y, Down(x));
  1291. X      y = MinSize(y, dim, extras);
  1292. X      back(x, dim) = back(y, dim);
  1293. X      fwd(x, dim)  = fwd(y, dim);
  1294. X      break;
  1295. X
  1296. X
  1297. X    case HEXPAND:
  1298. X    case VEXPAND:
  1299. X
  1300. X      Child(y, Down(x));
  1301. X      y = MinSize(y, dim, extras);
  1302. X      back(x, dim) = back(y, dim);
  1303. X      fwd(x, dim)  = fwd(y, dim);
  1304. X
  1305. X      /* insert index into *extras for expanding later */
  1306. X      if( dim == ROW )
  1307. X      {    z = New(EXPAND_IND);
  1308. X    actual(z) = x;
  1309. X    Link(*extras, z);
  1310. X    debug1(DCR, DDD, "  MinSize: %s", EchoObject(null, z));
  1311. X      }    
  1312. X      break;
  1313. X
  1314. X
  1315. X    case GRAPHIC:
  1316. X    
  1317. X      Child(y, LastDown(x));
  1318. X      y = MinSize(y, dim, extras);
  1319. X      back(x, dim) = back(y, dim);
  1320. X      fwd(x, dim)  = fwd(y, dim);
  1321. X      break;
  1322. X
  1323. X
  1324. X    case HSCALE:
  1325. X    case VSCALE:
  1326. X
  1327. X      /* work out size and set to 0 if parallel */
  1328. X      Child(y, Down(x));
  1329. X      y = MinSize(y, dim, extras);
  1330. X      if( (dim == COL) == (type(x) == HSCALE) )
  1331. X    back(x, dim) = fwd(x, dim) = 0;
  1332. X      else
  1333. X      {    back(x, dim) = back(y, dim);
  1334. X    fwd(x, dim)  = fwd(y, dim);
  1335. X      }
  1336. X      break;
  1337. X
  1338. X
  1339. X    case ROTATE:
  1340. X    
  1341. X      Child(y, Down(x));
  1342. X      if( dim == COL )
  1343. X      {    y = MinSize(y, COL, extras);
  1344. X    whereto(x) = New(ACAT);
  1345. X    y = MinSize(y, ROW, &whereto(x));
  1346. X    RotateSize(&back(x, COL), &fwd(x, COL), &back(x, ROW), &fwd(x, ROW),
  1347. X      y, sparec(constraint(x)));
  1348. X      }
  1349. X      else
  1350. X      {    TransferLinks(Down(whereto(x)), whereto(x), *extras);
  1351. X    Dispose(whereto(x));
  1352. X      }
  1353. X      break;
  1354. X    
  1355. X
  1356. X    case SCALE:
  1357. X
  1358. X      Child(y, Down(x));
  1359. X      y = MinSize(y, dim, extras);
  1360. X      if( dim == COL )
  1361. X      { back(x, dim) = (back(y, dim) * bc(constraint(x))) / SF;
  1362. X        fwd(x, dim)  = (fwd(y, dim)  * bc(constraint(x))) / SF;
  1363. X      }
  1364. X      else
  1365. X      { back(x, dim) = (back(y, dim) * fc(constraint(x))) / SF;
  1366. X        fwd(x, dim)  = (fwd(y, dim)  * fc(constraint(x))) / SF;
  1367. X      }
  1368. X      break;
  1369. X
  1370. X
  1371. X    case WIDE:
  1372. X
  1373. X      Child(y, Down(x));
  1374. X      y = MinSize(y, dim, extras);
  1375. X      if( dim == COL )
  1376. X      { y = BreakObject(y, &constraint(x));
  1377. X        assert( FitsConstraint(back(y, dim), fwd(y, dim), constraint(x)),
  1378. X        "MinSize: BreakObject failed to fit!" );
  1379. X        back(x, dim) = back(y, dim);
  1380. X    fwd(x, dim)  = fwd(y, dim);
  1381. X    EnlargeToConstraint(&back(x, dim), &fwd(x, dim), &constraint(x));
  1382. X      }
  1383. X      else
  1384. X      {    back(x, dim) = back(y, dim);
  1385. X    fwd(x, dim)  = fwd(y, dim);
  1386. X      }
  1387. X      break;
  1388. X
  1389. X
  1390. X    case HIGH:
  1391. X    
  1392. X      Child(y, Down(x));
  1393. X      y = MinSize(y, dim, extras);
  1394. X      if( dim == ROW )
  1395. X      { if( !FitsConstraint(back(y, dim), fwd(y, dim), constraint(x)) )
  1396. X        { Error(WARN, &fpos(x), "forced to enlarge %s", KW_HIGH);
  1397. X      debug0(DSF, D, "offending object was:");
  1398. X      ifdebug(DSF, D, EchoObject(stderr, y));
  1399. X      SetConstraint(constraint(x), MAX_LEN, size(y, dim), MAX_LEN);
  1400. X        }
  1401. X        back(x, dim) = back(y, dim);
  1402. X    fwd(x, dim)  = fwd(y, dim);
  1403. X    EnlargeToConstraint(&back(x, dim), &fwd(x, dim), &constraint(x));
  1404. X      }
  1405. X      else
  1406. X      {    back(x, dim) = back(y, dim);
  1407. X    fwd(x, dim)  = fwd(y, dim);
  1408. X      }
  1409. X      break;
  1410. X
  1411. X
  1412. X    case SPLIT:
  1413. X    
  1414. X      link = DownDim(x, dim);  Child(y, link);
  1415. X      y = MinSize(y, dim, extras);
  1416. X      back(x, dim) = back(y, dim);
  1417. X      fwd(x, dim)  = fwd(y, dim);
  1418. X      break;
  1419. X
  1420. X
  1421. X    case ACAT:
  1422. X    case HCAT:
  1423. X    case VCAT:
  1424. X    
  1425. X      if( (dim == ROW) == (type(x) == VCAT) )
  1426. X      {
  1427. X    /********************************************************************/
  1428. X    /*                                                                  */
  1429. X    /*  Calculate sizes parallel to join direction; loop invariant is:  */
  1430. X    /*                                                                  */
  1431. X    /*     If prev == nil, there are no definite children equal to or   */
  1432. X    /*        to the left of Child(link).                               */
  1433. X    /*     If prev != nil, prev is the rightmost definite child to the  */
  1434. X    /*        left of Child(link), and (b, f) is the total size up to   */
  1435. X    /*        the mark of prev i.e. not including fwd(prev).            */
  1436. X    /*     g is the most recent gap, or nil if none found yet.          */
  1437. X    /*     will_expand == TRUE when a gap is found that is likely to    */
  1438. X    /*        enlarge when ActualGap is called later on.                */
  1439. X    /*                                                                  */
  1440. X    /********************************************************************/
  1441. X
  1442. X    prev = g = nil;  will_expand = FALSE;  must_expand(x) = FALSE;
  1443. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1444. X    { Child(y, link);
  1445. X      if( is_index(type(y)) )
  1446. X      { if( dim == ROW )
  1447. X        { link = PrevDown(link);
  1448. X          MoveLink(NextDown(link), *extras, PARENT);
  1449. X        }
  1450. X        continue;
  1451. X      }
  1452. X      else if( type(y) == type(x) )
  1453. X      { link = PrevDown(link);
  1454. X        TransferLinks(Down(y), y, NextDown(link));
  1455. X        DisposeChild(Up(y));
  1456. X        continue;
  1457. X      }
  1458. X      else if( type(y) == GAP_OBJ )  g = y;
  1459. X      else /* calculate size of y and accumulate it */
  1460. X      { if( type(y) == WORD )
  1461. X        { if( dim == COL )
  1462. X          {    FontAtomSize(y);
  1463. X        debug4(DSF, DD, "FontAtomSize( %s ) font %d = %s,%s",
  1464. X        EchoObject(null, y), word_font(y),
  1465. X        EchoLength(back(y, COL)), EchoLength(fwd(y, COL)));
  1466. X          }
  1467. X        }
  1468. X        else y = MinSize(y, dim, extras);
  1469. X
  1470. X        if( is_indefinite(type(y)) )
  1471. X        {
  1472. X          /* error if preceding gap has mark */
  1473. X          if( g != nil && mark(gap(g)) )
  1474. X          {    Error(WARN, &fpos(y), "catenation modifier ^ deleted (%s)",
  1475. X            "it may not precede this object");
  1476. X        mark(gap(g)) = FALSE;
  1477. X          }
  1478. X
  1479. X          /* error if next unit is used in preceding gap */
  1480. X          if( g != nil && units(gap(g)) == NEXT_UNIT )
  1481. X          {    Error(WARN, &fpos(y), "gap replaced by 0i (%s)",
  1482. X            "unit n may not precede this object");
  1483. X        units(gap(g)) = FIXED_UNIT;
  1484. X        width(gap(g)) = 0;
  1485. X          }
  1486. X        }
  1487. X        else
  1488. X        {
  1489. X          /* calculate running total length */
  1490. X          if( prev == nil )  b = back(y, dim), f = 0;
  1491. X          else
  1492. X          {
  1493. X        assert( g!=nil && mode(gap(g))!=NO_MODE, "MinSize: NO_MODE!" );
  1494. X        f += MinGap(fwd(prev, dim), back(y, dim), fwd(y, dim), &gap(g));
  1495. X        if( units(gap(g)) == FRAME_UNIT && width(gap(g)) > FR )
  1496. X            will_expand = TRUE;
  1497. X        if( mark(gap(g)) )  b += f, f = 0;
  1498. X          }
  1499. X          prev = y;
  1500. X        }
  1501. X        debug2(DSF,DD,"  b = %s, f = %s",EchoLength(b),EchoLength(f));
  1502. X      }
  1503. X    } /* end for */
  1504. X
  1505. X    if( prev == nil )  b = f = 0;
  1506. X    else f += fwd(prev, dim);
  1507. X    back(x, dim) = min(MAX_LEN, b);
  1508. X    fwd(x, dim)  = min(MAX_LEN, f);
  1509. X
  1510. X    if( type(x) == ACAT && will_expand )  fwd(x, COL) = MAX_LEN;
  1511. X      }
  1512. X      else
  1513. X      {
  1514. X    /********************************************************************/
  1515. X    /*                                                                  */
  1516. X    /*  Calculate sizes perpendicular to join direction                 */
  1517. X    /*                                                                  */
  1518. X    /*  Loop invariant:                                                 */
  1519. X    /*                                                                  */
  1520. X    /*     if found, (b, f) is the size of x, from the last // or from  */
  1521. X    /*     the start, up to link exclusive.  Else no children yet.      */
  1522. X    /*     If dble_found, a previous // exists, and (0, dble_fwd) is    */
  1523. X    /*     the size of x from the start up to that //.                  */
  1524. X    /*                                                                  */
  1525. X    /********************************************************************/
  1526. X
  1527. X    dble_found = found = FALSE;  dble_fwd = 0;
  1528. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1529. X    { Child(y, link);
  1530. X      if( is_index(type(y)) )
  1531. X      { if( dim == ROW )
  1532. X        { link = PrevDown(link);
  1533. X          MoveLink(NextDown(link), *extras, PARENT);
  1534. X        }
  1535. X        continue;
  1536. X      }
  1537. X      else if( type(y) == type(x) )
  1538. X      { link = PrevDown(link);
  1539. X        TransferLinks(Down(y), y, NextDown(link));
  1540. X        DisposeChild(Up(y));
  1541. X        continue;
  1542. X      }
  1543. X      else if( type(y) == GAP_OBJ )
  1544. X      { assert( found, "MinSize/VCAT/perp: !found!" );
  1545. X        if( !join(gap(y)) )
  1546. X        {
  1547. X          /* found // or || operator, so end current group */
  1548. X          dble_found = TRUE;
  1549. X          dble_fwd = max(dble_fwd, b + f);
  1550. X          debug1(DSF, DD, "  endgroup, dble_fwd: %s", EchoLength(dble_fwd));
  1551. X          found = FALSE;
  1552. X        }
  1553. X      }
  1554. X      else /* found object */
  1555. X      {
  1556. X        /* calculate size of subobject y */
  1557. X        if( type(y) == WORD )
  1558. X        { if( dim == COL )  FontAtomSize(y);
  1559. X        }
  1560. X        else y = MinSize(y, dim, extras);
  1561. X        if( found )
  1562. X        { b = max(b, back(y, dim));
  1563. X          f = max(f, fwd(y, dim));
  1564. X        }
  1565. X        else
  1566. X        { b = back(y, dim);
  1567. X          f = fwd(y, dim);
  1568. X          found = TRUE;
  1569. X        }
  1570. X        debug2(DSF,DD, "  b: %s, f: %s", EchoLength(b), EchoLength(f));
  1571. X      }
  1572. X    } /* end for */
  1573. X    assert( found, "MinSize/VCAT/perp: !found (2)!" );
  1574. X
  1575. X    /* finish off last group */
  1576. X    if( dble_found )
  1577. X    { back(x, dim) = 0;
  1578. X      dble_fwd = max(dble_fwd, b + f);
  1579. X      fwd(x, dim) = min(MAX_LEN, dble_fwd);
  1580. X      debug1(DSF, DD, "  end group, dble_fwd: %s", EchoLength(dble_fwd));
  1581. X    }
  1582. X    else
  1583. X    { back(x, dim) = b;
  1584. X      fwd(x, dim)  = f;
  1585. X    }
  1586. X      } /* end else */
  1587. X      break;
  1588. X
  1589. X
  1590. X    case COL_THR:
  1591. X    case ROW_THR:
  1592. X
  1593. X      assert( (type(x) == COL_THR) == (dim == COL), "Manifest/COL_THR: dim!" );
  1594. X      if( thr_state(x) == NOTSIZED )
  1595. X      {    assert( Down(x) != x, "Manifest/COL_THR: Down(x)!" );
  1596. X    Child(y, Down(x));
  1597. X    y = MinSize(y, dim, extras);
  1598. X    b = back(y, dim);
  1599. X    f = fwd(y, dim);
  1600. X    for( link = NextDown(Down(x));  link != x;  link = NextDown(link) )
  1601. X    { Child(y, link);
  1602. X      assert( type(y) != GAP_OBJ, "Manifest/COL_THR: GAP_OBJ!" );
  1603. X      y = MinSize(y, dim, extras);
  1604. X      b = max(b, back(y, dim));
  1605. X      f = max(f, fwd(y, dim));
  1606. X    }
  1607. X    back(x, dim) = b;
  1608. X    fwd(x, dim)  = f;
  1609. X    thr_state(x) = SIZED;
  1610. X      }
  1611. X      break;
  1612. X
  1613. X
  1614. X    case INCGRAPHIC:
  1615. X    case SINCGRAPHIC:
  1616. X
  1617. X      /* open file, check for initial %!, and hunt for %%BoundingBox line */
  1618. X      /* according to DSC Version 3.0, the BoundingBox parameters must be */
  1619. X      /* integers; but we read them as floats and truncate since files    */
  1620. X      /* with fractional values seem to be common in the real world       */
  1621. X      if( dim == ROW )  break;
  1622. X      status = IG_LOOKING;
  1623. X      Child(y, Down(x));
  1624. X      fp = OpenIncGraphicFile(string(y), type(x), &full_name, &fpos(y));
  1625. X      /* *** fp = OpenFile(fnum = sparec(constraint(x)), FALSE); */
  1626. X      if( fp == NULL )  status = IG_NOFILE;
  1627. X      first_line = TRUE;
  1628. X      while( status == IG_LOOKING && fgets(buff, MAX_LINE, fp) != NULL )
  1629. X      {
  1630. X    if( first_line && (buff[0] != '%' || buff[1] != '!') )
  1631. X      status = IG_BADFILE;
  1632. X    else
  1633. X    { first_line = FALSE;
  1634. X      if( buff[0] == '%' &&
  1635. X          StringBeginsWith(buff, (unsigned char *) "%%BoundingBox:") &&
  1636. X          !StringContains(buff, "(atend)") )
  1637. X      { if( sscanf(buff, "%%%%BoundingBox: %f %f %f %f",
  1638. X        &fllx, &flly, &furx, &fury) == 4 )
  1639. X        {
  1640. X          status = IG_OK;
  1641. X          llx = fllx;
  1642. X          lly = flly;
  1643. X          urx = furx;
  1644. X          ury = fury;
  1645. X        }
  1646. X        else status = IG_BADSIZE;
  1647. X      }
  1648. X    }
  1649. X      }
  1650. X
  1651. X      /* report error or calculate true size, depending on status */
  1652. X      switch( status )
  1653. X      {
  1654. X    case IG_LOOKING:
  1655. X
  1656. X      Error(WARN, &fpos(x), "%s given zero size: format error in file %s%s",
  1657. X        type(x) == INCGRAPHIC ? KW_INCGRAPHIC : KW_SINCGRAPHIC,
  1658. X        string(full_name), " (missing %%BoundingBox: line)");
  1659. X      back(y, COL) = fwd(y, COL) = back(y, ROW) = fwd(y, ROW) = 0;
  1660. X      back(x, COL) = fwd(x, COL) = back(x, ROW) = fwd(x, ROW) = 0;
  1661. X      sparec(constraint(x)) = TRUE;
  1662. X      fclose(fp);
  1663. X      break;
  1664. X
  1665. X    case IG_NOFILE:
  1666. X
  1667. X      Error(WARN, &fpos(x), "%s deleted: cannot open file %s",
  1668. X        type(x) == INCGRAPHIC ? KW_INCGRAPHIC : KW_SINCGRAPHIC,
  1669. X        string(full_name));
  1670. X      sparec(constraint(x)) = FALSE;
  1671. X      back(x, COL) = fwd(x, COL) = back(x, ROW) = fwd(x, ROW) = 0;
  1672. X      break;
  1673. X
  1674. X    case IG_BADFILE:
  1675. X
  1676. X      Error(WARN, &fpos(x), "%s deleted: format error in file %s %s",
  1677. X        type(x) == INCGRAPHIC ? KW_INCGRAPHIC : KW_SINCGRAPHIC,
  1678. X        string(full_name), "(bad first line)");
  1679. X      sparec(constraint(x)) = FALSE;
  1680. X      back(x, COL) = fwd(x, COL) = back(x, ROW) = fwd(x, ROW) = 0;
  1681. X      fclose(fp);
  1682. X      break;
  1683. X    
  1684. X    case IG_BADSIZE:
  1685. X
  1686. X      Error(WARN, &fpos(x), "%s given zero size: format error in file %s%s",
  1687. X        type(x) == INCGRAPHIC ? KW_INCGRAPHIC : KW_SINCGRAPHIC,
  1688. X        string(full_name), " (bad %%BoundingBox: line)");
  1689. X      back(y, COL) = fwd(y, COL) = back(y, ROW) = fwd(y, ROW) = 0;
  1690. X      back(x, COL) = fwd(x, COL) = back(x, ROW) = fwd(x, ROW) = 0;
  1691. X      sparec(constraint(x)) = TRUE;
  1692. X      fclose(fp);
  1693. X      break;
  1694. X
  1695. X    case IG_OK:
  1696. X
  1697. X      Child(y, Down(x));
  1698. X      back(y, COL) = llx;  fwd(y, COL) = urx;
  1699. X      back(y, ROW) = lly;  fwd(y, ROW) = ury;
  1700. X      b = (urx - llx) * PT;
  1701. X      b = max(0, min(b, MAX_LEN));
  1702. X      back(x, COL) = fwd(x, COL) = b / 2;
  1703. X      b = (ury - lly) * PT;
  1704. X      b = max(0, min(b, MAX_LEN));
  1705. X      back(x, ROW) = fwd(x, ROW) = b / 2;
  1706. X      sparec(constraint(x)) = TRUE;
  1707. X      fclose(fp);
  1708. X      break;
  1709. X
  1710. X      }
  1711. X      DisposeObject(full_name);
  1712. X      break;
  1713. X
  1714. X
  1715. X    default:
  1716. X    
  1717. X      Error(INTERN, &fpos(x), "MinSize: type(x): %s", Image(type(x)));
  1718. X      break;
  1719. X
  1720. X
  1721. X  } /* end switch */
  1722. X  debug1(DSF, DD,  "] MinSize returning, x = %s", EchoObject(null, x));
  1723. X  debug3(DSF, DD, "  (%s size is %s, %s)", dimen(dim),
  1724. X        EchoLength(back(x, dim)), EchoLength(fwd(x, dim)) );
  1725. X  ifdebug(DSF, DDD, EchoObject(stderr, x));
  1726. X
  1727. X  assert( type(x) == WORD || back(x, dim) >= 0, "MinSize: back(x, dim) < 0!" );
  1728. X  assert( type(x) == WORD || fwd(x, dim)  >= 0, "MinSize: fwd(x, dim)  < 0!" );
  1729. X
  1730. X  return x;
  1731. X} /* end MinSize */
  1732. END_OF_FILE
  1733.   if test 18672 -ne `wc -c <'lout/z12.c'`; then
  1734.     echo shar: \"'lout/z12.c'\" unpacked with wrong size!
  1735.   fi
  1736.   # end of 'lout/z12.c'
  1737. fi
  1738. if test -f 'lout/z18.c' -a "${1}" != "-c" ; then 
  1739.   echo shar: Will not clobber existing file \"'lout/z18.c'\"
  1740. else
  1741.   echo shar: Extracting \"'lout/z18.c'\" \(16726 characters\)
  1742.   sed "s/^X//" >'lout/z18.c' <<'END_OF_FILE'
  1743. X/*@z18.c:Galley Transfer:TransferBegin(), TransferComponent()@****************/
  1744. X/*                                                                           */
  1745. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.03)       */
  1746. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  1747. X/*                                                                           */
  1748. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  1749. X/*  Basser Department of Computer Science                                    */
  1750. X/*  The University of Sydney 2006                                            */
  1751. X/*  AUSTRALIA                                                                */
  1752. X/*                                                                           */
  1753. X/*  This program is free software; you can redistribute it and/or modify     */
  1754. X/*  it under the terms of the GNU General Public License as published by     */
  1755. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  1756. X/*  any later version.                                                       */
  1757. X/*                                                                           */
  1758. X/*  This program is distributed in the hope that it will be useful,          */
  1759. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  1760. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  1761. X/*  GNU General Public License for more details.                             */
  1762. X/*                                                                           */
  1763. X/*  You should have received a copy of the GNU General Public License        */
  1764. X/*  along with this program; if not, write to the Free Software              */
  1765. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  1766. X/*                                                                           */
  1767. X/*  FILE:         z18.c                                                      */
  1768. X/*  MODULE:       Galley Transfer                                            */
  1769. X/*  EXTERNS:      TransferInit(), TransferBegin(), TransferComponent(),      */
  1770. X/*                TransferEnd(), TransferClose()                             */
  1771. X/*                                                                           */
  1772. X/*****************************************************************************/
  1773. X#include "externs"
  1774. X
  1775. X#define    MAX_DEPTH      30            /* max depth of galleys      */
  1776. Xstatic OBJECT        root_galley = nil;    /* the root galley           */
  1777. Xstatic OBJECT        targets[MAX_DEPTH];    /* currently open \Inputs    */
  1778. Xstatic CONSTRAINT    constraints[MAX_DEPTH];    /* their COL constraints     */
  1779. Xstatic int        itop;            /* stack top                 */
  1780. Xstatic CONSTRAINT    initial_constraint;    /* initial COL constraint    */
  1781. Xstatic STYLE        InitialStyle;        /* initial style             */
  1782. X
  1783. X#if DEBUG_ON
  1784. Xstatic debug_targets()
  1785. X{ int i;  OBJECT tmp;
  1786. X  for( i = 0;  i <= itop;  i++ )
  1787. X  { if( targets[i] == nil || Down(targets[i]) == targets[i] )  tmp = nil;
  1788. X    else Child(tmp, Down(targets[i]));
  1789. X    debug3(DGT, D, "  target[%d] %s = %s", i,
  1790. X      EchoConstraint(&constraints[i]), EchoObject(null, tmp));
  1791. X  }
  1792. X} /* end debug_targets */
  1793. X#endif
  1794. X
  1795. X
  1796. X/*@@**************************************************************************/
  1797. X/*                                                                           */
  1798. X/*  TransferInit(InitEnv)                                                    */
  1799. X/*                                                                           */
  1800. X/*  Initialise this module.  The initial environment is InitEnv.             */
  1801. X/*                                                                           */
  1802. X/*****************************************************************************/
  1803. X
  1804. XTransferInit(InitEnv)
  1805. XOBJECT InitEnv;
  1806. X{ OBJECT dest, x, y, recs, inners, nothing, dest_index, up_hd;
  1807. X  debug1(DGT, D, "TransferInit( %s )", EchoObject(null, InitEnv));
  1808. X  SetConstraint(initial_constraint, MAX_LEN-1, MAX_LEN-1, MAX_LEN-1);
  1809. X
  1810. X  /* save initial environment and style */
  1811. X  SetGap( line_gap(InitialStyle), FALSE, FALSE, FIXED_UNIT, MARK_MODE, 18*PT);
  1812. X  SetGap(space_gap(InitialStyle), FALSE, TRUE,  FIXED_UNIT, EDGE_MODE,  1*EM);
  1813. X  font(InitialStyle)            = 0;
  1814. X  hyph_style(InitialStyle)      = HYPH_UNDEF;
  1815. X  fill_style(InitialStyle)      = FILL_UNDEF;
  1816. X  display_style(InitialStyle)   = DISPLAY_UNDEF;
  1817. X
  1818. X  /* construct destination for root galley */
  1819. X  up_hd = New(HEAD);
  1820. X  dest_index = New(RECEIVING);
  1821. X  dest = New(CLOSURE);  actual(dest) = PrintSym;
  1822. X  actual(dest_index) = dest;
  1823. X  external(dest) = TRUE;
  1824. X  threaded(dest) = FALSE;
  1825. X  blocked(dest_index) = FALSE;
  1826. X  Link(up_hd, dest_index);
  1827. X
  1828. X  /* construct root galley */
  1829. X  root_galley = New(HEAD);
  1830. X  FposCopy(fpos(root_galley), *no_fpos);
  1831. X  actual(root_galley) = whereto(root_galley) = ready_galls(root_galley) = nil;
  1832. X  backward(root_galley) = must_expand(root_galley) = sized(root_galley) = FALSE;
  1833. X  x = New(CLOSURE);  actual(x) = InputSym;
  1834. X  Link(root_galley, x);
  1835. X  SizeGalley(root_galley, InitEnv, TRUE, FALSE, FALSE, FALSE, &InitialStyle,
  1836. X        &initial_constraint, nil, ¬hing, &recs, &inners);
  1837. X  assert( recs   == nil , "TransferInit: recs   != nil!" );
  1838. X  assert( inners == nil , "TransferInit: inners != nil!" );
  1839. X  Link(dest_index, root_galley);
  1840. X
  1841. X  /* initialise target and constraint stacks */
  1842. X  Child(y, Down(root_galley));
  1843. X  assert( type(y) == RECEPTIVE && type(actual(y)) == CLOSURE &&
  1844. X    actual(actual(y)) == InputSym, "TransferInit: initial galley!" );
  1845. X  assert( external(actual(y)), "TransferInit: input sym not external!" );
  1846. X  blocked(y) = TRUE;
  1847. X  targets[itop = 0] = New(ACAT);
  1848. X  Link(targets[itop], y);
  1849. X  Constrained(actual(y), &constraints[itop], COL);
  1850. X  debug2(DSC, D, "Constrained( %s, COL ) = %s",
  1851. X    EchoObject(null, y), EchoConstraint(&constraints[itop]));
  1852. X
  1853. X  debug0(DGT, D, "TransferInit returning.");
  1854. X  ifdebug(DGT, DD, debug_targets());
  1855. X} /* end TransferInit */
  1856. X
  1857. X
  1858. X/*@@**************************************************************************/
  1859. X/*                                                                           */
  1860. X/*  OBJECT TransferBegin(x)                                                  */
  1861. X/*                                                                           */
  1862. X/*  Commence the transfer of a new galley whose header is invokation x.      */
  1863. X/*                                                                           */
  1864. X/*****************************************************************************/
  1865. X
  1866. XOBJECT TransferBegin(x)
  1867. XOBJECT x;
  1868. X{ OBJECT xsym, index, y, link, env, new_env, hold_env, res, hd, target;
  1869. X  CONSTRAINT c;
  1870. X  debug1(DGT, D, "TransferBegin( %s )", EchoObject(null, x));
  1871. X  ifdebug(DGT, DD, debug_targets());
  1872. X  assert( type(x) == CLOSURE, "TransferBegin: non-CLOSURE!" );
  1873. X
  1874. X  /* construct new (inner) env chain */
  1875. X  if( Down(targets[itop]) == targets[itop] )
  1876. X      Error(FATAL, &fpos(x), "cannot attach galley %s", SymName(actual(x)));
  1877. X  Child(target, Down(targets[itop]));
  1878. X  xsym = actual(x);
  1879. X  env = GetEnv(actual(target));
  1880. X  debug1(DGT, DD, "  current env chain: %s", EchoObject(null, env));
  1881. X  if( has_body(xsym) )
  1882. X  {
  1883. X    /* prepare a copy of x for inclusion in environment */
  1884. X    y = CopyObject(x, no_fpos);
  1885. X
  1886. X    /* attach its environment */
  1887. X    AttachEnv(env, y);
  1888. X
  1889. X    /* now the new environment is y catenated with the old one */
  1890. X    new_env = SetEnv(y, nil);
  1891. X  }
  1892. X  else new_env = env;
  1893. X  hold_env = New(ACAT);  Link(hold_env, new_env);
  1894. X  debug1(DGT, DD, "  new env chain: %s", EchoObject(null, new_env));
  1895. X
  1896. X  /* convert x into an unsized galley called hd */
  1897. X  index = New(UNATTACHED);
  1898. X  hd = New(HEAD);
  1899. X  FposCopy(fpos(hd), fpos(x));
  1900. X  actual(hd) = xsym;
  1901. X  backward(hd) = TargetSymbol(x, &whereto(hd));
  1902. X  ready_galls(hd) = nil;
  1903. X  must_expand(hd) = TRUE;
  1904. X  sized(hd) = FALSE;
  1905. X  Link(index, hd);
  1906. X  Link(hd, x);
  1907. X  AttachEnv(env, x);
  1908. X
  1909. X  /* search for destination for hd and release it */
  1910. X  Link(Up(target), index);
  1911. X  debug0(DGF, D, "  calling FlushGalley from TransferBegin");
  1912. X  FlushGalley(hd);
  1913. X
  1914. X  /* if failed to flush, undo everything and exit */
  1915. X  Parent(index, Up(hd));
  1916. X  if( type(index) == UNATTACHED && !sized(hd) )
  1917. X  { DeleteNode(index);
  1918. X    DisposeObject(hold_env);
  1919. X    if( LastDown(x) != x )
  1920. X    { Child(env, LastDown(x));
  1921. X      if( type(env) == ENV )  DisposeChild(LastDown(x));
  1922. X    }
  1923. X    debug1(DGT,D, "TransferBegin returning failed, x: %s", EchoObject(null, x));
  1924. X    return x;
  1925. X  }
  1926. X
  1927. X  if( has_rpar(actual(hd)) )
  1928. X  {
  1929. X    /* set up new target to be inner \InputSym, or nil if none */
  1930. X    if( ++itop >= MAX_DEPTH ) Error(FATAL, &fpos(x),
  1931. X    "galley nested too deeply (max is %d)", MAX_DEPTH);
  1932. X    targets[itop] = New(ACAT);  target = nil;
  1933. X    for( link = Down(hd);  link != hd;  link = NextDown(link) )
  1934. X    { Child(y, link);
  1935. X      if( type(y) == RECEPTIVE && actual(actual(y)) == InputSym )
  1936. X      {
  1937. X    Constrained(actual(y), &constraints[itop], COL);
  1938. X    if( FitsConstraint(0, 0, constraints[itop]) )
  1939. X    { Link(targets[itop], y);  target = y;
  1940. X      debug2(DSC, D, "Constrained( %s, COL ) = %s",
  1941. X        EchoObject(null, y), EchoConstraint(&constraints[itop]));
  1942. X      env = DetachEnv(actual(y));
  1943. X      AttachEnv(new_env, actual(y));
  1944. X    }
  1945. X    else
  1946. X    { Error(WARN, &fpos(hd), "galley %s deleted (target too narrow)",
  1947. X        SymName(actual(hd)));
  1948. X    }
  1949. X    break;
  1950. X      }
  1951. X    }
  1952. X
  1953. X    /* return a token appropriate to the new target */
  1954. X    if( target == nil || external(actual(target)) )
  1955. X      res = NewToken(GSTUB_EXT, no_fpos, 0, 0, precedence(xsym), nil);
  1956. X    else
  1957. X    { Constrained(actual(target), &c, ROW);
  1958. X      if( constrained(c) )  Error(FATAL, &fpos(target),
  1959. X        "right parameter of %s is vertically constrained", SymName(xsym));
  1960. X      else res = NewToken(GSTUB_INT, no_fpos, 0, 0, precedence(xsym), nil);
  1961. X    }
  1962. X  }
  1963. X  else res = NewToken(GSTUB_NONE, no_fpos, 0, 0, precedence(xsym), nil);
  1964. X
  1965. X  DisposeObject(hold_env);
  1966. X  debug1(DGT, D, "TransferBegin returning %s", Image(type(res)));
  1967. X  ifdebug(DGT, DD, debug_targets());
  1968. X  return res;
  1969. X} /* end TransferBegin */
  1970. X
  1971. X
  1972. X/*@@**************************************************************************/
  1973. X/*                                                                           */
  1974. X/*  TransferComponent(x)                                                     */
  1975. X/*                                                                           */
  1976. X/*  Transfer component x of a galley.                                        */
  1977. X/*                                                                           */
  1978. X/*****************************************************************************/
  1979. X
  1980. XTransferComponent(x)
  1981. XOBJECT x;
  1982. X{ OBJECT y, env, start_search, recs, inners, nothing, hd, dest, dest_index;
  1983. X  debug1(DGT, D, "TransferComponent( %s )", EchoObject(null, x));
  1984. X  ifdebug(DGT, DD, debug_targets());
  1985. X
  1986. X  /* if no dest_index, discard x and exit */
  1987. X  if( Down(targets[itop]) == targets[itop] )
  1988. X  { DisposeObject(x);
  1989. X    debug0(DGT, D, "TransferComponent returning (no target).");
  1990. X    return;
  1991. X  }
  1992. X  Child(dest_index, Down(targets[itop]));
  1993. X  assert( external(actual(dest_index)), "TransferComponent: internal!" );
  1994. X
  1995. X  /* make the component into a galley */
  1996. X  hd = New(HEAD);
  1997. X  FposCopy(fpos(hd), fpos(x));
  1998. X  actual(hd) = whereto(hd) = ready_galls(hd) = nil;
  1999. X  backward(hd) = must_expand(hd) = sized(hd) = FALSE;
  2000. X  Link(hd, x);
  2001. X  dest = actual(dest_index);
  2002. X  env = GetEnv(dest);
  2003. X  debug1(DGT, DD, "  current env chain: %s", EchoObject(null, env));
  2004. X  SizeGalley(hd, env, TRUE, threaded(dest), FALSE, TRUE, &save_style(dest),
  2005. X    &constraints[itop], nil, ¬hing, &recs, &inners);
  2006. X  if( recs != nil )  ExpandRecursives(recs);
  2007. X
  2008. X  /* promote the components, remembering where old spot was */
  2009. X  start_search = PrevDown(Up(dest_index));
  2010. X  debug0(DSA, D, "  calling AdjustSize from TransferComponent");
  2011. X  AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
  2012. X  Promote(hd, hd, dest_index);
  2013. X  DeleteNode(hd);
  2014. X
  2015. X  /* flush any widowed galleys attached to \Input */
  2016. X  if( Down(dest_index) != dest_index )
  2017. X  { OBJECT tinners, index;
  2018. X    tinners = New(ACAT);
  2019. X    while( Down(dest_index) != dest_index )
  2020. X    { Child(y, Down(dest_index));
  2021. X      assert( type(y) == HEAD, "TransferComponent: input child!" );
  2022. X      DetachGalley(y);
  2023. X      Parent(index, Up(y));
  2024. X      MoveLink(Up(index), NextDown(start_search), PARENT);
  2025. X      Link(tinners, index);
  2026. X    }
  2027. X    FlushInners(tinners, nil);
  2028. X  }
  2029. X
  2030. X  /* flush any galleys inside hd */
  2031. X  if( inners != nil )  FlushInners(inners, nil);
  2032. X
  2033. X  /* flush parent galley, if needed */
  2034. X  if( blocked(dest_index) )
  2035. X  { blocked(dest_index) = FALSE;
  2036. X    Parent(y, Up(dest_index));
  2037. X    debug0(DGF, D, "  calling FlushGalley from TransferComponent");
  2038. X    FlushGalley(y);
  2039. X  }
  2040. X  
  2041. X  debug0(DGT, D, "TransferComponent returning.");
  2042. X  ifdebug(DGT, DD, debug_targets());
  2043. X} /* end TransferComponent */
  2044. X
  2045. X
  2046. X/*@@**************************************************************************/
  2047. X/*                                                                           */
  2048. X/*  TransferEnd(x)                                                           */
  2049. X/*                                                                           */
  2050. X/*  End the transfer of a galley.                                            */
  2051. X/*                                                                           */
  2052. X/*****************************************************************************/
  2053. X
  2054. XTransferEnd(x)
  2055. XOBJECT x;
  2056. X{ OBJECT recs, inners, nothing, z, env, dest, hd, dest_index, y, start_search;
  2057. X  debug1(DGT, D, "TransferEnd( %s )", EchoObject(null, x));
  2058. X  ifdebug(DGT, DD, debug_targets());
  2059. X
  2060. X  /* if no dest_index, discard x and exit */
  2061. X  if( Down(targets[itop]) == targets[itop] )
  2062. X  { DisposeObject(x);  DisposeObject(targets[itop--]);
  2063. X    debug0(DGT, D, "TransferEnd returning: no dest_index");
  2064. X    return;
  2065. X  }
  2066. X  Child(dest_index, Down(targets[itop]));
  2067. X
  2068. X  /* make the component into a galley */
  2069. X  hd = New(HEAD);  FposCopy(fpos(hd), fpos(x));
  2070. X  actual(hd) = whereto(hd) = ready_galls(hd) = nil;
  2071. X  backward(hd) = must_expand(hd) = sized(hd) = FALSE;
  2072. X  Link(hd, x);  dest = actual(dest_index);  env = GetEnv(dest);
  2073. X  debug1(DGT, DD, "  current env chain: %s", EchoObject(null, env));
  2074. X  SizeGalley(hd, env, external(dest), threaded(dest), FALSE, TRUE,
  2075. X    &save_style(dest), &constraints[itop], nil, ¬hing, &recs, &inners);
  2076. X  if( recs != nil )  ExpandRecursives(recs);
  2077. X
  2078. X  /* promote the components, remembering where old spot was */
  2079. X  start_search = PrevDown(Up(dest_index));
  2080. X  debug0(DSA, D, "calling AdjustSize from TransferEnd (a)");
  2081. X  AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
  2082. X  if( !external(dest) )
  2083. X  { Child(z, LastDown(hd));
  2084. X    debug0(DSA, D, "calling AdjustSize from TransferEnd (b)");
  2085. X    AdjustSize(dest, back(z, ROW), fwd(z, ROW), ROW);
  2086. X    Interpose(dest, VCAT, hd, z);
  2087. X  }
  2088. X  Promote(hd, hd, dest_index);  DeleteNode(hd);
  2089. X
  2090. X  /* flush any widowed galleys attached to \Input */
  2091. X  if( Down(dest_index) != dest_index )
  2092. X  { OBJECT tinners, index;
  2093. X    tinners = New(ACAT);
  2094. X    while( Down(dest_index) != dest_index )
  2095. X    { Child(y, Down(dest_index));
  2096. X      assert( type(y) == HEAD, "TransferComponent: input child!" );
  2097. X      DetachGalley(y);
  2098. X      Parent(index, Up(y));
  2099. X      MoveLink(Up(index), NextDown(start_search), PARENT);
  2100. X      Link(tinners, index);
  2101. X    }
  2102. X    FlushInners(tinners, nil);
  2103. X  }
  2104. X
  2105. X  /* flush any galleys inside hd */
  2106. X  if( inners != nil )  FlushInners(inners, nil);
  2107. X
  2108. X  /* close dest_index, and flush parent galley if needed */
  2109. X  if( blocked(dest_index) )
  2110. X  { Parent(y, Up(dest_index));
  2111. X    DeleteNode(dest_index);
  2112. X    debug0(DGF, D, "  calling FlushGalley from TransferEnd");
  2113. X    FlushGalley(y);
  2114. X  }
  2115. X  else DeleteNode(dest_index);
  2116. X  
  2117. X  /* pop target stack and exit */
  2118. X  DisposeObject(targets[itop--]);
  2119. X  debug0(DGT, D, "TransferEnd returning.");
  2120. X  ifdebug(DGT, DD, debug_targets());
  2121. X} /* end TransferEnd */
  2122. X
  2123. X
  2124. X/*****************************************************************************/
  2125. X/*                                                                           */
  2126. X/*  TransferClose()                                                          */
  2127. X/*                                                                           */
  2128. X/*  Close this module.                                                       */
  2129. X/*                                                                           */
  2130. X/*****************************************************************************/
  2131. X
  2132. XTransferClose()
  2133. X{ OBJECT inners;
  2134. X  debug0(DGT, D, "TransferClose()");
  2135. X  debug0(DGA, D, "  calling FreeGalley from TransferClose");
  2136. X  if( LastDown(root_galley) != root_galley )
  2137. X  { inners = nil;
  2138. X    FreeGalley(root_galley, root_galley, &inners, nil, nil);
  2139. X    if( inners != nil )  FlushInners(inners, nil);
  2140. X    debug0(DGF, D, "  calling FlushGalley from TransferClose");
  2141. X    FlushGalley(root_galley);
  2142. X  }
  2143. X  debug0(DGT, D, "TransferClose returning.");
  2144. X}
  2145. END_OF_FILE
  2146.   if test 16726 -ne `wc -c <'lout/z18.c'`; then
  2147.     echo shar: \"'lout/z18.c'\" unpacked with wrong size!
  2148.   fi
  2149.   # end of 'lout/z18.c'
  2150. fi
  2151. echo shar: End of archive 13 \(of 30\).
  2152. cp /dev/null ark13isdone
  2153. MISSING=""
  2154. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ; do
  2155.     if test ! -f ark${I}isdone ; then
  2156.     MISSING="${MISSING} ${I}"
  2157.     fi
  2158. done
  2159. if test "${MISSING}" = "" ; then
  2160.     echo You have unpacked all 30 archives.
  2161.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2162. else
  2163.     echo You still must unpack the following archives:
  2164.     echo "        " ${MISSING}
  2165. fi
  2166. exit 0
  2167. exit 0 # Just in case...
  2168.