#!/usr/bin/env python
# vim: set ts=8 sw=4 sts=4 et ai:
# Walter Doekes, Public Domain, 2013, version:1
from re import compile as re_compile
from socket import inet_aton
from struct import unpack
from sys import argv, exit, stdin

# The "program"
def main():
    items = extract_ips(stdin)
    items = [ipmask_to_tuple(i) for i in items]
    items = prune_tuples(items)
    print_tuples(items)
    
# Read IPs 
def extract_ips(file):
    extract_ips = re_compile(r'(\d+\.\d+\.\d+\.\d+/\d+)')
    ipmasks = []
    for line in file:
        ipmasks.extend(extract_ips.findall(line))
    return ipmasks

# Translate IP
def ipmask_to_tuple(string):
    ip, mask = string.split('/', 1)
    ip = unpack('>I', inet_aton(ip))[0]
    mask = int(mask)
    assert 0 <= mask <= 32, '%d?' % (mask,)
    mask = (0xffffffff << (32 - mask)) & 0xffffffff
    assert (ip & mask) == ip, '%08x/%08x' % (ip, mask)
    return ip, mask, string

# Remove dupes / overlap
def prune_tuples(items):
    # Sort and remove direct dupes
    items = list(set(items))
    items.sort()
    # See if there are larger blocks that encompass smaller ones
    # in a nice O(N^2) loop
    large_tuples = []
    for ip, mask, string in items:
        # For each IP, check if there is a bigger range
        for large_ip, large_mask, _ in items:
            # Don't check if our mask is bigger or is self
            # (a bigger mask is a smaller value!)
            if mask <= large_mask:
                continue
            # If the bigger mask encompasses us, ignore
            if (ip & large_mask) == large_ip:
                break
        else:
            # No break? Then we have an active one
            large_tuples.append((ip, mask, string))
    return large_tuples

# Print list
def print_tuples(items):
    print '('
    for ip, mask, string in items:
        print '    (0x%08x, 0x%08x), # %s' % (ip, mask, string)
    print ')'

# Go go go
if __name__ == '__main__':
    if len(argv) > 1:
        print 'Usage: %s < file_with_ip_mask.txt' % (argv[0],)
        print '  input data which contains one or more IP-blocks in'
        print '  CIDR notation (e.g. 1.2.3.0/24), will print output '
        print '  usable by python'
        print 'Example:'
        print '  (printf "1.2.3.0/24\\n1.2.4.0/24\\n1.2.2.0/23\\n"'
        print '   printf "1.2.2.0/24\\n1.2.0.0/22") | python %s' % (argv[0],)
        exit(0)
    main()
