home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / lout / part08 < prev    next >
Encoding:
Text File  |  1993-08-11  |  72.8 KB  |  2,105 lines

  1. Newsgroups: comp.sources.misc
  2. From: jeff@joyce.cs.su.oz.au (Jeff Kingston)
  3. Subject: v38i076:  lout - Lout document formatting system, v2.05, Part08/35
  4. Message-ID: <1993Aug8.180806.11563@sparky.sterling.com>
  5. X-Md4-Signature: 1517c2c830fbf70467a6af08f4be3af2
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sun, 8 Aug 1993 18:08:06 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: jeff@joyce.cs.su.oz.au (Jeff Kingston)
  12. Posting-number: Volume 38, Issue 76
  13. Archive-name: lout/part08
  14. Environment: UNIX
  15. Supersedes: lout: Volume 37, Issue 99-128
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  doc/tr.impl/s2.5 z06.c z08.c
  22. # Wrapped by kent@sparky on Sun Aug  8 12:29:23 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 8 (of 35)."'
  26. if test -f 'doc/tr.impl/s2.5' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'doc/tr.impl/s2.5'\"
  28. else
  29.   echo shar: Extracting \"'doc/tr.impl/s2.5'\" \(4418 characters\)
  30.   sed "s/^X//" >'doc/tr.impl/s2.5' <<'END_OF_FILE'
  31. X@SubSection
  32. X    @Tag { style }
  33. X    @Title { Context-sensitive attributes of objects }
  34. X@Begin
  35. X@PP
  36. XAlthough we are free to place any object in any context, the context
  37. Xmust influence the appearance of the object, since otherwise
  38. X@ID @Code "A short paragraph of text."
  39. Xcould not appear in a variety of fonts, column widths, etc.  This
  40. Xinfluence cannot take the purely static form that block-structured
  41. Xlanguages use to associate values with identifiers, for then an operator
  42. Xcould not influence the appearance of its parameters; and a state
  43. Xvariable solution is not compatible with the overall functional design.
  44. X@PP
  45. XThe information needed from the context seems quite limited, comprising
  46. Xthe font family, face, and size to use, the style of paragraph breaking
  47. Xrequired, how much space to substitute between the words of paragraphs,
  48. Xand how much horizontal and vertical space is available to receive the
  49. Xobject.  These four items constitute the so-called `style information'
  50. Xof Lout.  As graphics rendering hardware improves, the style information
  51. Xwill probably grow to include colour and texture information.
  52. X@PP
  53. XThe way to deal with fonts at least is very clear:
  54. X@ID @Code "{ Times Slope 12p } @Font { Hello, world }"
  55. Xshould have result
  56. X@ID { { Times Slope 12p } @Font { Hello, world } }
  57. XLout also provides @Code "@Break" and @Code "@Space" symbols for
  58. Xcontrolling the paragraph breaking and space styles mentioned
  59. Xabove.  These work in the same way, returning their right
  60. Xparameters in the style of their left.  The implementation is very
  61. Xsimple:  one merely broadcasts the style information down into the parse
  62. Xtree of the right parameter.  A font, for example, is converted to an
  63. X8-bit internal name and stored in each leaf, while a breaking style is
  64. Xstored in the root node of each paragraph.
  65. X@PP
  66. XThe same language design can be used for available width and height,
  67. Xonly here the implementation is much more demanding:
  68. X@ID @Code {
  69. X"2i @Wide {"
  70. X"(1)  |0.1i  An example"
  71. X"containing a small"
  72. X"paragraph of filled text."
  73. X"}"
  74. X}
  75. Xis guaranteed to be two inches wide:
  76. X@ID {
  77. X2i @Wide {
  78. X(1)  |0.1i  An example
  79. Xcontaining a small
  80. Xparagraph of filled text.
  81. X}
  82. X}
  83. XOne must calculate that 1.9 inches minus the width of @Code "(1)" is
  84. Xavailable
  85. Xto the paragraph, and break it accordingly; Basser Lout does this in two
  86. Xstages.  In the first, upward-moving stage, widths are calculated using the
  87. Xformulae of Section {@NumberOf objects}, which assume that available
  88. Xspace is infinite.  If the upward movement reaches a @Eq { WIDE }
  89. Xnode, corresponding to a @Code "@Wide" operator, and
  90. Xthe calculated width exceeds that allowed, a second, downward-moving stage
  91. Xis initiated which attempts to reduce the width by finding and breaking
  92. Xparagraphs.  This second stage is quite routine except at @Code "|" nodes,
  93. Xwhose children are the columns of a table.  It is necessary to apportion
  94. Xthe available width (minus inter-column gaps) among the columns.  Basser
  95. XLout leaves narrow columns unbroken and breaks the remaining columns to
  96. Xequal width, using up all of the available space.
  97. X@PP
  98. XThe size of an object is not clearly determined when the upward-moving
  99. Xsize is less than the downward-moving available space, and the object
  100. Xcontains constructs that depend on available space (e.g. right
  101. Xjustification).  For example, in
  102. X@ID @Code "2i @Wide { Heading // a |1rt b }"
  103. Xit seems natural to assign a width of two inches to the subobject
  104. X@Code "a |1rt b" because of the right justification, but it would be
  105. Xequally plausible if the width of @Code Heading was assigned to the
  106. Xsubobject instead.  The author is conscious of having failed to resolve
  107. Xthis matter properly; an extra operator for controlling available space
  108. Xis probably necessary.
  109. X@PP
  110. XThe actual paragraph breaking is just a simple transformation on the
  111. Xparse tree; the real issue is how to describe the various styles:  ragged
  112. Xright, adjusted, outdented, and so on.  Their diversity suggests that
  113. Xthey should somehow be defined using more basic features; but then there
  114. Xare algorithms for high-quality paragraph breaking, which presumably
  115. Xmust be built-in.  This dilemma was not clearly grasped by the author in
  116. X1985, and he included a built-in paragraph breaker, with the @Code
  117. X"@Break" operator selecting from a fixed set of styles.  A much better
  118. Xsolution based on galleys will be given in Section {@NumberOf horizontal},
  119. Xbut, regrettably, it is not implemented.
  120. X@End @SubSection
  121. END_OF_FILE
  122.   if test 4418 -ne `wc -c <'doc/tr.impl/s2.5'`; then
  123.     echo shar: \"'doc/tr.impl/s2.5'\" unpacked with wrong size!
  124.   fi
  125.   # end of 'doc/tr.impl/s2.5'
  126. fi
  127. if test -f 'z06.c' -a "${1}" != "-c" ; then 
  128.   echo shar: Will not clobber existing file \"'z06.c'\"
  129. else
  130.   echo shar: Extracting \"'z06.c'\" \(28492 characters\)
  131.   sed "s/^X//" >'z06.c' <<'END_OF_FILE'
  132. X/*@z06.c:Parser:PushObj(), PushToken(), etc.@*********************************/
  133. X/*                                                                           */
  134. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  135. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  136. X/*                                                                           */
  137. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  138. X/*  Basser Department of Computer Science                                    */
  139. X/*  The University of Sydney 2006                                            */
  140. X/*  AUSTRALIA                                                                */
  141. X/*                                                                           */
  142. X/*  This program is free software; you can redistribute it and/or modify     */
  143. X/*  it under the terms of the GNU General Public License as published by     */
  144. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  145. X/*  any later version.                                                       */
  146. X/*                                                                           */
  147. X/*  This program is distributed in the hope that it will be useful,          */
  148. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  149. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  150. X/*  GNU General Public License for more details.                             */
  151. X/*                                                                           */
  152. X/*  You should have received a copy of the GNU General Public License        */
  153. X/*  along with this program; if not, write to the Free Software              */
  154. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  155. X/*                                                                           */
  156. X/*  FILE:         z06.c                                                      */
  157. X/*  MODULE:       Parser                                                     */
  158. X/*  EXTERNS:      InitParser(), Parse()                                      */
  159. X/*                                                                           */
  160. X/*****************************************************************************/
  161. X#include "externs"
  162. X#define    LEFT_ASSOC    0
  163. X#define    RIGHT_ASSOC    1
  164. Xstatic    OBJECT        cross_name;    /* name of the cr database   */
  165. X
  166. X
  167. X#define    MAX_STACK    50            /* size of parser stacks     */
  168. Xstatic    OBJECT        obj_stack[MAX_STACK];    /* stack of objects          */
  169. Xstatic    int        otop = -1;        /* top of obj_stack          */
  170. Xstatic    OBJECT        tok_stack[MAX_STACK];    /* stack of tokens           */
  171. Xstatic    int        ttop = -1;        /* top of tok_stack          */
  172. Xstatic    BOOLEAN        obj_prev;        /* TRUE when object is prev  */
  173. X
  174. X
  175. X/*****************************************************************************/
  176. X/*                                                                           */
  177. X/*  PushObj(x)                                                               */
  178. X/*  PushToken(t)                                                             */
  179. X/*  OBJECT PopObj()                                                          */
  180. X/*  OBJECT PopToken()                                                        */
  181. X/*  OBJECT TokenTop                                                          */
  182. X/*  OBJECT ObjTop                                                            */
  183. X/*                                                                           */
  184. X/*  Push and pop from the object and token stacks; examine top item.         */
  185. X/*                                                                           */
  186. X/*****************************************************************************/
  187. X
  188. X#define PushObj(x)                            \
  189. X{ zz_hold = x;                                \
  190. X  if( ++otop < MAX_STACK ) obj_stack[otop] = zz_hold;            \
  191. X  else Error(FATAL, &fpos(obj_stack[otop-1]),                \
  192. X    "object stack overflow: need to simplify expression");        \
  193. X}
  194. X
  195. X#define PushToken(t)                            \
  196. X{ if( ++ttop < MAX_STACK ) tok_stack[ttop] = t;                \
  197. X  else Error(FATAL, &fpos(tok_stack[ttop-1]),                \
  198. X    "operator stack overflow: need to simplify expression");    \
  199. X}
  200. X
  201. X#define PopObj()    obj_stack[otop--]
  202. X#define PopToken()    tok_stack[ttop--]
  203. X#define    TokenTop    tok_stack[ttop]
  204. X#define    ObjTop        obj_stack[otop]
  205. X
  206. X
  207. X/*@::DebugStacks(), InsertSpace(), Shift(), ShiftObj()@***********************/
  208. X/*                                                                           */
  209. X/*  DebugStacks()                                                            */
  210. X/*                                                                           */
  211. X/*  Print debug output of the stacks state                                   */
  212. X/*                                                                           */
  213. X/*****************************************************************************/
  214. X
  215. X#if DEBUG_ON
  216. Xstatic DebugStacks(initial_ttop)
  217. Xint initial_ttop;
  218. X{ int i;
  219. X  fprintf(stderr, "obj_prev: %s; otop: %d; ttop: %d\n",
  220. X    bool(obj_prev), otop, ttop);
  221. X  for( i = 0;  i <= otop; i++ )
  222. X    fprintf(stderr, "obj[%d] = %s\n", i, EchoObject(obj_stack[i]));
  223. X  for( i = 0;  i <= ttop;  i++ )
  224. X  { if( i == initial_ttop+1 ) fprintf(stderr, "$\n");
  225. X    fprintf(stderr, "tok[%d] = %s.%d\n", i, type(tok_stack[i]) == CLOSURE ?
  226. X    SymName(actual(tok_stack[i])) : Image(type(tok_stack[i])),
  227. X    precedence(tok_stack[i]));
  228. X  }
  229. X}
  230. X#endif
  231. X
  232. X
  233. X/*****************************************************************************/
  234. X/*                                                                           */
  235. X/*  InsertSpace(t)                                                           */
  236. X/*                                                                           */
  237. X/*  Add any missing catenation operator in front of token t.                 */
  238. X/*                                                                           */
  239. X/*****************************************************************************/
  240. X
  241. X#define InsertSpace(t)                            \
  242. Xif( obj_prev )                                \
  243. X{ int typ, prec;                            \
  244. X  if( hspace(t) + vspace(t) > 0 )  typ = TSPACE, prec = ACAT_PREC;    \
  245. X  else typ = TJUXTA, prec = JUXTA_PREC;                    \
  246. X  while( obj_prev && precedence(TokenTop) >= prec )  Reduce();        \
  247. X  if( obj_prev )                            \
  248. X  { tmp = New(typ);  precedence(tmp) = prec;                \
  249. X    vspace(tmp) = vspace(t);  hspace(tmp) = hspace(t);            \
  250. X    mark(gap(tmp)) = FALSE;  join(gap(tmp)) = TRUE;            \
  251. X    FposCopy(fpos(tmp), fpos(t));                    \
  252. X    PushToken(tmp);                            \
  253. X  }                                    \
  254. X} /* end InsertSpace */
  255. X
  256. X
  257. X/*****************************************************************************/
  258. X/*                                                                           */
  259. X/*  static Shift(t, prec, rassoc, leftpar, rightpar)                         */
  260. X/*  static ShiftObj(t)                                                       */
  261. X/*                                                                           */
  262. X/*  Shift token or object t onto the stacks; it has the attributes shown.    */
  263. X/*                                                                           */
  264. X/*****************************************************************************/
  265. X
  266. X#define Shift(t, prec, rassoc, leftpar, rightpar)            \
  267. X{ if( leftpar )                                \
  268. X  { for(;;)                                \
  269. X    { if( !obj_prev )                            \
  270. X      {    PushObj( MakeWord(WORD, STR_EMPTY, &fpos(t)) );            \
  271. X    obj_prev = TRUE;                        \
  272. X      }                                    \
  273. X      else if( precedence(TokenTop) >= prec + rassoc )     Reduce();    \
  274. X      else break;                            \
  275. X    }                                    \
  276. X  }                                    \
  277. X  else InsertSpace(t);                            \
  278. X  PushToken(t);                                \
  279. X  if( rightpar )  obj_prev = FALSE;                    \
  280. X  else { obj_prev = TRUE;  Reduce(); }                     \
  281. X} /* end Shift */
  282. X
  283. X#define ShiftObj(t) { InsertSpace(t); PushObj(t);  obj_prev = TRUE; }
  284. X
  285. X/*@::Reduce()@****************************************************************/
  286. X/*                                                                           */
  287. X/*  static Reduce()                                                          */
  288. X/*                                                                           */
  289. X/*  Perform a single reduction of the stacks.                                */
  290. X/*                                                                           */
  291. X/*****************************************************************************/
  292. X
  293. Xstatic Reduce()
  294. X{ OBJECT p1, p2, p3, s1, s2, tmp;
  295. X  OBJECT op;
  296. X  assert( obj_prev, "Reduce: obj_prev!" );
  297. X
  298. X  op = PopToken();
  299. X  obj_prev = TRUE;
  300. X  switch( type(op) )
  301. X  {
  302. X
  303. X    case GSTUB_INT:
  304. X    case GSTUB_EXT:
  305. X    
  306. X    TransferEnd( PopObj() );
  307. X    obj_prev = TRUE;
  308. X    PushObj(New(NULL_CLOS));
  309. X    Dispose(op);
  310. X    break;
  311. X
  312. X
  313. X    case GSTUB_NONE:
  314. X
  315. X    PushObj(New(NULL_CLOS));
  316. X    Dispose(op);
  317. X    break;
  318. X
  319. X
  320. X    case NULL_CLOS:
  321. X    case CROSS:
  322. X    case ONE_ROW:
  323. X    case ONE_COL:
  324. X    case WIDE:
  325. X    case HIGH:
  326. X    case HSCALE:
  327. X    case VSCALE:
  328. X    case SCALE:
  329. X    case HCONTRACT:
  330. X    case VCONTRACT:
  331. X    case HEXPAND:
  332. X    case VEXPAND:
  333. X    case PADJUST:
  334. X    case HADJUST:
  335. X    case VADJUST:
  336. X    case ROTATE:
  337. X    case CASE:
  338. X    case YIELD:
  339. X    case XCHAR:
  340. X    case FONT:
  341. X    case SPACE:
  342. X    case BREAK:
  343. X    case NEXT:
  344. X    case TAGGED:
  345. X    case INCGRAPHIC:
  346. X    case SINCGRAPHIC:
  347. X    case GRAPHIC:
  348. X    case OPEN:
  349. X
  350. X    if( has_rpar(actual(op)) )
  351. X    { s2 = PopObj();
  352. X      Link(op, s2);
  353. X    }
  354. X    if( has_lpar(actual(op)) )
  355. X    { s1 = PopObj();
  356. X      Link(Down(op), s1);
  357. X      if( type(op)==CROSS && type(s1)!=CLOSURE ) Error(WARN, &fpos(s1),
  358. X        "left parameter of %s is not a symbol (or not visible)", KW_CROSS);
  359. X    }
  360. X    PushObj(op);
  361. X    break;
  362. X
  363. X
  364. X    case CLOSURE:
  365. X    
  366. X    if( has_rpar(actual(op)) )
  367. X    { s2 = New(PAR);
  368. X      tmp = PopObj();
  369. X      Link(s2, tmp);
  370. X      FposCopy(fpos(s2), fpos(tmp));
  371. X      actual(s2) = ChildSym(actual(op), RPAR);
  372. X      Link(op, s2);
  373. X    }
  374. X    if( has_lpar(actual(op)) )
  375. X    { s1 = New(PAR);
  376. X      tmp = PopObj();
  377. X      Link(s1, tmp);
  378. X      FposCopy(fpos(s1), fpos(tmp));
  379. X      actual(s1) = ChildSym(actual(op), LPAR);
  380. X      Link(Down(op), s1);
  381. X    }
  382. X    PushObj(op);
  383. X    break;
  384. X
  385. X
  386. X    case LBR:
  387. X    
  388. X    Error(WARN, &fpos(op), "unmatched %s - inserted %s", KW_LBR, KW_RBR);
  389. X    Dispose(op);
  390. X    break;
  391. X
  392. X
  393. X    case BEGIN:
  394. X    
  395. X    Error(INTERN,&fpos(op), "Reduce: unmatched %s", KW_BEGIN);
  396. X    break;
  397. X
  398. X
  399. X    case RBR:
  400. X    
  401. X    if( type(TokenTop) == LBR )
  402. X    { /* *** FposCopy(fpos(ObjTop), fpos(TokenTop)); *** */
  403. X      Dispose( PopToken() );
  404. X    }
  405. X    else if( type(TokenTop) == BEGIN )
  406. X      Error(WARN, &fpos(op), "unmatched %s; inserted %s at%s (after %s)",
  407. X        KW_RBR, KW_LBR, EchoFilePos(&fpos(TokenTop)), KW_BEGIN);
  408. X    else Error(INTERN, &fpos(op), "Reduce: unmatched %s", KW_RBR);
  409. X    Dispose(op);
  410. X    break;
  411. X
  412. X
  413. X    case END:
  414. X    
  415. X    if( type(TokenTop) != BEGIN )
  416. X      Error(INTERN, &fpos(op), "Reduce: unmatched %s", KW_END);
  417. X    else
  418. X    { if( actual(op) != actual(TokenTop) )
  419. X        if( actual(op) == StartSym )
  420. X          Error(WARN, &fpos(op),
  421. X        "%s %s appended at end of file to match %s at%s",
  422. X        KW_END, SymName(actual(TokenTop)),
  423. X        KW_BEGIN, EchoFilePos(&fpos(TokenTop)) );
  424. X        else if( actual(op) == nil )
  425. X          Error(WARN, &fpos(op),
  426. X        "%s replaced by %s %s to match %s at%s", KW_END, KW_END,
  427. X        SymName(actual(TokenTop)),
  428. X        KW_BEGIN, EchoFilePos(&fpos(TokenTop)) );
  429. X        else
  430. X          Error(WARN, &fpos(op),
  431. X        "%s %s replaced by %s %s to match %s at%s",
  432. X        KW_END, SymName(actual(op)), KW_END, SymName(actual(TokenTop)),
  433. X        KW_BEGIN, EchoFilePos(&fpos(TokenTop)) );
  434. X      Dispose( PopToken() );
  435. X    }
  436. X    Dispose(op);
  437. X    break;
  438. X
  439. X
  440. X    case GAP_OBJ:
  441. X
  442. X    p1 = PopObj();
  443. X    Link(op, p1);
  444. X    PushObj(op);
  445. X    obj_prev = FALSE;
  446. X    break;
  447. X
  448. X
  449. X    case VCAT:
  450. X    case HCAT:
  451. X    case ACAT:
  452. X    
  453. X    p3 = PopObj();  p2 = PopObj();  p1 = PopObj();
  454. X    if( type(p1) == type(op) )  Dispose(op);
  455. X    else
  456. X    { Link(op, p1);
  457. X      p1 = op;
  458. X    }
  459. X    Link(p1, p2);
  460. X    Link(p1, p3);
  461. X    PushObj(p1);
  462. X    break;
  463. X
  464. X
  465. X    case TSPACE:
  466. X    case TJUXTA:
  467. X
  468. X    p2 = PopObj();  p1 = PopObj();
  469. X    if( type(p1) != ACAT )
  470. X    { tmp = New(ACAT);
  471. X      Link(tmp, p1);
  472. X      FposCopy(fpos(tmp), fpos(p1));
  473. X      p1 = tmp;
  474. X    }
  475. X    type(op) = GAP_OBJ;
  476. X    Link(p1, op);
  477. X    Link(p1, p2);
  478. X    PushObj(p1);
  479. X    break;
  480. X
  481. X
  482. X    default:
  483. X    
  484. X    Error(INTERN, &fpos(op), "Reduce: %s", Image(type(op)) );
  485. X    break;
  486. X
  487. X  } /* end switch */
  488. X  debug0(DOP, DD, "Reduce returning; ");
  489. X  ifdebug(DOP, DD, DebugStacks(0) );
  490. X} /* end Reduce */
  491. X
  492. X
  493. X/*@::SetScope(), InitParser()@************************************************/
  494. X/*                                                                           */
  495. X/*  static SetScope(env, count)                                              */
  496. X/*                                                                           */
  497. X/*  Push scopes required to parse object whose environment is env.           */
  498. X/*  Add to *count the number of scope pushes made.                           */
  499. X/*                                                                           */
  500. X/*****************************************************************************/
  501. X
  502. Xstatic SetScope(env, count)
  503. XOBJECT env;  int *count;
  504. X{ OBJECT link, y, yenv;
  505. X  debug2(DOP, D, "SetScope( %s, %d )", EchoObject(env), *count);
  506. X  assert( env != nil && type(env) == ENV, "SetScope: type(env) != ENV!" );
  507. X  if( Down(env) != env )
  508. X  { Child(y, Down(env));
  509. X    assert( LastDown(y) != y, "SetScope: LastDown(y)!" );
  510. X    link = LastDown(env) != Down(env) ? LastDown(env) : LastDown(y);
  511. X    Child(yenv, link);
  512. X    assert( type(yenv) == ENV, "SetScope: type(yenv) != ENV!" );
  513. X    SetScope(yenv, count);
  514. X    PushScope(actual(y), FALSE, FALSE);  (*count)++;
  515. X  }
  516. X  debug1(DOP, D, "SetScope returning, count = %d", *count);
  517. X} /* end SetScope */
  518. X
  519. X
  520. X/*****************************************************************************/
  521. X/*                                                                           */
  522. X/*  InitParser()                                                             */
  523. X/*                                                                           */
  524. X/*  Initialise the parser to contain just GstubExt.                          */
  525. X/*  Remember cross_db, the name of the cross reference database, for Parse.  */
  526. X/*                                                                           */
  527. X/*****************************************************************************/
  528. X
  529. XInitParser(cross_db)
  530. XFULL_CHAR *cross_db;
  531. X{ if( StringLength(cross_db) >= MAX_LINE )  Error(FATAL, no_fpos,
  532. X    "cross reference database file name %s is too long", cross_db);
  533. X  cross_name = MakeWord(WORD, cross_db, no_fpos);
  534. X  PushToken( NewToken(GSTUB_EXT, no_fpos, 0, 0, DEFAULT_PREC, StartSym) );
  535. X} /* end InitParser */
  536. X
  537. X
  538. X/*@::ParseEnvClosure()@*******************************************************/
  539. X/*                                                                           */
  540. X/*  static OBJECT ParseEnvClosure(t, encl)                                   */
  541. X/*                                                                           */
  542. X/*  Parse an object which is a closure with environment.  Consume the        */
  543. X/*  concluding @Clos.                                                        */
  544. X/*                                                                           */
  545. X/*****************************************************************************/
  546. X
  547. Xstatic OBJECT ParseEnvClosure(t, encl)
  548. XOBJECT t, encl;
  549. X{ OBJECT env, res, y;  int count, i;
  550. X  debug0(DOP, DD, "ParseEnvClosure(t, encl)");
  551. X  assert( type(t) == ENV, "ParseEnvClosure: type(t) != ENV!" );
  552. X  env = t;  t = LexGetToken();
  553. X  while( type(t) != CLOS )  switch( type(t) )
  554. X  {
  555. X    case LBR:    count = 0;
  556. X        SetScope(env, &count);
  557. X        y = Parse(&t, encl, FALSE, FALSE);
  558. X        if( type(y) != CLOSURE )  Error(FATAL, &fpos(y),
  559. X            "syntax error in cross reference database");
  560. X        for( i = 1;  i <= count;  i++ )  PopScope();
  561. X        AttachEnv(env, y);
  562. X        debug0(DCR, DD, "  calling SetEnv from ParseEnvClosure (a)");
  563. X        env = SetEnv(y, nil);
  564. X        t = LexGetToken();
  565. X        break;
  566. X
  567. X    case ENV:    y = ParseEnvClosure(t, encl);
  568. X        debug0(DCR, DD, "  calling SetEnv from ParseEnvClosure (b)");
  569. X        env = SetEnv(y, env);
  570. X        t = LexGetToken();
  571. X        break;
  572. X
  573. X    default:    Error(FATAL, &fpos(t), "error in cross reference database");
  574. X        break;
  575. X  }
  576. X  Dispose(t);
  577. X  if( Down(env) == env || Down(env) != LastDown(env) )
  578. X    Error(FATAL, &fpos(env), "error in cross reference database");
  579. X  Child(res, Down(env));
  580. X  DeleteNode(env);
  581. X  debug1(DOP, DD, "ParseEnvClosure returning %s", EchoObject(res));
  582. X  assert( type(res) == CLOSURE, "ParseEnvClosure: type(res) != CLOSURE!" );
  583. X  return res;
  584. X} /* end ParseEnvClosure */
  585. X
  586. X
  587. X/*@::Parse()@*****************************************************************/
  588. X/*                                                                           */
  589. X/*  OBJECT Parse(token, encl, defs_allowed, transfer_allowed)                */
  590. X/*                                                                           */
  591. X/*  Parse input tokens, beginning with *token, looking for an object of the  */
  592. X/*  form { ... } or @Begin ... @End <sym>, and return the object.            */
  593. X/*  The parent definition is encl, and scope has been set appropriately.     */
  594. X/*  Parse reads up to and including the last token of the object             */
  595. X/*  (the right brace or <sym>), and returns nil in *token.                   */
  596. X/*                                                                           */
  597. X/*  If defs_allowed == TRUE, there may be local definitions in the object.   */
  598. X/*  In this case, encl is guaranteed to be the enclosing definition.         */
  599. X/*                                                                           */
  600. X/*  If transfer_allowed == TRUE, the parser may transfer components to the   */
  601. X/*  galley handler as they are read.                                         */
  602. X/*                                                                           */
  603. X/*  Note: the lexical analyser returns "@End \Input" at end of input, so the */
  604. X/*  parser does not have to handle end of input separately.                  */
  605. X/*                                                                           */
  606. X/*****************************************************************************/
  607. X
  608. XOBJECT Parse(token, encl, defs_allowed, transfer_allowed)
  609. XOBJECT *token, encl;  BOOLEAN defs_allowed, transfer_allowed;
  610. X{ OBJECT t, x, tmp, xsym, env, y, res;
  611. X  int i, initial_ttop = ttop;
  612. X
  613. X  debug4(DOP, D, "[ Parse(%s, %s, %s, %s)", EchoToken(*token),
  614. X    SymName(encl), bool(defs_allowed), bool(transfer_allowed));
  615. X  assert( type(*token) == LBR || type(*token) == BEGIN, "Parse: *token!" );
  616. X
  617. X  obj_prev = FALSE;
  618. X  Shift(*token, precedence(*token), 0, FALSE, TRUE);
  619. X  t = LexGetToken();
  620. X  if( defs_allowed )
  621. X  { ReadDefinitions(&t, encl, LOCAL);
  622. X    if( encl == StartSym ) /* transition point from defs to content */
  623. X    {
  624. X      /* if error in definitions, stop now */
  625. X      if( ErrorSeen() )  Error(FATAL, &fpos(t), "Exiting now");
  626. X
  627. X      /* load cross-references from previous run, open new cross refs */
  628. X      if( AllowCrossDb )
  629. X      {    NewCrossDb = DbCreate(MakeWord(WORD, string(cross_name), no_fpos));
  630. X    OldCrossDb = DbLoad(cross_name, SOURCE_PATH, FALSE, nil);
  631. X      }
  632. X      else OldCrossDb = NewCrossDb = nil;
  633. X
  634. X      /* tidy up and possibly print symbol table */
  635. X      FlattenUses();
  636. X      ifdebug(DST, D, DebugObject(StartSym));
  637. X
  638. X      /* read @Use, @Database, and @Prepend commands and construct env */
  639. X      env = New(ENV);
  640. X      for(;;)
  641. X      {    if( type(t) == USE )
  642. X    {
  643. X      OBJECT crs, res_env;  STYLE style;
  644. X      Dispose(t);  t = LexGetToken();
  645. X      if( type(t) != LBR )
  646. X        Error(FATAL, &fpos(t), "%s expected after %s", KW_LBR, KW_USE);
  647. X      y = Parse(&t, encl, FALSE, FALSE);
  648. X      if( type(y) == CROSS )
  649. X      { y = CrossExpand(y, env, &style, FALSE, &crs, &res_env);
  650. X        AttachEnv(res_env, y);
  651. X        debug0(DCR, DD, "  calling SetEnv from Parse (a)");
  652. X        env = SetEnv(y, env);
  653. X      }
  654. X      else if( type(y) == CLOSURE )
  655. X      { AttachEnv(env, y);
  656. X        debug0(DCR, DD, "  calling SetEnv from Parse (b)");
  657. X        env = SetEnv(y, nil);
  658. X      }
  659. X      else Error(FATAL, &fpos(y), "invalid parameter of %s", KW_USE);
  660. X      PushScope(actual(y), FALSE, TRUE);
  661. X      t = LexGetToken();
  662. X        }
  663. X    else if( type(t) == PREPEND || type(t) == SYS_PREPEND )
  664. X    { ReadPrependDef(type(t), encl);
  665. X      Dispose(t);
  666. X      t = LexGetToken();
  667. X    }
  668. X    else if( type(t) == DATABASE || type(t) == SYS_DATABASE )
  669. X    { ReadDatabaseDef(type(t), encl);
  670. X      Dispose(t);
  671. X      t = LexGetToken();
  672. X    }
  673. X    else break;
  674. X      }
  675. X      TransferInit(env);
  676. X    }
  677. X  }
  678. X
  679. X  for(;;)
  680. X  { 
  681. X    ifdebug(DOP, DD, DebugStacks(initial_ttop) );
  682. X    debug2(DOP, DD, ">> %s.%d", EchoToken(t), precedence(t) );
  683. X
  684. X    switch( type(t) )
  685. X    {
  686. X
  687. X      case WORD:
  688. X      
  689. X    if( string(t)[0] == CH_SYMSTART )
  690. X      Error(WARN, &fpos(t), "symbol %s unknown or misspelt", string(t));
  691. X    ShiftObj(t);
  692. X    t = LexGetToken();
  693. X    break;
  694. X
  695. X
  696. X      case QWORD:
  697. X      
  698. X    ShiftObj(t);
  699. X    t = LexGetToken();
  700. X    break;
  701. X
  702. X
  703. X      case VCAT:
  704. X      case HCAT:
  705. X      case ACAT:
  706. X      
  707. X    /* clean up left context */
  708. X    Shift(t, precedence(t), LEFT_ASSOC, TRUE, TRUE);
  709. X
  710. X    /* invoke transfer subroutines if appropriate */
  711. X    if( type(t) == VCAT && !has_join(actual(t))
  712. X        && type(tok_stack[ttop-2]) == GSTUB_EXT )
  713. X    { TransferComponent( PopObj() );
  714. X      obj_prev = FALSE;
  715. X      tmp = New(NULL_CLOS);
  716. X      FposCopy( fpos(tmp), fpos(t) );
  717. X      PushObj(tmp);
  718. X    }
  719. X
  720. X    /* push GAP_OBJ token, to cope with 3 parameters */
  721. X    x = New(GAP_OBJ);
  722. X    mark(gap(x)) = has_mark(actual(t));
  723. X    join(gap(x)) = has_join(actual(t));
  724. X    precedence(x) = GAP_PREC;
  725. X    FposCopy( fpos(x), fpos(t) );
  726. X    Shift(x, GAP_PREC, LEFT_ASSOC, FALSE, TRUE);
  727. X
  728. X    /* if op is followed by space, insert {} */
  729. X    t = LexGetToken();
  730. X    if( hspace(t) + vspace(t) > 0 )
  731. X    { ShiftObj(MakeWord(WORD, STR_EMPTY, &fpos(x)));
  732. X    }
  733. X    break;
  734. X
  735. X
  736. X      case CROSS:
  737. X      case NULL_CLOS:
  738. X      case ONE_COL:
  739. X      case ONE_ROW:
  740. X      case WIDE:
  741. X      case HIGH:
  742. X      case HSCALE:
  743. X      case VSCALE:
  744. X      case SCALE:
  745. X      case HCONTRACT:
  746. X      case VCONTRACT:
  747. X      case HEXPAND:
  748. X      case VEXPAND:
  749. X      case PADJUST:
  750. X      case HADJUST:
  751. X      case VADJUST:
  752. X      case ROTATE:
  753. X      case CASE:
  754. X      case YIELD:
  755. X      case XCHAR:
  756. X      case FONT:
  757. X      case SPACE:
  758. X      case BREAK:
  759. X      case NEXT:
  760. X      case TAGGED:
  761. X      case INCGRAPHIC:
  762. X      case SINCGRAPHIC:
  763. X      case GRAPHIC:
  764. X
  765. X    /* clean up left context of t (these ops are all right associative) */
  766. X    Shift(t, precedence(t), RIGHT_ASSOC,
  767. X        has_lpar(actual(t)), has_rpar(actual(t)));
  768. X    t = LexGetToken();
  769. X    break;
  770. X
  771. X
  772. X      case BEGIN:
  773. X      
  774. X    if( actual(t) == nil )
  775. X    { Error(WARN, &fpos(t), "%s replaced by %s", KW_BEGIN, KW_LBR);
  776. X      type(t) = LBR;
  777. X    }
  778. X    /* NB NO BREAK! */
  779. X
  780. X
  781. X      case LBR:
  782. X      
  783. X    Shift(t, LBR_PREC, 0, FALSE, TRUE);
  784. X    t = LexGetToken();
  785. X    break;
  786. X
  787. X
  788. X      case END:
  789. X      
  790. X    x = LexGetToken();
  791. X    if( type(x) == CLOSURE )
  792. X    { actual(t) = actual(x);
  793. X      Dispose(x);
  794. X      x = nil;
  795. X    }
  796. X    else if( type(x) == WORD && string(x)[0] == CH_SYMSTART )
  797. X    { Error(WARN,&fpos(x),"unknown or misspelt symbol %s after %s deleted",
  798. X        string(x), KW_END);
  799. X      actual(t) = nil;
  800. X      Dispose(x);
  801. X      x = nil;
  802. X    }
  803. X    else
  804. X    { Error(WARN, &fpos(x), "symbol expected after %s", KW_END);
  805. X      actual(t) = nil;
  806. X    }
  807. X    Shift(t, precedence(t), 0, TRUE, FALSE);
  808. X    if( ttop == initial_ttop )
  809. X    { ifdebug(DOP, DD, DebugStacks(initial_ttop));
  810. X      *token = x;
  811. X      debug0(DOP, D, "] Parse returning");
  812. X      ifdebug(DOP, D, DebugObject(ObjTop));
  813. X      obj_prev = FALSE;
  814. X      return PopObj();
  815. X    }
  816. X    t = (x != nil) ? x : LexGetToken();
  817. X    break;
  818. X
  819. X
  820. X      case RBR:
  821. X      
  822. X    Shift(t, precedence(t), 0, TRUE, FALSE);
  823. X    if( ttop == initial_ttop )
  824. X    { ifdebug(DOP, DD, DebugStacks(initial_ttop));
  825. X      *token = nil;
  826. X      debug0(DOP, D, "] Parse returning");
  827. X      ifdebug(DOP, D, DebugObject(ObjTop));
  828. X      obj_prev = FALSE;
  829. X      return PopObj();
  830. X    }
  831. X    t = LexGetToken();
  832. X    break;
  833. X                
  834. X
  835. X      case USE:
  836. X      case PREPEND:
  837. X      case SYS_PREPEND:
  838. X      case DATABASE:
  839. X      case SYS_DATABASE:
  840. X      
  841. X    Error(FATAL, &fpos(t), "%s symbol out of place", SymName(actual(t)));
  842. X    break;
  843. X
  844. X
  845. X      case ENV:
  846. X      
  847. X    /* only occurs in cross reference databases */
  848. X    res = ParseEnvClosure(t, encl);
  849. X    ShiftObj(res);
  850. X    t = LexGetToken();
  851. X    break;
  852. X
  853. X
  854. X      case LVIS:
  855. X      
  856. X    /* only occurs in cross-reference databases */
  857. X    SuppressVisible();
  858. X    Dispose(t);  t = LexGetToken();
  859. X    UnSuppressVisible();
  860. X    if( type(t) != CLOSURE )
  861. X      Error(FATAL, &fpos(t), "symbol expected following %s", KW_LVIS);
  862. X    /* NB NO BREAK! */
  863. X
  864. X
  865. X      case CLOSURE:
  866. X      
  867. X    x = t;  xsym = actual(x);
  868. X
  869. X    /* look ahead one token, which could be an NPAR */
  870. X    PushScope(xsym, TRUE, FALSE);
  871. X    t = LexGetToken();
  872. X    PopScope();
  873. X
  874. X    /* if x starts a cross-reference, make it a CLOSURE */
  875. X    if( type(t) == CROSS )
  876. X    { ShiftObj(x);
  877. X      break;
  878. X    }
  879. X
  880. X    /* clean up left context of x */
  881. X    Shift(x, precedence(x),right_assoc(xsym),has_lpar(xsym),has_rpar(xsym));
  882. X
  883. X    /* update uses relation if required */
  884. X    if( encl != StartSym )
  885. X    { if( !has_target(xsym) )  InsertUses(encl, xsym);
  886. X      else uses_galley(encl) = TRUE;
  887. X    }
  888. X
  889. X    /* read named parameters */
  890. X    while( type(t) == CLOSURE && enclosing(actual(t)) == xsym
  891. X                       && type(actual(t)) == NPAR )
  892. X    {    
  893. X      /* check syntax and attach the named parameter to x */
  894. X      OBJECT new_par = t;
  895. X      t = LexGetToken();
  896. X      if( type(t) != LBR )
  897. X      { Error(WARN, &fpos(new_par), "%s must follow named parameter %s",
  898. X          KW_LBR, SymName(actual(new_par)));
  899. X        Dispose(new_par);
  900. X        break;
  901. X      }
  902. X
  903. X      /* read the body of the named parameter */
  904. X      PushScope(actual(new_par), FALSE, FALSE);
  905. X      tmp = Parse(&t, encl, FALSE, FALSE);
  906. X      type(new_par) = PAR;
  907. X      Link(x, new_par);
  908. X      Link(new_par, tmp);
  909. X      PopScope();
  910. X
  911. X      /* get next token, possibly another NPAR */
  912. X      PushScope(xsym, TRUE, FALSE);     /* allow NPARs only */
  913. X      if( t == nil )  t = LexGetToken();
  914. X      PopScope();
  915. X
  916. X    } /* end while */
  917. X    obj_prev = !has_rpar(xsym);
  918. X
  919. X    /* record symbol name in BEGIN following, if any */
  920. X    if( type(t) == BEGIN )
  921. X    { if( !has_rpar(xsym) )
  922. X        Error(WARN, &fpos(x), "%s takes no right parameter", SymName(xsym));
  923. X      else actual(t) = xsym;
  924. X    }
  925. X
  926. X    /* if x can be transferred, do so */
  927. X    if( transfer_allowed && has_target(xsym) && !has_key(xsym) )
  928. X    {   
  929. X      if( !has_rpar(xsym) || uses_count(ChildSym(xsym, RPAR)) <= 1 )
  930. X      {
  931. X        debug1(DGT, DD, "examining transfer of %s", SymName(xsym));
  932. X        ifdebug(DGT, DD, DebugStacks(initial_ttop));
  933. X        i = has_rpar(xsym) ? ttop -1 : ttop;
  934. X        while( is_cat_op(type(tok_stack[i])) )   i--;
  935. X        if( (type(tok_stack[i])==LBR || type(tok_stack[i])==BEGIN)
  936. X          && type(tok_stack[i-1]) == GSTUB_EXT )
  937. X        {
  938. X          /* at this point it is likely that x is transferable */
  939. X          if( has_rpar(xsym) )
  940. X          { tmp = New(CLOSURE);
  941. X        actual(tmp) = InputSym;
  942. X        FposCopy( fpos(tmp), fpos(t) );
  943. X        PushObj(tmp);  obj_prev = TRUE;
  944. X        Reduce();
  945. X          }
  946. X          x = PopObj();
  947. X          x = TransferBegin(x);
  948. X          if( type(x) == CLOSURE )    /* failure: unReduce */
  949. X          {    if( has_rpar(xsym) )
  950. X        { Child(tmp, LastDown(x));
  951. X          assert(type(tmp)==PAR && type(actual(tmp))==RPAR,
  952. X                "Parse: cannot undo rpar" );
  953. X          DisposeChild(LastDown(x));
  954. X          if( has_lpar(xsym) )
  955. X          { Child(tmp, Down(x));
  956. X            assert(type(tmp)==PAR && type(actual(tmp))==LPAR,
  957. X                "Parse: cannot undo lpar" );
  958. X            Child(tmp, Down(tmp));
  959. X            PushObj(tmp);
  960. X            DeleteLink(Up(tmp));
  961. X            DisposeChild(Down(x));
  962. X          }
  963. X          PushToken(x);  obj_prev = FALSE;
  964. X        }
  965. X        else
  966. X        { PushObj(x);
  967. X          obj_prev = TRUE;
  968. X        }
  969. X          }
  970. X          else /* success */
  971. X          { obj_prev = FALSE;
  972. X            Shift(x, NO_PREC, 0, FALSE, has_rpar(xsym));
  973. X          }
  974. X        }
  975. X      }
  976. X    } /* end if has_target */
  977. X
  978. X    if( has_body(xsym) )
  979. X    { if( type(t) == BEGIN || type(t) == LBR )
  980. X      { PushScope(xsym, FALSE, TRUE);
  981. X        PushScope(ChildSym(xsym, RPAR), FALSE, FALSE);
  982. X        PushObj( Parse(&t, encl, FALSE, TRUE) );
  983. X        obj_prev = TRUE;
  984. X        Reduce();
  985. X        PopScope();
  986. X        PopScope();
  987. X        if( t == nil )  t = LexGetToken();
  988. X      }
  989. X      else
  990. X      { Error(WARN, &fpos(t),
  991. X          "%s parameter of %s must be enclosed in %s .. %s",
  992. X          KW_BODY, SymName(xsym), KW_LBR, KW_RBR);
  993. X      }
  994. X    }
  995. X    break;
  996. X
  997. X
  998. X      case OPEN:
  999. X
  1000. X    x = t;  xsym = nil;
  1001. X    Shift(t, precedence(t), RIGHT_ASSOC, TRUE, TRUE);
  1002. X    if( type(ObjTop) == CLOSURE )  xsym = actual(ObjTop);
  1003. X    else if( type(ObjTop) == CROSS && Down(ObjTop) != ObjTop )
  1004. X    { Child(tmp, Down(ObjTop));
  1005. X      if( type(tmp) == CLOSURE )  xsym = actual(tmp);
  1006. X    }
  1007. X    t = LexGetToken();
  1008. X
  1009. X    if( xsym == nil )  Error(WARN, &fpos(x),
  1010. X      "invalid left parameter of %s", KW_OPEN);
  1011. X    else if( type(t) != BEGIN && type(t) != LBR )
  1012. X      Error(WARN, &fpos(t), "%s parameter of %s not enclosed in %s .. %s",
  1013. X        KW_RIGHT, KW_OPEN, KW_LBR, KW_RBR);
  1014. X    else
  1015. X    { PushScope(xsym, FALSE, TRUE);
  1016. X      tmp = Parse(&t, encl, FALSE, FALSE);
  1017. X      ShiftObj(tmp);
  1018. X      PopScope();
  1019. X      if( t == nil )  t = LexGetToken();
  1020. X      Reduce();
  1021. X    }
  1022. X    break;
  1023. X
  1024. X
  1025. X      default:
  1026. X      
  1027. X    Error(INTERN, &fpos(t), "Parse: type %s", Image(type(t)) );
  1028. X    break;
  1029. X
  1030. X    } /* end switch */
  1031. X  } /* end for */
  1032. X
  1033. X} /* end Parse */
  1034. END_OF_FILE
  1035.   if test 28492 -ne `wc -c <'z06.c'`; then
  1036.     echo shar: \"'z06.c'\" unpacked with wrong size!
  1037.   fi
  1038.   # end of 'z06.c'
  1039. fi
  1040. if test -f 'z08.c' -a "${1}" != "-c" ; then 
  1041.   echo shar: Will not clobber existing file \"'z08.c'\"
  1042. else
  1043.   echo shar: Extracting \"'z08.c'\" \(36924 characters\)
  1044.   sed "s/^X//" >'z08.c' <<'END_OF_FILE'
  1045. X/*@z08.c:Object Manifest:ReplaceWithSplit()@**********************************/
  1046. X/*                                                                           */
  1047. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  1048. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  1049. X/*                                                                           */
  1050. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  1051. X/*  Basser Department of Computer Science                                    */
  1052. X/*  The University of Sydney 2006                                            */
  1053. X/*  AUSTRALIA                                                                */
  1054. X/*                                                                           */
  1055. X/*  This program is free software; you can redistribute it and/or modify     */
  1056. X/*  it under the terms of the GNU General Public License as published by     */
  1057. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  1058. X/*  any later version.                                                       */
  1059. X/*                                                                           */
  1060. X/*  This program is distributed in the hope that it will be useful,          */
  1061. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  1062. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  1063. X/*  GNU General Public License for more details.                             */
  1064. X/*                                                                           */
  1065. X/*  You should have received a copy of the GNU General Public License        */
  1066. X/*  along with this program; if not, write to the Free Software              */
  1067. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  1068. X/*                                                                           */
  1069. X/*  FILE:         z08.c                                                      */
  1070. X/*  MODULE:       Object Manifest                                            */
  1071. X/*  EXTERNS:      Manifest()                                                 */
  1072. X/*                                                                           */
  1073. X/*****************************************************************************/
  1074. X#include "externs"
  1075. X
  1076. X#define errorcase()                            \
  1077. X                                    \
  1078. X    y = MakeWord(WORD, STR_EMPTY, &fpos(x));                \
  1079. X    ReplaceNode(y, x);  DisposeObject(x);                \
  1080. X    x = Manifest(y, env, style, bthr, fthr, target, crs, ok, FALSE);    \
  1081. X    break;
  1082. X
  1083. X
  1084. X/*****************************************************************************/
  1085. X/*                                                                           */
  1086. X/*  static ReplaceWithSplit(x, bthr, fthr)                                   */
  1087. X/*                                                                           */
  1088. X/*  Replace object x with a SPLIT object, if threads for this object are     */
  1089. X/*  requested by bthr and/or fthr.                                           */
  1090. X/*                                                                           */
  1091. X/*****************************************************************************/
  1092. X
  1093. X#define ReplaceWithSplit(x, bthr, fthr)                    \
  1094. X   if( bthr[ROW] || bthr[COL] || fthr[ROW] || fthr[COL] )        \
  1095. X    x = insert_split(x, bthr, fthr)
  1096. X
  1097. Xstatic OBJECT insert_split(x, bthr, fthr)
  1098. XOBJECT x;  OBJECT bthr[2], fthr[2];
  1099. X{ OBJECT res, new_op;  int dim;
  1100. X  debug1(DOM, DD, "ReplaceWithSplit(%s, -)", EchoObject(x));
  1101. X  assert( type(x) != SPLIT, "ReplaceWithSplit: type(x) already SPLIT!" );
  1102. X  res = New(SPLIT);
  1103. X  FposCopy(fpos(res), fpos(x));
  1104. X  ReplaceNode(res, x);
  1105. X  for( dim = COL;  dim <= ROW;  dim++ )
  1106. X  { if( bthr[dim] || fthr[dim] )
  1107. X    { new_op = New(dim == COL ? COL_THR : ROW_THR);
  1108. X      thr_state(new_op) = NOTSIZED;
  1109. X      fwd(new_op, 1-dim) = 0;    /* will hold max frame_size */
  1110. X      back(new_op, 1-dim) = 0;    /* will hold max frame_origin */
  1111. X      FposCopy(fpos(new_op), fpos(x));
  1112. X      Link(res, new_op);  Link(new_op, x);
  1113. X      if( bthr[dim] )  Link(bthr[dim], new_op);
  1114. X      if( fthr[dim] )  Link(fthr[dim], new_op);
  1115. X    }
  1116. X    else Link(res, x);
  1117. X  }
  1118. X
  1119. X  debug1(DOM, DD, "ReplaceWithSplit returning %s", EchoObject(res));
  1120. X  return res;
  1121. X} /* end insert_split */
  1122. X
  1123. X/*@::ReplaceWithTidy()@*******************************************************/
  1124. X/*                                                                           */
  1125. X/*  OBJECT ReplaceWithTidy(x)                                                */
  1126. X/*                                                                           */
  1127. X/*  Replace object x with a tidier version in which juxtapositions are       */
  1128. X/*  folded.  If this is not possible, return the original object.            */
  1129. X/*                                                                           */
  1130. X/*****************************************************************************/
  1131. X
  1132. XOBJECT ReplaceWithTidy(x)
  1133. XOBJECT x;
  1134. X{ static FULL_CHAR    buff[MAX_LINE];        /* the growing current word */
  1135. X  static int        buff_len;        /* length of current word   */
  1136. X  static FILE_POS    buff_pos;        /* filepos of current word  */
  1137. X  static unsigned    buff_typ;        /* WORD or QWORD of current */
  1138. X  OBJECT                link, y, tmp, res;    /* temporaries              */
  1139. X  debug1(DOM, DD, "ReplaceWithTidy( %s )", EchoObject(x));
  1140. X  switch( type(x) )
  1141. X  {
  1142. X    case ACAT:
  1143. X    
  1144. X      for( link = Down(x);  link != x;  link = NextDown(link) )
  1145. X      {    Child(y, link);
  1146. X    if( type(y) == ACAT )
  1147. X    { tmp = Down(y);  TransferLinks(tmp, y, link);
  1148. X      DisposeChild(link);  link = PrevDown(tmp);
  1149. X    }
  1150. X      }
  1151. X      res = nil;  buff_len = 0;  buff_typ = WORD;  FposCopy(buff_pos, fpos(x));
  1152. X      for( link = Down(x); link != x; link = NextDown(link) )
  1153. X      {    Child(y, link);
  1154. X    if( is_word(type(y)) )
  1155. X    { if( buff_len + StringLength(string(y)) >= MAX_LINE )
  1156. X        Error(WARN, &fpos(y), "word is too long");
  1157. X      else
  1158. X      { if( buff_len == 0 )  FposCopy(buff_pos, fpos(y));
  1159. X        StringCopy(&buff[buff_len], string(y));
  1160. X        buff_len += StringLength(string(y));
  1161. X        if( type(y) == QWORD )  buff_typ = QWORD;
  1162. X      }
  1163. X    }
  1164. X    else if( type(y) == GAP_OBJ )
  1165. X    { if( Down(y) != y || hspace(y) + vspace(y) > 0 )
  1166. X      { tmp = MakeWord(buff_typ, buff, &buff_pos);
  1167. X        buff_len = 0;  buff_typ = WORD;
  1168. X        if( res == nil ) { res = New(ACAT); FposCopy(fpos(res), fpos(x)); }
  1169. X        Link(res, tmp);  Link(res, y);
  1170. X      }
  1171. X    }
  1172. X    else /* error */
  1173. X    { if( res != nil )  DisposeObject(res);
  1174. X      debug0(DOM, DD, "ReplaceWithTidy returning unchanged");
  1175. X      return x;
  1176. X    }
  1177. X      }
  1178. X      tmp = MakeWord(buff_typ, buff, &buff_pos);
  1179. X      if( res == nil )  res = tmp;
  1180. X      else Link(res, tmp);
  1181. X      ReplaceNode(res, x);  DisposeObject(x);
  1182. X      debug1(DOM, DD, "ReplaceWithTidy returning %s", EchoObject(res));
  1183. X      return res;
  1184. X
  1185. X
  1186. X    case WORD:
  1187. X    case QWORD:
  1188. X
  1189. X      debug1(DOM, DD, "ReplaceWithTidy returning %s", EchoObject(x));
  1190. X      return x;
  1191. X
  1192. X
  1193. X    default:
  1194. X
  1195. X      debug0(DOM, DD, "ReplaceWithTidy returning unchanged");
  1196. X      return x;
  1197. X  }
  1198. X} /* end ReplaceWithTidy */
  1199. X
  1200. X
  1201. X/*@::GetScaleFactor()@********************************************************/
  1202. X/*                                                                           */
  1203. X/*  static float GetScaleFactor(x, str)                                      */
  1204. X/*                                                                           */
  1205. X/*  Find a scale factor in object x and return it as a float, after checks.  */
  1206. X/*  Incorporate str in any error messages generated.                         */
  1207. X/*                                                                           */
  1208. X/*****************************************************************************/
  1209. X
  1210. Xstatic float GetScaleFactor(x, str)
  1211. XOBJECT x;  char *str;
  1212. X{ float scale_factor;
  1213. X  if( !is_word(type(x)) )
  1214. X  { Error(WARN, &fpos(x), "replacing invalid %s by 1.0", str);
  1215. X    scale_factor = 1.0;
  1216. X  }
  1217. X  else if( sscanf( (char *) string(x), "%f", &scale_factor) != 1 )
  1218. X  { Error(WARN, &fpos(x), "replacing invalid %s %s by 1.0", str, string(x));
  1219. X    scale_factor = 1.0;
  1220. X  }
  1221. X  else if( scale_factor < 0.01 )
  1222. X  { Error(WARN, &fpos(x), "replacing undersized %s %s by 1.0", str, string(x));
  1223. X    scale_factor = 1.0;
  1224. X  }
  1225. X  else if( scale_factor > 100 )
  1226. X  { Error(WARN, &fpos(x), "replacing oversized %s %s by 1.0", str, string(x));
  1227. X    scale_factor = 1.0;
  1228. X  }
  1229. X  return scale_factor;
  1230. X} /* GetScaleFactor */
  1231. X
  1232. X
  1233. Xstatic OBJECT nbt[2] = { nil, nil };        /* constant nil threads      */
  1234. Xstatic OBJECT nft[2] = { nil, nil };        /* constant nil threads      */
  1235. Xstatic OBJECT ntarget = nil;            /* constant nil target       */
  1236. X
  1237. X/*@::Manifest()@**************************************************************/
  1238. X/*                                                                           */
  1239. X/*  OBJECT Manifest(x, env, style, bthr, fthr, target, crs, ok, need_expand) */
  1240. X/*                                                                           */
  1241. X/*  Manifest object x, interpreted in environment env and style style.       */
  1242. X/*  The result replaces x, and is returned also.                             */
  1243. X/*  The manifesting operation converts x from a pure parse tree object       */
  1244. X/*  containing closures and no threads, to an object ready for sizing,       */
  1245. X/*  with fonts propagated to the words, fill styles propagated to the        */
  1246. X/*  ACATs, and line spacings propagated to all interested parties.           */
  1247. X/*  All non-recursive, non-indefinite closures are expanded.                 */
  1248. X/*  Threads joining objects on a mark are constructed, and SPLIT objects     */
  1249. X/*  inserted, so that sizing becomes a trivial operation.                    */
  1250. X/*                                                                           */
  1251. X/*  Manifest will construct threads and pass them up as children of bthr[]   */
  1252. X/*  and fthr[] whenever non-nil values of these variables are passed in:     */
  1253. X/*                                                                           */
  1254. X/*      bthr[COL]            protrudes upwards from x                        */
  1255. X/*      fthr[COL]            protrudes downwards from x                      */
  1256. X/*      bthr[ROW]            protrudes leftwards from x                      */
  1257. X/*      fthr[ROW]            protrudes rightwards from x                     */
  1258. X/*                                                                           */
  1259. X/*  If *target != nil, Manifest will expand indefinite closures leading to   */
  1260. X/*  the first @Galley lying within an object of type *target.                */
  1261. X/*                                                                           */
  1262. X/*  Some objects x are not "real" in the sense that they do not give rise    */
  1263. X/*  to rectangles in the final printed document.  The left parameter of      */
  1264. X/*  @Wide and similar operators, and the gap following a concatenation       */
  1265. X/*  operator, are examples of such non-real objects.  The ok flag is true    */
  1266. X/*  when x is part of a real object.  This is needed because some things,    */
  1267. X/*  such as the insinuation of cross references and the breaking of          */
  1268. X/*  lines @Break ACAT objects, only apply to real objects.                   */
  1269. X/*                                                                           */
  1270. X/*  If *crs != nil, it points to a list of indexes to cross-references       */
  1271. X/*  which are to be insinuated into the manifested form of x if x is real.   */
  1272. X/*                                                                           */
  1273. X/*  If need_expand is TRUE it forces closure x to expand.                    */
  1274. X/*                                                                           */
  1275. X/*****************************************************************************/
  1276. X
  1277. XOBJECT Manifest(x, env, style, bthr, fthr, target, crs, ok, need_expand)
  1278. XOBJECT x, env;  STYLE *style;
  1279. XOBJECT bthr[2], fthr[2]; OBJECT *target, *crs;
  1280. XBOOLEAN ok, need_expand;
  1281. X{ OBJECT bt[2], ft[2], y, link, sym, tag, gaplink, g, ylink, yield, ytag, zlink;
  1282. X  OBJECT res, res_env, res_env2, hold_env, hold_env2, first_bt, last_ft, z;
  1283. X  OBJECT firsttag, firstres, prev;  float scale_factor;
  1284. X  int par, perp;  GAP res_gap;  unsigned res_inc;  STYLE new_style;
  1285. X  BOOLEAN still_backing, done, multiline, symbol_free;  FULL_CHAR ch;
  1286. X
  1287. X  debug2(DOM, D,   "[Manifest(%s %s )", Image(type(x)), EchoObject(x));
  1288. X  debug1(DOM, DD,  "  environment: %s", EchoObject(env));
  1289. X  debug6(DOM, DD,  "  style: %s;  target: %s;  threads: %s%s%s%s",
  1290. X    EchoStyle(style), SymName(*target),
  1291. X    bthr[COL] ? " up"    : "",  fthr[COL] ? " down"  : "",
  1292. X    bthr[ROW] ? " left"  : "",  fthr[ROW] ? " right" : "");
  1293. X
  1294. X  if( type(x) <= ACAT ) switch( type(x) )    /* breaks up oversize switch */
  1295. X  {
  1296. X
  1297. X    case CLOSURE:
  1298. X    
  1299. X      sym = actual(x);
  1300. X      StyleCopy(save_style(x), *style);
  1301. X      debug1(DOM, DD,  "  closure; sym = %s", SymName(sym));
  1302. X
  1303. X      /* expand parameters where possible, and find if they are all free */
  1304. X      symbol_free = TRUE;
  1305. X      for( link = Down(x);  link != x;  link = NextDown(link) )
  1306. X      { Child(y, link);
  1307. X    assert( type(y) == PAR, "Manifest/CLOSURE: type(y) != PAR!" );
  1308. X    Child(z, Down(y));
  1309. X    if( !is_word(type(z)) && !has_par(actual(y)) )
  1310. X    { if( is_tag(actual(y)) || is_key(actual(y)) || type(z) == NEXT )
  1311. X      { z = Manifest(z, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1312. X        z = ReplaceWithTidy(z);
  1313. X      }
  1314. X    }
  1315. X    if( !is_word(type(z)) )  symbol_free = FALSE;
  1316. X      }
  1317. X
  1318. X      /* if all parameters are free of symbols, optimize environment */
  1319. X      if( symbol_free && imports(sym) == nil && enclosing(sym) != StartSym )
  1320. X      {    y = SearchEnv(env, enclosing(sym));
  1321. X    if( y != nil && type(y) == CLOSURE )
  1322. X    { 
  1323. X      debug0(DCR, DD, "calling SetEnv from Manifest (a)");
  1324. X      env = SetEnv(y, nil);
  1325. X      hold_env2 = New(ACAT);  Link(hold_env2, env);
  1326. X    }
  1327. X    else
  1328. X    { Error(WARN, &fpos(x), "symbol %s used outside %s",
  1329. X        SymName(sym), SymName(enclosing(sym)));
  1330. X      hold_env2 = nil;
  1331. X    }
  1332. X      }
  1333. X      else hold_env2 = nil;
  1334. X
  1335. X      if( has_target(sym) && !need_expand )
  1336. X      {
  1337. X    /* convert symbols with targets to unsized galleys */
  1338. X    OBJECT hd = New(HEAD);
  1339. X    FposCopy(fpos(hd), fpos(x));
  1340. X    actual(hd) = sym;
  1341. X    backward(hd) = TargetSymbol(x, &whereto(hd));
  1342. X    ready_galls(hd) = nil;
  1343. X    must_expand(hd) = TRUE;
  1344. X    sized(hd) = FALSE;
  1345. X    ReplaceNode(hd, x);
  1346. X    Link(hd, x);
  1347. X    AttachEnv(env, x);
  1348. X    x = hd;
  1349. X          threaded(x) = bthr[COL] != nil || fthr[COL] != nil;
  1350. X    ReplaceWithSplit(x, bthr, fthr);
  1351. X      }
  1352. X      else if(
  1353. X        *target == sym                ? (*target = nil, TRUE) :
  1354. X        need_expand                ? TRUE  :
  1355. X        uses_galley(sym) && !recursive(sym) ? TRUE  :
  1356. X        !indefinite(sym) && !recursive(sym) ? TRUE  :
  1357. X        indefinite(sym)  && *target != nil  ? SearchUses(sym, *target)
  1358. X                            : FALSE
  1359. X         )
  1360. X      {
  1361. X    /* expand the closure and manifest the result */
  1362. X    debug1(DOM, DD, "expanding; style: %s", EchoStyle(style));
  1363. X    x = ClosureExpand(x, env, TRUE, crs, &res_env);
  1364. X    hold_env = New(ACAT);  Link(hold_env, res_env);
  1365. X    debug1(DOM, DD, "recursive call; style: %s", EchoStyle(style));
  1366. X    x = Manifest(x, res_env, style, bthr, fthr, target, crs, ok, FALSE);
  1367. X    DisposeObject(hold_env);
  1368. X      }
  1369. X      else
  1370. X      {
  1371. X    /* indefinite symbol, leave unexpanded */
  1372. X    AttachEnv(env, x);
  1373. X    threaded(x) = bthr[COL] != nil || fthr[COL] != nil;
  1374. X    debug0(DOM, DD,  "  closure; calling ReplaceWithSplit");
  1375. X    ReplaceWithSplit(x, bthr, fthr);
  1376. X      }
  1377. X      if( hold_env2 != nil )  DisposeObject(hold_env2);
  1378. X      break;
  1379. X
  1380. X
  1381. X    case NULL_CLOS:
  1382. X
  1383. X      StyleCopy(save_style(x), *style);
  1384. X      ReplaceWithSplit(x, bthr, fthr);
  1385. X      break;
  1386. X
  1387. X
  1388. X    case CROSS:
  1389. X    
  1390. X      assert( Down(x) != x && LastDown(x) != Down(x), "Manifest: CROSS child!");
  1391. X      debug0(DCR, DD, "  calling CrossExpand from Manifest/CROSS");
  1392. X      x = CrossExpand(x, env, style, TRUE, crs, &res_env);
  1393. X      assert( type(x) == CLOSURE, "Manifest/CROSS: type(x)!" );
  1394. X      hold_env = New(ACAT);  Link(hold_env, res_env);
  1395. X      /* expand here (calling Manifest immediately makes unwanted cr) */
  1396. X      x = ClosureExpand(x, res_env, FALSE, crs, &res_env2);
  1397. X      hold_env2 = New(ACAT);  Link(hold_env2, res_env2);
  1398. X      x = Manifest(x, res_env2, style, bthr, fthr, target, crs, ok, TRUE);
  1399. X      DisposeObject(hold_env);
  1400. X      DisposeObject(hold_env2);
  1401. X      break;
  1402. X
  1403. X
  1404. X    case WORD:
  1405. X    case QWORD:
  1406. X    
  1407. X      if( !ok || *crs == nil )
  1408. X      {    word_font(x) = font(*style);
  1409. X    ReplaceWithSplit(x, bthr, fthr);
  1410. X    break;
  1411. X      }
  1412. X      y = New(ACAT);
  1413. X      FposCopy(fpos(y), fpos(x));
  1414. X      ReplaceNode(y, x);
  1415. X      Link(y, x);  x = y;
  1416. X      /* NB NO BREAK! */
  1417. X
  1418. X
  1419. X    case ACAT:
  1420. X    
  1421. X      StyleCopy(save_style(x), *style);
  1422. X      assert(Down(x) != x, "Manifest: ACAT!" );
  1423. X      link = Down(x);  Child(y, link);
  1424. X      assert( type(y) != GAP_OBJ, "Manifest ACAT: GAP_OBJ is first!" );
  1425. X      multiline = FALSE;
  1426. X
  1427. X      /* manifest first child and insert any cross references */
  1428. X      if( is_word(type(y)) )  word_font(y) = font(*style);
  1429. X      else y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE);
  1430. X      if( ok && *crs != nil )
  1431. X      {    
  1432. X    debug1(DCR, D, "  insinuating %s", EchoObject(*crs));
  1433. X    TransferLinks(Down(*crs), *crs, link);
  1434. X    DisposeObject(*crs);
  1435. X    *crs = nil;
  1436. X      }
  1437. X      prev = y;
  1438. X
  1439. X      for( gaplink = Down(link);  gaplink != x;  gaplink = NextDown(link) )
  1440. X      {
  1441. X    Child(g, gaplink);
  1442. X    assert( type(g) == GAP_OBJ, "Manifest ACAT: no GAP_OBJ!" );
  1443. X    link = NextDown(gaplink);
  1444. X    assert( link != x, "Manifest ACAT: GAP_OBJ is last!" );
  1445. X    Child(y, link);
  1446. X    assert( type(y) != GAP_OBJ, "Manifest ACAT: double GAP_OBJ!" );
  1447. X
  1448. X    /* manifest the next child */
  1449. X        debug1(DOM, DD, "  in ACAT (3), style = %s", EchoStyle(style));
  1450. X    if( is_word(type(y)) ) word_font(y) = font(*style);
  1451. X    else y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE);
  1452. X
  1453. X    /* manifest the gap object */
  1454. X    if( Down(g) != g )
  1455. X    {
  1456. X      /* explicit & operator whose value is the child of g */
  1457. X      Child(z, Down(g));
  1458. X      z = Manifest(z, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1459. X      z = ReplaceWithTidy(z);
  1460. X      GetGap(z, style, &gap(g), &res_inc);
  1461. X      vspace(g) = hspace(g) = 0;
  1462. X    }
  1463. X    else
  1464. X    {
  1465. X      /* implicit & operator */
  1466. X      GapCopy(gap(g), space_gap(*style));
  1467. X      width(gap(g)) = width(gap(g)) * (vspace(g) + hspace(g));
  1468. X      if( vspace(g) > 0 && is_definite(type(y)) )  multiline = TRUE;
  1469. X    }
  1470. X        debug1(DOM, DD, "  in ACAT, gap = %s", EchoLength(width(gap(g))));
  1471. X
  1472. X    /* compress adjacent juxtaposed words of equal font */
  1473. X    if( is_word(type(y)) && width(gap(g)) == 0 && vspace(g)+hspace(g) == 0 )
  1474. X    { if( units(gap(g)) == FIXED_UNIT && mode(gap(g)) == EDGE_MODE )
  1475. X      { if( prev != nil && is_word(type(prev)) )
  1476. X        { if( !mark(gap(g)) && word_font(prev)==word_font(y) )
  1477. X          {    unsigned typ;
  1478. X        if( StringLength(string(prev)) + StringLength(string(y))
  1479. X              >= MAX_LINE )
  1480. X          Error(FATAL, &fpos(prev), "word %s%s is too long",
  1481. X            string(prev), string(y));
  1482. X        z = y;
  1483. X        typ = type(prev) == QWORD || type(y) == QWORD ? QWORD : WORD;
  1484. X        y = MakeWordTwo(typ, string(prev), string(y), &fpos(prev));
  1485. X        word_font(y) = word_font(prev);
  1486. X        MoveLink(link, y, CHILD);
  1487. X        DisposeObject(z);
  1488. X        DisposeChild(Up(prev));
  1489. X        DisposeChild(gaplink);
  1490. X          }
  1491. X        }
  1492. X      }
  1493. X    }
  1494. X    prev = y;
  1495. X
  1496. X    /* insinuate any cross-references */
  1497. X    if( ok && *crs != nil )
  1498. X    {
  1499. X      debug1(DCR, D, "  insinuating %s", EchoObject(*crs));
  1500. X      TransferLinks(Down(*crs), *crs, link);
  1501. X      DisposeObject(*crs);
  1502. X      *crs = nil;
  1503. X    }
  1504. X
  1505. X      }
  1506. X
  1507. X      /* implement FILL_OFF break option if required */
  1508. X      if( ok && multiline && fill_style(*style) == FILL_UNDEF )
  1509. X    Error(FATAL, &fpos(x), "missing %s operator or option", KW_BREAK);
  1510. X      if( ok && multiline && fill_style(*style) == FILL_OFF )
  1511. X      {    OBJECT last_acat = x, new_acat;
  1512. X    x = New(VCAT);
  1513. X    ReplaceNode(x, last_acat);
  1514. X    Link(x, last_acat);
  1515. X    for( link = Down(last_acat); link != last_acat; link = NextDown(link) )
  1516. X    { Child(g, link);
  1517. X      if( type(g) == GAP_OBJ && mode(gap(g)) != NO_MODE && vspace(g) > 0 )
  1518. X      { link = PrevDown(link);
  1519. X        MoveLink(NextDown(link), x, PARENT);
  1520. X        GapCopy(gap(g), line_gap(*style));
  1521. X        width(gap(g)) *= vspace(g);
  1522. X        new_acat = New(ACAT);
  1523. X        if( hspace(g) > 0 )
  1524. X        { z = MakeWord(WORD, STR_EMPTY, &fpos(g));
  1525. X          Link(new_acat, z);
  1526. X          z = New(GAP_OBJ);
  1527. X          hspace(z) = hspace(g);
  1528. X          vspace(z) = 0;
  1529. X          GapCopy(gap(z), space_gap(*style));
  1530. X          width(gap(z)) *= hspace(z);
  1531. X          Link(new_acat, z);
  1532. X        }
  1533. X        TransferLinks(NextDown(link), last_acat, new_acat);
  1534. X        StyleCopy(save_style(new_acat), *style);
  1535. X        Link(x, new_acat);
  1536. X        last_acat = new_acat;
  1537. X        link = last_acat;
  1538. X      }
  1539. X    }
  1540. X      }
  1541. X
  1542. X      ReplaceWithSplit(x, bthr, fthr);
  1543. X      break;
  1544. X
  1545. X
  1546. X    default:
  1547. X
  1548. X      Error(INTERN, &fpos(x), "Manifest: no case for type %s", Image(type(x)));
  1549. X      break;
  1550. X
  1551. X  } /* end <= ACAT */
  1552. X  else if( type(x) <= VCAT )  switch( type(x) )
  1553. X  {
  1554. X
  1555. X    case HCAT:
  1556. X    case VCAT:
  1557. X    
  1558. X      par = type(x) == HCAT ? ROW : COL;
  1559. X      perp = 1 - par;
  1560. X      link = Down(x);
  1561. X      gaplink = NextDown(link);
  1562. X      assert( link!=x && gaplink!=x, "Manifest/VCAT: less than two children!" );
  1563. X      Child(y, link);  Child(g, gaplink);
  1564. X
  1565. X      /* set bt and ft threads for y */
  1566. X      bt[perp] = bthr[perp];
  1567. X      ft[perp] = fthr[perp];
  1568. X      first_bt = bt[par] = bthr[par] ? New(THREAD) : nil;
  1569. X      ft[par] = join(gap(g)) ? New(THREAD) : nil;
  1570. X      still_backing = first_bt != nil;
  1571. X
  1572. X      /* manifest y and insinuate any cross-references */
  1573. X      y = Manifest(y, env, style, bt, ft, target, crs, ok, FALSE);
  1574. X      if( type(x) == VCAT && ok && *crs != nil )
  1575. X      {
  1576. X    debug1(DCR, D, "  insinuating %s", EchoObject(*crs));
  1577. X    TransferLinks(Down(*crs), *crs, link);
  1578. X    DisposeObject(*crs);
  1579. X    *crs = nil;
  1580. X      }
  1581. X
  1582. X      /* manifest the remaining children */
  1583. X      while( g != nil )
  1584. X      {    
  1585. X    /* manifest the gap object, store it in gap(g), add perp threads */
  1586. X    assert( type(g) == GAP_OBJ, "Manifest/VCAT: type(g) != GAP_OBJECT!" );
  1587. X    assert( Down(g) != g, "Manifest/VCAT: GAP_OBJ has no child!" );
  1588. X    Child(z, Down(g));
  1589. X    debug1(DOM, DD, "manifesting gap, style = %s", EchoStyle(style));
  1590. X    z = Manifest(z, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1591. X    debug1(DOM, DD, "replacing with tidy, style = %s", EchoStyle(style));
  1592. X    z = ReplaceWithTidy(z);
  1593. X    debug1(DOM, DD, "calling GetGap, style = %s", EchoStyle(style));
  1594. X    GetGap(z, style, &gap(g), &res_inc);
  1595. X    if( bt[perp] )  Link(bt[perp], g);
  1596. X    if( ft[perp] )  Link(ft[perp], g);
  1597. X
  1598. X    /* find the next child y, and following gap if any */
  1599. X    link = NextDown(gaplink);
  1600. X    assert( link != x, "Manifest/VCAT: GAP_OBJ is last child!" );
  1601. X    Child(y, link);
  1602. X    gaplink = NextDown(link);
  1603. X    if( gaplink == x )  g = nil;
  1604. X    else Child(g, gaplink);
  1605. X
  1606. X    /* set bt and ft threads for y */
  1607. X    last_ft = ft[par];
  1608. X    bt[par] = ft[par] ? New(THREAD) : nil;
  1609. X    ft[par] = g != nil ? join(gap(g)) ? New(THREAD) : nil
  1610. X               : fthr[par]    ? New(THREAD) : nil;
  1611. X
  1612. X    /* manifest y and insinuate any cross references */
  1613. X    y = Manifest(y, env, style, bt, ft, target, crs, ok, FALSE);
  1614. X    if( type(x) == VCAT && ok && *crs != nil )
  1615. X        {
  1616. X      debug1(DCR, D, "  insinuating %s", EchoObject(*crs));
  1617. X      TransferLinks(Down(*crs), *crs, link);
  1618. X      DisposeObject(*crs);
  1619. X      *crs = nil;
  1620. X        }
  1621. X
  1622. X    if( bt[par] )    /* then thread lists last_ft and bt[par] must merge */
  1623. X    { OBJECT llink, rlink, lthread, rthread;  BOOLEAN goes_through;
  1624. X      assert( Down(bt[par]) != bt[par], "Manifest: bt[par] no children!" );
  1625. X      assert( last_ft!=nil && Down(last_ft)!=last_ft, "Manifest:last_ft!" );
  1626. X
  1627. X      /* check whether marks run right through y in par direction */
  1628. X      goes_through = FALSE;
  1629. X      if( ft[par] )
  1630. X      { assert( Down(ft[par]) != ft[par], "Manifest: ft[par] child!" );
  1631. X        Child(lthread, LastDown(bt[par]));
  1632. X        Child(rthread, LastDown(ft[par]));
  1633. X        goes_through = lthread == rthread;
  1634. X      }
  1635. X
  1636. X      /* merge the thread lists */
  1637. X      llink = Down(last_ft);  rlink = Down(bt[par]);
  1638. X      while( llink != last_ft && rlink != bt[par] )
  1639. X      { Child(lthread, llink);
  1640. X        Child(rthread, rlink);
  1641. X        assert( lthread != rthread, "Manifest: lthread == rthread!" );
  1642. X        MergeNode(lthread, rthread);
  1643. X        llink = NextDown(llink);
  1644. X        rlink = NextDown(rlink);
  1645. X      }
  1646. X
  1647. X      /* attach leftover back threads to first_bt if required */
  1648. X      if( rlink != bt[par] )
  1649. X      { 
  1650. X        if( still_backing )  TransferLinks(rlink, bt[par], first_bt);
  1651. X      }
  1652. X      DisposeObject(bt[par]);
  1653. X
  1654. X      /* attach leftover forward threads to ft[par] if required */
  1655. X      if( llink != last_ft )
  1656. X      {
  1657. X        if( goes_through )  TransferLinks(llink, last_ft, ft[par]);
  1658. X      }
  1659. X      DisposeObject(last_ft);
  1660. X
  1661. X      if( !goes_through )  still_backing = FALSE;
  1662. X
  1663. X    }
  1664. X    else still_backing = FALSE;
  1665. X
  1666. X      } /* end while */
  1667. X
  1668. X      /* export par threads */
  1669. X      if( fthr[par] )  MergeNode(fthr[par], ft[par]);
  1670. X      if( bthr[par] )  MergeNode(bthr[par], first_bt);
  1671. X      break;
  1672. X
  1673. X
  1674. X    default:
  1675. X
  1676. X      Error(INTERN, &fpos(x), "Manifest: no case for type %s", Image(type(x)));
  1677. X      break;
  1678. X
  1679. X  }
  1680. X  else switch( type(x) )
  1681. X  {
  1682. X
  1683. X    case WIDE:
  1684. X    case HIGH:
  1685. X    
  1686. X      Child(y, Down(x));
  1687. X      y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1688. X      y = ReplaceWithTidy(y);
  1689. X      GetGap(y, style, &res_gap, &res_inc);
  1690. X      if( res_inc != GAP_ABS || mode(res_gap) != EDGE_MODE ||
  1691. X    units(res_gap) != FIXED_UNIT )
  1692. X      {    Error(WARN, &fpos(y), "replacing invalid left parameter of %s by 2i",
  1693. X            Image(type(x)) );
  1694. X    units(res_gap) = FIXED_UNIT;
  1695. X    width(res_gap) = 2*IN;
  1696. X      }
  1697. X      SetConstraint(constraint(x), MAX_LEN, width(res_gap), MAX_LEN);
  1698. X      DisposeChild(Down(x));
  1699. X      /* NB NO BREAK! */
  1700. X
  1701. X
  1702. X    case HCONTRACT:
  1703. X    case VCONTRACT:
  1704. X    case HEXPAND:
  1705. X    case VEXPAND:
  1706. X    case PADJUST:
  1707. X    case HADJUST:
  1708. X    case VADJUST:
  1709. X    case ONE_COL:
  1710. X    case ONE_ROW:
  1711. X    
  1712. X      par = (type(x)==ONE_COL || type(x)==HEXPAND || type(x) == HCONTRACT ||
  1713. X         type(x)==PADJUST || type(x)==HADJUST || type(x)==WIDE) ? COL : ROW;
  1714. X      Child(y, Down(x));
  1715. X
  1716. X      /* manifest the child, propagating perp threads and suppressing pars */
  1717. X      bt[par] = ft[par] = nil;
  1718. X      bt[1-par] = bthr[1-par];  ft[1-par] = fthr[1-par];
  1719. X      y = Manifest(y, env, style, bt, ft, target, crs, ok, FALSE);
  1720. X
  1721. X      /* replace with split object if par threads needed */
  1722. X      bt[par] = bthr[par];  ft[par] = fthr[par];
  1723. X      bt[1-par] = ft[1-par] = nil;
  1724. X      ReplaceWithSplit(x, bt, ft);
  1725. X      break;
  1726. X
  1727. X
  1728. X    case ROTATE:
  1729. X
  1730. X      Child(y, Down(x));
  1731. X      y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1732. X      y = ReplaceWithTidy(y);
  1733. X      GetGap(y, style, &res_gap, &res_inc);
  1734. X      if( res_inc != GAP_ABS || mode(res_gap) != EDGE_MODE ||
  1735. X        units(res_gap) != DEG_UNIT )
  1736. X      {    Error(WARN, &fpos(y), "replacing invalid left parameter of %s by 0d",
  1737. X            Image(type(x)) );
  1738. X    units(res_gap) = DEG_UNIT;
  1739. X    width(res_gap) = 0;
  1740. X      }
  1741. X      sparec(constraint(x)) = width(res_gap);
  1742. X      DisposeChild(Down(x));
  1743. X      Child(y, Down(x));
  1744. X      y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE);
  1745. X      ReplaceWithSplit(x, bthr, fthr);
  1746. X      break;
  1747. X
  1748. X
  1749. X    case HSCALE:
  1750. X    case VSCALE:
  1751. X
  1752. X      Child(y, Down(x));
  1753. X      y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE);
  1754. X      ReplaceWithSplit(x, bthr, fthr);
  1755. X      break;
  1756. X
  1757. X
  1758. X    case SCALE:
  1759. X
  1760. X      Child(y, Down(x));
  1761. X      y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1762. X      y = ReplaceWithTidy(y);
  1763. X      if( type(y) != ACAT )
  1764. X      { scale_factor = GetScaleFactor(y, "scale factor");
  1765. X        bc(constraint(x)) = fc(constraint(x)) = scale_factor * SF;
  1766. X      }
  1767. X      else
  1768. X      {
  1769. X    /* get horizontal scale factor */
  1770. X    Child(z, Down(y));
  1771. X    scale_factor = GetScaleFactor(z, "horizontal scale factor");
  1772. X        bc(constraint(x)) = scale_factor * SF;
  1773. X
  1774. X    /* get vertical scale factor */
  1775. X    Child(z, LastDown(y));
  1776. X    scale_factor = GetScaleFactor(z, "vertical scale factor");
  1777. X        fc(constraint(x)) = scale_factor * SF;
  1778. X      }
  1779. X      DisposeChild(Down(x));
  1780. X      Child(y, LastDown(x));
  1781. X      y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE);
  1782. X      ReplaceWithSplit(x, bthr, fthr);
  1783. X      break;
  1784. X
  1785. X
  1786. X    case YIELD:
  1787. X
  1788. X      Error(FATAL, &fpos(x), "%s outside of %s", KW_YIELD, KW_CASE);
  1789. X      break;
  1790. X
  1791. X
  1792. X    case CASE:
  1793. X
  1794. X      /* make sure left parameter (the tag) is in order */
  1795. X      debug0(DOM, DD, "  manifesting CASE now");
  1796. X      Child(tag, Down(x));
  1797. X      debug1(DOM, DD, "  manifesting CASE tag %s now", EchoObject(tag));
  1798. X      tag = Manifest(tag, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1799. X      tag = ReplaceWithTidy(tag);
  1800. X
  1801. X      /* make sure the right parameter is an ACAT */
  1802. X      Child(y, LastDown(x));
  1803. X      if( type(y) == YIELD )
  1804. X      {    z = New(ACAT);
  1805. X    MoveLink(Up(y), z, PARENT);
  1806. X    Link(x, z);
  1807. X    y = z;
  1808. X      }
  1809. X      if( type(y) != ACAT )
  1810. X      {    Error(WARN, &fpos(y), "%s deleted: right parameter is malformed",
  1811. X      KW_CASE);
  1812. X    errorcase();
  1813. X      }
  1814. X
  1815. X      /* hunt through right parameter for res, the selected case */
  1816. X      res = nil;  firsttag = nil;
  1817. X      for( ylink = Down(y); ylink != y && res == nil; ylink = NextDown(ylink) )
  1818. X      {    Child(yield, ylink);
  1819. X    if( type(yield) == GAP_OBJ )  continue;
  1820. X    if( type(yield) != YIELD )
  1821. X    { Error(WARN, &fpos(yield), "%s contains non-%s", KW_CASE, KW_YIELD);
  1822. X      break;
  1823. X    }
  1824. X    Child(ytag, Down(yield));
  1825. X    ytag = Manifest(ytag, env, style, nbt, nft, &ntarget, crs, FALSE,FALSE);
  1826. X    ytag = ReplaceWithTidy(ytag);
  1827. X    if( is_word(type(ytag)) )
  1828. X    { if( firsttag == nil )
  1829. X      { firsttag = ytag;
  1830. X        Child(firstres, LastDown(yield));
  1831. X      }
  1832. X      if( (is_word(type(tag)) && StringEqual(string(ytag), string(tag))) ||
  1833. X          StringEqual(string(ytag), STR_ELSE)  )
  1834. X      { Child(res, LastDown(yield));
  1835. X        break;
  1836. X      }
  1837. X    }
  1838. X    else if( type(ytag) == ACAT )
  1839. X    { z = ytag;
  1840. X      for( zlink = Down(z);  zlink != z;  zlink = NextDown(zlink) )
  1841. X      { Child(ytag, zlink);
  1842. X        if( type(ytag) == GAP_OBJ )  continue;
  1843. X        if( !is_word(type(ytag)) )
  1844. X        { Error(WARN, &fpos(ytag), "error in left parameter of %s",
  1845. X        KW_YIELD);
  1846. X          break;
  1847. X        }
  1848. X        if( firsttag == nil )
  1849. X        { firsttag = ytag;
  1850. X          Child(firstres, LastDown(yield));
  1851. X        }
  1852. X        if( (is_word(type(tag)) && StringEqual(string(ytag), string(tag)))
  1853. X            || StringEqual(string(ytag), STR_ELSE) )
  1854. X        { Child(res, LastDown(yield));
  1855. X          break;
  1856. X        }
  1857. X      }
  1858. X    }
  1859. X    else Error(WARN,&fpos(ytag), "error in left parameter of %s", KW_YIELD);
  1860. X      }
  1861. X      if( res == nil )
  1862. X      { if( firsttag != nil )
  1863. X    { Error(WARN, &fpos(tag), "replacing unkown %s option %s by %s",
  1864. X        KW_CASE, string(tag), string(firsttag));
  1865. X      res = firstres;
  1866. X    }
  1867. X    else
  1868. X    { Error(WARN, &fpos(tag), "%s deleted: selection %s unknown",
  1869. X        KW_CASE, string(tag));
  1870. X      errorcase();
  1871. X    }
  1872. X      }
  1873. X
  1874. X      /* now manifest the result and replace x with it */
  1875. X      DeleteLink(Up(res));
  1876. X      ReplaceNode(res, x);
  1877. X      DisposeObject(x);
  1878. X      x = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE);
  1879. X      break;
  1880. X
  1881. X
  1882. X    case XCHAR:
  1883. X
  1884. X      Child(y, Down(x));
  1885. X      y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1886. X      y = ReplaceWithTidy(y);
  1887. X      if( !is_word(type(y)) )
  1888. X      {    Error(WARN, &fpos(x), "%s dropped: parameter is not a simple word",
  1889. X      KW_XCHAR);
  1890. X    res = MakeWord(WORD, STR_EMPTY, &fpos(x));
  1891. X      }
  1892. X      else if( word_font(y) == 0 )
  1893. X      {    Error(WARN, &fpos(x), "%s dropped: no current font at this point",
  1894. X      KW_XCHAR);
  1895. X    res = MakeWord(WORD, STR_EMPTY, &fpos(x));
  1896. X      }
  1897. X      else if( (ch=EvRetrieve(string(y), FontEncoding(word_font(y)))) == '\0' )
  1898. X      {    type(y) = QWORD;
  1899. X    Error(WARN, &fpos(x), "%s dropped: character %s unknown in font %s",
  1900. X      KW_XCHAR, StringQuotedWord(y),
  1901. X      FontFamilyAndFace(word_font(y)));
  1902. X    res = MakeWord(WORD, STR_EMPTY, &fpos(x));
  1903. X      }
  1904. X      else
  1905. X      {    res = MakeWord(QWORD, STR_SPACE, &fpos(x));
  1906. X    string(res)[0] = ch;
  1907. X      }
  1908. X      ReplaceNode(res, x);
  1909. X      DisposeObject(x);
  1910. X      x = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE);
  1911. X      break;
  1912. X
  1913. X
  1914. X    case FONT:
  1915. X    case SPACE:
  1916. X    case BREAK:
  1917. X    
  1918. X      assert( Down(x) != x && NextDown(Down(x)) != x, "Manifest: FONT!" );
  1919. X      StyleCopy(new_style, *style);
  1920. X      Child(y, Down(x));
  1921. X      y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  1922. X      y = ReplaceWithTidy(y);
  1923. X      if( type(x) == FONT )       FontChange(&new_style, y);
  1924. X      else if( type(x) == SPACE ) SpaceChange(&new_style, y);
  1925. X      else              BreakChange(&new_style, y);
  1926. X      DisposeChild(Down(x));
  1927. X      Child(y, Down(x));
  1928. X      y = Manifest(y, env, &new_style, bthr, fthr, target, crs, ok, FALSE);
  1929. X      DeleteLink(Down(x));
  1930. X      MergeNode(y, x);  x = y;
  1931. X      break;
  1932. X
  1933. X
  1934. X    case NEXT:
  1935. X
  1936. X      assert( Down(x) != x, "Manifest/NEXT: Down(x) == x!" );
  1937. X      Child(y, Down(x));
  1938. X      debug1(DCS, D, "  Manifesting Next( %s, 1 )", EchoObject(y));
  1939. X      y = Manifest(y, env, style, bthr, fthr, target, crs, FALSE, FALSE);
  1940. X      debug1(DCS, D, "  calling Next( %s, 1 )", EchoObject(y));
  1941. X      done = FALSE;
  1942. X      y = Next(y, 1, &done);
  1943. X      debug2(DCS, D, "  Next(done = %s) returning %s",
  1944. X            bool(done), EchoObject(y));
  1945. X      DeleteLink(Down(x));
  1946. X      MergeNode(y, x);  x = y;
  1947. X      break;
  1948. X
  1949. X
  1950. X    case OPEN:
  1951. X
  1952. X      Child(y, Down(x));
  1953. X      Child(res, LastDown(x));
  1954. X      if( type(y) == CLOSURE )
  1955. X      { AttachEnv(env, y);
  1956. X    StyleCopy(save_style(y), *style);
  1957. X    debug0(DCR, DD, "calling SetEnv from Manifest (b)");
  1958. X    res_env = SetEnv(y, nil);
  1959. X    hold_env = New(ACAT);  Link(hold_env, res_env);
  1960. X    res = Manifest(res, res_env, style, bthr, fthr, target, crs, ok, FALSE);
  1961. X    DisposeObject(hold_env);
  1962. X      }
  1963. X      else if( type(y) == CROSS )
  1964. X      {    debug0(DCR, DD, "  calling CrossExpand from Manifest/OPEN");
  1965. X    y = CrossExpand(y, env, style, TRUE, crs, &res_env);
  1966. X    AttachEnv(res_env, y);
  1967. X    debug0(DCR, DD, "calling SetEnv from Manifest (c)");
  1968. X    res_env = SetEnv(y, env);
  1969. X    hold_env = New(ACAT);  Link(hold_env, res_env);
  1970. X    res = Manifest(res, res_env, style, bthr, fthr, target, crs, ok, FALSE);
  1971. X    DisposeObject(hold_env);
  1972. X      }
  1973. X      else
  1974. X      {    Error(WARN, &fpos(y), "invalid left parameter of %s", KW_OPEN);
  1975. X    res = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE);
  1976. X      }
  1977. X      ReplaceNode(res, x);
  1978. X      DisposeObject(x);
  1979. X      x = res;
  1980. X      break;
  1981. X
  1982. X
  1983. X    case TAGGED:
  1984. X
  1985. X      /* make sure first argument is a cross-reference */
  1986. X      assert( Down(x) != x && NextDown(Down(x)) != x &&
  1987. X    NextDown(NextDown(Down(x))) == x, "Manifest TAGGED: children!" );
  1988. X      Child(y, Down(x));
  1989. X      if( type(y) != CROSS )
  1990. X      {    Error(WARN, &fpos(y), "left parameter of %s is not a cross-reference",
  1991. X      KW_TAGGED);
  1992. X    errorcase();
  1993. X      }
  1994. X
  1995. X      /* make sure the arguments of the cross-reference are OK */
  1996. X      Child(z, Down(y));
  1997. X      if( type(z) != CLOSURE )
  1998. X      {    Error(WARN,&fpos(y),"left parameter of %s must be a symbol", KW_TAGGED);
  1999. X    errorcase();
  2000. X      }
  2001. X      if( !has_tag(actual(z)) )
  2002. X      {    Error(WARN, &fpos(z), "symbol %s illegal with %s since it has no %s",
  2003. X      SymName(actual(z)), KW_TAGGED, KW_TAG);
  2004. X    errorcase();
  2005. X      }
  2006. X      Child(z, NextDown(Down(y)));
  2007. X      z = Manifest(z, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  2008. X      z = ReplaceWithTidy(z);
  2009. X      if( is_word(type(z)) && StringEqual(string(z), KW_PRECEDING) )
  2010. X    cross_type(y) = CROSS_PREC;
  2011. X      else if( is_word(type(z)) && StringEqual(string(z), KW_FOLLOWING) )
  2012. X    cross_type(y) = CROSS_FOLL;
  2013. X      else
  2014. X      {    Error(WARN, &fpos(z), "%s of left parameter of %s must be %s or %s",
  2015. X      KW_TAG, KW_TAGGED, KW_PRECEDING, KW_FOLLOWING);
  2016. X    errorcase();
  2017. X      }
  2018. X
  2019. X      /* make sure second argument (the new key) is ok */
  2020. X      Child(tag, LastDown(x));
  2021. X      tag = Manifest(tag, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  2022. X      tag = ReplaceWithTidy(tag);
  2023. X      if( !is_word(type(tag)) )
  2024. X      {    Error(WARN, &fpos(tag), "right parameter of %s must be a simple word",
  2025. X      KW_TAGGED);
  2026. X    ifdebug(DOM, D, DebugObject(tag));
  2027. X    errorcase();
  2028. X      }
  2029. X
  2030. X      /* assemble insinuated cross reference which replaces x */
  2031. X      ReplaceNode(tag, z);
  2032. X      DisposeObject(z);
  2033. X      ReplaceNode(y, x);
  2034. X      DisposeObject(x);
  2035. X      x = y;
  2036. X      ReplaceWithSplit(x, bthr, fthr);
  2037. X      break;
  2038. X
  2039. X
  2040. X    case GRAPHIC:
  2041. X
  2042. X      debug1(DRS, DD, "  graphic style in Manifest = %s", EchoStyle(style));
  2043. X      Child(y, LastDown(x));
  2044. X      y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE);
  2045. X      StyleCopy(save_style(x), *style);
  2046. X      Child(y, Down(x));
  2047. X      y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  2048. X      ReplaceWithSplit(x, bthr, fthr);
  2049. X      break;
  2050. X    
  2051. X
  2052. X    case INCGRAPHIC:
  2053. X    case SINCGRAPHIC:
  2054. X
  2055. X      Child(y, Down(x));
  2056. X      y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE);
  2057. X      y = ReplaceWithTidy(y);
  2058. X      if( !is_word(type(y)) )
  2059. X      { Error(WARN, &fpos(y), "%s deleted: invalid right parameter",
  2060. X      type(x) == INCGRAPHIC ? KW_INCGRAPHIC : KW_SINCGRAPHIC);
  2061. X    errorcase();
  2062. X      }
  2063. X      ReplaceWithSplit(x, bthr, fthr);
  2064. X      break;
  2065. X    
  2066. X
  2067. X    default:
  2068. X
  2069. X      Error(INTERN, &fpos(x), "Manifest: no case for type %s", Image(type(x)));
  2070. X      break;
  2071. X
  2072. X  } /* end switch */
  2073. X
  2074. X  debug2(DOM, D, "]Manifest returning %s %s", Image(type(x)), EchoObject(x));
  2075. X  debug1(DOM, DD, "  at exit, style = %s", EchoStyle(style));
  2076. X  debug1(DOM, DDD, "up:    ", EchoObject(bthr[COL]));
  2077. X  debug1(DOM, DDD, "down:  ", EchoObject(fthr[COL]));
  2078. X  debug1(DOM, DDD, "left:  ", EchoObject(bthr[ROW]));
  2079. X  debug1(DOM, DDD, "right: ", EchoObject(fthr[ROW]));
  2080. X  return x;
  2081. X} /* end Manifest */
  2082. END_OF_FILE
  2083.   if test 36924 -ne `wc -c <'z08.c'`; then
  2084.     echo shar: \"'z08.c'\" unpacked with wrong size!
  2085.   fi
  2086.   # end of 'z08.c'
  2087. fi
  2088. echo shar: End of archive 8 \(of 35\).
  2089. cp /dev/null ark8isdone
  2090. MISSING=""
  2091. 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 31 32 33 34 35 ; do
  2092.     if test ! -f ark${I}isdone ; then
  2093.     MISSING="${MISSING} ${I}"
  2094.     fi
  2095. done
  2096. if test "${MISSING}" = "" ; then
  2097.     echo You have unpacked all 35 archives.
  2098.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2099. else
  2100.     echo You still must unpack the following archives:
  2101.     echo "        " ${MISSING}
  2102. fi
  2103. exit 0
  2104. exit 0 # Just in case...
  2105.