in MultiSource/Benchmarks/MiBench/consumer-typeset/z08.c [881:2068]
OBJECT Manifest(OBJECT x, OBJECT env, STYLE *style, OBJECT bthr[2],
OBJECT fthr[2], OBJECT *target, OBJECT *crs, BOOLEAN ok, BOOLEAN need_expand,
OBJECT *enclose, BOOLEAN fcr)
{ OBJECT bt[2], ft[2], y, link, gaplink, g; register FULL_CHAR *p;
OBJECT res, res_env, res_env2, hold_env, hold_env2, z, prev;
OBJECT link1, link2, x1, x2, y1, y2;
int par, num1, num2; GAP res_gap; unsigned res_inc; STYLE new_style;
BOOLEAN done, multiline; FULL_CHAR ch; float scale_factor;
static int depth = 0;
#if DEBUG_ON
static unsigned int debug_type[MAX_DEPTH];
static OBJECT debug_actual[MAX_DEPTH];
static int debug_lnum[MAX_DEPTH];
BOOLEAN eee = (*enclose != nilobj);
debug_type[depth] = type(x);
debug_lnum[depth] = line_num(fpos(x));
if( type(x) == CLOSURE ) debug_actual[depth] = actual(x);
depth++;
if( depth == MAX_DEPTH )
{ Error(8, 20, "maximum depth of symbol expansion (%d) reached",
WARN, &fpos(x), MAX_DEPTH);
Error(8, 21, "the symbols currently being expanded are:", WARN, &fpos(x));
while( --depth >= 0 )
{
Error(8, 22, "at %d: %d %s %s", WARN, &fpos(x), depth, debug_lnum[depth],
Image(debug_type[depth]), debug_type[depth] == CLOSURE ?
FullSymName(debug_actual[depth], AsciiToFull(".")) : STR_EMPTY);
}
Error(8, 23, "exiting now", FATAL, &fpos(x));
}
#else
depth++;
if( depth == MAX_DEPTH )
{
Error(8, 40, "maximum depth of symbol expansion (%d) reached",
FATAL, &fpos(x), MAX_DEPTH);
}
#endif
debug2(DOM, DD, "[Manifest(%s %s )", Image(type(x)), EchoObject(x));
debug1(DOM, DD, " environment: %s", EchoObject(env));
debug6(DOM, DD, " style: %s; target: %s; threads: %s%s%s%s",
EchoStyle(style), SymName(*target),
bthr[COLM] ? " up" : "", fthr[COLM] ? " down" : "",
bthr[ROWM] ? " left" : "", fthr[ROWM] ? " right" : "");
debugcond2(DHY, DD, eee, "[ Manifest(%s, *enclose = %s)",
EchoObject(x), EchoObject(*enclose));
switch( type(x) )
{
case ENV_OBJ:
debug0(DHY, DD, "[Manifest env_obj:");
ifdebug(DHY, DD, DebugObject(x));
Child(y, Down(x));
Child(res_env, NextDown(Down(x)));
assert( type(res_env) == ENV, "Manifest/ENV_OBJ: res_env!");
y = Manifest(y, res_env, style, bthr, fthr, target, crs, ok, TRUE, enclose, fcr);
/* we always expand children of ENV_OBJ (need_expand == TRUE) */
ReplaceNode(y, x);
DisposeObject(x);
x = y;
debug1(DHY, DD, "]Manifest env_obj returning %s", EchoObject(x));
break;
case CLOSURE:
x = ManifestCl(x, env, style, bthr, fthr, target, crs, ok, need_expand, enclose, fcr);
break;
case PAGE_LABEL:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, TRUE);
ReplaceWithSplit(x, bthr, fthr);
break;
case NULL_CLOS:
StyleCopy(save_style(x), *style);
ReplaceWithSplit(x, bthr, fthr);
break;
case CROSS:
case FORCE_CROSS:
assert( Down(x) != x && LastDown(x) != Down(x), "Manifest: CROSS child!");
if( !fcr ) /* stop if fcr, i.e. if purpose was to find a cross-reference */
{
debug0(DCR, DD, " calling CrossExpand from Manifest/CROSS");
Child(y, Down(x));
if( type(y) == CLOSURE )
{
/* *** want cross ref now always, not only if ok
x = CrossExpand(x, env, style, ok, crs, &res_env);
*** */
x = CrossExpand(x, env, style, crs, &res_env);
assert( type(x) == CLOSURE, "Manifest/CROSS: type(x)!" );
New(hold_env, ACAT); Link(hold_env, res_env);
/* expand here (calling Manifest immediately makes unwanted cr) */
debug0(DCE, DD, " calling ClosureExpand from Manifest/CROSS");
x = ClosureExpand(x, res_env, FALSE, crs, &res_env2);
New(hold_env2, ACAT); Link(hold_env2, res_env2);
x = Manifest(x, res_env2, style, bthr, fthr, target, crs, ok, TRUE, enclose, fcr);
DisposeObject(hold_env);
DisposeObject(hold_env2);
}
else
{ y = MakeWord(WORD, STR_EMPTY, &fpos(x));
ReplaceNode(y, x);
DisposeObject(x);
x = Manifest(y, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
}
}
break;
case WORD:
case QWORD:
if( !ok || *crs == nilobj )
{ word_font(x) = font(*style);
word_colour(x) = colour(*style);
word_outline(x) = outline(*style);
word_language(x) = language(*style);
word_hyph(x) = hyph_style(*style) == HYPH_ON;
debug3(DOM, DDD, " manfifest/WORD underline() := %s for %s %s",
"UNDER_OFF", Image(type(x)), EchoObject(x));
if( small_caps(*style) && ok ) x = MapSmallCaps(x, style);
underline(x) = UNDER_OFF;
ReplaceWithSplit(x, bthr, fthr);
break;
}
New(y, ACAT);
FposCopy(fpos(y), fpos(x));
ReplaceNode(y, x);
Link(y, x); x = y;
/* NB NO BREAK! */
case ACAT:
StyleCopy(save_style(x), *style);
adjust_cat(x) = padjust(*style);
StyleCopy(new_style, *style);
padjust(new_style) = FALSE;
assert(Down(x) != x, "Manifest: ACAT!" );
link = Down(x); Child(y, link);
assert( type(y) != GAP_OBJ, "Manifest ACAT: GAP_OBJ is first!" );
multiline = FALSE;
/* manifest first child and insert any cross references */
if( is_word(type(y)) )
{ word_font(y) = font(*style);
word_colour(y) = colour(*style);
word_outline(y) = outline(*style);
word_language(y) = language(*style);
word_hyph(y) = hyph_style(*style) == HYPH_ON;
if( small_caps(*style) && ok ) y = MapSmallCaps(y, style);
}
else y = Manifest(y, env, &new_style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
debug3(DOM, DDD, " manfifest/ACAT1 underline() := %s for %s %s",
"UNDER_OFF", Image(type(y)), EchoObject(y));
underline(y) = UNDER_OFF;
/* ??? if( is_word(type(y)) ) */
if( ok && *crs != nilobj )
{
debug1(DCR, DD, " insinuating %s", EchoObject(*crs));
TransferLinks(Down(*crs), *crs, link);
DisposeObject(*crs);
*crs = nilobj;
}
prev = y;
/* manifest subsequent gaps and children */
for( gaplink = Down(link); gaplink != x; gaplink = NextDown(link) )
{
Child(g, gaplink);
assert( type(g) == GAP_OBJ, "Manifest ACAT: no GAP_OBJ!" );
debug3(DOM, DDD, " manfifest/ACAT2 underline() := %s for %s %s",
"UNDER_OFF", Image(type(g)), EchoObject(g));
underline(g) = UNDER_OFF;
link = NextDown(gaplink);
assert( link != x, "Manifest ACAT: GAP_OBJ is last!" );
Child(y, link);
assert( type(y) != GAP_OBJ, "Manifest ACAT: double GAP_OBJ!" );
/* manifest the next child */
debug1(DOM, DD, " in ACAT (3), style = %s", EchoStyle(style));
if( is_word(type(y)) )
{ word_font(y) = font(*style);
word_colour(y) = colour(*style);
word_outline(y) = outline(*style);
word_language(y) = language(*style);
word_hyph(y) = hyph_style(*style) == HYPH_ON;
if( small_caps(*style) && ok ) y = MapSmallCaps(y, style);
}
else y = Manifest(y, env, &new_style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
debug3(DOM, DDD, " manifest/ACAT3 underline() := %s for %s %s",
"UNDER_OFF", Image(type(y)), EchoObject(y));
underline(y) = UNDER_OFF;
/* manifest the gap object */
if( Down(g) != g )
{
/* explicit & operator whose value is the child of g */
Child(z, Down(g));
z = Manifest(z, env, &new_style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
z = ReplaceWithTidy(z, FALSE);
GetGap(z, style, &gap(g), &res_inc);
vspace(g) = hspace(g) = 0;
}
else
{
/* implicit & operator */
GapCopy(gap(g), space_gap(*style));
switch( space_style(*style) )
{
case SPACE_LOUT:
/* usual Lout spacing, the number of white space characters */
width(gap(g)) = width(gap(g)) * (vspace(g) + hspace(g));
break;
case SPACE_COMPRESS:
/* either zero or one space */
if( vspace(g) + hspace(g) == 0 )
{ width(gap(g)) = 0;
}
else
{ /* else width is like one space, so OK as is */
}
break;
case SPACE_SEPARATE:
/* exactly one space always, so do nothing further */
break;
case SPACE_TROFF:
/* Lout spacing plus one extra space for sentence end at eoln */
width(gap(g)) = width(gap(g)) * (vspace(g) + hspace(g));
debugcond2(DLS, DD, vspace(g) > 0, " prev = %s %s",
Image(type(prev)), EchoObject(prev));
if( vspace(g) > 0 )
{
/* set z to the preceding object; may need to search ACATs! */
z = prev;
while( type(z) == ACAT
|| type(z) == ONE_COL || type(z) == ONE_ROW
|| type(z) == HCONTRACT || type(z) == VCONTRACT )
{ Child(z, LastDown(z));
}
/* if preceding object is a word, check for end sentence */
if( is_word(type(z)) )
{
for( p = string(z); *p != '\0'; p++ );
debug4(DLS, DD, " prev = %s, last = %c, LSE = %s, LWES = %s",
EchoObject(z), *(p-1), bool(LanguageSentenceEnds[*(p-1)]),
bool(LanguageWordEndsSentence(z, FALSE)));
if( p != string(z) && LanguageSentenceEnds[*(p-1)]
&& LanguageWordEndsSentence(z, FALSE) )
width(gap(g)) += width(space_gap(*style));
}
}
break;
case SPACE_TEX:
if( vspace(g) + hspace(g) == 0 )
{
/* zero spaces gives zero result, as for compress above */
width(gap(g)) = 0;
}
else
{
/* set z to the preceding object; may need to search ACATs! */
z = prev;
while( type(z) == ACAT
|| type(z) == ONE_COL || type(z) == ONE_ROW
|| type(z) == HCONTRACT || type(z) == VCONTRACT )
{ Child(z, LastDown(z));
}
/* one extra space if preceding is word ending sentence */
if( is_word(type(z)) )
{
for( p = string(z); *p != '\0'; p++ );
debug4(DLS, DD, " prev = %s, last = %c, LSE = %s, LWES = %s",
EchoObject(z), *(p-1), bool(LanguageSentenceEnds[*(p-1)]),
bool(LanguageWordEndsSentence(z, TRUE)));
if( p != string(z) && LanguageSentenceEnds[*(p-1)]
&& LanguageWordEndsSentence(z, TRUE) )
width(gap(g)) += width(space_gap(*style));
}
}
break;
default:
assert(FALSE, "Manifest: unexpected space_style!");
break;
}
nobreak(gap(g)) = (width(gap(g)) == 0);
if( line_breaker(g) && is_definite(type(y)) ) multiline = TRUE;
}
debug1(DOM, DD, " in ACAT, gap = %s", EchoLength(width(gap(g))));
/* compress adjacent juxtaposed words of equal font, etc. */
if( is_word(type(y)) && width(gap(g)) == 0 && nobreak(gap(g)) &&
vspace(g)+hspace(g)==0 &&
units(gap(g)) == FIXED_UNIT && mode(gap(g)) == EDGE_MODE &&
prev != nilobj && is_word(type(prev)) && !mark(gap(g)) &&
word_font(prev) == word_font(y) &&
word_colour(prev) == word_colour(y) &&
word_outline(prev) == word_outline(y) &&
word_language(prev) == word_language(y) )
/* no need to compare underline() since both are false */
{ unsigned typ;
assert( underline(prev) == UNDER_OFF, "Manifest/ACAT: underline(prev)!" );
assert( underline(y) == UNDER_OFF, "Manifest/ACAT: underline(y)!" );
if( StringLength(string(prev))+StringLength(string(y)) >= MAX_BUFF )
Error(8, 24, "word %s%s is too long",
FATAL, &fpos(prev), string(prev), string(y));
z = y;
typ = type(prev) == QWORD || type(y) == QWORD ? QWORD : WORD;
y = MakeWordTwo(typ, string(prev), string(y), &fpos(prev));
word_font(y) = word_font(prev);
word_colour(y) = word_colour(prev);
word_outline(y) = word_outline(prev);
word_language(y) = word_language(prev);
word_hyph(y) = word_hyph(prev);
underline(y) = UNDER_OFF;
debug3(DOM, DDD, " manifest/ACAT4 underline() := %s for %s %s",
"UNDER_OFF", Image(type(y)), EchoObject(y));
MoveLink(link, y, CHILD);
DisposeObject(z);
DisposeChild(Up(prev));
DisposeChild(gaplink);
}
prev = y;
/* insinuate any cross-references */
if( ok && *crs != nilobj )
{
debug1(DCR, DD, " insinuating %s", EchoObject(*crs));
TransferLinks(Down(*crs), *crs, link);
DisposeObject(*crs);
*crs = nilobj;
}
}
/* implement FILL_OFF break option if required */
/* *** this has been moved now to MinSize, z12.c *** */
/* ***
if( ok && multiline && fill_style(*style) == FILL_UNDEF )
Error(8, 25, "missing %s symbol or option", FATAL, &fpos(x), KW_BREAK);
if( ok && multiline && fill_style(*style) == FILL_OFF )
{ OBJECT prev_acat, new_acat; BOOLEAN jn;
%* compress any ACAT children of ACAT x *%
for( link = x; NextDown(link) != x; link = NextDown(link) )
{ Child(y, NextDown(link));
if( type(y) == ACAT )
{ TransferLinks(Down(y), y, NextDown(link));
DisposeChild(Up(y));
link = PrevDown(link);
}
}
%* do line breaks now *%
prev_acat = x;
New(x, VCAT);
adjust_cat(x) = FALSE;
ReplaceNode(x, prev_acat);
Link(x, prev_acat);
FirstDefinite(prev_acat, link, y, jn);
if( link != prev_acat )
{
NextDefiniteWithGap(prev_acat, link, y, g, jn);
while( link != prev_acat )
{
if( mode(gap(g)) != NO_MODE && line_breaker(g) )
{ OBJECT glink = PrevDown(Up(g));
debug2(DOM, DD, "lines gap just before definite %s at %s",
Image(type(y)), EchoFilePos(&fpos(y)));
MoveLink(NextDown(glink), x, PARENT);
GapCopy(gap(g), line_gap(*style));
width(gap(g)) *= find_max(1, vspace(g));
New(new_acat, ACAT);
adjust_cat(new_acat) = padjust(*style);
FposCopy(fpos(new_acat), fpos(g));
if( hspace(g) > 0 )
{ z = MakeWord(WORD, STR_EMPTY, &fpos(g));
word_font(z) = font(*style);
word_colour(z) = colour(*style);
word_outline(z) = outline(*style);
word_language(z) = language(*style);
word_hyph(z) = hyph_style(*style) == HYPH_ON;
underline(z) = UNDER_OFF;
Link(new_acat, z);
New(z, GAP_OBJ);
hspace(z) = hspace(g);
vspace(z) = 0;
underline(z) = UNDER_OFF;
GapCopy(gap(z), space_gap(*style));
width(gap(z)) *= hspace(z);
Link(new_acat, z);
}
TransferLinks(NextDown(glink), prev_acat, new_acat);
StyleCopy(save_style(new_acat), *style);
Link(x, new_acat);
prev_acat = new_acat;
glink = prev_acat;
}
NextDefiniteWithGap(prev_acat, link, y, g, jn);
}
}
%* remove any singleton ACAT objects under x, if they are VCATs *%
for( link = Down(x); link != x; link = NextDown(link) )
{ Child(y, link);
if( type(y) == ACAT && Down(y) == LastDown(y) )
{ Child(z, Down(y));
if( type(z) == VCAT )
{ MoveLink(link, z, CHILD);
DisposeObject(y);
}
}
}
}
*** */
ReplaceWithSplit(x, bthr, fthr);
break;
case HCAT:
case VCAT:
x = ManifestCat(x, env, style, bthr, fthr, target, crs, ok, need_expand,
enclose, fcr);
break;
case WIDE:
case HIGH:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
GetGap(y, style, &res_gap, &res_inc);
if( res_inc != GAP_ABS || mode(res_gap) != EDGE_MODE ||
units(res_gap) != FIXED_UNIT )
{ Error(8, 26, "replacing invalid left parameter of %s by 2i",
WARN, &fpos(y), Image(type(x)) );
units(res_gap) = FIXED_UNIT;
width(res_gap) = 2*IN;
}
SetConstraint(constraint(x), MAX_FULL_LENGTH, width(res_gap), MAX_FULL_LENGTH);
DisposeChild(Down(x));
goto ETC; /* two cases down from here */
case HSHIFT:
case VSHIFT:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
GetGap(y, style, &shift_gap(x), &res_inc);
shift_type(x) = res_inc;
if( mode(shift_gap(x)) != EDGE_MODE ||
(units(shift_gap(x))!=FIXED_UNIT && units(shift_gap(x))!=NEXT_UNIT) )
{ Error(8, 27, "replacing invalid left parameter of %s by +0i",
WARN, &fpos(y), Image(type(x)) );
shift_type(x) = GAP_INC;
units(shift_gap(x)) = FIXED_UNIT;
width(shift_gap(x)) = 0;
mode(shift_gap(x)) = EDGE_MODE;
}
DisposeChild(Down(x));
goto ETC; /* next case down from here */
case HCONTRACT:
case VCONTRACT:
case HLIMITED:
case VLIMITED:
case HEXPAND:
case VEXPAND:
case ONE_COL:
case ONE_ROW:
ETC:
par = (type(x)==ONE_COL || type(x)==HEXPAND || type(x) == HCONTRACT ||
type(x)==HLIMITED || type(x)==WIDE || type(x)==HSHIFT) ? COLM : ROWM;
Child(y, Down(x));
/* manifest the child, propagating perp threads and suppressing pars */
bt[par] = ft[par] = nilobj;
bt[1-par] = bthr[1-par]; ft[1-par] = fthr[1-par];
y = Manifest(y, env, style, bt, ft, target, crs, ok, FALSE, enclose, fcr);
/* replace with split object if par threads needed */
bt[par] = bthr[par]; ft[par] = fthr[par];
bt[1-par] = ft[1-par] = nilobj;
ReplaceWithSplit(x, bt, ft);
break;
case BEGIN_HEADER:
case SET_HEADER:
/* first manifest gap, which is left parameter */
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE,
&nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
GetGap(y, style, &line_gap(save_style(x)), &res_inc);
/* now the right parameter */
Child(y, LastDown(x));
y = Manifest(y, env, style, bthr, fthr, target, crs, ok, need_expand,
enclose, fcr);
break;
case END_HEADER:
case CLEAR_HEADER:
/* give these objects a dummy child, just so that threads can attach */
/* to it and keep the thread code happy. Don't use ReplaceWithSplit */
/* because we don't want a split above a header */
y = MakeWord(WORD, STR_EMPTY, &fpos(x));
Link(x, y);
y = Manifest(y, env, style, bthr, fthr, target, crs, ok, need_expand,
enclose, fcr);
break;
case HSPAN:
case VSPAN:
ReplaceWithSplit(x, bthr, fthr);
break;
case ROTATE:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
GetGap(y, style, &res_gap, &res_inc);
if( res_inc != GAP_ABS || mode(res_gap) != EDGE_MODE ||
units(res_gap) != DEG_UNIT )
{ Error(8, 28, "replacing invalid left parameter of %s by 0d",
WARN, &fpos(y), Image(type(x)) );
units(res_gap) = DEG_UNIT;
width(res_gap) = 0;
}
sparec(constraint(x)) = width(res_gap);
DisposeChild(Down(x));
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE,enclose,fcr);
ReplaceWithSplit(x, bthr, fthr);
break;
case BACKGROUND:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE,enclose,fcr);
Child(y, LastDown(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE,enclose,fcr);
ReplaceWithSplit(x, bthr, fthr);
break;
case START_HVSPAN:
case START_HSPAN:
case START_VSPAN:
case HSCALE:
case VSCALE:
case HCOVER:
case VCOVER:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE,enclose,fcr);
ReplaceWithSplit(x, bthr, fthr);
break;
case SCALE:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
if( is_word(type(y)) && StringEqual(string(y), STR_EMPTY) )
{
/* missing scale factor, meaning to be inserted automatically */
bc(constraint(x)) = fc(constraint(x)) = 0; /* work out later */
}
else if( type(y) != ACAT )
{
/* presumably one word, common factor for horizontal and vertical */
scale_factor = GetScaleFactor(y);
bc(constraint(x)) = fc(constraint(x)) = scale_factor * SF;
}
else
{
/* get horizontal scale factor */
Child(z, Down(y));
scale_factor = GetScaleFactor(z);
bc(constraint(x)) = scale_factor * SF;
/* get vertical scale factor */
Child(z, LastDown(y));
scale_factor = GetScaleFactor(z);
fc(constraint(x)) = scale_factor * SF;
}
DisposeChild(Down(x));
Child(y, LastDown(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
ReplaceWithSplit(x, bthr, fthr);
break;
case KERN_SHRINK:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
Child(y, LastDown(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
ReplaceWithSplit(x, bthr, fthr);
break;
case YIELD:
Error(8, 29, "%s not expected here", FATAL, &fpos(x), KW_YIELD);
break;
case RAW_VERBATIM:
case VERBATIM:
Child(y, Down(x));
y = Manifest(y, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
DeleteLink(Down(x));
MergeNode(y, x); x = y;
break;
case CASE:
x = ManifestCase(x,env,style, bthr, fthr, target, crs, ok, need_expand, enclose, fcr);
break;
case BACKEND:
res = MakeWord(WORD, BackEnd->name, &fpos(x));
ReplaceNode(res, x);
DisposeObject(x);
x = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
break;
case XCHAR:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
if( !is_word(type(y)) )
{ Error(8, 30, "%s dropped (parameter is not a simple word)",
WARN, &fpos(y), KW_XCHAR);
res = MakeWord(WORD, STR_EMPTY, &fpos(x));
}
else if( (word_font(y) = font(*style)) == 0 )
{ Error(8, 31, "%s dropped (no current font at this point)",
WARN, &fpos(y), KW_XCHAR);
res = MakeWord(WORD, STR_EMPTY, &fpos(x));
}
else
{ ch = MapCharEncoding(string(y), FontMapping(word_font(y), &fpos(y)));
if( ch == '\0' )
{ type(y) = QWORD;
Error(8, 32, "%s dropped (character %s unknown in font %s)",
WARN, &fpos(y), KW_XCHAR, StringQuotedWord(y),
FontFamilyAndFace(word_font(y)));
res = MakeWord(WORD, STR_EMPTY, &fpos(x));
}
else
{ res = MakeWord(QWORD, STR_SPACE, &fpos(x));
string(res)[0] = ch;
}
}
ReplaceNode(res, x);
DisposeObject(x);
x = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
break;
case CURR_LANG:
if( language(*style) == 0 )
{ Error(8, 33, "no current language at this point, using %s",
WARN, &fpos(x), STR_NONE);
res = MakeWord(WORD, STR_NONE, &fpos(x));
}
else res = MakeWord(WORD, LanguageString(language(*style)), &fpos(x));
ReplaceNode(res, x);
DisposeObject(x);
x = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
break;
case CURR_FAMILY:
case CURR_FACE:
if( font(*style) == 0 )
{ Error(8, 38, "no current font at this point, using %s",
WARN, &fpos(x), STR_NONE);
res = MakeWord(WORD, STR_NONE, &fpos(x));
}
else if( type(x) == CURR_FAMILY )
res = MakeWord(WORD, FontFamily(font(*style)), &fpos(x));
else
res = MakeWord(WORD, FontFace(font(*style)), &fpos(x));
ReplaceNode(res, x);
DisposeObject(x);
x = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
break;
case CURR_YUNIT:
case CURR_ZUNIT:
{ FULL_CHAR buff[20];
if( type(x) == CURR_YUNIT )
sprintf( (char *) buff, "%dp", yunit(*style) / PT);
else
sprintf( (char *) buff, "%dp", zunit(*style) / PT);
res = MakeWord(WORD, buff, &fpos(x));
}
ReplaceNode(res, x);
DisposeObject(x);
x = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
break;
case FONT:
case SPACE:
case YUNIT:
case ZUNIT:
case BREAK:
case COLOUR:
case LANGUAGE:
assert( Down(x) != x && NextDown(Down(x)) != x, "Manifest: FONT!" );
StyleCopy(new_style, *style);
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, type(x) == COLOUR);
switch( type(x) )
{
case FONT: FontChange(&new_style, y);
break;
case SPACE: SpaceChange(&new_style, y);
break;
case YUNIT: YUnitChange(&new_style, y);
break;
case ZUNIT: ZUnitChange(&new_style, y);
break;
case BREAK: BreakChange(&new_style, y);
break;
case COLOUR: ColourChange(&new_style, y);
break;
case LANGUAGE: LanguageChange(&new_style, y);
break;
}
DisposeChild(Down(x));
Child(y, Down(x));
y = Manifest(y, env, &new_style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
DeleteLink(Down(x));
MergeNode(y, x); x = y;
break;
case OUTLINE:
case PADJUST:
case HADJUST:
case VADJUST:
StyleCopy(new_style, *style);
if( type(x) == OUTLINE ) outline(new_style) = TRUE;
else if( type(x) == VADJUST ) vadjust(new_style) = TRUE;
else if( type(x) == HADJUST ) hadjust(new_style) = TRUE;
else padjust(new_style) = TRUE;
Child(y, Down(x));
y = Manifest(y, env, &new_style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
DeleteLink(Down(x));
MergeNode(y, x); x = y;
break;
case UNDERLINE:
/* change x to an ACAT and set the underline flags in its child */
assert( Down(x) != x && NextDown(Down(x)) == x, "Manifest: UNDERLINE!" );
type(x) = ACAT;
adjust_cat(x) = padjust(*style);
padjust(*style) = FALSE;
StyleCopy(save_style(x), *style);
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
SetUnderline(x);
ReplaceWithSplit(x, bthr, fthr);
break;
case MELD:
case COMMON:
case RUMP:
assert( Down(x) != x && NextDown(Down(x)) != x, "Manifest: COMMON!" );
debug2(DHY, DDD, "[Manifest %s %s", EchoObject(x), EchoObject(env));
/* find the first child of x, make sure it is an ACAT, and manifest */
Child(x1, Down(x));
if( type(x1) != ACAT )
{ OBJECT newx1;
New(newx1, ACAT);
adjust_cat(newx1) = padjust(*style);
padjust(*style) = FALSE;
MoveLink(Down(x), newx1, CHILD);
Link(newx1, x1);
x1 = newx1;
}
x1 = Manifest(x1, env, style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
link1 = x1;
while( NextDown(link1) != x1 )
{ Child(z, NextDown(link1));
if( type(z) == ACAT )
{ TransferLinks(Down(z), z, NextDown(link1));
DisposeChild(Up(z));
}
else link1 = NextDown(link1);
}
debug1(DHY, DDD, " manifested x1 = %s", EchoObject(x1));
/* find the second child of x, make sure it is an ACAT, and manifest */
Child(x2, NextDown(Down(x)));
if( type(x2) != ACAT )
{ OBJECT newx2;
New(newx2, ACAT);
adjust_cat(newx2) = padjust(*style);
padjust(*style) = FALSE;
MoveLink(NextDown(Down(x)), newx2, CHILD);
Link(newx2, x2);
x2 = newx2;
}
x2 = Manifest(x2, env, style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
link2 = x2;
while( NextDown(link2) != x2 )
{ Child(z, NextDown(link2));
if( type(z) == ACAT )
{ TransferLinks(Down(z), z, NextDown(link2));
DisposeChild(Up(z));
}
else link2 = NextDown(link2);
}
debug1(DHY, DDD, " manifested x2 = %s", EchoObject(x2));
if( type(x) == MELD )
{
/* if Meld, result is Meld(x1, x2) */
res = Meld(x1, x2);
}
else
{
/* find the point where x1 and x2 begin to differ */
link1 = Down(x1);
link2 = Down(x2);
while( link1 != x1 && link2 != x2 )
{
Child(y1, link1);
Child(y2, link2);
debug1(DHY, DDD, " y1 = %s", EchoObject(y1));
debug1(DHY, DDD, " y2 = %s", EchoObject(y2));
if( is_word(type(y1)) && is_word(type(y2)) )
{
if( !StringEqual(string(y1), string(y2)) ) break;
}
else if( type(y1) != type(y2) ) break;
link1 = NextDown(link1);
link2 = NextDown(link2);
}
/* if COMMON, result is x1 or x2 if either ran out, */
/* or else x2 (say) up to but not including link2 and prec gap */
if( type(x) == COMMON )
{ if( link2 == x2 )
{ res = x2;
}
else if( link1 == x1 )
{ res = x1;
}
else
{ if( link2 == Down(x2) )
res = MakeWord(WORD, STR_EMPTY, &fpos(x2));
else
{ TransferLinks(PrevDown(link2), x2, x1);
res = x2;
}
}
}
/* if RUMP, result is x2 starting from link2 or NextDown(link2) */
else if( type(x) == RUMP )
{ if( link2 == x2 )
res = MakeWord(WORD, STR_EMPTY, &fpos(x2));
else if( link1 == x1 )
{
TransferLinks(Down(x2), NextDown(link2), x1);
res = x2;
}
else /* link1 != x1 */
{
TransferLinks(Down(x2), link2, x1);
res = x2;
}
}
}
/* now res replaces x */
ReplaceNode(res, x);
DisposeObject(x);
x = res;
ReplaceWithSplit(x, bthr, fthr);
debug1(DHY, DDD, "]Manifest returning %s", EchoObject(x));
break;
case INSERT:
/* manifest and detach the left parameter, call it z */
Child(z, Down(x));
z = Manifest(z, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
DeleteLink(Down(x));
/* manifest the right parameter and make it the result */
Child(y, LastDown(x));
y = Manifest(y, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
DeleteLink(LastDown(x));
MergeNode(y, x); x = y;
/* now find the reattachment point for z down inside the result, x */
x = InsertObject(x, &z, style);
if( z != nilobj )
{ Error(8, 34, "object dropped by %s: no suitable insert point", WARN,
&fpos(x), KW_INSERT);
DisposeObject(z);
}
break;
case ONE_OF:
Child(y, Down(x));
if( type(y) != ACAT )
{
/* child is not a sequence of choices, so ignore ONE_OF */
Error(8, 39, "%s ignored: no choices in right parameter", WARN,
&fpos(x), KW_ONE_OF);
y = Manifest(y, env, style, bthr, fthr, target, crs, ok, FALSE,
enclose, fcr);
DeleteLink(Down(x));
MergeNode(y, x); x = y;
}
else
{
/* try each child in turn; result is first to find *target */
OBJECT target_before;
for( link = Down(y); link != y; link = NextDown(link) )
{
Child(z, link);
if( type(z) == GAP_OBJ ) continue;
target_before = *target;
z = Manifest(z, env, style, bthr, fthr, target, crs, ok, FALSE,
enclose, fcr);
if( *target != target_before )
break;
}
DeleteLink(Up(z));
ReplaceNode(z, x);
DisposeObject(x);
x = z;
}
break;
case NEXT:
assert( Down(x) != x, "Manifest/NEXT: Down(x) == x!" );
Child(y, Down(x));
debug1(DCS, DD, " Manifesting Next( %s, 1 )", EchoObject(y));
y = Manifest(y, env, style, bthr, fthr, target, crs, FALSE, FALSE, enclose, fcr);
debug1(DCS, DD, " calling Next( %s, 1 )", EchoObject(y));
done = FALSE;
y = Next(y, 1, &done);
debug2(DCS, DD, " Next(done = %s) returning %s",
bool(done), EchoObject(y));
DeleteLink(Down(x));
MergeNode(y, x); x = y;
break;
case PLUS:
case MINUS:
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
Child(z, NextDown(Down(x)));
z = Manifest(z, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
z = ReplaceWithTidy(z, FALSE);
if( is_word(type(y)) && sscanf( (char *) string(y), "%d", &num1) == 1 &&
is_word(type(z)) && sscanf( (char *) string(z), "%d", &num2) == 1 )
{
FULL_CHAR buff[MAX_BUFF];
sprintf( (char *) buff, "%d", type(x) == PLUS ? num1+num2 : num1-num2);
res = MakeWord(WORD, buff, &fpos(x));
}
else
{ res = MakeWord(WORD, STR_NOCROSS, &fpos(x));
}
debug4(DOM, DD, "{ %s } %s { %s } = %s", EchoObject(y), Image(type(x)),
EchoObject(z), EchoObject(res));
res = Manifest(res, env, style, bthr, fthr, target, crs, FALSE, FALSE, enclose, fcr);
ReplaceNode(res, x);
DisposeObject(x);
x = res;
break;
case OPEN:
debug0(DCR, DD, " [ Manifest/OPEN begins:");
Child(y, Down(x));
DeleteLink(Down(x));
Child(res, LastDown(x));
hold_env = nilobj;
if( type(y) == CLOSURE )
{ AttachEnv(env, y);
StyleCopy(save_style(y), *style);
debug0(DCR, DDD, "calling SetEnv from Manifest (b)");
res_env = SetEnv(y, nilobj);
New(hold_env, ACAT); Link(hold_env, res_env);
res = Manifest(res, res_env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
}
else if( is_cross(type(y)) )
{ Child(z, Down(y));
if( type(z) == CLOSURE )
{ debug0(DCR, DD, " calling CrossExpand from Manifest/OPEN");
/* *** want cross ref now always, not only if ok
y = CrossExpand(y, env, style, ok, crs, &res_env);
*** */
y = CrossExpand(y, env, style, crs, &res_env);
AttachEnv(res_env, y);
debug0(DCR, DDD, "calling SetEnv from Manifest (c)");
res_env = SetEnv(y, env);
New(hold_env, ACAT); Link(hold_env, res_env);
res = Manifest(res, res_env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
}
else
{ Error(8, 35, "invalid left parameter of %s", WARN, &fpos(y), KW_OPEN);
res = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
}
}
else
{ Error(8, 36, "invalid left parameter of %s", WARN, &fpos(y), KW_OPEN);
res = Manifest(res, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
}
ReplaceNode(res, x);
DisposeObject(x);
if( hold_env != nilobj ) DisposeObject(hold_env);
x = res;
debug0(DCR, DD, " ] Manifest/OPEN ends");
break;
case TAGGED:
x = ManifestTg(x, env, style, bthr, fthr, target, crs, ok, need_expand, enclose, fcr);
debug2(DCR, DD, "Manifest returning %ld %s", (long) x, EchoObject(x));
break;
case PLAIN_GRAPHIC:
case GRAPHIC:
debug1(DRS, DD, " graphic style in Manifest = %s", EchoStyle(style));
Child(y, LastDown(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok, FALSE, enclose, fcr);
StyleCopy(save_style(x), *style);
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
ReplaceWithSplit(x, bthr, fthr);
break;
case LINK_SOURCE:
case LINK_DEST:
Child(y, LastDown(x));
y = Manifest(y, env, style, nbt, nft, target, crs, ok,FALSE,enclose,fcr);
StyleCopy(save_style(x), *style);
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE,
&nenclose, fcr);
y = ReplaceWithTidy(y, TRUE);
ReplaceWithSplit(x, bthr, fthr);
break;
case INCGRAPHIC:
case SINCGRAPHIC:
StyleCopy(save_style(x), *style);
debug2(DGP, DD, " manifest at %s (style %s)",
EchoObject(x), EchoStyle(&save_style(x)));
Child(y, Down(x));
y = Manifest(y, env, style, nbt, nft, &ntarget, crs, FALSE, FALSE, &nenclose, fcr);
y = ReplaceWithTidy(y, FALSE);
if( !is_word(type(y)) )
{ Error(8, 37, "%s deleted (invalid right parameter)", WARN, &fpos(y),
type(x) == INCGRAPHIC ? KW_INCGRAPHIC : KW_SINCGRAPHIC);
y = MakeWord(WORD, STR_EMPTY, &fpos(x));
ReplaceNode(y, x); DisposeObject(x);
x = Manifest(y, env, style, bthr, fthr, target, crs, ok, FALSE, enclose, fcr);
return x;
}
ReplaceWithSplit(x, bthr, fthr);
break;
default:
assert1(FALSE, "Manifest:", Image(type(x)));
break;
} /* end switch */
debug2(DOM, DD, "]Manifest returning %s %s", Image(type(x)), EchoObject(x));
debug1(DOM, DD, " at exit, style = %s", EchoStyle(style));
debug1(DOM, DDD, "up: ", EchoObject(bthr[COLM]));
debug1(DOM, DDD, "down: ", EchoObject(fthr[COLM]));
debug1(DOM, DDD, "left: ", EchoObject(bthr[ROWM]));
debug1(DOM, DDD, "right: ", EchoObject(fthr[ROWM]));
debugcond1(DHY, DD, eee, "] Manifest returning %s", EchoObject(x));
depth--;
return x;
} /* end Manifest */