#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); }