text:
# Copyright (c) 2012, derrotehund361@googlemail.com
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""
his: Heuristic instruction scanner for RIM's JVM.
"""

import sys
from utils import Primitive, TypeToken, TypeList
from resolve import ClassDef, FieldDef, RoutineDef, LazyClassDef, LazyFieldDef, LazyRoutineDef
from analysis import Subroutine
import traceback, struct
from itertools import combinations

# the maximum number of slots that can be on the stack before a
# stack overflow exception is thrown
GLOBAL_MAX_STACK = 0x200

# the maximum number of rescans of a basic block
GLOBAL_MAX_RESCAN = 100

class AbortScanning(Exception): pass

class UnknownTotos(AbortScanning): pass

class ScanningStackUnderflow(AbortScanning): pass

class ScanningStackOverflow(AbortScanning): pass

class FieldPatchFailed(AbortScanning): pass

class VirtualPatchFailed(AbortScanning): pass

class TStack(list):
    def push(self, value, count=1):
        assert isinstance(value, TypeToken), "Bad value (%s [%s]) pushed onto type stack!" % (value, type(value))
        # if long or double primitive, this is a wide (takes up two slots) value
        if value.code in (6, 12) and not value._array:
            count *= 2
        self += ([value] * count)
        if len(self) > GLOBAL_MAX_STACK:
            raise ScanningStackOverflow("Stack overflow while scanning instructions")

    def pop(self, count=None):
        if (count != 0) and (len(self) == 0):
            raise ScanningStackUnderflow("Stack underflow while scanning instructions")

        if count is None:
            return list.pop(self)
        elif count > 0:
            ret = self[-count:]
            del self[-count:]
            return ret

    def top(self, count=1):
        if len(self) == 0:
            return None
        elif count == 1:
            return self[-1]
        else:
            return self[-count:]

    def pop_push(self, new_top):
        self.pop()
        self.push(new_top)

    def copy(self):
        return TStack(self[:])

    def __str__(self):
        return "{%s}" % ''.join(map(str, self))

class HILogger(object):
    ''' Capture stats and error information for a series of HIScans. '''
    def __init__(self, logfile=sys.stderr):
        self._logfile = logfile
        self._indent = ''
        self._header = None
        self._stats = {
            'subs': 0,
            'codes': 0,
            'fields': 0,
            'virtuals': 0,
        }
        self._bad_subs = []

    def count(self, kind):
        self._stats[kind] += 1

    def log(self, msg=''):
        if self._header:
            print >>self._logfile, "SUB: %s" % self._header
            self._header = None
        _fputs = self._logfile.write
        _fputs(self._indent)
        _fputs(msg)
        _fputs('\n')

    def enter_sub(self, sub):
        self.count("subs")
        self._header = '%s in %s' % (str(sub.routine), str(sub.routine.module))
        self._indent = '\t'

    def error_sub(self, sub, err):
        from StringIO import StringIO
        import traceback
        dump = StringIO()
        traceback.print_exc(file=dump)
        dump.seek(0)
        dump = dump.read()
        sub_name = str(sub.routine)
        mod_name = str(sub.routine.module)
        self.log("ERROR: %s (aborting scan of '%s' in %s)" % (err, sub_name, mod_name))
        # uncomment for a traceback
        self.log(dump)
        self._bad_subs.append(sub_name)
        self._indent = ''

    def exit_sub(self, sub):
        self._indent = ''

    def dump_stats(self):
        self.log()
        self.log('*** HIScan Stats Summary ***')
        self.log('-'*60)
        self.log("Subs scanned: %d" % self._stats['subs'])
        lbs = len(self._bad_subs)
        if self._stats['subs']:
            self.log("Subs failed: %d (%.2f%%)" % (lbs, float(lbs) / self._stats['subs'] * 100))
        self.log("Instructions scanned: %d" % self._stats['codes'])
        self.log("Fields patched up: %d" % self._stats['fields'])
        self.log("Virtual methods patched up: %d" % self._stats['virtuals'])
        self.log()

    def dump_bad_subs(self):
        if self._bad_subs:
            self.log()
            self.log("*** HIScan Failed Subs ***")
            self.log('-'*60)
            for bs in self._bad_subs:
                self.log(bs)
            self.log()

class HIScanner(object):

    # RIM-JVM-type-ordinal -> JTS character mapping
    # (For when we need to create arrays based on a type ordinal value)
    TYPE_ORDINAL = {
        1: "Z",
        2: "B",
        3: "C",
        4: "S",
        5: "I",
        6: "J",
        10: "V",
        11: "F",
        12: "D",
        14: "Ljava/lang/String;",
    }

    # Common TypeToken types we will use, named appropriately
    CORE_TTS = {
        '*': '*',       # We don't know ANYTHING about this type
        'null': '?',    # Special: could be any kind of OBJECT
        'boolean': 'Z',
        'byte': 'B',
        'char': 'C',
        'short': 'S',
        'int': 'I',
        'long': 'J',
        'float': 'F',
        'double': 'D',
        'string': 'Ljava/lang/String;',
        'string[]': '[Ljava/lang/String;',
    }

    def __init__(self, routine, hi_logger=None, debug_level=0):
        self.routine = routine
        self.sub = Subroutine(routine)
        if hi_logger:
            self._logfile = hi_logger._logfile
            self._logger = hi_logger
        else:
            self._logfile = sys.stderr
            self._logger = HILogger(self._logfile)
        self.debug_level = debug_level

        # Precompute some common types
        self._tt = dict((k, self.mktt(v)) for k, v in self.CORE_TTS.iteritems())

    def log(self, msg):
        if not msg.startswith('DEBUG: '):
            self._logger.log(msg)
        elif self.debug_level:
            self._logger.log(msg)

    def count(self, kind):
        self._logger.count(kind)

    def mktt(self, tname, dims=0, class_name=False, base_module_name=None):
        if isinstance(tname, TypeToken):
            # Clone type token
            tt = tname.clone()
        elif isinstance(tname, (ClassDef, LazyClassDef)):
            # Object TypeToken of a given class type
            tt = TypeToken(None)
            tt._object = True
            tt._array = False
            tt.code = 7
            tt.type = tname
        elif isinstance(tname, Primitive):
            if str(tname) not in self._tt:
                raise ValueError("Primitive type %s cannot be a valid type token for scanning" % tname)
            tt = self._tt[str(tname)].clone()
        elif isinstance(tname, basestring):
            if class_name:
                # tname is a raw class name (i.e., "java/lang/String" instead of "Ljava/lang/String;")
                tt = TypeToken(None)
                tt._object = True
                tt._array = False
                tt.code = 7
                if base_module_name:
                    # we know the modules this class lives in
                    tt.type = self.routine.module._L.ref_class(base_module_name, tname)
                else:
                    # we need to find this class from our module's context
                    tt.type = self.routine.module.ref_class(tname)
            elif tname == '?':
                # Special null-object-ref wildcard (not just any type, any OBJECT type)
                tt = TypeToken.from_jts('*')
                tt._object = True
            else:
                # Parse a fully-JTS-encoded type description
                tt = TypeToken.from_jts(tname, self.routine.module)
        elif isinstance(tname, (int, long)):
            # Ordinal [primitive] type code
            assert (tname in self.TYPE_ORDINAL), "Invalid RIM JVM type ordinal for mktt(): %d" % tname
            tt = TypeToken(None)
            tt._object = False
            tt._array = False
            tt.code = tname
            tt.type = Primitive(TypeToken.TYPE_NAME[tname])
        else:
            raise ValueError("Invalid argument to mktt(): %s (%s)" % (tname, type(tname)))

        # Apply dimensions (which may change the initial type shape)
        if dims:
            tt._array = True
            tt.dims = dims

        return tt

    def _merge_ttoken(self, tts, no_fail = False):
        ''' Merges a list of TypeTokens
        '''
        #self.log('Merging types:')
        #for tt in tts:
        #    self.log('  %s' % tt)
        if not no_fail:
            return max(tts)
        else:
            try:
                return max(tts)
            except:
                # we have incompatible types...
                # first, remove lesser types for more specific
                reduced_tts = set(tts)
                for t1, t2 in combinations(reduced_tts, 2):
                    try:
                        if cmp(t1, t2) == -1:
                            # t2 is more specific
                            reduced_tts.remove(t1)
                        else:
                            # t1 is more specific
                            reduced_tts.remove(t2)
                    except:
                        # we need to keep both incompatible
                        pass
                # otherwise take the most common or most defined
                max_count = 0
                max_tts = []
                for tt in reduced_tts:
                    count = tts.count(tt)
                    if count > max_count:
                        max_tts = [tt,]
                        max_count = count
                    elif count == max_count:
                        max_tts.append(tt)

                # grab the most common one deterministically
                # TODO: select this smartly
                max_tt = max_tts[0]
                return max_tt

    def _merge_tlists(self, tlists, no_fail = False):
        '''Merges a list of TStacks (stacks) or lists of TypeTokens (locals)
        '''
        tlists = [x for x in tlists if x]
        #self.log('Merging:')
        #for tlist in tlists:
        #    self.log('  %s' % tlist)
        if not tlists:
            return [] # err... may not return TStack... ugh.
        # assert that all lists are of equal size
        lengths = set(len(x) for x in tlists)
        tl = []
        if no_fail:
            max_length = max(lengths)
            for i in range(max_length):
                tl.append(self._merge_ttoken([x[i] for x in tlists if len(x) > i], no_fail))
        else:
            assert len(lengths) == 1
            for i in range(len(tlists[0])):
                tl.append(self._merge_ttoken([x[i] for x in tlists], no_fail))
        if isinstance(tlists[0], TStack):
            tl = TStack(tl)
        return tl

    def _get_next_bb(self, candidates, visited, failed, last_scanned = None):
        '''Given a list of candidate BBs and a set of visited BBs, pick the next one to scan.

        Algorithm:
            1. Scan candidates in presented order
                1a. rescan candidates if the last basic_block scanned has generated better type info
                1b. scan a candidate if all parents have been scanned
                1c. if one is not found, continue to phase 2
            2. Remove/return first candidate from the list
        '''
        self.log("DEBUG: selecting from candidates: %s" % [str(x) for x in candidates])
        self.log("DEBUG: failed list: %s" % [str(x) for x in failed])
        # if we just finished scanning a parent of this candidate and
        # if we have better type info available now
        for c in candidates:
            parents = [p for why, p in c.entry]
            if c in visited or c in failed:
                parents_tstack = self._get_starting_tstacks(c)
                parents_tlocals = self._get_starting_tlocals(c)
                # TODO: improve with stack map info
                parents_merged_tstack = self._merge_tlists(parents_tstack, no_fail = True)
                parents_merged_tlocals = self._merge_tlists(parents_tlocals, no_fail = True)

                if parents_merged_tstack != c.starting_tstack or \
                   parents_merged_tlocals != c.starting_tlocals:
                    self.log("DEBUG: selected to rescan: %s" % c)
                    if parents_merged_tstack != c.starting_tstack:
                        self.log("DEBUG: new stack type information")
                        for i, parent_tstack in enumerate(parents_tstack):
                            self.log('DEBUG:     Parent %2d stack: %s' % (i, parent_tstack))
                        self.log('DEBUG:     Merged stack:     %s' % parents_merged_tstack)
                        self.log('DEBUG:     Starting stack:   %s' % c.starting_tstack)
                    if parents_merged_tlocals != c.starting_tlocals:
                        self.log("DEBUG: new locals type information")
                        self.log('DEBUG:     Merged locals:   %s' % parents_merged_tlocals)
                        self.log('DEBUG:     Starting locals: %s' % c.starting_tlocals)
                    candidates.remove(c)
                    return c
                #else:
                #    candidates.remove(c)

        # if all parents have been scanned
        for c in candidates:
            parents = [p for why, p in c.entry]
            if c not in visited:
                if c not in failed:
                    if all((p in visited) for p in parents):
                        self.log("DEBUG: selected to scan bb with all parents scanned: %s" % c)
                        candidates.remove(c)
                        return c
            else:
                candidates.remove(c)

        while candidates:
            c = candidates.pop(0)
            if c not in visited and c not in failed:
                self.log("DEBUG: selected to scan next available block: %s" % c)
                return c
        return None

    def _get_starting_tstacks(self, bb):
        '''Gathers a list of potential starting stacks based on parent exit stacks.
        '''
        pstacks = []
        for why, p in bb.entry:
            # If we get here via an exception thrown, construct an appropriate stack
            if isinstance(why, basestring) and why and (why != 'default'):
                if why == 'finally' or why == 'java/lang/Throwable':
                    why = 'java/lang/Throwable'
                    base_module_name = 'net_rim_cldc'
                    pstacks.append(TStack([self.mktt(why, class_name=True, base_module_name=base_module_name)]))
                else:
                    # otherwise we need to resolve the type from our module's context
                    pstacks.append(TStack([self.mktt(why, class_name=True)]))
            elif p.tstack is not None:
                # If this instruction came from a checkcastbranch* that failed, pop the top
                if why is False and p.instructions[-1]._name.startswith('checkcastbranch'):
                    pstacks.append(TStack(p.tstack[:-1]))
                # Otherwise, just considered the ending typestack, if any
                else:
                    pstacks.append(TStack(p.tstack))
        return pstacks

    def _get_starting_tlocals(self, bb):
        '''Gathers a list of potential starting locals based on parent exit locals.
        '''
        plocals = []
        for why, p in bb.entry:
            # Always copy the locals over
            if p.tlocals is not None:
                plocals.append(p.tlocals)
        return plocals

    def _calculate_starting_tstack(self, bb):
        ''' Calculates the starting stack of a basic blocks based on parent exit stacks.
        '''
        pstacks = self._get_starting_tstacks(bb)

        # Check for initial-tstack mismatches among parent BBs
        try:
            tstack = TStack(self._merge_tlists(pstacks))
        except:
            tstack = TStack(self._merge_tlists(pstacks, no_fail = True))
        return tstack

    def _calculate_starting_tlocals(self, bb):
        ''' Calculates the starting locals of a basic blocks based on parent exit locals.

            Optionally provide a RoutineDef to use stack map information if available.
        '''
        plocals = self._get_starting_tlocals(bb)

        # Initialize locals, then try to eliminate wildcard types by finding more
        # explicit type info from other parent BBs' locals
        try:
            tlocals = self._merge_tlists(plocals)
        except:
            tlocals = self._merge_tlists(plocals, no_fail = True)
        return tlocals

    def scan(self, count=3, scanning_step_callback=None):
        ''' Compute type-on-top-of-stack values for the RIM-JVM instructions in an analysis.Subroutine.

            Blows away any previous .totos values for those instructions.
            Returns True if scan was successful, False otherwise.
        '''
        self._logger.enter_sub(self.sub)
        try:
            # Find the initial basic block; mark it as having an empty initial typestack
            # (Also, blow away the tstack snapshots in each BB)
            bb = None
            for b in self.sub.basic_blocks:
                #self.log('DEBUG: %s exits: %s' % (str(b), str([(why, str(next)) for why, next in b.exit.iteritems()])))
                # ending bb type information
                b.tstack = None
                b.tlocals = None
                # starting bb type information
                b.starting_tstack = None
                b.starting_tlocals = None
                # scan count
                b.scan_count = 0
                if b.is_initial():
                    bb = b
            if bb is None:
                raise AbortScanning("No initial BB found in %s" % self.routine)

            # Mark the basic blocks we've visited
            visited = set()
            # Mark the basic blocks that failed
            failed = set()

            # List BBs we want to visit
            last_scanned = None
            candidates = [bb]

            # Handle BBs until we're all out
            self._reals = False
            while candidates:
                # Get next BB to visit
                bb = self._get_next_bb(candidates, visited, failed, last_scanned)
                if not bb:
                    break

                # check to see if we are potentially in an infinite loop
                bb.scan_count += 1
                if bb.scan_count > GLOBAL_MAX_RESCAN:
                    raise AbortScanning("Maximum rescan count exceeded for basic block %s" % bb)

                if bb in failed:
                    failed.remove(bb)

                # If we have no parents, use and initial stack/localset
                if bb.is_initial():
                    # Allocate 256 local slots to be safe; pre-populate first slots with parameter types
                    tlocals = [self._tt['*'] for i in xrange(256)]
                    i = 0
                    for ptype in self.routine.param_types:
                        tlocals[i] = ptype
                        if ptype.slots() == 2:
                            tlocals[i+1] = ptype
                            i += 2
                        else:
                            i += 1
                    # Clean stack
                    tstack = TStack()
                else:
                    # Otherwise, compute our starting stack/local lists.
                    tstack = self._calculate_starting_tstack(bb)
                    tlocals = self._calculate_starting_tlocals(bb)

                    # track starting type info so if we encounter this block later,
                    # we can compare to see if we have better info
                    bb.starting_tstack = tstack.copy()
                    bb.starting_tlocals = tlocals[:]
                    #self.log("DEBUG: starting stack: %s" % bb.starting_tstack)
                    #self.log("DEBUG: starting locals: %s" % bb.starting_tlocals)

                self.log("DEBUG: walking BB %s w/ %s" % (bb, tstack))

                # visualize this step of the scan
                if scanning_step_callback:
                    scanning_step_callback(self.sub, bb, candidates, visited, failed)
                try:
                    # Walk the instructions in the BB, tracking the scanned stack
                    for i, instr in enumerate(bb.instructions):
                        # "isreal" isn't a true instruction--just a prefix that sets a flag for the next one
                        if instr._name == 'isreal':
                            self._reals = True
                            continue

                        # What is on the stack (typewise) when we start executing this instruction?
                        instr.totos = tstack.top()

                        # Simulate the instruction's effect on the stack
                        try:
                            handler = getattr(self, '_%s' % instr._name)
                        except AttributeError:
                            # Implicit NO-OP
                            self.log("WARNING: unimplemented instruction type '%s'" % instr._name)
                            continue

                        self.count("codes")

                        # Exceptions are caught by the surrounding, method-wide try/except block
                        if self.debug_level > 1:
                            self.log("DEBUG: %05d: %s" % (instr.offset, instr))
                            self.log("DEBUG:     Pre locals (only 4): %s" % tlocals[:4])
                            self.log("DEBUG:     Pre stack: %s" % tstack)
                        handler(instr, tstack, tlocals)
                        if self.debug_level > 1:
                            self.log("DEBUG:     Post stack: %s" % tstack)

                        # Clear the "isreal" flag
                        self._reals = False

                    # TODO: assert the ending stack is the same size as when we previously scanned
                    # this will catch infinite loops that cause the stack to grow uncontrollably
                    # maybe just do this if we aren't confused by an exception handler
                    #assert len(tstack) == len(bb.tstack), "Basic block stack size should not vary between scans"
                    # Set our BB's ending tstack/tlocals
                    bb.tstack = tstack
                    bb.tlocals = tlocals
                    last_scanned = bb

                    # OK, we're done with the basic block
                    visited.add(bb)

                    # scan this basic block's exit points for new candidates
                    # sort the next basic blocks by their offset
                    #self.log('DEBUG: %s exits: %s' % (str(bb), str([(why, str(next_bb)) for why, next_bb in bb.exit.iteritems()])))
                    next_bbs = [(next_bb.instructions[0].offset, next_bb) for why, next_bb in bb.exit.iteritems()]
                    next_bbs += [(next_bb.instructions[0].offset, next_bb) for next_bb in candidates]
                    next_bbs += [(next_bb.instructions[0].offset, next_bb) for next_bb in failed]
                    next_bbs.sort()
                    next_bbs = [next_bb for offset, next_bb in next_bbs]
                    candidates = list(set(next_bbs))
                except Exception, e:
                    # let's see what caused this error
                    import traceback
                    from StringIO import StringIO
                    dump = StringIO()
                    traceback.print_exc(file=dump)
                    dump.seek(0)
                    dump = dump.read()
                    dump = 'DEBUG: ' + dump
                    dump = dump.replace('\n', '\nDEBUG:')
                    self.log(dump)

                    # add this to the failed list and try a different block
                    failed.add(bb)
                    candidates.append(bb)

                    # ..unless there are no more to try
                    if not set(candidates) - set(failed):
                        raise e

            if failed:
                '''
                self.log('DEBUG: Remaining basic blocks:')
                remaining_bb = set(candidates + list(failed))
                for bb in remaining_bb:
                    parents = [p for why, p in bb.entry]
                    parents_tstack = [p.tstack for p in parents]
                    parents_tlocals = [p.tlocals for p in parents]
                    parents_merged_tstack = self._merge_tlists(parents_tstack, no_fail = True)
                    parents_merged_tlocals = self._merge_tlists(parents_tlocals, no_fail = True)
                    self.log('DEBUG: %s:' % str(bb))
                    self.log('DEBUG: Merged stack:    %s' % parents_merged_tstack)
                    self.log('DEBUG: Starting stack:  %s' % bb.starting_tstack)
                    self.log('DEBUG: Merged locals:   %s' % parents_merged_tlocals)
                    self.log('DEBUG: Starting locals: %s' % bb.starting_tlocals)
                '''

                raise Exception('Exhausted basic block candidates while trying to scan failed basic blocks: %s' % [str(x) for x in failed])
        except Exception as err:
            print >>self._logfile, err
            if count:
                count -= 1
                self.log('WARNING: Attempting rescan (%d tries left)' % count)
                return self.scan(count, scanning_step_callback)
            else:
                self._logger.error_sub(self.sub, err)
                return False
        # visualize the final step of scanning
        if scanning_step_callback:
            scanning_step_callback(self.sub, None, candidates, visited, failed)
        self._logger.exit_sub(self.sub)
        return True

    # Many instructions can be heuristically scanned using the
    # following set of simple type-stack operations
    ###########################################################
    def __nop(self, instr, tstack, tlocals):
        pass
    def __pop1(self, instr, tstack, tlocals):
        tstack.pop()
    def __pop2(self, instr, tstack, tlocals):
        tstack.pop(2)
    def __pop3(self, instr, tstack, tlocals):
        tstack.pop(3)
    def __push_int(self, instr, tstack, tlocals):
        if self._reals:
            tstack.push(self._tt['float'])
        else:
            tstack.push(self._tt['int'])
    def __push_long(self, instr, tstack, tlocals):
        if self._reals:
            tstack.push(self._tt['double'])
        else:
            tstack.push(self._tt['long'])
    def __push_float(self, instr, tstack, tlocals):
        tstack.push(self._tt['float'])
    def __push_double(self, instr, tstack, tlocals):
        tstack.push(self._tt['double'])

    # Common instructions (using one of the above methods)
    ###########################################################
    # TODO: errOp1 and errOp2

    _enter_narrow = _enter_wide = _xenter = _xenter_wide = _enter = __nop
    _iinc = _ineg = _goto = _goto_w = _i2b = _return = __nop
    _jmpback = _jmpforward = __nop
    _i2s = _lneg = _noenter_return = _dneg = __nop
    _fneg = _i2c = __nop
    _iinc_wide = _halt = _clinit_wait = _clinit_return = __nop
    _clinit = _clinit_lib = _synch = _synch_static = __nop
    _ireturn_bipush = _ireturn_sipush = _ireturn_iipush = __nop
    _invokenative = _iinvokenative = _linvokenative = __nop

    _ifeq = _ifne = _iflt = _ifge = _ifgt = _ifle = _ifnull = _ifnonnull = __pop1
    _iand = _ishl = _iushr = _isub = _ixor = __pop1
    _imul = _iadd = _ior = _lushr = _idiv = _pop = _ishr = _irem = __pop1
    _monitorenter = _monitorexit = __pop1
    _tableswitch = _lookupswitch = _lookupswitch_short = __pop1
    _lshl = _lshr = _lushr = __pop1
    _fadd = _fsub = _fmul = _fdiv = _frem = __pop1

    _if_acmpeq = _if_acmpne = _if_acmplt = _if_acmpge = _if_acmpgt = _if_acmple = __pop2
    _if_icmpeq = _if_icmpne = _if_icmplt = _if_icmpge = _if_icmpgt = _if_icmple = __pop2
    _pop2 = _ladd = _lsub = _lmul = _ldiv = __pop2
    _lor = _lrem = _lxor = _dadd = _dsub = _dmul = _ddiv = _drem = __pop2
    _land = __pop2

    _bastore = _iastore = _castore = _aastore = _sastore = __pop3

    _iconst_1 = _iconst_0 = __push_int
    _bipush = _sipush = _iipush = _iload = _iload_wide = __push_int
    _iload_0 = _iload_1 = _iload_2 = _iload_3 = _iload_4 = _iload_5 = _iload_6 = _iload_7 = __push_int

    _lload = _lload_wide = _lipush = __push_long

    _dconst_0 = _dconst_1 = __push_double
    _fconst_0 = _fconst_1 = _fconst_2 = __push_float

    # Instructions with specific type-stack implementations
    ###########################################################
    def _swap(self, instr, tstack, tlocals):
        assert (str(tstack[-1]) not in 'JD'), "invalid use of swap"
        assert (str(tstack[-2]) not in 'JD'), "invalid use of swap"
        t1 = tstack.pop()
        t2 = tstack.pop()
        tstack.push(t1)
        tstack.push(t2)

    def _aconst_null(self, instr, tstack, tlocals):
        tstack.push(self._tt['null'])

    # This is, perhaps, not such a good assumption...
    def _ldc(self, instr, tstack, tlocals):
        tstack.push(self._tt['string'])
    _ldc_nullstr = _ldc_unicode = _ldc

    # Push the type in that <tlocals> slot
    def _aload(self, instr, tstack, tlocals):
        tstack.push(tlocals[instr.operands[0]])
    _aload_wide = _aload

    def _aload_0(self, instr, tstack, tlocals):
        tstack.push(tlocals[0])
    def _aload_1(self, instr, tstack, tlocals):
        tstack.push(tlocals[1])
    def _aload_2(self, instr, tstack, tlocals):
        tstack.push(tlocals[2])
    def _aload_3(self, instr, tstack, tlocals):
        tstack.push(tlocals[3])
    def _aload_4(self, instr, tstack, tlocals):
        tstack.push(tlocals[4])
    def _aload_5(self, instr, tstack, tlocals):
        tstack.push(tlocals[5])
    def _aload_6(self, instr, tstack, tlocals):
        tstack.push(tlocals[6])
    def _aload_7(self, instr, tstack, tlocals):
        tstack.push(tlocals[7])

    def _istore(self, instr, tstack, tlocals):
        tstack.pop()
        if self._reals:
            tlocals[instr.operands[0]] = self._tt['float']
        else:
            tlocals[instr.operands[0]] = self._tt['int']
    _istore_wide = _istore

    def _astore(self, instr, tstack, tlocals):
        tlocals[instr.operands[0]] = tstack.pop()
    _astore_wide = _astore

    def _lstore(self, instr, tstack, tlocals):
        tstack.pop(2)
        local_index = instr.operands[0]
        if self._reals:
            tlocals[local_index] = tlocals[local_index+1] = self._tt['double']
        else:
            tlocals[local_index] = tlocals[local_index+1] = self._tt['long']
    _lstore_wide = _lstore

    def _istore_0(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[0] = tt
    def _istore_1(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[1] = tt
    def _istore_2(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[2] = tt
    def _istore_3(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[3] = tt
    def _istore_4(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[4] = tt
    def _istore_5(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[5] = tt
    def _istore_6(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[6] = tt
    def _istore_7(self, instr, tstack, tlocals):
        if self._reals:
            tt = self._tt['float']
        else:
            tt = self._tt['int']
        tstack.pop(); tlocals[7] = tt

    def _astore_0(self, instr, tstack, tlocals):
        tlocals[0] = tstack.pop()
    def _astore_1(self, instr, tstack, tlocals):
        tlocals[1] = tstack.pop()
    def _astore_2(self, instr, tstack, tlocals):
        tlocals[2] = tstack.pop()
    def _astore_3(self, instr, tstack, tlocals):
        tlocals[3] = tstack.pop()
    def _astore_4(self, instr, tstack, tlocals):
        tlocals[4] = tstack.pop()
    def _astore_5(self, instr, tstack, tlocals):
        tlocals[5] = tstack.pop()
    def _astore_6(self, instr, tstack, tlocals):
        tlocals[6] = tstack.pop()
    def _astore_7(self, instr, tstack, tlocals):
        tlocals[7] = tstack.pop()

    def _getfield(self, instr, tstack, tlocals):
        field = instr.operands[0]
        if hasattr(field, 'type'):
            tstack.pop_push(field.type[0])
        else:
            totos = tstack.top()

            # Can we look up the field by index within TOTOS?
            if (totos.type is None):
                # No way to know what goes here
                raise FieldPatchFailed("field lookup (%r) on unresolvable stack type" % instr)
            elif (not hasattr(totos.type, 'fft')) or (len(totos.type.fft) <= field):
                # No way to know what goes here
                raise FieldPatchFailed("field lookup (%r) on unhelpful stack type (%s)" % (instr, totos))
            else:
                cdef = totos.type
                cdef.actualize()

                try:
                    assert (field >= 0), "Runtime field offset %d < 0" % field
                    fdef = cdef.fft[field]
                except (IndexError, AssertionError):
                    raise FieldPatchFailed("error looking up field %d for type %s" % (field, cdef))

                # Replace classref type with field type
                field_type = fdef.type[0]
                tstack.pop_push(field_type)

                # check if it is a long access or not
                if 'lget' in instr._name:
                    assert str(field_type) in 'JD', 'ERROR: expected category 2 computational type, instead got %s' % str(field_type)
                else:
                    assert str(field_type) not in 'JD', 'ERROR: expected category 1 computational type, instead got %s' % str(field_type)

                # Also, patchup the instruction's operand list accordingly
                instr.operands[0] = fdef
                self.count("fields")
    _lgetfield = _lgetfield_wide = _getfield_wide = _getfield

    def _lreturn(self, instr, tstack, tlocals):
        totos = tstack.top()
        if self._reals and not totos:
          self.log("WARNING: expected double type on top of stack for return, got empty stack")
        if not self._reals and not totos:
          self.log("WARNING: expected long type on top of stack for return, got empty stack")
        if self._reals and str(totos) not in 'D':
          self.log("WARNING: expected double type on top of stack for return, instead got %s" % repr(totos))
        elif not self._reals and str(totos) not in 'J':
          self.log("WARNING: expected long type on top of stack for return, instead got %s" % repr(totos))
        tstack.pop(2)

    def _ireturn(self, instr, tstack, tlocals):
        totos = tstack.top()
        if self._reals and not totos:
          self.log("WARNING: expected float type on top of stack for return, got empty stack")
        if not self._reals and not totos:
          self.log("WARNING: expected int, short, byte, char or boolean type on top of stack for return, got empty stack")
        if self._reals and str(totos) not in 'F':
          self.log("WARNING: expected float type on top of stack for return, instead got %s" % repr(totos))
        elif not self._reals and str(totos) not in 'ISCBZ':
          self.log("WARNING: expected int, short, byte, char or boolean type on top of stack for return, instead got %s" % repr(totos))
        tstack.pop()

    def _ireturn_field(self, instr, tstack, tlocals):
        # calls getfield on self and then ireturns
        self._aload_0(instr, tstack, tlocals)
        self._getfield(instr, tstack, tlocals)
        self._ireturn(instr, tstack, tlocals)
    _ireturn_field_wide = _ireturn_field

    def _areturn(self, instr, tstack, tlocals):
        totos = tstack.top()
        if not totos:
          self.log("WARNING: expected object type on top of stack for return, got empty stack")
        if not totos._object and not totos._array:
          self.log("WARNING: expected object type on top of stack for return, got %s" % repr(totos))
        tstack.pop()

    def _areturn_field(self, instr, tstack, tlocals):
        # calls getfield on self and then areturns
        self._aload_0(instr, tstack, tlocals)
        self._getfield(instr, tstack, tlocals)
        self._areturn(instr, tstack, tlocals)
    _areturn_field_wide = _areturn_field

    def _aload_0_getfield(self, instr, tstack, tlocals):
        # Equivalent to "push tlocal[0]; getfield BLAH"
        tstack.push(tlocals[0])
        self._getfield(instr, tstack, tlocals)
    _aload_0_getfield_wide = _aload_0_getfield

    def _getstatic(self, instr, tstack, tlocals):
        if hasattr(instr.operands[0], 'type'):
            field_type = instr.operands[0].type[0]
            tstack.push(field_type)

            # check if it is a long access or not
            if 'lget' in instr._name:
                assert str(field_type) in 'JD', 'ERROR: expected category 2 computational type, instead got %s' % str(field_type)
            else:
                assert str(field_type) not in 'JD', 'ERROR: expected category 1 computational type, instead got %s' % str(field_type)
        else:
            # Then we just don't know!
            self.log("WARNING: unknown static field '%s' for 'getstatic'; pushing *" % instr.operands[0])
            tstack.push(self._tt['*'])
    _lgetstatic_lib = _lgetstatic = _getstatic_lib = _getstatic

    def _putstatic(self, instr, tstack, tlocals):
        if hasattr(instr.operands[0], 'type'):
            tstack.pop()
        else:
            self.log("WARNING: unknown static field '%s' for 'putstatic'" % instr.operands[0])
            tstack.pop()
    _putstatic_lib = _putstatic

    def _lputstatic(self, instr, tstack, tlocals):
        if hasattr(instr.operands[0], 'type'):
            tstack.pop(2)
        else:
            self.log("WARNING: unknown static field '%s' for 'lputstatic'" % instr.operands[0])
            tstack.pop(2)
    _lputstatic_lib = _lputstatic

    def _arraylength(self, instr, tstack, tlocals):
        tstack.pop_push(self._tt['int'])

    # This is a non-standard JVM opcode; assuming it behaves like arraylength
    _stringlength = _arraylength

    def _new(self, instr, tstack, tlocals):
        tstack.push(self.mktt(instr.operands[0], class_name=True))
    _new_lib = _new

    def _baload(self, instr, tstack, tlocals):
        tstack.pop()
        if self._reals:
            tstack.pop_push(self._tt['float'])
        else:
            tstack.pop_push(self._tt['int'])
    _iaload = _saload = _caload = _baload

    def _newarray(self, instr, tstack, tlocals):
        tstack.pop_push(self.mktt(self._tt[instr.operands[0]], 1))

    def _dup(self, instr, tstack, tlocals):
        assert (str(tstack[-1]) not in 'JD'), "invalid use of dup"
        tstack.append(tstack.top())

    def _dup2(self, instr, tstack, tlocals):
        tstack += tstack[-2:]

    def _jumpspecial(self, instr, tstack, tlocals):
        # jump special appears to simply hand over control to the another function
        # with the current parameters pushed onto the stack:
        #
        # <init>() {
        #   //   0. (00009): jumpspecial_lib java/lang/Object/<init>(Ljava/lang/Object;)V
        # }
        #
        # .method <init>()V
        #    aload_0 ; met001_slot000
        #    invokespecial java/lang/Object.<init>()V
        #    return
        #
        # we need to go through the motions to adjust our max stack and local size
        tl_jts = instr.operands[0].to_jts().split('(')[1].split(')')[0]
        num_params = len(TypeList.split_jts(tl_jts))
        for i in range(num_params):
            tstack.push(tlocals[i])
    _jumpspecial_lib = _jumpspecial

    # TODO: implement arguments type verification
    def _invokevirtual(self, instr, tstack, tlocals):
        # If we already know what method we're dealing with, use its info for number of params
        # to pop and type of return value
        if hasattr(instr.operands[0], 'return_type'):
            rdef = instr.operands[0]
            tstack.pop(rdef.param_types.slots())
            ret_type = rdef.return_type
            if ret_type:  # It might be void, you know...
                tstack.push(ret_type[0])
        elif isinstance(instr.operands[0], (int, long)):
            # This is where it gets tricksy.  We look at the second parameter to see how far
            # down the stack "this" lives (and we hope this is right; I've seen it be wrong on
            # fixed-up method calls; maybe that's why they're fixed up???)  We pop the parameters
            # (including "this"), and go from there
            args = tstack.pop(instr.operands[1])
            this = None
            if args[0]._array:
                this = self.sub.routine.module._L.ref_class('net_rim_cldc', 'java/lang/Object')
            elif args[0]._object:
                this = args[0].type
            # we need to actualize this to get the virtual function table
            this.resolve().actualize()

            if (this is None) or (not hasattr(this, 'vft')) or (len(this.vft) <= instr.operands[0]):
                # No idea what should go here
                raise VirtualPatchFailed("virtual method call (%r) on unhelpful stack type (%s)" % (instr, args[0]))

            try:
                vmindex = instr.operands[0]
                assert (vmindex >= 0), "Runtime VM index %d < 0" % vmindex
                vmethod = this.vft[vmindex]
            except (IndexError, AssertionError) as err:
                raise VirtualPatchFailed("error looking up virtual method %d for type %s" % (instr.operands[0], this))

            # Push the return type (if non-void)
            if vmethod.return_type:
                tstack.push(vmethod.return_type[0])

            # Fix-up this instruction so we know what call to make in the future (more easily)
            instr.operands[0] = vmethod
            self.count("virtuals")
        else:
            raise ValueError("Invalid virtual method: %r" % instr.operands[0])
    _invokevirtual_short = _invokevirtual

    def _invokestatic(self, instr, tstack, tlocals):
        # Assume we have a RoutineDef here...
        rdef = instr.operands[0]
        tstack.pop(rdef.param_types.slots())
        if rdef.return_type:
            tstack.push(rdef.return_type[0])
    _invokestaticqc_lib = _invokestaticqc = _invokestatic_lib = _invokestatic

    def _l2i(self, instr, tstack, tlocals):
        tstack.pop()
        tstack.pop_push(self._tt['int'])
    _d2i = _l2i

    def _arrayinit(self, instr, tstack, tlocals):
        tstack.push(self.mktt(self._tt[instr.operands[0]], 1))

    def _stringarrayinit(self, instr, tstack, tlocals):
        tstack.push(self._tt['string[]'])

    def _multianewarray(self, instr, tstack, tlocals):
        num_dims_given, dims, type = instr.operands
        # pop any specified dimension depths
        for i in range(num_dims_given):
            tstack.pop()
        tstack.push(self.mktt(self._tt[type], dims))

    def _multianewarray_object(self, instr, tstack, tlocals):
        type, num_dims_given, dims = instr.operands
        # pop any specified dimension depths
        for i in range(num_dims_given):
            tstack.pop()
        tstack.push(self.mktt(type, dims))
    _multianewarray_object_lib = _multianewarray_object

    def _i2l(self, instr, tstack, tlocals):
        tstack.pop()
        tstack.push(self._tt['long'])
    _f2l = _i2l

    def _dup2_x1(self, instr, tstack, tlocals):
        # Stupid category 2 computational types...
        assert (str(tstack[-3]) not in 'JD'), "invalid use of dup2_x1"
        if str(tstack[-2]) not in 'JD':
            # form 1
            tstack[-3:] = tstack[-2:] + tstack[-3:]
        else:
            assert str(tstack[-1]) == str(tstack[-2])
            # form 2
            tstack[-3:] = [tstack[-2], tstack[-1], tstack[-3], tstack[-2], tstack[-1]]

    def _dup2_x2(self, instr, tstack, tlocals):
        # Did I mention that category 2 computational types were a stupid idea?
        if str(tstack[-1]) not in 'JD' and str(tstack[-2]) not in 'JD' and str(tstack[-3]) not in 'JD' and str(tstack[-4]) not in 'JD':
            # form 1
            tstack[-4:] = tstack[-2:] + tstack[-4:]
        elif str(tstack[-1]) in 'JD' and str(tstack[-3]) not in 'JD' and str(tstack[-4]) not in 'JD':
            # form 2
            assert str(tstack[-1]) == str(tstack[-2])
            tstack[-4:] = tstack[-2:] + tstack[-4:-2] + tstack[-2:]
        elif str(tstack[-1]) not in 'JD' and str(tstack[-2]) not in 'JD' and str(tstack[-3]) in 'JD':
            # form 3
            assert str(tstack[-3]) == str(tstack[-4])
            tstack[-4:] = tstack[-2:] + tstack[-4:-2] + tstack[-2:]
        elif str(tstack[-1]) in 'JD' and str(tstack[-3]) in 'JD':
            # form 4
            assert str(tstack[-1]) == str(tstack[-2])
            assert str(tstack[-3]) == str(tstack[-4])
            tstack[-4:] = tstack[-2:] + tstack[-4:-2] + tstack[-2:]

    def _dup_x1(self, instr, tstack, tlocals):
        tstack.insert(-2, tstack[-1])

    def _dup_x2(self, instr, tstack, tlocals):
        # Is this the last one???
        assert (str(tstack[-1]) not in 'JD'), "invalid use of dup2_x2"
        if str(tstack[-2]) not in 'JD':
            # form 1
            tstack.insert(-3, tstack[-1])
        else:
            # form 2
            assert str(tstack[-2]) == str(tstack[-3])
            tstack[-3:] = [tstack[-1:], tstack[-3], tstack[-2], tstack[-1:]]

    def _lcmp(self, instr, tstack, tlocals):
        tstack.pop(4)
        tstack.push(self._tt['int'])

    def _invokenonvirtual(self, instr, tstack, tlocals):
        # Figure out the method being called
        rdef = instr.operands[0]

        # In any case, pop all the arguments
        tstack.pop(rdef.param_types.slots())

        # Handle pushing the return type
        if not hasattr(rdef, 'return_type'):
            raise UnknownTotos("unknown/corrupted return type for nonvirtual method '%s'; TOTOS undefined" % rdef)
        elif rdef.return_type:
            tstack.push(rdef.return_type[0])
    _invokespecial = _invokespecial_lib = _invokenonvirtual_lib = _invokenonvirtual

    def _athrow(self, instr, tstack, tlocals):
        exref = tstack.top()
        del tstack[:]   # Blow away the stack and push the exception object
        tstack.push(exref)

    def _aaload(self, instr, tstack, tlocals):
        tstack.pop()
        arrtype = tstack.pop()
        # Do we return an array type or an element-of-an-array type?  Check dims...
        if arrtype.type is None:
            # We have no idea what type would go here
            raise UnknownTotos("%r on indeterminate type; TOTOS undefined..." % instr)
        elif not arrtype._array:
            raise UnknownTotos("%r on non-array type '%s'; TOTOS undefined..." % (instr, arrtype))
        else:
            tstack.push(self.mktt(arrtype.type, arrtype.dims - 1))

    def _laload(self, instr, tstack, tlocals):
        tstack.pop(2)
        if self._reals:
            tstack.push(self._tt['double'])
        else:
            tstack.push(self._tt['long'])

    def _lastore(self, instr, tstack, tlocals):
        tstack.pop(4)

    def _checkcast(self, instr, tstack, tlocals):
        new_type = self.mktt(instr.operands[0], class_name=True)
        tstack.pop_push(new_type)
    _checkcastbranch_lib = _checkcastbranch = _checkcast_lib = _checkcast

    def _checkcast_array(self, instr, tstack, tlocals):
        tstack.pop_push(instr.operands[0])
    _checkcastbranch_array = _checkcast_array

    def _checkcast_arrayobject(self, instr, tstack, tlocals):
        new_type = self.mktt(instr.operands[0], instr.operands[1])
        tstack.pop_push(new_type)
    _checkcast_arrayobject_lib = _checkcast_arrayobject

    def _newarray_object(self, instr, tstack, tlocals):
        tstack.pop_push(self.mktt(instr.operands[0], 1, class_name=True))
    _newarray_object_lib = _newarray_object

    def _invokeinterface(self, instr, tstack, tlocals):
        # Pop instance/args
        tstack.pop(instr.operands[-2])

        # Figure out return type (if any)
        rdef = instr.operands[0]
        if not hasattr(rdef, 'return_type'):
            raise UnknownTotos("unknown/corrupted return type for interface method '%s'; TOTOS undefined" % rdef)
        elif rdef.return_type:
            tstack.push(rdef.return_type[0])

    def _i2f(self, instr, tstack, tlocals):
        tstack.pop_push(self._tt['float'])

    def _f2i(self, instr, tstack, tlocals):
        tstack.pop_push(self._tt['int'])

    def _f2d(self, instr, tstack, tlocals):
        tstack.pop()
        tstack.push(self._tt['double'])
    _i2d = _f2d

    def _l2d(self, instr, tstack, tlocals):
        tstack.pop(2)
        tstack.push(self._tt['double'])

    def _stringaload(self, instr, tstack, tlocals):
        # indexes a string
        tstack.pop()
        tstack.pop_push(self._tt['char'])

    def _dcmpl(self, instr, tstack, tlocals):
        tstack.pop(3)
        tstack.pop_push(self._tt['int'])
    _dcmpg = _dcmpl

    def _instanceof(self, instr, tstack, tlocals):
        tstack.pop_push(self._tt['int'])
    _instanceof_array = _instanceof_lib = _instanceof

    def _instanceof_arrayobject(self, instr, tstack, tlocals):
        tstack.pop_push(self._tt['int'])
    _instanceof_arrayobject_lib = _instanceof_arrayobject

    def _l2f(self, instr, tstack, tlocals):
        tstack.pop()
        tstack.pop_push(self._tt['float'])
    _d2f = _l2f

    def _fcmpl(self, instr, tstack, tlocals):
        tstack.pop()
        tstack.pop_push(self._tt['int'])
    _fcmpg = _fcmpl

    def _d2l(self, instr, tstack, tlocals):
        tstack.pop(2)
        tstack.push(self._tt['long'])

    def _putfield(self, instr, tstack, tlocals):
        field = instr.operands[0]
        value = tstack.pop() # the value we are "putting"
        this = tstack.pop() # the object we are "putting" into

        # If the field is an integer, that means we need to patch it up
        if isinstance(field, (int, long)):
            if (this.type is None) or (not hasattr(this.type, 'fft')) or (len(this.type.fft) <= field):
                raise FieldPatchFailed("field lookup (%r) on unhelpful stack type (%s)" % (instr, this))
            else:
                try:
                    assert (field >= 0), "Runtime field index %d < 0" % field
                    fdef = this.type.fft[field]
                except (IndexError, AssertionError) as err:
                    raise FieldPatchFailed("field (%d) lookup failed on type '%s'" % (field, this))

                instr.operands[0] = fdef
                self.count("fields")
    _putfield_wide = _putfield

    def _putfield_return(self, instr, tstack, tlocals):
        # calls putfield on object and then returns
        self._aload_0(instr, tstack, tlocals) # object
        self._aload_1(instr, tstack, tlocals) # value
        self._putfield(instr, tstack, tlocals)
    _putfield_return_wide = _putfield_return

    def _lputfield(self, instr, tstack, tlocals):
        # Same as putfield, but with 2 pops for the value
        tstack.pop()
        self._putfield(instr, tstack, tlocals)
    _lputfield_wide = _lputfield

    # TODO: not really sure about that...
    def _ldc_class(self, instr, tstack, tlocals):
        type = self.mktt(instr.operands[0], class_name=True)
        tstack.push(type)
    _ldc_class_lib = _ldc_class

redpajama_set_name: RedPajamaGithub


text:
You are here: Home › ZITF ends on a high
ZITF ends on a high
April 29, 2018 in Local, News
The 59th edition of the Zimbabwe International Trade Fair (ZITF) ended in Bulawayo yesterday with the organisers describing this year's fair as one of the best in recent years.
BY NKULULEKO SIBANDA
ZITF Company chairperson Ruth Ncube told journalists the showcase had been a success.
"The 59th edition of the ZITF comes to an end today [yesterday]. The exhibition was characterised by high-quality exhibits and high-level business networking," she said.
"Feedback from participants from across the board shows that ZITF 2018 is a value, adding show that continues to offer opportunities for business growth and relationship building."
Statistics provided by the ZITF Company showed that all the exhibition space was taken up with 753 exhibitors taking part in the annual event.
"We had 753 exhibitors, 68 of which were foreign. This compares favourably to last year's closing total of 706," Ncube said.
"Direct exhibitors were 467, 23 of these were foreign. We also had 286 indirect exhibitors, 45 of which were foreign."
She said exhibitors were drawn from countries such as Botswana, China, South Africa, the United Arab Emirates and Zambia, among others.
"The business-to-business trading period, which constitutes the first three days of the exhibition, saw a sharp increase (114%) from last year's 3 200 business visitors to 6 914 visitors walking through the exhibition centre," Ncube added.
Hwange Colliery Company Limited spokesperson Rugare Dhobbie said the company had received a substantial amount of enquiries during the fair.
"The exhibition was a good platform for us to engage with our business' stakeholders," she said.
"Many of them came through to the stand to make enquiries and we are happy that we did get time to engage and also discuss more business opportunities."
Johannes Nyamayedenga, the public relations manager at the Rural Electrification Agency, said the exhibition afforded the organisation time to market its products.
However, showgoers said there was not much of change from what they had seen at previous events.
Munetsi: Zimbabwe's very own Yaya Toure
Reconciliation needs an honest broker

redpajama_set_name: RedPajamaCommonCrawl


text:
Elektra Records — американский лейбл звукозаписи, приобретённый компанией Warner Music Group. В 2004 году был объединён с Atlantic Records Group, также принадлежащим WMG. После пяти лет бездействия лейбл был возрождён компанией Atlantic Records в 2009 году.

История

Начало
Elektra был создан в 1950 году Джеком Хольцманом и Полом Рикхольтом, каждый из которых вложил в дело по $300. В качестве названия было взято изменённое традиционное написание имени героини древнегреческой мифологии Электра (в английском языке её имя пишется как «Electra»), что Хольцман позднее во всеуслышание объяснял: «Я дал ей 'K', которого мне не хватало.»

Первым лонгплеем Elektra стал «New Songs» («Новые песни») (EKLP 1 выпущен в марте 1951), представлявший собой сборник лидов (немецких романсов) и схожих арт-песен, который разошёлся всего лишь несколькими копиями. В 50-е и начале 60-х лейбл занимался в основном изданием фолк-музыки, выпустив несколько хорошо продаваемых альбомов Джуди Коллинз и певцов протеста, таких как Фил Оукс и Том Пэкстон, но к середине 60-х поп-музыка выделилась в отдельное направление, а лейбл получил таким образом значительный авторитет на музыкальной сцене как один из первых лейблов, заключивший контракты с ведущими исполнителями новой волны американского психоделического рока 1966-67 годов. Самыми значительными контрактами лейбла были контракты с чикагской Paul Butterfield Blues Band (с участием Майкла Блумфилда), лос-анджелесскими группами Love и The Doors, а также детройтскими группами The Stooges и MC5. Одним из наиболее значимых лос-анджелесских исполнителей Elektra был Тим Бакли, будущий отец Джефа Бакли.

Также в 1967 году Elektra запустила нашумевшую серию Nonesuch Explorer Series, ставшую одной из первых коллекций музыки, которую теперь называют этнической. Отрывки из нескольких записей Nonesuch Explorer позднее были представлены на двух золотых пластинках «Вояджера», отправленных в открытый космос в 1977 году на борту космических аппаратов Вояджер-1 и Вояджер-2.

Elektra также занималась выпуском чрезвычайно популярной бюджетной классической серии Nonesuch, которая стала наиболее продаваемой классической бюджетной серией своей эпохи. Прочие лейблы также начали выпуск собственных бюджетных серий, но серия Nonesuch продолжала оставаться самой популярной, а Джек Хольцман в своей книге утверждал, что прибыль от продаж бюджетной классической серии позволила Elektra экспериментировать со своими поп-релизами.

Слияние с Asylum Records
Elektra, вместе со своим дочерним подразделением Nonesuch Records, было приобретено компанией Kinney National Company в 1970 году. Вскоре после этого Kinney объединил все лейблы холдинга под вывеской Warner Communications. Хольцман оставался в команде Elektra до 1972 года, когда произошло слияние с Asylum Records, в результате чего появился лейбл Elektra/Asylum Records; основатель Asylum, Дэвид Джеффен, возглавил объединённый лейбл. Хольцман, тем временем, был назначен старшим вице-президентом и директором по технологиям в Warner, что ознаменовало собой выход компании на рынок домашних видеосистем и первых развлекательных кабельных систем. Также Хольцман принял участие в развитии Discovery Records. В 1975 году Джеффен оставил пост из-за проблем со здоровьем. Он был заменён Джо Смитом, который впоследствии стал генеральным директором Capitol Records.

Несмотря на то, что компания на документах технически обозначалась как «Elektra/Asylum Records», прошедшие годы с момента основания компании взяли своё: в компании продолжали неофициально именоваться Elektra Records (а Asylum рассматривался как дочернее подразделение). В 1982 году Elektra создала дочерний лейбл Elektra/Musician для выпуска джаза. На следующий год Боб Краснов стал президентом и генеральным директором Elektra; под его руководством лейбл достиг пика своего коммерческого успеха на протяжении оставшейся части 1980-х и вплоть до середины 1990-х.

Elektra Entertainment Group
В 1989 году компания официально изменила название на Elektra Entertainment. Краснов был заменён Сильвией Роун, которая в 1994 году была назначена генеральным директором; в том же году лейбл стал называться Elektra Entertainment Group. В это время Elektra развивала отношения с британским лейблом 4AD Records, став североамериканским дистрибьютором групп, подписанных на 4AD, как например, Pixies, The Breeders, Френк Блэк и The Amps. В конечном счёте это привело к тому, что родственный Elektra лейбл «Warner Strategic Marketing» подписал контракт на эксклюзивную американскую дистрибуцию почти всех изданий «4AD» на период с 1992 по 1998 год.

Несмотря на наличие большого числа известных групп, 1990-е годы выдались весьма трудными для лейбла, у Elektra начался резкий спад доходов одновременно со значительным падением позиций в хит-парадах. Помимо этого лейбл заработал себе весьма негативную репутацию в индустрии из-за плохо организованной рекламы многих своих выпусков, даже получил прозвище «Neglectra» от многих групп. В итоге, лейбл остался далеко позади своих родственных лейблов, Warner Bros. Records и Atlantic Records.

Поглощение лейблом Atlantic Records

В феврале 2004 года Warner Music Group была продана Time Warner группе частных инвесторов, состоящей из «Thomas Lee Partners», Bain & Company и Эдгара Бронфмана-младшего (исполняющий обязанности генерального директора).

В поисках способа защитить свои вложения, новые владельцы WMG решили объединить «Elektra» и «Atlantic Records». Так как «Elektra» из двух данных лейблов был меньшим, то сделки «Elektra» составили 40 % операций новой компании, а остальные 60 % — сделки «Atlantic». Как следствие, новая компания стала называться «Atlantic Records Group», а «Elektra» был выделен в дочернее подразделение, который оставался бездействующим вплоть до своего возрождения в 2009 году.

Каталог Elektra продолжил переиздаваться лейблом Rhino Records, который в ноябре 2006 года выпустил 5-дисковый набор, представлявший собой компиляцию песен различных исполнителей и озаглавленный Forever Changing: the Golden Age of Elektra Records 1963—1973 (с англ. «Вечно меняющийся: золотая эпоха "Электра рекордс" 1963—1973»).

Возрождение
«Atlantic Records Group» объявила о возрождении лейбла «Elektra Records» 1 июня 2009. Во главе возрождённого лейбла стали два новых сопрезидента: Майк Карен, исполнительный вице-президент A&R в «Atlantic Records», и Джон Джени, основатель и президент известного инди-лейбла Fueled by Ramen. Лейбл продолжил свою деятельность в составе «Atlantic Records Group».

Литература
 Jac Holzman. Follow the Music: The Life and High Times of Elektra Records in the Great Years of American Pop Culture. First Media Books (1998). ISBN 0-9661221-1-9.

Примечания

Ссылки
 Официальный веб-сайт
 История «Elektra» на сайте BSN Pubs
 Дискография «Elektra» с 1950 по середину 1973 гг.

Компании, основанные в 1950 году
Лейблы звукозаписи США
Лейблы Warner Music
Atlantic Records
Члены IFPI

redpajama_set_name: RedPajamaWikipedia


Service Oriented Computing (SOC) has been established in the last recent years as a successful paradigm in Software Engineering. The systems built under this paradigm, known as Service Based System (SBS), are composed of several services, which are usually third-party software run by external service providers. SBS rely on these service providers to ensure that their services comply with the agreed Quality of Service (QoS). In contrast to other systems, the dynamic behaviour of SBS requires up-to-date QoS information for its proper management in the different stages of its lifecycle, from their initial construction until their decommission. Providing such QoS information has resulted in different technological solutions built around a monitor. Nonetheless, several research challenges in the field remain still open, ranging from theoretical aspects of quality assurance to architectonical challenges in decentralized monitoring. Based on the current research challenges for service monitoring, the research gaps in which we aim to contribute are twofold: - To investigate on the definition and structure of the different quality factors of services, and provide a framework of common understanding for the definition of what to monitor. - To investigate on the different features required to support the activities of the whole SBS lifecycle (i.e. how to monitor), and develop a monitoring framework that accomplishes such features. As a result of this thesis, we provide: What to monitor - A distribution of the quality models along the time dimension and the identification of their relationships. - An analysis of the size and definition coverage of the proposed quality models. - A quantified coverage of the different ISO/IEC 25010 quality factors given by the proposals. - The identification of the most used quality factors, and provided the most consolidated definitions for them. How to monitor - The elicitation of the requirements of the different activities in the SBS lifecycle. - The definition of the set of features that supports the elicited requirements. - A modular service-oriented monitoring framework, named SALMon, implementing the defined features. SALMon has been validated by including it in several frameworks supporting the different activities of the SBS lifecycle. Finally, we have conducted a performance evaluation of SALMon over real web services.


text:
TURKEY – UNITED STATES
On trial in Izmir on espionage charges, Pastor Brunson can see some light at the end of the tunnel
Three key prosecution witnesses have retracted their statements a few hours before the start of the fourth hearing in the trial. The prosecution has upheld the charges but has agreed to the accused's release. Trump might use this in the upcoming mid-term elections.
Izmir (AsiaNews/Agencies) – There might be some light at the end of the tunnel for US pastor Andrew Craig Brunson, a married father of three held in a Turkish jail for more than two years on a number of charges.
At the trial in Izmir, now in its fourth hearing, the prosecution has accused the Christian clergyman of terrorism and demanded a ten-year sentence. At the same time, it accepted a motion to allow Brunson's release from house arrest for a brief return to the United States. Meanwhile, some key witnesses have withdrawn their testimonies against the pastor.
Some US media cite diplomatic sources saying that Turkish and US officials might have struck a secret deal to free Brunson and thus end a situation that had damaged relations between the two countries.
Brunson's release could help Donald Trump in the up-coming mid-term election, especially among Evangelicals.
The Christian missionary was arrested in October 2016 on charges of espionage and links with the Kurdistan Workers' Party (PKK), which Turkey considers a terrorist organization, as well as the movement of Islamic preacher Fethullah Gülen, accused of masterminding the failed coup in July 2016.
If convicted, Brunson could get up to life in prison, i.e. 35 years in prison. However, the clergyman has always rejected the accusations, calling them "shameful and disgusting". He explained that he had always "strived to prevent politics from entering the church."
Instead, his work was "helping refugees" from Syria and was not involved with the PKK. One of the things he was trying to do was build a church in Turkey. He has also denied claims that he received money and support from the Gülen network.
The story of the 50-year-old pastor from Black Mountain, North Carolina, head of the Resurrection Church (Dirilis) in Izmir, who has lived for 20 years in the country, is a thorny issue that has soured relations between Ankara and Washington.
The US government has repeatedly called for Brunson's release, saying that he was being held "unjustly". For Turkey, the matter before the courts and the government cannot interfere.
The major political and diplomatic row between the two countries, both NATO embers, contributed to collapse of the Turkish lira, which lost 40 per cent of its value since the start of the year.
US media are now saying that the two government have reached an agreement on his release, which would lead to a partial lifting of US sanctions against Turkey.
For his part, Turkish President Recep Tayyip Erdogan has repeatedly rejected the pressures from the Trump administration and US public opinion, claiming that he has no power or influence over Turkey's courts, which he says are independent.
gulen
Pastor Brunson freed, flying to the USA
White House to stop Beijing's "imperialist" policy in the South China Sea
US sanctions over arrested Protestant pastor. Erdogan: Evangelist and Zionist mentality
Ankara arrests 1112 people for alleged ties to Gulen's coup network


text:
#ifndef IVW_INVIWOFILEDIALOG_H
#define IVW_INVIWOFILEDIALOG_H

#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/qt/widgets/inviwoqtwidgetsdefine.h>
#include <inviwo/core/util/fileextension.h>
#include <string>
#include <QFileDialog>
#include <QUrl>
#include <QSettings>

#include <unordered_map>

namespace inviwo {

class IVW_QTWIDGETS_API InviwoFileDialog : public QFileDialog {
    Q_OBJECT
public:
    InviwoFileDialog(QWidget *parent, const std::string &title,
        const std::string &pathType = "default",
        const std::string &path="");

    void addExtension(const FileExtension &fileExt);
    void addExtension(const std::string &ext, const std::string &description);
    void addExtension(const std::string &extString);

    void addSidebarPath(const InviwoApplication::PathType &path);
    void addSidebarPath(const std::string &path);
    void addSidebarPath(const QString &path);

    void useNativeDialog(const bool &use = true);

    void setCurrentDirectory(const std::string &path);

    FileExtension getSelectedFileExtension() const;

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
    virtual int exec() override;
#else
    virtual int exec();
#endif

    static QString getPreviousPath(const QString &pathType);
    static void setPreviousPath(const QString &pathType, const QString &path);

    static QString getPreviousExtension(const QString &pathType);
    static void setPreviousExtension(const QString &pathType, const QString &path);

protected slots:
    void filterSelectionChanged(const QString &filter);

protected:
    FileExtension getMatchingFileExtension(const QString &extStr);

    QList<QUrl> sidebarURLs_;
    QStringList extension_;
    QString selectedExtension_;
    QString pathType_;
    QString currentPath_;

    FileExtension selectedFilter_;

    using FileExtMap = std::unordered_map<std::string, FileExtension>;
    FileExtMap extmap_;

    static QSettings globalSettings_;
};
}  // namespace

#endif


We manufacture handpainted and handcrafted candles in Bredasdorp,close to the southern most tip of Africa. We supply upmarket gift and department stores with our wide range of themed and crafted candles.
We are a leading provider and manufacturer of LED flameless candles and candle holders in China. to the great R&D capability in-house, we have developed the most stable and realistic looking, flickering LED candle on the market. Our unique electronic design is patented by us. Many of our LED candles together with different candle holders are sold by our customers to QVC, and passed QVC's strict quality requirements.
We have advanced and professional production technology.Our products cover a wide range, such as artistic candles, LED candles,Tealight candles,Pillar candles,Votive candles Christmas candles,Valentines Day candles,jelly candles,jar candles, Massage candles and so on, which are based on paraffin wax, soybean wax,palm wax and gel wax. We adhere to the "Quality first, Customer foremost " business philosophy.
Our business scope includes Paper craft, Storage box, Wall hanging, Wall clock, Bag, Umbrella, Scented Candle, Clothing and accessory, Hardware, Silicone kitchenware, Air mattress, Automotive supplies, Sporting goods, and other Daily necessities, Leather gift and craft, Paper gift and craft, Medical devices, Home appliance, Home and Garden, and so on.
Shijiazhuang Tiankai Industry and Trade Co.,Ltd is professional Candle manufacturer and exporter, mainly product have White Candle, Pillar Candle, Tealight Candle, Glass Candle, Spiral Candle etc.
Ethanol Fireplace Our company specializes in ethanol fireplace manufacture,we mainly engaged in firepalces , alcohol fireplace ,bio fuel firepalce , cast iron fireplace , bio fireplace , gel fireplace , art firepalce ,ethanol lamp , firepalce burner , stainless steel firepalce , bio - ethanol fireplace design and development, Our products cover a wide range of models, from wall-mounted,free-standing,floor to in-wall .
We are Chinese manufacturer of beeswax candles, led flameless candles, glass jar candles, church candles, pillar candles, taper candles, tealight candles, citronella candles, shaped candles, memorial candles, birthday candles, candle holders, sealing wax series, antifrost candles, DIY candles and so on. We can provide competitive quotations for you.
Comei factory (C&H) is specializing in manufacturing all kinds of artistic candles. Our products are ranging from basic candles to novel craft candles. Although we supply many types of craft candles,our strengths mainly lie in our ability to provide the highest quality basic candles with most competitive prices.