Revamp command line options to add mcpp mode with defaults.

Also remove stderr from subprocess call (let the subprocess do its own output to stderr without capturing and re-emitting it ourselves).
This commit is contained in:
Sei Lisa 2015-03-19 04:11:29 +01:00
parent 226f382c4f
commit df8a8b4e9e

112
main.py
View file

@ -147,13 +147,12 @@ Usage: {progname}
[-h|--help] print this help [-h|--help] print this help
[--version] print this program's version [--version] print this program's version
[-o|--output=<filename>] output to file rather than stdout [-o|--output=<filename>] output to file rather than stdout
[-H|--header] Add the script as a comment in Firestorm format [-H|--header] add the script as a comment in Firestorm format
[-p|--preproc=mode] run external preprocessor (default is GNU cpp) [-p|--preproc=mode] run external preprocessor (see below for modes)
(resets the preprocessor command line so far)
[-P|--prearg=<arg>] add parameter to preprocessor's command line [-P|--prearg=<arg>] add parameter to preprocessor's command line
(or command name if first after --prereset) [--precmd=<cmd>] preprocessor command ('cpp' by default)
[--precmd=<cmd>] Preprocessor command. By default, 'cpp'. [--prenodef] no LSL specific defines (__AGENTKEY__ etc.)
Useful mainly if it's not in the path.
[--prereset] reset the preprocessor cmd/arg list
[--avid=<UUID>] specify UUID of avatar saving the script [--avid=<UUID>] specify UUID of avatar saving the script
[--avname=<name>] specify name of avatar saving the script [--avname=<name>] specify name of avatar saving the script
[--assetid=<UUID>] specify the asset UUID of the script [--assetid=<UUID>] specify the asset UUID of the script
@ -164,8 +163,11 @@ If filename is a dash (-) then standard input is used.
Use: {progname} -O help for help on the command line options. Use: {progname} -O help for help on the command line options.
Preprocessor modes: Preprocessor modes:
external: Invoke GNU cpp ext Invoke preprocessor
extnodef: Invoke GNU cpp, don't add extra defines mcpp Invoke mcpp as preprocessor, setting default parameters pertinent
to it. Implies --precmd=mcpp
gcpp Invoke GNU cpp as preprocessor, setting default parameters
pertinent to it. Implies --precmd=cpp
none: No preprocessing (default) none: No preprocessing (default)
'''.format(progname=sys.argv[0], version=VERSION)) '''.format(progname=sys.argv[0], version=VERSION))
@ -257,6 +259,8 @@ Optimizer options (+ means active by default, - means inactive by default):
return return
def main(): def main():
'''Main executable.'''
# If it's good to append the basename to it, it's good to append the # If it's good to append the basename to it, it's good to append the
# auxiliary files' names to it, which should be located where this file is. # auxiliary files' names to it, which should be located where this file is.
lslopt.lslcommon.DataPath = __file__[:-len(os.path.basename(__file__))] lslopt.lslcommon.DataPath = __file__[:-len(os.path.basename(__file__))]
@ -270,7 +274,7 @@ def main():
try: try:
opts, args = getopt.gnu_getopt(sys.argv[1:], 'hO:o:pP:H', opts, args = getopt.gnu_getopt(sys.argv[1:], 'hO:o:pP:H',
('optimizer-options=', 'help', 'version', 'output=', 'header', ('optimizer-options=', 'help', 'version', 'output=', 'header',
'preproc=', 'prereset', 'precmd=', 'prearg=', 'preproc=', 'precmd=', 'prearg=', 'prenodef',
'avid=', 'avname=', 'assetid=', 'scriptname=')) 'avid=', 'avname=', 'assetid=', 'scriptname='))
except getopt.GetoptError: except getopt.GetoptError:
Usage() Usage()
@ -281,20 +285,11 @@ def main():
avname = '' avname = ''
shortname = '' shortname = ''
assetid = '00000000-0000-0000-0000-000000000000' assetid = '00000000-0000-0000-0000-000000000000'
preproc_cmdline = [ preproc_cmdline = ['cpp']
'cpp', '-undef', '-x', 'c', '-std=c99', '-nostdinc', '-trigraphs', preproc = 'none'
'-dN', '-fno-extended-identifiers', predefines = True
'-Dinteger(...)=((integer)(__VA_ARGS__))', script_header = ''
'-Dfloat(...)=((float)(__VA_ARGS__))', mcpp_mode = False
'-Dstring(...)=((string)(__VA_ARGS__))',
'-Dkey(...)=((key)(__VA_ARGS__))',
'-Drotation(...)=((rotation)(__VA_ARGS__))',
'-Dquaternion(...)=((quaternion)(__VA_ARGS__))',
'-Dvector(...)=((vector)(__VA_ARGS__))',
'-Dlist(...)=((list)(__VA_ARGS__))'
]
preproc = False
script_header = False
for opt, arg in opts: for opt, arg in opts:
if type(opt) is unicode: if type(opt) is unicode:
@ -329,22 +324,46 @@ def main():
elif opt in ('-p', '--preproc'): elif opt in ('-p', '--preproc'):
preproc = arg.lower() preproc = arg.lower()
if preproc not in ('external', 'extnodef', 'none'): if preproc not in ('ext', 'gcpp', 'mcpp', 'none'):
Usage() Usage()
return 1 return 1
elif opt == '--precmd': mcpp_mode = False
if preproc_cmdline: del preproc_cmdline[1:]
preproc_cmdline[0] = arg
else:
preproc_cmdline.append(arg)
elif opt == '--prereset': if preproc == 'gcpp':
preproc_cmdline = [] preproc_cmdline = [
'cpp', '-undef', '-x', 'c', '-std=c99', '-nostdinc',
'-trigraphs', '-dN', '-fno-extended-identifiers',
]
elif preproc == 'mcpp':
mcpp_mode = True
preproc_cmdline = [
'mcpp', '-e', 'UTF-8', '-I-', '-N', '-3', '-j',
]
if predefines:
preproc_cmdline += [
'-Dinteger(...)=((integer)(__VA_ARGS__))',
'-Dfloat(...)=((float)(__VA_ARGS__))',
'-Dstring(...)=((string)(__VA_ARGS__))',
'-Dkey(...)=((key)(__VA_ARGS__))',
'-Drotation(...)=((rotation)(__VA_ARGS__))',
'-Dquaternion(...)=((quaternion)(__VA_ARGS__))',
'-Dvector(...)=((vector)(__VA_ARGS__))',
'-Dlist(...)=((list)(__VA_ARGS__))',
]
elif opt == '--precmd':
preproc_cmdline[0] = arg
elif opt in ('-P', '--prearg'): elif opt in ('-P', '--prearg'):
preproc_cmdline.append(arg) preproc_cmdline.append(arg)
elif opt == '--prenodef':
predefines = False
elif opt in ('-H', '--header'): elif opt in ('-H', '--header'):
script_header = True script_header = True
@ -385,7 +404,7 @@ def main():
if shortname == '': if shortname == '':
shortname = os.path.basename(fname) shortname = os.path.basename(fname)
if preproc == 'external': if predefines:
preproc_cmdline.append('-D__AGENTKEY__="' + avid + '"') preproc_cmdline.append('-D__AGENTKEY__="' + avid + '"')
preproc_cmdline.append('-D__AGENTID__="' + avid + '"') preproc_cmdline.append('-D__AGENTID__="' + avid + '"')
preproc_cmdline.append('-D__AGENTIDRAW__=' + avid) preproc_cmdline.append('-D__AGENTIDRAW__=' + avid)
@ -395,7 +414,7 @@ def main():
preproc_cmdline.append('-D__OPTIMIZER__=LSL PyOptimizer') preproc_cmdline.append('-D__OPTIMIZER__=LSL PyOptimizer')
preproc_cmdline.append('-D__OPTIMIZER_VERSION__=' + VERSION) preproc_cmdline.append('-D__OPTIMIZER_VERSION__=' + VERSION)
if preproc in ('external', 'extnodef'): if preproc != 'none':
# At this point, for the external preprocessor to work we need the # At this point, for the external preprocessor to work we need the
# script as a byte array, not as unicode, but it should be valid UTF-8. # script as a byte array, not as unicode, but it should be valid UTF-8.
if type(script) is unicode: if type(script) is unicode:
@ -410,6 +429,11 @@ def main():
sys.stderr.write(e.message + '\n') sys.stderr.write(e.message + '\n')
return 1 return 1
script = PreparePreproc(script) script = PreparePreproc(script)
if mcpp_mode:
# As a special treatment for mcpp, we force it to output its macros
# so we can read if USE_xxx are defined. With GCC that is achieved
# with -dN but with mcpp there's no command line option.
script += '\n#pragma MCPP put_defines\n'
# Invoke the external preprocessor # Invoke the external preprocessor
import subprocess import subprocess
@ -417,14 +441,13 @@ def main():
stdout = '' stdout = ''
p = subprocess.Popen(preproc_cmdline, stdin=subprocess.PIPE, p = subprocess.Popen(preproc_cmdline, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE)
p.stdin.write(script) p.stdin.write(script)
p.stdin.close() p.stdin.close()
while True: while True:
time.sleep(0.1) time.sleep(0.1)
status = p.poll() status = p.poll()
stdout += p.stdout.read() stdout += p.stdout.read()
sys.stderr.write(p.stderr.read())
if status is not None: if status is not None:
break break
if status: if status:
@ -432,10 +455,14 @@ def main():
script = stdout script = stdout
del p, status, stdout del p, status, stdout
if ('\n'+script).find('\n#define USE_SWITCHES\n') != -1: for x in re.findall(r'(?:(?<=\n)|^)\s*#\s*define\s+('
options.add('enableswitch') r'USE_SWITCHES'
if ('\n'+script).find('\n#define USE_LAZY_LISTS\n') != -1: r'|USE_LAZY_LISTS'
options.add('lazylists') r')(?:$|[^A-Za-z0-9_])', script, re.S):
if x == 'USE_SWITCHES':
options.add('enableswitch')
elif x == 'USE_LAZY_LISTS':
options.add('lazylists')
p = parser() p = parser()
try: try:
@ -450,13 +477,10 @@ def main():
del opt del opt
outs = outscript() outs = outscript()
script = outs.output(ts, options) script = script_header + outs.output(ts, options)
del outs del outs
del ts del ts
del script_header
if script_header is not False:
script = script_header + script
del script_header
if outfile == '-': if outfile == '-':
sys.stdout.write(script) sys.stdout.write(script)