home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / source / c / c11.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-07-18  |  12.5 KB  |  850 lines

  1. #
  2. /*
  3.  *  C compiler
  4.  */
  5.  
  6. #include "c1h.c"
  7.  
  8. max(a, b)
  9. {
  10.     if (a>b)
  11.         return(a);
  12.     return(b);
  13. }
  14.  
  15. degree(at)
  16. struct tnode *at;
  17. {
  18.     register struct tnode *t, *t1;
  19.  
  20.     if ((t=at)==0 || t->op==0)
  21.         return(0);
  22.     if (t->op == CON)
  23.         return(-3);
  24.     if (t->op == AMPER)
  25.         return(-2);
  26.     if (t->op==ITOL && (t1 = isconstant(t)) && t1->value>= 0)
  27.         return(-2);
  28.     if ((opdope[t->op] & LEAF) != 0) {
  29.         if (t->type==CHAR || t->type==FLOAT)
  30.             return(1);
  31.         return(0);
  32.     }
  33.     return(t->degree);
  34. }
  35.  
  36. pname(ap, flag)
  37. struct tnode *ap;
  38. {
  39.     register i;
  40.     register struct tnode *p;
  41.  
  42.     p = ap;
  43. loop:
  44.     switch(p->op) {
  45.  
  46.     case SFCON:
  47.     case CON:
  48.         printf("$");
  49.         psoct(p->value);
  50.         return;
  51.  
  52.     case FCON:
  53.         printf("L%d", p->value);
  54.         return;
  55.  
  56.     case NAME:
  57.         i = p->offset;
  58.         if (flag==2)
  59.             i =+ 2;
  60.         if (i) {
  61.             psoct(i);
  62.             if (p->class!=OFFS)
  63.                 putchar('+');
  64.             if (p->class==REG)
  65.                 regerr();
  66.         }
  67.         switch(p->class) {
  68.  
  69.         case SOFFS:
  70.         case XOFFS:
  71.             pbase(p);
  72.  
  73.         case OFFS:
  74.             printf("(r%d)", p->regno);
  75.             return;
  76.  
  77.         case EXTERN:
  78.         case STATIC:
  79.             pbase(p);
  80.             return;
  81.  
  82.         case REG:
  83.             printf("r%d", p->nloc);
  84.             return;
  85.  
  86.         }
  87.         error("Compiler error: pname");
  88.         return;
  89.  
  90.     case AMPER:
  91.         putchar('$');
  92.         p = p->tr1;
  93.         if (p->op==NAME && p->class==REG)
  94.             regerr();
  95.         goto loop;
  96.  
  97.     case AUTOI:
  98.         printf("(r%d)%c", p->nloc, flag==1?0:'+');
  99.         return;
  100.  
  101.     case AUTOD:
  102.         printf("%c(r%d)", flag==1?0:'-', p->nloc);
  103.         return;
  104.  
  105.     case STAR:
  106.         p = p->tr1;
  107.         putchar('*');
  108.         goto loop;
  109.  
  110.     }
  111.     error("pname called illegally");
  112. }
  113.  
  114. regerr()
  115. {
  116.     error("Illegal use of register");
  117. }
  118.  
  119. pbase(ap)
  120. struct tnode *ap;
  121. {
  122.     register struct tnode *p;
  123.  
  124.     p = ap;
  125.     if (p->class==SOFFS || p->class==STATIC)
  126.         printf("L%d", p->nloc);
  127.     else
  128.         printf("_%.8s", &(p->nloc));
  129. }
  130.  
  131. xdcalc(ap, nrleft)
  132. struct tnode *ap;
  133. {
  134.     register struct tnode *p;
  135.     register d;
  136.  
  137.     p = ap;
  138.     d = dcalc(p, nrleft);
  139.     if (d<20 && p->type==CHAR) {
  140.         if (nrleft>=1)
  141.             d = 20;
  142.         else
  143.             d = 24;
  144.     }
  145.     return(d);
  146. }
  147.  
  148. dcalc(ap, nrleft)
  149. struct tnode *ap;
  150. {
  151.     register struct tnode *p, *p1;
  152.  
  153.     if ((p=ap)==0)
  154.         return(0);
  155.     switch (p->op) {
  156.  
  157.     case NAME:
  158.         if (p->class==REG)
  159.             return(9);
  160.  
  161.     case AMPER:
  162.     case FCON:
  163.     case AUTOI:
  164.     case AUTOD:
  165.         return(12);
  166.  
  167.     case CON:
  168.     case SFCON:
  169.         if (p->value==0)
  170.             return(4);
  171.         if (p->value==1)
  172.             return(5);
  173.         if (p->value > 0)
  174.             return(8);
  175.         return(12);
  176.  
  177.     case STAR:
  178.         p1 = p->tr1;
  179.         if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD)
  180.             if (p->type!=LONG)
  181.                 return(12);
  182.     }
  183.     if (p->type==LONG)
  184.         nrleft--;
  185.     return(p->degree <= nrleft? 20: 24);
  186. }
  187.  
  188. notcompat(ap, ast, op)
  189. struct tnode *ap;
  190. {
  191.     register at, st;
  192.     register struct tnode *p;
  193.  
  194.     p = ap;
  195.     at = p->type;
  196.     st = ast;
  197.     if (st==0)        /* word, byte */
  198.         return(at>CHAR && at<PTR);
  199.     if (st==1)        /* word */
  200.         return(at>INT && at<PTR);
  201.     st =- 2;
  202.     if ((at&(~(TYPE+XTYPE))) != 0)
  203.         at = 020;
  204.     if ((at&(~TYPE)) != 0)
  205.         at = at&TYPE | 020;
  206.     if (st==FLOAT && at==DOUBLE)
  207.         at = FLOAT;
  208.     if (p->op==NAME && p->class==REG && op==ASSIGN && st==CHAR)
  209.         return(0);
  210.     return(st != at);
  211. }
  212.  
  213. prins(op, c, itable)
  214. struct instab *itable;
  215. {
  216.     register struct instab *insp;
  217.     register char *ip;
  218.  
  219.     for (insp=itable; insp->op != 0; insp++) {
  220.         if (insp->op == op) {
  221.             ip = c? insp->str2: insp->str1;
  222.             if (ip==0)
  223.                 break;
  224.             printf("%s", ip);
  225.             return;
  226.         }
  227.     }
  228.     error("No match' for op %d", op);
  229. }
  230.  
  231. collcon(ap)
  232. struct tnode *ap;
  233. {
  234.     register op;
  235.     register struct tnode *p;
  236.  
  237.     p = ap;
  238.     if (p->op==STAR)
  239.         p = p->tr1;
  240.     if (p->op==PLUS) {
  241.         op = p->tr2->op;
  242.         if (op==CON || op==AMPER)
  243.             return(1);
  244.     }
  245.     return(0);
  246. }
  247.  
  248. isfloat(at)
  249. struct tnode *at;
  250. {
  251.     register struct tnode *t;
  252.  
  253.     t = at;
  254.     if ((opdope[t->op]&RELAT)!=0)
  255.         t = t->tr1;
  256.     if (t->type==FLOAT || t->type==DOUBLE) {
  257.         nfloat = 1;
  258.         return('f');
  259.     }
  260.     return(0);
  261. }
  262.  
  263. oddreg(t, areg)
  264. struct tnode *t;
  265. {
  266.     register reg;
  267.  
  268.     reg = areg;
  269.     if (!isfloat(t))
  270.         switch(t->op) {
  271.         case DIVIDE:
  272.         case MOD:
  273.         case ASDIV:
  274.         case ASMOD:
  275.             reg++;
  276.  
  277.         case TIMES:
  278.         case ASTIMES:
  279.             return(reg|1);
  280.         }
  281.     return(reg);
  282. }
  283.  
  284. arlength(t)
  285. {
  286.     if (t>=PTR)
  287.         return(2);
  288.     switch(t) {
  289.  
  290.     case INT:
  291.     case CHAR:
  292.         return(2);
  293.  
  294.     case LONG:
  295.         return(4);
  296.  
  297.     case FLOAT:
  298.     case DOUBLE:
  299.         return(8);
  300.     }
  301.     return(1024);
  302. }
  303.  
  304. /*
  305.  * Strings for switch code.
  306.  */
  307.  
  308. char    dirsw[] {"\
  309. cmp    r0,$%o\n\
  310. jhi    L%d\n\
  311. asl    r0\n\
  312. jmp    *L%d(r0)\n\
  313. .data\n\
  314. L%d:\
  315. " };
  316.  
  317. char    simpsw[] {"\
  318. mov    $L%d,r1\n\
  319. mov    r0,L%d\n\
  320. L%d:cmp    r0,(r1)+\n\
  321. jne    L%d\n\
  322. jmp    *L%d-L%d(r1)\n\
  323. .data\n\
  324. L%d:\
  325. "};
  326.  
  327. char    hashsw[] {"\
  328. mov    r0,r1\n\
  329. clr    r0\n\
  330. div    $%o,r0\n\
  331. asl    r1\n\
  332. add    $L%d,r1\n\
  333. mov    r0,*(r1)+\n\
  334. mov    (r1)+,r1\n\
  335. L%d:cmp    r0,-(r1)\n\
  336. jne    L%d\n\
  337. jmp    *L%d-L%d(r1)\n\
  338. .data\n\
  339. L%d:\
  340. "};
  341.  
  342. pswitch(afp, alp, deflab)
  343. struct swtab *afp, *alp;
  344. {
  345.     int tlab, ncase, i, j, tabs, worst, best, range;
  346.     register struct swtab *swp, *fp, *lp;
  347.     int poctab[swsiz];
  348.  
  349.     fp = afp;
  350.     lp = alp;
  351.     if (fp==lp) {
  352.         printf("jbr    L%d\n", deflab);
  353.         return;
  354.     }
  355.     tlab = isn++;
  356.     if (sort(fp, lp))
  357.         return;
  358.     ncase = lp-fp;
  359.     lp--;
  360.     range = lp->swval - fp->swval;
  361.     /* direct switch */
  362.     if (range>0 && range <= 3*ncase) {
  363.         if (fp->swval)
  364.             printf("sub    $%o,r0\n", fp->swval);
  365.         printf(dirsw, range, deflab, isn, isn);
  366.         isn++;
  367.         for (i=fp->swval; i<=lp->swval; i++) {
  368.             if (i==fp->swval) {
  369.                 printf("L%d\n", fp->swlab);
  370.                 fp++;
  371.             } else
  372.                 printf("L%d\n", deflab);
  373.         }
  374.         goto esw;
  375.     }
  376.     /* simple switch */
  377.     if (ncase<8) {
  378.         i = isn++;
  379.         j = isn++;
  380.         printf(simpsw, i, j, isn, isn, j, i, i);
  381.         isn++;
  382.         for (; fp<=lp; fp++)
  383.             printf("%o\n", fp->swval);
  384.         printf("L%d:..\n", j);
  385.         for (fp = afp; fp<=lp; fp++)
  386.             printf("L%d\n", fp->swlab);
  387.         printf("L%d\n", deflab);
  388.         goto esw;
  389.     }
  390.     /* hash switch */
  391.     best = 077777;
  392.     for (i=ncase/4; i<=ncase/2; i++) {
  393.         for (j=0; j<i; j++)
  394.             poctab[j] = 0;
  395.         for (swp=fp; swp<=lp; swp++)
  396.             poctab[lrem(0, swp->swval, i)]++;
  397.         worst = 0;
  398.         for (j=0; j<i; j++)
  399.             if (poctab[j]>worst)
  400.                 worst = poctab[j];
  401.         if (i*worst < best) {
  402.             tabs = i;
  403.             best = i*worst;
  404.         }
  405.     }
  406.     i = isn++;
  407.     printf(hashsw, tabs, isn, i, i, isn+tabs+1, isn+1, isn);
  408.     isn++;
  409.     for (i=0; i<=tabs; i++)
  410.         printf("L%d\n", isn+i);
  411.     for (i=0; i<tabs; i++) {
  412.         printf("L%d:..\n", isn++);
  413.         for (swp=fp; swp<=lp; swp++)
  414.             if (lrem(0, swp->swval, tabs) == i)
  415.                 printf("%o\n", ldiv(0, swp->swval, tabs));
  416.     }
  417.     printf("L%d:", isn++);
  418.     for (i=0; i<tabs; i++) {
  419.         printf("L%d\n", deflab);
  420.         for (swp=fp; swp<=lp; swp++)
  421.             if (lrem(0, swp->swval, tabs) == i)
  422.                 printf("L%d\n", swp->swlab);
  423.     }
  424. esw:
  425.     printf(".text\n");
  426. }
  427.  
  428. sort(afp, alp)
  429. struct swtab *afp, *alp;
  430. {
  431.     register struct swtab *cp, *fp, *lp;
  432.     int intch, t;
  433.  
  434.     fp = afp;
  435.     lp = alp;
  436.     while (fp < --lp) {
  437.         intch = 0;
  438.         for (cp=fp; cp<lp; cp++) {
  439.             if (cp->swval == cp[1].swval) {
  440.                 error("Duplicate case (%d)", cp->swval);
  441.                 return(1);
  442.             }
  443.             if (cp->swval > cp[1].swval) {
  444.                 intch++;
  445.                 t = cp->swval;
  446.                 cp->swval = cp[1].swval;
  447.                 cp[1].swval = t;
  448.                 t = cp->swlab;
  449.                 cp->swlab = cp[1].swlab;
  450.                 cp[1].swlab = t;
  451.             }
  452.         }
  453.         if (intch==0)
  454.             break;
  455.     }
  456.     return(0);
  457. }
  458.  
  459. ispow2(atree)
  460. {
  461.     register int d;
  462.     register struct tnode *tree;
  463.  
  464.     tree = atree;
  465.     if (!isfloat(tree) && tree->tr2->op==CON) {
  466.         d = tree->tr2->value;
  467.         if (d>1 && (d&(d-1))==0)
  468.             return(d);
  469.     }
  470.     return(0);
  471. }
  472.  
  473. pow2(atree)
  474. struct tnode *atree;
  475. {
  476.     register int d, i;
  477.     register struct tnode *tree;
  478.  
  479.     tree = atree;
  480.     if (d = ispow2(tree)) {
  481.         for (i=0; (d=>>1)!=0; i++);
  482.         tree->tr2->value = i;
  483.         d = tree->op;
  484.         tree->op = d==TIMES? LSHIFT:
  485.               (d==DIVIDE? RSHIFT:
  486.               (d==ASTIMES? ASLSH: ASRSH));
  487.         tree = optim(tree);
  488.     }
  489.     return(tree);
  490. }
  491.  
  492. cbranch(atree, albl, cond, areg)
  493. struct tnode *atree;
  494. {
  495.     int l1, op;
  496.     register lbl, reg;
  497.     register struct tnode *tree;
  498.  
  499.     lbl = albl;
  500.     reg = areg;
  501.     if ((tree=atree)==0)
  502.         return;
  503.     switch(tree->op) {
  504.  
  505.     case LOGAND:
  506.         if (cond) {
  507.             cbranch(tree->tr1, l1=isn++, 0, reg);
  508.             cbranch(tree->tr2, lbl, 1, reg);
  509.             label(l1);
  510.         } else {
  511.             cbranch(tree->tr1, lbl, 0, reg);
  512.             cbranch(tree->tr2, lbl, 0, reg);
  513.         }
  514.         return;
  515.  
  516.     case LOGOR:
  517.         if (cond) {
  518.             cbranch(tree->tr1, lbl, 1, reg);
  519.             cbranch(tree->tr2, lbl, 1, reg);
  520.         } else {
  521.             cbranch(tree->tr1, l1=isn++, 1, reg);
  522.             cbranch(tree->tr2, lbl, 0, reg);
  523.             label(l1);
  524.         }
  525.         return;
  526.  
  527.     case EXCLA:
  528.         cbranch(tree->tr1, lbl, !cond, reg);
  529.         return;
  530.  
  531.     case COMMA:
  532.         rcexpr(tree->tr1, efftab, reg);
  533.         tree = tree->tr2;
  534.         break;
  535.     }
  536.     op = tree->op;
  537.     if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) {
  538.         if (tree->type!=LONG) {
  539.             tree->op = MINUS;
  540.             tree->type = LONG;
  541.             tree = optim(tree);
  542.         } else
  543.             op = NEQUAL;
  544.         rcexpr(tree, regtab, 0);
  545.         printf("ashc    $0,r0\n");
  546.         branch(lbl, op, !cond);
  547.         return;
  548.     }
  549.     rcexpr(tree, cctab, reg);
  550.     op = tree->op;
  551.     if ((opdope[op]&RELAT)==0)
  552.         op = NEQUAL;
  553.     else {
  554.         l1 = tree->tr2->op;
  555.          if ((l1==CON || l1==SFCON) && tree->tr2->value==0)
  556.             op =+ 200;        /* special for ptr tests */
  557.         else
  558.             op = maprel[op-EQUAL];
  559.     }
  560.     if (isfloat(tree))
  561.         printf("cfcc\n");
  562.     branch(lbl, op, !cond);
  563. }
  564.  
  565. branch(lbl, aop, c)
  566. {
  567.     register op;
  568.  
  569.     if(op=aop)
  570.         prins(op, c, branchtab);
  571.     else
  572.         printf("jbr");
  573.     printf("\tL%d\n", lbl);
  574. }
  575.  
  576. label(l)
  577. {
  578.     printf("L%d:", l);
  579. }
  580.  
  581. popstk(a)
  582. {
  583.     switch(a) {
  584.  
  585.     case 0:
  586.         return;
  587.  
  588.     case 2:
  589.         printf("tst    (sp)+\n");
  590.         return;
  591.  
  592.     case 4:
  593.         printf("cmp    (sp)+,(sp)+\n");
  594.         return;
  595.     }
  596.     printf("add    $%o,sp\n", a);
  597. }
  598.  
  599. error(s, p1, p2, p3, p4, p5, p6)
  600. {
  601.     register f;
  602.     extern fout;
  603.  
  604.     nerror++;
  605.     flush();
  606.     f = fout;
  607.     fout = 1;
  608.     printf("%d: ", line);
  609.     printf(s, p1, p2, p3, p4, p5, p6);
  610.     putchar('\n');
  611.     flush();
  612.     fout = f;
  613. }
  614.  
  615. psoct(an)
  616. {
  617.     register int n, sign;
  618.  
  619.     sign = 0;
  620.     if ((n = an) < 0) {
  621.         n = -n;
  622.         sign = '-';
  623.     }
  624.     printf("%c%o", sign, n);
  625. }
  626.  
  627. /*
  628.  * Read in an intermediate file.
  629.  */
  630. getree()
  631. {
  632.     struct tnode *expstack[20];
  633.     register struct tnode **sp;
  634.     register t, op;
  635.     static char s[9];
  636.     struct swtab *swp;
  637.  
  638.     spacep = treespace;
  639.     sp = expstack;
  640.     for (;;) {
  641.         if (sp >= &expstack[20])
  642.             error("Stack botch");
  643.         op = getw(ascbuf);
  644.         if ((op&0177400) != 0177000) {
  645.             error("Intermediate file error");
  646.             exit(1);
  647.         }
  648.         switch(op =& 0377) {
  649.  
  650.     case EOF:
  651.         return;
  652.  
  653.     case BDATA:
  654.         printf(".byte ");
  655.         seq(',');
  656.         break;
  657.  
  658.     case WDATA:
  659.         seq(';');
  660.         break;
  661.  
  662.     case PROG:
  663.         printf(".text\n");
  664.         break;
  665.  
  666.     case DATA:
  667.         printf(".data\n");
  668.         break;
  669.  
  670.     case BSS:
  671.         printf(".bss\n");
  672.         break;
  673.  
  674.     case SYMDEF:
  675.         printf(".globl    _%s\n", outname(s));
  676.         break;
  677.  
  678.     case RETRN:
  679.         printf("jmp    cret\n");
  680.         break;
  681.  
  682.     case CSPACE:
  683.         t = outname(s);
  684.         printf(".comm    _%s,%o\n", t, getw(ascbuf));
  685.         break;
  686.  
  687.     case SSPACE:
  688.         printf(".=.+%o\n", getw(ascbuf));
  689.         break;
  690.  
  691.     case EVEN:
  692.         printf(".even\n");
  693.         break;
  694.  
  695.     case SAVE:
  696.         printf("jsr    r5,csv\n");
  697.         t = getw(ascbuf)-6;
  698.         if (t==2)
  699.             printf("tst    -(sp)\n");
  700.         else if (t > 2)
  701.             printf("sub    $%o,sp\n", t);
  702.         break;
  703.  
  704.     case PROFIL:
  705.         t = getw(ascbuf);
  706.         printf("mov    $L%d,r0\njsr    pc,mcount\n", t);
  707.         printf(".bss\nL%d:.=.+2\n.text\n", t);
  708.         break;
  709.  
  710.     case SNAME:
  711.         t = outname(s);
  712.         printf("~%s=L%d\n", t, getw(ascbuf));
  713.         break;
  714.  
  715.     case ANAME:
  716.         t = outname(s);
  717.         printf("~%s=%o\n", t, getw(ascbuf));
  718.         break;
  719.  
  720.     case RNAME:
  721.         t = outname(s);
  722.         printf("~%s=r%d\n", t, getw(ascbuf));
  723.         break;
  724.  
  725.     case SWIT:
  726.         t = getw(ascbuf);
  727.         line = getw(ascbuf);
  728.         swp = treespace;
  729.         while (swp->swlab = getw(ascbuf)) {
  730.             swp->swval = getw(ascbuf);
  731.             swp++;
  732.         }
  733.         pswitch(treespace, swp, t);
  734.         break;
  735.  
  736.     case EXPR:
  737.         line = getw(ascbuf);
  738.         if (sp != &expstack[1]) {
  739.             error("Expression input botch\n");
  740.             exit(1);
  741.         }
  742.         nstack = 0;
  743.         rcexpr(optim(*--sp), efftab, 0);
  744.         spacep = treespace;
  745.         break;
  746.  
  747.     case NAME:
  748.         t = getw(ascbuf);
  749.         if (t==EXTERN) {
  750.             t = getw(ascbuf);
  751.             *sp = block(6, NAME, t, 0, EXTERN, 0, 0,0,0,0);
  752.             outname(&(*sp)->nloc);
  753.             sp++;
  754.             break;
  755.         }
  756.         *sp = block(3, NAME, 0, 0, t, 0, 0);
  757.         (*sp)->type = getw(ascbuf);
  758.         (*sp)->nloc = getw(ascbuf);
  759.         sp++;
  760.         break;
  761.  
  762.     case CON:
  763.     case SFCON:
  764.     case FCON:
  765.         t = getw(ascbuf);
  766.         *sp++ = block(1, op, t, 0, getw(ascbuf));
  767.         break;
  768.  
  769.     case FSEL:
  770.         t = getw(ascbuf);
  771.         sp[-1] = block(2, op, t, 0, sp[-1], getw(ascbuf));
  772.         break;
  773.  
  774.     case NULL:
  775.         *sp++ = block(0, 0, 0, 0);
  776.         break;
  777.  
  778.     case CBRANCH:
  779.         t = getw(ascbuf);
  780.         sp[-1] = block(1, CBRANCH, sp[-1], t, getw(ascbuf));
  781.         break;
  782.  
  783.     case LABEL:
  784.         label(getw(ascbuf));
  785.         break;
  786.  
  787.     case NLABEL:
  788.         printf("_%s:\n", outname(s));
  789.         break;
  790.  
  791.     case RLABEL:
  792.         t = outname(s);
  793.         printf("_%s:\n~~%s:\n", t, t);
  794.         break;
  795.  
  796.     case BRANCH:
  797.         branch(getw(ascbuf), 0);
  798.         break;
  799.  
  800.     case SETREG:
  801.         nreg = getw(ascbuf)-1;
  802.         break;
  803.  
  804.     default:
  805.         if (opdope[op]&BINARY) {
  806.             if (sp < &expstack[1]) {
  807.                 error("Binary expression botch");
  808.                 exit(1);
  809.             }
  810.             t = *--sp;
  811.             *sp++ = block(2, op, getw(ascbuf), 0, *--sp, t);
  812.         } else {
  813.             sp[-1] = block(1, op, getw(ascbuf), 0, sp[-1]);
  814.         }
  815.         break;
  816.     }
  817.     }
  818. }
  819.  
  820. outname(s)
  821. {
  822.     register char *p, c;
  823.     register n;
  824.  
  825.     p = s;
  826.     n = 0;
  827.     while (c = getc(ascbuf)) {
  828.         *p++ = c;
  829.         n++;
  830.     }
  831.     while (n++ < 8)
  832.         *p++ = 0;
  833.     return(s);
  834. }
  835.  
  836. seq(c)
  837. {
  838.     register o;
  839.  
  840.     if (getw(ascbuf) == 0)
  841.         return;
  842.     for (;;) {
  843.         printf("%o", getw(ascbuf));
  844.         if ((o = getw(ascbuf)) != 1)
  845.             break;
  846.         printf("%c", c);
  847.     }
  848.     printf("\n");
  849. }
  850.