#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef int32_t ip;// for netmasks
typedef uint32_t uip;// for networks
typedef char ips[16];
typedef char ipb[3];

uip atoip(char *s) {
	uip ip = 0;
	if (*s == '/') {
		while (*++s)
			ip = ip * 10 + (*s - '0');
		ip = ~((1 << 32 - ip) - 1);
	} else while (*s) {
		if (*s == '.')
			ip <<= 8;
		else
			ip += (ip & 255) * 10 + (*s - '0') - (ip & 255);
		++s;
	}
	return ip;
}

// string print ip
void spip(ips s, uip ip) {
	sprintf(s, "%3u.%3u.%3u.%3u",
			ip >> 24 & 255,
			ip >> 16 & 255,
			ip >>  8 & 255,
			ip >>  0 & 255);
}

void putip(uip ip) {
	ips ips; spip(ips, ip); puts(ips);
}

// string netmask to bit
void snm2b(ipb s, ip netmask) {
	int b = 0;
	while (netmask)
		netmask <<= 1, ++b;
	sprintf(s, "%2u", b);
}

int i10len(int i) {
	int len = 0;
	while (i)
		i /= 10, ++len;
	return len;
}

int l_;
char **nv_;

// Subnet the network, one bit at a time
int subnet(uip network, ip netmask) {
	network &= netmask;
	if (!~netmask)
		return 0;
	uip length = ~netmask + 1;
	//printf("length1 %u %u\n", length, network & length);
	
	uip n = 0;
	if (*nv_) {
		n = atoi(*nv_) + 2;
		if (length >> 1 >= n)
			return (subnet(network, netmask >> 1),
					subnet(network + (length >> 1), netmask >> 1));
		if (length >= n) ++nv_;
		else n = 0;
	}
	//printf("length2 %u %u\n", length, network & length);
	
	ips nws, nwf, nwl, nwb, nms;
	spip(nws, network);
	spip(nwf, network + 1);
	spip(nwl, network + (length - 2));
	spip(nwb, network | ~netmask);
	spip(nms, netmask);
	ipb nbs;
	snm2b(nbs, netmask);
	printf("| %s | %s | %s | %s || %s /%s | %*u | %*u/%*u |\n",
		   nws, nwf, nwl, nwb, nms, nbs, l_, length, l_, n ? n - 2 : 0, l_, length - 2);
	
	return n;
}

int main(int argc, char *argv[]) {
	if (argc < 4) {
		puts("Usage : vlsm network netmask N...\n"
			 " network : IPv4 address (N.N.N.N or /N)\n"
			 " netmask : IPv4 address (N.N.N.N or /N)\n"
			 " N : Number of hosts in a network.");
		return 1;
	}
	
	uip network = atoip(argv[1]);
	ip netmask = atoip(argv[2]);
	l_ = i10len(~netmask + 1);
	nv_ = argv + 3;
	
	printf("network :\n ");
	putip(network);
	printf("netmask :\n ");
	putip(netmask);
	
	int l;
#define _line \
	printf("+-----------------+-----------------+-----------------+-----------------++---------------------+-");\
	for(l=0;l<l_;++l)putchar('-');printf("-+-");for(l=0;l<l_+1+l_;++l)putchar('-');printf("-+\n");
	
	_line
	printf("|         network |            from |              to |       broadcast ||             netmask | "
		   "%*s | %*s/%*s |\n", l_, "l", l_, "u", l_, "a");
	_line
	
	subnet(network, netmask);
	
	_line
	
	if (*nv_) {
		puts("Not enough space for these :");
		while (*nv_)
			putchar(' '), puts(*nv_++);
	}
	
	return 0;
}
