| #include <u.h> | 
 | #include <libc.h> | 
 | #include <ip.h> | 
 |  | 
 | enum | 
 | { | 
 | 	Isprefix= 16 | 
 | }; | 
 |  | 
 | /* XXX: manually initialize once to placate the Sun monster */ | 
 | uchar prefixvals[256]; | 
 | #ifdef NOTDEF | 
 | uchar prefixvals[256] = | 
 | { | 
 | [0x00] 0 | Isprefix, | 
 | [0x80] 1 | Isprefix, | 
 | [0xC0] 2 | Isprefix, | 
 | [0xE0] 3 | Isprefix, | 
 | [0xF0] 4 | Isprefix, | 
 | [0xF8] 5 | Isprefix, | 
 | [0xFC] 6 | Isprefix, | 
 | [0xFE] 7 | Isprefix, | 
 | [0xFF] 8 | Isprefix, | 
 | }; | 
 | #endif | 
 |  | 
 | int | 
 | eipfmt(Fmt *f) | 
 | { | 
 | 	char buf[5*8]; | 
 | 	static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux"; | 
 | 	static char *altefmt = "%.2ux:%.2ux:%.2ux:%.2ux:%.2ux:%.2ux"; | 
 | 	static char *ifmt = "%d.%d.%d.%d"; | 
 | 	char *fmt; | 
 | 	uchar *p, ip[16]; | 
 | 	ulong *lp; | 
 | 	ushort s; | 
 | 	int i, j, n, eln, eli; | 
 |  | 
 | 	static int once = 0;	/* XXX: placate the Sun monster */ | 
 |  | 
 | 	if(!once){ | 
 | 		once = 1; | 
 | 		memset(prefixvals, 0, sizeof(prefixvals)); | 
 | 		prefixvals[0x00] = 0 | Isprefix; | 
 | 		prefixvals[0x80] = 1 | Isprefix; | 
 | 		prefixvals[0xC0] = 2 | Isprefix; | 
 | 		prefixvals[0xE0] = 3 | Isprefix; | 
 | 		prefixvals[0xF0] = 4 | Isprefix; | 
 | 		prefixvals[0xF8] = 5 | Isprefix; | 
 | 		prefixvals[0xFC] = 6 | Isprefix; | 
 | 		prefixvals[0xFE] = 7 | Isprefix; | 
 | 		prefixvals[0xFF] = 8 | Isprefix; | 
 | 	} | 
 |  | 
 | 	switch(f->r) { | 
 | 	case 'E':		/* Ethernet address */ | 
 | 		p = va_arg(f->args, uchar*); | 
 | 		fmt = efmt; | 
 | 		if(f->flags&FmtSharp) | 
 | 			fmt = altefmt; | 
 | 		snprint(buf, sizeof buf, fmt, p[0], p[1], p[2], p[3], p[4], p[5]); | 
 | 		return fmtstrcpy(f, buf); | 
 |  | 
 | 	case 'I':		/* Ip address */ | 
 | 		p = va_arg(f->args, uchar*); | 
 | common: | 
 | 		if(memcmp(p, v4prefix, 12) == 0){ | 
 | 			snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]); | 
 | 			return fmtstrcpy(f, buf); | 
 | 		} | 
 |  | 
 | 		/* find longest elision */ | 
 | 		eln = eli = -1; | 
 | 		for(i = 0; i < 16; i += 2){ | 
 | 			for(j = i; j < 16; j += 2) | 
 | 				if(p[j] != 0 || p[j+1] != 0) | 
 | 					break; | 
 | 			if(j > i && j - i > eln){ | 
 | 				eli = i; | 
 | 				eln = j - i; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		/* print with possible elision */ | 
 | 		n = 0; | 
 | 		for(i = 0; i < 16; i += 2){ | 
 | 			if(i == eli){ | 
 | 				n += sprint(buf+n, "::"); | 
 | 				i += eln; | 
 | 				if(i >= 16) | 
 | 					break; | 
 | 			} else if(i != 0) | 
 | 				n += sprint(buf+n, ":"); | 
 | 			s = (p[i]<<8) + p[i+1]; | 
 | 			n += sprint(buf+n, "%ux", s); | 
 | 		} | 
 | 		return fmtstrcpy(f, buf); | 
 |  | 
 | 	case 'i':		/* v6 address as 4 longs */ | 
 | 		lp = va_arg(f->args, ulong*); | 
 | 		for(i = 0; i < 4; i++) | 
 | 			hnputl(ip+4*i, *lp++); | 
 | 		p = ip; | 
 | 		goto common; | 
 |  | 
 | 	case 'V':		/* v4 ip address */ | 
 | 		p = va_arg(f->args, uchar*); | 
 | 		snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]); | 
 | 		return fmtstrcpy(f, buf); | 
 |  | 
 | 	case 'M':		/* ip mask */ | 
 | 		p = va_arg(f->args, uchar*); | 
 |  | 
 | 		/* look for a prefix mask */ | 
 | 		for(i = 0; i < 16; i++) | 
 | 			if(p[i] != 0xff) | 
 | 				break; | 
 | 		if(i < 16){ | 
 | 			if((prefixvals[p[i]] & Isprefix) == 0) | 
 | 				goto common; | 
 | 			for(j = i+1; j < 16; j++) | 
 | 				if(p[j] != 0) | 
 | 					goto common; | 
 | 			n = 8*i + (prefixvals[p[i]] & ~Isprefix); | 
 | 		} else | 
 | 			n = 8*16; | 
 |  | 
 | 		/* got one, use /xx format */ | 
 | 		snprint(buf, sizeof buf, "/%d", n); | 
 | 		return fmtstrcpy(f, buf); | 
 | 	} | 
 | 	return fmtstrcpy(f, "(eipfmt)"); | 
 | } |