#include <stdio.h>
#define nl '\n'
int
main (int argc, char **argv)
{
// DOCUMENT LAYOUT PROGRAM
// SYMBOLIC CONSTANTS
static int half = 1;
static int lineexp = 0;
static int expind = 0;
static int expbit = 1024;
static int expsh = 0;
static int linesub = 0;
static int subind = 0;
static int subbit = 2048;
static int subshb = 0;
static int subshe = 0;
// PARA HACER LO DE LAS FIGURAS
static int figura = 0;
static int sin = 1;
// SOURCE INPUT STREAM
static int err = 0, doc = 2, sout = 3;
// OUTPUT STREAMS
static int lbound = 200;
// LINE BUFF BOUND
static int abound = 200;
// ATOM BUFF BOUND
static int sbound = 200;
// SOURCE LINE BUFF BOUND
static int vbound = 25;
// VECTOR (EG TAB) BOUND
static int escbit = 256, undbit = 128, casebit = 32;
static int charmask = 255, basicmask = 127, letmask = 95;
static int sentsp = 512 + ' ';
// LAYOUT PARAMETERS
static int top = 5, bottom = 9, left = 0, page = 57, line = 69;
static int sline = 69, nls = 2, sgap = 2, pgap = 3;
static int indent = 0, sectno = 0, pageno = 1, start = 1;
static int escape = '$', cap = '@', und = '_', capsh = '.', undsh = '%';
static int capo = '@', undo = '_', capsho = '.', undsho = '%';
static int invert = 32, ascii = 1, just = 1, mark = 1;
static int tab[25 + 1];
#define tab(n) tab[n]
static int tempa[25 + 1];
#define tempa(n) tempa[n]
static int tempb[25 + 1];
#define tempb(n) tempb[n]
static int xlines = 0, linecapind = 0, lineundind = 0, linemidind = 0;
static int indentind = 1, textind = 0, errind = 0, endind = 0;
static int cols = 0;
// COLUMNS USED ON CURRENT LINE
static int lines = 0;
// LINES PRINTED ON CURRENT PAGE
static int pages = 0;
// TOTAL PAGES PRINTED
static int fixed = 0;
// FIXED COLUMNS
static int gaps = 0, sgaps = 0;
// TOTAL GAPS, SENTENCE GAPS
static int size = 0;
// SIZE OF CURRENT ATOM
static int smax = 0;
// UPDATED SOURCE POINTER
static int indentcol = 1;
int next;
int directive;
int relind;
int hbuff[lbound];
#define hbuff(n) hbuff[(n)-1]
// HELP (SUB & SUP) BUFF
int buff[lbound];
#define buff(n) buff[(n)-1]
// LINE BUFFER
int abuff[abound];
#define abuff(n) abuff[(n)-1]
// ATOM BUFFER
int sbuff[sbound];
#define sbuff(n) sbuff[(n)-1]
// SOURCE LINE (UPDATED)
auto void fault (int n)
{
fputc ('*', stderr);
switch (n)
{
case 1: /* 1 */
fprintf (stderr, "FAULTY FORMAT AT ");
fputc (next, stderr);
errind = 1;
fputc ('\n', stderr);
return;
case 3: /* 3 */
fprintf (stderr, "UNKNOWN NAME\n");
errind = 1;
return;
case 4: /* 4 */
fprintf (stderr, "SCALAR/VECTOR MISMATCH\n");
errind = 1;
return;
case 5: /* 5 */
fprintf (stderr, "UNKNOWN DIRECTIVE ");
break;
case 6: /* 6 */
fprintf (stderr, "SPURIOUS DIRECTIVE ");
break;
case 7: /* 7 */
fprintf (stderr, "OUT OF BOUNDS ");
break;
case 8: /* 8 */
fprintf (stderr, "OFF PAGE ");
break;
case 9: /* 9 */
fprintf (stderr, "OVER TEXT ");
break;
}
fputc (directive, stderr);
if (relind != 0)
fputc (relind, stderr);
errind = 1;
fputc ('\n', stderr);
}
// !!!!!!!!!!!
int inbuff[200];
#define inbuff(n) inbuff[(n)-1]
// INPUT BUFFER
static int inp = 0;
static int inmax = 0;
auto void construct (void)
{
int k;
inmax = 0;
do inbuff (++inmax) = k = fgetc(stdin); while (k != nl);
}
// * ----=============
auto void readone (int *k)
{
if (++inp > inmax)
{
inp = 1;
construct ();
}
*k = inbuff (inp);
}
// *-------------------------------
// !!!!!!!!!!!!
auto void readatomordirective (void)
{
int k;
int c;
int u;
int atomcapind;
int atomundind;
int partexpind;
int partsubind;
if (next == 0)
readone (&k);
else
{
k = next;
next = 0;
}
partexpind = 0;
partsubind = 0;
directive = 0;
size = 0;
atomcapind = 0;
atomundind = 0;
if (k == capsh)
{
atomcapind = casebit;
readone (&k);
}
for (;;)
{
if (k == undsh)
{
atomundind = undbit;
readone (&k);
}
u = lineundind;
// !!!!!!
// !! %IF K=EXPSH %THEN %START
// !! PARTEXPIND=PARTEXPIND!!EXPBIT
// !! READ ONE(K)
// !! EXPIND=EXPIND!1
// !! %IF PARTSUBIND#0 %THEN %START
// !! %PRINTTEXT '** EXP AND SUB **'
// !! NEWLINE
// !! %FINISH
// !! %FINISH
// !! %IF K=SUBSHB %THEN %START
// !! %IF PARTEXPIND#0 %THEN %START
// !! %PRINTTEXT'** SUB AND EXP'
// !! NEWLINE
// !! %FINISH
// !! PARTSUBIND=SUBBIT
// !! READ ONE(K)
// !! SUBIND=1
// !! %FINISH
// !! %IF K=SUBSHE %THEN PARTSUBIND=0 %AND READ ONE(K)
// !!!
c = linecapind | atomcapind;
if (k == und)
{
u |= undbit;
readone (&k);
}
u |= (partsubind | partexpind);
if (k != ' ')
u |= atomundind;
if (k == cap)
{
c = casebit;
readone (&k);
}
if (('A' <= (k & letmask)) && ((k & letmask) <= 'Z'))
k ^= invert;
// LET
if (('A' <= ((k & basicmask) - casebit))
&& (((k & basicmask) - casebit) <= 'Z'))
k -= c;
// LC LET
if (k == nl)
break;
if (k == escape)
{
readone (&k);
k += escbit;
}
k |= u;
if (k == ' ')
break;
if (((k & escbit) != 0) && ('A' <= (k & letmask))
&& ((k & letmask) <= 'Z'))
{
if (size != 0)
break;
directive = k & letmask;
readone (&next);
return;
}
abuff (++size) = k;
readone (&k);
}
next = k;
if (atomundind == 0 || size == 0)
return;
k = abuff (size) ^ undbit;
if (k == '.' || k == ',' || k == ':' || k == ';' || k == ')')
abuff (size) = k;
}
auto void printsourceline (void)
{
int i;
if (errind != 0)
{
i = 0;
while (i != smax)
fputc (sbuff (++i), stderr);
fputc ('\n', stderr);
errind = 0;
}
i = 0;
while (i != smax) fputc (sbuff (++i), stderr);
fputc ('\n', stderr);
smax = 0;
}
auto void store (int k)
{
sbuff (++smax) = k;
}
auto void storesourceatom (void)
{
int i;
int j;
int k;
int atomcapind;
int atomundind;
auto void translateunderline (void)
{
int p;
int q;
if (lineundind != 0)
{
k -= undbit;
return;
}
if ((k & basicmask) == ' ')
goto one;
if (atomundind != 0)
{
k -= undbit;
return;
}
if (undsho == 0)
goto one;
p = i;
while (p != size)
{
q = abuff (++p);
if (((q & undbit) == 0) &&
(p != size
|| (q != '.' && q != ',' && q != ':' && q != ';' && q != ')')))
goto one;
}
store (undsho);
k -= undbit;
atomundind = 1;
return;
one:
if (undo == 0)
return;
store (undo);
k -= undbit;
}
atomcapind = 0;
atomundind = 0;
if (linecapind == 0 && capsho != 0 && size >= 2)
{
for (i = 1; i <= size; i += 1)
{
k = abuff (i) & basicmask;
if ('A' <= k - casebit && k - casebit <= 'Z')
{
atomcapind = 0;
break;
} // LC
if ('A' <= k && k <= 'Z')
atomcapind += 1;
// UC
}
}
if (smax != 0 && xlines == 0)
{
if (smax + size + 1 <= sline)
store (' ');
else
printsourceline ();
}
if (atomcapind != 0)
store (capsho);
for (i = 1; i <= size; i += 1)
{
k = abuff (i);
if ((k & undbit) != 0)
translateunderline ();
if (('A' <= k && k <= 'Z') && (linecapind != 0 || atomcapind != 0))
k += casebit;
if (('A' <= k && k <= 'Z') && capo != 0)
{
store (capo);
k += casebit;
}
if (('A' <= (k & letmask)) && ((k & letmask) <= 'Z')) k ^= invert;
if ((k & escbit) != 0) store (escape);
store (k & charmask);
}
}
auto void setcolumn (int m)
{
if (1 <= m && m <= line)
{
m -= 1;
if (cols < m)
{
do
buff (++cols) = ' ';
while (cols != m);
}
else
{
while (cols != m)
{
if (buff (cols) != ' ')
{
fault (9);
break;
}
cols -= 1;
}
}
}
else
{
fault (8);
if (indentcol == m)
indentcol = 1;
}
fixed = cols;
gaps = 0;
sgaps = 0;
}
auto void printdocline (void)
{
static int cr = 13;
int i;
int j;
int k;
int l;
int m;
int u;
auto void printit (int buff)
{
}
// * ------------------------------------- PRINTIT
auto void putsuporsub (int msk)
{
for (i = 1; i <= cols; i += 1)
{
k = buff (i);
if ((k & msk) != 0)
{
hbuff (i) = k ^ msk;
buff (i) = ' ';
}
else
hbuff (i) = ' ';
}
}
// * ---------------------------- PUT SUP OR SUB
auto void wait (void)
{
// removed
}
// * ------------------------------ WAIT
lines += nls;
// !! %IF LINEEXP#0 %THEN HALF=HALF!!1 %AND LINES=LINES+HALF
// !! %IF LINESUB#0 %THEN HALF=HALF!!1 %AND LINES=LINES+HALF
if (pages + 1 >= start)
{
if (lines == nls)
{
if (mark != 0)
{
if (mark == 1)
{
fputc ('=', stdout);
{int i; for (i = 0; i < line-2; i++) fprintf (stdout, " ");}
fputc ('=', stdout);
}
else
{
fputc (12, stdout);
// FORM FEED
}
fprintf (stdout, "\n");
}
{int i; for (i = 0; i < top; i++) fprintf (stdout, "\n");}
}
if (textind != 0)
{
l = left;
if (linemidind != 0)
l = l + ((int) ((line - cols)) / (int) (2));
{int i; for (i = 0; i < l; i++) fprintf (stdout, " ");}
u = undbit;
for (i = 1; i <= cols; i += 1)
{
k = buff (i);
if ((k & u) != 0)
{
m = i;
for (j = i; j <= cols; j += 1)
{
if ((buff (j) & undbit) != 0)
{
{int i; for (i = 0; i < j - m; i++) fprintf (stdout, " ");}
fputc ('_', stdout);
m = j + 1;
}
}
fputc (cr, stdout);
fputc (cr, stdout);
{int i; for (i = 0; i < l + i - 1; i++) fprintf (stdout, " ");}
u = 0;
}
fputc (k & basicmask, stdout);
}
//
//
// !! %IF LINEEXP#0 %THEN %START
// !! PUT SUP OR SUB(EXPBIT)
// !! !LEFT=LEFT-1
// !! PRINTIT(HBUFF)
// !! WAIT
// !! !LEFT=LEFT+1
// !! %FINISH
// !! %IF LINESUB#0 %THEN %START
// !! PUT SUP OR SUB(SUBBIT)
// !! !LEFT=LEFT-1
// !! PRINTIT(BUFF)
// !! WAIT
// !! !LEFT=LEFT+1
// !! PRINTIT(HBUFF)
// !! %FINISH %ELSE PRINTIT(BUFF)
}
{int i; for (i = 0; i < nls; i++) fprintf (stdout, "\n");}
if (lines >= page)
{
if (pageno == 0)
{int i; for (i = 0; i < bottom; i++) fprintf (stdout, "\n");}
else
{
fprintf (stdout, "\n\n");
{int i; for (i = 0; i < left + ((int) (line) / (int) (2 - 4)); i++) fprintf (stdout, " ");}
fprintf (stdout, "%0d", pageno);
{int i; for (i = 0; i < bottom-2; i++) fprintf (stdout, "\n");}
}
}
}
lineexp = 0;
linesub = 0;
if (lines >= page)
{
lines = 0;
pages += 1;
if (pageno != 0)
pageno += 1;
// LO DE LA FIGURA
if (figura == 1)
{
figura = 0;
pageno += 1;
} // SE ACABO
}
if (xlines != 0)
{
xlines -= 1;
if (xlines == 0)
{
linecapind = 0;
lineundind = 0;
linemidind = 0;
indentind = 1;
}
}
textind = 0;
cols = 0;
fixed = 0;
if (indentind != 0)
setcolumn (indentcol);
}
auto void justify (void)
{
int i;
int j;
int k;
int l;
int min;
int count;
int scount;
int wait;
int swait;
count = line - cols;
if (count <= 0 || gaps == 0)
return;
min = ((int) (count) / (int) (gaps));
count = count - min * gaps;
scount = sgaps;
if (count < sgaps)
scount = count;
count -= scount;
if ((lines & 1) == 0)
{
wait = 0;
swait = 0;
}
else
{
wait = gaps - count;
swait = sgaps - scount;
}
j = line;
for (i = cols; i >= 1; i -= 1)
{
k = buff (i);
if ((k == sentsp || k == ' ') && buff (i - 1) != k)
{
l = j - min;
if (wait == 0)
{
if (count != 0)
{
l -= 1;
count -= 1;
}
}
else
wait -= 1;
if (k == sentsp)
{
if (swait == 0)
{
if (scount != 0)
{
l -= 1;
scount -= 1;
}
}
else
swait -= 1;
}
while (j != l)
buff (j--) = ' ';
if (j == i)
{
cols = line;
return;
}
}
buff (j--) = k;
}
exit (0);
}
auto void placeatom (void)
{
int i;
int l;
int s;
if (cols != fixed && xlines == 0)
{
l = cols + 1;
s = ' ';
if (buff (cols) == '.' && 'A' <= abuff (1) && abuff (1) <= 'Z')
{
l = cols + sgap;
s = sentsp;
}
if (l + size <= line)
{
while (cols != l)
buff (++cols) = s;
gaps += 1;
if (s == sentsp)
sgaps += 1;
}
else
{
// L+SIZE IS > LINE PRINT
if (just != 0)
justify ();
printdocline ();
if (smax != 0)
printsourceline ();
}
}
i = 0;
lineexp = lineexp | expind;
linesub = linesub | subind;
while (i != size)
buff (++cols) = abuff (++i);
expind = 0;
subind = 0;
textind = 1;
}
auto void processdirective (void)
{
int num;
int c;
int t;
auto void assign (void);
auto void skip (void)
{
sbuff (++smax) = next;
readone (&next);
}
if (xlines != 0)
{
fault (6);
xlines = 1;
printdocline ();
}
if (textind != 0 && ('C' != (directive & letmask)) && ((directive & letmask) != 'T'))
{
printdocline ();
if (smax != 0)
printsourceline ();
}
if (smax + 5 > sline)
printsourceline ();
if (smax != 0)
store (' ');
store (escape);
store (directive);
relind = 0;
num = 1;
if (next == '+' || next == '-')
{
relind = next;
skip ();
}
if ('0' <= next && next <= '9')
{
num = next - '0';
skip ();
while (('0' <= next && next <= '9'))
{
num = 10 * num - '0' + next;
skip ();
}
}
if (relind == '-')
num = (-(num));
switch (directive & letmask)
{
case 'A': /* 'A' */
// ASSIGN
for (;;)
{
assign ();
while ((next != ';' && next != nl))
skip ();
if (next == nl)
break;
skip ();
}
if (indent < 0|| indent > vbound)
{
fault (7);
indent = 0;
}
indentcol = tab (indent);
setcolumn (indentcol);
return;
case 'B': /* 'B' */
// BLANKS
if (page - lines < num)
num = page - lines;
while (num > 0)
{
printdocline ();
num -= 1;
}
return;
case 'C': /* 'C' */
// COL
if (relind != 0)
num = cols + 1 + num;
setcolumn (num);
return;
case 'E': /* 'E' */
// END
endind = 1;
next = nl;
while (lines != 0)
printdocline ();
return;
case 'I': /* 'I' */
// INDENT
if (relind != 0)
num = indent + num;
if (num < 0 || num > vbound)
{
fault (7);
num = 0;
}
num = tab (num);
setcolumn (num);
return;
case 'L': /* 'L' */
// LINES
xlines = num;
indentind = 0;
while (next != nl)
{
if ((next & letmask) == 'C')
linecapind = casebit;
if ((next & letmask) == 'U')
lineundind = undbit;
if ((next & letmask) == 'M')
linemidind = 1;
if ((next & letmask) == 'I')
indentind = 1;
skip ();
}
if (indentind == 0)
{
cols = 0;
fixed = 0;
}
return;
case 'N': /* 'N' */
// NEWPAGE
while (lines != 0)
printdocline ();
return;
case 'P': /* 'P' */
// PARAGRAPH
if (lines != 0)
{
if (page - lines < num + 2)
num = page - lines;
while (num > 0)
{
printdocline ();
num -= 1;
}
}
setcolumn (cols + 1 + pgap);
return;
case 'T': /* 'T' */
// TAB
if (relind != 0)
{
t = 0;
c = cols + 1;
if (relind == '+')
{
while (num > 0)
{
do t += 1; while (t <= vbound && tab (t) <= c);
if (t > vbound)
{
fault (7);
return;
}
c = tab (t);
num -= 1;
}
}
else
{
do t += 1; while (t <= vbound && tab (t) < c);
while (num < 0)
{
do t -= 1; while (t >= 0 && tab (t) >= c);
if (t < 0)
{
fault (7);
return;
}
c = tab (t);
num += 1;
}
}
}
else
{
if (num < 0 || num > vbound)
{
fault (7);
return;
}
c = tab (num);
}
setcolumn (c);
return;
case 'V': /* 'V' */
// VERIFY
// PARA HACER LO DE LA FIGURA
if (num == 0)
figura = 1;
// SE ACABO
if (page - lines < num)
{
while (lines != 0)
printdocline ();
}
return;
case 'D': /* 'D' */
case 'F': /* 'F' */
case 'G': /* 'G' */
case 'H': /* 'H' */
case 'J': /* 'J' */
case 'K': /* 'K' */
case 'M': /* 'M' */
case 'O': /* 'O' */
case 'Q': /* 'Q' */
case 'R': /* 'R' */
case 'S': /* 'S' */
case 'U': /* 'U' */
case 'W': /* 'W' */
case 'X': /* 'X' */
case 'Y': /* 'Y' */
case 'Z': /* 'Z' */
fault (5);
return;
}
auto void assign (void)
{
static int scalarmax = 30, parmax = 34;
int i;
int j;
int k;
auto void readvalue (int *j);
auto void readname (int *ordinal);
auto int *map (int i);
auto int *vmap (int i, int j);
readname (&i);
if (i == 0)
return;
if (next != '=')
{
fault (1);
return;
}
do skip (); while (next == ' ');
if (i <= scalarmax)
{
if (('A' <= (next & letmask)) && ((next & letmask) <= 'Z'))
{
readname (&j);
if (j == 0)
return;
if (j > scalarmax)
{
fault (4);
return;
}
*map (i) = *map (j);
}
else
{
readvalue (&j);
*map (i) = j;
}
}
else
{
if (('A' <= (next & letmask)) && ((next & letmask) <= 'Z'))
{
readname (&j);
if (j == 0)
return;
if (j <= scalarmax)
{
fault (4);
return;
}
for (k = 1; k <= vbound; k += 1)
{
*vmap (i, k) = *vmap (j, k);
}
}
else
{
for (k = 1; k <= vbound; k += 1)
{
readvalue (&j);
*vmap (i, k) = j;
if (next != ',')
break;
do skip (); while (next == ' ');
}
}
}
if (next != ';' && next != nl)
fault (1);
auto void readvalue (int *v)
{
if (next != '\\')
{
*v = 0;
while (('0' <= next && next <= '9'))
{
*v = (10 * (*v)) - '0' + next;
skip ();
}
}
else
{
skip ();
// QUOTE-MARK
*v = next;
skip ();
// QUOTED SYMBOL
skip ();
// QUOTE-MARK (PRESUMABLY)
}
}
// READ VALUE
auto void readname (int *ordinal)
{
int n1;
int n2;
static int name1[34];
#define name1(n) name1[(n)-1]
static int name2[34];
#define name2(n) name2[(n)-1]
auto void get (int *k)
{
if ((next & letmask) < 'A' || (next & letmask) > 'Z')
{
*k = 0;
return;
}
*k = next & 31;
skip ();
}
// GET
auto void gettrio (int *t)
{
int a;
int b;
int c;
get (&a);
get (&b);
get (&c);
*t = (((a << 5) + b) << 5) + c;
}
// GET TRIO
while (next == ' ')
skip ();
gettrio (&n1);
gettrio (&n2);
if (n1 == 0)
{
fault (1);
*ordinal = 0;
return;
}
for (*ordinal = 1; *ordinal <= parmax; *ordinal += 1)
{
if (name1 (*ordinal) == n1 && name2 (*ordinal) == n2)
return;
}
fault (3);
*ordinal = 0;
}
// READ NAME
auto int *map (int i)
{
switch (i)
{
case 1: /* 1 */
return (&top);
case 2: /* 2 */
return (&bottom);
case 3: /* 3 */
return (&left);
case 4: /* 4 */
return (&page);
case 5: /* 5 */
return (&line);
case 6: /* 6 */
return (&sline);
case 7: /* 7 */
return (&nls);
case 8: /* 8 */
return (&sgap);
case 9: /* 9 */
return (&pgap);
case 10: /* 10 */
return (&indent);
case 11: /* 11 */
return (§no);
case 12: /* 12 */
return (&pageno);
case 13: /* 13 */
return (&escape);
case 14: /* 14 */
return (&cap);
case 15: /* 15 */
return (&und);
case 16: /* 16 */
return (&capsh);
case 17: /* 17 */
return (&undsh);
case 18: /* 18 */
return (&capo);
case 19: /* 19 */
return (&undo);
case 20: /* 20 */
return (&capsho);
case 21: /* 21 */
return (&undsho);
case 22: /* 22 */
return (&invert);
case 23: /* 23 */
return (&ascii);
case 24: /* 24 */
return (&just);
case 25: /* 25 */
return (&mark);
case 26: /* 26 */
return (&start);
case 27: /* 27 */
return (&expsh);
case 28: /* 28 */
return (&subshb);
case 29: /* 29 */
return (&subshe);
}
}
// MAP
auto int *vmap (int i, int j)
{
switch (i)
{
case 31: /* 31 */
return (map (j));
case 32: /* 32 */
return (&tab (j));
case 33: /* 33 */
return (&tempa (j));
case 34: /* 34 */
return (&tempb (j));
}
}
// VMAP
}
// ASSIGN
}
// PROCESS DIRECTIVE
if (argc != 1) {
fprintf(stderr, "syntax: layout < file.lay > file.lis\n");
exit(1);
}
next = 0;
do
{
readatomordirective ();
if (directive != 0)
{
processdirective ();
if (next == nl)
printsourceline ();
}
else
{
if (xlines == 0)
{
if (size != 0)
{
placeatom ();
storesourceatom ();
}
else
{
if (next == nl)
printsourceline ();
}
}
else
{
if (size != 0)
{
placeatom ();
storesourceatom ();
}
if (next == ' ')
{
store (next);
buff (++cols) = ' ';
}
if (next == nl)
{
printdocline ();
printsourceline ();
}
}
}
if (next == ' ' || next == nl)
next = 0;
}
while (endind == 0);
}