void write_compression(unsigned char sigbits[255], unsigned long bitencodings[255], FILE * fphuff, FILE * fporig) {//write the huffman compression to the output file //compression variables int readchar; int numsignificant; unsigned long encoding; //1000 0000 0000 0000 0000 0000 0000 0000 unsigned long mask = 0x80000000; bitspot = 0; currentbyte = 0; //write file while (!feof(fporig)) {//read every character in the file until the EOF is found readchar = fgetc(fporig); if (readchar != EOF) //keeps the standard EOF file from being written, we must write our own pseudo EOF {//save encoding, save amount of digits, shift the most significant bit to the far left encoding = bitencodings[(int) readchar]; numsignificant = sigbits[(int) readchar]; encoding <<= (32 - numsignificant); while (numsignificant > 0) {//loop until we have used all of the significant bits in our encoding if ((mask & encoding) == mask) {//if the furthest left bit is 1, pack a 1 write_bit(fphuff, 1); } else {//if the furthest left bit is 0, pack a 0 write_bit(fphuff, 0); } //set up the next bit to write, decrement the number of bits still to write encoding <<= 1; --numsignificant; } } } //write the pseudo EOF character, using ASCII NULL = 0000 0000 encoding = bitencodings[0]; numsignificant = sigbits[0]; encoding <<= (32 - numsignificant); //same as above, except dedicated to writing pseudo EOF while (numsignificant > 0) { if ((mask & encoding) == mask) { write_bit(fphuff, 1); } else { write_bit(fphuff, 0); } encoding <<= 1; --numsignificant; } //finish off the byte with 0's and write it pad_file(fphuff); return; }
int main(int argc, char * * argv) { int * weights = malloc(sizeof(int) * 256); char * filename = argv[1]; int count; int numNodes; numchar = 0; unsigned char sigbits[255] = {0}; unsigned long bitencodings[255] = {0}; Node * temp = NULL; Node * head = NULL; Node * root = NULL; if (argc > 2) {//error checking fprintf(stderr, "\nERROR! TOO MANY INPUTS, huff.c ACCEPTS 1 INPUT: FILENAME.txt\n\n"); return (ERROR); } FILE * fp = fopen(filename, "r"); if (fp == NULL) {//error checking fprintf(stderr, "\nERROR! FILE COULD NOT BE OPENED.\n\n"); return (ERROR); } //counting the frequencies of chars in the file weights = parse_file(weights, fp); fclose(fp); //generate linked list of non 0 weighted chars which are sorted in ascending order for (count = 0, numNodes = 0; count < 256; ++count) { if (weights[count] != 0) {//use all characters that showed up in the input file temp = create_node((char) count, weights[count]); if (head == NULL) {//if its the first node, set it as the head head = temp; } else {//insert the node into the list in ascending order head = insert_node(head, temp); }//keep track of the number of nodes in the list ++numNodes; } } //adding pseudo-EOF node temp = create_node((char) 0, 1); head = insert_node(head, temp); ++numNodes; //make huffman tree out of linked list root = create_tree(head, numNodes); //create sigbits and encodings from huffman tree bits = 0; countbits = 0; generate_encodings(root, sigbits, bitencodings); //file to read from FILE * fporig = fopen(filename, "r"); rewind(fporig); //file to write to strcat(filename, ".huff"); FILE * fphuff = fopen(filename, "w"); if (fporig == NULL || fphuff == NULL) {//error checking fprintf(stderr, "\nERROR! FILE COULD NOT BE OPENED.\n\n"); return (ERROR); } //write header bitspot = 0; currentbyte = 0; write_header(root, fphuff); //write an extra 0 so that the header reader can reach the exit condition write_bit(fphuff, 0); //pad with zeroes pad_file(fphuff); //write the number of characters fwrite(&numchar, sizeof(unsigned int), 1, fphuff); //write a newline which will mark the end of the header unsigned char newline = '\n'; fwrite(&newline, sizeof(unsigned char), 1, fphuff); //write compressed data with pseudo EOF and necessary padding write_compression(sigbits, bitencodings, fphuff, fporig); //were done fclose(fporig); fclose(fphuff); destroy_tree(root); return (0); }
int util_save_image(char *orig_file_name, char *save_file_name) { int origFd = -1, saveFd = -1; char *start_data, *end_data, *start_text, *end_round; struct exec old_hdr, new_hdr; struct stat old_stat; int n, page_size, length_text, length_data; if ((origFd = open(orig_file_name, 0)) < 0) { perror(orig_file_name); (void) fprintf(stderr, "Cannot open original a.out file\n"); goto bad; } if (fstat(origFd, &old_stat) < 0) { perror(orig_file_name); (void) fprintf(stderr, "Cannot stat original a.out file\n"); goto bad; } /* * Read the a.out header from the original file. */ if (read(origFd, (char *) &old_hdr, sizeof(old_hdr)) != sizeof(old_hdr)) { perror(orig_file_name); (void) fprintf(stderr, "Cannot read original a.out header\n"); goto bad; } if (N_BADMAG(old_hdr)) { (void) fprintf(stderr, "File %s has a bad magic number (%o)\n", orig_file_name, old_hdr.a_magic); goto bad; } if (old_hdr.a_magic != ZMAGIC) { (void) fprintf(stderr, "File %s is not demand-paged\n", orig_file_name); goto bad; } /* * Open the output file. */ if (access(save_file_name, /* F_OK */ 0) == 0) { (void) unlink(save_file_name); } if ((saveFd = creat(save_file_name, 0777)) < 0) { if (errno == ETXTBSY) { (void) unlink(save_file_name); saveFd = creat(save_file_name, 0777); } if (saveFd < 0) { perror(save_file_name); (void) fprintf(stderr, "Cannot create save file.\n"); goto bad; } } /* * Find out how far the data segment extends. */ new_hdr = old_hdr; end_data = sbrk(0); page_size = getpagesize(); n = ((((int) end_data) + page_size - 1) / page_size) * page_size; end_round = (char *) n; if (end_round > end_data) { end_data = sbrk(end_round - end_data); } #ifdef vax start_text = 0; length_text = new_hdr.a_text; start_data = (char *) old_hdr.a_text; length_data = end_data - start_data; #endif vax #ifdef sun start_text = (char *) N_TXTADDR(old_hdr) + sizeof(old_hdr); length_text = old_hdr.a_text - sizeof(old_hdr); start_data = (char *) N_DATADDR(old_hdr); length_data = end_data - start_data; #endif sun new_hdr.a_data = end_data - start_data; new_hdr.a_bss = 0; /* * First, the header plus enough pad to extend up to N_TXTOFF. */ if (write(saveFd, (char *) &new_hdr, (int) sizeof(new_hdr)) != sizeof(new_hdr)) { perror("write"); (void) fprintf(stderr, "Error while copying header.\n"); goto bad; } if (! pad_file(saveFd, N_TXTOFF(old_hdr) - sizeof(new_hdr))) { (void) fprintf(stderr, "Error while padding.\n"); goto bad; } /* * Copy our text segment */ if (write(saveFd, start_text, length_text) != length_text) { perror("write"); (void) fprintf(stderr, "Error while copying text segment.\n"); goto bad; } /* * Copy our data segment */ if (write(saveFd, start_data, length_data) != length_data) { perror("write"); (void) fprintf(stderr, "Error while copying data segment.\n"); goto bad; } /* * Copy the symbol table and everything else. * This takes us to the end of the original file. */ (void) lseek(origFd, (long) N_SYMOFF(old_hdr), 0); if (! copy_file(origFd, saveFd, old_stat.st_size - N_SYMOFF(old_hdr))) { (void) fprintf(stderr, "Error while copying symbol table.\n"); goto bad; } (void) close(origFd); (void) close(saveFd); return 1; bad: if (origFd >= 0) (void) close(origFd); if (saveFd >= 0) (void) close(saveFd); return 0; }