diff --git a/lslopt/lslbasefuncs.py b/lslopt/lslbasefuncs.py index f0c5d38..1ebacca 100644 --- a/lslopt/lslbasefuncs.py +++ b/lslopt/lslbasefuncs.py @@ -81,15 +81,15 @@ Indet = Infinity * 0 class ELSLTypeMismatch(Exception): def __init__(self): - super(ELSLTypeMismatch, self).__init__("Type mismatch") + super(ELSLTypeMismatch, self).__init__(u"Type mismatch") class ELSLMathError(Exception): def __init__(self): - super(ELSLMathError, self).__init__("Math Error") + super(ELSLMathError, self).__init__(u"Math Error") class ELSLInvalidType(Exception): def __init__(self): - super(ELSLInvalidType, self).__init__("Internal error: Invalid type") + super(ELSLInvalidType, self).__init__(u"Internal error: Invalid type") class ELSLCantCompute(Exception): pass @@ -476,7 +476,7 @@ def InternalUTF8toString(s): # python-coverage. It IS executed but not detected. continue if LSO: - raise ELSONotSupported("Byte strings not supported") + raise ELSONotSupported(u"Byte strings not supported") ret += u'?' * len(partialchar) partialchar = b'' # 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 elif o >= 0x80: if LSO: - raise ELSONotSupported("Byte strings not supported") + raise ELSONotSupported(u"Byte strings not supported") ret += u'?' else: ret += c.decode('utf8') if partialchar: if LSO: - raise ELSONotSupported("Byte strings not supported") + raise ELSONotSupported(u"Byte strings not supported") ret += u'?' * len(partialchar) return zstr(ret) diff --git a/lslopt/lslfoldconst.py b/lslopt/lslfoldconst.py index 072076f..d9c80aa 100644 --- a/lslopt/lslfoldconst.py +++ b/lslopt/lslfoldconst.py @@ -951,7 +951,7 @@ class foldconst(object): ) if generatesTabs: 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 parent[index] = {'nt':'CONST', 't':node['t'], 'value':value} except lslfuncs.ELSLCantCompute: @@ -1266,6 +1266,6 @@ class foldconst(object): self.FoldTree(tree, idx) self.globalmode = False 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: self.FoldTree(tree, idx) diff --git a/lslopt/lsloutput.py b/lslopt/lsloutput.py index 91426dd..d770254 100644 --- a/lslopt/lsloutput.py +++ b/lslopt/lsloutput.py @@ -47,7 +47,7 @@ class outscript(object): # is lost. So we emit a warning instead, letting the compiler # report the error in the generated source. 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.globalmode: pfx = '(key)' @@ -55,10 +55,10 @@ class outscript(object): pfx = '((key)' sfx = ')' if '\t' in value and self.warntabs: - warning("A string contains a tab. Tabs are expanded to four" - " spaces by the viewer when copy-pasting the code" - " (disable this warning by disabling the 'warntabs'" - " option).") + warning(u"A string contains a tab. Tabs are expanded to four" + " spaces by the viewer when copy-pasting the code" + " (disable this warning by disabling the 'warntabs'" + " option).") return pfx + '"' + value.encode('utf8').replace('\\','\\\\') \ .replace('"','\\"').replace('\n','\\n') + '"' + sfx if tvalue == int: diff --git a/lslopt/lslparse.py b/lslopt/lslparse.py index 985b047..c76cd50 100644 --- a/lslopt/lslparse.py +++ b/lslopt/lslparse.py @@ -29,8 +29,8 @@ import sys, re # reading it. def warning(txt): - assert type(txt) == str - sys.stderr.write('WARNING: ' + txt + '\n') + assert type(txt) == unicode + sys.stderr.write(u"WARNING: " + txt + u"\n") def isdigit(c): return '0' <= c <= '9' @@ -2688,13 +2688,24 @@ list lazy_list_set(list L, integer i, list v) f = open(lslcommon.DataPath + builtins, 'rb') try: + linenum = 0 + try: + ubuiltins = builtins.decode('utf8') + except UnicodeDecodeError: + ubuiltins = builtins.decode('iso-8859-15') while True: + linenum += 1 line = f.readline() if not line: break 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) if not match: - warning('Syntax error in ' + builtins + ', line ' + line) + warning(u"Syntax error in %s, line %d" % (ubuiltins, linenum)) continue if match.group(1): # event or function @@ -2704,7 +2715,7 @@ list lazy_list_set(list L, integer i, list v) if typ == 'void': typ = None 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 args = [] arglist = match.group(3) @@ -2714,23 +2725,29 @@ list lazy_list_set(list L, integer i, list v) for arg in arglist: argtyp = parse_arg_re.search(arg).group(1) 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 break - args.append(parse_arg_re.search(arg).group(1)) + args.append(argtyp) if bad: continue name = match.group(2) if typ == 'event': 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) else: # Library functions go to the functions table. If # they are implemented in lslfuncs.*, they get a # reference to the implementation; otherwise None. 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) self.funclibrary[name] = {'Kind':'f', 'Type':typ, 'ParamTypes':args} if fn is not None: @@ -2739,10 +2756,14 @@ list lazy_list_set(list L, integer i, list v) # constant name = match.group(5) 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) 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 if typ == 'quaternion': typ = 'rotation' @@ -2772,10 +2793,10 @@ list lazy_list_set(list L, integer i, list v) #if typ == 'key': # value = Key(value) else: - warning('Invalid string in ' + builtins + ': ' + line) + warning(u"Invalid string in %s line %d: %s" % (ubuiltins, linenum, uline)) value = None 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 elif typ in ('vector', 'rotation'): try: @@ -2805,10 +2826,10 @@ list lazy_list_set(list L, integer i, list v) value[3] = lslfuncs.F32(float(num.group(1))) value = Quaternion(value) 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: 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 if value is not None: self.constants[name] = value diff --git a/main.py b/main.py index 6a4e2ec..b16a4d9 100755 --- a/main.py +++ b/main.py @@ -38,9 +38,9 @@ def ReportError(script, e): sys.stderr.write(e[0] + '\n') 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. - ''' + """ def __init__(self, script): self.script = script @@ -50,7 +50,7 @@ class UniConvScript(object): self.script = self.script.decode('utf8') except UnicodeDecodeError as e: self.errorpos = e.start - raise EParse(self, 'Invalid UTF-8 in script') + raise EParse(self, u"Invalid UTF-8 in script") return self.script def PreparePreproc(script): @@ -155,7 +155,7 @@ def ScriptHeader(script, avname): def Usage(about = None): if about is None: sys.stderr.write( -r'''LSL optimizer v{version} +ur"""LSL optimizer v{version} (C) Copyright 2015 Sei Lisa. All rights reserved. @@ -199,12 +199,12 @@ Preprocessor modes: Normally, running the preprocessor needs the option 'processpre' active, to 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 if about == 'optimizer-options': sys.stderr.write( -r''' +ur""" Optimizer control options. + means active by default, - means inactive by default. Case insensitive. @@ -295,11 +295,11 @@ Case insensitive. is useless with 'optimize' and 'optsigns', and is of basically no use in general, other than to see where automatic casts happen. -''') +""") return def main(): - '''Main executable.''' + """Main executable.""" # 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.