a1a5a21298
Use group 'misc' as a default and print a warning. Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
192 lines
5.2 KiB
Python
Executable file
192 lines
5.2 KiB
Python
Executable file
#!/usr/bin/python
|
|
|
|
import errno
|
|
import os
|
|
import re
|
|
import sys
|
|
import hashlib
|
|
|
|
from collections import defaultdict
|
|
from pprint import pprint
|
|
|
|
# TODO: handle commands with the same name in multiple files
|
|
# TODO: handle #ifdefs
|
|
|
|
HELP_START = re.compile(r"""^BAREBOX_CMD_HELP_START\s*\((\w+)\)?\s*$""")
|
|
HELP_TEXT = re.compile(r"""^BAREBOX_CMD_HELP_TEXT\s*\("(.*?)"\)?\s*$""")
|
|
HELP_OPT = re.compile(r"""^BAREBOX_CMD_HELP_OPT\s*\("(.+?)",\s*"(.+?)"\)?\s*$""")
|
|
HELP_END = re.compile(r"""^BAREBOX_CMD_HELP_END\s*$""")
|
|
|
|
CMD_START = re.compile(r"""^BAREBOX_CMD_START\s*\((.+)\)\s*$""")
|
|
CMD_FUNC = re.compile(r"""^\s*\.cmd\s*=\s*(.+?),\s*$""")
|
|
CMD_DESC = re.compile(r"""^\s*BAREBOX_CMD_DESC\s*\("(.*?)"\)?\s*$""")
|
|
CMD_OPTS = re.compile(r"""^\s*BAREBOX_CMD_OPTS\s*\("(.*?)"\)?\s*$""")
|
|
CMD_GROUP = re.compile(r"""^\s*BAREBOX_CMD_GROUP\s*\((.+)\)\s*$""")
|
|
CMD_END = re.compile(r"""^BAREBOX_CMD_END\s*$""")
|
|
|
|
CONT = re.compile(r"""\s*"(.*?)"\s*\)?\s*$""")
|
|
|
|
CMDS = {}
|
|
|
|
def parse_c(name):
|
|
cmd = None
|
|
last = None
|
|
for line in file(name, 'r'):
|
|
x = HELP_START.match(line)
|
|
if x:
|
|
cmd = CMDS.setdefault(x.group(1), defaultdict(list))
|
|
cmd.setdefault("files", set()).add(name)
|
|
continue
|
|
x = CMD_START.match(line)
|
|
if x:
|
|
cmd = CMDS.setdefault(x.group(1), defaultdict(list))
|
|
cmd.setdefault("files", set()).add(name)
|
|
continue
|
|
if cmd is None:
|
|
continue
|
|
x = HELP_TEXT.match(line)
|
|
if x:
|
|
if 'h_opts' not in cmd:
|
|
last = cmd['h_pre']
|
|
else:
|
|
last = cmd['h_post']
|
|
last.append(x.group(1).decode("string_escape").strip())
|
|
continue
|
|
x = HELP_OPT.match(line)
|
|
if x:
|
|
last = cmd['h_opts']
|
|
last.append([
|
|
x.group(1).decode("string_escape"),
|
|
x.group(2).decode("string_escape")
|
|
])
|
|
continue
|
|
x = CMD_FUNC.match(line)
|
|
if x:
|
|
last = cmd['c_func']
|
|
last.append(x.group(1))
|
|
continue
|
|
x = CMD_DESC.match(line)
|
|
if x:
|
|
last = cmd['c_desc']
|
|
last.append(x.group(1).decode("string_escape"))
|
|
continue
|
|
x = CMD_OPTS.match(line)
|
|
if x:
|
|
last = cmd['c_opts']
|
|
last.append(x.group(1).decode("string_escape"))
|
|
continue
|
|
x = CMD_GROUP.match(line)
|
|
if x:
|
|
last = cmd['c_group']
|
|
last.append(x.group(1).split('_')[-1].lower())
|
|
continue
|
|
x = CONT.match(line)
|
|
if x:
|
|
if last is None:
|
|
raise Exception("Parse error in %s: %r" % (name, line))
|
|
if isinstance(last[-1], str):
|
|
last[-1] += x.group(1).decode("string_escape")
|
|
elif isinstance(last[-1], list):
|
|
last[-1][1] += x.group(1).decode("string_escape")
|
|
continue
|
|
x = HELP_END.match(line)
|
|
if x:
|
|
cmd = last = None
|
|
x = CMD_END.match(line)
|
|
if x:
|
|
cmd = last = None
|
|
|
|
def gen_rst(name, cmd):
|
|
out = []
|
|
out.append('.. index:: %s (command)' % name)
|
|
out.append('')
|
|
out.append('.. _command_%s:' % name)
|
|
out.append('')
|
|
if 'c_desc' in cmd:
|
|
out.append("%s - %s" % (name, ''.join(cmd['c_desc']).strip()))
|
|
else:
|
|
out.append("%s" % (name,))
|
|
out.append('='*len(out[-1]))
|
|
out.append('')
|
|
if 'c_opts' in cmd:
|
|
out.append('Usage')
|
|
out.append('^'*len(out[-1]))
|
|
out.append('``%s %s``' % (name, ''.join(cmd['c_opts']).strip()))
|
|
out.append('')
|
|
if 'h_pre' in cmd:
|
|
pre = cmd['h_pre']
|
|
if pre and pre[-1] == "Options:":
|
|
del pre[-1]
|
|
if pre and pre[-1] == "":
|
|
del pre[-1]
|
|
if pre:
|
|
out.append('Synopsis')
|
|
out.append('^'*len(out[-1]))
|
|
out.append('\n'.join(cmd['h_pre']).strip())
|
|
out.append('')
|
|
if 'h_opts' in cmd:
|
|
out.append('Options')
|
|
out.append('^'*len(out[-1]))
|
|
for o, d in cmd['h_opts']:
|
|
o = o.strip()
|
|
d = d.strip()
|
|
if o:
|
|
out.append('%s\n %s' % (o, d))
|
|
else:
|
|
out.append(' %s' % (d,))
|
|
out.append('')
|
|
if 'h_post' in cmd:
|
|
post = cmd['h_post']
|
|
if post and post[0] == "":
|
|
del post[0]
|
|
if post:
|
|
out.append('Description')
|
|
out.append('^'*len(out[-1]))
|
|
out.append('\n'.join(cmd['h_post']).strip())
|
|
out.append('')
|
|
out.append('.. generated from: %s' % ', '.join(cmd['files']))
|
|
if 'c_func' in cmd:
|
|
out.append('.. command function: %s' % ', '.join(cmd['c_func']))
|
|
return '\n'.join(out)
|
|
|
|
for root, dirs, files in os.walk(sys.argv[1]):
|
|
for name in files:
|
|
if name.endswith('.c'):
|
|
source = os.path.join(root, name)
|
|
parse_c(source)
|
|
|
|
for name in CMDS.keys():
|
|
CMDS[name] = dict(CMDS[name])
|
|
|
|
for name, cmd in CMDS.items():
|
|
#pprint({name: cmd})
|
|
rst = gen_rst(name, cmd)
|
|
group = cmd.get('c_group')
|
|
if group is None:
|
|
print >> sys.stderr, "gen_commands: warning: using default group 'misc' for command '%s'" % name
|
|
group = ['misc']
|
|
subdir = os.path.join(sys.argv[2], group[0])
|
|
try:
|
|
os.makedirs(subdir)
|
|
except OSError as e:
|
|
if e.errno == errno.EEXIST and os.path.isdir(subdir):
|
|
pass
|
|
else:
|
|
raise
|
|
target = os.path.join(subdir, name+'.rst')
|
|
|
|
# Only write the new rst if it differs from the old one. Wroto
|
|
hash_old = hashlib.sha1()
|
|
try:
|
|
f = open(target, 'rb')
|
|
hash_old.update(f.read())
|
|
except:
|
|
pass
|
|
hash_new = hashlib.sha1()
|
|
hash_new.update(rst)
|
|
if hash_old.hexdigest() == hash_new.hexdigest():
|
|
continue
|
|
|
|
file(target, 'w').write(rst)
|
|
|