home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / unix / hqxtobin.shr / hqxify.c next >
C/C++ Source or Header  |  1989-04-10  |  19KB  |  564 lines

  1. #include "mactypes.h"
  2.  
  3. #define HQXBUFLEN 512
  4. byte hqxbuf[HQXBUFLEN+1], *buf_ptr, *buf_end, *buf_start=hqxbuf+1;
  5.  
  6. #define MAXLINE 255
  7. byte line[MAXLINE+1], *line_ptr, *line_end, *line_start=line+1;
  8.  
  9. int line_count, file_count;
  10. int save_state, total_bytes, save_run_length;
  11. word save_nibble;
  12. char binfname[BINNAMELEN], hqxfname[BINNAMELEN];
  13. FILE *hqxfile, *binfile;
  14.  
  15. /* This routine reads the header of a hqxed file and appropriately twiddles it,
  16.     determines if it has CRC problems, creates the .bin file, and puts the info
  17.     into the .bin file.
  18.     Output is hqx_datalen, hqx_rsrclen, type, binfname, binfile */
  19.  
  20. hqx_to_bin_hdr(type, hqx_datalen, hqx_rsrclen)
  21. char *type;
  22. ulong *hqx_datalen, *hqx_rsrclen;
  23. {   register byte *hqx_ptr, *hqx_end;
  24.     register ulong calc_crc;
  25.     hqx_buf *hqx_block;
  26.     hqx_header *hqx;
  27.     info_header info;
  28.     ulong mtim;
  29.     extern word magic[];
  30.     extern FILE *verbose;
  31.     extern char *dir, *ext;
  32.  
  33.     /* read the hqx header, assuming that I won't exhaust hqxbuf in so doing */
  34.     fill_hqxbuf();
  35.     hqx_block = (hqx_buf *) buf_ptr;
  36.     hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  37.     hqx_ptr = buf_ptr;
  38.     hqx_end = (byte *) hqx + sizeof(hqx_header);
  39.     calc_crc = 0;
  40.     while (hqx_ptr < hqx_end)
  41.         calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  42.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  43.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  44.     buf_ptr = hqx_ptr;
  45.  
  46.     /* stuff the hqx header data into the info header */
  47.     bzero(&info, sizeof(info_header));
  48.     info.nlen = hqx_block->nlen;
  49.     strncpy(info.name, hqx_block->name, info.nlen);     /* name */
  50.     bcopy(hqx->type, info.type, 9);             /* type, author, flag */
  51.     info.flags  &= 0x7e;                        /* reset lock bit, init bit */
  52.     if (hqx->protect & 0x40) info.protect = 1;  /* copy protect bit */
  53.     bcopy(hqx->dlen, info.dlen, 8);             /* dlen, rlen */
  54.     mtim = time2mac(time(0));
  55.     bcopy(&mtim, info.mtim, 4);
  56.     bcopy(&mtim, info.ctim, 4);
  57.  
  58.     /* Create the .bin file and write the info to it */
  59.     unixify(hqx_block->name);
  60.     sprintf(binfname, "%s/%s%s", dir, hqx_block->name, ext);
  61.     fprintf(verbose,
  62.         "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  63.         hqx_block->name, info.type, info.auth);
  64.     if ((binfile = fopen(binfname, "w")) == NULL)
  65.         error("Cannot open %s", binfname);
  66.     check_hqx_crc(calc_crc, "File header CRC mismatch in %s", binfname);
  67.     fwrite(&info, sizeof(info), 1, binfile);
  68.  
  69.     /* Get a couple of items we'll need later */
  70.     bcopy(info.dlen, hqx_datalen, 4);
  71.     *hqx_datalen = mac2long(*hqx_datalen);
  72.     bcopy(info.rlen, hqx_rsrclen, 4);
  73.     *hqx_rsrclen = mac2long(*hqx_rsrclen);
  74.     bcopy(info.type, type, 4);
  75.     }
  76.  
  77. /* This routine reads the header of a bin file and appropriately twiddles it,
  78.     creates the .hqx file, and puts the info into the .hqx file.
  79.     Output is hqx_datalen, hqx_rsrclen, type, hqxfname, hqxfile */
  80.  
  81. bin_to_hqx_hdr(hqx_datalen, hqx_rsrclen)
  82. ulong *hqx_datalen, *hqx_rsrclen;
  83. {   register byte *hqx_ptr, *hqx_end;
  84.     register ulong calc_crc;
  85.     hqx_buf *hqx_block;
  86.     hqx_header *hqx;
  87.     info_header info;
  88.     extern word magic[];
  89.     extern FILE *verbose;
  90.     extern char **hqxnames_left;
  91.     extern char *ext;
  92.  
  93.     strcpy(binfname, *hqxnames_left++);
  94.     if (!(binfile = fopen(binfname, "r"))) {
  95.         /* Maybe we are supposed to figure out the suffix ourselves? */
  96.         strcat(binfname, ext);
  97.         if (!(binfile = fopen(binfname, "r")))
  98.             error("Cannot open %s", binfname);
  99.         }
  100.     if (!fread(&info, sizeof(info), 1, binfile))
  101.         error("Unexpected EOF in header of %s", binfname);
  102.  
  103.     /* stuff the info header into the hqx header */
  104.     hqx_block = (hqx_buf *) buf_ptr;
  105.     hqx_block->nlen = info.nlen;
  106.     strncpy(hqx_block->name, info.name, info.nlen);
  107.     hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  108.     hqx->version  = 0;
  109.     bcopy(info.type, hqx->type, 9);             /* type, author, flags */
  110.     if (info.protect = 1) hqx->protect = 0;     /* protect bit: 0x40 */
  111.     else hqx->protect = 0;
  112.     bcopy(info.dlen, hqx->dlen, 8);             /* dlen, rlen */
  113.  
  114.     /* Create the .hqx file and write the info to it */
  115.     strncpy(hqxfname, info.name, info.nlen);
  116.     unixify(hqxfname);
  117.     fprintf(verbose,
  118.         "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  119.         hqxfname, info.type, info.auth);
  120.  
  121.     calc_crc = 0;
  122.     hqx_ptr = (byte *) hqx_block;
  123.     hqx_end = hqx_ptr + 1 + hqx_block->nlen + sizeof(hqx_header);
  124.     while (hqx_ptr < hqx_end)
  125.         calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  126.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  127.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  128.     buf_ptr = hqx_end;
  129.     write_hqx_crc(calc_crc);
  130.  
  131.     /* Get a couple of items we'll need later */
  132.     bcopy(info.dlen, hqx_datalen, 4);
  133.     *hqx_datalen = mac2long(*hqx_datalen);
  134.     bcopy(info.rlen, hqx_rsrclen, 4);
  135.     *hqx_rsrclen = mac2long(*hqx_rsrclen);
  136.     }
  137.  
  138.  
  139. /* This routine copies bytes from the decoded input stream to the output.  
  140.     It also pads to a multiple of 128 bytes on the output, which is part
  141.     of the .bin format */
  142. word hqx_to_bin_fork(nbytes)
  143. register ulong nbytes;
  144. {   register byte *c;
  145.     register ulong calc_crc;
  146.     register int c_length;
  147.     ulong extra_bytes;
  148.     extern word magic[];
  149.  
  150.     extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
  151.     calc_crc = 0;
  152.     for (;;) {
  153.         c = buf_ptr;
  154.         c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
  155.         nbytes -= c_length;
  156.         fwrite(c, sizeof(byte), c_length, binfile);
  157.         while (c_length--)
  158.             calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
  159.         if (!nbytes) break;
  160.         fill_hqxbuf();
  161.         }
  162.     buf_ptr = c;
  163.     while (extra_bytes--) putc(0, binfile);
  164.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  165.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  166.     return (word) calc_crc;
  167.     }
  168.  
  169. /* This routine copies bytes from the input stream to the encoded output.  
  170.     It also pads to a multiple of 128 bytes on the input, which is part
  171.     of the .bin format */
  172. word bin_to_hqx_fork(nbytes)
  173. register ulong nbytes;
  174. {   register byte *c;
  175.     register ulong calc_crc;
  176.     register int c_length;
  177.     ulong extra_bytes;
  178.     extern word magic[];
  179.  
  180.     extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
  181.     calc_crc = 0;
  182.     for (;;) {
  183.         c = buf_ptr;
  184.         c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
  185.         nbytes -= c_length;
  186.         fread(c, sizeof(byte), c_length, binfile);
  187.         buf_ptr += c_length;
  188.         while (c_length--)
  189.             calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
  190.         if (!nbytes) break;
  191.         empty_hqxbuf();
  192.         }
  193.     buf_ptr = c;
  194.  
  195.     fseek(binfile, extra_bytes, 1);
  196.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  197.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  198.     return (word) calc_crc;
  199.     }
  200.  
  201. /* Essentials for Binhex 8to6 run length encoding */
  202. #define RUNCHAR 0x90
  203. #define MAXRUN 255
  204. #define IS_LEGAL <0x40
  205. #define ISNT_LEGAL >0x3f
  206. #define DONE 0x7F /* tr68[':'] = DONE, since Binhex terminator is ':' */
  207. #define SKIP 0x7E /* tr68['\n'|'\r'] = SKIP, i. e. end of line char.  */
  208. #define FAIL 0x7D /* character illegal in binhex file */
  209.  
  210. byte tr86[] =
  211.         "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; 
  212. byte tr68[] = {
  213.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  214.     FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
  215.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  216.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  217.     FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  218.     0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
  219.     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
  220.     0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
  221.     0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
  222.     0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
  223.     0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
  224.     0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
  225.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
  226.     0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
  227.     0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
  228.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  229.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  230.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  231.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  232.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  233.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  234.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  235.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  236.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  237.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  238.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  239.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  240.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  241.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  242.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  243.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  244.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  245.     };
  246.  
  247. /*
  248.  *  This procedure transparently reads and decodes the hqx input.  It does run 
  249.  *  length and 6 to 8 decoding.
  250.  */
  251. #define READING 0
  252. #define SKIPPING 1
  253. #define FIND_START_COLON 2
  254.  
  255. fill_hqxbuf()
  256. {   register ulong c, nibble;
  257.     register int not_in_a_run = TRUE, state68;
  258.     register byte *fast_buf, *fast_line;
  259.     static int status = FIND_START_COLON;
  260.  
  261.     buf_ptr = fast_buf = buf_start;
  262.     fast_line = line_ptr;
  263.     state68 = save_state;
  264.     nibble = save_nibble;
  265.     if (save_run_length > 0) {
  266.         c = save_run_length;
  267.         save_run_length = 0;
  268.         goto continue_run;
  269.         }
  270.     while (fast_buf < buf_end) {
  271.         next_char:
  272.         if ((c = *fast_line++) ISNT_LEGAL) {
  273.             if (c == DONE) break;
  274.             next_line:
  275.             if (!fgets(line_start, MAXLINE, hqxfile) && !new_in_hqx_file())
  276.                 error("Premature EOF in %s\n", hqxfname);
  277.             line_ptr = line_start;
  278.             scan_line:
  279.             fast_line = line_ptr;
  280.             while ((*fast_line++ = tr68[*fast_line]) IS_LEGAL);
  281.             c = *--fast_line;
  282.             switch (status) {
  283.             case READING:
  284.                 if (c == SKIP && fast_line == line_end) break;
  285.                 if (c == DONE) {
  286.                     status = FIND_START_COLON;
  287.                     break;
  288.                     }
  289.                 status = SKIPPING;
  290.                 goto next_line;
  291.             case SKIPPING:
  292.                 if (c == SKIP && fast_line == line_end) {
  293.                     status = READING;
  294.                     break;
  295.                     }
  296.                 goto next_line;
  297.             case FIND_START_COLON:
  298.                 if (*line_start == DONE) {
  299.                     status = READING;
  300.                     line_ptr++;
  301.                     goto scan_line;
  302.                     }
  303.                 goto next_line;
  304.                 }
  305.             fast_line = line_ptr;
  306.             c = *fast_line++;
  307.             }
  308.  
  309.         /* Finally, we have the next 6 bits worth of data */
  310.         switch (state68++) {
  311.         case 0:
  312.             nibble = c;
  313.             goto next_char;
  314.         case 1:
  315.             nibble = (nibble << 6) | c;
  316.             c = nibble >> 4;
  317.             break;
  318.         case 2:
  319.             nibble = (nibble << 6) | c;
  320.             c = (nibble >> 2) & 0xff;
  321.             break;
  322.         case 3:
  323.             c = (nibble << 6) & 0xff | c;
  324.             state68 = 0;
  325.             break;
  326.             }
  327.         if (not_in_a_run)
  328.             if (c != RUNCHAR) *fast_buf++ = c;
  329.             else {not_in_a_run = FALSE; goto next_char;}
  330.         else {
  331.             if (c--) {
  332.                 not_in_a_run = buf_end - fast_buf;
  333.                 if (c > not_in_a_run) {
  334.                     save_run_length = c - not_in_a_run;
  335.                     c = not_in_a_run;
  336.                     }
  337.                 continue_run:
  338.                 not_in_a_run = fast_buf[-1];
  339.                 while (c--) *fast_buf++ = not_in_a_run;
  340.                 }
  341.             else *fast_buf++ = RUNCHAR;
  342.             not_in_a_run = TRUE;
  343.             }
  344.         }
  345.     total_bytes += fast_buf - buf_ptr;
  346.     buf_start[-1] = fast_buf[-1];
  347.     line_ptr = fast_line;
  348.     save_state = state68;
  349.     save_nibble = nibble;
  350.     }
  351.  
  352.  
  353. new_in_hqx_file()
  354. {   char *hqx_ext;
  355.     extern char **hqxnames_left;
  356.     if (*hqxnames_left[0] == '\0' || *hqxnames_left[0] == '-') return FALSE;
  357.     strcpy(hqxfname, *hqxnames_left++);
  358.     hqx_ext = hqxfname + strlen(hqxfname) - 4;
  359.     if (!strcmp(hqx_ext, ".hqx"))
  360.         if (!freopen(hqxfname, "r", hqxfile))
  361.             error("Cannot open %s\n", hqxfname);
  362.             else;
  363.     else {
  364.         if (!freopen(hqxfname, "r", hqxfile)) {
  365.             hqx_ext += 4;
  366.             strcpy(hqx_ext, ".hqx");
  367.             if (!freopen(hqxfname, "r", hqxfile)) {
  368.                 error("Cannot find %s\n", hqxfname);
  369.             }
  370.         }
  371.       }
  372.     fgets(line_start, MAXLINE, hqxfile);
  373.     return TRUE;
  374.     }
  375.  
  376. /*
  377.  *  This procedure transparently encodes and writes the hqx output.  
  378.  *  It does run length and 8 to 6 encoding.
  379.  */
  380. empty_hqxbuf()
  381. {   register ulong c, nibble, last_c;
  382.     register byte *fast_buf, *fast_line;
  383.     register int state86, dont_look_for_runs = FALSE, run_length;
  384.     extern int maxlines;
  385.  
  386.     run_length = save_run_length;
  387.     last_c = buf_start[-1];
  388.     fast_buf = buf_start;
  389.     fast_line = line_ptr;
  390.     state86 = save_state;
  391.     nibble = save_nibble;
  392.     while (fast_buf < buf_ptr) {
  393.         c = *fast_buf++;
  394.         if (dont_look_for_runs) dont_look_for_runs = FALSE;
  395.         else if (last_c == c &&  run_length < MAXRUN) {run_length++; continue;}
  396.         else {
  397.             if (run_length >1) {
  398.                 --fast_buf;
  399.                 if (run_length == 2 && last_c != RUNCHAR) c = last_c;
  400.                 else {
  401.                     c = RUNCHAR;
  402.                     *--fast_buf = run_length;
  403.                     dont_look_for_runs = TRUE;
  404.                     }
  405.                 run_length = 1;
  406.                 }
  407.             else last_c = c;
  408.             if (c == RUNCHAR && !dont_look_for_runs) {
  409.                 *--fast_buf = 0;
  410.                 dont_look_for_runs = TRUE;
  411.                 }
  412.             }
  413.  
  414.         if (fast_line == line_end) {
  415.             if (line_count++ == maxlines) new_out_hqx_file();
  416.             fputs(line_start, hqxfile);
  417.             fast_line = line_start;
  418.             }
  419.  
  420.         switch (state86++) {
  421.         case 0:
  422.             *fast_line++ = tr86[ c >> 2 ];
  423.             nibble = (c << 4) & 0x3f;
  424.             break;
  425.         case 1:
  426.             *fast_line++ = tr86[ (c >> 4) | nibble ];
  427.             nibble = (c << 2) & 0x3f;
  428.             break;
  429.         case 2:
  430.             *fast_line++ = tr86[ (c >> 6) | nibble ];
  431.             if (fast_line == line_end) {
  432.                 if (line_count++ == maxlines) new_out_hqx_file();
  433.                 fputs(line_start, hqxfile);
  434.                 fast_line = line_start;
  435.                 }
  436.             *fast_line++ = tr86[ c & 0x3f ];
  437.             state86 = 0;
  438.             break;
  439.             }
  440.         }
  441.     save_run_length = run_length;
  442.     buf_start[-1] = last_c;
  443.     buf_ptr = buf_start;
  444.     line_ptr = fast_line;
  445.     save_state = state86;
  446.     save_nibble = nibble;
  447.     }
  448.  
  449. new_out_hqx_file()
  450. {   char filename[NAMELEN + 7];
  451.     extern int maxlines;
  452.     fprintf(hqxfile, "<<< End of Part %2d >>>\n", file_count);
  453.     fclose(hqxfile);
  454.     file_count++;
  455.     if (maxlines) sprintf(filename, "%s%02d.hqx", hqxfname, file_count);
  456.     else sprintf(filename, "%s.hqx", hqxfname);
  457.     if ((hqxfile = fopen(filename, "w")) == NULL)
  458.         error("Can't create %s", filename);
  459.     if (file_count > 1)
  460.         fprintf(hqxfile, "<<< Start of Part %2d >>>\n", file_count);
  461.     else fprintf(hqxfile, "(This file must be converted with BinHex 4.0)\n\n");
  462.     line_count = 3;
  463.     }
  464.  
  465. check_hqx_crc(calc_crc, msg, name)
  466. word calc_crc;
  467. char msg[], name[];
  468. {   word read_crc;
  469.     if (buf_ptr >= buf_end) fill_hqxbuf();
  470.     read_crc = *buf_ptr++ << 8;
  471.     if (buf_ptr >= buf_end) fill_hqxbuf();
  472.     read_crc |= *buf_ptr++;
  473.     if (read_crc != calc_crc) error(msg, name);
  474.     }
  475.  
  476. write_hqx_crc(calc_crc)
  477. word calc_crc;
  478. {   if (buf_ptr == buf_end) empty_hqxbuf();
  479.     *buf_ptr++ = calc_crc >> 8;
  480.     if (buf_ptr == buf_end) empty_hqxbuf();
  481.     *buf_ptr++ = calc_crc;
  482.     }
  483.  
  484. un_hqx(unpit_flag)
  485. int unpit_flag;
  486. {   char type[4];
  487.     ulong hqx_datalen, hqx_rsrclen;
  488.     word un_pit();
  489.     int unpitting, bytes_read;
  490.     word calc_crc;
  491.     extern char **hqxnames_left;
  492.  
  493.     hqxfile = fopen("/dev/null", "r");
  494.     line_end = line_start + HQXLINELEN;
  495.     buf_end = buf_start + HQXBUFLEN;
  496.     while (*hqxnames_left[0] != '-') {
  497.         total_bytes = 0;
  498.         line_ptr = line_start;
  499.         line_ptr[0] = SKIP;
  500.         save_state = 0;
  501.         save_run_length = 0;
  502.  
  503.         hqx_to_bin_hdr(type, &hqx_datalen, &hqx_rsrclen); /* binfname */
  504.  
  505.         unpitting = unpit_flag && !strcmp(type, "PIT ");
  506.         if (unpitting) {
  507.             fclose(binfile);
  508.             unlink(binfname);
  509.             bytes_read = total_bytes - (buf_end - buf_ptr);
  510.             calc_crc = un_pit();
  511.             bytes_read = total_bytes - (buf_end - buf_ptr) - bytes_read;
  512.             if (bytes_read != hqx_datalen)
  513.                 fprintf(stderr,
  514.                   "Warning - Extraneous characters ignored in %s\n", binfname);
  515.             }
  516.         else calc_crc = hqx_to_bin_fork(hqx_datalen);
  517.         check_hqx_crc(calc_crc, "File data CRC mismatch in %s", binfname);
  518.  
  519.         calc_crc = hqx_to_bin_fork(hqx_rsrclen);
  520.         check_hqx_crc(calc_crc, "File rsrc CRC mismatch in %s", binfname);
  521.  
  522.         if (!unpitting) fclose(binfile);
  523.         }
  524.     }
  525.  
  526. re_hqx()
  527. {   word calc_crc;
  528.     ulong hqx_datalen, hqx_rsrclen;
  529.     extern char **hqxnames_left;
  530.     extern int maxlines;
  531.     line_end = line_start + HQXLINELEN;
  532.     buf_end = buf_start + HQXBUFLEN;
  533.     while (*hqxnames_left[0] != '-') {
  534.         hqxfile = fopen("/dev/null", "w");
  535.         line_count = maxlines;
  536.         file_count = 0;
  537.         line_ptr = line_start;
  538.         *line_ptr++ = ':';
  539.         strcpy(line_end, "\n");
  540.         buf_ptr = buf_start;
  541.         save_state = 0;
  542.         save_run_length = 1;
  543.  
  544.         bin_to_hqx_hdr(&hqx_datalen, &hqx_rsrclen);   /* calculates hqxfname */
  545.  
  546.         calc_crc = bin_to_hqx_fork(hqx_datalen);
  547.         write_hqx_crc(calc_crc);
  548.  
  549.         calc_crc = bin_to_hqx_fork(hqx_rsrclen);
  550.         write_hqx_crc(calc_crc);
  551.  
  552.         *buf_ptr++ = !buf_ptr[-1];      /* To end a run and to get the last */
  553.         empty_hqxbuf();                 /* stray bits, temporarily add a char */
  554.         if (save_state != 2) --line_ptr;
  555.         if (line_ptr == line_end) {
  556.             fputs(line_start, hqxfile);
  557.             line_ptr = line_start;
  558.             }
  559.         strcpy(line_ptr, ":\n");
  560.         fputs(line_start, hqxfile);
  561.         fclose(hqxfile);
  562.         }
  563.     }
  564.