[comp.graphics] Query: binary CGM <-> text CGM

kadie@m.cs.uiuc.edu (03/16/90)

Does anyone know of a program that will convert binary metafiles (CGM)
to text metafiles (and visa versa)?

[CGM stands for Computer Graphic Metafiles. It is an object-oriented
graphics specification language. It is used by the new version of Lotus 1-2-3
and several word processors (some call it *.GMF). The standard is 
described in the book "CGM and CGI" by David Arnold. There are three
encodings for CGM files: binary, character, and text.]


Carl Kadie
University of Illinois at Urbana-Champaign
ARPA:  kadie@m.cs.uiuc.edu
UUCP:  uiucdcs!kadie
CSNET: kadie@uiuc.csnet

flitter@dtrc.dt.navy.mil (Flitter) (03/20/90)

   CGM (Computer Graphics Metafile) is an ANSI and ISO standard described by
   ANSI X3.122-1986. It is also a Federal Information Processing Standard. Just
   for general info it's not a Lotus and wordprocessing format.
   Anyway, there is a public domain program called GPLOT which supports the
   binary encoding and the clear text encoding. I don't have the internet
   address handy right now but you can get the program by anonymous ftp. I'll
   see if I can find the IP address and I'll post it. As a side note I wouldn't
   trust GPLOT's conversion capabilities to much. I found it to be somewhat
   dissapointing.
   If you want commercial software, Lyle Henderson, the document editor of the
   CGM standard, has a company called Henderson Software located in California
   near LA. His company makes CGM products and they are probably pretty
   reliable. You might look him up if you really need reliability.

richard@pantor.UUCP (Richard Sargent) (03/21/90)

> From: flitter@dtrc.dt.navy.mil (Flitter)
> Message-ID: <1338@nems.dt.navy.mil>
...
>    If you want commercial software, Lyle Henderson, the document editor of the
>    CGM standard, has a company called Henderson Software located in California
>    near LA. His company makes CGM products and they are probably pretty
>    reliable. You might look him up if you really need reliability.

The editor's name is Lofton Henderson. And, unless he's moved within
the last year, he is located in Colorado.

The last information I have is:

	Lofton Henderson
	Henderson Software
	P.O.Box 4036
	Boulder, CO 80306
	(303) 494 - 5241
	...!hplabs!hao!scdpyr!lofton

Richard Sargent                   Internet: richard@pantor.UUCP
Systems Analyst                   UUCP:     ...!mnetor!becker!pantor!richard

littauer@uts.amdahl.com (Tom Littauer) (03/22/90)

In article <4400060@m.cs.uiuc.edu> kadie@m.cs.uiuc.edu writes:
>
>Does anyone know of a program that will convert binary metafiles (CGM)
>to text metafiles (and visa versa)?
>
>[CGM stands for Computer Graphic Metafiles. It is an object-oriented
>graphics specification language. It is used by the new version of Lotus 1-2-3
>and several word processors (some call it *.GMF). The standard is 
>described in the book "CGM and CGI" by David Arnold. There are three
>encodings for CGM files: binary, character, and text.]

The following shar file is a hack at binary to text (taken from the cited
book). I was looking into doing useful things with the output of Lotus
Freelance at the time (it outputs in CGM). Unfortunately, I ran into a
number of private use thingies and stopped for lack of time. The state of
bugginess and prettyness of the code is therefore undetermined. Anyone may
use this for whatever purpose they like, with the understanding that they
use it entirely at their own risk and that there are no warrantees, express
or implied. Amdahl Corp. is completely uninvolved in this, as the code was
developed on my own time and with my own resources.

The lawyers having been satisfied, let me know if my exploration project ends
up doing someone some good (I would never have bet on it at the time I stopped
working on it :-). I hope it does... I'd like to "pay forward" the debt I owe
to those who've helped me.

# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# gmf.c

: =-=-=-=-=-=-= first line of shar 1 of 1 =-=-=-=-=-=-=-=-=-
echo x - gmf.c
sed -e 's/^X//' > "gmf.c" << '//E*O*F gmf.c//'
X#include <stdio.h>
X#include <fcntl.h>
X#include <io.h>
X
X#define FALSE	0
X#define TRUE	(! FALSE)
X
X#define	DEBUG	TRUE
X
Xunsigned class;
Xunsigned element;
Xunsigned paramlen;
Xunsigned continued;
Xchar *indent;
X
Xint vdctype;				/* 0 = integer, 1 = real	*/
Xint realtype;				/* 1 = int.int			*/
Xint realint;				/* bits in int part of real 	*/
Xint realfrac;				/* bits in frac part of real	*/
Xint intprec;				/* bits in an integer		*/
Xdouble scale;				/* global scale factor		*/
Xint scalemode;				/* 0 = abstract, 1 = metric	*/
Xint vdclen;				/* # bytes a vdc point takes	*/
X
X/* coordinates of lower left and upper right corners */
X
Xdouble vdcllx;
Xdouble vdclly;
Xdouble vdcurx;
Xdouble vdcury;
X
Xint inputloc = 0;			/* current disp. in input file */
Xint bytesgot = 0;			/* # bytes gotten for parameter */
X	
X
Xmain() {
X	
X	
X	int tmp;
X	void spinoff(int);
X
X#ifdef MSDOS
X	setmode(fileno(stdin),O_BINARY);	/* make sure stdin is binary */
X#endif
X	
X	while ((tmp=getbyte(1)) != EOF) {
X		
X		class = (tmp >> 4) & 0x0f; 
X		element = (tmp & 0x0f) << 3;
X
X		tmp=getbyte(0);
X
X		element += (tmp >> 5) & 0x07;
X		paramlen = tmp & 0x1f;
X		
X		if (paramlen == 31) {  /* long parameter list */
X		
X			paramlen = longparm();
X		}
X
X		bytesgot = 0;	
X	
X		switch (class) {
X			
X			case 0:
X				class0();
X				break;
X
X			case 1:
X				class1();
X				break;
X							
X			case 2:
X				class2();
X				break;
X							
X			case 3:
X				class3();
X				break;
X							
X			case 4:
X				class4();
X				break;
X							
X			case 5:
X				class5();
X				break;
X							
X			case 6:
X				class6();
X				break;
X							
X			case 7:
X				class7();
X				break;
X
X			default:
X			
X				printf("Unknown class (%d) at location 0x%x\n",
X					class, inputloc);			
X				break;
X		}
X		spinoff(paramlen-bytesgot);
X
X		while (continued) {
X			
X			paramlen = longparm();
X			spinoff(paramlen);
X		}
X		
X	}
X}		
X
X
X
Xint getbyte(returneof)
X
Xint returneof;
X
X{
X	
X	int tmp;
X	
X	if (((tmp=fgetc(stdin)) == EOF) && ! returneof) {
X
X		perror("Unexpected EOF");
X		exit(1);
X	}
X	inputloc++;
X	bytesgot++;
X
X	return tmp;
X}
X
Xint getword()
X
X{
X	unsigned tmp1, tmp2;
X	unsigned tmp;
X
X	if (bytesgot >= paramlen) {
X		
X		printf("\nOverran parameter list at location 0x%x\n",inputloc);
X		exit(1);
X	}
X	
X	tmp1 = getbyte(0);
X	tmp2 = getbyte(0);
X	
X	tmp = tmp1*256 + tmp2;
X	return (int)(tmp>32767 ? tmp - 65536L : tmp);  
X}
X
Xdouble getreal()
X
X{
X	int tmp1, tmp2;
X	
X	tmp1 = getword();
X	tmp2 = getword();
X
X	return  tmp1 + ((double)tmp2)/32767;
X}
X
Xdouble getvdc()
X
X{
X
X	
X	if (vdctype == 0) return (double)getword();
X	if (vdctype == 1) return getreal();
X
X	printf("Unknown vdctype (%d) at location 0x%x\n",vdctype,inputloc);
X	exit(1);
X
X}
X	
Xvoid spinoff(numspin)
X
Xint numspin;
X
X{
X	if (! numspin) return;
X
X#ifdef DEBUG	
X
X	printf("%s\t",indent);
X	while (numspin--) {
X		printf("%02x",getbyte(0));
X		if (!(numspin & 1)) printf("\n%s\t",indent);
X	}
X	printf("\n");
X
X#else
X
X	while (numspin--) getbyte(0);
X
X#endif
X
X	return;
X}
X
Xint longparm()
X
X{
X	int tmp;
X	int pl;
X	
X				
X	tmp=getbyte(0);
X
X	if (tmp & 0x80) continued = TRUE;
X	else continued = FALSE;
X	
X	pl = (tmp & 0x7f) << 8;
X
X	tmp=getbyte(0);
X		
X	pl += tmp;
X
X	return pl;
X}
X
Xvoid putvdc(x,y)
X
Xdouble x;
Xdouble y;
X
X{
X
X	if (vdctype == 0) {
X				
X		printf("(%.0f,%.0f)",x,y);
X	}
X	else {
X		
X		printf("(%f,%f)",x,y);
X	}
X}
X
Xvoid getmfstr(buf,bufmax)
X
Xchar *buf;
Xint bufmax;
X
X{
X	int len;
X
X	len = getbyte(0);
X	
X	if (len > paramlen-1) {
X		printf("String length greater than parameter length\n");
X		printf("Location: 0x%x Class: %d Element: %d\n",
X			inputloc,class,element);
X			
X		exit(1);
X	}
X	
X	if (len > bufmax-1) {
X		printf("String length greater than buffer size\n");
X		printf("Location: 0x%x Class: %d Element: %d\n",
X			inputloc,class,element);
X			
X		exit(1);
X	}
X
X	while (len--) {
X
X		*buf = getbyte(0);
X		if (*buf == '\'') *(++buf)='\'';
X		buf++;
X	}
X
X	*buf = '\0';
X	return;
X}
X	
X
Xclass0()
X
X{
X	char buf[512];
X
X	char *cp;
X	
X	switch (element) {
X	
X		case 1:
X			
X			indent = " ";
X			getmfstr(buf,512);
X			printf("%sBEGMF '%s';\n",indent,buf);
X			indent = "\t";
X			break;
X			
X		case 2:
X			indent = " ";
X			printf("%sENDMF;\n",indent);
X			break;
X			
X		case 3:
X		
X			getmfstr(buf,512);
X			printf("%sBEGPIC '%s';\n",indent,buf);
X			indent="\t\t";
X			break;
X
X		case 4:
X			printf("%sBEGPICBODY;\n",indent);
X			indent="\t\t\t";
X			break;
X			
X		case 5:
X			indent="\t";
X			printf("%sENDPIC;\n",indent);
X			break;
X
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
Xclass1()
X
X{
X	char buf[512];
X	int tmp;
X	int i;
X	char *cp;
X	
X	switch (element) {
X
X		case 1:
X			tmp = getword();
X			printf("%sMFVERSION %d;\n",indent,tmp);
X			break;		
X
X		case 2:
X		
X			getmfstr(buf,512);
X			printf("%sMFDESC '%s';\n",indent,buf);
X			break;
X
X		case 3:
X			tmp = getword();
X			printf("%sVDCTYPE %s;\n",indent,tmp?"REAL":"INTEGER");
X			vdctype = tmp;
X			break;		
X
X		case 4:
X			intprec = getword();
X			printf("%sINTEGERPREC %d;\n",indent,intprec);
X			break;		
X
X		case 5:
X			realtype = getword();
X			printf("%sREALPREC %d, ",indent,realtype);
X			realint = getword();
X			printf("%d,",realint);
X			realfrac = getword();
X			printf(" %d;\n",realfrac);
X			
X			if (realtype != 1) {
X				printf("Can't handle mode %d\n",realtype);
X				exit(1);
X			}
X
X			break;		
X
X		case 6:
X			tmp = getword();
X			printf("%sINDEXPREC %d;\n",indent,tmp);
X			break;		
X
X		case 7:
X			tmp = getword();
X			printf("%sCOLRPREC %d;\n",indent,tmp);
X			break;		
X
X		case 8:
X			tmp = getword();
X			printf("%sCOLRINDEXPREC %d;\n",indent,tmp);
X			break;		
X
X		case 9:
X			tmp = getword();
X			printf("%sMAXCOLRINDEX %d;\n",indent,tmp);
X			break;		
X
X		case 10:
X		
X			printf("%sCOLRVALUEEXT\n",indent);
X			break;
X
X		case 11:
X		
X			printf("%sMFELEMLIST ",indent);
X			tmp = getword();	/* number of elements */
X			for (i=0; i < tmp; i++) {
X				if (!(i % 8)) printf("\n%s",indent);
X				printf("\t%d",getword());
X				printf(":%d",getword());
X			}
X			printf(";\n");
X			break;
X
X		case 12:
X		
X			printf("%sBEGMFDEFAULTS\n",indent);
X			break;
X
X		case 13:
X		
X			printf("%sFONTLIST\n",indent);
X			break;
X
X		case 14:
X		
X			printf("%sCHARSETLIST\n",indent);
X			break;
X
X		case 15:
X			tmp = getword();
X			printf("%sCHARCODING %d;\n",indent,tmp);
X			break;		
X
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
X
Xclass2()
X
X{
X	char buf[512];
X	int tmp;
X	char *cp;
X	
X	switch (element) {
X
X		case 1:
X			scalemode = getword();
X			printf("%sSCALEMODE %s ",indent,
X				scalemode ? "METRIC" : "ABSTRACT");
X			scale = getreal();
X			printf("%f;\n",scale);
X			break;		
X
X		case 2:
X			tmp = getword();
X			printf("%sCOLRMODE %d;\n",indent,tmp);
X			break;		
X
X		case 3:
X			tmp = getword();
X			printf("%sLINEWIDTHMODE %d;\n",indent,tmp);
X			break;		
X
X		case 4:
X			tmp = getword();
X			printf("%sMARKERSIZEMODE %d;\n",indent,tmp);
X			break;		
X
X		case 5:
X			tmp = getword();
X			printf("%sEDGEWIDTHMODE %d;\n",indent,tmp);
X			break;		
X
X		case 6:
X			vdcllx = getvdc();
X			vdclly = getvdc();
X			vdcurx = getvdc();
X			vdcury = getvdc();
X			printf("%sVDCEXT ",indent);
X			putvdc(vdcllx,vdclly);
X			printf("  ");
X			putvdc(vdcurx,vdcury);
X			printf(";\n");
X			break;		
X
X		case 7:
X			tmp = getword();
X			printf("%sBACKCOLR %d;\n",indent,tmp);
X			break;		
X
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
Xclass3()
X
X{
X	char buf[512];
X	int tmp;
X	char *cp;
X	
X	switch (element) {
X
X
X		case 1:
X			tmp = getword();
X			printf("%sVDCINTEGERPREC %d;\n",indent,tmp);
X			vdclen = tmp / 8; /* ??? */
X			break;
X
X		case 2:
X			printf("%sVDCREALPREC\n",indent);
X			break;
X
X		case 3:
X			printf("%sAUXCOLR\n",indent);
X			break;
X
X		case 4:
X			tmp = getword();
X			printf("%sTRANSPARENCY %s;\n",indent,tmp ? "ON" : "OFF");
X			break;
X
X		case 5:
X			printf("%sCLIPRECT\n",indent);
X			break;
X
X		case 6:
X			tmp = getword();
X			printf("%sCLIP %s;\n",indent,tmp ? "ON" : "OFF");
X			break;
X			
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
Xclass4()
X
X{
X	char buf[512];
X	int tmp;
X	double rtmp1, rtmp2;
X	int i;
X	char *cp;
X	
X	switch (element) {
X
X
X		case 1:
X			printf("%sLINE",indent);
X			putvdclst();
X			break;
X
X		case 2:
X			printf("%sDISJTLINE",indent);
X			putvdclst();
X			break;
X
X		case 3:
X			printf("%sMARKER\n",indent);
X			break;
X
X		case 4:
X			rtmp1 = getvdc();
X			rtmp2 = getvdc();
X			tmp = getword();
X			getmfstr(buf,512);
X			printf("%sTEXT ",indent);
X			putvdc(rtmp1,rtmp2);
X			printf(" %s",tmp ? "FINAL" : "NON-FINAL");
X			printf(" '%s\n';",buf);
X			break;
X
X		case 5:
X			printf("%sRESTRTEXT\n",indent);
X			break;
X
X		case 6:
X			printf("%sAPNDTEXT\n",indent);
X			break;
X
X		case 7:
X			printf("%sPOLYGON",indent);
X			putvdclst();
X			break;
X
X		case 8:
X			printf("%sPOLYGONSET\n",indent);
X			break;
X
X		case 9:
X			printf("%sCELLARRAY\n",indent);
X			break;
X
X		case 10:
X			printf("%sGDP\n",indent);
X			break;
X
X		case 11:
X			printf("%sRECT",indent);
X			putvdclst();
X			break;
X
X		case 12:
X			printf("%sCIRCLE",indent);
X			putvdclst();
X			break;
X
X		case 13:
X			printf("%sARC3PT\n",indent);
X			break;
X
X		case 14:
X			printf("%sARC3PTCLOSE\n",indent);
X			break;
X
X		case 15:
X			printf("%sARCCTR\n",indent);
X			break;
X
X		case 16:
X			printf("%sARCCTRCLOSE\n",indent);
X			break;
X
X		case 17:
X			printf("%sELLIPSE",indent);
X			putvdclst();
X			break;
X
X		case 18:
X			printf("%sELLIPARC",indent);
X			putvdclst();
X			break;
X
X		case 19:
X			printf("%sELLIPARCCLOSE\n",indent);
X			break;
X
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
Xclass5()
X
X{
X	char buf[512];
X	int tmp;
X	char *cp;
X	
X	switch (element) {
X
X
X		case 1:
X			tmp = getword();
X			printf("%sLINEINDEX %d;\n",indent,tmp);
X			break;
X
X		case 2:
X			tmp = getword();
X			printf("%sLINETYPE %d;\n",indent,tmp);
X			break;
X
X		case 3:
X			tmp = getword();
X			printf("%sLINEWIDTH %d;\n",indent,tmp);
X			break;
X
X		case 4:
X			tmp = getword();
X			printf("%sLINECOLR %d;\n",indent,tmp);
X			break;
X
X		case 5:
X			tmp = getword();
X			printf("%sMARKERINDEX %d;\n",indent,tmp);
X			break;
X
X		case 6:
X			tmp = getword();
X			printf("%sMARKERTYPE %d;\n",indent,tmp);
X			break;
X
X		case 7:
X			tmp = getword();
X			printf("%sMARKERSIZE %d;\n",indent,tmp);
X			break;
X
X		case 8:
X			tmp = getword();
X			printf("%sMARKERCOLR %d;\n",indent,tmp);
X			break;
X
X		case 9:
X			tmp = getword();
X			printf("%sTEXTINDEX %d;\n",indent,tmp);
X			break;
X
X		case 10:
X			tmp = getword();
X			printf("%sTEXTFONTINDEX %d;\n",indent,tmp);
X			break;
X
X		case 11:
X			tmp = getword();
X			printf("%sTEXTPREC %d;\n",indent,tmp);
X			break;
X
X		case 12:
X			tmp = getword();
X			printf("%sCHAREXPAN %d;\n",indent,tmp);
X			break;
X
X		case 13:
X			tmp = getword();
X			printf("%sCHARSPACE %d;\n",indent,tmp);
X			break;
X
X		case 14:
X			tmp = getword();
X			printf("%sTEXTCOLR %d;\n",indent,tmp);
X			break;
X
X		case 15:
X			tmp = getword();
X			printf("%sCHARHEIGHT %d;\n",indent,tmp);
X			break;
X
X		case 16:
X			tmp = getword();
X			printf("%sCHARORI (%d",indent,tmp);
X			tmp = getword();
X			printf(", %d",tmp);
X			tmp = getword();
X			printf(", %d",tmp);
X			tmp = getword();
X			printf(", %d);\n",tmp);
X			break;
X
X		case 17:
X			tmp = getword();
X			printf("%sTEXTPATH %d;\n",indent,tmp);
X			break;
X
X		case 18:
X			tmp = getword();
X			printf("%sTEXTALIGN %d;\n",indent,tmp);
X			break;
X
X		case 19:
X			tmp = getword();
X			printf("%sCHARSETINDEX %d;\n",indent,tmp);
X			break;
X
X		case 20:
X			tmp = getword();
X			printf("%sALTCHARSETINDEX %d;\n",indent,tmp);
X			break;
X
X		case 21:
X			tmp = getword();
X			printf("%sFILLINDEX %d;\n",indent,tmp);
X			break;
X
X		case 22:
X			tmp = getword();
X			printf("%sINTSTYLE %d;\n",indent,tmp);
X			break;
X
X		case 23:
X			tmp = getword();
X			printf("%sFILLCOLR %d;\n",indent,tmp);
X			break;
X
X		case 24:
X			tmp = getword();
X			printf("%sHATCHINDEX %d;\n",indent,tmp);
X			break;
X
X		case 25:
X			tmp = getword();
X			printf("%sPATHINDEX %d;\n",indent,tmp);
X			break;
X
X		case 26:
X			tmp = getword();
X			printf("%sEDGEINDEX %d;\n",indent,tmp);
X			break;
X
X		case 27:
X			tmp = getword();
X			printf("%sEDGETYPE %d;\n",indent,tmp);
X			break;
X
X		case 28:
X			tmp = getword();
X			printf("%sEDGEWIDTH %d;\n",indent,tmp);
X			break;
X
X		case 29:
X			tmp = getword();
X			printf("%sEDGECOLR %d;\n",indent,tmp);
X			break;
X
X		case 30:
X			tmp = getword();
X			printf("%sEDGEVIS %d;\n",indent,tmp);
X			break;
X
X		case 31:
X			tmp = getword();
X			printf("%sFILLREFPT %d;\n",indent,tmp);
X			break;
X
X		case 32:
X			tmp = getword();
X			printf("%sPATTABLE %d;\n",indent,tmp);
X			break;
X
X		case 33:
X			tmp = getword();
X			printf("%sPATSIZE %d;\n",indent,tmp);
X			break;
X
X		case 34:
X			tmp = getword();
X			printf("%sCOLRTABLE %d;\n",indent,tmp);
X			break;
X
X		case 35:
X			tmp = getword();
X			printf("%sASF %d;\n",indent,tmp);
X			break;
X
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
Xclass6()
X
X{
X	char buf[512];
X	int tmp;
X	char *cp;
X	
X	switch (element) {
X
X		case 1:
X
X			tmp = getword();
X			printf("%sESCAPE %d;\n",indent,tmp);
X			break;
X
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
Xclass7()
X
X{
X	char buf[512];
X	int tmp;
X	char *cp;
X	
X	switch (element) {
X
X		case 1:
X			tmp = getword();
X			getmfstr(buf,512);
X			printf("%sMESSAGE %s '%s';\n",
X				indent,tmp?"ACTION":"NO-ACTION",buf);
X			break;
X
X		case 2:
X			tmp = getbyte(0);
X			printf("%sAPPLDATA %c%c\n",indent,tmp,getbyte(0));
X			break;
X
X		default:
X			printf("*** Unknown element (%d:%d) at location 0x%x\n",
X				class, element, inputloc);
X				
X			break;
X	}
X}
X
X
Xputvdclst()
X
X{
X
X	int i;
X	double rtmp1, rtmp2;
X	
X	i = 0;
X	while (i < paramlen) {
X		if (!((i/vdclen)%3)) printf("\n%s\t",indent);
X		rtmp1 = getvdc();
X		rtmp2 = getvdc();
X		printf("  ");
X		putvdc(rtmp1,rtmp2);
X		i += 2 * vdclen;
X	}
X	printf(";\n");
X}
//E*O*F gmf.c//

exit 0
-- 
UUCP:  littauer@amdahl.amdahl.com
  or:  {sun,decwrl,hplabs,pyramid,ames,uunet}!amdahl!littauer
DDD:   (408) 737-5056
USPS:  Amdahl Corp.  M/S 278,  1250 E. Arques Av,  Sunnyvale, CA 94086

I'll tell you when I'm giving you the party line. The rest of the time
it's my very own ravings (accept no substitutes).