Make Unicode some strings that should be, and improve error reporting in builtins.txt

Also work towards the convention that strings that represent text (possibly translatable) are in double quotes, not single.
This commit is contained in:
Sei Lisa 2016-12-20 19:22:48 +01:00
parent a124deb6b3
commit 39261cbfc8
5 changed files with 56 additions and 35 deletions

View file

@ -81,15 +81,15 @@ Indet = Infinity * 0
class ELSLTypeMismatch(Exception): class ELSLTypeMismatch(Exception):
def __init__(self): def __init__(self):
super(ELSLTypeMismatch, self).__init__("Type mismatch") super(ELSLTypeMismatch, self).__init__(u"Type mismatch")
class ELSLMathError(Exception): class ELSLMathError(Exception):
def __init__(self): def __init__(self):
super(ELSLMathError, self).__init__("Math Error") super(ELSLMathError, self).__init__(u"Math Error")
class ELSLInvalidType(Exception): class ELSLInvalidType(Exception):
def __init__(self): def __init__(self):
super(ELSLInvalidType, self).__init__("Internal error: Invalid type") super(ELSLInvalidType, self).__init__(u"Internal error: Invalid type")
class ELSLCantCompute(Exception): class ELSLCantCompute(Exception):
pass pass
@ -476,7 +476,7 @@ def InternalUTF8toString(s):
# python-coverage. It IS executed but not detected. # python-coverage. It IS executed but not detected.
continue continue
if LSO: if LSO:
raise ELSONotSupported("Byte strings not supported") raise ELSONotSupported(u"Byte strings not supported")
ret += u'?' * len(partialchar) ret += u'?' * len(partialchar)
partialchar = b'' partialchar = b''
# fall through to process current character # fall through to process current character
@ -485,14 +485,14 @@ def InternalUTF8toString(s):
pending = 1 if o < 0xE0 else 2 if o < 0xF0 else 3 pending = 1 if o < 0xE0 else 2 if o < 0xF0 else 3
elif o >= 0x80: elif o >= 0x80:
if LSO: if LSO:
raise ELSONotSupported("Byte strings not supported") raise ELSONotSupported(u"Byte strings not supported")
ret += u'?' ret += u'?'
else: else:
ret += c.decode('utf8') ret += c.decode('utf8')
if partialchar: if partialchar:
if LSO: if LSO:
raise ELSONotSupported("Byte strings not supported") raise ELSONotSupported(u"Byte strings not supported")
ret += u'?' * len(partialchar) ret += u'?' * len(partialchar)
return zstr(ret) return zstr(ret)

View file

@ -951,7 +951,7 @@ class foldconst(object):
) )
if generatesTabs: if generatesTabs:
if self.warntabs: if self.warntabs:
warning("Can't optimize call to %s because it would generate a tab character (you can force the optimization with the 'foldtabs' option, or disable this warning by disabling the 'warntabs' option)." % node['name']) warning(u"Can't optimize call to %s because it would generate a tab character (you can force the optimization with the 'foldtabs' option, or disable this warning by disabling the 'warntabs' option)." % node['name'].decode('utf8'))
return return
parent[index] = {'nt':'CONST', 't':node['t'], 'value':value} parent[index] = {'nt':'CONST', 't':node['t'], 'value':value}
except lslfuncs.ELSLCantCompute: except lslfuncs.ELSLCantCompute:
@ -1266,6 +1266,6 @@ class foldconst(object):
self.FoldTree(tree, idx) self.FoldTree(tree, idx)
self.globalmode = False self.globalmode = False
if warningpass and not self.IsValidGlobalConstant(tree[idx]): if warningpass and not self.IsValidGlobalConstant(tree[idx]):
warning("Expression in globals doesn't resolve to a simple constant.") warning(u"Expression in globals doesn't resolve to a simple constant.")
else: else:
self.FoldTree(tree, idx) self.FoldTree(tree, idx)

View file

@ -47,7 +47,7 @@ class outscript(object):
# is lost. So we emit a warning instead, letting the compiler # is lost. So we emit a warning instead, letting the compiler
# report the error in the generated source. # report the error in the generated source.
if self.globalmode and self.listmode: if self.globalmode and self.listmode:
warning('Illegal combo: Key type inside a global list') warning(u"Illegal combo: Key type inside a global list")
if self.listmode or not self.globalmode: if self.listmode or not self.globalmode:
if self.globalmode: if self.globalmode:
pfx = '(key)' pfx = '(key)'
@ -55,10 +55,10 @@ class outscript(object):
pfx = '((key)' pfx = '((key)'
sfx = ')' sfx = ')'
if '\t' in value and self.warntabs: if '\t' in value and self.warntabs:
warning("A string contains a tab. Tabs are expanded to four" warning(u"A string contains a tab. Tabs are expanded to four"
" spaces by the viewer when copy-pasting the code" " spaces by the viewer when copy-pasting the code"
" (disable this warning by disabling the 'warntabs'" " (disable this warning by disabling the 'warntabs'"
" option).") " option).")
return pfx + '"' + value.encode('utf8').replace('\\','\\\\') \ return pfx + '"' + value.encode('utf8').replace('\\','\\\\') \
.replace('"','\\"').replace('\n','\\n') + '"' + sfx .replace('"','\\"').replace('\n','\\n') + '"' + sfx
if tvalue == int: if tvalue == int:

View file

@ -29,8 +29,8 @@ import sys, re
# reading it. # reading it.
def warning(txt): def warning(txt):
assert type(txt) == str assert type(txt) == unicode
sys.stderr.write('WARNING: ' + txt + '\n') sys.stderr.write(u"WARNING: " + txt + u"\n")
def isdigit(c): def isdigit(c):
return '0' <= c <= '9' return '0' <= c <= '9'
@ -2688,13 +2688,24 @@ list lazy_list_set(list L, integer i, list v)
f = open(lslcommon.DataPath + builtins, 'rb') f = open(lslcommon.DataPath + builtins, 'rb')
try: try:
linenum = 0
try:
ubuiltins = builtins.decode('utf8')
except UnicodeDecodeError:
ubuiltins = builtins.decode('iso-8859-15')
while True: while True:
linenum += 1
line = f.readline() line = f.readline()
if not line: break if not line: break
if line[-1] == '\n': line = line[:-1] if line[-1] == '\n': line = line[:-1]
try:
uline = line.decode('utf8')
except UnicodeDecodeError:
warning(u"Bad Unicode in %s line %d" % (ubuiltins, linenum))
continue
match = parse_lin_re.search(line) match = parse_lin_re.search(line)
if not match: if not match:
warning('Syntax error in ' + builtins + ', line ' + line) warning(u"Syntax error in %s, line %d" % (ubuiltins, linenum))
continue continue
if match.group(1): if match.group(1):
# event or function # event or function
@ -2704,7 +2715,7 @@ list lazy_list_set(list L, integer i, list v)
if typ == 'void': if typ == 'void':
typ = None typ = None
elif typ != 'event' and typ not in self.types: elif typ != 'event' and typ not in self.types:
warning('Invalid type in ' + builtins + ', line ' + line + ': ' + typ) warning(u"Invalid type in %s, line %d: %s" % (ubuiltins, linenum, typ))
continue continue
args = [] args = []
arglist = match.group(3) arglist = match.group(3)
@ -2714,23 +2725,29 @@ list lazy_list_set(list L, integer i, list v)
for arg in arglist: for arg in arglist:
argtyp = parse_arg_re.search(arg).group(1) argtyp = parse_arg_re.search(arg).group(1)
if argtyp not in self.types: if argtyp not in self.types:
warning('Invalid type in ' + builtins + ', line ' + line + ': ' + argtyp) uargtyp = argtyp.decode('utf8')
warning(u"Invalid type in %s, line %d: %s" % (ubuiltins, linenum, uargtyp))
del uargtyp
bad = True bad = True
break break
args.append(parse_arg_re.search(arg).group(1)) args.append(argtyp)
if bad: if bad:
continue continue
name = match.group(2) name = match.group(2)
if typ == 'event': if typ == 'event':
if name in self.events: if name in self.events:
warning('Event already defined in ' + builtins + ', overwriting: ' + name) uname = name.decode('utf8')
warning(u"Event at line %d was already defined in %s, overwriting: %s" % (linenum, ubuiltins, uname))
del uname
self.events[name] = tuple(args) self.events[name] = tuple(args)
else: else:
# Library functions go to the functions table. If # Library functions go to the functions table. If
# they are implemented in lslfuncs.*, they get a # they are implemented in lslfuncs.*, they get a
# reference to the implementation; otherwise None. # reference to the implementation; otherwise None.
if name in self.funclibrary: if name in self.funclibrary:
warning('Function already defined in ' + builtins + ', overwriting: ' + name) uname = name.decode('utf8')
warning(u"Function at line %d was already defined in %s, overwriting: %s" % (linenum, ubuiltins, uname))
del uname
fn = getattr(lslfuncs, name, None) fn = getattr(lslfuncs, name, None)
self.funclibrary[name] = {'Kind':'f', 'Type':typ, 'ParamTypes':args} self.funclibrary[name] = {'Kind':'f', 'Type':typ, 'ParamTypes':args}
if fn is not None: if fn is not None:
@ -2739,10 +2756,14 @@ list lazy_list_set(list L, integer i, list v)
# constant # constant
name = match.group(5) name = match.group(5)
if name in self.constants: if name in self.constants:
warning('Global already defined in ' + builtins + ', overwriting: ' + name) uname = name.decode('utf8')
warning(u"Global at line %d was already defined in %s, overwriting: %s" % (linenum, ubuiltins, uname))
del uname
typ = match.group(4) typ = match.group(4)
if typ not in self.types: if typ not in self.types:
warning('Invalid type in ' + builtins + ', line ' + line + ': ' + typ) utyp = typ.decode('utf8')
warning(u"Invalid type in %s, line %d: %s" % (ubuiltins, linenum, utyp))
del utyp
continue continue
if typ == 'quaternion': if typ == 'quaternion':
typ = 'rotation' typ = 'rotation'
@ -2772,10 +2793,10 @@ list lazy_list_set(list L, integer i, list v)
#if typ == 'key': #if typ == 'key':
# value = Key(value) # value = Key(value)
else: else:
warning('Invalid string in ' + builtins + ': ' + line) warning(u"Invalid string in %s line %d: %s" % (ubuiltins, linenum, uline))
value = None value = None
elif typ == 'key': elif typ == 'key':
warning('Key constants not supported in ' + builtins + ': ' + line) warning(u"Key constants not supported in %s, line %d: %s" % (ubuiltins, linenum, uline))
value = None value = None
elif typ in ('vector', 'rotation'): elif typ in ('vector', 'rotation'):
try: try:
@ -2805,10 +2826,10 @@ list lazy_list_set(list L, integer i, list v)
value[3] = lslfuncs.F32(float(num.group(1))) value[3] = lslfuncs.F32(float(num.group(1)))
value = Quaternion(value) value = Quaternion(value)
except ValueError: except ValueError:
warning('Invalid vector/rotation syntax in ' + builtins + ': ' + line) warning(u"Invalid vector/rotation syntax in %s line %d: %s" % (ubuiltins, linenum, uline))
else: else:
assert typ == 'list' assert typ == 'list'
warning('List constants not supported in ' + builtins + ': ' + line) warning(u"List constants not supported in %s, line %d: %s" % (ubuiltins, linenum, uline))
value = None value = None
if value is not None: if value is not None:
self.constants[name] = value self.constants[name] = value

16
main.py
View file

@ -38,9 +38,9 @@ def ReportError(script, e):
sys.stderr.write(e[0] + '\n') sys.stderr.write(e[0] + '\n')
class UniConvScript(object): class UniConvScript(object):
'''Converts the script to Unicode, setting the properties required by """Converts the script to Unicode, setting the properties required by
EParse to report a meaningful error position. EParse to report a meaningful error position.
''' """
def __init__(self, script): def __init__(self, script):
self.script = script self.script = script
@ -50,7 +50,7 @@ class UniConvScript(object):
self.script = self.script.decode('utf8') self.script = self.script.decode('utf8')
except UnicodeDecodeError as e: except UnicodeDecodeError as e:
self.errorpos = e.start self.errorpos = e.start
raise EParse(self, 'Invalid UTF-8 in script') raise EParse(self, u"Invalid UTF-8 in script")
return self.script return self.script
def PreparePreproc(script): def PreparePreproc(script):
@ -155,7 +155,7 @@ def ScriptHeader(script, avname):
def Usage(about = None): def Usage(about = None):
if about is None: if about is None:
sys.stderr.write( sys.stderr.write(
r'''LSL optimizer v{version} ur"""LSL optimizer v{version}
(C) Copyright 2015 Sei Lisa. All rights reserved. (C) Copyright 2015 Sei Lisa. All rights reserved.
@ -199,12 +199,12 @@ Preprocessor modes:
Normally, running the preprocessor needs the option 'processpre' active, to Normally, running the preprocessor needs the option 'processpre' active, to
make the output readable by the optimizer. This option is active by default. make the output readable by the optimizer. This option is active by default.
'''.format(progname=sys.argv[0], version=VERSION)) """.format(progname=sys.argv[0], version=VERSION))
return return
if about == 'optimizer-options': if about == 'optimizer-options':
sys.stderr.write( sys.stderr.write(
r''' ur"""
Optimizer control options. Optimizer control options.
+ means active by default, - means inactive by default. + means active by default, - means inactive by default.
Case insensitive. Case insensitive.
@ -295,11 +295,11 @@ Case insensitive.
is useless with 'optimize' and 'optsigns', and is of is useless with 'optimize' and 'optsigns', and is of
basically no use in general, other than to see where basically no use in general, other than to see where
automatic casts happen. automatic casts happen.
''') """)
return return
def main(): def main():
'''Main executable.''' """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.