mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Add command line option -y/--python-exception, revert previous commit.
By default, catch exceptions and report them without a stack trace. When this option is specified, raise an actual Python exception (should show a strack trace). Note: diff for this patch is best seen with -b (ignore-whitespace-change).
This commit is contained in:
parent
26b49b0807
commit
e5ffe56fec
1 changed files with 152 additions and 139 deletions
291
main.py
291
main.py
|
@ -174,6 +174,7 @@ Usage: {progname}
|
||||||
[-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
|
||||||
[-T|--timestamp] add a timestamp as a comment at the beginning
|
[-T|--timestamp] add a timestamp as a comment at the beginning
|
||||||
|
[-y|--python-exceptions] when an exception is raised, show a stack trace
|
||||||
[-p|--preproc=mode] run external preprocessor (see below for modes)
|
[-p|--preproc=mode] run external preprocessor (see below for modes)
|
||||||
(resets the preprocessor command line so far)
|
(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
|
||||||
|
@ -337,9 +338,9 @@ def main(argv):
|
||||||
% (b"', '".join(options - validoptions)).decode('utf8'))
|
% (b"', '".join(options - validoptions)).decode('utf8'))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.gnu_getopt(argv[1:], 'hO:o:p:P:HT',
|
opts, args = getopt.gnu_getopt(argv[1:], 'hO:o:p:P:HTy',
|
||||||
('optimizer-options=', 'help', 'version', 'output=', 'header',
|
('optimizer-options=', 'help', 'version', 'output=', 'header',
|
||||||
'timestamp',
|
'timestamp','python-exceptions',
|
||||||
'preproc=', 'precmd=', 'prearg=', 'prenodef', 'preshow',
|
'preproc=', 'precmd=', 'prearg=', 'prenodef', 'preshow',
|
||||||
'avid=', 'avname=', 'assetid=', 'shortname='))
|
'avid=', 'avname=', 'assetid=', 'shortname='))
|
||||||
except getopt.GetoptError as e:
|
except getopt.GetoptError as e:
|
||||||
|
@ -359,6 +360,7 @@ def main(argv):
|
||||||
script_timestamp = ''
|
script_timestamp = ''
|
||||||
mcpp_mode = False
|
mcpp_mode = False
|
||||||
preshow = False
|
preshow = False
|
||||||
|
raise_exception = False
|
||||||
|
|
||||||
for opt, arg in opts:
|
for opt, arg in opts:
|
||||||
if type(opt) is unicode:
|
if type(opt) is unicode:
|
||||||
|
@ -402,6 +404,9 @@ def main(argv):
|
||||||
elif opt in ('-o', '--output'):
|
elif opt in ('-o', '--output'):
|
||||||
outfile = arg
|
outfile = arg
|
||||||
|
|
||||||
|
elif opt in ('-y', '--python-exceptions'):
|
||||||
|
raise_exception = True
|
||||||
|
|
||||||
elif opt in ('-p', '--preproc'):
|
elif opt in ('-p', '--preproc'):
|
||||||
preproc = arg.lower()
|
preproc = arg.lower()
|
||||||
supported = ('ext', 'mcpp', 'gcpp', 'none')
|
supported = ('ext', 'mcpp', 'gcpp', 'none')
|
||||||
|
@ -470,148 +475,156 @@ def main(argv):
|
||||||
shortname = arg
|
shortname = arg
|
||||||
del opts
|
del opts
|
||||||
|
|
||||||
if 'lso' in options:
|
try:
|
||||||
lslopt.lslcommon.LSO = True
|
|
||||||
options.remove('lso')
|
|
||||||
|
|
||||||
if 'expr' in options:
|
if 'lso' in options:
|
||||||
lslopt.lslcommon.IsCalc = True
|
lslopt.lslcommon.LSO = True
|
||||||
options.remove('expr')
|
options.remove('lso')
|
||||||
|
|
||||||
if 'help' in options:
|
if 'expr' in options:
|
||||||
Usage(argv[0], 'optimizer-options')
|
lslopt.lslcommon.IsCalc = True
|
||||||
|
options.remove('expr')
|
||||||
|
|
||||||
|
if 'help' in options:
|
||||||
|
Usage(argv[0], 'optimizer-options')
|
||||||
|
return 0
|
||||||
|
|
||||||
|
fname = args[0] if args else None
|
||||||
|
if fname is None:
|
||||||
|
Usage(argv[0])
|
||||||
|
sys.stderr.write(u"\nError: Input file not specified. Use -"
|
||||||
|
u" if you want to use stdin.\n")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
del args
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
if fname == '-':
|
||||||
|
script = sys.stdin.read()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
f = open(fname, 'r')
|
||||||
|
except IOError as e:
|
||||||
|
if e.errno == 2:
|
||||||
|
sys.stderr.write('Error: File not found: %s\n' % fname)
|
||||||
|
return 2
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
script = f.read()
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
del f
|
||||||
|
|
||||||
|
if script_header:
|
||||||
|
script_header = ScriptHeader(script, avname)
|
||||||
|
|
||||||
|
if script_timestamp:
|
||||||
|
import time
|
||||||
|
tmp = time.time()
|
||||||
|
script_timestamp = time.strftime(
|
||||||
|
'// Generated on %Y-%m-%dT%H:%M:%S.{0:06d}Z\n'
|
||||||
|
.format(int(tmp % 1 * 1000000)), time.gmtime(tmp))
|
||||||
|
del tmp
|
||||||
|
|
||||||
|
if shortname == '':
|
||||||
|
shortname = os.path.basename(fname)
|
||||||
|
|
||||||
|
if predefines:
|
||||||
|
preproc_cmdline.append('-D__AGENTKEY__="' + avid + '"')
|
||||||
|
preproc_cmdline.append('-D__AGENTID__="' + avid + '"')
|
||||||
|
preproc_cmdline.append('-D__AGENTIDRAW__=' + avid)
|
||||||
|
preproc_cmdline.append('-D__AGENTNAME__="' + avname + '"')
|
||||||
|
preproc_cmdline.append('-D__ASSETID__=' + assetid)
|
||||||
|
preproc_cmdline.append('-D__SHORTFILE__="' + shortname + '"')
|
||||||
|
preproc_cmdline.append('-D__OPTIMIZER__=LSL PyOptimizer')
|
||||||
|
preproc_cmdline.append('-D__OPTIMIZER_VERSION__=' + VERSION)
|
||||||
|
|
||||||
|
if type(script) is unicode:
|
||||||
|
script = script.encode('utf8')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
# Try converting the script to Unicode, to report any encoding
|
||||||
|
# errors with accurate line information. At this point we don't
|
||||||
|
# need the result.
|
||||||
|
UniConvScript(script).to_unicode()
|
||||||
|
except EParse as e:
|
||||||
|
# We don't call ReportError to prevent problems due to
|
||||||
|
# displaying invalid UTF-8
|
||||||
|
sys.stderr.write(e.args[0] + u"\n")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if preproc != 'none':
|
||||||
|
# At this point, for the external preprocessor to work we need the
|
||||||
|
# script as a byte array, not as unicode, but it should be UTF-8.
|
||||||
|
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 mcpp has no command line option.
|
||||||
|
script += '\n#pragma MCPP put_defines\n'
|
||||||
|
|
||||||
|
# Invoke the external preprocessor
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
p = subprocess.Popen(preproc_cmdline, stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE)
|
||||||
|
script = p.communicate(input=script)[0]
|
||||||
|
status = p.wait()
|
||||||
|
if status:
|
||||||
|
return status
|
||||||
|
del p, status
|
||||||
|
|
||||||
|
# This method is very imperfect, in several senses. However, since
|
||||||
|
# it's applied to the output of the preprocessor, all of the
|
||||||
|
# concerns should be addressed:
|
||||||
|
# - \s includes \n, but \n should not be allowed.
|
||||||
|
# - Comments preceding the directive should not cause problems.
|
||||||
|
# e.g.: /* test */ #directive
|
||||||
|
# - #directive within a comment or string should be ignored.
|
||||||
|
for x in re.findall(r'(?:(?<=\n)|^)\s*#\s*define\s+('
|
||||||
|
r'USE_SWITCHES'
|
||||||
|
r'|USE_LAZY_LISTS'
|
||||||
|
r')(?:$|[^A-Za-z0-9_])', script, re.S):
|
||||||
|
if x == 'USE_SWITCHES':
|
||||||
|
options.add('enableswitch')
|
||||||
|
elif x == 'USE_LAZY_LISTS':
|
||||||
|
options.add('lazylists')
|
||||||
|
|
||||||
|
if not preshow:
|
||||||
|
|
||||||
|
p = parser()
|
||||||
|
try:
|
||||||
|
ts = p.parse(script, options)
|
||||||
|
except EParse as e:
|
||||||
|
ReportError(script, e)
|
||||||
|
return 1
|
||||||
|
del p, script
|
||||||
|
|
||||||
|
opt = optimizer()
|
||||||
|
ts = opt.optimize(ts, options)
|
||||||
|
del opt
|
||||||
|
|
||||||
|
outs = outscript()
|
||||||
|
script = script_header + script_timestamp + outs.output(ts, options)
|
||||||
|
del outs, ts
|
||||||
|
|
||||||
|
del script_header, script_timestamp
|
||||||
|
|
||||||
|
if outfile == '-':
|
||||||
|
sys.stdout.write(script)
|
||||||
|
else:
|
||||||
|
outf = open(outfile, 'w')
|
||||||
|
try:
|
||||||
|
outf.write(script)
|
||||||
|
finally:
|
||||||
|
outf.close()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
fname = args[0] if args else None
|
except Exception as e:
|
||||||
if fname is None:
|
if raise_exception:
|
||||||
Usage(argv[0])
|
|
||||||
sys.stderr.write(u"\nError: Input file not specified. Use -"
|
|
||||||
u" if you want to use stdin.\n")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
del args
|
|
||||||
|
|
||||||
script = ''
|
|
||||||
if fname == '-':
|
|
||||||
script = sys.stdin.read()
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
f = open(fname, 'r')
|
|
||||||
except IOError as e:
|
|
||||||
if e.errno == 2:
|
|
||||||
sys.stderr.write('Error: File not found: %s\n' % fname)
|
|
||||||
return 2
|
|
||||||
raise
|
raise
|
||||||
try:
|
sys.stderr.write(e.__class__.__name__ + ': ' + str(e) + '\n')
|
||||||
script = f.read()
|
return 1
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
del f
|
|
||||||
|
|
||||||
if script_header:
|
|
||||||
script_header = ScriptHeader(script, avname)
|
|
||||||
|
|
||||||
if script_timestamp:
|
|
||||||
import time
|
|
||||||
tmp = time.time()
|
|
||||||
script_timestamp = time.strftime(
|
|
||||||
'// Generated on %Y-%m-%dT%H:%M:%S.{0:06d}Z\n'
|
|
||||||
.format(int(tmp % 1 * 1000000)), time.gmtime(tmp))
|
|
||||||
del tmp
|
|
||||||
|
|
||||||
if shortname == '':
|
|
||||||
shortname = os.path.basename(fname)
|
|
||||||
|
|
||||||
if predefines:
|
|
||||||
preproc_cmdline.append('-D__AGENTKEY__="' + avid + '"')
|
|
||||||
preproc_cmdline.append('-D__AGENTID__="' + avid + '"')
|
|
||||||
preproc_cmdline.append('-D__AGENTIDRAW__=' + avid)
|
|
||||||
preproc_cmdline.append('-D__AGENTNAME__="' + avname + '"')
|
|
||||||
preproc_cmdline.append('-D__ASSETID__=' + assetid)
|
|
||||||
preproc_cmdline.append('-D__SHORTFILE__="' + shortname + '"')
|
|
||||||
preproc_cmdline.append('-D__OPTIMIZER__=LSL PyOptimizer')
|
|
||||||
preproc_cmdline.append('-D__OPTIMIZER_VERSION__=' + VERSION)
|
|
||||||
|
|
||||||
if type(script) is unicode:
|
|
||||||
script = script.encode('utf8')
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
# Try converting the script to Unicode, to report any encoding
|
|
||||||
# errors with accurate line information. At this point we don't
|
|
||||||
# need the result.
|
|
||||||
UniConvScript(script).to_unicode()
|
|
||||||
except EParse as e:
|
|
||||||
# We don't call ReportError to prevent problems due to
|
|
||||||
# displaying invalid UTF-8
|
|
||||||
sys.stderr.write(e.args[0] + u"\n")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if preproc != 'none':
|
|
||||||
# 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 = 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
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
p = subprocess.Popen(preproc_cmdline, stdin=subprocess.PIPE,
|
|
||||||
stdout=subprocess.PIPE)
|
|
||||||
script = p.communicate(input=script)[0]
|
|
||||||
status = p.wait()
|
|
||||||
if status:
|
|
||||||
return status
|
|
||||||
del p, status
|
|
||||||
|
|
||||||
# This method is very imperfect, in several senses. However, since
|
|
||||||
# it's applied to the output of the preprocessor, all of the concerns
|
|
||||||
# should be addressed:
|
|
||||||
# - \s includes \n, but \n should not be allowed.
|
|
||||||
# - Comments preceding the directive should not cause problems.
|
|
||||||
# e.g.: /* test */ #directive
|
|
||||||
# - #directive within a comment or string should be ignored.
|
|
||||||
for x in re.findall(r'(?:(?<=\n)|^)\s*#\s*define\s+('
|
|
||||||
r'USE_SWITCHES'
|
|
||||||
r'|USE_LAZY_LISTS'
|
|
||||||
r')(?:$|[^A-Za-z0-9_])', script, re.S):
|
|
||||||
if x == 'USE_SWITCHES':
|
|
||||||
options.add('enableswitch')
|
|
||||||
elif x == 'USE_LAZY_LISTS':
|
|
||||||
options.add('lazylists')
|
|
||||||
|
|
||||||
if not preshow:
|
|
||||||
|
|
||||||
p = parser()
|
|
||||||
try:
|
|
||||||
ts = p.parse(script, options)
|
|
||||||
except EParse as e:
|
|
||||||
ReportError(script, e)
|
|
||||||
return 1
|
|
||||||
del p, script
|
|
||||||
|
|
||||||
opt = optimizer()
|
|
||||||
ts = opt.optimize(ts, options)
|
|
||||||
del opt
|
|
||||||
|
|
||||||
outs = outscript()
|
|
||||||
script = script_header + script_timestamp + outs.output(ts, options)
|
|
||||||
del outs, ts
|
|
||||||
|
|
||||||
del script_header, script_timestamp
|
|
||||||
|
|
||||||
if outfile == '-':
|
|
||||||
sys.stdout.write(script)
|
|
||||||
else:
|
|
||||||
outf = open(outfile, 'w')
|
|
||||||
try:
|
|
||||||
outf.write(script)
|
|
||||||
finally:
|
|
||||||
outf.close()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ret = main(sys.argv)
|
ret = main(sys.argv)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue