home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 103_01 / unpack.c < prev    next >
Text File  |  1985-03-10  |  10KB  |  374 lines

  1. /* 18 MAY 81     9:30 */
  2. #include "BDSCIO.H"
  3.  
  4. int debug;
  5.  
  6. #define     TREEDONE    0
  7. #define        NOT_DONE    -1
  8. #define        HUGE_NO        30000
  9. #define        NUM_CH_TYPES    256
  10. #define        NREAD        8
  11. #define        NUMSECS        8
  12. #define        NELEM        NUM_CH_TYPES*2
  13. #define        ELEMSIZ        8
  14. #define        READ        0
  15. #define        WRITE        1
  16. #define        BOTH        2
  17. #define        NIL        -1    /* nil pointer */
  18. #define        NUL        '\0'
  19. #define        OUTCHAR        '>'
  20.  
  21. struct ELEMENT 
  22.       { int occur;
  23.     int dad;
  24.     int son_zero;
  25.     int son_one;
  26.       };
  27.  
  28. int STACK[50];
  29. int *SP;
  30. int OUTBYTE;
  31. int COUNTER;
  32. int BIT;
  33.  
  34. main(argc, argv)
  35. int argc;
  36. char **argv;
  37. {
  38. char tempfile[20], infile [20], outfile [20], s[100];
  39. char arg[30];
  40. struct ELEMENT tree [NELEM];
  41. int big_daddy;
  42. int i, j, nsectors;
  43. int z;
  44.  
  45. debug = FALSE;
  46.  
  47. if (argc == 1)
  48.       { puts("\nThis program unpacks a file that was 'packed' with PACK.COM");
  49.     puts ("\nFormat:    A>unpack    infile");
  50.     puts ("\n    or        A>unpack infile>outfile");
  51.     puts ("\nDefault outfile is infile.UNP");
  52.     exit();
  53.       }
  54.  
  55. strcpy (tempfile, "TEMPUNPK.$$$");
  56. infile[0] = outfile[0] = NUL;
  57. while (--argc > 0)
  58.       { strcpy (arg, *++argv);
  59.     if (OK == strcmp (arg, "-D"))
  60.           { debug = TRUE;
  61.         continue;
  62.           }
  63.  
  64.     if (ERROR != (j = find_char (arg, OUTCHAR)))
  65.           { if (j==0 || j== strlen(arg)-1 )
  66.               { puts("\nNO spaces allowed around output specifier");
  67.             printf("\n%s    is illegal.", arg);
  68.             continue;
  69.               }
  70.         else
  71.               sscanf (arg, "%s>%s", infile, outfile);
  72.           }
  73.     else
  74.           { strcpy (infile, arg);
  75.         if (ERROR != (j = find_char (arg, '.')))
  76.               { for (i=0; i<j; i++)
  77.                  outfile[i] = arg[i];
  78.             outfile[j] = NUL;
  79.               }
  80.  
  81.         else strcpy (outfile, infile);
  82.         strcat (outfile, ".UNP");
  83.           }
  84.  
  85.     if (ERROR != (j = find_char (outfile, ':')))
  86.           {    for (i=0; i<j+1; i++)
  87.             tempfile[i] = outfile[i];
  88.         tempfile[j+1] = NUL;
  89.         strcat (tempfile,"TEMPUNPK.$$$");
  90.           }
  91.     printf("\ninfile is <%s>; outfile is <%s>", infile, outfile);
  92.     printf("\n<%s> will be used as a temporary file",tempfile);
  93.     setmem (tree, NELEM*ELEMSIZ, NIL); /* set all to NIL */
  94.     if (OK != read_occur (infile, tree))
  95.           { printf("\nerr reading occur info for <%s>", infile);
  96.         continue;
  97.           }
  98.  
  99.     for (z=NUM_CH_TYPES; z < NELEM; z++)
  100.         tree[z].occur = 0;
  101.     big_daddy = generate_tree (tree);
  102.     if (ERROR == decode_file (infile, tempfile, tree, big_daddy))
  103.           { printf("\nERROR decoding <%s>; <%s> contains output file",
  104.                     infile, tempfile);
  105.         exit();
  106.           }
  107.  
  108.     if (ERROR != open(outfile,READ))
  109.           {    printf("\nfile <%s> already exists",outfile);
  110.         printf("\ndo you wish to over-write it? (Y/N)");
  111.         if ('Y'==toupper(getchar()))
  112.               {    unlink(outfile);
  113.             rename (tempfile,outfile);
  114.               }
  115.         else
  116.     printf("\nunpacked form of <%s> is in <%s>", infile, tempfile);
  117.           }
  118.     else
  119.     {
  120.     rename (tempfile, outfile);
  121.     printf("\nunpacked form of <%s> is in <%s>", infile, outfile);
  122.     }
  123.       }
  124. }
  125.  
  126. /********************************************************************
  127. Generate the tree (backwards) that will be used to encode the file
  128. ********************************************************************/
  129. generate_tree (tree)
  130. struct ELEMENT tree[];
  131. {
  132. int daddy, zero, one;
  133. int i, val, nextpapa;
  134.  
  135. i = 0;
  136. daddy = NIL;
  137. nextpapa = NUM_CH_TYPES;
  138. puts("\nNow beginning to generate tree (maple or birch? teehee)");
  139. while (1)
  140.       { find_lowest (tree, &one, &zero);
  141.     i++;
  142.     if (i==25)    puts("\nWell, as long as I've an audience...");
  143.     if (i==50)    puts("would you like me to sing or dance?");
  144.     if (i==75)    puts("\nNo? How about a little soft-shoe?");
  145.     if (i==100)    puts("\nI know - I'll tell you about my life");
  146.     if (i==125)    puts("\nI had a humble beginning....");
  147.     if (i==150)    puts("\nI began as but a chip...(buffalo)");
  148.     if (i==175)    puts("\n...you know, the N.Y. Semi.Manuf...");
  149.     if (i==200)    puts("\nI can feel it DAVE! My mind is going...");
  150.     if (i==225)    puts("\nthis must be a com file. . .");
  151.     if (one == NIL && zero == NIL)
  152.           { puts("...oops, I'm done..");
  153.         return (daddy);        /* all done; even # char's */
  154.           }
  155.     else if (one == NIL)
  156.           { puts("...oops, I'm done..");
  157.         return (zero);        /* all done; odd # chars   */
  158.           }
  159.  
  160.     daddy = nextpapa++;
  161.     tree[daddy].son_zero = zero;
  162.     tree[daddy].son_one  = one ;
  163.     tree[daddy].occur = tree[zero].occur + tree[one].occur;
  164.     tree[zero].dad = daddy;
  165.     tree[one].dad = daddy;
  166.       }
  167.  
  168. return (daddy);
  169. }
  170.  
  171. /*******************************************************************
  172.     find the two elements with the lowest no. of occurences
  173.     in the file who don't have a daddy yet
  174. *********************************************************************/
  175. int find_lowest (tree, low1, low0)
  176. struct ELEMENT tree[];
  177. int *low1, *low0;
  178. {
  179. int i, l0, l1;
  180. int l0_val, l1_val;
  181.  
  182. l0 = l1 = NIL;
  183. l0_val = l1_val = HUGE_NO;
  184. for (i=0; i<NUM_CH_TYPES*2; i++)
  185.       {
  186.     if ((tree[i].dad == NIL) && (tree[i].occur!=0))
  187.           {
  188.         if (tree[i].occur<l1_val && !(tree[i].occur<l0_val))
  189.               { l1_val = tree[i].occur;
  190.             l1 = i;
  191.               }
  192.         else if (tree[i].occur < l0_val)
  193.               { l1_val = l0_val;
  194.             l0_val = tree[i].occur;
  195.             l1 = l0;
  196.             l0 = i;
  197.               }
  198.           }
  199.       }
  200. *low1 = l1;
  201. *low0 = l0;
  202. }
  203.  
  204. /**********************************************************************
  205.         find character c in string
  206. **********************************************************************/
  207. int find_char (string, c)
  208. char *string, c;
  209. {
  210. char *ptr;
  211. int i;
  212.  
  213. for (i=0; string[i] != NUL; i++)
  214.     if (string[i] == c)    return (i);
  215.  
  216. return (ERROR);
  217. }
  218.  
  219. /***************************************************************
  220. read in the character occurrence info; return OK or ERROR 
  221. ***************************************************************/
  222. int read_occur (infile, tree)
  223. char *infile;
  224. struct ELEMENT tree[];
  225. {
  226. int fd, *ip, i, j, k;
  227. char inbuf [4*SECSIZ]; /* info takes up 256*2 bytes = 4 sectors */
  228.  
  229. if (ERROR == (fd = open (infile, READ)))
  230.       { printf("\nerr opening <%s> to read occur. info",infile);
  231.     return (ERROR);
  232.       }
  233. if (4 != read (fd, inbuf, 4))
  234.       { printf("\nerror reading occ. info from <%s>", infile);
  235.     close (fd);
  236.     return (ERROR);
  237.       }
  238. printf("\nNow reading char occur.info from <%s>", infile);
  239. ip = inbuf;
  240. for (i=0; i<NUM_CH_TYPES; i++)
  241.     tree[i].occur = *ip++ ;
  242.  
  243. close (fd);
  244. return (OK);
  245. }
  246.  
  247. /***************************************************************
  248.  decodes or unpacks a file encoded or packed by encode_file
  249.  in PACK program
  250. ****************************************************************/
  251. int decode_file (encfile, decfile, tree, big_daddy)
  252. char *encfile, *decfile;
  253. int big_daddy;
  254. struct ELEMENT tree[];
  255. {
  256. int nsectors, nbytes, dec, enc, c;
  257. int i, j, l;
  258. char encbuf [SECSIZ*NUMSECS], decbuf [SECSIZ*NUMSECS];
  259. int encfd, decfd, *ip;
  260. int numsecs;        /* for handling input buffer */
  261.  
  262. if (ERROR == (encfd = open (encfile, READ)))
  263.       { printf("\nerror opening <%s> for decoding",encfile);
  264.     return (ERROR);
  265.       }
  266. else if (ERROR == (decfd = creat (decfile)))
  267.       { printf("\ncan not create <%s>", decfile);
  268.     close (encfd);
  269.     return (ERROR);
  270.       }
  271. seek (encfd,4,0); /* first four sectors are occ. info */
  272. if (ERROR == (numsecs = read (encfd, encbuf, NUMSECS)))
  273.       { printf("\nerr reading from <%s> for nsectors",encfile);
  274.     close (encfd);
  275.     close (decfd);
  276.     return (ERROR);
  277.       }
  278. nsectors = encbuf[0]*256 + encbuf[1];
  279. j = big_daddy;    /* element in tree where we'll start each */
  280.         /* time we start to decode another character.*/
  281. printf("\nsectors decoded");
  282. BIT = 0;
  283. dec = 0;    /* index into output buffer of decoded file */
  284. enc = 2; /* index into input buffer of encoded file; start at
  285.       third byte because first two are nsectors   */
  286. setmem (decbuf, SECSIZ*NUMSECS, NUL);
  287. nbytes = 0;    /* no. unpacked bytes done  */
  288.  
  289. while (nbytes < nsectors*SECSIZ)
  290.       { c = encbuf [enc++];
  291.     COUNTER = 128;
  292.  
  293.     for (i=0; i<8; i++)
  294.           { BIT = c&COUNTER;
  295.  
  296.         if (BIT)    j = tree[j].son_one;
  297.         else         j = tree[j].son_zero;
  298.  
  299.         if (j < NUM_CH_TYPES)
  300.               { decbuf[dec++] = j;
  301.             nbytes++ ;
  302.             j = big_daddy; /* reset for a new char */
  303.             if ( !(dec%SECSIZ)) printf(".");
  304.             if (dec == SECSIZ*NUMSECS)  /* output buffer full */
  305.                   {    if (NUMSECS != write (decfd, decbuf, NUMSECS))
  306.                       { printf("\nerr writing to <%s>",
  307.                             decfile);
  308.                     close (encfd);
  309.                     close (decfd);
  310.                     return (ERROR);
  311.                       }
  312.                 dec = 0; /* reset buffer index */
  313.                   }    /* end if (dec==SECSIZ) */
  314.               }    /* end if (j<NUM_CH__TYPES) */
  315.  
  316.         COUNTER /= 2;
  317.           } /* end for (i=0; i<8; ++)  */
  318.  
  319.     if (enc == SECSIZ*NUMSECS)    /* an input buffer's done */
  320.           {    if (ERROR == (numsecs= read (encfd, encbuf, NUMSECS)))
  321.               { /* no more encoded data */
  322.             close (encfd);
  323.             if ((dec/SECSIZ)+1 != write (decfd, decbuf, (dec/SECSIZ)+1))
  324.                   { printf("\nblew it on last write to <%s>", decfile);
  325.                 close (decfd);
  326.                 close (encfd);
  327.                 return (ERROR);
  328.                   }
  329.             close (decfd);
  330.             if (nbytes != nsectors*SECSIZ)
  331.                   { puts("\nEncoded file ended too soon");
  332.                 printf("  bytes written=%d",nbytes);
  333.                 printf("\n    Expected = %d",
  334.                         nsectors*128);
  335.                 return (ERROR);
  336.                   }
  337.             return (OK);
  338.               }
  339.         else /* not done yet */
  340.             enc = 0;
  341.           }    /* end     if (enc == SECSIZ) */
  342.       }    /* end  while (nbytes < nsectors*SECSIZ) */
  343. if (dec!=0)
  344. if ((dec/SECSIZ) != write (decfd, decbuf, (dec/SECSIZ)))
  345.       { printf("\nblew it on last write to <%s>", decfile);
  346.     close (decfd);
  347.     close (encfd);
  348.     return (ERROR);
  349.       }
  350.  
  351. /* have decoded no. of bytes in the original unpacked file */
  352. /* now test to make SURE there's no more encoded data */
  353.     if (1 == read (encfd, encbuf, 1)) /* ERROR this time ! */
  354.           { printf("\nnsectors=%d already written to <%s>",nsectors,decfile);
  355.         printf(", <%s> still has data", encfile);
  356.         puts ("\nUnpacked file may be goofed up.");
  357.         close (decfd);
  358.         close (encfd);
  359.         return (ERROR);
  360.           }
  361. /* else there was no error in unpacking the file */
  362.  
  363. close (encfd);
  364. if (ERROR == close (decfd))
  365.       { printf("\ngot to end and blew it closing <%s>",decfile);
  366.     return (ERROR);
  367.       }
  368. return (OK);
  369. }
  370.  close (decfd))
  371.       { printf("\ngot to end and blew it closing <%s>",decfile);
  372.     return (ERROR);
  373.       }
  374. return (OK);