| 1 | #! /usr/bin/python |
| 2 | |
| 3 | import sre as re |
| 4 | import os |
| 5 | from sys import argv, stderr |
| 6 | |
| 7 | class struct (object): |
| 8 | def __init__(me, **kw): |
| 9 | me.__dict__.update(kw) |
| 10 | def __repr__(me): |
| 11 | r = '%s(' % me.__class__.__name__ |
| 12 | sep = '' |
| 13 | for k in me.__dict__: |
| 14 | r += sep + '%s=%r' % (k, me.__dict__[k]) |
| 15 | sep = ', ' |
| 16 | r += ')' |
| 17 | return r |
| 18 | |
| 19 | class service (struct): |
| 20 | def __str__(me): |
| 21 | return '%(name)s:%(port)d/%(proto)s' % me.__dict__ |
| 22 | def key(me): |
| 23 | return me.port, me.proto, me.name |
| 24 | def parse(string): |
| 25 | m = re.match(r'''^ (\S+) \s+ (\d+)/(\S+) \s* |
| 26 | ([^#\s] [^#]* [^#\s] | [^#\s])? \s* |
| 27 | (?: \# \s* (\S .* \S | \S |) )? \s* $''', |
| 28 | string, re.VERBOSE) |
| 29 | if not m: |
| 30 | raise 'Bad service line %r' % string |
| 31 | me = service(name = m.group(1), |
| 32 | port = int(m.group(2)), |
| 33 | proto = m.group(3), |
| 34 | aliases = m.group(4) and m.group(4).split() or [], |
| 35 | comment = m.group(5)) |
| 36 | return me |
| 37 | parse = staticmethod(parse) |
| 38 | |
| 39 | class servicetab (object): |
| 40 | def __init__(me): |
| 41 | me.tab = {} |
| 42 | def _insert(me, serv): |
| 43 | tab = me.tab |
| 44 | changep = False |
| 45 | if serv.key() not in tab: |
| 46 | tab[serv.key()] = serv |
| 47 | changep = True |
| 48 | else: |
| 49 | s = tab[serv.key()] |
| 50 | d = {} |
| 51 | for a in s.aliases: |
| 52 | d[a] = 1 |
| 53 | #warnp = True |
| 54 | dd = {} |
| 55 | for a in serv.aliases: |
| 56 | dd[a] = 1 |
| 57 | if a not in d: |
| 58 | #if warnp: |
| 59 | # print >>stderr, 'Merging aliases for %s' % s |
| 60 | # warnp = False |
| 61 | s.aliases += [a] |
| 62 | changep = True |
| 63 | #for a in s.aliases: |
| 64 | # if a not in dd: |
| 65 | # if warnp: |
| 66 | # print >>stderr, 'Merging aliases for %s' % s |
| 67 | # warnp = False |
| 68 | return changep |
| 69 | def scan(me, file): |
| 70 | changep = False |
| 71 | for l in open(file): |
| 72 | if re.match(r'^\s*(\#.*)?$', l): |
| 73 | continue |
| 74 | serv = service.parse(l) |
| 75 | if me._insert(serv): |
| 76 | changep = True |
| 77 | if not changep: |
| 78 | print >>stderr, 'File `%s\' redundant' % file |
| 79 | return changep |
| 80 | def write(me): |
| 81 | kk = me.tab.values() |
| 82 | kk.sort(lambda x, y: cmp(x.key(), y.key())) |
| 83 | print '## services file [generated]' |
| 84 | print |
| 85 | for s in kk: |
| 86 | print '%-20s %9s %s' % (s.name, |
| 87 | '%d/%s' % (s.port, s.proto), |
| 88 | ' '.join(s.aliases)) |
| 89 | |
| 90 | if 'running_under_emacs_p' not in globals(): |
| 91 | t = servicetab() |
| 92 | for f in argv[1:]: |
| 93 | t.scan(f) |
| 94 | t.write() |