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

typedef /*u*/int32_t ip;
typedef char ips[16];
typedef char ipb[3];

ip atoip(char *s) {
	ip ip = 0;
	if (*s == '/') {
		while (*++s)
			ip = ip * 10 + (*s - '0');
		ip = -1 >> 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, ip ip) {
	sprintf(s, "%3u.%3u.%3u.%3u",
			ip >> 24 & 255,
			ip >> 16 & 255,
			ip >>  8 & 255,
			ip >>  0 & 255);
}

void putip(ip 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(ip network, ip netmask) {
	network &= netmask;
	if (!~netmask)
		return 0;
	ip length = ~netmask + 1;
	
	int 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;
	}
	
	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, nbs, nwf, nwl, nwb, nms, 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)\n"
			 " netmask : IPv4 address (N.N.N.N)\n"
			 " N : Number of hosts in a network.");
		return 1;
	}
	
	ip network = atoip(argv[1]);
	ip netmask = atoip(argv[2]);
	l_ = i10len(~netmask + 1);
	nv_ = argv + 3;
	
	int l;
	printf("+--------------------+-----------------+-----------------+-----------------+--------------------+-");
	for (l = 0; l < l_; ++l) putchar('-');
	printf("-+-");
	for (l = 0; l < l_ + 1 + l_; ++l) putchar('-');
	printf("-+\n");
	printf("|         network |            from |              to |       broadcast |            netmask | %*s | %*s/%*s |\n",
		   l_, "l", l_, "u", l_, "a");
	printf("+--------------------+-----------------+-----------------+-----------------+-----------------+-");
	for (l = 0; l < l_; ++l) putchar('-');
	printf("-+-");
	for (l = 0; l < l_ + 1 + l_; ++l) putchar('-');
	printf("-+\n");
	
	subnet(network, netmask);
	
	printf("+--------------------+-----------------+-----------------+-----------------+--------------------+-");
	for (l = 0; l < l_; ++l) putchar('-');
	printf("-+-");
	for (l = 0; l < l_ + 1 + l_; ++l) putchar('-');
	printf("-+\n");
	
	return 0;
}
