#! /usr/bin/python import sre as re import os from sys import argv, stderr class struct (object): def __init__(me, **kw): me.__dict__.update(kw) def __repr__(me): r = '%s(' % me.__class__.__name__ sep = '' for k in me.__dict__: r += sep + '%s=%r' % (k, me.__dict__[k]) sep = ', ' r += ')' return r class service (struct): def __str__(me): return '%(name)s:%(port)d/%(proto)s' % me.__dict__ def key(me): return me.port, me.proto, me.name def parse(string): m = re.match(r'''^ (\S+) \s+ (\d+)/(\S+) \s* ([^#\s] [^#]* [^#\s] | [^#\s])? \s* (?: \# \s* (\S .* \S | \S |) )? \s* $''', string, re.VERBOSE) if not m: raise 'Bad service line %r' % string me = service(name = m.group(1), port = int(m.group(2)), proto = m.group(3), aliases = m.group(4) and m.group(4).split() or [], comment = m.group(5)) return me parse = staticmethod(parse) class servicetab (object): def __init__(me): me.tab = {} def _insert(me, serv): tab = me.tab changep = False if serv.key() not in tab: tab[serv.key()] = serv changep = True else: s = tab[serv.key()] d = {} for a in s.aliases: d[a] = 1 #warnp = True dd = {} for a in serv.aliases: dd[a] = 1 if a not in d: #if warnp: # print >>stderr, 'Merging aliases for %s' % s # warnp = False s.aliases += [a] changep = True #for a in s.aliases: # if a not in dd: # if warnp: # print >>stderr, 'Merging aliases for %s' % s # warnp = False return changep def scan(me, file): changep = False for l in open(file): if re.match(r'^\s*(\#.*)?$', l): continue serv = service.parse(l) if me._insert(serv): changep = True if not changep: print >>stderr, 'File `%s\' redundant' % file return changep def write(me): kk = me.tab.values() kk.sort(lambda x, y: cmp(x.key(), y.key())) print '## services file [generated]' print for s in kk: print '%-20s %9s %s' % (s.name, '%d/%s' % (s.port, s.proto), ' '.join(s.aliases)) if 'running_under_emacs_p' not in globals(): t = servicetab() for f in argv[1:]: t.scan(f) t.write()