chiark / gitweb /
infra: Add a copy of the GPL.
[services] / merge-services
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()