home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / unix-utils / xusq.c < prev   
C/C++ Source or Header  |  2000-06-09  |  7KB  |  298 lines

  1. static char *sccsid = "@(#)usq.c        1.7u (UCF) 82/12/15";
  2. /*
  3.  *     usq.c - CP/M compatible file unsqueezer utility
  4.  *
  5.  *    compile as follows:
  6.  *    cc [-DVAX] -O usq.c -o usq
  7.  *       (define VAX only if running on VAX)
  8.  */
  9.  
  10. #define VAX 1
  11.  
  12. #include <stdio.h>
  13. #include <signal.h>
  14. #include <ctype.h>
  15.  
  16. #define TRUE 1
  17. #define FALSE 0
  18. #define ERROR (-1)
  19. #define PATHLEN    312    /* Number of characters allowed in pathname */
  20. #define OK 0
  21.  
  22. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  23. #define DLE 0x90        /* repeat byte flag */
  24. #define SPEOF 256        /* special endfile token */
  25. #define NUMVALS 257        /* 256 data values plus SPEOF*/
  26. #define LARGE 30000
  27.  
  28. #ifdef VAX   /* then we don't want 32 bit integers */
  29.  
  30. typedef short INT;
  31. typedef unsigned short UNSIGNED;
  32.  
  33. #else   /*  16 bit machines  */
  34.  
  35. typedef int INT;
  36. typedef unsigned UNSIGNED;
  37.  
  38. #endif
  39.  
  40. struct _sqleaf {        /* Decoding tree */
  41.     INT _children[2];    /* left, right */
  42. };
  43. struct _sqleaf Dnode[NUMVALS - 1];
  44.  
  45.  
  46. INT Bpos;        /* last bit position read */
  47. INT Curin;        /* last byte value read */
  48. INT Repct;        /* Number of times to return value */
  49. INT Value;        /* current byte value or EOF */
  50.  
  51. INT MakeLCPathname=TRUE;    /* translate pathname to lc if all caps */
  52. INT Nlmode=FALSE;        /* zap cr's if true */
  53. INT Inbackground = FALSE;
  54.  
  55. INT getcr(), getuhuff(), portgetw();
  56.  
  57. main(argc, argv)
  58. char *argv[];
  59. {
  60.     register char *cp;
  61.     register INT npats=0;
  62.     char **patts;
  63.     INT n, errorstat;
  64.  
  65.     if (signal(SIGINT, SIG_IGN)==SIG_IGN)
  66.         Inbackground++;
  67.     else
  68.         signal(SIGINT, SIG_DFL);
  69.     signal(SIGHUP, SIG_IGN);
  70.     errorstat=0;
  71.     if(argc<2)
  72.         goto usage;
  73.     while (--argc) {
  74.         cp = *++argv;
  75.         if(*cp == '-') {
  76.             while( *++cp) {
  77.                 switch(*cp) {
  78.                 case 'n':
  79.                     Nlmode=TRUE; break;
  80.                 case 'u':
  81.                     MakeLCPathname=FALSE; break;
  82.                 default:
  83.                     goto usage;
  84.                 }
  85.             }
  86.         }
  87.         else if( !npats && argc>0) {
  88.             if(argv[0][0]) {
  89.                 npats=argc;
  90.                 patts=argv;
  91.             }
  92.         }
  93.     }
  94.     if(npats < 1) {
  95. usage:
  96.         fprintf(stderr,"Usage: usq [-nu] file ...\n");
  97.         fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
  98.         fprintf(stderr,"\t-u preserve Uppercase pathnames\n");
  99.         exit(1);
  100.     }
  101.     for(n=0; n<npats; ++n)
  102.         errorstat |= squeeze(patts[n]);
  103.     exit(errorstat != 0);
  104. }
  105.  
  106. /*
  107.     The following code is primarily from typesq.c and utr.c.  Typesq
  108. is a modification of USQ by Dick Greenlaw.  Those modifications (usq
  109. to typesq) were made by Bob Mathias, I am responsible for the butchery
  110. done to make it work with cat.
  111.  
  112. */
  113.  
  114. FILE *in, *out;
  115. squeeze(fname)
  116. char *fname;
  117. {
  118.     register INT i, c;
  119.     register char *p;
  120.     register INT numnodes;            /* size of decoding tree */
  121.     register UNSIGNED crc;
  122.     UNSIGNED filecrc;
  123.     char origname[PATHLEN];        /* Original file name without drive */
  124.  
  125.     init_cr(); init_huff(); crc=0;
  126.  
  127.     if((in=fopen( fname, "r"))==NULL) {
  128.         fprintf(stderr, "usq: can't open %s\n", fname);
  129.         return ERROR;
  130.     }
  131.     if(portgetw(in) != (INT) RECOGNIZE) {/* Process header */
  132.         fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
  133.         return(ERROR);
  134.     }
  135.     filecrc = (UNSIGNED) portgetw(in);    /* checksum */
  136.     p = origname;                /* Get original file name */
  137.     do {                    /* send it to array */
  138.         *p = getc(in);
  139.     } while(*p++ != '\0');
  140.  
  141.     numnodes = portgetw(in);
  142.     if(numnodes < 0 || numnodes >= NUMVALS) {
  143.         fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
  144.         fclose(in);
  145.         return(ERROR);
  146.     }
  147.     /* Initialize for possible empty tree (SPEOF only) */
  148.     Dnode[0]._children[0] = -(SPEOF + 1);
  149.     Dnode[0]._children[1] = -(SPEOF + 1);
  150.  
  151.     for(i = 0; i < numnodes; ++i) {    /* Get decoding tree from file */
  152.         Dnode[i]._children[0] = portgetw(in);
  153.         Dnode[i]._children[1] = portgetw(in);
  154.     }
  155.     /* Get translated output bytes and write file */
  156.     if(MakeLCPathname && !IsAnyLower(origname))
  157.         uncaps(origname);
  158.     for(p=origname; *p; ++p)        /* change / to _ */
  159.         if( *p == '/')
  160.             *p = '_';
  161.     if (!Inbackground)
  162.         fprintf(stderr, "usq: %s -> %s\n",fname,origname);
  163.     if((out=fopen(origname, "w"))==NULL) {
  164.         fprintf(stderr, "usq: can't create %s\n", origname);
  165.     }
  166.     while ((c = getcr()) != EOF) {
  167.         crc += (UNSIGNED) c;
  168.         if ( c == '\r' && Nlmode)
  169.             continue;
  170.         putc(c, out);
  171.     }
  172.     fclose(in);
  173.     fflush(out);
  174.     fclose(out);
  175.     if( crc != filecrc ) {
  176.         fprintf(stderr, "usq: bad checksum in %s\n", fname);
  177.         fflush(stdout);
  178.         return(ERROR);
  179.     }
  180.     return(OK);
  181. }
  182. /*** from utr.c - */
  183. /* initialize decoding functions */
  184.  
  185. init_cr()
  186. {
  187.     Repct = 0;
  188. }
  189.  
  190. init_huff()
  191. {
  192.     Bpos = 99;    /* force initial read */
  193. }
  194.  
  195. /* Get bytes with decoding - this decodes repetition,
  196.  * calls getuhuff to decode file stream into byte
  197.  * level code with only repetition encoding.
  198.  *
  199.  * The code is simple passing through of bytes except
  200.  * that DLE is encoded as DLE-zero and other values
  201.  * repeated more than twice are encoded as value-DLE-count.
  202.  */
  203.  
  204. INT
  205. getcr()
  206. {
  207.     register INT c;
  208.  
  209.     if(Repct > 0) {
  210.         /* Expanding a repeated char */
  211.         --Repct;
  212.         return(Value);
  213.     } else {
  214.         /* Nothing unusual */
  215.         if((c = getuhuff()) != DLE) {
  216.             /* It's not the special delimiter */
  217.             Value = c;
  218.             if(Value == EOF)
  219.                 Repct = LARGE;
  220.             return(Value);
  221.         } else {
  222.             /* Special token */
  223.             if((Repct = getuhuff()) == 0)
  224.                 /* DLE, zero represents DLE */
  225.                 return(DLE);
  226.             else {
  227.                 /* Begin expanding repetition */
  228.                 Repct -= 2;    /* 2nd time */
  229.                 return(Value);
  230.             }
  231.         }
  232.     }
  233. }
  234. /* Decode file stream into a byte level code with only
  235.  * repetition encoding remaining.
  236.  */
  237.  
  238. INT
  239. getuhuff()
  240. {
  241.     register INT i;
  242.  
  243.     /* Follow bit stream in tree to a leaf*/
  244.     i = 0;    /* Start at root of tree */
  245.     do {
  246.         if(++Bpos > 7) {
  247.             if((Curin = getc(in)) == ERROR)
  248.                 return(ERROR);
  249.             Bpos = 0;
  250.             /* move a level deeper in tree */
  251.             i = Dnode[i]._children[1 & Curin];
  252.         } else
  253.             i = Dnode[i]._children[1 & (Curin >>= 1)];
  254.     } while(i >= 0);
  255.  
  256.     /* Decode fake node index to original data value */
  257.     i = -(i + 1);
  258.     /* Decode special endfile token to normal EOF */
  259.     i = (i == SPEOF) ? EOF : i;
  260.     return(i);
  261. }
  262. /*
  263.  * Machine independent getw which always gets bytes in the same order
  264.  *  as the CP/M version of SQ wrote them
  265.  */
  266. INT
  267. portgetw(f)
  268. FILE *f;
  269. {
  270.     register INT c;
  271.  
  272.     c = getc(f) & 0377;
  273.     return(c | (getc(f) << 8));
  274. }
  275.  
  276.  
  277. /* make string s lower case */
  278. uncaps(s)
  279. char *s;
  280. {
  281.     for( ; *s; ++s)
  282.         if(isupper(*s))
  283.             *s = tolower(*s);
  284. }
  285.  
  286.  
  287. /*
  288.  * IsAnyLower returns TRUE if string s has lower case letters.
  289.  */
  290. IsAnyLower(s)
  291. char *s;
  292. {
  293.     for( ; *s; ++s)
  294.         if (islower(*s))
  295.             return(TRUE);
  296.     return(FALSE);
  297. }
  298.