/******************************************************************************* * * * UNJAC.C May 1992 * * * * Written in Borland C++ 2.0 under MS-DOS 5.0 * * Memory model = medium * * * *******************************************************************************/ #include typedef struct chardata { short charnum; // which character to be encoded short frequency; // frequency of occurance, }; #define FALSE 0 #define TRUE !FALSE // just for making code easy to use in different enviroments #define input fgetc(infile) #define output(i) fputc(i,outfile) struct chardata *table[256]; struct chardata *temp; FILE *infile; // file ptr to original file (uncompressed) FILE *outfile; // file ptr to output file char *infile_name; // ptr to name of input file char *outfile_name; // ptr to name of output file int n=0,S=0; int sort(short); int frequency_16_char(short); int timeout(void); int main(int argc, char **argv) { enum { IDLE, DECODE8, DECODE12_1,DECODE12_2 } decode_state = IDLE; register short c,X,quad_high; if (argc < 3) { // check command line arguments puts("'jac file1 file2 ' encodes file1 into file2."); return 1; } puts("Jac by TT, 1992"); infile_name = argv[1]; outfile_name = argv[2]; if (argc == 3) S=atoi(argv[3]); for (c=0; c < 256; c++) // initialize decode table { if ((table[c] = (struct chardata *)malloc(sizeof (struct chardata)))== NULL) { printf("Unable to allocate space for %dth table node.",c); return 1; } table[c]->charnum = c; // need to know who we are after sort table[c]->frequency = 1; } if ((infile=fopen(infile_name, "rb")) == NULL) // open the input file { printf("Unable to open %s.\n", infile_name); return 1; } outfile=fopen(outfile_name,"wb"); while (!timeout()) // get character distribution data { c = input; if (!timeout()) { switch (decode_state) { case IDLE: { X=c >> 4; // get high quad to X if (X < S) // check if quad is 4-bit character { output(table[X]->charnum); // store character S=sort(X); // sort table X=c & 0x0f; // get low quad if (X < S) // check if quad_low is also 4-bit character { output(table[X]->charnum); S=sort(X); // sort table decode_state=IDLE; // just be sure break; } else if (X==0x0f && S!=0) // if 12-bit character { decode_state=DECODE12_1; // quad 1111 received break; } else // else 8-bit character { decode_state=DECODE8; // high quad of 8-bit character received quad_high=c & 0x0f; // store value for 8-bit decoding break; } } else if (X==0x0f && S!=0) // 12-bit character { if (c < 256-S) // check first is X 8-bit char { X=c-(15*S); // get actual value of X output(table[X]->charnum); S=sort(X); decode_state=IDLE; // one byte decoded -> IDLE break; } else // byte must be part of 12-bit char { decode_state=DECODE12_2; quad_high=c & 0x0f; // store quad_high for 12-bit decoding; break; } } else // 8-bit character if (c<256-S) { X=c-(15*S); // get actual value of X output(table[X]->charnum); S=sort(X); decode_state=IDLE; // just be sure break; } } case DECODE8: { X=(quad_high << 4) + (c >> 4); // quad X=X-(15*S); output(table[X]->charnum); S=sort(X); X=c & 0x0f; // get low quad if (Xcharnum); S=sort(X); decode_state=IDLE; break; } else if (X==0x0f && S!=0) // low quad start of 12-bit { decode_state=DECODE12_1; break; } else { quad_high=c & 0x0f; // store low quad decode_state=DECODE8; break; } } case DECODE12_1:{ // 1111 quad already received, this is X X=0xf0+(c >> 4); X=X-15*S; if (X<(256-16*S)) // if 1111+high quad 8-bit value { output(table[X]->charnum); S=sort(X); X=c & 0x0f; // get low quad if (Xcharnum); S=sort(X); decode_state=IDLE; break; } else if (X==0x0f && S!=0) { decode_state=DECODE12_1; break; } else { quad_high=c & 0x0f; decode_state=DECODE8; break; } } else // must be 12-bit char if (c>255-16*S) { X=c; output(table[X]->charnum); S=sort(X); decode_state=IDLE; break; } } case DECODE12_2:{ X=(quad_high << 4) + (c >> 4); output(table[X]->charnum); S=sort(X); X=c & 0x0f; // get low quad if (X < S) // check if quad_low is also 4-bit character { output(table[X]->charnum); S=sort(X); decode_state=IDLE; break; } else if (X==0x0f && S!=0) // if 12-bit character { decode_state=DECODE12_1; break; } else // else 8-bit character { decode_state=DECODE8; quad_high=c & 0x0f; // store value for 8-bit decoding break; } } default: break; } // switch (deco.... } // if (!timeout .... } fclose(infile); // Close files fclose(outfile); // close files return 0; } // Function makes limited short // if function has been called 128 times // it calcultes new value for S int sort(short x) { int c,b; table[x]->frequency++; // update frequency // printf("%c",table[x]->charnum); if (x<16) c=0; else c=x-16; while((table[c]->frequency >= table[x]->frequency) || c==x) c++; // printf("c=%d\n",c); // If new frequency greater than value(s) above change places if (cfrequency >= table[b]->frequency) { table[x]=table[b]; // store original value to X place table[b]=temp; // replace new value to b temp=table[x]; // restore original value to temp } } table[x]=temp; } // Check is it time to calculate S set n++; // increment counter if (n==128) // Time to check SET S { // calculate best S value S=0; for (c=0;c<16;c++) if ((table[c]->frequency) > frequency_16_char(256-(c+1)*16)) S=c; printf("S=%d \t",S); // divide by two the original character count for (c=0;c<256;c++) table[c]->frequency >>=1; // set n to zero for next calculation n=0; } return S; } // Calculates total frequency of 16 characters starting from charcter c int frequency_16_char(short c) { int v,val=0; for(v=c;vfrequency; return val; } // Returns TRUE if timeout occurs // In this case timeout is only true if end of file infile int timeout(void) { if(!feof(infile)) return FALSE; else return TRUE; }