home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / forum4.lzh / SPRACHEN / C / ROFF / roff.c next >
C/C++ Source or Header  |  1988-01-11  |  22KB  |  1,233 lines

  1. /*
  2.  *
  3.  *        roff - C version.
  4.  *      the Colonel.  19 May 1983.
  5.  *
  6.  *        fix by Tim Maroney, 31 Dec 1984.
  7.  *        .hc implemented, 8 Feb 1985.
  8.  *        fix to hyhenating with underlining, 12 Feb 1985.
  9.  *        fixes to long-line hang and .bp by Dave Tutelman, 30 May 1985.
  10.  *
  11.  *        adapted to OS-9/68k by Uwe Simon 17 July 1987.
  12.  *      .sh implemented, 20 Nov 1987.
  13.  *        -c option implemented, 7 Jan 1987.
  14.  *        \(xx  specialcharacters impelmented, (no underline) 8 Jan 1987.
  15.  *      printermodes impelmeted  11 Jan 1987 
  16.  */
  17.  
  18.  
  19. #include <signal.h>
  20. #include <stdio.h>
  21.  
  22.  
  23. /*  Printmode = (underl:doublepr:kursiv:subsk:supersk:inv:0:0) */
  24. #define undl_on 0x80
  25. #define undl_of 0x7f
  26. #define doub_on 0x40
  27. #define doub_of 0xbf
  28. #define kurs_on 0x20
  29. #define kurs_of 0xdf
  30. #define subsc   0x10
  31. #define supersc 0x08
  32. #define normal  0xe7
  33. #define inv_on  0x40
  34. #define inv_of  0xfb
  35.  
  36. /* Gepard OS-9 Druckersteuerkodes */
  37. #define pr_normal  0x91
  38. #define pr_super   0x90
  39. #define pr_sub     0x8f
  40. #define pr_kurson  0x94
  41. #define pr_kursof  0x95
  42. #define pr_undl_on 0x15
  43. #define pr_undl_of 0x14
  44. #define pr_doub_on 0x12
  45. #define pr_doub_of 0x11
  46. #define pr_inv_on  0x0e
  47. #define pr_inv_of  0x0f
  48.  
  49.  
  50. #define TXTLEN (o_pl-o_m1-o_m2-o_m3-o_m4-2)
  51. #define IDTLEN (o_ti>=0?o_ti:o_in)
  52. #define MAXMAC 64
  53. #define MAXDEPTH 10
  54. #define MAXLENGTH 255
  55. #define UNDERL    '\000'
  56. #define TAB_CONT "tab_of_cont"
  57.  
  58. char spacechars[] = " \t\n";
  59. int sflag, hflag,startpage,stoppage,inhalt;
  60. char holdword[MAXLENGTH],holdattr[MAXLENGTH], *holdp, *holdattrp;
  61. char assyline[MAXLENGTH],assyattr[MAXLENGTH];
  62. int assylen;
  63. char ehead[100],efoot[100],ohead[100],ofoot[100],title[100];
  64. struct macrotype {
  65.     char mname[3];
  66.     long int moff;
  67.     
  68. } macro[MAXMAC];
  69. int n_macros;
  70. int depth;
  71. int adjtoggle;
  72. int isrequest=0;
  73. char o_tr[40][2];
  74. int o_cc='.';
  75. int o_hc=-1;
  76. int o_tc=' ';
  77. int o_in=0;
  78. int o_ix=-1;
  79. int o_ta[20] = {
  80.     9,17,25,33,41,49,57,65,73,81,89,97,105,
  81.     133,121,129,137,145,153,161};
  82. int n_ta=20;
  83. int o_ll=65, o_ad=1,o_po=0,o_ls=1,o_ig=0,o_fi=1;
  84. int o_pl=66,o_ro=0,o_hx=0,o_bl=0,o_sp=0,o_sk=0;
  85. int o_ce=0,o_m1=2,o_m2=2,o_m3=1,o_m4=3,o_ul=0;
  86. int o_li=0,o_n1=0,o_n2=0,o_bp=-1,o_hy=1;
  87. int o_ni=1;
  88. int o_nn=0;
  89. int o_ti=-1;
  90. int center=0;
  91. int page_no=-1;
  92. int line_no=9999;
  93. int n_outwords;
  94. FILE *File,*Macread,*Macwrite;
  95. FILE *Save,*Inh;
  96. long int teller[MAXDEPTH],ftell();
  97. char *strcat(),*strcpy(),*strend(),*strhas();
  98. char *sprintf();
  99. int o_pa[]={0,0,0,0,0,0};
  100. char *request[] ={
  101.     "ad","ar","bl","bp","br","cc","ce","de",
  102.     "ds","ef","eh","fi","fo","hc","he","hx","hy","ig",
  103.     "in","ix","li","ll","ls","m1","m2","m3","m4",
  104.     "n1","n2","na","ne","nf","ni","nn","nx","of","oh",
  105.     "pa","pl","po","ro","sh","sk","sp","ss","ta","tc","ti",
  106.     "tr","ul",0};
  107.                     /* Definition der Makros fuer erweiterten Zeichensatz */
  108.                     /* wird nur bei 7-Bit Terminal gebraucht !!           */
  109.                     /* \(xx  ist der Aufruf fuer Zeichen xx               */
  110. char *spec_char[] ={
  111.         "","","","","","","","","","co",   /* 160-169 */
  112.         "","","","","rg","","","+-","ua","da",   /* 170-179 */
  113.         "->","","","<-","","","","","","",   /* 180-189 */
  114.         "","","","","","","Ae","","AE","",   /* 190-199 */
  115.         "","","FA","EX","ib","mo","cu","nm","","",   /* 200-209 */
  116.         "nu","sm","NE","ca","Oe","","","","","",   /* 210-219 */
  117.         "Ue","","","ss","","","","","ae","",   /* 220-229 */
  118.         "","","","","","","","","","",   /* 230-239 */
  119.         "","","","","","","oe","","","",   /* 240-249 */
  120.         "","","ue","","",""                /* 250-255 */
  121.     };
  122. char *mktemp(),*mfilnam="/r0/TMP/rtmXXXXXX";
  123. int c;
  124.  
  125. main(argc,argv)
  126. int argc;
  127. char **argv;
  128. {
  129.   inhalt=0;
  130.   while (--argc) switch(**++argv) {
  131.       case '+':
  132.                startpage=atoi(++*argv);
  133.                break;
  134.       case '-':
  135.                ++*argv;
  136.                if(isdigit(**argv)) stoppage=atoi(*argv);
  137.                else switch(toupper(**argv)) {
  138.                 case 'C':
  139.                         inhalt++;
  140.                 case 'S':
  141.                             sflag++;
  142.                             break;
  143.                   case 'H':
  144.                            hflag++;
  145.                            break;
  146.                   default :
  147.                            bomb();
  148.               }
  149.               break;
  150.       default :
  151.               argc++;
  152.               goto endargs;
  153.     }    
  154. endargs:
  155.     mesg(0);
  156.     assylen=0;
  157.     assyline[0]='\0';
  158.     if(inhalt) {
  159.         if((Inh=fopen(TAB_CONT,"w"))==NULL) {
  160.             inhalt=0;
  161.             fprintf(stderr,"can't open %s\n",TAB_CONT);
  162.         }
  163.     }
  164.     if(!argc) {
  165.         File=stdin;
  166.         readfile();
  167.     }
  168.     else while(--argc) {
  169.         File=fopen(*argv,"r");
  170.         if(NULL==(int)File) {
  171.             fprintf(stderr,"roff: cannot read %s\n",*argv);
  172.             exit(1);
  173.         }
  174.         readfile();
  175.         fclose(File);
  176.         argv++;
  177.     }
  178.     writebreak();
  179.     endpage();
  180.     for(;o_sk;o_sk--) blankpage();
  181.     if(inhalt) {
  182.         fclose(Inh);
  183.     }
  184.     mesg(1);    
  185. }
  186.     
  187.  
  188. mesg(f)
  189. int f;
  190. {
  191.     
  192. }
  193.  
  194. readfile(){
  195.     while(readline()) {
  196.         if(isrequest) continue;
  197.         if(center||!o_fi) {
  198.             if(assylen) writeline(0,1);
  199.             else blankline();
  200.         }
  201.     }
  202. }
  203.  
  204. readline()
  205. {
  206.       int startline,doingword;
  207.       isrequest=0;
  208.       startline=1;
  209.       doingword=0;
  210.       c=suck();
  211.       if (c=='\n') {
  212.           o_sp=1;
  213.           writebreak();
  214.           goto out;
  215.       }
  216.       else if (isspace(c)) writebreak();
  217.       for(;;) {
  218.           if(c==EOF) {
  219.               if(doingword) bumpword();
  220.               break;
  221.           }
  222.           if(c!=o_cc&&o_ig){
  223.               while(c!='\n' && c!=EOF) c=suck();
  224.               break;
  225.           }
  226.           if(isspace(c) && !doingword) {
  227.               startline=0;
  228.               switch(c) {
  229.                   case ' ':
  230.                           assyline[assylen++]=' ';
  231.                           break;
  232.                   case '\t':
  233.                           tabulate();
  234.                           break;
  235.                   case '\n':
  236.                           goto out;
  237.            }
  238.            c=suck();
  239.            continue;
  240.         }
  241.         if(isspace(c)&&doingword) {
  242.             bumpword();
  243.             if(c=='\t') tabulate();
  244.             else if(assylen) assyline[assylen++]=' ';
  245.             doingword=0;
  246.             if(c=='\n') break;
  247.         }
  248.         if(!isspace(c)) {
  249.             if(doingword) *holdp++=o_ul?c|UNDERL:c;
  250.             else if(startline&&c==o_cc&&!o_li) {
  251.                 isrequest=1;
  252.                 return readreq();
  253.             }
  254.             else {
  255.                 doingword=1;
  256.                 holdp=holdword;
  257.                 *holdp++=o_ul?c|UNDERL:c;
  258.             }
  259.         }
  260.         startline=0;
  261.         c=suck();
  262.     }
  263. out:
  264.     if(o_ul) o_ul--;
  265.     center=o_ce;
  266.     if(o_ce) o_ce--;
  267.     if(o_li)o_li--;
  268.     return c!=EOF;
  269. }
  270.  
  271. bumpword()
  272. {
  273.     char *hc;
  274.     *holdp='\0';
  275.     if(!o_fi) goto giveup;
  276.     if(assylen+reallen(holdword)>o_ll-IDTLEN) {
  277.         if(!o_hy) writeline(o_ad,0);
  278.         else while(assylen+reallen(holdword)>o_ll-IDTLEN) {
  279.             if(o_hc&&strhas(holdword,o_hc)) {
  280.                 for (hc=strend(holdword); hc>=holdword;hc--) {
  281.                     if ((*hc&~UNDERL)!=o_hc) continue;
  282.                     *hc='\0';
  283.                     if(assylen+reallen(holdword)+1> o_ll-IDTLEN) {
  284.                         *hc=o_hc;
  285.                         continue;
  286.                     }
  287.                     dehyph(holdword);
  288.                     strcpy(&assyline[assylen],holdword);
  289.                     strcat(assyline,"-");
  290.                     assylen+=strlen(holdword)+1;
  291.                     strcpy(holdword,++hc);
  292.                     break;
  293.                 }
  294.                 writeline(o_ad,0);
  295.                 if(hc<holdword) goto giveup;
  296.             }
  297.             else {
  298.                 writeline(o_ad,0);
  299.                 goto giveup;
  300.             }
  301.         }
  302.     }
  303. giveup:
  304.     if(o_hc) dehyph(holdword);
  305.     strcpy(&assyline[assylen],holdword);
  306.     assylen+=strlen(holdword);
  307.     holdp=holdword;
  308. }
  309.     
  310.  
  311. dehyph(s)
  312. char *s;
  313. {
  314.     char *t;
  315.     for(t=s;*s;s++) if((*s&~UNDERL)!=o_hc) *t++=*s;
  316.     *t='\0';
  317. }
  318.  
  319. int reallen(s)
  320. char *s;
  321. {
  322.     register n;
  323.     n=0;
  324.     while(*s) n+=(o_hc!=(~UNDERL&*s++));
  325.     return(n);
  326. }
  327.  
  328. tabulate()
  329. {
  330.     int j;
  331.     for(j=0;j<n_ta;j++) if(o_ta[j]-1>assylen+IDTLEN) {
  332.         for(;assylen+IDTLEN<o_ta[j]-1;assylen++) assyline[assylen]=o_tc;
  333.         return;
  334.     }
  335.     assyline[assylen++]=o_tc;
  336. }
  337.  
  338. int readreq()
  339. {
  340.     char req[3];
  341.     int r,s;
  342.     if(skipsp()) return c!=EOF;
  343.     c=suck(c);
  344.     if(c==EOF||c=='\n') return c!=EOF;
  345.     if(c=='.') {
  346.         o_ig=0;
  347.         do(c=suck());
  348.         while(c!=EOF&& c!='\n');
  349.         if(depth) endmac();
  350.         return c!=EOF;
  351.     }
  352.     if(o_ig) {
  353.         while(c!=EOF&&c!='\n') c=suck();
  354.         return c!=EOF;
  355.     }
  356.     req[0]=c;
  357.     c=suck();
  358.     if(c==EOF||c=='\n') req[1]='\0';
  359.     else req[1]=c;
  360.     req[2]='\0';
  361.     for(r=0;r<n_macros;r++) if(!strcmp(macro[r].mname,req)) {
  362.         submac(r);
  363.         goto reqflsh;
  364.     }
  365.     for(r=0;request[r];r++) if(!strcmp(request[r],req)) break;
  366.     if(!request[r]) {
  367.         do(c=suck());
  368.         while(c!=EOF&&c!='\n');
  369.         return c!=EOF;
  370.     }
  371.     switch(r) {
  372.         case 0:   /*  ad */
  373.                   o_ad=1;
  374.                   writebreak();
  375.                   break;
  376.         case 1:  /*  ar */
  377.                   o_ro=0; break;
  378.         case 2:  /*  bl */
  379.                   nread(&o_bl);
  380.                   writebreak();
  381.                   break;
  382.         case 3:  /*  bp */
  383.         case 37: /*  pa */
  384.                   c=snread(&r,&s,1);
  385.                   if(s>0) o_bp=page_no+r;
  386.                   else if(s<0) o_bp=page_no-r;
  387.                   else o_bp=r;
  388.                   writebreak();
  389.                   if(line_no) {
  390.                     endpage();
  391.                     beginpage();
  392.                 }
  393.                 break;
  394.         case 4:  /*  br */
  395.                 writebreak();
  396.                 break;
  397.         case 5:  /* cc */
  398.                 c=cread(&o_cc);
  399.                 break;
  400.         case 6:  /* ce */
  401.                 nread(&o_ce);
  402.                 writebreak();
  403.                 break;
  404.         case 7:  /* de */
  405.                 defmac();
  406.                 break;
  407.         case 8:  /*  ds */
  408.                 o_ls=2;
  409.                 writebreak();
  410.                 break;
  411.         case 9:  /*  ef */
  412.                 c=tread(efoot);
  413.                 break;
  414.         case 10: /*  eh */
  415.                 c=tread(ehead);
  416.                 break;
  417.         case 11: /*  fi */
  418.                 o_fi=1;
  419.                 writebreak();
  420.                 break;
  421.         case 12: /*  fo */
  422.                 c=tread(efoot);
  423.                 strcpy(ofoot,efoot);
  424.                 break;
  425.         case 13: /*  hc */
  426.                 c=cread(&o_hc);
  427.                 break;
  428.         case 14: /*  he */
  429.                 c=tread(ehead);
  430.                 strcpy(ohead,ehead);
  431.                 break;
  432.         case 15: /*  hx */
  433.                 o_hx=1;
  434.                 break;
  435.         case 16: /*  hy */
  436.                 nread(&o_hy);
  437.                 break;
  438.         case 17: /*  ig */
  439.                 o_ig=1;
  440.                 break;
  441.         case 18: /*  in */
  442.                 writebreak();
  443.                 snset(&o_in);
  444.                 o_ix=-1;
  445.                 break;
  446.         case 19: /*  ix */
  447.                 snset(&o_ix);
  448.                 if(!n_outwords) o_in=o_ix;
  449.                 break;
  450.         case 20: /*  li */
  451.                 nread(&o_li);
  452.                 break;
  453.         case 21: /*  ll */
  454.                 snset(&o_ll);
  455.                 break;
  456.         case 22: /*  ls */
  457.                 snset(&o_ls);
  458.                 break;
  459.         case 23: /*  m1 */
  460.                 nread(&o_m1);
  461.                 break;
  462.         case 24: /*  m2 */
  463.                 nread(&o_m2);
  464.                 break;
  465.         case 25: /*  m3 */
  466.                 nread(&o_m3);
  467.                 break;
  468.         case 26: /*  m4 */
  469.                 nread(&o_m4);
  470.                 break;
  471.         case 27: /*  n1 */
  472.                 o_n1=1;
  473.                 break;
  474.         case 28: /*  n2 */
  475.                 nread(&o_n2);
  476.                 break;
  477.         case 29: /*  na */
  478.                 o_ad=0;
  479.                 writebreak();
  480.                 break;
  481.         case 30: /*  ne */
  482.                 nread(&r);
  483.                 if(line_no+(r-1)*o_ls+1>TXTLEN) {
  484.                     writebreak();
  485.                     endpage();
  486.                     beginpage();
  487.                 }
  488.                 break;
  489.         case 31: /*  nf */
  490.                 o_fi=0;
  491.                 writebreak();
  492.                 break;
  493.         case 32: /*  ni */
  494.                 snset(&o_ni);
  495.                 break;
  496.         case 33: /*  nn */
  497.                 snset(&o_nn);
  498.                 break;
  499.         case 34: /*  nx */
  500.                 do_nx();
  501.                 c='\n';
  502.                 break;
  503.         case 35: /*  of */
  504.                 c=tread(ofoot);
  505.                 break;
  506.         case 36: /*  oh */
  507.                 c=tread(ohead);
  508.                 break;
  509.         case 38: /*  pl */
  510.                 snset(&o_pl);
  511.                 break;
  512.         case 39: /*  po */
  513.                 snset(&o_po);
  514.                 break;
  515.         case 40: /*  ro */
  516.                 o_ro=1;
  517.                 break;
  518.         case 41: /*  sh */ {
  519.                     int sh,i;
  520.                     char st[100];
  521.                        nread(&sh);
  522.                        if(sh) {
  523.                            c=tread(title);
  524.                         writebreak();
  525.                         for(i=sh;i<=5;i++) o_pa[i]=0;
  526.                            o_pa[sh-1]++;
  527.                            assyline[0]='\0';
  528.                            for(i=0;i<sh;i++) {
  529.                                sprintf(st,"%d.",o_pa[i]);
  530.                                strcat(assyline,st);
  531.                            }
  532.                            strcat(assyline,"  ");
  533.                            strcat(assyline,title);
  534.                            assylen=strlen(assyline);
  535.                            if(inhalt) {    /* ins Inhaltsverzeichnis eintragen */
  536.                                fprintf(Inh,"%s :%d\n",assyline,page_no);
  537.                            }
  538.                     }
  539.                     else {
  540.                         for(i=0;i<=5;i++) o_pa[i]=0;
  541.                     }
  542.                        break;
  543.                    }
  544.         case 42: /*  sk */
  545.                 nread(&o_sk);
  546.                 break;
  547.         case 43: /*  sp */
  548.                 nread(&o_sp);
  549.                 writebreak();
  550.                 break;
  551.         case 44: /* ss */
  552.                 writebreak();
  553.                 o_ls=1;
  554.                 break;
  555.         case 45: /*  ta */
  556.                 do_ta();
  557.                 break;
  558.         case 46: /*  tc */
  559.                 c=cread(&o_tc);
  560.                 break;
  561.         case 47: /*  ti */
  562.                 writebreak();
  563.                 c=snread(&r,&s,0);
  564.                 if(s>0) o_ti=o_in+r;
  565.                 else if(s<0) o_ti=o_in-r;
  566.                 else o_ti=r;
  567.                 break;
  568.         case 48: /*  tr */
  569.                 do_tr();
  570.                 break;
  571.         case 49: /*  ul */
  572.                 nread(&o_ul);
  573.                 break;
  574.     }
  575. reqflsh:
  576.     while(c!=EOF&&c!='\n') c=suck();
  577.     return c!=EOF;
  578. }    
  579.                 
  580. snset(par)
  581. int *par;
  582. {
  583.     int r,s;
  584.     c=snread(&r,&s,0);
  585.     if(s>0) *par+=r;
  586.     else if(s<0) *par-=r;
  587.     else *par=r;
  588. }
  589.  
  590. tread(s)
  591. char *s;
  592. {
  593.     int leadbl;
  594.     leadbl=0;
  595.     for(;;) {
  596.         c=suck();
  597.         if(c==' '&&!leadbl) continue;
  598.         if(c==EOF||c=='\n') {
  599.             *s='\0';
  600.             return c;
  601.         }
  602.         *s++=c;
  603.         leadbl++;
  604.     }
  605. }
  606.  
  607. nread(i)
  608. int *i;
  609. {
  610.     int f;
  611.     f=0;
  612.     *i=0;
  613.     if(!skipsp()) for(;;) {
  614.         c=suck();
  615.         if(c==EOF) break;
  616.         if(isspace(c)) break;
  617.         if(isdigit(c)) {
  618.             f++;
  619.             *i=*i*10+c-'0';
  620.         }
  621.         else break;
  622.     }
  623.     if(!f) *i=1;
  624. }
  625.  
  626. int snread(i,s,sdef)
  627. int *i,*s,sdef;
  628. {
  629.     int f;
  630.     f=*i=*s=0;
  631.     for(;;) {
  632.         c=suck();
  633.         if(c==EOF||c=='\n') break;
  634.         if(isspace(c)) {
  635.             if(f) break;
  636.             else continue;
  637.         }
  638.         if(isdigit(c)) {
  639.             f++;
  640.             *i=*i*10+c-'0';
  641.         }
  642.         else if((c=='+'||c=='-')&&!f) {
  643.             f++;
  644.             *s=c=='+'?1:-1;
  645.         }
  646.         else break;
  647.     }
  648.     while(c!=EOF&&c!='\n') c=suck();
  649.     if(!f) {
  650.         *i=1;
  651.         *s=sdef;
  652.     }
  653.     return c;
  654. }
  655.  
  656. int cread(k)
  657. int *k;
  658. {
  659.     int u;
  660.     *k=-1;
  661.     for(;;) {
  662.         u=suck();
  663.         if(u==EOF||u=='\n') return u;
  664.         if(isspace(u)) continue;
  665.         if(*k<0) *k=u;
  666.     }
  667. }
  668.  
  669. defmac()
  670. {
  671.     int i;
  672.     char newmac[3], *nm;
  673.     if(skipsp()) return;
  674.     nm=newmac;
  675.     if(!Macwrite) openmac();
  676.     *nm++=suck();
  677.     c=suck();
  678.     if(c!=EOF&&c!='\n'&&c!=' '&&c!='\t') *nm++=c;
  679.     *nm='\0';
  680.     for(i=0;i<n_macros;i++) if(!strcmp(newmac,macro[i].mname)) {
  681.         macro[i].mname[0]='\0';
  682.         break;
  683.     }
  684.     macro[n_macros].moff=ftell(Macwrite);
  685.     strcpy(macro[n_macros++].mname,newmac);
  686.     while(c!=EOF&&c!='\n') c=suck();
  687.     while (copyline());
  688.     fflush(Macwrite);
  689. }
  690.  
  691. openmac()
  692. {
  693.     if(NULL==(int)(Macwrite=fopen(mktemp(mfilnam),'w'))) {
  694.         fprintf(stderr,"roff : cannot open temp file\n");
  695.         exit(1);
  696.     }
  697.     Macread=fopen(mfilnam,'r');
  698.     unlink(mfilnam);
  699. }
  700.  
  701. int copyline()
  702. {
  703.     int n,first,second;
  704.     if(c==EOF) {
  705.         fprintf(Macwrite,"..\n");
  706.         return 0;
  707.     }
  708.     n=0;
  709.     first=1;
  710.     second=0;
  711.     for(;;) {
  712.         c=suck();
  713.         if(c==EOF) {
  714.             if(!first) putc('\n',Macwrite);
  715.             return(0);
  716.         }
  717.         if(c=='\n') {
  718.             putc('\n',Macwrite);
  719.             return n!=2;
  720.         }
  721.         if(first&&c=='.') n++;
  722.         else if(second &&n==1&&c=='.') n++;
  723.         putc(c,Macwrite);
  724.         second=first;
  725.         first=0;
  726.     }
  727. }
  728.  
  729. submac(r)
  730. int r;
  731. {
  732.     while(c!=EOF&&c!='\n') c=suck();
  733.     if(depth) teller[depth-1]=ftell(Macwrite);
  734.     else {
  735.         Save=File;
  736.         File=Macread;
  737.     }
  738.     depth++;
  739.     fseek(Macread,macro[r].moff,0);
  740. }
  741.  
  742. endmac()
  743. {
  744.     depth--;
  745.     if(depth) fseek(Macread,teller[depth-1],0);
  746.     else File=Save;
  747.     c='\n';
  748. }
  749.  
  750. do_ta()
  751. {
  752.     int v;
  753.     n_ta=0;
  754.     for(;;) {
  755.         nread(&v);
  756.         if(v==1) return;
  757.         else o_ta[n_ta++]=v;
  758.         if(c=='\n'||c==EOF) break;
  759.     }
  760. }
  761.  
  762. do_tr()
  763. {
  764.     char *t;
  765.     t=&o_tr[0][0];
  766.     *t='\0';
  767.     if(skipsp()) return;
  768.     for(;;) {
  769.         c=suck();
  770.         if(c==EOF||c=='\n') break;
  771.         *t++=c;
  772.     }
  773.     *t='\0';
  774. }
  775.  
  776. do_nx()
  777. {
  778.     char fname[100],*f;
  779.     f=fname;
  780.     if(skipsp()) return;
  781.     for(;;) switch(c=suck()) {
  782.         case EOF:
  783.         case '\n':
  784.         case ' ' :
  785.         case '\t':
  786.             if(f==fname) return;
  787.             goto got_nx;
  788.         default:
  789.             *f++=c;
  790.     }
  791. got_nx:
  792.     fclose(File);
  793.     *f='\0';
  794.     if(!(File=fopen(fname,"r"))) {
  795.         fprintf(stderr,"roff: cannot read %s\n",fname);
  796.         exit(1);
  797.     }
  798. }
  799.  
  800. int skipsp()
  801. {
  802.     for(;;) switch(c=suck()) {
  803.         case EOF:
  804.         case '\n':
  805.             return 1;
  806.         case ' ':
  807.         case '\t':
  808.             continue;
  809.         default:
  810.             ungetc(c,File);
  811.             return 0;
  812.     }
  813. }
  814.  
  815. writebreak()
  816. {
  817.     int q;
  818.     if(assylen) writeline(0,1);
  819.     q=TXTLEN;
  820.     if(o_bl) {
  821.         if(o_bl+line_no>q) {
  822.             endpage();
  823.             beginpage();
  824.         }
  825.         for(;o_bl;o_bl--) blankline();
  826.     }
  827.     else if(o_sp) {
  828.         if(o_sp+line_no>q) newpage();
  829.         else if(line_no) for(;o_sp;o_sp--) blankline();
  830.     }
  831. }
  832.  
  833. blankline()
  834. {
  835.     if(line_no>=TXTLEN) newpage();
  836.     if(o_n2) o_n2++;
  837.     spit('\n');
  838.     line_no++;
  839. }
  840.  
  841. writeline(adflag,flushflag)
  842. int adflag,flushflag;
  843. {
  844.     int j,q;
  845.     char lnstring[7];
  846.     for(j=assylen-1;j;j--) {
  847.         if(assyline[j]==' ') assylen--;
  848.         else break;
  849.     }
  850.     q=TXTLEN;
  851.     if(line_no>=q) newpage();
  852.     for(j=0;j<o_po;j++) spit(' ');
  853.     if(o_n1) {
  854.         if(o_nn) for(j=0;j<o_ni+4;j++) spit(' ');
  855.         else {
  856.             for(j=0;j<o_ni;j++) spit(' ');
  857.             sprintf(lnstring,"%3d ",line_no+1);
  858.             spits(lnstring);
  859.         }
  860.     }
  861.     if(o_n2) {
  862.         if(o_nn) for(j=0;j<o_ni;j++) spit(' ');
  863.         else {
  864.             for(j=0;j<o_ni;j++) spit(' ');
  865.             sprintf(lnstring,"%3d ",o_n2++);
  866.             spits(lnstring);
  867.         }
  868.     }
  869.     if(o_nn) o_nn--;
  870.     if(center) for(j=0;j<(o_ll-assylen+1)/2;j++) spit(' ');
  871.     else for(j=0;j<IDTLEN;j++) spit(' ');
  872.     if(adflag&&!flushflag)fillline();
  873.     for(j=0;j<assylen;j++) spit(assyline[j]);
  874.     spit('\n');
  875.     assylen=0;
  876.     assyline[0]='\0';
  877.     line_no++;
  878.     for(j=1;j<o_ls;j++) if(line_no<=q) blankline();
  879.     if(!flushflag) {
  880.         if(o_hc) dehyph(holdword);
  881.         strcpy(assyline,holdword);
  882.         assylen=strlen(holdword);
  883.         *holdword='\0';
  884.         holdp=holdword;
  885.     }
  886.     if(o_ix>=0) o_in=o_ix;
  887.     o_ix=o_ti= -1;
  888. }
  889.  
  890. fillline()
  891. {
  892.     int excess,j,s,inc,spaces;
  893.     adjtoggle^=1;
  894.     if(!(excess=o_ll-IDTLEN-assylen)) return;
  895.     if(excess<0) {
  896.         fprintf(stderr,"roff: internal error #2 [%d]\n",excess);
  897.         exit(1);
  898.     }
  899.     for(j=2;j<256;j++) {
  900.         if(adjtoggle) {
  901.             s=0;
  902.             inc=1;
  903.         }
  904.         else {
  905.             s=assylen-1;
  906.             inc= -1;
  907.         }
  908.         spaces=0;
  909.         while(s>=0&&s<assylen) {
  910.             if(assyline[s]==' ') spaces++;
  911.             else {
  912.                 if(0<spaces && spaces<j) {
  913.                     insrt(s-inc);
  914.                     if(inc>0) s++;
  915.                     if(!--excess) return;
  916.                 }
  917.                 spaces=0;
  918.             }
  919.             s+=inc;
  920.         }
  921.     }
  922. }
  923.  
  924. insrt(p)
  925. int p;
  926. {
  927.     int i;
  928.     for(i=assylen;i>p;i--) assyline[i]=assyline[i-1];
  929.     assylen++;
  930. }
  931.  
  932.  
  933. newpage()
  934. {
  935.     if(page_no>=0) endpage();
  936.     else page_no=1;
  937.     for(;o_sk;o_sk--) blankpage();
  938.     beginpage();
  939. }
  940.  
  941. beginpage()
  942. {
  943.     int i;
  944.     for(i=0;i<o_m1;i++) spit('\n');
  945.     writetitle(page_no&1? ohead:ehead);
  946.     for(i=0;i<o_m2;i++) spit('\n');
  947.     line_no=0;
  948. }
  949.  
  950. endpage()
  951. {
  952.     int i;
  953.     for(i=line_no;i<TXTLEN;i++) blankline();
  954.     for(i=0;i<o_m3;i++) spit('\n');
  955.     writetitle(page_no&1? ofoot:efoot);
  956.     for(i=0;i<o_m4;i++) spit('\n');
  957.     if(o_bp<0) page_no++;
  958.     else {
  959.         page_no=o_bp;
  960.         o_bp= -1;
  961.     }
  962. }
  963.  
  964. blankpage()
  965. {
  966.     int i;
  967.     for(i=0;i<o_m1;i++) spit('\n');
  968.     writetitle(page_no&1?ohead:ehead);
  969.     for(i=0;i<o_m2;i++) spit('\n');
  970.     for(i=0;i<TXTLEN;i++) spit('\n');
  971.     for(i=0;i<o_m3;i++) spit('\n');
  972.     writetitle(page_no&1?ofoot:efoot);
  973.     page_no++;
  974.     for(i=0;i<o_m4;i++) spit('\n');
  975.     line_no=0;
  976. }
  977.  
  978. nix()
  979. {}
  980.  
  981. writetitle(t)
  982. char *t;
  983. {
  984.     char d,*pst,*pgform();
  985.     int j,l,m,n;
  986.     d=*t;
  987.     if(o_hx||!d) {
  988.         spit('\n');
  989.         return;
  990.     }
  991.     pst=pgform();
  992.     for(j=0;j<o_po;j++) spit(' ');
  993.     l=titlen(++t,d,strlen(pst));
  994.     while(*t&&*t!=d) {
  995.         if(*t=='%') spits(pst);
  996.         else spit(*t);
  997.         t++;
  998.     }
  999.     if(!*t) {
  1000.         spit('\n');
  1001.         return;
  1002.     }
  1003.     m=titlen(++t,d,strlen(pst));
  1004.     for(j=1;j<(o_ll-m)/2;j++) spit(' ');
  1005.     while(*t&&*t!=d) {
  1006.         if(*t=='%') spits(pst);
  1007.         else spit(*t);
  1008.         t++;
  1009.     }
  1010.     if(!*t) {
  1011.         spit('\n');
  1012.         return;
  1013.     }
  1014.     if((o_ll-m)/2>1) m+=(o_ll-m)/2;
  1015.     else m+=1;
  1016.     n=titlen(++t,d,strlen(pst));
  1017.     for(j=m;j<o_ll-n;j++) spit(' ');
  1018.     while(*t&&*t!=d) {
  1019.         if(*t=='%') spits(pst);
  1020.         else spit(*t);
  1021.         t++;
  1022.     }
  1023.     spit('\n');
  1024. }
  1025.  
  1026. char *pgform()
  1027. {
  1028.     static char pst[11];
  1029.     int i;
  1030.     if(o_ro) {
  1031.         *pst='\0';
  1032.         i=page_no;
  1033.         if (i>=400) {
  1034.             strcat(pst,"cd");
  1035.             i-=400;
  1036.         }
  1037.         while(i>=100) {
  1038.             strcat(pst,"c");
  1039.             i-=100;
  1040.         }
  1041.         if(i>=90) {
  1042.             strcat(pst,"xc");
  1043.             i-=90;
  1044.         }
  1045.         if(i>=50) {
  1046.             strcat(pst,"l");
  1047.             i-=50;
  1048.         }
  1049.         if(i>=40) {
  1050.             strcat(pst,"xl");
  1051.             i-=40;
  1052.         }
  1053.         while(i>=10) {
  1054.             strcat(pst,"x");
  1055.             i-=10;
  1056.         }
  1057.         if(i>9) {
  1058.             strcat(pst,"ix");
  1059.             i-=9;
  1060.         }
  1061.         if(i>=5) {
  1062.             strcat(pst,"v");
  1063.             i-=5;
  1064.         }
  1065.         if(i>=4) {
  1066.             strcat(pst,"iv");
  1067.             i-=4;
  1068.         }
  1069.         while (i--) strcat(pst,"i");
  1070.     }
  1071.     else sprintf(pst,"%d",page_no);
  1072.     return pst;
  1073. }
  1074.  
  1075.  
  1076.     
  1077. int titlen(t,c,k)
  1078. char *t,c;
  1079. int k;
  1080. {
  1081.     int q;
  1082.     q=0;
  1083.     while(*t&&*t!=c) q+=*t++=='%'?k:1;
  1084.     return q;
  1085. }
  1086.  
  1087. spits(s)
  1088. char *s;
  1089. {
  1090.     while(*s) spit(*s++);
  1091. }
  1092.  
  1093. spit(c)
  1094. char c;
  1095. {
  1096.     static int col_no,n_blanks;
  1097.     int ulflag;
  1098.     char *t;
  1099.     ulflag=c&UNDERL;
  1100.     c&=~UNDERL;
  1101.     for(t=(char *)o_tr; *t;t++ ) if(*t++==c) {
  1102.         c=*t?*t:' ';
  1103.         break;
  1104.     }
  1105.     if(page_no<startpage||(stoppage&&page_no>stoppage)) return;
  1106.     if(c!=' '&&c!='\n'&&n_blanks) {
  1107.         if(hflag&&n_blanks>1)
  1108.         while(col_no/8<(col_no+n_blanks)/8) {
  1109.             putc('\t',stdout);
  1110.             n_blanks-=8-(col_no&07);
  1111.             col_no=8+col_no&~07;
  1112.         }
  1113.         for(;n_blanks;n_blanks--) {
  1114.             putc(' ',stdout);
  1115.             col_no++;
  1116.         }
  1117.     }
  1118.     if(ulflag&&isalnum(c)) fputs("_\b",stdout);
  1119.     if(c==' ') n_blanks++;
  1120.     else {
  1121.         putc(c,stdout);
  1122.         col_no++;
  1123.     }
  1124.     if(c=='\n') {
  1125.         col_no=0;
  1126.         n_blanks=0;
  1127.     }
  1128. }
  1129.  
  1130. int suck()
  1131. {
  1132.     for(;;) {
  1133.         if((c=getc(File))=='\\') {
  1134.             if((c=getc(File))=='(') {  /* jetzt ist es ein Sonderzeichen */
  1135.                 if((c=spchar())==0) {  /* Sonderzeichen nicht bekannt    */
  1136.                     fprintf(stderr,"unknown special-char\n");
  1137.                     c='@';
  1138.                 } else
  1139.                     return(c);
  1140.                     
  1141.             }
  1142.             else {
  1143.                 ungetc(c,File);       /* letztes Zeichen zurueckstellen */
  1144.                 c='\\';               /* '\' zurueckgeben */
  1145.             }
  1146.         }
  1147.         if(islegal(c)) return(c);
  1148.     }
  1149. }
  1150.  
  1151.  
  1152. int spchar()       /* holt Sonderzeichen */
  1153. {
  1154.     char s[3],c;
  1155.     s[2]='\0';
  1156.     s[0]=getc(File);
  1157.     s[1]=getc(File);
  1158.     for(c=0;c<96;c++)
  1159.         if(strcmp(s,spec_char[c])==0) return(c+160);
  1160.     return(0);    /* unbekanntes Sonderzeichen */
  1161. }
  1162.  
  1163.  
  1164. char *strhas (p,c)
  1165. char *p,c;
  1166. {
  1167.     for(;*p;p++) if((*p&~UNDERL)==c) return p;
  1168.     return NULL;
  1169. }
  1170.  
  1171. char *strend(p)
  1172. char *p;
  1173. {
  1174.     while(*p++);
  1175.     return p;
  1176. }
  1177.  
  1178.  
  1179. /* hier werden neue Functionen isspace isalnum isspecial benutzt */
  1180. /* sollen nur Character unter $7F benutzt werden, so kann statt  */
  1181. /* dessen <ctype.h> benutzt werden */
  1182.  
  1183.  
  1184. int isspace(c)
  1185. int c;
  1186. {
  1187.     char *s;
  1188.     for(s=spacechars;*s;s++) if(*s==c) return(1);
  1189.     return(0);
  1190. }
  1191.  
  1192.  
  1193. int isspecial(c)
  1194. int c;
  1195. {
  1196.     return(c>160);
  1197. }
  1198.  
  1199.  
  1200. int isdigit(c)
  1201. int c;
  1202. {
  1203.     return(c>='0' &&c<='9');
  1204. }
  1205.  
  1206.  
  1207. int isalnum(c)
  1208. int c;
  1209. {
  1210.     return((c>='A'&&c<='Z') || (c>='a' && c<='z') || isdigit(c) || isspecial(c));
  1211. }
  1212.  
  1213.  
  1214. int islegal(c)
  1215. int c;
  1216. {
  1217.     return c>=' '&&c<='~'||isspace(c)||c=='\n'||c==EOF;
  1218. }
  1219.  
  1220. bomb()
  1221. {
  1222.     fprintf(stderr,"Syntax: roff {[+00] [-00] [-s] -[h] file}\n");
  1223.     fprintf(stderr,"Function: format textfiles\n");
  1224.     fprintf(stderr,"Options:\n");
  1225.     fprintf(stderr,"     +00       start at page 00\n");
  1226.     fprintf(stderr,"     -00       end at page 00\n");
  1227.     fprintf(stderr,"     -c        print tabel of contents\n");
  1228.     fprintf(stderr,"     -s        ????\n");
  1229.     fprintf(stderr,"     -h        use hardtabs\n");
  1230.     exit(1);
  1231. }
  1232.  
  1233.