home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / sit_shar / macbinfilt.c next >
C/C++ Source or Header  |  1991-05-20  |  4KB  |  167 lines

  1. /*
  2.  * macbinfilt -- filters usenet articles from comp.binaries.mac into a form
  3.  *  suitable for xbin to decode.  Will rearange parts of file if they are not
  4.  *  in order.  Strips out all extraneous lines.
  5.  *  Does all of this by making many bold assumtions--but it's worked so far.
  6.  *
  7.  *  Only works on one article at a time.  All files on the input line are
  8.  *  considered parts of the same article.
  9.  *
  10.  *  If you have the sysV regualar expression routines (regcmp, regex) then
  11.  *  define HAVE_REGCMP for a more robust pattern match.
  12.  *
  13.  *  --Tom Bereiter
  14.  *    ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
  15.  */
  16. #include <stdio.h>
  17.  
  18. int cur_part,part,divert_part;
  19. int max_part;
  20. #define IBUFSZ    512
  21. char ibuf[IBUFSZ];
  22. char pname[80];
  23. FILE *ofs=stdout;
  24. FILE *saveofs;
  25. FILE *parts[100];
  26.  
  27. #ifdef HAVE_REGCMP
  28. #define EXP ".*[Pp][Aa][Rr][Tt][ \t]*([0-9]+)$0[ \t]*[Oo][Ff][ \t]*([0-9]+)$1"
  29. #else
  30. #define EXP "part %d of %d"
  31. #endif
  32. char *exp;
  33.  
  34. main(argc,argv) char **argv[]; {
  35.     FILE *fs;
  36.     int i,rc=0;
  37.  
  38. #ifdef HAVE_REGCMP
  39.     exp = (char *)regcmp(EXP,0);
  40. #else
  41.     exp = EXP;
  42. #endif
  43.  
  44.     fputs("(This file must be converted with BinHex 4.0)\n\n",ofs);
  45.  
  46.     if (argc == 1)
  47.         filter(stdin);
  48.     else while (--argc) {
  49.         if ((fs=fopen(*++argv,"r"))==NULL) {
  50.             perror(*argv); exit(-1); }
  51.         filter(fs);
  52.         fclose(fs);
  53.     }
  54.     /* add any remaining parts */
  55.     for (i=cur_part+1; i<=max_part; i++)
  56.         if (parts[i])
  57.             putpart(i);
  58.         else {
  59.             fprintf(stderr,"Missing part %d\n",i);
  60.             rc = -1;
  61.         }
  62.     exit(rc);
  63. }
  64.  
  65. /* valid xbin chars + '\n' and '\r' */
  66. #define    Btst(i) (bmap[i>>3] & (1<<(i&07)))
  67. char bmap[]={0x00,0x24,0x00,0x00,0xfe,0x3f,0x7f,0x07,
  68.              0xff,0x7f,0x7f,0x0f,0x7f,0x3f,0x07,0x00};
  69.  
  70. /* filter out extraneous lines and look for lines of the form:
  71.  *    part n of m
  72.  * A line is considered valid if it has only valid xbin characters and is
  73.  * either greater than 60 characters or ends in a ':'
  74.  */
  75.  
  76. filter(fs) FILE *fs; {
  77.     register char *p,*inp;
  78.  
  79. reget:
  80.     while ((inp=fgets(ibuf,IBUFSZ,fs))) {
  81.         for (p=inp; *p; p++)
  82.             if (Btst(*p) == 0) {    /* invalid character */
  83.                 checkparts(inp);
  84.                 goto reget;
  85.             }
  86.         if (p-inp > 60 || inp[(p-inp)-2]==':')    /* arbitrary max or end */
  87.             fputs(ibuf,ofs);
  88.     }
  89.     if (divert_part)    /* diversion in progress */
  90.         end_oseq();
  91. }
  92.  
  93. checkparts(str) char *str; {
  94.     char *p;
  95.     char num0[40], num1[40];
  96.  
  97. #ifdef HAVE_REGEXP
  98.     if (regex(exp, str, num0,num1)!=NULL) {
  99.         part = atoi(num0);
  100.         max_part = atoi(num1);
  101. fprintf(stderr,"part %d of %d\n",part,max_part);
  102.         dopart();
  103.     }
  104. #else
  105.     for (p=str; *p; p++)    /* rescan for 'part' string */
  106.         if (*p==exp[0])
  107.             if (sscanf(p,exp,&part,&max_part) == 2) {
  108.                 dopart();
  109.                 break;
  110.             }
  111. #endif
  112. }
  113.  
  114. dopart() {
  115.     if (divert_part) {    /* diversion in progress */
  116.         if (part == divert_part)    /* another mention of current part */
  117.             return;
  118.         end_oseq();
  119.     }
  120.     if (part == cur_part+1)     /* OK: next in sequence */
  121.         cur_part = part;
  122.     else if (part > cur_part)     /* out of sequence */
  123.         oseq();
  124.     else     /* "can't" happen */
  125.         fprintf(stderr,"Part %d unexpected\n",part);
  126. }
  127.  
  128. /* part out of sequence */
  129. oseq() {
  130.     int i;
  131.  
  132.     /* try and fill in gap */
  133.     for (i=cur_part+1; i<part; i++)
  134.         if (parts[i]) {
  135.             putpart(i);
  136.             cur_part = i;
  137.         }
  138.         else goto isgap;
  139.     /* all missing parts restored -- continue */
  140.     return;
  141. isgap:
  142.     /* start diversion */
  143.     divert_part = part;
  144.     saveofs = ofs;
  145.     sprintf(pname,"part%d",part);
  146.     if ((ofs = fopen(pname,"w+")) == NULL) {
  147.         perror(pname); exit(-1); }
  148.     parts[part] = ofs;
  149. }
  150. end_oseq() {
  151.     divert_part = 0;
  152.     ofs = saveofs;
  153. }
  154.  
  155. putpart(n) {
  156.     FILE *fs;
  157.     register int c;
  158.  
  159.     fs = parts[n];
  160.     rewind(fs);
  161.     while ((c=getc(fs))!=EOF)
  162.         putc(c,ofs);
  163.     fclose(fs);
  164.     sprintf(pname,"part%d",n);
  165.     unlink(pname);
  166. }
  167.