home *** CD-ROM | disk | FTP | other *** search
/ Between Heaven & Hell 2 / BetweenHeavenHell.cdr / 300 / 256 / msmkboo.c < prev    next >
C/C++ Source or Header  |  1984-12-07  |  8KB  |  246 lines

  1. /* MSMKBOO.C
  2.  *
  3.  * This program takes a file and encodes it into printable characters.
  4.  * These printable files can then be decoded by the programs MSPCBOOT.BAS
  5.  * or MSPCTRAN.BAS as the need may be.  The file is encoded by taking
  6.  * three consecutive eight bit bytes and dividing them into four six bit
  7.  * bytes.  An ASCII zero was then added to the resulting four characters.
  8.  * to make them all printable ASCII characters in the range of the
  9.  * character zero to the character underscore.  In order to reduce the
  10.  * size of the file null repeat count was used.  The null repeat count
  11.  * compresses up to 78 consecutive nulls into only two characters.  This
  12.  * is done by using the character tilde (~) as an indication that a group
  13.  * of repetitive nulls has occured.  The character following the tilde is
  14.  * number of nulls in the group.  The number is also converted in to a
  15.  * printable character by adding an ASCII zero.  The highest number of
  16.  * nulls is therefore the highest printable character tilde.  This is
  17.  * equal to tilde minus zero nulls or 78 nulls.  Because of the three
  18.  * byte to four byte encoding the repeat counting can only start with
  19.  * the first character of a three byte triplet.
  20.  *
  21.  * This C program was written specifically for the DEC-20 and as such
  22.  * will not easily be transported to another system.  The main problem
  23.  * lies in the file I/O routines.  It is necessary to make sure that
  24.  * untranslated eight bit bytes are input from the input file.  The 
  25.  * main change would be to make the OPEN statement reflect this for 
  26.  * your particular system and brand of UNIX and C.  The rest of the
  27.  * program should be transportable with little or no problems.
  28.  *
  29.  */
  30.  
  31.  
  32. #include <stdio.h>        /* Standard UNIX i/o definitions */
  33. #include <file.h>
  34.  
  35. /* Symbol Definitions */
  36.  
  37. #define MAXPACK        80    /* Maximum packet size */
  38.  
  39. #define MYRPTQ        '~'    /* Repeat count prefix I will use */
  40. #define DATALEN        78    /* Length of data buffer */
  41.  
  42. #define TRUE        -1    /* Boolean constants */
  43. #define FALSE        0
  44.  
  45. /* Macros */
  46.  
  47. #define tochar(ch)  ((ch) + '0')
  48.  
  49. /* Global Variables */
  50.  
  51. int    size,            /* Size of present data */
  52.     maxsize,        /* Max size for data field */
  53.         nc,            /* Number of input chars */
  54.         oc,            /* Number of output chars */
  55.     fd,            /* File pointer of file to read/write */
  56.     ofd,
  57.     rpt,            /* repeat count */
  58.     rptq,            /* repeat quote */
  59.     rptflg,            /* repeat processing flag */
  60.     eoflag,            /* Set when file is empty. */
  61.     otot;            /* What char number we are processing. */
  62.  
  63. char    t,            /* Current character */
  64.     one,
  65.     two,
  66.     three,
  67.     *filnam,        /* Current file name */
  68.         *ofile,
  69.     packet[MAXPACK];    /* Packet buffer */
  70.  
  71. main(argc,argv)                /* Main program */
  72. int argc;                /* Command line argument count */
  73. char **argv;                /* Pointers to args */
  74. {
  75.     char sfile();                /* Send file routine & ret code */
  76.     if (--argc != 2) usage();        /* Make sure there's a command line. */
  77.     rptq = MYRPTQ;            /* Repeat Quote */
  78.     rptflg = TRUE;            /* Repeat Count Processing Flag */
  79.  
  80.     filnam = *++argv;            /* Get file to send */
  81.     ofile = *++argv;            /* Output file to create */
  82.     sfile();
  83.     printf("Done, in: %d, out: %d, efficiency: %.2f%%\n",nc,oc,(100.0*nc)/oc);
  84. }
  85.  
  86. /*
  87.    S F I L E - Send a whole file
  88. */
  89.  
  90. char sfile()                /* Send a file */
  91. {
  92.     char *i;
  93.  
  94.     fd = open(filnam,FATT_RDONLY|FATT_BINARY|FATT_DEFSIZE);
  95.     if (fd < 0)                /* Report any errors */
  96.     {
  97.         printf("\n?Error opening file \"%s\"\n",filnam);
  98.         exit(1);
  99.     }
  100.  
  101.     ofd = open(ofile,FATT_WRONLY|FATT_CREATE|FATT_BINARY);
  102.     if (ofd < 0)
  103.     {
  104.         printf("\n?error opening file \"%s\"\n",ofile);
  105.         exit(1);
  106.     }
  107.  
  108.     oc = strlen(filnam);        /* Get the string length. */
  109.     for (i=filnam; *i != '\0'; i++)    /* Uppercase the file name. */
  110.     if (*i >= 'a' && *i <= 'z') *i ^= 040;
  111.     write(ofd,filnam,oc);         /* Write the file name in the file. */
  112.     write(ofd,"\r\n",2);
  113.  
  114.     maxsize = DATALEN - 5;
  115.     rpt = 0;                /* Zero the repeat count. */
  116.     oc = nc = 0;            /* Output & input character counts. */
  117.     otot = 1;                /* Start with first char of triplet. */
  118.     while (getbuf() > 0)        /* While not EOF, get a packet. */
  119.     {
  120.     packet[size++] = '\r';        /* Explicit CRLF. */
  121.     packet[size++] = '\n';
  122.     packet[size] = '\0';
  123.         oc += size;            /* Count output size. */
  124.         write(ofd,packet,size);        /* Write the packet to the file. */
  125. /*        printf("%d: %s",size,packet);    /* Print on the screen for testing. */
  126.     }
  127. }
  128. /*
  129.    G E T B U F -- Do one packet.
  130. */
  131.  
  132. getbuf()                /* Fill one packet buffer. */
  133. {
  134.     if (eoflag != 0) return(-1);    /* If at the end of file, stop. */
  135.     size = 0;
  136.     while((t = getch()) >= 0)        /* t == -1 means EOF. */
  137.     {
  138.     nc++;                /* Count the character. */
  139.         process(t);            /* Process the character. */
  140.     if (size >= maxsize)        /* If the packet is full, */
  141.     {
  142.             packet[size] = '\0';    /*  terminate the string. */
  143.             return(size);
  144.         }
  145.     }
  146.     eoflag = -1;            /* Say we hit the end of the file. */
  147.     process(0);                /* Clean out any remaining chars. */
  148.     process(0);
  149.     process(' ');
  150.     packet[size] = '\0';        /* Return any partial final buffer. */
  151.     return(size);
  152. }
  153.  
  154. /* P R O C E S S -- Do one character. */
  155.  
  156. process(a)
  157. char a;
  158. {
  159.     if (otot == 1)            /* Is this the first of three chars? */
  160.     {
  161.         if (a == 0)            /* Is it a null? */
  162.         {
  163.         if (++rpt < 78)        /* Below max nulls, just count. */
  164.                 return;
  165.         else if (rpt == 78)        /* Reached max number, must output. */
  166.         {
  167.                 packet[size++] = rptq;    /* Put in null repeat char and */
  168.                 packet[size++] = tochar(rpt); /* number of nulls. */
  169.                 packet[size] = '\0';
  170.                 rpt = 0;
  171.             return;
  172.         }
  173.         }
  174.     else
  175.         {
  176.         if (rpt == 1)        /* Just one null? */
  177.         {
  178.         one = 0;        /* Say the first char was a null. */
  179.         two = a;        /* This char is the second one. */
  180.         otot = 3;        /* Look for the third char. */
  181.         rpt = 0;        /* Restart null count. */
  182.         return;
  183.         }
  184.         if (rpt > 1)        /* Some number of nulls? */
  185.         {
  186.                 packet[size++] = rptq;    /* Insert the repeat prefix */
  187.                 packet[size++] = tochar(rpt); /* and count. */
  188.                 packet[size] = '\0';
  189.                 rpt = 0;        /* Reset repeat counter. */
  190.          }
  191.         one = a;            /* Set first character. */
  192.         otot = 2;            /* Say we are at the second char. */
  193.     }
  194.     }
  195.     else if (otot == 2)
  196.     {
  197.     two = a;            /* Set second character. */
  198.     otot = 3;            /* Say we are at the third char. */
  199.     }
  200.     else
  201.     {
  202.         three = a;
  203.     otot = 1;            /* Start over at one. */
  204.     pack(one,two,three);        /* Pack in the three characters. */
  205.     }
  206. }
  207.  
  208. /* This routine does the actual three character to four character encoding.
  209.  * The concept is relatively straight forward.  The first output character
  210.  * consists of the first (high order or most significant) six bits of the
  211.  * first input character.  The second output character is made from the
  212.  * remaining two low order bits of the first input character and the first
  213.  * four high order bits of the second input character.  The third output
  214.  * character is built from the last four low order bits of the second input
  215.  * character and the two high order bits of the third input character.  The
  216.  * fourth and last output character consists of the six low order bit of
  217.  * the third input character.  In this way the three eight bit input char-
  218.  * acters (for a total of 24 bits) are divided into four six bit output
  219.  * characters (also for a total of 24 bits).  In order to make the four
  220.  * output characters printable an ASCII zero is then added to each of them.
  221.  *
  222.  */
  223.  
  224. pack(x,y,z)
  225. char x,y,z;
  226. {
  227.     packet[size++] = tochar((x >> 2) & 077);
  228.     packet[size++] = tochar(((x & 003) << 4) | ((y >> 4) & 017));
  229.     packet[size++] = tochar(((y & 017) << 2) | ((z >> 6) & 003));
  230.     packet[size++] = tochar(z & 077);
  231.     packet[size] = '\0';
  232. }
  233.  
  234. getch()                    /* Get next (or pushed) char. */
  235. {
  236.    char a;
  237.  
  238.    return((read(fd,&a,1) > 0) ? a : -1); /* (or -1 if EOF) */
  239. }
  240.  
  241. usage()                    /* Give message if user makes */
  242. {                    /* a mistake in the command. */
  243.     fprintf(stderr,"usage: msmkboo inputfile outputfile\n");
  244.     exit(1);
  245. }
  246.