home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / CPM68K / 68000USQ.LBR / USQ.C < prev    next >
Text File  |  2000-06-30  |  11KB  |  410 lines

  1. static char    Sccs_Id[] = "@(#)usq.c    1.3    9/4/84 19:57:05";
  2.  
  3. /* USQ.C CHANGE HISTORY:
  4.  * 1.3  Converted to support USG Unix on 68000.  Define unix to
  5.  *    get unix version, cpm to get CP/M-68K version.  Geoff Kuenning 9/3/84
  6.  * 1.2  Converted to Unix SCCS.  Geoff Kuenning 9/3/84
  7.  * 1.1    Added WILDEXP.  JEC 1/2/84
  8.  * 1.0  Converted to CP/M-68K C,  Jim Cathey 11-5-83
  9.  *    Taken from BDS C version 2.0
  10.  * 2.0    Added checkurk(), changed credits -CAF 8-14-83
  11.  * 1.9  Added wildexp -CAF 6-12-82
  12.  * 1.8  Output CPMEOF's while last output sector is partially filled.
  13.  *    Needed if file was squeezed on a non-CP/M system. -CAF 3-10-82
  14.  * 1.7  Added -n to change NL to CRLF when unsqueezing files.  Added CPMEOF
  15.  *    at end of file in case of checksum error detected.
  16.  * 1.6  Lengthened permissible length of unsqueezed filename so long **nix
  17.  *    pathnames won't choke unsqueeze(). -CAF 12-5-81
  18.  * 1.5  Break up long lines of introductory text
  19.  *      -count no longer appends formfeed to preview of each file.
  20.  *    -fcount (-f10, -F10) does append formfeed.
  21.  * 1.4    Add -count option to allow quick inspection of files.
  22.  * 1.3    Close inbuff to avoid exceeding maximum number of
  23.  *    open files. Includes rearranging error exits.
  24.  *
  25.  * Program to unsqueeze files formed by sq.com
  26.  *
  27.  * Usage (CPM version):
  28.  *    USQ item ...
  29.  * where ... represents more (optional) items and
  30.  * "item" is either:
  31.  *    drive:        to change the output drive
  32.  *    file        input file
  33.  *    drive:file    input file
  34.  *    -<count>    Previewing feature: redirects output
  35.  *             files to standard output with parity stripped
  36.  *            and unprintables except CR, LF, TAB and  FF
  37.  *            converted to periods. Limits each file
  38.  *            to first count lines.
  39.  *            Defaults to console, but see below how
  40.  *            to capture all in one file for further
  41.  *            processing, such as by PIP.
  42.  *            Count defaults to a very high value.
  43.  *            No CRC check is performed when previewing.
  44.  *            Use drive: to cancel this.
  45.  *
  46.  *    -f<count>    Same as -count except formfeed
  47.  *            appended to preview of each file.
  48.  *            Example: -f10.
  49.  *
  50.  *    -n        Change NL to CRLF
  51.  *
  52.  * If no such items are given on the command line you will be
  53.  * prompted for commands (one at a time). An empty command
  54.  * terminates the program.
  55.  *
  56.  * Usage (USG Unix version):
  57.  *    USQ item ...
  58.  * where ... represents more (optional) items and
  59.  * "item" is either:
  60.  *    file        input file
  61.  *    -<count>    Previewing feature: redirects output
  62.  *             files to standard output with parity stripped
  63.  *            and unprintables except CR, LF, TAB and  FF
  64.  *            converted to periods. Limits each file
  65.  *            to first count lines.
  66.  *            Count defaults to a very high value.
  67.  *            No CRC check is performed when previewing.
  68.  *            Use -e to cancel this.
  69.  *    
  70.  *    -f<count>    Same as -<count> except formfeed
  71.  *            appended to preview of each file.
  72.  *            Example: -f10.
  73.  *
  74.  *    -u        Cancel -<count> or -f<count>.
  75.  *    -n        Change CRLF to NL.  Note that this is the EXACT
  76.  *            opposite of the meaning of this flag in CP/M.
  77.  *
  78.  * If no such items are given on the command line you will be
  79.  * prompted for commands (one at a time). An empty command
  80.  * terminates the program.
  81.  *
  82.  * The unsqueezed file name is recorded in the squeezed file.
  83.  * 
  84.  * Examples (CP/M):
  85.  *    A>USQ GRUMP.QQQ        writes on a:
  86.  *    A>USQ D:CRAP.XQZ    writes on A:
  87.  *    A>USQ B: D:CRAP.CQM    writes on B:
  88.  *    B>USQ X.AQ C: Y.BQ    writes X.?? on B: and Y.?? on C:
  89.  *
  90.  * Examples (Unix):
  91.  *    usq grump.qqq        writes grump.q?q in current directory
  92.  *    usq - crap.xqz        writes cleaned-up crap to standard output
  93.  */
  94.  
  95. #ifndef unix            /* Make sure *something* is defined */
  96. #define cpm
  97. #endif
  98.  
  99. #ifdef unix
  100. #include <stdio.h>
  101. #include <ctype.h>
  102. #else
  103. #include <a:stdio.h>
  104. #include <a:ctype.h>
  105. #endif
  106. #include "sqcom.h"
  107. #include "usq.h"
  108.  
  109. #define VERSION "1.3   9/4/84"    /* Version for titling output */
  110.  
  111. unsigned dispcnt;    /* How much of each file to preview */
  112. char    ffflag;        /* Formfeed separates preview from different files */
  113. char    nlmode;        /* <>0 if adding/deleting cr's for host system */
  114.  
  115. #ifdef cpm
  116. #define SENTINEL 055555    /* For catching out-of-memory conditions */
  117. #ifndef PATHLEN
  118. #define PATHLEN    16    /* Maximum length of an input filename */
  119. #endif
  120. #define LONGPATH 257    /* Maximum length of an output filename */
  121.  
  122. char    origname[LONGPATH]; /* Original file name without drive */
  123. unsigned Sentinel;    /* be sure this doesn't get munged ! */
  124. #endif
  125.  
  126. #ifdef unix
  127. #ifndef PATHLEN
  128. #define PATHLEN    512    /* Maximum length of a pathname */
  129. #endif
  130. #define LONGPATH PATHLEN
  131. #endif
  132.  
  133. short brgetw ();
  134.  
  135. main(argc, argv)
  136. int argc;
  137. char *argv[];
  138. {
  139.     int i,c;
  140.     char inparg[PATHLEN];    /* parameter from input */
  141.  
  142. #ifdef cpm
  143.     wildexp(&argc, &argv);
  144.     Sentinel = SENTINEL;    /* unlikely value */
  145. #endif
  146.  
  147.     nlmode = dispcnt = 0;    /* Not in preview or nlmode */
  148.  
  149.  
  150. #ifdef cpm
  151.     /* Initialize output drive to default drive */
  152.     outdrv[0]  = '\0';
  153.     /* But prepare for a specific drive */
  154.     outdrv[1] = ':';
  155.     outdrv[2] = '\0';    /* string terminator */
  156. #endif
  157.  
  158.     /* Process the parameters in order */
  159.     for(i = 1; i < argc; ++i)
  160.         obey(argv[i]);
  161.  
  162.     if(argc < 2) {
  163.         fprintf(stderr, "File unsqueezer version %s\n", VERSION);
  164.         fprintf(stderr,"Conceived by Richard Greenlaw Modified by Chuck Forsberg et al.\n");
  165. #ifdef cpm
  166.         fprintf(stderr, "Accepts redirection and wildcards.\n");
  167.         fprintf(stderr, "Usage: usq [-count][-Fcount][-N] [file ...]\n");
  168.         fprintf(stderr, "Parameters are from command line or one-at-a-time from standard\n");
  169.         fprintf(stderr, "input and are output drives and input file names. Empty to quit.\n");
  170. #endif
  171. #ifdef unix
  172.         fprintf(stderr, "Usage: usq [-<count>][-f<count>][-u][-n] [file ...]\n");
  173.         fprintf(stderr, "Parameters are from command line or one-at-a-time from standard\n");
  174.         fprintf(stderr, "input and are input file names. Empty to quit.\n");
  175. #endif
  176.  
  177.         do {
  178.             fprintf(stderr, "\n*");
  179.             for(i = 0; i < sizeof (inparg); ++i) {
  180.                 if((c = getchar()) == EOF)
  181.                     c = '\n';    /* force empty (exit) command */
  182.                 if((inparg[i] = c) == '\n') {
  183.                     inparg[i] = '\0';
  184.                     break;
  185.                 }
  186.             }
  187.             if(inparg[0] != '\0')
  188.                 obey(inparg);
  189.         } while(inparg[0] != '\0');
  190.     }
  191. #ifdef cpm
  192.     if (Sentinel != SENTINEL)
  193.         fprintf(stderr,"Out of memory: translation suspect!\007\n");
  194. #endif
  195.     return 0;
  196. }
  197.  
  198. obey(p)
  199. char *p;
  200. {
  201.     char *q;
  202.  
  203.     if(*p == '-') {
  204.         if('n' ==tolower(p[1])) {
  205.             ++nlmode; return;
  206.         }
  207. #ifdef unix
  208.         if('e' == tolower (p[1])) {
  209.             dispcnt = 0;    /* cancel previewing */
  210.             return;
  211.         }
  212. #endif
  213.         if(ffflag = (tolower(*(p+1)) == 'f'))
  214.             ++p;
  215.         /* Set number of lines of each file to view */
  216.         dispcnt = 65535;    /* default */
  217.         if(*(p+1))
  218.             if((dispcnt = atoi(p + 1)) == 0)
  219.                 fprintf(stderr, "\nBAD COUNT %s", p + 1);
  220.         return;
  221.     }    
  222.  
  223. #ifdef cpm
  224.     if(*(p + 1) == ':') {
  225.         /* Got a drive */
  226.         if(isalpha(*p)) {
  227.             if(*(p+2) == '\0') {
  228.                 /* Change output drive */
  229.                 dispcnt = 0;    /* cancel previewing */
  230.                 printf("\nOutput drive =%s",p);
  231.                 outdrv[0] = *p;
  232.                 return;
  233.             }
  234.         } else {
  235.             fprintf(stderr, "\nERROR - Ignoring %s.", p);
  236.             return;
  237.         }
  238.     }
  239.  
  240.     /* Check for ambiguous (wild-card) name */
  241.     for(q = p; *q != '\0'; ++q)
  242.         if(*q == '*' || *q == '?') {
  243.             fprintf(stderr, "\nCan't accept ambiguous name %s.", p);
  244.             return;
  245.         }
  246. #endif
  247.  
  248.     unsqueeze(p);
  249. }
  250.  
  251.  
  252. unsqueeze(infile)
  253. char *infile;
  254. {
  255.     FILE *inbuff, *outbuff;    /* file buffers */
  256. #ifdef cpm
  257.     FILE *fopenb(), *fdopen();
  258. #endif
  259. #ifdef unix
  260.     FILE *fopen (), *fdopen ();
  261. #define creatb    creat
  262. #define fopenb    fopen
  263. #endif
  264.     int i, c, ofd;
  265.     char cc;
  266.  
  267.     char *p;
  268.     unsigned short filecrc;    /* checksum */
  269.     int numnodes;        /* size of decoding tree */
  270.     char outfile[LONGPATH];    /* output file name */
  271.     unsigned linect;    /* count of number of lines previewed */
  272.  
  273.     if((inbuff = fopenb(infile,"r")) == 0) {
  274.         fprintf(stderr, "Can't open %s\n", infile);
  275.         return;
  276.     }
  277.     /* Initialization */
  278.     linect = 0;
  279.     crc = 0;
  280.     init_cr();
  281.     init_huff();
  282.  
  283.     /* Process header */
  284.     if(brgetw (inbuff) != RECOGNIZE) {
  285.         fprintf(stderr, "'%s' is not a squeezed file!\n", infile);
  286.         goto closein;
  287.     }
  288.  
  289.     filecrc = brgetw(inbuff);
  290.  
  291.     /* Get original file name */
  292. #ifdef cpm
  293.     p = origname;    /* send it to array */
  294. #endif
  295. #ifdef unix
  296.     p = outfile;
  297. #endif
  298.     do {
  299.         *p = getc(inbuff);
  300.     } while(*p++ != '\0');
  301.  
  302. #ifdef cpm
  303.     /* Combine with output drive */
  304.     outfile[0] = '\0';        /* empty */
  305.     strcat(outfile, outdrv);    /* drive */
  306.     strcat(outfile, origname);    /* name */
  307. #endif
  308.  
  309.     printf("\n%s -> %s: ", infile, outfile);
  310.  
  311.  
  312.     numnodes = brgetw(inbuff);
  313.  
  314.     if(numnodes < 0 || numnodes >= NUMVALS) {
  315.         fprintf(stderr, "'%s' has invalid decode tree size.\n", infile);
  316.         goto closein;
  317.     }
  318.  
  319.     /* Initialize for possible empty tree (SPEOF only) */
  320.     dnode[0].children[0] = -(SPEOF + 1);
  321.     dnode[0].children[1] = -(SPEOF + 1);
  322.  
  323.     /* Get decoding tree from file */
  324.     for(i = 0; i < numnodes; ++i) {
  325.         dnode[i].children[0] = brgetw(inbuff);
  326.         dnode[i].children[1] = brgetw(inbuff);
  327.     }
  328.  
  329.     if(dispcnt) {
  330.         /* Use standard output for previewing */
  331.         putchar('\n');
  332.         while(((c = getcr(inbuff)) != EOF) && (linect < dispcnt)) {
  333.             cc = 0x7f & c;    /* strip parity */
  334.             if((cc < ' ') || (cc > '~'))
  335.                 /* Unprintable */
  336.                 switch(cc) {
  337.                 case '\r':    /* return */
  338.                     /* newline will generate CR-LF */
  339.                     goto next;
  340.                 case '\n':    /* newline */
  341.                     ++linect;
  342.                 case '\f':    /* formfeed */
  343.                 case '\t':    /* tab */
  344.                     break;
  345.                 default:
  346.                     cc = '.';
  347.                 }
  348.             putchar(cc);
  349.         next: ;
  350.         }
  351.         if(ffflag)
  352.             putchar('\f');    /* formfeed */
  353.     } else {
  354.         /* Create output file */
  355.         if((ofd = creatb(outfile, 0755)) == ERROR) {
  356.             fprintf(stderr, "Can't create '%s'.\n", outfile);
  357.             goto closeall;
  358.         }
  359.         outbuff = fdopen(ofd,"w");
  360.         /* Get translated output bytes and write file */
  361.         while((c = getcr(inbuff)) != EOF) {
  362.             crc += c;
  363.             if(nlmode && c=='\n')
  364.                 fputc('\r',outbuff);
  365.             if((fputc(c, outbuff)) == ERROR) {
  366.                 fprintf(stderr, "Write error in '%s'.\n", outfile);
  367.                 goto closeall;
  368.             }
  369.         }
  370.  
  371.         if(filecrc != crc) {
  372. #ifdef cpm
  373.             fputc(CPMEOF, outbuff);
  374. #endif
  375.             fprintf(stderr, "ERROR - checksum error in '%s'.\n", outfile);
  376.         }
  377.  
  378.  
  379.     closeall:
  380.         /*
  381.          * If the last sector is partially filled (this would happen
  382.          * iff the file was squeezed on MARC, Unix(TM), MS-DOS or
  383.          * similar system which avoids the CP/M EOF crock),
  384.          * pad it out with ^Z characters so editors,
  385.          * etc. won't choke on it. -CAF 3-10-82
  386.          */
  387. /*        while(outbuff._nleft % SECSIZ)    /* for BDS C 1.4x only */
  388. /*            putc(CPMEOF, &outbuff); */
  389.         fflush(outbuff);
  390.         fclose(outbuff);
  391.     }
  392.  
  393. closein:
  394.     fclose(inbuff);
  395. }
  396.  
  397. short brgetw(stream)
  398. FILE *stream;
  399. {
  400. /*    Get word from stream. Since BDS C is byte reversed and
  401.     CP/M-68K isn't, we need to swap every byte.
  402.  
  403.     We don't use 'getw' because it returns 32 bits on a 32-bit machine.
  404. */
  405.     short wordin, wordout;
  406.     wordin = (getc (stream) << 8) | (getc (stream) & 0xFF);
  407.     swab(&wordin, &wordout, 2);
  408.     return wordout;
  409. }
  410.