Γεια σου, ήθελα να μάθω την τιμή σας.
Sat Sep 12 03:35:09 EDT 2026
Sweep through our loaded casino game catalog <a href="https://vegastar-au.com/en-au/">https://vegastar-au.com/en-au/</a>
Sat Sep 12 01:06:29 EDT 2026
Stop paying for broad, unfocused visitors. Vantovo's AI targets by specific keywords and precise locations (down to city or zip), then continuously optimizes based on what actually engages. Start a free 7-day trial—no long-term contracts, cancel anytime. https://cutt.ly/NykOWBim
Fri Sep 11 20:06:14 EDT 2026
Fri Sep 11 19:49:34 EDT 2026
--- /usr/glenda/src/9front/sys/src/cmd/compress/compress.c
+++ compress.c
@@ -4,7 +4,7 @@
* Algorithm from "A Technique for High Performance Data Compression",
* Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
*
- * Usage: compress [-dfvc] [-b bits] [file ...]
+ * usage: compress [-dfvc] [-b bits] [file ...]
* Inputs:
* -b: limit the max number of bits/code.
* -c: write output on stdout, don't remove original.
@@ -90,11 +90,11 @@
typedef long code_int;
typedef long count_int;
-static char rcs_ident[] = "9front native: compress.c,v 4.0 85/07/30 12:50:00 joe
mama Release me";
+static char rcsident[] = "9front native: compress.c,v 4.0 85/07/30 12:50:00 joe
mama Release me";
-uchar magic_header[] = { 0x1F, 0x9D }; /* 1F 9D */
+uchar magicheader[] = { 0x1F, 0x9D }; /* 1F 9D */
-int n_bits; /* Number of bits/code */
+int nbits; /* Number of bits/code */
int maxbits = BITS; /* User settable max # bits/code */
code_int maxcode; /* Maximum code, given n_bits */
code_int maxmaxcode = 1 << BITS; /* Should NEVER generate this code */
@@ -105,14 +105,14 @@
code_int hsize = HSIZE; /* For dynamic table sizing */
count_int fsize;
-code_int free_ent = 0; /* first unused entry */
-int exit_stat = 0;
+code_int freeent = 0; /* first unused entry */
+int exitstat = 0;
code_int getcode();
int debug = 0;
int nomagic = 0; /* Use a 3-byte magic number header, unless old file */
-int zcat_flg = 0; /* Write output on stdout, suppress messages */
+int zcatflg = 0; /* Write output on stdout, suppress messages */
int quiet = 1; /* Don't tell me about compression */
/*
@@ -119,8 +119,8 @@
* Block compression parameters -- after all codes are used up,
* and compression rate changes, start over.
*/
-int block_compress = BLOCK_MASK;
-int clear_flg = 0;
+int blockcompress = BLOCK_MASK;
+int clearflg = 0;
long ratio = 0;
count_int checkpoint = CHECK_GAP;
@@ -128,12 +128,12 @@
char ofname [100];
void (*bgnd_flag)(int);
-int do_decomp = 0;
+int decomp = 0;
static int offset;
-long in_count = 1; /* Length of input */
-long bytes_out; /* Length of compressed output */
-long out_count = 0; /* # of codes output (for debugging) */
+long incount = 1; /* Length of input */
+long bytesout; /* Length of compressed output */
+long outcount = 0; /* # of codes output (for debugging) */
static char buf[BITS];
@@ -140,18 +140,20 @@
uchar lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
uchar rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+Biobuf *Fin, *Fout;
+
void
-Usage(void)
+usage(void)
{
- fprintf(stderr,"usage: compress [-cdfvV] [-b maxbits] [file ...]\n");
+ fprint(2, "usage: %s [-cdfvV] [-b maxbits] [file...]\n", argv0);
+ exits("usage");
}
void
version(void)
{
- fprintf(stderr, "%s\n", rcs_ident);
- fprintf(stderr, "Options: ");
- fprintf(stderr, "BITS = %d\n", BITS);
+ fprint(2, "%s\n", rcsident);
+ fprint(2, "Options: BITS = %d\n", BITS);
}
/*
@@ -161,101 +163,84 @@
int
foreground(void)
{
- if(bgnd_flag) /* background? */
+ char buf[64];
+
+ if(fd2path(2, buf, sizeof(buf)) < 0)
return 0;
- else /* foreground */
- return isatty(2); /* and stderr is a tty */
-}
-void
-onintr(int)
-{
- unlink(ofname);
- exit(1);
+ return strstr(buf, "cons") != nil;
}
void
-oops(int) /* wild pointer -- assume bad input */
+catchnote(void *ureg, char *msg)
{
- if (do_decomp == 1)
- fprintf(stderr, "uncompress: corrupt input\n");
- unlink(ofname);
- exit(1);
+ USED(ureg);
+ if(strncmp(msg, "sys:", 4) == 0){
+ if(decomp)
+ fprint(2, "uncompress: corrupt input\n");
+ remove(ofname);
+ exits(msg);
+ }
+
+ if(strncmp(msg, "interrupt", 9) == 0){
+ remove(ofname);
+ exits("interrupt");
+ }
+
+ noted(NDFLT);
}
void
-prratio(FILE *stream, long num, long den)
+prratio(long num, long den)
{
- int q; /* Doesn't need to be long */
+ int q;
- if(num > 214748L) /* 2147483647/10000 */
- q = num / (den / 10000L);
+ if(num > 214748L)
+ q = num / (den / 10000);
else
- q = 10000L * num / den; /* Long calculations, though */
- if (q < 0) {
- putc('-', stream);
+ q = 10000L * num / den;
+
+ if(q < 0){
+ fprint(2, "-");
q = -q;
}
- fprintf(stream, "%d.%02d%%", q / 100, q % 100);
+
+ fprint(2, "%d.%02d%%", q /100, q % 100);
}
void
-cl_hash(count_int hsize) /* reset code table */
+clhash(count_int hsize) /* Reset code table */
{
- count_int *htab_p;
+ count_int *htabp;
long i;
long m1;
- htab_p = htab + hsize;
- mi = -1;
+ htabp = htab + hsize;
+ m1 = -1;
i = hsize - 16;
- do { /* might use Sys V memset(3) here */
- *(htab_p-16) = m1;
- *(htab_p-15) = m1;
- *(htab_p-14) = m1;
- *(htab_p-13) = m1;
- *(htab_p-12) = m1;
- *(htab_p-11) = m1;
- *(htab_p-10) = m1;
- *(htab_p-9) = m1;
- *(htab_p-8) = m1;
- *(htab_p-7) = m1;
- *(htab_p-6) = m1;
- *(htab_p-5) = m1;
- *(htab_p-4) = m1;
- *(htab_p-3) = m1;
- *(htab_p-2) = m1;
- *(htab_p-1) = m1;
- htab_p -= 16;
- } while ((i -= 16) >= 0);
- for ( i += 16; i > 0; i-- )
- *--htab_p = m1;
-}
+ do{
+ *(htabp - 16) = m1;
+ *(htabp - 15) = m1;
+ *(htabp - 14) = m1;
+ *(htabp - 13) = m1;
+ *(htabp - 12) = m1;
+ *(htabp - 11) = m1;
+ *(htabp - 10) = m1;
+ *(htabp - 9) = m1;
+ *(htabp - 8) = m1;
+ *(htabp - 7) = m1;
+ *(htabp - 6) = m1;
+ *(htabp - 5) = m1;
+ *(htabp - 4) = m1;
+ *(htabp - 3) = m1;
+ *(htabp - 2) = m1;
+ *(htabp - 1) = m1;
+ htabp -= 16;
+ } while((i -= 16) >= 0);
-void
-cl_block (void) /* table clear for block compress */
-{
- long rat;
-
- checkpoint = in_count + CHECK_GAP;
- if (in_count > 0x007fffff) { /* shift will overflow */
- rat = bytes_out >> 8;
- if (rat == 0) /* Don't divide by zero */
- rat = 0x7fffffff;
- else
- rat = in_count / rat;
- } else
- rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
- if (rat > ratio)
- ratio = rat;
- else {
- ratio = 0;
- cl_hash((count_int)hsize);
- free_ent = FIRST;
- clear_flg = 1;
- output((code_int)CLEAR);
- }
+ for(i += 16; i > 0; i--)
+ *--htabp = m1;
}
/*
@@ -270,56 +255,60 @@
code_int
getcode(void)
{
- int r_off, bits;
+ int roff, bits;
code_int code;
static int offset = 0, size = 0;
static uchar buf[BITS];
- uchar *bp = buf;
+ uchar *bp;
- if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
+ bp = buf;
+
+ if(clearflg != 0 || offset >= size || freeent > maxcode){
/*
* If the next entry will be too big for the current code
- * size, then we must increase the size. This implies reading
+ * size, then we must increase the size. This implies reading
* a new buffer full, too.
*/
- if ( free_ent > maxcode ) {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode; /* won't get any bigger now */
+ if(freeent > maxcode){
+ nbits++;
+ if(nbits == maxbits)
+ maxcode = maxmaxcode; /* Won't get any bigger now */
else
- maxcode = MAXCODE(n_bits);
+ maxcode = MAXCODE(nbits);
}
- if ( clear_flg > 0) {
- maxcode = MAXCODE(n_bits = INIT_BITS);
- clear_flg = 0;
+ if(clearflg > 0){
+ maxcode = MAXCODE(nbits = INIT_BITS);
+ clearflg = 0;
}
- size = fread(buf, 1, n_bits, stdin);
- if (size <= 0)
- return -1; /* end of file */
+ size = Bread(Fin, buf, nbits);
+ if(size <= 0)
+ return -1;
offset = 0;
/* Round size down to integral number of codes */
- size = (size << 3) - (n_bits - 1);
+ size = (size << 3) - (nbits - 1);
}
- r_off = offset;
- bits = n_bits;
+ roff = offset;
+ bits = nbits;
/*
* Get to the first byte.
*/
- bp += (r_off >> 3);
- r_off &= 7;
+ bp += (roff >> 3);
+ roff &= 7;
/* Get first part (low order bits) */
- code = (*bp++ >> r_off);
- bits -= (8 - r_off);
- r_off = 8 - r_off; /* now, offset into code word */
+ code = (*bp++ >> roff);
+ bits -= (8 - roff);
+ roff = 8 - roff; /* Now, offset into code word */
/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if (bits >= 8) {
- code |= *bp++ << r_off;
- r_off += 8;
+ if(bits >= 8){
+ code |= *bp++ << roff;
+ roff += 8;
bits -= 8;
}
- /* high order bits. */
- code |= (*bp & rmask[bits]) << r_off;
- offset += n_bits;
+
+ /* High order bits. */
+ code |= (*bp & rmask[bits]) << roff;
+ offset += nbits;
+
return code;
}
@@ -326,49 +315,50 @@
void
writeerr(void)
{
- perror(ofname);
- unlink(ofname);
- exit(1);
+ fprint(2, "%s: %r\n", ofname);
+ remove(ofname);
+ exits("write error");
}
void
copystat(char *ifname, char *ofname)
{
- int mode;
- time_t timep[2];
- struct stat statbuf;
+ Dir *d, nd;
- fclose(stdout);
- if (stat(ifname, &statbuf)) { /* Get stat on input file */
- perror(ifname);
+ if((d = dirstat(ifname)) == nil){ /* Get stat on input file */
+ fprint(2, "%s: %r\n", ifname);
return;
}
- if (!S_ISREG(statbuf.st_mode)) {
- if (quiet)
- fprintf(stderr, "%s: ", ifname);
- fprintf(stderr, " -- not a regular file: unchanged");
- exit_stat = 1;
- } else if (exit_stat == 2 && !force) {
- /* No compression: remove file.Z */
- if (!quiet)
- fprintf(stderr, " -- file unchanged");
- } else { /* Successful Compression */
- exit_stat = 0;
- mode = statbuf.st_mode & 0777;
- if (chmod(ofname, mode)) /* Copy modes */
- perror(ofname);
- /* Copy ownership */
- chown(ofname, statbuf.st_uid, statbuf.st_gid);
- timep[0] = statbuf.st_atime;
- timep[1] = statbuf.st_mtime;
+ if(d->mode & DMDIR){
+ if(quiet)
+ fprint(2, "%s: ", ifname);
+ fprint(2, " -- not a regular file: unchanged");
+ exitstat = 1;
+ } else if(exitstat == 2 && !force){
+ if(!quiet)
+ fprint(2, " -- file unchanged");
+ } else { /* Successful Compression */
+ exitstat = 0;
+ nulldir(&nd);
+ nd.mode = d->mode & 0777;
/* Update last accessed and modified times */
- utime(ofname, timep);
- return; /* success */
+ nd.mtime = d->mtime;
+ nd.atime = d->atime;
+
+ /*
+ * Plan 9 has no chown(2) equivalent for arbitrary users;
+ * ownership of ofname is left to whoever created it
+ */
+ if(dirwstat(ofname, &nd) < 0)
+ fprint(2, "%s: %r\n", ofname);
+ free(d);
+ return;
}
/* Unsuccessful return -- one of the tests failed */
- if (unlink(ofname))
- perror(ofname);
+ free(d);
+ if(remove(ofname) < 0)
+ fprint(2, "%s: %r\n", ofname);
}
/*
@@ -389,32 +379,34 @@
void
output(code_int code)
{
- int r_off, bits;
+ int roff, bits;
char *bp;
- r_off = offset;
- bits = n_bits;
+ roff = offset;
+ bits = nbits;
bp = buf;
- if (code >= 0) {
+
/*
* byte/bit numbering on the VAX is simulated by the
* following code
- */
- /*
+ *
+ *
* Get to the first byte.
*/
- bp += (r_off >> 3);
- r_off &= 7;
+ if(code >= 0){
+ bp += (roff >> 3);
+ roff &= 7;
/*
* Since code is always >= 8 bits, only need to mask the first
* hunk on the left.
*/
- *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
+ *bp = (*bp & rmask[roff]) | (code << roff) & lmask[roff];
bp++;
- bits -= 8 - r_off;
- code >>= 8 - r_off;
+ bits -= 8 - roff;
+ code >>= 8 - roff;
+
/* Get any 8 bit parts in the middle (<=1 for up to 16 bits).
*/
- if ( bits >= 8 ) {
+ if(bits >= 8){
*bp++ = code;
code >>= 8;
bits -= 8;
@@ -423,14 +415,15 @@
if(bits)
*bp = code;
- offset += n_bits;
- if ( offset == (n_bits << 3) ) {
+ offset += nbits;
+ if(offset == (nbits << 3)){
bp = buf;
- bits = n_bits;
- bytes_out += bits;
- do {
- putchar(*bp++);
+ bits = nbits;
+ bytesout += bits;
+ do{
+ Bputc(Fout, *bp++);
} while(--bits);
+
offset = 0;
}
@@ -438,27 +431,27 @@
* If the next entry is going to be too big for the code size,
* then increase it, if possible.
*/
- if ( free_ent > maxcode || (clear_flg > 0)) {
+ if(freeent > maxcode || (clearflg > 0)){
/*
* Write the whole buffer, because the input side won't
* discover the size increase until after it has read it.
*/
- if ( offset > 0 ) {
- if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
+ if(offset > 0){
+ if(Bwrite(Fout, buf, nbits) != nbits)
writeerr();
- bytes_out += n_bits;
+ bytesout += nbits;
}
offset = 0;
- if ( clear_flg ) {
- maxcode = MAXCODE (n_bits = INIT_BITS);
- clear_flg = 0;
+ if(clearflg){
+ maxcode = MAXCODE(nbits = INIT_BITS);
+ clearflg = 0;
} else {
- n_bits++;
- if ( n_bits == maxbits )
+ nbits++;
+ if(nbits == maxbits)
maxcode = maxmaxcode;
else
- maxcode = MAXCODE(n_bits);
+ maxcode = MAXCODE(nbits);
}
}
} else {
@@ -465,16 +458,43 @@
/*
* At EOF, write the rest of the buffer.
*/
- if ( offset > 0 )
- fwrite( buf, 1, (offset + 7) / 8, stdout );
- bytes_out += (offset + 7) / 8;
+ if(offset > 0)
+ Bwrite(Fout, buf, (offset + 7) / 8);
+
+ bytesout += (offset + 7) / 8;
offset = 0;
- fflush( stdout );
- if( ferror( stdout ) )
+
+ if(Bflush(Fout) < 0)
writeerr();
}
}
+void
+clblock(void) /* table clear for block compress */
+{
+ long rat;
+
+ checkpoint = incount + CHECK_GAP;
+
+ if(incount > 0x007fffff){
+ rat = bytesout >> 8;
+ if(rat == 0)
+ rat = 0x7fffffff;
+ else
+ rat = incount / rat;
+ } else
+ rat = (incount << 8) / bytesout;
+ if(rat > ratio)
+ ratio = rat;
+ else {
+ ratio = 0;
+ clhash((count_int)hsize);
+ freeent = FIRST;
+ clearflg = 1;
+ output((code_int)CLEAR);
+ }
+}
+
/*
* compress stdin to stdout
*
@@ -491,89 +511,88 @@
* questions about this implementation to ames!jaw.
*/
void
-compress(void)
+compress(Biobuf *fin, Biobuf *fout)
{
- code_int ent, hsize_reg;
+ code_int ent, hsizereg;
code_int i;
int c, disp, hshift;
long fcode;
- if (nomagic == 0) {
- putchar(magic_header[0]);
- putchar(magic_header[1]);
- putchar((char)(maxbits | block_compress));
- if(ferror(stdout))
- writeerr();
+ Fin = fin;
+ Fout = fout;
+
+ if(nomagic == 0){
+ Bputc(Fout, magicheader[0]);
+ Bputc(Fout, magicheader[1]);
+ Bputc(Fout, (char)(maxbits | blockcompress));
}
offset = 0;
- bytes_out = 3; /* includes 3-byte header mojo */
- out_count = 0;
- clear_flg = 0;
+ bytesout = 3;
+ outcount = 0;
+ clearflg = 0;
ratio = 0;
- in_count = 1;
+ incount = 1;
checkpoint = CHECK_GAP;
- maxcode = MAXCODE(n_bits = INIT_BITS);
- free_ent = (block_compress? FIRST: 256);
+ maxcode = MAXCODE(nbits = INIT_BITS);
+ freeent = (blockcompress ? FIRST : 256);
- ent = getchar ();
+ ent = Bgetc(Fin);
hshift = 0;
- for (fcode = (long)hsize; fcode < 65536L; fcode *= 2)
+ for(fcode = (long)hsize; fcode < 65536L; fcode *= 2)
hshift++;
- hshift = 8 - hshift; /* set hash code range bound */
+ hshift = 8 - hshift;
- hsize_reg = hsize;
- cl_hash( (count_int) hsize_reg); /* clear hash table */
+ hsizereg = hsize;
+ clhash((count_int)hsizereg);
- while ((c = getchar()) != EOF) {
- in_count++;
- fcode = (long) (((long) c << maxbits) + ent);
- i = ((c << hshift) ^ ent); /* xor hashing */
+ while((c = Bgetc(Fin)) != -1){
+ incount++;
+ fcode = (long)(((long)c << maxbits) + ent);
+ i = ((c << hshift) ^ ent);
- if (Htabof (i) == fcode) {
+ if(Htabof(i) == fcode){
ent = Codetabof(i);
continue;
- } else if ((long)Htabof(i) < 0 ) /* empty slot */
+ } else if((long)Htabof(i) < 0)
goto nomatch;
- disp = hsize_reg - i; /* secondary hash (after G. Knott) */
- if (i == 0)
+
+ disp = hsizereg - i;
+ if(i == 0)
disp = 1;
+
probe:
- if ((i -= disp) < 0)
- i += hsize_reg;
+ if((i -= disp) < 0)
+ i+= hsizereg;
+ if(Htabof(i) == fcode){
+ ent = Codetabof(i);
+ continue;
+ }
+ if((long)Htabof(i) > 0)
+ goto probe;
- if (Htabof (i) == fcode) {
- ent = Codetabof(i);
- continue;
- }
- if ((long)Htabof(i) > 0)
- goto probe;
nomatch:
output((code_int)ent);
- out_count++;
- ent = c;
- if (free_ent < maxmaxcode) {
- Codetabof(i) = free_ent++; /* code -> hashtable */
+ outcount++;
+ ent = c;
+
+ if(freeent < maxmaxcode){
+ Codetabof(i) = freeent++;
Htabof(i) = fcode;
- } else if ((count_int)in_count >= checkpoint && block_compress)
- cl_block ();
+ } else if((count_int)incount >= checkpoint && blockcompress)
+ clblock();
}
- /*
- * Put out the final code.
- */
- output( (code_int)ent );
- out_count++;
- output( (code_int)-1 );
- /*
- * Print out stats on stderr
- */
- if(zcat_flg == 0 && !quiet) {
- fprintf( stderr, "Compression: " );
- prratio( stderr, in_count-bytes_out, in_count );
+ output((code_int)ent);
+ outcount++;
+ output((code_int)-1);
+
+ if(zcatflg == 0 && !quiet){
+ fprint(2, "Compression: ");
+ prratio(incount - bytesout, incount);
}
- if(bytes_out > in_count) /* exit(2) if no savings */
- exit_stat = 2;
+ if(bytesout > incount)
+ exitstat = 2;
}
/*
@@ -583,44 +602,46 @@
* with those of the compress() routine. See the definitions above.
*/
void
-decompress(void)
+decompress(Biobuf *fin, Biobuf *fout)
{
int finchar;
code_int code, oldcode, incode;
uchar *stackp;
+ Fin = fin;
+ Fout = fout;
+
/*
* As above, initialize the first 256 entries in the table.
*/
- maxcode = MAXCODE(n_bits = INIT_BITS);
- for (code = 255; code >= 0; code--) {
+ maxcode = MAXCODE(nbits = INIT_BITS);
+ for(code = 255; code >= 0; code--){
Tab_prefixof(code) = 0;
Tab_suffixof(code) = (uchar)code;
}
- free_ent = (block_compress? FIRST: 256);
+ freeent = (blockcompress ? FIRST : 256);
finchar = oldcode = getcode();
- if(oldcode == -1) /* EOF already? */
- return; /* Get out of here */
- putchar((char)finchar); /* first code must be 8 bits = char */
- if(ferror(stdout)) /* Crash if can't write */
- writeerr();
+ if(oldcode == -1) /* EOF already? */
+ return; /* Get out of here */
+ Bputc(Fout, (char)finchar); /* First code must be 8 bits = char */
stackp = De_stack;
- while ((code = getcode()) > -1) {
- if ((code == CLEAR) && block_compress) {
- for (code = 255; code >= 0; code--)
+ while((code = getcode()) > -1){
+ if((code == CLEAR) && blockcompress){
+ for(code = 255; code >= 0; code--)
Tab_prefixof(code) = 0;
- clear_flg = 1;
- free_ent = FIRST - 1;
- if ((code = getcode()) == -1) /* O, untimely death! */
- break;
+ clearflg = 1;
+ freeent = FIRST -1;
+ if((code = getcode()) == -1)
+ break;
}
- incode = code;
+
/*
* Special case for KwKwK string.
*/
- if (code >= free_ent) {
+ incode = code;
+ if(code >= freeent){
*stackp++ = finchar;
code = oldcode;
}
@@ -628,7 +649,7 @@
/*
* Generate output characters in reverse order
*/
- while (code >= 256) {
+ while(code >= 256){
*stackp++ = Tab_suffixof(code);
code = Tab_prefixof(code);
}
@@ -637,25 +658,25 @@
/*
* And put them out in forward order
*/
- do {
- putchar(*--stackp);
- } while (stackp > De_stack);
+ do{
+ Bputc(Fout, *--stackp);
+ } while(stackp > De_stack);
/*
* Generate the new entry.
*/
- if ( (code=free_ent) < maxmaxcode ) {
+ if((code = freeent) < maxmaxcode){
Tab_prefixof(code) = (ushort)oldcode;
Tab_suffixof(code) = finchar;
- free_ent = code+1;
+ freeent = code + 1;
}
+
/*
* Remember previous code.
*/
oldcode = incode;
}
- fflush(stdout);
- if(ferror(stdout))
+ if(Bflush(Fout) < 0)
writeerr();
}
@@ -663,70 +684,42 @@
main(int argc, char **argv)
{
int overwrite;
- char tempname[512];
+ char tmpname[512];
char **filelist, **fileptr;
char *cp;
- struct stat statbuf;
+ Dir *d;
+ int fd;
+ char response[2];
+ int consfd;
overwrite = 0; /* Do not overwrite unless given -f flag */
+ argv0 = argv[0];
- if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
- signal(SIGINT, onintr);
- signal(SIGSEGV, oops);
- }
+ notify(catchnote);
- filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
- *filelist = NULL;
-
- if((cp = strrchr(argv[0], '/')) != 0)
+ if((cp = strrchr(argv[0], '/')) != nil)
cp++;
else
cp = argv[0];
if(strcmp(cp, "uncompress") == 0)
- do_decomp = 1;
- else if(strcmp(cp, "zcat") == 0) {
- do_decomp = 1;
- zcat_flg = 1;
+ decomp = 1;
+ if(strcmp(cp, "zcat") == 0){
+ decomp = 1;
+ zcatflg = 1;
}
- /*
- * Argument Processing
- * All flags are optional.
- * -C generate output compatible with compress 2.0.
- * -D debug
- * -V print Version; debug verbose
- * -b maxbits maxbits. If -b is specified, then maxbits MUST be
- * given also.
- * -c cat all output to stdout
- * -d do_decomp
- * -f force overwrite of output file
- * -n no header: useful to uncompress old files
- * -v unquiet
- * if a string is left, must be an input filename.
- */
- for (argc--, argv++; argc > 0; argc--, argv++) {
- if (**argv == '-') { /* A flag argument */
- while (*++(*argv)) { /* Process all flags in this arg */
- switch (**argv) {
+ ARGBEGIN{
case 'C':
- block_compress = 0;
+ blockcompress = 0;
break;
- case 'V':
- version();
- break;
case 'b':
- if (!ARGVAL()) {
- fprintf(stderr, "Missing maxbits\n");
- Usage();
- exit(1);
- }
- maxbits = atoi(*argv);
- goto nextarg;
+ maxbits = atoi(EARGF(usage()));
+ break;
case 'c':
- zcat_flg = 1;
+ zcatflg = 1;
break;
case 'd':
- do_decomp = 1;
+ decomp = 1;
break;
case 'f':
case 'F':
@@ -742,185 +735,168 @@
case 'v':
quiet = 0;
break;
+ case 'V':
+ version();
+ break;
default:
- fprintf(stderr, "Unknown flag: '%c'; ", **argv);
- Usage();
- exit(1);
- }
- }
- } else { /* Input file name */
- *fileptr++ = *argv; /* Build input file list */
- *fileptr = NULL;
- /* process nextarg; */
- }
-nextarg:
- continue;
- }
+ usage();
+ }ARGEND
- if(maxbits < INIT_BITS) maxbits = INIT_BITS;
- if (maxbits > BITS) maxbits = BITS;
+ /*
+ * ARGBEGIN/ARGEND leaves argv[] holding just the non-flag
+ * filename arguments, nil-terMinated
+ */
+ fileptr = argv;
+ filelist = fileptr;
+
+ if(maxbits < INIT_BITS)
+ maxbits = INIT_BITS;
+ if(maxbits > BITS)
+ maxbits = BITS;
+
maxmaxcode = 1 << maxbits;
- if (*filelist != NULL) {
- for (fileptr = filelist; *fileptr; fileptr++) {
- exit_stat = 0;
- if (do_decomp != 0) { /* DECOMPRESSION */
- /* Check for .Z suffix */
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
- /* No .Z: tack one on */
- strcpy(tempname, *fileptr);
- strcat(tempname, ".Z");
- *fileptr = tempname;
- }
- /* Open input file */
- if ((freopen(*fileptr, "r", stdin)) == NULL) {
- perror(*fileptr);
- continue;
- }
- /* Check the magic number */
- if (nomagic == 0) {
- if ((getchar() != (magic_header[0] & 0xFF))
- || (getchar() != (magic_header[1] & 0xFF))) {
- fprintf(stderr, "%s: not in compressed format\n",
- *fileptr);
- continue;
- }
- maxbits = getchar(); /* set -b from file */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- maxmaxcode = 1 << maxbits;
- if(maxbits > BITS) {
- fprintf(stderr,
- "%s: compressed with %d bits, can only handle %d bits\n",
- *fileptr, maxbits, BITS);
- continue;
- }
- }
- /* Generate output filename */
- strcpy(ofname, *fileptr);
- ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .Z */
- } else { /* COMPRESSION */
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
- fprintf(stderr,
- "%s: already has .Z suffix -- no change\n",
- *fileptr);
- continue;
- }
- /* Open input file */
- if ((freopen(*fileptr, "r", stdin)) == NULL) {
- perror(*fileptr);
- continue;
- }
- (void) stat(*fileptr, &statbuf);
- fsize = (long) statbuf.st_size;
- /*
- * tune hash table size for small files -- ad hoc,
- * but the sizes match earlier #defines, which
- * serve as upper bounds on the number of output codes.
- */
- hsize = HSIZE;
- if (fsize < (1 << 12))
- hsize = Min(5003, HSIZE);
- else if (fsize < (1 << 13))
- hsize = Min(9001, HSIZE);
- else if (fsize < (1 << 14))
- hsize = Min (18013, HSIZE);
- else if (fsize < (1 << 15))
- hsize = Min (35023, HSIZE);
- else if (fsize < 47000)
- hsize = Min (50021, HSIZE);
+ if(*filelist != nil){
+ for(fileptr = filelist; *fileptr; fileptr++){
+ exitstat = 0;
+ if(decomp != 0){ /* Decompression */
+ if(strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0){
+ snprint(tmpname, sizeof(tmpname), "%s.Z", *fileptr);
+ *fileptr = tmpname;
+ }
+ if((Fin = Bopen(*fileptr, OREAD)) == nil){
+ fprint(2, "%s: %r\n", *fileptr);
+ continue;
+ }
+ if(nomagic == 0){
+ if(Bgetc(Fin) != (magicheader[0] & 0xff)
+ || Bgetc(Fin) != (magicheader[1] & 0xff)){
+ fprint(2, "%s: not in compressed format\n", *fileptr);
+ Bterm(Fin);
+ continue;
+ }
+ maxbits = Bgetc(Fin);
+ blockcompress = maxbits & BLOCK_MASK;
+ maxbits &= BIT_MASK;
+ maxmaxcode = 1 << maxbits;
+ if(maxbits > BITS){
+ fprint(2, "%s: compressed with %d bits, can only handle %d bits\n",
+ *fileptr, maxbits, BITS);
+ Bterm(Fin);
+ continue;
+ }
+ }
+ strcpy(ofname, *fileptr);
+ ofname[strlen(*fileptr) - 2] = '\0'; /* Strip ending .Z */
+ } else { /* Compression */
+ if(strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0){
+ fprint(2, "%s: already has .Z suffix -- no change\n", *fileptr);
+ continue;
+ }
+ if((Fin = Bopen(*fileptr, OREAD)) == nil){
+ fprint(2, "%s: %r\n", *fileptr);
+ continue;
+ }
+ if((d = dirstat(*fileptr)) != nil){
+ fsize = d->length;
+ free(d);
+ } else
+ fsize = 0;
- /* Generate output filename */
- strcpy(ofname, *fileptr);
- if ((cp=strrchr(ofname,'/')) != NULL)
- cp++;
- else
- cp = ofname;
- /*
- *** changed 12 to 25; should be NAMELEN-3, but I don't want
- * to fight the headers. ehg 5 Nov 92 **
- */
- if (strlen(cp) > 25) {
- fprintf(stderr, "%s: filename too long to tack on .Z\n",
- cp);
- continue;
- }
- strcat(ofname, ".Z");
- }
- /* Check for overwrite of existing file */
- if (overwrite == 0 && zcat_flg == 0 &&
- stat(ofname, &statbuf) == 0) {
- char response[2];
+ hsize = HSIZE;
+ if(fsize < (1 << 12))
+ hsize = Min(5003, HSIZE);
+ else if(fsize < (1 << 13))
+ hsize = Min(9001, HSIZE);
+ else if(fsize < (1 << 14))
+ hsize = Min(18013, HSIZE);
+ else if(fsize < (1 << 15))
+ hsize = Min (35023, HSIZE);
+ else if (fsize < 47000)
+ hsize = Min (50021, HSIZE);
- response[0] = 'n';
- fprintf(stderr, "%s already exists;", ofname);
- if (foreground()) {
- fprintf(stderr,
- " do you wish to overwrite %s (y or n)? ",
- ofname);
- fflush(stderr);
- (void) read(2, response, 2);
- while (response[1] != '\n')
- if (read(2, response+1, 1) < 0) {
- /* Ack! */
- perror("stderr");
- break;
+ snprint(ofname, sizeof(ofname), "%s.Z", *fileptr);
+ }
+ if(overwrite == 0 && zcatflg == 0 && (d = dirstat(ofname)) != nil){
+ free(d);
+ response[0] = 'n';
+ fprint(2, "%s already exists;", ofname);
+ if(foreground() != 0){
+ if((consfd = open("/dev/cons", OREAD)) >= 0){
+ fprint(2, " do you wish to overwrite %s (y or n)?", ofname);
+ (void) read(consfd, response, 2);
+ while(response[1] != '\n')
+ if(read(2, response + 1, 1) < 0){
+ fprint(2, "/dev/cons: %r/n");
+ break;;
+ }
+ close(consfd);
}
+ }
+ if(response[0] != 'y'){
+ fprint(2, "\tnot overwritten\n");
+ Bterm(Fin);
+ continue;
+ }
}
- if (response[0] != 'y') {
- fprintf(stderr, "\tnot overwritten\n");
- continue;
- }
- }
- if(zcat_flg == 0) { /* Open output file */
- if (freopen(ofname, "w", stdout) == NULL) {
- perror(ofname);
- continue;
- }
- if(!quiet)
- fprintf(stderr, "%s: ", *fileptr);
- }
+ if(zcatflg == 0){
+ fd = create(ofname, OWRITE, 0666);
+ if(fd < 0 || (Fout = Bfdopen(fd, OWRITE)) == nil){
+ fprint(2, "%s: %r\n", ofname);
+ Bterm(Fin);
+ continue;
+ }
+ if(!quiet)
+ fprint(2, "%s: ", *fileptr);
+ } else
+ Fout = Bfdopen(1, OWRITE);
+ if(decomp == 0)
+ compress(Fin, Fout);
+ else
+ decompress(Fin, Fout);
- /* Actually do the compression/decompression */
- if (do_decomp == 0)
- compress();
- else
- decompress();
- if(zcat_flg == 0) {
- copystat(*fileptr, ofname); /* Copy stats */
- if (exit_stat == 1 || !quiet)
- putc('\n', stderr);
+ Bterm(Fin);
+ Bflush(Fout);
+ if(zcatflg == 0){
+ Bterm(Fout);
+ copystat(*fileptr, ofname);
+ if(exitstat == 1 || !quiet)
+ fprint(2, "\n");
+ } else
+ Bterm(Fout);
}
- }
- } else { /* Standard input */
- if (do_decomp == 0) {
- compress();
- if(!quiet)
- putc('\n', stderr);
} else {
- /* Check the magic number */
- if (nomagic == 0) {
- if ((getchar()!=(magic_header[0] & 0xFF))
- || (getchar()!=(magic_header[1] & 0xFF))) {
- fprintf(stderr, "stdin: not in compressed format\n");
- exit(1);
+ Fin = Bfdopen(0, OREAD);
+ Fout = Bfdopen(1, OWRITE);
+ if(decomp == 0){
+ compress(Fin, Fout);
+ if(!quiet)
+ fprint(2, "\n");
+ } else {
+ if(nomagic == 0){
+ if(Bgetc(Fin) != (magicheader[0] & 0xff)
+ || Bgetc(Fin) != (magicheader[1] & 0xff)){
+ fprint(2, "stdin: not in compressed format\n");
+ exits("format");
+ }
+ maxbits = Bgetc(Fin);
+ blockcompress = maxbits & BLOCK_MASK;
+ maxbits &= BIT_MASK;
+ maxmaxcode = 1 << maxbits;
+ fsize = 100000;
+ if(maxbits > BITS){
+ fprint(2, "stdin: compressed with %d bits, can only handle %d bits\n",
+ maxbits, BITS);
+ exits("format");
+ }
+ }
+ decompress(Fin, Fout);
}
- maxbits = getchar(); /* set -b from file */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- maxmaxcode = 1 << maxbits;
- fsize = 100000; /* assume stdin large for USERMEM */
- if(maxbits > BITS) {
- fprintf(stderr,
- "stdin: compressed with %d bits, can only handle %d bits\n",
- maxbits, BITS);
- exit(1);
- }
- }
- decompress();
+ Bflush(Fout);
+ Bterm(Fin);
+ Bterm(Fout);
}
- }
- exit(exit_stat);
+ exits(exitstat ? "error": nil);
}
/*
Fri Sep 11 19:48:34 EDT 2026
--- /usr/glenda/src/9front/sys/src/cmd/compress/compress.c
+++ compress.c
@@ -26,9 +26,9 @@
* Algorithm:
* Modified Lempel-Ziv method (LZW). Basically finds common
* substrings and replaces them with a variable size code. This is
- * deterministic, and can be done on the fly. Thus, the decompression
+ * deterMinistic, and can be done on the fly. Thus, the decompression
* procedure needs no input table, but tracks the way the table was built.
-
+ *
* Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
* Jim McKie (decvax!mcvax!jim)
* Steve Davies (decvax!vax135!petsd!peora!srd)
@@ -36,138 +36,640 @@
* James A. Woods (decvax!ihnp4!ames!jaw)
* Joe Orost (decvax!vax135!petsd!joe)
*/
-#define _PLAN9_SOURCE
-
#include <u.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <libc.h>
+#include <bio.h>
-#define min(a,b) ((a>b) ? b : a)
+#define Min(a,b) ((a>b) ? b : a)
#define BITS 16
-#define HSIZE 69001 /* 95% occupancy */
+#define HSIZE 69001 /* 95% occupancy */
-/*
- * a code_int must be able to hold 2**BITS values of type int, and also -1
- */
-typedef long code_int;
-typedef long count_int;
+#define CHECK_GAP 10000 /* Ratio check interval */
-static char rcs_ident[] = "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe
Release $";
-
-uchar magic_header[] = { 0x1F, 0x9D }; /* 1F 9D */
-
/* Defines for third byte of header */
#define BIT_MASK 0x1f
#define BLOCK_MASK 0x80
-/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
- a fourth header byte (for expansion).
-*/
-#define INIT_BITS 9 /* initial number of bits/code */
-void onintr(int);
-void oops(int);
+/*
+ * Masks 0x40 and 0x20 are free.
+ * I think 0x20 should mean that there is a fourth header byte
+ * (for expansion).
+ */
+#define INIT_BITS 9 /* initial number of bits/code */
#define ARGVAL() (*++(*argv) || (--argc && *++argv))
-int n_bits; /* number of bits/code */
-int maxbits = BITS; /* user settable max # bits/code */
-code_int maxcode; /* maximum code, given n_bits */
-code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */
-
#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
-count_int htab[HSIZE];
-ushort codetab[HSIZE];
+#define Htabof(i) htab[i]
+#define Codetabof(i) codetab[i]
-#define htabof(i) htab[i]
-#define codetabof(i) codetab[i]
-
-code_int hsize = HSIZE; /* for dynamic table sizing */
-count_int fsize;
-
/*
* To save much memory, we overlay the table used by compress() with those
- * used by decompress(). The tab_prefix table is the same size and type
- * as the codetab. The tab_suffix table needs 2**BITS characters. We
- * get this from the beginning of htab. The output stack uses the rest
- * of htab, and contains characters. There is plenty of room for any
+ * used by decompress(). The tab_prefix table is the same size and type
+ * as the codetab. The tab_suffix table needs 2**BITS characters. We
+ * get this from the beginning of htab. The output stack uses the rest
+ * of htab, and contains characters. There is plenty of room for any
* possible stack (stack used to be 8000 characters).
*/
+#define Tab_prefixof(i) Codetabof(i)
+#define Tab_suffixof(i) ((uchar *)(htab))[i]
+#define De_stack ((uchar *)&Tab_suffixof(1<<BITS))
-#define tab_prefixof(i) codetabof(i)
-#define tab_suffixof(i) ((uchar *)(htab))[i]
-#define de_stack ((uchar *)&tab_suffixof(1<<BITS))
+/*
+ * The next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define FIRST 257 /* First free entry */
+#define CLEAR 256 /* Table clear output code */
+/*
+ * A code_int must be able to hold 2**BITS values of type int, and also -1
+ */
+typedef long code_int;
+typedef long count_int;
+
+static char rcs_ident[] = "9front native: compress.c,v 4.0 85/07/30 12:50:00 joe
mama Release me";
+
+uchar magic_header[] = { 0x1F, 0x9D }; /* 1F 9D */
+
+int n_bits; /* Number of bits/code */
+int maxbits = BITS; /* User settable max # bits/code */
+code_int maxcode; /* Maximum code, given n_bits */
+code_int maxmaxcode = 1 << BITS; /* Should NEVER generate this code */
+
+count_int htab[HSIZE];
+ushort codetab[HSIZE];
+
+code_int hsize = HSIZE; /* For dynamic table sizing */
+count_int fsize;
+
code_int free_ent = 0; /* first unused entry */
int exit_stat = 0;
code_int getcode();
-void
-Usage(void)
-{
-#ifdef DEBUG
- fprintf(stderr,"usage: compress [-cdfDV] [-b maxbits] [file ...]\n");
-#else
- fprintf(stderr,"usage: compress [-cdfvV] [-b maxbits] [file ...]\n");
-#endif /* DEBUG */
-}
-
int debug = 0;
int nomagic = 0; /* Use a 3-byte magic number header, unless old file */
int zcat_flg = 0; /* Write output on stdout, suppress messages */
-int quiet = 1; /* don't tell me about compression */
+int quiet = 1; /* Don't tell me about compression */
/*
- * block compression parameters -- after all codes are used up,
+ * Block compression parameters -- after all codes are used up,
* and compression rate changes, start over.
*/
int block_compress = BLOCK_MASK;
int clear_flg = 0;
long ratio = 0;
-#define CHECK_GAP 10000 /* ratio check interval */
count_int checkpoint = CHECK_GAP;
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define FIRST 257 /* first free entry */
-#define CLEAR 256 /* table clear output code */
int force = 0;
char ofname [100];
-#ifdef DEBUG
-int verbose = 0;
-#endif /* DEBUG */
void (*bgnd_flag)(int);
int do_decomp = 0;
-void decompress(void);
-void compress(void);
-void output(code_int);
-void writeerr(void);
-void copystat(char*, char*);
-void cl_block(void);
-void cl_hash(long);
-void prratio(FILE*, long, long);
-void version(void);
+static int offset;
+long in_count = 1; /* Length of input */
+long bytes_out; /* Length of compressed output */
+long out_count = 0; /* # of codes output (for debugging) */
+static char buf[BITS];
+
+uchar lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
+uchar rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
void
+Usage(void)
+{
+ fprintf(stderr,"usage: compress [-cdfvV] [-b maxbits] [file ...]\n");
+}
+
+void
+version(void)
+{
+ fprintf(stderr, "%s\n", rcs_ident);
+ fprintf(stderr, "Options: ");
+ fprintf(stderr, "BITS = %d\n", BITS);
+}
+
+/*
+ * This routine returns 1 if we are running in the foreground and stderr
+ * is a tty.
+ */
+int
+foreground(void)
+{
+ if(bgnd_flag) /* background? */
+ return 0;
+ else /* foreground */
+ return isatty(2); /* and stderr is a tty */
+}
+
+void
+onintr(int)
+{
+ unlink(ofname);
+ exit(1);
+}
+
+void
+oops(int) /* wild pointer -- assume bad input */
+{
+ if (do_decomp == 1)
+ fprintf(stderr, "uncompress: corrupt input\n");
+ unlink(ofname);
+ exit(1);
+}
+
+void
+prratio(FILE *stream, long num, long den)
+{
+ int q; /* Doesn't need to be long */
+
+ if(num > 214748L) /* 2147483647/10000 */
+ q = num / (den / 10000L);
+ else
+ q = 10000L * num / den; /* Long calculations, though */
+ if (q < 0) {
+ putc('-', stream);
+ q = -q;
+ }
+ fprintf(stream, "%d.%02d%%", q / 100, q % 100);
+}
+
+void
+cl_hash(count_int hsize) /* reset code table */
+{
+ count_int *htab_p;
+ long i;
+ long m1;
+
+ htab_p = htab + hsize;
+ mi = -1;
+
+ i = hsize - 16;
+ do { /* might use Sys V memset(3) here */
+ *(htab_p-16) = m1;
+ *(htab_p-15) = m1;
+ *(htab_p-14) = m1;
+ *(htab_p-13) = m1;
+ *(htab_p-12) = m1;
+ *(htab_p-11) = m1;
+ *(htab_p-10) = m1;
+ *(htab_p-9) = m1;
+ *(htab_p-8) = m1;
+ *(htab_p-7) = m1;
+ *(htab_p-6) = m1;
+ *(htab_p-5) = m1;
+ *(htab_p-4) = m1;
+ *(htab_p-3) = m1;
+ *(htab_p-2) = m1;
+ *(htab_p-1) = m1;
+ htab_p -= 16;
+ } while ((i -= 16) >= 0);
+ for ( i += 16; i > 0; i-- )
+ *--htab_p = m1;
+}
+
+void
+cl_block (void) /* table clear for block compress */
+{
+ long rat;
+
+ checkpoint = in_count + CHECK_GAP;
+ if (in_count > 0x007fffff) { /* shift will overflow */
+ rat = bytes_out >> 8;
+ if (rat == 0) /* Don't divide by zero */
+ rat = 0x7fffffff;
+ else
+ rat = in_count / rat;
+ } else
+ rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
+ if (rat > ratio)
+ ratio = rat;
+ else {
+ ratio = 0;
+ cl_hash((count_int)hsize);
+ free_ent = FIRST;
+ clear_flg = 1;
+ output((code_int)CLEAR);
+ }
+}
+
+/*
+ * TAG( getcode )
+ *
+ * Read one code from the standard input. If EOF, return -1.
+ * Inputs:
+ * stdin
+ * Outputs:
+ * code or -1 is returned.
+ */
+code_int
+getcode(void)
+{
+ int r_off, bits;
+ code_int code;
+ static int offset = 0, size = 0;
+ static uchar buf[BITS];
+ uchar *bp = buf;
+
+ if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
+ /*
+ * If the next entry will be too big for the current code
+ * size, then we must increase the size. This implies reading
+ * a new buffer full, too.
+ */
+ if ( free_ent > maxcode ) {
+ n_bits++;
+ if ( n_bits == maxbits )
+ maxcode = maxmaxcode; /* won't get any bigger now */
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ if ( clear_flg > 0) {
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ clear_flg = 0;
+ }
+ size = fread(buf, 1, n_bits, stdin);
+ if (size <= 0)
+ return -1; /* end of file */
+ offset = 0;
+ /* Round size down to integral number of codes */
+ size = (size << 3) - (n_bits - 1);
+ }
+ r_off = offset;
+ bits = n_bits;
+ /*
+ * Get to the first byte.
+ */
+ bp += (r_off >> 3);
+ r_off &= 7;
+ /* Get first part (low order bits) */
+ code = (*bp++ >> r_off);
+ bits -= (8 - r_off);
+ r_off = 8 - r_off; /* now, offset into code word */
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if (bits >= 8) {
+ code |= *bp++ << r_off;
+ r_off += 8;
+ bits -= 8;
+ }
+ /* high order bits. */
+ code |= (*bp & rmask[bits]) << r_off;
+ offset += n_bits;
+ return code;
+}
+
+void
+writeerr(void)
+{
+ perror(ofname);
+ unlink(ofname);
+ exit(1);
+}
+
+void
+copystat(char *ifname, char *ofname)
+{
+ int mode;
+ time_t timep[2];
+ struct stat statbuf;
+
+ fclose(stdout);
+ if (stat(ifname, &statbuf)) { /* Get stat on input file */
+ perror(ifname);
+ return;
+ }
+ if (!S_ISREG(statbuf.st_mode)) {
+ if (quiet)
+ fprintf(stderr, "%s: ", ifname);
+ fprintf(stderr, " -- not a regular file: unchanged");
+ exit_stat = 1;
+ } else if (exit_stat == 2 && !force) {
+ /* No compression: remove file.Z */
+ if (!quiet)
+ fprintf(stderr, " -- file unchanged");
+ } else { /* Successful Compression */
+ exit_stat = 0;
+ mode = statbuf.st_mode & 0777;
+ if (chmod(ofname, mode)) /* Copy modes */
+ perror(ofname);
+ /* Copy ownership */
+ chown(ofname, statbuf.st_uid, statbuf.st_gid);
+ timep[0] = statbuf.st_atime;
+ timep[1] = statbuf.st_mtime;
+ /* Update last accessed and modified times */
+ utime(ofname, timep);
+ return; /* success */
+ }
+
+ /* Unsuccessful return -- one of the tests failed */
+ if (unlink(ofname))
+ perror(ofname);
+}
+
+/*
+ * TAG( output )
+ *
+ * Output the given code.
+ * Inputs:
+ * code: A n_bits-bit integer. If == -1, then EOF. This assumes
+ * that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a BITS character long buffer (so that 8 codes will
+ * fit in it exactly). When the buffer fills up empty it and start over.
+ */
+void
+output(code_int code)
+{
+ int r_off, bits;
+ char *bp;
+
+ r_off = offset;
+ bits = n_bits;
+ bp = buf;
+ if (code >= 0) {
+ /*
+ * byte/bit numbering on the VAX is simulated by the
+ * following code
+ */
+ /*
+ * Get to the first byte.
+ */
+ bp += (r_off >> 3);
+ r_off &= 7;
+ /*
+ * Since code is always >= 8 bits, only need to mask the first
+ * hunk on the left.
+ */
+ *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
+ bp++;
+ bits -= 8 - r_off;
+ code >>= 8 - r_off;
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if ( bits >= 8 ) {
+ *bp++ = code;
+ code >>= 8;
+ bits -= 8;
+ }
+ /* Last bits. */
+ if(bits)
+ *bp = code;
+
+ offset += n_bits;
+ if ( offset == (n_bits << 3) ) {
+ bp = buf;
+ bits = n_bits;
+ bytes_out += bits;
+ do {
+ putchar(*bp++);
+ } while(--bits);
+ offset = 0;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+ if ( free_ent > maxcode || (clear_flg > 0)) {
+ /*
+ * Write the whole buffer, because the input side won't
+ * discover the size increase until after it has read it.
+ */
+ if ( offset > 0 ) {
+ if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
+ writeerr();
+ bytes_out += n_bits;
+ }
+ offset = 0;
+
+ if ( clear_flg ) {
+ maxcode = MAXCODE (n_bits = INIT_BITS);
+ clear_flg = 0;
+ } else {
+ n_bits++;
+ if ( n_bits == maxbits )
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ }
+ } else {
+ /*
+ * At EOF, write the rest of the buffer.
+ */
+ if ( offset > 0 )
+ fwrite( buf, 1, (offset + 7) / 8, stdout );
+ bytes_out += (offset + 7) / 8;
+ offset = 0;
+ fflush( stdout );
+ if( ferror( stdout ) )
+ writeerr();
+ }
+}
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+void
+compress(void)
+{
+ code_int ent, hsize_reg;
+ code_int i;
+ int c, disp, hshift;
+ long fcode;
+
+ if (nomagic == 0) {
+ putchar(magic_header[0]);
+ putchar(magic_header[1]);
+ putchar((char)(maxbits | block_compress));
+ if(ferror(stdout))
+ writeerr();
+ }
+ offset = 0;
+ bytes_out = 3; /* includes 3-byte header mojo */
+ out_count = 0;
+ clear_flg = 0;
+ ratio = 0;
+ in_count = 1;
+ checkpoint = CHECK_GAP;
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ free_ent = (block_compress? FIRST: 256);
+
+ ent = getchar ();
+
+ hshift = 0;
+ for (fcode = (long)hsize; fcode < 65536L; fcode *= 2)
+ hshift++;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ hsize_reg = hsize;
+ cl_hash( (count_int) hsize_reg); /* clear hash table */
+
+ while ((c = getchar()) != EOF) {
+ in_count++;
+ fcode = (long) (((long) c << maxbits) + ent);
+ i = ((c << hshift) ^ ent); /* xor hashing */
+
+ if (Htabof (i) == fcode) {
+ ent = Codetabof(i);
+ continue;
+ } else if ((long)Htabof(i) < 0 ) /* empty slot */
+ goto nomatch;
+ disp = hsize_reg - i; /* secondary hash (after G. Knott) */
+ if (i == 0)
+ disp = 1;
+probe:
+ if ((i -= disp) < 0)
+ i += hsize_reg;
+
+ if (Htabof (i) == fcode) {
+ ent = Codetabof(i);
+ continue;
+ }
+ if ((long)Htabof(i) > 0)
+ goto probe;
+nomatch:
+ output((code_int)ent);
+ out_count++;
+ ent = c;
+ if (free_ent < maxmaxcode) {
+ Codetabof(i) = free_ent++; /* code -> hashtable */
+ Htabof(i) = fcode;
+ } else if ((count_int)in_count >= checkpoint && block_compress)
+ cl_block ();
+ }
+ /*
+ * Put out the final code.
+ */
+ output( (code_int)ent );
+ out_count++;
+ output( (code_int)-1 );
+
+ /*
+ * Print out stats on stderr
+ */
+ if(zcat_flg == 0 && !quiet) {
+ fprintf( stderr, "Compression: " );
+ prratio( stderr, in_count-bytes_out, in_count );
+ }
+ if(bytes_out > in_count) /* exit(2) if no savings */
+ exit_stat = 2;
+}
+
+/*
+ * Decompress stdin to stdout. This routine adapts to the codes in the
+ * file building the "string" table on-the-fly; requiring no table to
+ * be stored in the compressed file. The tables used herein are shared
+ * with those of the compress() routine. See the definitions above.
+ */
+void
+decompress(void)
+{
+ int finchar;
+ code_int code, oldcode, incode;
+ uchar *stackp;
+
+ /*
+ * As above, initialize the first 256 entries in the table.
+ */
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ for (code = 255; code >= 0; code--) {
+ Tab_prefixof(code) = 0;
+ Tab_suffixof(code) = (uchar)code;
+ }
+ free_ent = (block_compress? FIRST: 256);
+
+ finchar = oldcode = getcode();
+ if(oldcode == -1) /* EOF already? */
+ return; /* Get out of here */
+ putchar((char)finchar); /* first code must be 8 bits = char */
+ if(ferror(stdout)) /* Crash if can't write */
+ writeerr();
+ stackp = De_stack;
+
+ while ((code = getcode()) > -1) {
+ if ((code == CLEAR) && block_compress) {
+ for (code = 255; code >= 0; code--)
+ Tab_prefixof(code) = 0;
+ clear_flg = 1;
+ free_ent = FIRST - 1;
+ if ((code = getcode()) == -1) /* O, untimely death! */
+ break;
+ }
+ incode = code;
+ /*
+ * Special case for KwKwK string.
+ */
+ if (code >= free_ent) {
+ *stackp++ = finchar;
+ code = oldcode;
+ }
+
+ /*
+ * Generate output characters in reverse order
+ */
+ while (code >= 256) {
+ *stackp++ = Tab_suffixof(code);
+ code = Tab_prefixof(code);
+ }
+ *stackp++ = finchar = Tab_suffixof(code);
+
+ /*
+ * And put them out in forward order
+ */
+ do {
+ putchar(*--stackp);
+ } while (stackp > De_stack);
+
+ /*
+ * Generate the new entry.
+ */
+ if ( (code=free_ent) < maxmaxcode ) {
+ Tab_prefixof(code) = (ushort)oldcode;
+ Tab_suffixof(code) = finchar;
+ free_ent = code+1;
+ }
+ /*
+ * Remember previous code.
+ */
+ oldcode = incode;
+ }
+ fflush(stdout);
+ if(ferror(stdout))
+ writeerr();
+}
+
+void
main(int argc, char **argv)
{
- int overwrite = 0; /* Do not overwrite unless given -f flag */
+ int overwrite;
char tempname[512];
char **filelist, **fileptr;
char *cp;
struct stat statbuf;
+ overwrite = 0; /* Do not overwrite unless given -f flag */
+
if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
signal(SIGINT, onintr);
signal(SIGSEGV, oops);
@@ -209,19 +711,9 @@
case 'C':
block_compress = 0;
break;
-#ifdef DEBUG
- case 'D':
- debug = 1;
- break;
case 'V':
- verbose = 1;
version();
break;
-#else
- case 'V':
- version();
- break;
-#endif
case 'b':
if (!ARGVAL()) {
fprintf(stderr, "Missing maxbits\n");
@@ -328,19 +820,18 @@
*/
hsize = HSIZE;
if (fsize < (1 << 12))
- hsize = min(5003, HSIZE);
+ hsize = Min(5003, HSIZE);
else if (fsize < (1 << 13))
- hsize = min(9001, HSIZE);
+ hsize = Min(9001, HSIZE);
else if (fsize < (1 << 14))
- hsize = min (18013, HSIZE);
+ hsize = Min (18013, HSIZE);
else if (fsize < (1 << 15))
- hsize = min (35023, HSIZE);
+ hsize = Min (35023, HSIZE);
else if (fsize < 47000)
- hsize = min (50021, HSIZE);
+ hsize = Min (50021, HSIZE);
/* Generate output filename */
strcpy(ofname, *fileptr);
-#ifndef BSD4_2
if ((cp=strrchr(ofname,'/')) != NULL)
cp++;
else
@@ -354,7 +845,6 @@
cp);
continue;
}
-#endif
strcat(ofname, ".Z");
}
/* Check for overwrite of existing file */
@@ -394,17 +884,8 @@
/* Actually do the compression/decompression */
if (do_decomp == 0)
compress();
-#ifndef DEBUG
else
decompress();
-#else
- else if (debug == 0)
- decompress();
- else
- printcodes();
- if (verbose)
- dump_tab();
-#endif /* DEBUG */
if(zcat_flg == 0) {
copystat(*fileptr, ofname); /* Copy stats */
if (exit_stat == 1 || !quiet)
@@ -414,10 +895,6 @@
} else { /* Standard input */
if (do_decomp == 0) {
compress();
-#ifdef DEBUG
- if(verbose)
- dump_tab();
-#endif
if(!quiet)
putc('\n', stderr);
} else {
@@ -440,706 +917,10 @@
exit(1);
}
}
-#ifndef DEBUG
decompress();
-#else
- if (debug == 0)
- decompress();
- else
- printcodes();
- if (verbose)
- dump_tab();
-#endif /* DEBUG */
}
}
exit(exit_stat);
-}
-
-static int offset;
-long in_count = 1; /* length of input */
-long bytes_out; /* length of compressed output */
-long out_count = 0; /* # of codes output (for debugging) */
-
-/*
- * compress stdin to stdout
- *
- * Algorithm: use open addressing double hashing (no chaining) on the
- * prefix code / next character combination. We do a variant of Knuth's
- * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- * secondary probe. Here, the modular division first probe is gives way
- * to a faster exclusive-or manipulation. Also do block compression with
- * an adaptive reset, whereby the code table is cleared when the compression
- * ratio decreases, but after the table fills. The variable-length output
- * codes are re-sized at this point, and a special CLEAR code is generated
- * for the decompressor. Late addition: construct the table according to
- * file size for noticeable speed improvement on small files. Please direct
- * questions about this implementation to ames!jaw.
- */
-void
-compress(void)
-{
- code_int ent, hsize_reg;
- code_int i;
- int c, disp, hshift;
- long fcode;
-
- if (nomagic == 0) {
- putchar(magic_header[0]);
- putchar(magic_header[1]);
- putchar((char)(maxbits | block_compress));
- if(ferror(stdout))
- writeerr();
- }
- offset = 0;
- bytes_out = 3; /* includes 3-byte header mojo */
- out_count = 0;
- clear_flg = 0;
- ratio = 0;
- in_count = 1;
- checkpoint = CHECK_GAP;
- maxcode = MAXCODE(n_bits = INIT_BITS);
- free_ent = (block_compress? FIRST: 256);
-
- ent = getchar ();
-
- hshift = 0;
- for (fcode = (long)hsize; fcode < 65536L; fcode *= 2)
- hshift++;
- hshift = 8 - hshift; /* set hash code range bound */
-
- hsize_reg = hsize;
- cl_hash( (count_int) hsize_reg); /* clear hash table */
-
- while ((c = getchar()) != EOF) {
- in_count++;
- fcode = (long) (((long) c << maxbits) + ent);
- i = ((c << hshift) ^ ent); /* xor hashing */
-
- if (htabof (i) == fcode) {
- ent = codetabof(i);
- continue;
- } else if ((long)htabof(i) < 0 ) /* empty slot */
- goto nomatch;
- disp = hsize_reg - i; /* secondary hash (after G. Knott) */
- if (i == 0)
- disp = 1;
-probe:
- if ((i -= disp) < 0)
- i += hsize_reg;
-
- if (htabof (i) == fcode) {
- ent = codetabof(i);
- continue;
- }
- if ((long)htabof(i) > 0)
- goto probe;
-nomatch:
- output((code_int)ent);
- out_count++;
- ent = c;
- if (free_ent < maxmaxcode) {
- codetabof(i) = free_ent++; /* code -> hashtable */
- htabof(i) = fcode;
- } else if ((count_int)in_count >= checkpoint && block_compress)
- cl_block ();
- }
- /*
- * Put out the final code.
- */
- output( (code_int)ent );
- out_count++;
- output( (code_int)-1 );
-
- /*
- * Print out stats on stderr
- */
- if(zcat_flg == 0 && !quiet) {
-#ifdef DEBUG
- fprintf( stderr,
- "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
- in_count, out_count, bytes_out );
- prratio( stderr, in_count, bytes_out );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tCompression as in compact: " );
- prratio( stderr, in_count-bytes_out, in_count );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
- free_ent - 1, n_bits );
-#else /* !DEBUG */
- fprintf( stderr, "Compression: " );
- prratio( stderr, in_count-bytes_out, in_count );
-#endif /* DEBUG */
- }
- if(bytes_out > in_count) /* exit(2) if no savings */
- exit_stat = 2;
-}
-
-/*
- * TAG( output )
- *
- * Output the given code.
- * Inputs:
- * code: A n_bits-bit integer. If == -1, then EOF. This assumes
- * that n_bits =< (long)wordsize - 1.
- * Outputs:
- * Outputs code to the file.
- * Assumptions:
- * Chars are 8 bits long.
- * Algorithm:
- * Maintain a BITS character long buffer (so that 8 codes will
- * fit in it exactly). When the buffer fills up empty it and start over.
- */
-
-static char buf[BITS];
-
-uchar lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
-uchar rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
-
-void
-output(code_int code)
-{
-#ifdef DEBUG
- static int col = 0;
-#endif
- int r_off = offset, bits= n_bits;
- char *bp = buf;
-
-#ifdef DEBUG
- if (verbose)
- fprintf(stderr, "%5d%c", code,
- (col+=6) >= 74? (col = 0, '\n'): ' ');
-#endif
- if (code >= 0) {
- /*
- * byte/bit numbering on the VAX is simulated by the
- * following code
- */
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /*
- * Since code is always >= 8 bits, only need to mask the first
- * hunk on the left.
- */
- *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
- bp++;
- bits -= 8 - r_off;
- code >>= 8 - r_off;
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if ( bits >= 8 ) {
- *bp++ = code;
- code >>= 8;
- bits -= 8;
- }
- /* Last bits. */
- if(bits)
- *bp = code;
-
- offset += n_bits;
- if ( offset == (n_bits << 3) ) {
- bp = buf;
- bits = n_bits;
- bytes_out += bits;
- do {
- putchar(*bp++);
- } while(--bits);
- offset = 0;
- }
-
- /*
- * If the next entry is going to be too big for the code size,
- * then increase it, if possible.
- */
- if ( free_ent > maxcode || (clear_flg > 0)) {
- /*
- * Write the whole buffer, because the input side won't
- * discover the size increase until after it has read it.
- */
- if ( offset > 0 ) {
- if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
- writeerr();
- bytes_out += n_bits;
- }
- offset = 0;
-
- if ( clear_flg ) {
- maxcode = MAXCODE (n_bits = INIT_BITS);
- clear_flg = 0;
- } else {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode;
- else
- maxcode = MAXCODE(n_bits);
- }
-#ifdef DEBUG
- if ( debug ) {
- fprintf(stderr,
- "\nChange to %d bits\n", n_bits);
- col = 0;
- }
-#endif
- }
- } else {
- /*
- * At EOF, write the rest of the buffer.
- */
- if ( offset > 0 )
- fwrite( buf, 1, (offset + 7) / 8, stdout );
- bytes_out += (offset + 7) / 8;
- offset = 0;
- fflush( stdout );
-#ifdef DEBUG
- if ( verbose )
- fprintf( stderr, "\n" );
-#endif
- if( ferror( stdout ) )
- writeerr();
- }
-}
-
-/*
- * Decompress stdin to stdout. This routine adapts to the codes in the
- * file building the "string" table on-the-fly; requiring no table to
- * be stored in the compressed file. The tables used herein are shared
- * with those of the compress() routine. See the definitions above.
- */
-void
-decompress(void)
-{
- int finchar;
- code_int code, oldcode, incode;
- uchar *stackp;
-
- /*
- * As above, initialize the first 256 entries in the table.
- */
- maxcode = MAXCODE(n_bits = INIT_BITS);
- for (code = 255; code >= 0; code--) {
- tab_prefixof(code) = 0;
- tab_suffixof(code) = (uchar)code;
- }
- free_ent = (block_compress? FIRST: 256);
-
- finchar = oldcode = getcode();
- if(oldcode == -1) /* EOF already? */
- return; /* Get out of here */
- putchar((char)finchar); /* first code must be 8 bits = char */
- if(ferror(stdout)) /* Crash if can't write */
- writeerr();
- stackp = de_stack;
-
- while ((code = getcode()) > -1) {
- if ((code == CLEAR) && block_compress) {
- for (code = 255; code >= 0; code--)
- tab_prefixof(code) = 0;
- clear_flg = 1;
- free_ent = FIRST - 1;
- if ((code = getcode()) == -1) /* O, untimely death! */
- break;
- }
- incode = code;
- /*
- * Special case for KwKwK string.
- */
- if (code >= free_ent) {
- *stackp++ = finchar;
- code = oldcode;
- }
-
- /*
- * Generate output characters in reverse order
- */
- while (code >= 256) {
- *stackp++ = tab_suffixof(code);
- code = tab_prefixof(code);
- }
- *stackp++ = finchar = tab_suffixof(code);
-
- /*
- * And put them out in forward order
- */
- do {
- putchar(*--stackp);
- } while (stackp > de_stack);
-
- /*
- * Generate the new entry.
- */
- if ( (code=free_ent) < maxmaxcode ) {
- tab_prefixof(code) = (ushort)oldcode;
- tab_suffixof(code) = finchar;
- free_ent = code+1;
- }
- /*
- * Remember previous code.
- */
- oldcode = incode;
- }
- fflush(stdout);
- if(ferror(stdout))
- writeerr();
-}
-
-/*
- * TAG( getcode )
- *
- * Read one code from the standard input. If EOF, return -1.
- * Inputs:
- * stdin
- * Outputs:
- * code or -1 is returned.
- */
-code_int
-getcode(void)
-{
- int r_off, bits;
- code_int code;
- static int offset = 0, size = 0;
- static uchar buf[BITS];
- uchar *bp = buf;
-
- if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
- /*
- * If the next entry will be too big for the current code
- * size, then we must increase the size. This implies reading
- * a new buffer full, too.
- */
- if ( free_ent > maxcode ) {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode; /* won't get any bigger now */
- else
- maxcode = MAXCODE(n_bits);
- }
- if ( clear_flg > 0) {
- maxcode = MAXCODE(n_bits = INIT_BITS);
- clear_flg = 0;
- }
- size = fread(buf, 1, n_bits, stdin);
- if (size <= 0)
- return -1; /* end of file */
- offset = 0;
- /* Round size down to integral number of codes */
- size = (size << 3) - (n_bits - 1);
- }
- r_off = offset;
- bits = n_bits;
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /* Get first part (low order bits) */
- code = (*bp++ >> r_off);
- bits -= (8 - r_off);
- r_off = 8 - r_off; /* now, offset into code word */
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if (bits >= 8) {
- code |= *bp++ << r_off;
- r_off += 8;
- bits -= 8;
- }
- /* high order bits. */
- code |= (*bp & rmask[bits]) << r_off;
- offset += n_bits;
- return code;
-}
-
-#ifdef DEBUG
-void
-printcodes(void)
-{
- /*
- * Just print out codes from input file. For debugging.
- */
- code_int code;
- int col = 0, bits;
-
- bits = n_bits = INIT_BITS;
- maxcode = MAXCODE(n_bits);
- free_ent = ((block_compress) ? FIRST : 256 );
- while ( ( code = getcode() ) >= 0 ) {
- if ( (code == CLEAR) && block_compress ) {
- free_ent = FIRST - 1;
- clear_flg = 1;
- }
- else if ( free_ent < maxmaxcode )
- free_ent++;
- if ( bits != n_bits ) {
- fprintf(stderr, "\nChange to %d bits\n", n_bits );
- bits = n_bits;
- col = 0;
- }
- fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
- }
- putc( '\n', stderr );
- exit( 0 );
-}
-
-code_int sorttab[1<<BITS]; /* sorted pointers into htab */
-
-#define STACK_SIZE 15000
-
-dump_tab() /* dump string table */
-{
- int i, first, c, ent;
- int stack_top = STACK_SIZE;
-
- if(do_decomp == 0) { /* compressing */
- int flag = 1;
-
- for(i=0; i<hsize; i++) { /* build sort pointers */
- if((long)htabof(i) >= 0) {
- sorttab[codetabof(i)] = i;
- }
- }
- first = block_compress ? FIRST : 256;
- for(i = first; i < free_ent; i++) {
- fprintf(stderr, "%5d: \"", i);
- de_stack[--stack_top] = '\n';
- de_stack[--stack_top] = '"';
- stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff,
- stack_top);
- for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
- ent > 256;
- ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
- stack_top = in_stack(htabof(sorttab[ent]) >> maxbits,
- stack_top);
- }
- stack_top = in_stack(ent, stack_top);
- fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
- stack_top = STACK_SIZE;
- }
- } else if(!debug) { /* decompressing */
-
- for ( i = 0; i < free_ent; i++ ) {
- ent = i;
- c = tab_suffixof(ent);
- if ( isascii(c) && isprint(c) )
- fprintf( stderr, "%5d: %5d/'%c' \"",
- ent, tab_prefixof(ent), c );
- else
- fprintf( stderr, "%5d: %5d/\\%03o \"",
- ent, tab_prefixof(ent), c );
- de_stack[--stack_top] = '\n';
- de_stack[--stack_top] = '"';
- for ( ; ent != NULL;
- ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
- stack_top = in_stack(tab_suffixof(ent), stack_top);
- }
- fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
- stack_top = STACK_SIZE;
- }
- }
-}
-
-int
-in_stack(int c, int stack_top)
-{
- if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
- de_stack[--stack_top] = c;
- } else {
- switch( c ) {
- case '\n': de_stack[--stack_top] = 'n'; break;
- case '\t': de_stack[--stack_top] = 't'; break;
- case '\b': de_stack[--stack_top] = 'b'; break;
- case '\f': de_stack[--stack_top] = 'f'; break;
- case '\r': de_stack[--stack_top] = 'r'; break;
- case '\\': de_stack[--stack_top] = '\\'; break;
- default:
- de_stack[--stack_top] = '0' + c % 8;
- de_stack[--stack_top] = '0' + (c / 8) % 8;
- de_stack[--stack_top] = '0' + c / 64;
- break;
- }
- de_stack[--stack_top] = '\\';
- }
- return stack_top;
-}
-#endif /* DEBUG */
-
-void
-writeerr(void)
-{
- perror(ofname);
- unlink(ofname);
- exit(1);
-}
-
-void
-copystat(char *ifname, char *ofname)
-{
- int mode;
- time_t timep[2];
- struct stat statbuf;
-
- fclose(stdout);
- if (stat(ifname, &statbuf)) { /* Get stat on input file */
- perror(ifname);
- return;
- }
- if (!S_ISREG(statbuf.st_mode)) {
- if (quiet)
- fprintf(stderr, "%s: ", ifname);
- fprintf(stderr, " -- not a regular file: unchanged");
- exit_stat = 1;
- } else if (exit_stat == 2 && !force) {
- /* No compression: remove file.Z */
- if (!quiet)
- fprintf(stderr, " -- file unchanged");
- } else { /* Successful Compression */
- exit_stat = 0;
- mode = statbuf.st_mode & 0777;
- if (chmod(ofname, mode)) /* Copy modes */
- perror(ofname);
- /* Copy ownership */
- chown(ofname, statbuf.st_uid, statbuf.st_gid);
- timep[0] = statbuf.st_atime;
- timep[1] = statbuf.st_mtime;
- /* Update last accessed and modified times */
- utime(ofname, timep);
-// if (unlink(ifname)) /* Remove input file */
-// perror(ifname);
- return; /* success */
- }
-
- /* Unsuccessful return -- one of the tests failed */
- if (unlink(ofname))
- perror(ofname);
-}
-
-/*
- * This routine returns 1 if we are running in the foreground and stderr
- * is a tty.
- */
-int
-foreground(void)
-{
- if(bgnd_flag) /* background? */
- return 0;
- else /* foreground */
- return isatty(2); /* and stderr is a tty */
-}
-
-void
-onintr(int)
-{
- unlink(ofname);
- exit(1);
-}
-
-void
-oops(int) /* wild pointer -- assume bad input */
-{
- if (do_decomp == 1)
- fprintf(stderr, "uncompress: corrupt input\n");
- unlink(ofname);
- exit(1);
-}
-
-void
-cl_block (void) /* table clear for block compress */
-{
- long rat;
-
- checkpoint = in_count + CHECK_GAP;
-#ifdef DEBUG
- if ( debug ) {
- fprintf ( stderr, "count: %ld, ratio: ", in_count );
- prratio ( stderr, in_count, bytes_out );
- fprintf ( stderr, "\n");
- }
-#endif /* DEBUG */
-
- if (in_count > 0x007fffff) { /* shift will overflow */
- rat = bytes_out >> 8;
- if (rat == 0) /* Don't divide by zero */
- rat = 0x7fffffff;
- else
- rat = in_count / rat;
- } else
- rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
- if (rat > ratio)
- ratio = rat;
- else {
- ratio = 0;
-#ifdef DEBUG
- if (verbose)
- dump_tab(); /* dump string table */
-#endif
- cl_hash((count_int)hsize);
- free_ent = FIRST;
- clear_flg = 1;
- output((code_int)CLEAR);
-#ifdef DEBUG
- if (debug)
- fprintf(stderr, "clear\n");
-#endif /* DEBUG */
- }
-}
-
-void
-cl_hash(count_int hsize) /* reset code table */
-{
- count_int *htab_p = htab+hsize;
- long i;
- long m1 = -1;
-
- i = hsize - 16;
- do { /* might use Sys V memset(3) here */
- *(htab_p-16) = m1;
- *(htab_p-15) = m1;
- *(htab_p-14) = m1;
- *(htab_p-13) = m1;
- *(htab_p-12) = m1;
- *(htab_p-11) = m1;
- *(htab_p-10) = m1;
- *(htab_p-9) = m1;
- *(htab_p-8) = m1;
- *(htab_p-7) = m1;
- *(htab_p-6) = m1;
- *(htab_p-5) = m1;
- *(htab_p-4) = m1;
- *(htab_p-3) = m1;
- *(htab_p-2) = m1;
- *(htab_p-1) = m1;
- htab_p -= 16;
- } while ((i -= 16) >= 0);
- for ( i += 16; i > 0; i-- )
- *--htab_p = m1;
-}
-
-void
-prratio(FILE *stream, long num, long den)
-{
- int q; /* Doesn't need to be long */
-
- if(num > 214748L) /* 2147483647/10000 */
- q = num / (den / 10000L);
- else
- q = 10000L * num / den; /* Long calculations, though */
- if (q < 0) {
- putc('-', stream);
- q = -q;
- }
- fprintf(stream, "%d.%02d%%", q / 100, q % 100);
-}
-
-void
-version(void)
-{
- fprintf(stderr, "%s\n", rcs_ident);
- fprintf(stderr, "Options: ");
-#ifdef DEBUG
- fprintf(stderr, "DEBUG, ");
-#endif
-#ifdef BSD4_2
- fprintf(stderr, "BSD4_2, ");
-#endif
- fprintf(stderr, "BITS = %d\n", BITS);
}
/*
Fri Sep 11 19:04:34 EDT 2026
diff d683e5c0cf8fcad8fdf21a550453eb9e4b17e8fb uncommitted
--- a/sys/src/cmd/sha1sum.c
+++ b/sys/src/cmd/sha1sum.c
@@ -1,22 +1,20 @@
/*
- * sha1sum - compute SHA1 or SHA2 digest
+ * sha1sum - compute SHA1, SHA2 or SHA3 digest
*/
#include <u.h>
#include <libc.h>
#include <libsec.h>
-#pragma varargck type "M" uchar*
-
static char exitstr[ERRMAX];
-typedef struct Sha2 Sha2;
-struct Sha2 {
+typedef struct Sha Sha;
+struct Sha {
int bits;
int dlen;
- DigestState* (*func)(uchar *, ulong, uchar *, DigestState *);
+ DigestState* (*f)(uchar *, ulong, uchar *, DigestState *);
};
-static Sha2 sha2s[] = {
+static Sha sha2s[] = {
224, SHA2_224dlen, sha2_224,
256, SHA2_256dlen, sha2_256,
384, SHA2_384dlen, sha2_384,
@@ -23,21 +21,18 @@
512, SHA2_512dlen, sha2_512,
};
-static DigestState* (*shafunc)(uchar *, ulong, uchar *, DigestState *);
-static int shadlen;
+static Sha sha3s[] = {
+ 224, SHA3_224dlen, sha3_224,
+ 256, SHA3_256dlen, sha3_256,
+ 384, SHA3_384dlen, sha3_384,
+ 512, SHA3_512dlen, sha3_512,
+};
-static int
-digestfmt(Fmt *fmt)
-{
- char buf[SHA2_512dlen*2 + 1];
- uchar *p;
- int i;
+static Sha sha1s[] = {
+ 128, SHA1dlen, sha1,
+};
- p = va_arg(fmt->args, uchar*);
- for(i = 0; i < shadlen; i++)
- sprint(buf + 2*i, "%.2ux", p[i]);
- return fmtstrcpy(fmt, buf);
-}
+Sha *hash = &sha1s[0];
static void
sum(int fd, char *name)
@@ -46,21 +41,32 @@
uchar buf[IOUNIT], digest[SHA2_512dlen];
DigestState *s;
- s = (*shafunc)(nil, 0, nil, nil);
+ s = hash->f(nil, 0, nil, nil);
while((n = read(fd, buf, sizeof buf)) > 0)
- (*shafunc)(buf, n, nil, s);
+ hash->f(buf, n, nil, s);
if(n < 0){
snprint(exitstr, sizeof(exitstr), "reading %s: %r\n", name? name:
"stdin");
fprint(2, "%s", exitstr);
return;
}
- (*shafunc)(nil, 0, digest, s);
+ hash->f(nil, 0, digest, s);
if(name == nil)
- print("%M\n", digest);
+ print("%.*lH\n", hash->dlen, digest);
else
- print("%M\t%s\n", digest, name);
+ print("%.*lH\t%s\n", hash->dlen, digest, name);
}
+static Sha*
+pick(Sha *from, int n, int bits)
+{
+ Sha *s;
+
+ for(s = from; s < from+n; s++)
+ if(s->bits == bits)
+ return s;
+ return nil;
+}
+
static void
usage(void)
{
@@ -71,27 +77,20 @@
void
main(int argc, char *argv[])
{
- int i, fd, bits;
- Sha2 *sha;
+ int i, fd;
- shafunc = sha1;
- shadlen = SHA1dlen;
ARGBEGIN{
case '2':
- bits = atoi(EARGF(usage()));
- for (sha = sha2s; sha < sha2s + nelem(sha2s); sha++)
- if (sha->bits == bits)
- break;
- if (sha >= sha2s + nelem(sha2s))
- sysfatal("unknown number of sha2 bits: %d", bits);
- shafunc = sha->func;
- shadlen = sha->dlen;
+ hash = pick(sha2s, nelem(sha2s), atoi(EARGF(usage())));
break;
+ case '3':
+ hash = pick(sha3s, nelem(sha3s), atoi(EARGF(usage())));
+ break;
default:
usage();
}ARGEND
- fmtinstall('M', digestfmt);
+ fmtinstall('H', encodefmt);
if(argc == 0)
sum(0, nil);
Fri Sep 11 18:56:40 EDT 2026
diff d683e5c0cf8fcad8fdf21a550453eb9e4b17e8fb uncommitted --- a/lib/bullshit +++ b/lib/bullshit @@ -83,11 +83,13 @@ extensible ^ compliant ^ scale-out ^ +vibe-coded ^ session | content-driven | high-performance | general-purpose | out-scaling | +human-in-the-loop | generic ^ mobile ^ responsive ^ @@ -116,6 +118,7 @@ virtual ^ shared ^ stable ^ +agentic ^ SQL * JSON * XML * @@ -131,6 +134,7 @@ SSL * HTTP * TOR * +MCP * ActivityPub * layer $ element |
Fri Sep 11 18:14:07 EDT 2026
% mk -s clean app/blink/stm32l4.bin app/blink/t.out
rm -f app/blink/[t].out app/blink/*.[t] app/blink/stm32l4.bin test/*.[t] \
stm32l4/lib/*.a \
libc/port/*.[t] libc/stm32l4/*.[t]
stm32l4/lib/libc.a doesn't exist: assuming it will be an archive
5a -t -o libc/stm32l4/l.t libc/stm32l4/l.s
tc -Iinclude -Istm32l4/include -o libc/port/init.t libc/port/init.c
5a -t -o libc/stm32l4/halt.t libc/stm32l4/halt.s
tc -Iinclude -Istm32l4/include -o libc/stm32l4/sleep.t libc/stm32l4/sleep.c
tc -Iinclude -Istm32l4/include -o libc/stm32l4/sys.t libc/stm32l4/sys.c
tc -Iinclude -Istm32l4/include -o libc/stm32l4/isr.t libc/stm32l4/isr.c
tc -Iinclude -Istm32l4/include -o app/blink/blink.t app/blink/blink.c
ar crv stm32l4/lib/libc.a `{membername $prereq}
a - libc/stm32l4/l.t
a - libc/port/init.t
a - libc/stm32l4/halt.t
a - libc/stm32l4/sleep.t
a - libc/stm32l4/sys.t
a - libc/stm32l4/isr.t
tl -T0x08000000 -R0 -D0x10000000 -a -H0 -o app/blink/stm32l4.bin
stm32l4/lib/libc.a app/blink/blink.t | awk '$1 >= "08000400"'
main: undefined external: STK in main
main: undefined external: RCC in main
main: undefined external: GPIOB in main
Fri Sep 11 14:46:42 EDT 2026
#include <u.h>
#include <libc.h>
#include "fs.h"
u64int /* this returns a byte position! */
getdentry(u64int dirblk, u64int size, u64int block)
{
u64int nblks, blk, pos;
char buf[BLKSZ];
char target[BLOCKSIZ+1];
char field[STRSIZ+1];
seprint(target, target + sizeof(target), "%ulld", block);
nblks = size / BLKSZ + (size % BLKSZ > 0);
for(blk = dirblk; blk < dirblk + nblks; ++blk) {
if(blkread(blk, buf) < 0) {
werrstr("blkread: %r");
return 0;
}
for(pos = 0; pos + DENTRYSIZ <= BLKSZ; pos += DENTRYSIZ) {
if(buf[pos] == 'd' || buf[pos] == '#')
continue;
#ifdef DEFENSIVE
if(buf[pos] != '+') {
werrstr("block %ulld: bad status '%c' at entry
%ulld",
blk, buf[pos], (blk - dirblk) * (BLKSZ/DENTRYSIZ)
+ pos/DENTRYSIZ);
return 0;
}
#endif
getfield(buf + pos, BLOCK, BLOCKSIZ, field);
if(strtoull(field, nil, 10) == block) {
return blk * BLKSZ + pos;
}
}
}
return 0; /* not found */
}
void
getfield(char *buf, int offset, int size, char *out)
{
int i;
for(i = 0; i < size; ++i)
out[i] = buf[offset + i];
out[size] = '\0';
for(i = size - 1; i >= 0 && out[i] == ' '; --i)
out[i] = '\0';
}
void
writefield(char *buf, int offset, int size, char *in)
{
int i;
for(i = 0; in[i] != '\0'; ++i)
buf[offset + i] = in[i];
for(; i < size; ++i)
buf[offset + i] = ' ';
}
static int
isleap(u32int year)
{
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
static u64int
iso2unix(char *buf)
{
#ifdef DEFENSIVE
if(buf[4] != '-'
|| buf[7] != '-'
|| buf[10] != 'T'
|| buf[13] != ':'
|| buf[16] != ':'
|| buf[19] != 'Z') {
werrstr("wrong time format");
return 0;
}
#endif
u32int y, m, d, i;
u64int days = 0;
y = strtoul(buf, nil, 10);
m = strtoul(buf + 5, nil, 10);
d = strtoul(buf + 8, nil, 10);
for(i = 1970; i < y; ++i)
days += 365 + isleap(i);
int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(isleap(y))
mdays[1] = 29;
for(i = 0; i < m - 1; ++i)
days += mdays[i];
days += d - 1;
return days * 86400
+ strtoul(buf + 11, nil, 10) * 3600
+ strtoul(buf + 14, nil, 10) * 60
+ strtoul(buf + 17, nil, 10);
}
static char *
unix2iso(char *buf, u64int t)
{
u32int y = 1970, m, d, h, min, s;
u64int days = t / 86400;
u32int secs = t % 86400;
int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
while(days >= 365 + isleap(y)) {
days -= 365 + isleap(y);
++y;
}
if(isleap(y))
mdays[1] = 29;
m = 0;
while(m < 12 && days >= mdays[m]) {
days -= mdays[m];
++m;
}
d = days + 1;
h = secs / 3600;
min = (secs % 3600) / 60;
s = secs % 60;
snprint(buf, 20, "%04ud-%02ud-%02udT%02ud:%02ud:%02udZ", y, m+1, d, h,
min, s);
return buf;
}
#ifdef DEFENSIVE
static ulong
rwx2num(char *buf)
{
ulong p = 0;
if(buf[0] == 'r')
p |= (1 << 8);
else if(buf[0] != '-')
goto err;
if(buf[1] == 'w')
p |= (1 << 7);
else if(buf[1] != '-')
goto err;
if(buf[2] == 'x')
p |= (1 << 6);
else if(buf[2] != 'x')
goto err;
if(buf[3] == 'r')
p |= (1 << 5);
else if(buf[3] != '-')
goto err;
if(buf[4] == 'w')
p |= (1 << 4);
else if(buf[4] != '-')
goto err;
if(buf[5] == 'x')
p |= (1 << 3);
else if(buf[5] != '-')
goto err;
if(buf[6] == 'r')
p |= (1 << 2);
else if(buf[6] != '-')
goto err;
if(buf[7] == 'w')
p |= (1 << 1);
else if(buf[7] != '-')
goto err;
if(buf[8] == 'x')
p |= (1 << 0);
else if(buf[8] != '-')
goto err;
return p;
err:
werrstr("incorrect permissions format");
return 0;
}
#endif
#ifndef DEFENSIVE
static ulong
rwx2num(char *buf)
{
ulong p = 0;
if(buf[0] == 'r')
p |= (1 << 8);
if(buf[1] == 'w')
p |= (1 << 7);
if(buf[2] == 'x')
p |= (1 << 6);
if(buf[3] == 'r')
p |= (1 << 5);
if(buf[4] == 'w')
p |= (1 << 4);
if(buf[5] == 'x')
p |= (1 << 3);
if(buf[6] == 'r')
p |= (1 << 2);
if(buf[7] == 'w')
p |= (1 << 1);
if(buf[8] == 'x')
p |= (1 << 0);
return p;
}
#endif
static char *
num2rwx(char *buf, ulong mode)
{
buf[0] = (mode & (1 << 8)) ? 'r' : '-';
buf[1] = (mode & (1 << 7)) ? 'w' : '-';
buf[2] = (mode & (1 << 6)) ? 'x' : '-';
buf[3] = (mode & (1 << 5)) ? 'r' : '-';
buf[4] = (mode & (1 << 4)) ? 'w' : '-';
buf[5] = (mode & (1 << 3)) ? 'x' : '-';
buf[6] = (mode & (1 << 2)) ? 'r' : '-';
buf[7] = (mode & (1 << 1)) ? 'w' : '-';
buf[8] = (mode & (1 << 0)) ? 'x' : '-';
buf[9] = '\0';
return buf;
}
Dir *
fsstat(u64int dentrypos)
{
u64int pos; /* to avoid a conversion */
u64int blk;
char buf[BLKSZ];
char field[STRSIZ+1];
pos = dentrypos % BLKSZ;
blk = dentrypos / BLKSZ + (pos > 0);
if(blkread(blk, buf) < 0) {
werrstr("blkread: %r");
return nil;
}
Dir *out = calloc(1, sizeof(Dir));
if(out == nil) {
werrstr("calloc: %r");
return nil;
}
/* Qid */
getfield(buf + pos, BLOCK, BLOCKSIZ, field);
out->qid.path = strtoull(field, nil, 10);
/* Type */ /* add fragmentation support here */
getfield(buf + pos, TYPE, TYPESIZ, field);
if(strcmp(field, " DIR") == 0) {
out->qid.type = QTDIR;
out->mode = DMDIR;
} else if(strcmp(field, " APPD") == 0) {
out->qid.type = QTAPPEND;
out->mode = DMAPPEND;
} else if(strcmp(field, " EXCL") == 0) {
out->qid.type = QTEXCL;
out->mode = DMEXCL;
} else {
out->qid.type = QTFILE;
out->mode = 0;
}
/* Perms */
getfield(buf + pos, PERMS, PERMSSIZ, field);
out->mode |= rwx2num(field);
/* Name */
getfield(buf + pos, NAME, NAMESIZ, field);
out->name = strdup(field);
if(out->name == nil)
goto nomem;
/* Size */
getfield(buf + pos, SIZE, SIZESIZ, field);
out->length = strtoll(field, nil, 10);
/* UID */
getfield(buf + pos, UID, UIDSIZ, field);
out->uid = strdup(field);
if(out->uid == nil)
goto nomem;
/* GID */
getfield(buf + pos, GID, GIDSIZ, field);
out->gid = strdup(field);
if(out->gid == nil)
goto nomem;
/* MUID */
getfield(buf + pos, MUID, MUIDSIZ, field);
out->muid = strdup(field);
if(out->muid == nil)
goto nomem;
/* Times */
getfield(buf + pos, MTIME, MTIMESIZ, field);
out->mtime = iso2unix(field);
#ifdef DEFENSIVE
if(out->mtime == 0) {
werrstr("iso2unix: %r");
goto err;
}
#endif
getfield(buf + pos, ATIME, ATIMESIZ, field);
out->atime = iso2unix(field);
#ifdef DEFENSIVE
if(out->atime == 0) {
werrstr("iso2unix: %r");
goto err;
}
#endif
return out;
nomem:
werrstr("malloc: %r");
err:
free(out->name);
free(out->uid);
free(out->gid);
free(out->muid);
free(out);
return nil;
}
u64int
dir1up(u64int dirblk, u64int dirsize,
Qid *parent, u64int parentsize)
{
u64int parentblk = parent->path;
u64int parentblks = parentsize / BLKSZ + (parentsize % BLKSZ > 0);
#ifdef DEFENSIVE
if(dirblk == super.rootblk || parentblk == SUPERBLK) {
werrstr("Cannot extend root directory");
return 0;
/* stub - you should actually extend here */
}
#endif
u64int dirnblks = dirsize / BLKSZ + (dirsize % BLKSZ > 0);
u64int nextblk = dirblk + dirnblks;
if(nextblk < super.nblocks && !bused(nextblk, nextblk)) {
if(balloc(nextblk, nextblk) < 0) {
werrstr("balloc: %r");
return 0;
}
return dirblk;
}
u64int newblk = bfindfree(dirnblks + 1, dirblk);
if(newblk == 0) {
werrstr("no space for %ulld contiguous blocks", dirnblks + 1);
return 0;
}
if(balloc(newblk, newblk + dirnblks) < 0) {
werrstr("balloc: %r");
return 0;
}
char buf[BLKSZ];
for(u64int i = 0; i < dirnblks; i++) {
if(blkcopy(dirblk + i, newblk + i, buf) < 0) {
werrstr("blkcopy: %r");
if(bfree(newblk, newblk + dirnblks) < 0)
werrstr("blkcopy and bfree: %r");
return 0;
}
}
u64int pos = getdentry(parentblk, parentblks, dirblk);
if(pos == 0) {
werrstr("getdentry: %r");
return 0;
}
u64int dblk = pos / BLKSZ;
pos = pos % BLKSZ;
if(blkread(dblk, buf) < 0) {
werrstr("blkread: %r");
return 0;
}
char field[BLOCKSIZ + 1];
seprint(field, field + sizeof(field), "%ulld", newblk);
writefield(buf + pos % BLKSZ, BLOCK, BLOCKSIZ, field);
if(blkwrite(dblk, buf) < 0) {
werrstr("blkwrite: %r");
return 0;
}
INCR_VERS(parent->vers);
if(bfree(dirblk, dirblk + dirnblks - 1) < 0) {
werrstr("bfree: %r");
return 0;
}
return newblk;
}
int //add a root case
initdentry(Qid *dir, u64int dirsize,
Qid *parent, u64int parentsize,
Dir *file)
{
u64int dirblk = dir->path, parentblk = parent->path;
u64int blk, pos;
u64int nblks = dirsize / BLKSZ + (dirsize % BLKSZ > 0);
char buf[BLKSZ], field[STRSIZ+1];
for(blk = dirblk; blk < dirblk + nblks; ++blk) {
if(blkread(blk, buf) < 0) {
werrstr("blkread: %r");
return -1;
}
for(pos = 0; pos + DENTRYSIZ <= BLKSZ; pos += DENTRYSIZ) {
if(buf[pos] == 'd')
goto found;
}
}
dirblk = dir1up(dirblk, dirsize, parent, parentsize);
if(dirblk == 0) {
werrstr("dir1up: %r");
return 0;
}
dir->path = dirblk;
++nblks;
blk = dirblk + nblks - 1;
if(blkread(blk, buf) < 0) {
werrstr("blkread: %r");
return -1;
}
pos = 0;
found:
buf[pos] = '+';
seprint(field, field + sizeof(field), "%ulld", file->qid.path);
writefield(buf + pos, BLOCK, BLOCKSIZ, field);
writefield(buf + pos, NAME, NAMESIZ, file->name);
if(file->qid.type & QTDIR)
writefield(buf + pos, TYPE, TYPESIZ, " DIR ");
else if(file->qid.type & QTAPPEND)
writefield(buf + pos, TYPE, TYPESIZ, " APPD ");
else if(file->qid.type & QTEXCL)
writefield(buf + pos, TYPE, TYPESIZ, " EXCL ");
else
writefield(buf + pos, TYPE, TYPESIZ, " FILE ");
seprint(field, field + sizeof(field), "%lld", file->length);
writefield(buf + pos, SIZE, SIZESIZ, field);
num2rwx(field, file->mode & 0777);
writefield(buf + pos, PERMS, PERMSSIZ, field);
writefield(buf + pos, UID, UIDSIZ, file->uid);
writefield(buf + pos, GID, GIDSIZ, file->gid);
writefield(buf + pos, MUID, MUIDSIZ, file->muid);
unix2iso(field, file->mtime);
writefield(buf + pos, MTIME, MTIMESIZ, field);
unix2iso(field, file->atime);
writefield(buf + pos, ATIME, ATIMESIZ, field);
if(blkwrite(blk, buf) < 0) {
werrstr("blkwrite: %r");
return -1;
}
INCR_VERS(dir->vers);
pos = getdentry(parentblk, parentsize, dirblk);
if(pos == 0) {
werrstr("getdentry: %r");
return -1;
}
blk = pos / BLKSZ + (pos % BLKSZ > 0);
pos = pos % BLKSZ;
if(blkread(blk, buf) < 0) {
werrstr("blkread: %r");
return -1;
}
getfield(buf + pos, SIZE, SIZESIZ, field);
u64int size = strtoull(field, nil, 10);
seprint(field, field + sizeof(field), "%ulld", size);
writefield(buf + pos, SIZE, SIZESIZ, field);
if(blkwrite(blk, buf) < 0) {
werrstr("blkwrite: %r");
return -1;
}
INCR_VERS(parent->vers);
return 0;
}
Fri Sep 11 11:56:08 EDT 2026
diff c2a936a02473681c2733ffbe154172e195f434a9 uncommitted
--- a/sys/src/libdraw/alloc.c
+++ b/sys/src/libdraw/alloc.c
@@ -17,13 +17,11 @@
_allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong col,
int screenid, int refresh)
{
uchar *a;
- char *err;
Image *i;
Rectangle clipr;
int id;
int depth;
- err = nil;
i = nil;
if(badrect(r)){
@@ -37,12 +35,9 @@
depth = chantodepth(chan);
if(depth == 0){
- err = "bad channel descriptor";
+ werrstr("bad channel descriptor");
Error:
- if(err != nil)
- werrstr("allocimage: %s", err);
- else
- werrstr("allocimage: %r");
+ werrstr("allocimage: %r");
free(i);
return nil;
}
@@ -110,27 +105,26 @@
namedimage(Display *d, char *name)
{
uchar *a;
- char *err, buf[12*12+1];
+ char buf[12*12+1];
Image *i;
int id, n;
ulong chan;
- err = nil;
i = nil;
+ if(name == nil || name[0] == '\0'){
+ werrstr("namedimage: name can't be empty");
+ return nil;
+ }
+
n = strlen(name);
- if(n >= 256){
- err = "name too long";
+ if(n > 255){
+ werrstr("name too long");
Error:
- if(err != nil)
- werrstr("namedimage: %s", err);
- else
- werrstr("namedimage: %r");
+ werrstr("namedimage: %r");
free(i);
return nil;
}
- /* flush pending data so we don't get error allocating the image */
- flushimage(d, 0);
_lockdisplay(d);
a = bufimage(d, 1+4+1+n);
if(a == nil){
@@ -157,7 +151,6 @@
i = malloc(sizeof(Image));
if(i == nil){
- Error1:
_lockdisplay(d);
a = bufimage(d, 1+4);
if(a != nil){
@@ -171,9 +164,10 @@
}
i->display = d;
i->id = id;
- if((chan=strtochan(buf+2*12))==0){
- werrstr("bad channel '%.12s' from devdraw", buf+2*12);
- goto Error1;
+ if((chan = strtochan(buf+2*12)) == 0){
+ werrstr("namedimage: bad channel '%.12s' from devdraw", buf+2*12);
+ _freeimage1(i);
+ return nil;
}
i->chan = chan;
i->depth = chantodepth(chan);
@@ -197,7 +191,16 @@
uchar *a;
int n;
+ if(name == nil || name[0] == '\0'){
+ werrstr("nameimage: name can't be empty");
+ return 0;
+ }
+
n = strlen(name);
+ if(n > 255){
+ werrstr("nameimage: name too long");
+ return 0;
+ }
_lockdisplay(i->display);
a = bufimage(i->display, 1+4+1+1+n);
if(a == nil){
@@ -224,6 +227,7 @@
if(i == nil || i->display == nil)
return 0;
+
d = i->display;
_lockdisplay(d);
a = bufimage(d, 1+4);
--- a/sys/src/libdraw/getrect.c
+++ b/sys/src/libdraw/getrect.c
@@ -109,11 +109,11 @@
freetmp();
if(tmp[0] == 0){
r = Rect(0, 0, max(Dx(display->screenimage->r), Dx(rc)), W);
- tmp[0] = allocimage(display, r, screen->chan, 0, -1);
- tmp[1] = allocimage(display, r, screen->chan, 0, -1);
+ tmp[0] = allocimage(display, r, screen->chan, 0, DNofill);
+ tmp[1] = allocimage(display, r, screen->chan, 0, DNofill);
r = Rect(0, 0, W, max(Dy(display->screenimage->r), Dy(rc)));
- tmp[2] = allocimage(display, r, screen->chan, 0, -1);
- tmp[3] = allocimage(display, r, screen->chan, 0, -1);
+ tmp[2] = allocimage(display, r, screen->chan, 0, DNofill);
+ tmp[3] = allocimage(display, r, screen->chan, 0, DNofill);
red = allocimage(display, Rect(0,0,1,1), screen->chan, 1,
DRed);
if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0){
freetmp();
--- a/sys/src/libdraw/window.c
+++ b/sys/src/libdraw/window.c
@@ -162,8 +162,6 @@
return;
}
- if(n==0)
- return;
_lockdisplay(d);
b = bufimage(d, 1+1+2+4*n);
if(b == nil){