[news.software.b] Yet another C-News-Stamp program

mason@tmsoft.uucp (Dave Mason) (12/12/89)

/* c-news-stamp - Written 89.12.11 Dave Mason <mason@tmsoft.uucp>
		released to the Public Domain
	(although I'd appreciate acknowledgement of authorship)

	For use with C News to generate a unique Message-ID:

Claimed advantages over other implementations?
	very small (<1k executable)
	fast
	dense
	believed to be general purpose bit extractor

Breaks the 32 bit date/time + 16 bit parent process id into 9 or 10 characters
chosen from a 5 bit (32 element) character set.

While slightly denser coding is possible, larger character sets are required:
	Character Set Size	Number of Characters to encode 48 bits
		32		10 (9 for now) - easy.
		41		9 - but requires messy divide on 32bit machines
		64		8 - no way without Upper & Lower Case
				    (should be fine, but I'm untrusting)
		116		7 - no way with 7 bit ASCII
		256		6 - get serious (but easy :-)
		777		5 - ugly AND implausible
		4096		4 - maybe in Japan
		65536		3 - not even in Japan

The bit mapping is as follows:
	       4          3         2          1         0
	7654321098765432 1098765432109876 5432109876543210
	xxx.....xxxxx... ..xxxxx.....xxxx x.....xxxxx.....
	(first character is removed if '0' - which it will be until ~2000)
 */

/* to change to N bit encoding, just change these 2 defines */
#define	BITS	5
#define	BIT_MASK 31

#define	MAX_CHARS ((48+BITS-1)/BITS)
/* of course if BITS is more than 6, you'll have to change this too */
char enc[]="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-";

main() {
	unsigned short sh[4];
	long l;
	static char rep[MAX_CHARS+1];
	extern long time();
	register long w=0,bit=48%BITS,p=0;
	register char *op=rep,*fp=rep;
	l=time((long *)0);
	sh[0]=l>>16;
	sh[1]=l;
	sh[2]=getppid();
	while (op<&rep[MAX_CHARS]) {
		if (bit<0) {
			w=sh[p++]<<(-bit);
			bit+=16;
		  }
		else if (bit<BITS)
			w|=sh[p]>>bit;
		*op++ = enc[(w>>(16-BITS))&BIT_MASK];
		w<<=BITS;
		bit-=BITS;
	  }
	*op++='\n';
	while (*fp==enc[0])
		++fp;
	write(1,fp,op-fp);
}