home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 304_01 / roff53.c < prev    next >
Text File  |  1990-02-14  |  11KB  |  378 lines

  1. /********************************************************/
  2. /*         ROFF5, Version 2.00            */
  3. /*    (c) 1983,4,8,9 by Ernest E. Bergmann        */
  4. /*    730 Seneca Street, Bethlehem, Pa. 18015        */
  5. /*                            */
  6. /* Permission is hereby granted for all commercial and    */
  7. /* non-commercial reproduction and distribution of this    */
  8. /* material provided this notice is included.        */
  9. /********************************************************/
  10. #include <roff5.h>
  11. #include <string.h>
  12. #if (VERSION!=2) || (subVERSION!=00)
  13. #error ***************This is version 2.00******************
  14. #endif
  15. /**************************/
  16. void exitm(char *msg)
  17. {fprintf(stderr,msg);
  18.  exit(1);
  19. }
  20. /***************************************************/
  21. /* regist() returns pointer to integer variable.   */
  22. /* It searches RLIST; creates new entry if needed; */
  23. /***************************************************/
  24. int *regist(char *s)
  25. {ENTRY *pe;
  26. int *pw;
  27. FORMAT *pf;
  28. char *pc,*s2;
  29. unsigned siz; ENTRY *where;
  30. char buff[64];
  31. pc=find2(s,&RLINK);
  32. if(pc != NULL) return((int *)pc); /*else create new entry*/
  33. pe=(ENTRY *)buff;
  34. pe->link=RLINK.link;
  35. pc=(char *)&(pe->ident);
  36. s2=s;
  37. transfer(&s2,&pc,'\0');
  38. pw=(int *)pc;
  39. *pw=REGDEF;
  40. siz = (int)pw - (int)buff + sizeof(int) + sizeof(FORMAT);
  41. if (NULL==(where=(ENTRY *)malloc(siz))) exitm("regist(): cannot malloc\n");
  42. RLINK.link = (ENTRY *)memcpy(where,buff,siz);
  43. pc = (char *)RLINK.link + siz;
  44. pf = (FORMAT *)pc - 1;
  45. pw = (int *)pf - 1;
  46. /* writing default FORMAT */
  47. pf->fill = ' ';
  48. pf->typ  = ' ';
  49. pf->minwidth=1;
  50. return(pw);
  51. }
  52. /****************************************/
  53. void dovar()    /*process .NR request*/
  54. {char typ, wbuf[MAXLINE], *lptr;
  55. int val, *pw;
  56. gwLIN(wbuf);
  57. skip_blanks();
  58. val=get_val2(LIN,&typ,&lptr);
  59. gwLIN(wbuf);
  60. if(wbuf[0]==NUMSIGN && wbuf[1]=='\0')
  61.     {set(&NEWPAG,val,typ,NEWPAG,1,30000);
  62.     }
  63. else    {pw=regist(wbuf);
  64.     set(pw,val,typ,REGDEF,0,30000);
  65.     }
  66. }
  67. /****************************************/
  68. void source()
  69. {char name[FNAMSIZ];
  70. gwLIN(name);
  71. if(gwLIN(name)!=WE_HAVE_A_WORD)
  72.     {fprintf(stderr,".SO has no name\n");
  73.     return;
  74.     }
  75. strupr(name);
  76. if(FPTR<FMAX)
  77.     {FSTACK[FPTR].IFP=ifp;
  78.      FSTACK[FPTR].nlines=INPUTlns;
  79.      INPUTlns=0;
  80.      /* need to save pbbuf ptr*/
  81.      FSTACK[FPTR].binp=BINP;
  82.      FSTACK[FPTR].backbuf=BACKBUF;
  83.      FSTACK[FPTR].bbsiz=BBSIZ;
  84.      BBSIZ-=BINP;
  85.      BACKBUF+=BINP;
  86.      BINP=0;
  87.      strcpy(FSTACK[++FPTR].FNAME,name);
  88.     }
  89. else exitm("source(): FSTACK overflow\n");
  90. if( (ifp=fopen(name,"r")) != ERROR ) return;
  91.     /*else*/
  92.     fprintf(stderr,"Can't open <%s>\n",name);
  93. endso();
  94. }
  95. /****************************************/
  96. void showr()    /*lists register names and contents*/
  97. {int *pr;
  98. FORMAT *pf;
  99. ENTRY *pe;
  100. char *pc;
  101. fprintf(stderr,"REGISTERS and <values> and [format]:\n");
  102. pf = &PAGFMT;
  103. fprintf(stderr,"#   <%d>  [%c%c %d]\n",
  104.         NEWPAG,pf->fill,pf->typ,pf->minwidth);
  105. pe=RLINK.link;
  106. while(pe)
  107.     {pc=(char *)&(pe->ident);
  108.     fprintf(stderr,"%s ",pc);
  109.     pr=(int *)(pc+1+strlen(pc));
  110.     pf=(FORMAT *)(pr+1);
  111.     fprintf(stderr,"<%d>  [%c%c %d]\n",
  112.             *pr,pf->fill,pf->typ,pf->minwidth);
  113.     pe = pe->link;
  114.     }
  115. dashes();
  116. }
  117. /****************************************/
  118. void assignfmt()
  119. {char *pc, wbuf[MAXLINE];
  120.  int *pw;
  121.  gwLIN(wbuf);
  122.  skip_blanks();
  123.  gwLIN(wbuf);
  124.  skip_blanks();
  125.  if(LIN[0]=='"') pc = strtok(&LIN[1],"\"");
  126.  else pc = strtok(&LIN[0]," \t\n");
  127.  if (wbuf[0]==NUMSIGN && wbuf[1]=='\0') picfmt(pc,&PAGFMT);
  128.  else    {pw = regist(wbuf);
  129.       picfmt(pc,(FORMAT *)(pw+1));
  130.      }
  131. }
  132. /********************************************/
  133. /* picfmt() converts the string it receives */
  134. /* into a FORMAT describing the min width   */
  135. /* and format type and fill character;  For */
  136. /* example, ".......1" would be in arabic   */
  137. /* with width at least 8, left filled with  */
  138. /* '.';  "i" whould be lowercase roman at   */
  139. /* least one character wide; "   A" would   */
  140. /* be lettered: 0,A,B..,Z,AA,AB,..AZ,BA,    */
  141. /* right justified in field of width 4      */
  142. /********************************************/
  143. FORMAT *picfmt(char *string, FORMAT *pf)
  144. {if ((*string) < ' ') return (NULL);
  145.  pf->minwidth = strlen(string);
  146.  pf->typ = *strpbrk(string,"AaIi");
  147.  if (pf->typ == '\0') pf->typ = '1';
  148.  pf->fill = *string;
  149.  return ( pf ) ;
  150. }
  151. /****************************************/
  152. void endso()    /*called upon EOF to return to previous input file*/
  153. {if(FPTR)
  154.     {close(ifp);
  155.     ifp=FSTACK[--FPTR].IFP;
  156.     INPUTlns=FSTACK[FPTR].nlines;
  157.     /*need to handle pbbuf*/
  158.     BBSIZ=FSTACK[FPTR].bbsiz;
  159.     BACKBUF=FSTACK[FPTR].backbuf;
  160.     BINP=FSTACK[FPTR].binp;
  161.     LIN=fgets3();
  162.     }
  163. else BINP=0;
  164. }
  165. /****************************************/
  166. void dashes()
  167. {fprintf(stderr,"-----------\n");
  168. }
  169. /****************************************/
  170. void ignore()    /*handle .ig request*/
  171. {int i; char C1, C2;  ARGs a;
  172.  i = process(&a);
  173.  if (i==0) return; /*no arg so ignore current line*/
  174.  C1 = a.arg[1][0]; C2 = a.arg[1][1];
  175.  while(fgets3())    /*until EOF or MSDOSEOF*/
  176.     if(*LIN==COMMAND)
  177.     if(LIN[1]==C1)
  178.     if(!C2 || (LIN[2]==C2) )  return; /*found match to 1st 2 letters*/
  179. }
  180. /************************************/
  181. /* detab() checks OUTBUF2 for tabs, */
  182. /* soh; it not found does nothing.  */
  183. /* else it replaces tabs with .tc   */
  184. /* and it replaces ^a,^A with .lc   */
  185. /************************************/
  186. void detab()
  187. {char ch;
  188.  int p1,p2,p3;
  189.  int BP3;
  190.  char OUTBUF3[LSZ]; /* temp needed to expand tabs, etc.*/
  191.  /*prescan for tabs, soh to save time, effort*/
  192.  int tabs;
  193.  tabs=CP=BPOS=0;
  194.  while('\0'!=(ch=OUTBUF2[BPOS]))
  195.   {if(ch=='\t')   tabs=YES;
  196.    if(ch=='\001') tabs=YES;
  197.    if(ch==CFVAL[0])
  198.     {ch=OUTBUF2[BPOS+1];
  199.      if((ch=='t')||(ch=='T'))
  200.         {tabs=YES; ch='\t'; BPOS++;}
  201.      else if((ch=='a')||(ch=='A'))
  202.         {tabs=YES; ch='\001'; BPOS++;}
  203.      else ch=OUTBUF2[BPOS];
  204.     }
  205.    OUTBUF2[CP++]=ch;
  206.    BPOS++;
  207.   }
  208.  OUTBUF2[CP]='\0';
  209.  if(!tabs) return;
  210.  /* below is the processing needed to expand tabs, soh */
  211.  BP3=CP=BPOS=0;
  212.  while('\0'!=(ch=OUTBUF2[BPOS]))
  213.   {switch(class(ch))
  214.    {case TRANSLATE: OUTBUF3[BP3++]=ch;OUTBUF3[BP3++]=OUTBUF2[++BPOS];
  215.             CP++; break;
  216.     case BLACK:
  217.     case WHITE:     OUTBUF3[BP3++]=ch;
  218.             CP++; break;
  219.     case CONTROL:   OUTBUF3[BP3++]=ch;ch=OUTBUF2[++BPOS];
  220.             switch(ch)
  221.             {case 'h':
  222.              case 'H': if (CP) CP--;OUTBUF3[BP3++]=ch;break;
  223.              case '(': p1=CP;OUTBUF3[BP3++]=ch;break;
  224.              case ')': CP=p1;OUTBUF3[BP3++]=ch;break;
  225.              case '[': p2=CP;OUTBUF3[BP3++]=ch;break;
  226.              case ']': CP=p2;OUTBUF3[BP3++]=ch;break;
  227.              case '{': p3=CP;OUTBUF3[BP3++]=ch;break;
  228.              case '}': CP=p3;OUTBUF3[BP3++]=ch;break;
  229.              default:/*?,ignore*/;break;
  230.             } break;
  231.     case HTAB:       {int cp2,newCP;
  232.             cp2=CP;
  233.             do cp2++; while(RULER[cp2]=='-');
  234.             if (RULER[cp2]=='l') newCP=cp2;
  235.             else   {char tc,bc,bc2; int W,D;
  236.                 tc=RULER[cp2];
  237.                 D=cp2-CP;W=0;
  238.                 if((tc=='.')||(tc==','))
  239.                 while((bc=OUTBUF2[BPOS+1+W])!=0)
  240.                   {if (bc==tc) break;
  241.                    if (bc=='\t') break;
  242.                    if (bc=='\001') break;
  243.                    W++;
  244.                   }
  245.                 else while((bc=OUTBUF2[BPOS+1+W])!=0)
  246.                   {if (bc=='\t') break;
  247.                    if (bc=='\001') break;
  248.                    W++;
  249.                   }
  250.                 /* now W,D are known */
  251.                 if((tc=='r')||(tc=='R')) newCP=CP+D-W+1;
  252.                 else if((tc=='.')||(tc==',')) newCP=CP+D-W ;
  253.                 else if (tc=='c') newCP=CP+D-(W/2);
  254.                }
  255.             while(CP<newCP)
  256.                {OUTBUF3[BP3++]=TCVAL;
  257.                 CP++;
  258.                }
  259.            } break;
  260.     case SOH:       {int cp2,newCP;
  261.             cp2=CP;
  262.             do cp2++; while(RULER[cp2]=='-');
  263.             if (RULER[cp2]=='l') newCP=cp2;
  264.             else   {char tc,bc,bc2; int W,D;
  265.                 tc=RULER[cp2];
  266.                 D=cp2-CP;W=0;
  267.                 if((tc=='.')||(tc==','))
  268.                 while((bc=OUTBUF2[BPOS+1+W])!=0)
  269.                   {if (bc==tc) break;
  270.                    if (bc=='\t') break;
  271.                    if (bc=='\001') break;
  272.                    W++;
  273.                   }
  274.                 else while((bc=OUTBUF2[BPOS+1+W])!=0)
  275.                   {if (bc=='\t') break;
  276.                    if (bc=='\001') break;
  277.                    W++;
  278.                   }
  279.                 /* now W,D are known */
  280.                 if((tc=='r')||(tc=='R')) newCP=CP+D-W+1;
  281.                 else if((tc=='.')||(tc==',')) newCP=CP+D-W ;
  282.                 else if (tc=='c') newCP=CP+D-(W/2);
  283.                }
  284.             while(CP<newCP)
  285.                {OUTBUF3[BP3++]=LCVAL;
  286.                 CP++;
  287.                }
  288.            } break;
  289.     case OTHERS:   fprintf(stderr,"\nweird character value: %o\n",ch);
  290.            break;
  291.    }
  292.    BPOS++;
  293.   }
  294.  OUTBUF3[BP3]='\0';
  295.  strcpy(OUTBUF2,OUTBUF3);
  296. }
  297. /**********************************************/
  298. /* to handle predefined (read only) registers */
  299. /**********************************************/
  300. int readonly(char *wbuf) /*used by fgets3();returns TRUE if predefined*/
  301. {if(wbuf[1]=='\0')    /*length 1*/
  302.     {int pnum;
  303.      if(*wbuf!=NUMSIGN) return(FALSE);
  304.         {if((VLINENO>=PLVAL[0])
  305.             ||(VLINENO<0)) pnum=NEWPAG;
  306.          else pnum=CURPAG;
  307.          itoC(pnum,wbuf,PAGFMT);
  308.          pbstr(wbuf);
  309.          return(TRUE);
  310.         }
  311.      }
  312.  else if(wbuf[2]=='\0')    /*length 2*/
  313.     {int reg;
  314.      if(*wbuf=='d')
  315.         {if(wbuf[1]=='l') reg=DWIDTH;
  316.          else if(wbuf[1]=='n') reg=DLINES;
  317.          else return(FALSE);
  318.         }
  319.      else if(*wbuf=='n')
  320.         {if(wbuf[1]=='l') reg=PLINENO;
  321.          else return(FALSE);
  322.         }
  323.      else if(*wbuf=='l')
  324.         {if(wbuf[1]=='n') reg=LN;
  325.          else return(FALSE);
  326.         }
  327.      else if(*wbuf=='.')
  328.         switch(wbuf[1])
  329.         {case 'c': reg=INPUTlns; break;
  330.          case 'd': if(DIVERTING) reg=DLINES;
  331.                else reg=PLINENO;
  332.                break;
  333.          case 'i': reg=INVAL;    break;
  334.          case 'j': if(JUSTIFY)reg=DOTJ;
  335.                else reg=0; break;
  336.          case 'l': reg=RMVAL-INVAL; break;
  337.          case 'n': exitm("/.n/not yet implemented");
  338.          case 'o': reg=dotO;    break;
  339.          case 'p': reg=PLVAL[0]; break;
  340.          case 't': if(DIVERTING)
  341.                {reg=-1;
  342.                 if((Dstats->dtname[0]) && (Dstats->dt>0))
  343.                 reg=(Dstats->dt)-DLINES;
  344.                 if(reg<0) reg=HUGE;
  345.                }
  346.                else reg=dotT(VLINENO);
  347.                break;
  348.          case 'u': reg=FILL;    break;
  349.          case 'x': reg=VERSION; break;
  350.          case 'y': reg=subVERSION; break;
  351.          case 'z': pbstr(DNAME); return(TRUE);
  352.          case 'F': pbstr(FSTACK[FPTR].FNAME); return(TRUE);
  353.          case 'L': reg=LSVAL[0]; break;
  354.          default : return(FALSE);
  355.         }
  356.      else return(FALSE);
  357.      itoa(reg,wbuf,10);
  358.      pbstr(wbuf);
  359.      return(TRUE);
  360.     }
  361.  else if(wbuf[3]=='\0') /*length 3*/
  362.     {int reg;
  363.      if((wbuf[0]=='.')&&(wbuf[1]=='m'))
  364.        switch(wbuf[2])
  365.        {case '1': reg=M1VAL[0]; break;
  366.         case '2': reg=M2VAL[0]; break;
  367.         case '3': reg=M3VAL[0]; break;
  368.         case '4': reg=M4VAL[0]; break;
  369.         default:  return(FALSE);
  370.        }
  371.      else return(FALSE);
  372.      itoa(reg,wbuf,10);
  373.      pbstr(wbuf);
  374.      return(TRUE);
  375.     }
  376.  return(FALSE);
  377. }
  378.