FMOD_RESULT F_CALLBACK FMOD_FILE_OPENCALLBACK_BRIDGE(const char * name, int unicode, unsigned int * filesize, void ** handle, void ** userdata) {
	JNIEnv *java_env/* = 0*/;
	bool attached = acquire_jenv(&java_env);
	jstring jname = 0;
	if(name) {
		jname = java_env->NewStringUTF((const char *)name);
	}
	jobject jfilesize = 0;
	if(filesize) {
		jfilesize = java_env->NewDirectByteBuffer((int *)filesize, 4);
	}
	jobject jhandle = newPointer(java_env);
	jobject juserdata = newPointer(java_env);
	jint result_ = java_env->CallStaticIntMethod(caller, callbackId[22], jname, (jint)unicode, jfilesize, jhandle, juserdata);
	if(jhandle) {
		POINTER_TYPE jhandleAddress = getPointerAddress(java_env, jhandle);
		if(jhandleAddress) {
			*handle = N2J_CAST_PTR(jhandleAddress, void *);
		}
	}
	if(juserdata) {
		POINTER_TYPE juserdataAddress = getPointerAddress(java_env, juserdata);
		if(juserdataAddress) {
			*userdata = N2J_CAST_PTR(juserdataAddress, void *);
		}
	}
	leave_jenv(attached);
	return (FMOD_RESULT)result_;
}
Example #2
0
File: vm.cpp Project: 0x7CFE/llst
void SmalltalkVM::doSendBinary(TVMExecutionContext& ec)
{
    // Loading the operand objects
    TObject* rightObject = ec.stackPop();
    TObject* leftObject  = ec.stackPop();

    // If operands are both small integers, we may handle it ourselves
    if (isSmallInteger(leftObject) && isSmallInteger(rightObject)) {
        // Loading actual operand values
        int32_t rightOperand = TInteger(rightObject);
        int32_t leftOperand  = TInteger(leftObject);
        bool unusedCondition;

        // Performing an operation
        switch ( static_cast<binaryBuiltIns::Operator>(ec.instruction.getArgument()) ) {
            case binaryBuiltIns::operatorLess:
                ec.returnedValue = (leftOperand < rightOperand) ? globals.trueObject : globals.falseObject;
                break;

            case binaryBuiltIns::operatorLessOrEq:
                ec.returnedValue = (leftOperand <= rightOperand) ? globals.trueObject : globals.falseObject;
                break;

            case binaryBuiltIns::operatorPlus:
                ec.returnedValue = callSmallIntPrimitive(primitive::smallIntAdd, leftOperand, rightOperand, unusedCondition);
                break;

            default:
                std::fprintf(stderr, "VM: Invalid opcode %d passed to sendBinary\n", ec.instruction.getArgument());
                std::exit(1);
        }

        ec.stackPush( ec.returnedValue );
        m_messagesSent++;
    } else {
        // This binary operator is performed on an ordinary object.
        // We do not know how to handle it, thus send the message to the receiver

        // Protecting pointers in case if GC occurs
        hptr<TObject> pRightObject = newPointer(rightObject);
        hptr<TObject> pLeftObject  = newPointer(leftObject);

        hptr<TObjectArray> messageArguments = newObject<TObjectArray>(2/*, false*/);
        messageArguments[1] = pRightObject;
        messageArguments[0] = pLeftObject;

        TSymbol* messageSelector = static_cast<TSymbol*>( globals.binaryMessages[ec.instruction.getArgument()] );
        doSendMessage(ec, messageSelector, messageArguments);
    }
}
Example #3
0
File: vm.cpp Project: 0x7CFE/llst
TByteObject* SmalltalkVM::newBinaryObject(TClass* klass, std::size_t dataSize)
{
    // Class may be moved during GC in allocation,
    // so we need to protect the pointer
    hptr<TClass> pClass = newPointer(klass);

    // All binary objects are descendants of ByteObject
    // They could not have ordinary fields, so we may use it
    uint32_t slotSize = sizeof(TByteObject) + dataSize;

    void* objectSlot = m_memoryManager->allocate(correctPadding(slotSize), &m_lastGCOccured);
    if (!objectSlot) {
        std::fprintf(stderr, "VM: memory manager failed to allocate %d bytes\n", slotSize);
        return static_cast<TByteObject*>(globals.nilObject);
    }

    // VM need to perform some actions if collection was occured.
    // First of all we need to invalidate the method cache
    if (m_lastGCOccured)
        onCollectionOccured();

    TByteObject* instance = new (objectSlot) TByteObject(dataSize, pClass);

    return instance;
}
Example #4
0
File: vm.cpp Project: 0x7CFE/llst
TObject* SmalltalkVM::newOrdinaryObject(TClass* klass, std::size_t slotSize)
{
    // Class may be moved during GC in allocation,
    // so we need to protect the pointer
    hptr<TClass> pClass = newPointer(klass);

    void* objectSlot = m_memoryManager->allocate(correctPadding(slotSize), &m_lastGCOccured);
    if (!objectSlot) {
        std::fprintf(stderr, "VM: memory manager failed to allocate %u bytes\n", slotSize);
        return globals.nilObject;
    }

    // VM need to perform some actions if collection was occured.
    // First of all we need to invalidate the method cache
    if (m_lastGCOccured)
        onCollectionOccured();

    // Object size stored in the TSize field of any ordinary object contains
    // number of pointers except for the first two fields
    std::size_t fieldsCount = slotSize / sizeof(TObject*) - 2;

    TObject* instance = new (objectSlot) TObject(fieldsCount, pClass);

    for (uint32_t index = 0; index < fieldsCount; index++)
        instance->putField(index, globals.nilObject);

    return instance;
}
Example #5
0
int readRuleSetFromLocalFile( const char *ruleBaseName, const char *rulesFileName, RuleSet *ruleSet, Env *funcDesc, int *errloc, rError_t *errmsg, Region *r ) {

    FILE *file;
    char errbuf[ERR_MSG_LEN];
    file = fopen( rulesFileName, "r" );
    if ( file == NULL ) {
        snprintf( errbuf, ERR_MSG_LEN,
                  "readRuleSetFromFile() could not open rules file %s\n",
                  rulesFileName );
        addRErrorMsg( errmsg, RULES_FILE_READ_ERROR, errbuf );
        return RULES_FILE_READ_ERROR;
    }
    Pointer *e = newPointer( file, ruleBaseName );
    int ret = parseRuleSet( e, ruleSet, funcDesc, errloc, errmsg, r );
    deletePointer( e );
    if ( ret < 0 ) {
        return ret;
    }

    Node *errnode{};
    ExprType *restype = typeRuleSet( ruleSet, errmsg, &errnode, r );
    if ( getNodeType( restype ) == T_ERROR ) {
        if ( NULL != errnode ) {
            *errloc = NODE_EXPR_POS( errnode );
        }
        return RE_TYPE_ERROR;
    }

    return 0;
}
InternalVariantProperty::Pointer InternalVariantProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
{
    InternalVariantProperty *newPointer(new InternalVariantProperty(name, propertyOwner));
    InternalVariantProperty::Pointer smartPointer(newPointer);

    newPointer->setInternalWeakPointer(smartPointer);

    return smartPointer;
}
InternalBindingProperty::Pointer InternalBindingProperty::create(const QString &name, const InternalNodePointer &propertyOwner)
{
    InternalBindingProperty *newPointer(new InternalBindingProperty(name, propertyOwner));
    InternalBindingProperty::Pointer smartPointer(newPointer);

    newPointer->setInternalWeakPointer(smartPointer);

    return smartPointer;
}
Example #8
0
static void como_compile_ast(ast_node *p, const char *filename) {
    Object *main_code = newArray(4);
    global_frame = create_frame(main_code);
    global_frame->filename = newString(filename);
    mapInsertEx(global_frame->cf_symtab, "__FUNCTION__", 
        newString("__main__"));

    (void)como_compile(p, global_frame);
    
    arrayPushEx(main_code, newPointer((void *)create_op(HALT, NULL)));

    (void)como_execute(global_frame, NULL);
}
Example #9
0
File: vm.cpp Project: 0x7CFE/llst
void SmalltalkVM::setupVarsForDoesNotUnderstand(hptr<TMethod>& method, hptr<TObjectArray>& arguments, TSymbol* selector, TClass* receiverClass) {
    // Looking up the #doesNotUnderstand: method:
    method = newPointer(lookupMethod(globals.badMethodSymbol, receiverClass));
    if (method == 0) {
        // Something goes really wrong.
        // We could not continue the execution
        std::fprintf(stderr, "Could not locate #doesNotUnderstand:\n");
        //exit(1);
    }

    // Protecting the selector pointer because it may be invalidated later
    hptr<TSymbol> failedSelector = newPointer(selector);

    // We're replacing the original call arguments with custom one
    hptr<TObjectArray> errorArguments = newObject<TObjectArray>(2);

    // Filling in the failed call context information
    errorArguments[0] = arguments[0];   // receiver object
    errorArguments[1] = failedSelector; // message selector that failed

    // Replacing the arguments with newly created one
    arguments = errorArguments;
}
Example #10
0
File: vm.cpp Project: 0x7CFE/llst
TObject* SmalltalkVM::performPrimitive(uint8_t opcode, hptr<TProcess>& process, TVMExecutionContext& ec, bool& failed) {
    switch (opcode) {
        // FIXME opcodes 253-255 are not standard
        case 255:
            // Debug trap
            std::printf("Debug trap\n");
            break;

        case 254:
            m_memoryManager->collectGarbage();
            break;

#if defined(LLVM)
        case primitive::LLVMsendMessage: { //252
            TObjectArray* args = ec.stackPop<TObjectArray>();
            TSymbol*  selector = ec.stackPop<TSymbol>();
            try {
                return sendMessage(ec.currentContext, selector, args, 0);
            } catch(TBlockReturn& blockReturn) {
                //When we catch blockReturn we change the current context to block.creatingContext.
                //The post processing code will change 'block.creatingContext' to the previous one
                // and the result of blockReturn will be injected on the stack
                ec.currentContext = blockReturn.targetContext;
                return blockReturn.value;
            } catch(TContext* errorContext) {
                //context is thrown by LLVM:throwError primitive
                //that means that it was not caught by LLVM:executeProcess function
                //so we have to stop execution of the current process and return returnError
                process->context = errorContext;
                failed = true;
                return globals.nilObject;
            }
        } break;

        case 247: { // Jit once: aBlock
            try {
                TBlock* const block = ec.stackPop<TBlock>();
                return JITRuntime::Instance()->invokeBlock(block, ec.currentContext, true);
            } catch(TBlockReturn& blockReturn) {
                ec.currentContext = blockReturn.targetContext;
                return blockReturn.value;
            } catch(TContext* errorContext) {
                process->context = errorContext;
                failed = true;
                return globals.nilObject;
            }
        }
#endif

        case 251: {
            // TODO Unicode support

            TString* prompt = ec.stackPop<TString>();
            std::string strPrompt(reinterpret_cast<const char*>(prompt->getBytes()), prompt->getSize());

            std::string input;
            bool userInsertedAnything = CompletionEngine::Instance()->readline(strPrompt, input);

            if ( userInsertedAnything ) {
                if ( !input.empty() )
                    CompletionEngine::Instance()->addHistory(input);

                TString* result = static_cast<TString*>( newBinaryObject(globals.stringClass, input.size()) );
                std::memcpy(result->getBytes(), input.c_str(), input.size());
                return result;
            } else
                return globals.nilObject;
        } break;

#if defined(LLVM)
        case 250: // patchHotMethods
            JITRuntime::Instance()->patchHotMethods();
            break;

        case 249: { // printMethod
            TMethod* method = ec.stackPop<TMethod>();
            JITRuntime::Instance()->printMethod(method);
        } break;

        case 248:
            JITRuntime::Instance()->printStat();
            break;
#endif

        case primitive::startNewProcess: { // 6
            TInteger  ticks = ec.stackPop();
            TProcess* newProcess = ec.stackPop<TProcess>();

            // FIXME possible stack overflow due to recursive call
            TExecuteResult result = this->execute(newProcess, ticks);

            return TInteger(result);
        } break;

        case primitive::allocateObject: { // 7
            // Taking object's size and class from the stack
            TObject* size  = ec.stackPop();
            TClass*  klass = ec.stackPop<TClass>();
            uint32_t fieldsCount = TInteger(size);

            // Instantinating the object. Each object has size and class fields

            return newOrdinaryObject(klass, sizeof(TObject) + fieldsCount * sizeof(TObject*));
        } break;

        case primitive::blockInvoke: { // 8
            TBlock*  block = ec.stackPop<TBlock>();
            uint32_t argumentLocation = block->argumentLocation;

            // Amount of arguments stored on the stack except the block itself
            uint32_t argCount = ec.instruction.getArgument() - 1;

            // Checking the passed temps size
            TObjectArray* blockTemps = block->temporaries;

            if (argCount > (blockTemps ? blockTemps->getSize() - argumentLocation : 0) ) {
                ec.stackTop -= (argCount  + 1); // unrolling stack
                failed = true;
                break;
            }

            // Loading temporaries array
            for (uint32_t index = argCount - 1, count = argCount; count > 0; index--, count--)
                (*blockTemps)[argumentLocation + index] = ec.stackPop();

            // Switching execution context to the invoking block
            block->previousContext = ec.currentContext->previousContext;
            ec.currentContext = static_cast<TContext*>(block);
            ec.stackTop = 0; // resetting stack

            // Block is bound to the method's bytecodes, so it's
            // first bytecode will not be zero but the value specified
            ec.bytePointer = block->blockBytePointer;

            return block;
        } break;

        case primitive::throwError: // 19
            process->context = ec.currentContext;
            process->result  = ec.returnedValue;
            break;

        case primitive::allocateByteArray: { // 20
            TInteger dataSize = ec.stackPop();
            TClass* klass     = ec.stackPop<TClass>();

            return newBinaryObject(klass, dataSize);
        } break;

        case primitive::arrayAt:      // 24
        case primitive::arrayAtPut: { // 5
            TObject* indexObject = ec.stackPop();
            TObjectArray* array  = ec.stackPop<TObjectArray>();
            TObject* valueObject = 0;

            // If the method is Array:at:put then pop a value from the stack
            if (opcode == primitive::arrayAtPut)
                valueObject = ec.stackPop();

            if (! isSmallInteger(indexObject) ) {
                failed = true;
                break;
            }

            // Smalltalk indexes arrays starting from 1, not from 0
            // So we need to recalculate the actual array index before
            uint32_t actualIndex = TInteger(indexObject) - 1;

            // Checking boundaries
            if (actualIndex >= array->getSize()) {
                failed = true;
                break;
            }

            if (opcode == primitive::arrayAt) {
                return array->getField(actualIndex);
            } else {
                // Array:at:put

                TObject** objectSlot = &( array->getFields()[actualIndex] );

                // Checking whether we need to register current object slot in the GC
                checkRoot(valueObject, objectSlot);

                // Storing the value into the array
                array->putField(actualIndex, valueObject);

                // Return self
                return static_cast<TObject*>(array);
            }
        } break;

        case primitive::cloneByteObject: { // 23
            TClass* klass = ec.stackPop<TClass>();
            hptr<TByteObject> original = newPointer( ec.stackPop<TByteObject>() );

            // Creating clone
            uint32_t dataSize  = original->getSize();
            TByteObject* clone = newBinaryObject(klass, dataSize);

            // Cloning data
            std::memcpy(clone->getBytes(), original->getBytes(), dataSize);
            return static_cast<TObject*>(clone);
        } break;

        //         case primitive::integerDiv:   // Integer /
        //         case primitive::integerMod:   // Integer %
        //         case primitive::integerAdd:   // Integer +
        //         case primitive::integerMul:   // Integer *
        //         case primitive::integerSub:   // Integer -
        //         case primitive::integerLess:  // Integer <
        //         case primitive::integerEqual: // Integer ==
        //             //TODO integer operations
        //             break;

        case primitive::integerNew: { // 32
            TObject* object = ec.stackPop();
            if (! isSmallInteger(object)) {
                failed = true;
                break;
            }

            return object; // FIXME long integer
        } break;

        case primitive::flushCache: // 34
            flushMethodCache();
            break;

        case primitive::bulkReplace: { // 38
            //Implementation of replaceFrom:to:with:startingAt: as a primitive

            // Array replaceFrom: start to: stop with: replacement startingAt: repStart
            //      <38 start stop replacement repStart self>.

            // Current stack contents (top is the top)
            //      self
            //      repStart
            //      replacement
            //      stop
            //      start

            TObject* destination            = ec.stackPop();
            TObject* sourceStartOffset      = ec.stackPop();
            TObject* source                 = ec.stackPop();
            TObject* destinationStopOffset  = ec.stackPop();
            TObject* destinationStartOffset = ec.stackPop();

            bool isSucceeded = doBulkReplace( destination, destinationStartOffset, destinationStopOffset, source, sourceStartOffset );

            if (! isSucceeded) {
                failed = true;
                break;
            }
            return destination;
        } break;

        // TODO cases 33, 35, 40
        // TODO case 18 // turn on debugging

        case primitive::objectsAreEqual:    // 1
        case primitive::getClass:           // 2
        case primitive::getSize:            // 4

        case primitive::ioGetChar:          // 9
        case primitive::ioPutChar:          // 3
        case primitive::ioFileOpen:         // 100
        case primitive::ioFileClose:        // 103
        case primitive::ioFileSetStatIntoArray:   // 105
        case primitive::ioFileReadIntoByteArray:  // 106
        case primitive::ioFileWriteFromByteArray: // 107
        case primitive::ioFileSeek:         // 108

        case primitive::stringAt:           // 21
        case primitive::stringAtPut:        // 22

        case primitive::smallIntAdd:        // 10
        case primitive::smallIntDiv:        // 11
        case primitive::smallIntMod:        // 12
        case primitive::smallIntLess:       // 13
        case primitive::smallIntEqual:      // 14
        case primitive::smallIntMul:        // 15
        case primitive::smallIntSub:        // 16
        case primitive::smallIntBitOr:      // 36
        case primitive::smallIntBitAnd:     // 37
        case primitive::smallIntBitShift:   // 39

        case primitive::getSystemTicks:     //253

        default: {
            uint32_t argCount = ec.instruction.getArgument();
            hptr<TObjectArray> args = newObject<TObjectArray>(argCount);

            uint32_t i = argCount;
            while (i > 0)
                args[--i] = ec.stackPop();

            TObject* result = callPrimitive(opcode, args, failed);
            return result;
        }
    }

    return globals.nilObject;
}
Example #11
0
File: vm.cpp Project: 0x7CFE/llst
void SmalltalkVM::doSendMessage(TVMExecutionContext& ec, TSymbol* selector, TObjectArray* arguments, TClass* receiverClass /*= 0*/ )
{
    hptr<TObjectArray> messageArguments = newPointer(arguments);

    if (!receiverClass) {
        TObject* receiver = messageArguments[0];
        assert(receiver != 0);
        receiverClass = isSmallInteger(receiver) ? globals.smallIntClass : receiver->getClass();
        assert(receiverClass != 0);
    }

    hptr<TMethod> receiverMethod = newPointer(lookupMethod(selector, receiverClass));

    // Checking whether we found a method
    if (receiverMethod == 0) {
        // Oops. Method was not found. In this case we should send #doesNotUnderstand: message to the receiver
        setupVarsForDoesNotUnderstand(receiverMethod, messageArguments, selector, receiverClass);
        // Continuing the execution just as if #doesNotUnderstand: was the actual selector that we wanted to call
    }

    // Save stack and opcode pointers
    ec.storePointers();

    // Create a new context for the giving method and arguments
    hptr<TContext>   newContext = newObject<TContext>();
    hptr<TObjectArray> newStack = newObject<TObjectArray>(receiverMethod->stackSize);
    hptr<TObjectArray> newTemps = newObject<TObjectArray>(receiverMethod->temporarySize);

    newContext->stack           = newStack;
    newContext->temporaries     = newTemps;
    newContext->arguments       = messageArguments;
    newContext->method          = receiverMethod;
    newContext->stackTop        = 0;
    newContext->bytePointer     = 0;

    // Suppose that current send message operation is last operation in the current context.
    // If it is true then next instruction will be either stackReturn or blockReturn.
    //
    // VM will switch to the newContext, perform it and then switch back to the current context
    // for the single one return instruction. This is pretty dumb to load the whole context
    // just to exit it immediately. Therefore, we looking one instruction ahead to see if it is
    // a return instruction. If it is, we may skip our context and set our previousContext as
    // previousContext for the newContext. In case of blockReturn it will be the previousContext
    // of the wrapping method context.

    uint8_t nextInstruction = ec.currentContext->method->byteCodes->getByte(ec.bytePointer);
    if (nextInstruction == (opcode::doSpecial * 16 + special::stackReturn)) {
        // Optimizing stack return
        newContext->previousContext = ec.currentContext->previousContext;
    } else if (nextInstruction == (opcode::doSpecial * 16 + special::blockReturn) &&
              (ec.currentContext->getClass() == globals.blockClass))
    {
        // Optimizing block return
        newContext->previousContext = ec.currentContext.cast<TBlock>()->creatingContext->previousContext;
    } else {
        newContext->previousContext = ec.currentContext;
    }
    // Replace current context with the new one. On the next iteration,
    // VM will start interpreting instructions from the new context.
    ec.currentContext = newContext;
    ec.loadPointers();

    m_messagesSent++;
}
Example #12
0
File: vm.cpp Project: 0x7CFE/llst
SmalltalkVM::TExecuteResult SmalltalkVM::execute(TProcess* p, uint32_t ticks)
{
    // Protecting the process pointer
    hptr<TProcess> currentProcess = newPointer(p);

    assert(currentProcess->context != 0);
    assert(currentProcess->context->method != 0);

    // Initializing an execution context
    TVMExecutionContext ec(m_memoryManager, this);
    ec.currentContext = currentProcess->context;
    ec.loadPointers(); // Loads bytePointer & stackTop

    while (true)
    {
        assert(ec.currentContext != 0);
        assert(ec.currentContext->method != 0);
        assert(ec.currentContext->stack != 0);
        assert(ec.bytePointer <= ec.currentContext->method->byteCodes->getSize());
        assert(ec.currentContext->arguments->getSize() >= 1);
        assert(ec.currentContext->arguments->getField(0) != 0);

        // Initializing helper references
        TByteObject&  byteCodes = * ec.currentContext->method->byteCodes;

        TObjectArray& temporaries       = * ec.currentContext->temporaries;
        TObjectArray& arguments         = * ec.currentContext->arguments;
        TObjectArray& instanceVariables = * arguments.getField<TObjectArray>(0);
        TSymbolArray& literals          = * ec.currentContext->method->literals;

        if (ticks && (--ticks == 0)) {
            // Time frame expired
            ec.storePointers();
            currentProcess->context = ec.currentContext;
            currentProcess->result  = ec.returnedValue;

            return returnTimeExpired;
        }

        // Decoding the instruction
        const uint16_t lastBytePointer = ec.bytePointer;
        ec.instruction = st::InstructionDecoder::decodeAndShiftPointer(byteCodes, ec.bytePointer);

        // And executing it
        switch (ec.instruction.getOpcode()) {
            case opcode::pushInstance:    ec.stackPush(instanceVariables[ec.instruction.getArgument()]); break;
            case opcode::pushArgument:    ec.stackPush(arguments[ec.instruction.getArgument()]);         break;
            case opcode::pushTemporary:   ec.stackPush(temporaries[ec.instruction.getArgument()]);       break;
            case opcode::pushLiteral:     ec.stackPush(literals[ec.instruction.getArgument()]);          break;
            case opcode::pushConstant:    doPushConstant(ec);                                  break;
            case opcode::pushBlock:       doPushBlock(ec);                                     break;

            case opcode::assignTemporary: temporaries[ec.instruction.getArgument()] = ec.stackLast();    break;
            case opcode::assignInstance: {
                TObject*  newValue   =   ec.stackLast();
                TObject** objectSlot = & instanceVariables[ec.instruction.getArgument()];

                // Checking whether we need to register current object slot in the GC
                checkRoot(newValue, objectSlot);

                // Performing the assignment
                *objectSlot = newValue;
            } break;

            case opcode::markArguments: doMarkArguments(ec); break;

            case opcode::sendMessage:   doSendMessage(ec);   break;
            case opcode::sendUnary:     doSendUnary(ec);     break;
            case opcode::sendBinary:    doSendBinary(ec);    break;

            case opcode::doPrimitive: {
                TExecuteResult result = doPrimitive(currentProcess, ec);
                if (result != returnNoReturn)
                    return result;
            } break;

            case opcode::doSpecial: {
                TExecuteResult result = doSpecial(currentProcess, ec);
                if (result != returnNoReturn)
                    return result;
            } break;

            default:
                std::fprintf(stderr, "VM: Invalid opcode %d at offset %d in method ", ec.instruction.getOpcode(), lastBytePointer);
                std::fprintf(stderr, "'%s'\n", ec.currentContext->method->name->toString().c_str() );
                std::exit(1);
        }
    }
}
Example #13
0
static void como_compile(ast_node* p, ComoFrame *frame)
{
    assert(p);

    switch(p->type) {
        default:
            printf("%s(): invalid node type(%d)\n", __func__, p->type);
            exit(1);
        break;
        case AST_NODE_TYPE_STRING:
            arrayPushEx(frame->code, newPointer((void *)create_op(LOAD_CONST, 
                newString(p->u1.string_value.value)))); 
        break;
        case AST_NODE_TYPE_PRINT:
            como_compile(p->u1.print_node.expr, frame);
            arrayPushEx(frame->code, 
                newPointer((void *)create_op(IPRINT, NULL)));
        break;
        case AST_NODE_TYPE_NUMBER:
            arrayPushEx(frame->code, newPointer((void *)create_op(LOAD_CONST, 
                newLong((long)p->u1.number_value))));
        break;
        case AST_NODE_TYPE_ID:
            arrayPushEx(frame->code, newPointer((void *)create_op(LOAD_NAME, 
                newString(p->u1.string_value.value)))); 
        break;
        case AST_NODE_TYPE_RET:
            if(p->u1.return_node.expr != NULL) {
                como_compile(p->u1.return_node.expr, frame);
                arrayPushEx(frame->code, newPointer((void *)create_op(IRETURN, 
                    newLong(1L))));
            } else {
                arrayPushEx(frame->code, newPointer((void *)create_op(IRETURN, 
                    newLong(0L))));
            }
        break;
        case AST_NODE_TYPE_STATEMENT_LIST: {
            size_t i;
            for(i = 0; i < p->u1.statements_node.count; i++) {
                ast_node* stmt = p->u1.statements_node.statement_list[i];
                como_compile(stmt, frame);
            }
        } 
        break;
        case AST_NODE_TYPE_WHILE: {
            Object *l = newLong((long)(O_AVAL(frame->code)->size));
            arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, l)));
            
            Object *l2 = newLong(0);
            como_compile(p->u1.while_node.condition, frame);
            arrayPushEx(frame->code, newPointer((void *)create_op(JZ, l2)));

            como_compile(p->u1.while_node.body, frame);
            arrayPushEx(frame->code, newPointer((void *)create_op(JMP, 
                    newLong(O_LVAL(l)))));
        
            Object *l3 = newLong((long)(O_AVAL(frame->code)->size));
    
            arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, 
                    l3))); 

            O_LVAL(l2) = O_LVAL(l3);
        }
        break;
        case AST_NODE_TYPE_FOR: {
            Object *l = newLong((long)(O_AVAL(frame->code)->size));
            arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, 
                    l))); 
            
            Object *l2 = newLong(0);
            como_compile(p->u1.for_node.initialization, frame);
            como_compile(p->u1.for_node.condition, frame);
            arrayPushEx(frame->code, newPointer((void *)create_op(JZ, 
                    l2))); 

            Object *l4 = newLong((long)(O_AVAL(frame->code)->size));
            /* label for the body */
            arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, 
                    l4)));    

            como_compile(p->u1.for_node.body, frame);
            
            como_compile(p->u1.for_node.final_expression, frame);

            como_compile(p->u1.for_node.condition, frame);
            arrayPushEx(frame->code, newPointer((void *)create_op(JZ, 
                    l2))); 

            arrayPushEx(frame->code, newPointer((void *)create_op(JMP, 
                    newLong(O_LVAL(l4))))); 
        
            Object *l3 = newLong((long)(O_AVAL(frame->code)->size));
    
            arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, 
                l3))); 
        
            O_LVAL(l2) = O_LVAL(l3);
        }
        break;
        case AST_NODE_TYPE_IF: {
            Object *l2 = newLong(0);
            Object *l4 = newLong(0);
            como_compile(p->u1.if_node.condition, frame);
        
            arrayPushEx(frame->code, newPointer((void *)create_op(JZ, 
                l2))); 
        

            como_compile(p->u1.if_node.b1, frame);

            arrayPushEx(frame->code, newPointer((void *)create_op(JMP, 
                    l4))); 
            
            Object *l3 = newLong((long)(O_AVAL(frame->code)->size));
        
            arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, 
                    l3))); 

            if(p->u1.if_node.b2 != NULL) {
                como_compile(p->u1.if_node.b2, frame);
            }
        
            O_LVAL(l2) = O_LVAL(l3);
            O_LVAL(l4) = (long)(O_AVAL(frame->code)->size);

            arrayPushEx(frame->code, newPointer((void *)create_op(LABEL, 
                    newLong((long)(O_AVAL(frame->code)->size))))); 

        } 
        break;
        case AST_NODE_TYPE_FUNC_DECL: { 
            const char *name = p->u1.function_node.name;
            Object *func_decl = newArray(4);
            Object *func_decl_parameters = newArray(2);
            ComoFrame *func_decl_frame = create_frame(func_decl);
            func_decl_frame->namedparameters = func_decl_parameters;

            if(frame->filename != NULL) {
                func_decl_frame->filename = copyObject(frame->filename);
            } else {
                func_decl_frame->filename = newString("<unknown>");
            }

            size_t i;
            ast_node_statements *parameters = &p->u1.function_node
                .parameter_list->u1
                .statements_node;

            for(i = 0; i < parameters->count; i++) {
                arrayPushEx(func_decl_parameters, newString(
                            AST_NODE_AS_ID(
                                parameters->statement_list[i]
                            )
                        )
                );
            }

            arrayPushEx(func_decl_frame->code, newPointer((void *)create_op(LOAD_CONST, 
                newString(name)))); 
            arrayPushEx(func_decl_frame->code, newPointer((void *)create_op(STORE_NAME, 
										newString("__FUNCTION__"))));

            como_compile(p->u1.function_node.body, func_decl_frame);

            Array *temp = O_AVAL(func_decl_frame->code);
            Object *temp2 = temp->table[temp->size - 1];

            ComoOpCode *opcode = (ComoOpCode *)(O_PTVAL(temp2));

            if(opcode->op_code != IRETURN) {
                //como_debug("automatically inserting IRETURN for function %s", name);
                arrayPushEx(func_decl_frame->code, newPointer(
                    (void *)create_op(LOAD_CONST, newLong(0L)))); 
                arrayPushEx(func_decl_frame->code, newPointer(
                    (void *)create_op(IRETURN, newLong(1L))));           
            } 

            mapInsertEx(global_frame->cf_symtab, name, newPointer(
                (void *)func_decl_frame));

            break;
        } 
        case AST_NODE_TYPE_CALL: {
            const char *name = p->u1.call_node.id->u1.id_node.name;
            const long argcount = (long)p->u1
                .call_node
                .arguments->u1
                .statements_node
                .count;

            como_compile(p->u1.call_node.arguments, frame);
            arrayPushEx(frame->code, newPointer(
                    (void *)create_op(LOAD_CONST, newLong(argcount)))); 

            arrayPushEx(frame->code, newPointer(
                    (void *)create_op(LOAD_NAME, newString(name))));

            arrayPushEx(frame->code, newPointer(
                    (void *)create_op(CALL_FUNCTION, newString(name))));

            break;
        } 
        case AST_NODE_TYPE_POSTFIX: {
            Object *name = newString(AST_NODE_AS_ID(p->u1.postfix_node.expr));
            switch(p->u1.postfix_node.type) {
                case AST_POSTFIX_OP_INC:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(POSTFIX_INC, name)));
                break;
                case AST_POSTFIX_OP_DEC:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(POSTFIX_DEC, name)));
                break;
            }
            break;
        }
        case AST_NODE_TYPE_UNARY_OP: {
            switch(p->u1.unary_node.type) {
                case AST_UNARY_OP_MINUS:
                    como_compile(p->u1.unary_node.expr, frame);
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(UNARY_MINUS, NULL)));
                break;
            }
        }
        break;
        case AST_NODE_TYPE_BIN_OP: {
            if(p->u1.binary_node.type != AST_BINARY_OP_ASSIGN) {
                como_compile(p->u1.binary_node.left, frame);
                como_compile(p->u1.binary_node.right, frame);       
            }  
            switch(p->u1.binary_node.type) {
                case AST_BINARY_OP_REM:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IREM, NULL)));
                break;  
                case AST_BINARY_OP_LTE:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IS_LESS_THAN_OR_EQUAL, NULL)));
                break;  
                case AST_BINARY_OP_GTE:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IS_GREATER_THAN_OR_EQUAL, NULL)));
                break;
                case AST_BINARY_OP_LT: 
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IS_LESS_THAN, NULL)));                    
                break;
                case AST_BINARY_OP_GT:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IS_GREATER_THAN, NULL)));  
                break;
                case AST_BINARY_OP_CMP:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IS_EQUAL, NULL)));  
                break;
                case AST_BINARY_OP_NEQ:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IS_NOT_EQUAL, NULL)));  
                break;
                case AST_BINARY_OP_MINUS: 
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IMINUS, NULL)));  
                break;
                case AST_BINARY_OP_DIV:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IDIV, NULL)));  
                break;
                case AST_BINARY_OP_ADD:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(IADD, NULL)));  
                break;
                case AST_BINARY_OP_TIMES:
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(ITIMES, NULL)));  
                break;
                case AST_BINARY_OP_ASSIGN: 
                    como_compile(p->u1.binary_node.right, frame);
                    arrayPushEx(frame->code, newPointer(
                        (void *)create_op(STORE_NAME, newString(
                            p->u1.binary_node.left->u1.id_node.name))));        
                break;
            }   
        } break;
    }
}
Example #14
0
int processXMsg( int streamId, char *readmsg,
                 RuleEngineEventParam *param, Node *node,
                 Env *env, ruleExecInfo_t *rei ) {

    char myhdr[HEADER_TYPE_LEN];
    char mymsg[MAX_NAME_LEN];
    char *outStr = NULL;
    int i, n;
    int iLevel, wCnt;
    int  ruleInx = 0;
    Region *r;
    Res *res;
    rError_t errmsg;
    errmsg.len = 0;
    errmsg.errMsg = NULL;
    r = make_region( 0, NULL );
    ParserContext *context = newParserContext( &errmsg, r );
    Pointer *e = newPointer2( readmsg );
    int rulegen = 1;
    int found;
    int grdf[2];
    int cmd = 0;
    int smallW;

    snprintf( myhdr, HEADER_TYPE_LEN - 1,   "idbug:%s", param->actionName );
    memset( mymsg, 0, sizeof( mymsg ) );

    PARSER_BEGIN( DbgCmd )
    TRY( DbgCmd )
    TTEXT2( "n", "next" );
    cmd = REDEBUG_STEP_OVER;
    OR( DbgCmd )
    TTEXT2( "s", "step" );
    cmd = REDEBUG_NEXT;
    OR( DbgCmd )
    TTEXT2( "f", "finish" );
    cmd = REDEBUG_STEP_OUT;
    OR( DbgCmd )
    TTEXT2( "b", "break" );
    TRY( Param )
    TTYPE( TK_TEXT );
    int breakPointsInx2;
    for ( breakPointsInx2 = 0; breakPointsInx2 < 100; breakPointsInx2++ ) {
        if ( breakPoints[breakPointsInx2].actionName == NULL ) {
            break;
        }
    }
    if ( breakPointsInx2 == 100 ) {
        _writeXMsg( streamId, myhdr, "Maximum breakpoint count reached. Breakpoint not set.\n" );
        cmd = REDEBUG_WAIT;
    }
    else {
        breakPoints[breakPointsInx2].actionName = strdup( token->text );
        char * base_ptr = NULL;
        TRY( loc )
        TTYPE( TK_TEXT );
        base_ptr = ( char * ) malloc( sizeof( token->text ) + 2 );
        base_ptr[0] = 'f';
        strcpy( base_ptr + 1, token->text );
        TTEXT( ":" );
        TTYPE( TK_INT );
        breakPoints[breakPointsInx2].base = strdup( base_ptr );
        breakPoints[breakPointsInx2].line = atoi( token->text );
        rodsLong_t range[2];
        char rulesFileName[MAX_NAME_LEN];
        getRuleBasePath( base_ptr, rulesFileName );

        FILE *file;
        /* char errbuf[ERR_MSG_LEN]; */
        file = fopen( rulesFileName, "r" );
        if ( file == NULL ) {
            free( context );
            deletePointer( e );
            free( base_ptr );
            return RULES_FILE_READ_ERROR;
        }
        Pointer *p = newPointer( file, base_ptr );


        if ( getLineRange( p, breakPoints[breakPointsInx2].line, range ) == 0 ) {
            breakPoints[breakPointsInx2].start = range[0];
            breakPoints[breakPointsInx2].finish = range[1];
        }
        else {
            breakPoints[breakPointsInx2].actionName = NULL;
        }
        deletePointer( p );
        OR( loc )
        TTYPE( TK_INT );
        if ( node != NULL ) {
            breakPoints[breakPointsInx2].base = strdup( node->base );
            breakPoints[breakPointsInx2].line = atoi( token->text );
            rodsLong_t range[2];
            Pointer *p = newPointer2( breakPoints[breakPointsInx2].base );
            if ( getLineRange( p, breakPoints[breakPointsInx2].line, range ) == 0 ) {
                breakPoints[breakPointsInx2].start = range[0];
                breakPoints[breakPointsInx2].finish = range[1];
            }
            else {
                breakPoints[breakPointsInx2].actionName = NULL;
            }
            deletePointer( p );
        }
        else {
            breakPoints[breakPointsInx2].actionName = NULL;
        }
        OR( loc )
        /* breakPoints[breakPointsInx].base = NULL; */
        END_TRY( loc )

        free( base_ptr );
        if ( breakPoints[breakPointsInx2].actionName != NULL )
            snprintf( mymsg, MAX_NAME_LEN, "Breakpoint %i  set at %s\n", breakPointsInx2,
                      breakPoints[breakPointsInx2].actionName );
        else {
            snprintf( mymsg, MAX_NAME_LEN, "Cannot set breakpoint, source not available\n" );
        }
        _writeXMsg( streamId, myhdr, mymsg );
        if ( breakPointsInx <= breakPointsInx2 ) {
            breakPointsInx = breakPointsInx2 + 1;
        }
        cmd = REDEBUG_WAIT;
    }
    OR( Param )
    NEXT_TOKEN_BASIC;
    _writeXMsg( streamId, myhdr, "Unknown parameter type.\n" );
    cmd = REDEBUG_WAIT;
    OR( Param )
    _writeXMsg( streamId, myhdr, "Debugger command \'break\' requires at least one argument.\n" );
    cmd = REDEBUG_WAIT;
    END_TRY( Param )

    OR( DbgCmd )
    TRY( Where )
    TTEXT2( "w", "where" );
    smallW = 1;
    OR( Where )
    TTEXT2( "W", "Where" );
    smallW = 0;
    END_TRY( Where )
    wCnt = 20;
    OPTIONAL_BEGIN( Param )
    TTYPE( TK_INT );
    wCnt = atoi( token->text );
    OPTIONAL_END( Param )
    iLevel = 0;

    i = reDebugStackCurrPtr - 1;
    while ( i >= 0 && wCnt > 0 ) {
        if ( !smallW || ( reDebugPCType( ( RuleEngineEvent ) reDebugStackCurr[i].label ) & 1 ) != 0 ) {
            snprintf( myhdr, HEADER_TYPE_LEN - 1,   "idbug: Level %3i", iLevel );
            char msg[HEADER_TYPE_LEN - 1];
            RuleEngineEventParam param;
            param.ruleIndex = 0;
            param.actionName = reDebugStackCurr[i].step;
            printRuleEngineEventLabel( msg, HEADER_TYPE_LEN - 1, ( RuleEngineEvent ) reDebugStackCurr[i].label, &param );
            _writeXMsg( streamId,  myhdr, msg );
            if ( reDebugStackCurr[i].label != EXEC_ACTION_BEGIN ) {
                iLevel++;
            }
            wCnt--;
        }
        i--;
    }
    OR( DbgCmd )
    TTEXT2( "l", "list" );
    TRY( Param )
    TTEXT2( "r", "rule" );
    TRY( ParamParam )
    TTYPE( TK_TEXT );

    mymsg[0] = '\n';
    mymsg[1] = '\0';
    snprintf( myhdr, HEADER_TYPE_LEN - 1,   "idbug: Listing %s", token->text );
    RuleIndexListNode *node;
    found = 0;
    while ( findNextRule2( token->text, ruleInx, &node ) != NO_MORE_RULES_ERR ) {
        found = 1;
        if ( node->secondaryIndex ) {
            n = node->condIndex->valIndex->len;
            int i;
            for ( i = 0; i < n; i++ ) {
                Bucket *b = node->condIndex->valIndex->buckets[i];
                while ( b != NULL ) {
                    RuleDesc *rd = getRuleDesc( *( int * )b->value );
                    char buf[MAX_RULE_LEN];
                    ruleToString( buf, MAX_RULE_LEN, rd );
                    snprintf( mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ), "%i: %s\n%s\n", node->ruleIndex, rd->node->base[0] == 's' ? "<source>" : rd->node->base + 1, buf );
                    b = b->next;
                }
            }
        }
        else {
            RuleDesc *rd = getRuleDesc( node->ruleIndex );
            char buf[MAX_RULE_LEN];
            ruleToString( buf, MAX_RULE_LEN, rd );
            snprintf( mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ), "\n  %i: %s\n%s\n", node->ruleIndex, rd->node->base[0] == 's' ? "<source>" : rd->node->base + 1, buf );
        }
        ruleInx ++;
    }
    if ( !found ) {
        snprintf( mymsg, MAX_NAME_LEN, "Rule %s not found\n", token->text );
    }
    _writeXMsg( streamId, myhdr, mymsg );
    cmd = REDEBUG_WAIT;
    OR( ParamParam )
    _writeXMsg( streamId, myhdr, "Debugger command \'list rule\' requires one argument.\n" );
    cmd = REDEBUG_WAIT;
    END_TRY( ParamParam )
    OR( Param )
    TTEXT2( "b", "breakpoints" );
    snprintf( myhdr, HEADER_TYPE_LEN - 1,   "idbug: Listing %s", token->text );
    mymsg[0] = '\n';
    mymsg[1] = '\0';
    for ( i = 0; i < breakPointsInx; i++ ) {
        if ( breakPoints[i].actionName != NULL ) {
            if ( breakPoints[i].base != NULL ) {
                snprintf( mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ), "Breaking at BreakPoint %i:%s %s:%d\n", i , breakPoints[i].actionName, breakPoints[i].base[0] == 's' ? "<source>" : breakPoints[i].base + 1, breakPoints[i].line );
            }
            else {
                snprintf( mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ), "Breaking at BreakPoint %i:%s\n", i , breakPoints[i].actionName );
            }
        }
    }
    _writeXMsg( streamId, myhdr, mymsg );
    cmd = REDEBUG_WAIT;
    OR( Param )
    TTEXT( "*" );
    snprintf( myhdr, HEADER_TYPE_LEN - 1,   "idbug: Listing %s", token->text );
    Env *cenv = env;
    mymsg[0] = '\n';
    mymsg[1] = '\0';
    found = 0;
    while ( cenv != NULL ) {
        n = cenv->current->size;
        for ( i = 0; i < n; i++ ) {
            Bucket *b = cenv->current->buckets[i];
            while ( b != NULL ) {
                if ( b->key[0] == '*' ) { /* skip none * variables */
                    found = 1;
                    char typeString[128];
                    typeToString( ( ( Res * )b->value )->exprType, NULL, typeString, 128 );
                    snprintf( mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ), "%s of type %s\n", b->key, typeString );
                }
                b = b->next;
            }
        }
        cenv = cenv->previous;
    }
    if ( !found ) {
        snprintf( mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ), "<empty>\n" );
    }
    _writeXMsg( streamId, myhdr, mymsg );
    cmd = REDEBUG_WAIT;
    OR( Param )
    syncTokenQueue( e, context );
    skipWhitespace( e );
    ABORT( lookAhead( e, 0 ) != '$' );
    snprintf( myhdr, HEADER_TYPE_LEN - 1,   "idbug: Listing %s", token->text );
    mymsg[0] = '\n';
    mymsg[1] = '\0';
    Hashtable *vars = newHashTable( 100 );
    for ( i = 0; i < coreRuleVarDef .MaxNumOfDVars; i++ ) {
        if ( lookupFromHashTable( vars, coreRuleVarDef.varName[i] ) == NULL ) {
            snprintf( &mymsg[strlen( mymsg )], MAX_NAME_LEN - strlen( mymsg ), "$%s\n", coreRuleVarDef.varName[i] );
            insertIntoHashTable( vars, coreRuleVarDef.varName[i], coreRuleVarDef.varName[i] );
        }
    }
    deleteHashTable( vars, NULL );
    _writeXMsg( streamId, myhdr, mymsg );
    cmd = REDEBUG_WAIT;
    OR( Param )
    NEXT_TOKEN_BASIC;
    _writeXMsg( streamId, myhdr, "Unknown parameter type.\n" );
    cmd = REDEBUG_WAIT;
    OR( Param )
    _writeXMsg( streamId, myhdr, "Debugger command \'list\' requires at least one argument.\n" );
    cmd = REDEBUG_WAIT;
    END_TRY( Param )
    OR( DbgCmd )
    TTEXT2( "c", "continue" );
    cmd = REDEBUG_STEP_CONTINUE;
    OR( DbgCmd )
    TTEXT2( "C", "Continue" );
    cmd = REDEBUG_CONTINUE_VERBOSE;
    OR( DbgCmd )
    TTEXT2( "del", "delete" );
    TRY( Param )
    TTYPE( TK_INT );
    n = atoi( token->text );
    if ( breakPoints[n].actionName != NULL ) {
        free( breakPoints[n].actionName );
        if ( breakPoints[n].base != NULL ) {
            free( breakPoints[n].base );
        }
        breakPoints[n].actionName = NULL;
        breakPoints[n].base = NULL;
        snprintf( mymsg, MAX_NAME_LEN, "Breakpoint %i  deleted\n", n );
    }
    else {
        snprintf( mymsg, MAX_NAME_LEN, "Breakpoint %i  has not been defined\n", n );
    }
    _writeXMsg( streamId, myhdr, mymsg );
    cmd = REDEBUG_WAIT;
    OR( Param )
    _writeXMsg( streamId, myhdr, "Debugger command \'delete\' requires one argument.\n" );
    cmd = REDEBUG_WAIT;
    END_TRY( Param )
    OR( DbgCmd )
    TTEXT2( "p", "print" );
    Node *n = parseTermRuleGen( e, 1, context );
    if ( getNodeType( n ) == N_ERROR ) {
        errMsgToString( context->errmsg, mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ) );
    }
    else {
        snprintf( myhdr, HEADER_TYPE_LEN - 1,   "idbug: Printing " );
        char * ptr = myhdr + strlen( myhdr );
        i = HEADER_TYPE_LEN - 1 - strlen( myhdr );
        termToString( &ptr, &i, 0, MIN_PREC, n, 0 );
        snprintf( ptr, i, "\n" );
        if ( env != NULL ) {
            disableReDebugger( grdf );
            res = computeNode( n, NULL, regionRegionCpEnv( env, r, ( RegionRegionCopyFuncType * ) regionRegionCpNode ), rei, 0, &errmsg, r );
            enableReDebugger( grdf );
            outStr = convertResToString( res );
            snprintf( mymsg, MAX_NAME_LEN, "%s\n", outStr );
            free( outStr );
            if ( getNodeType( res ) == N_ERROR ) {
                errMsgToString( &errmsg, mymsg + strlen( mymsg ), MAX_NAME_LEN - strlen( mymsg ) );
            }
        }
        else {
            snprintf( mymsg, MAX_NAME_LEN, "Runtime environment: <empty>\n" );
        }
    }
    _writeXMsg( streamId, myhdr, mymsg );

    cmd = REDEBUG_WAIT;
    OR( DbgCmd )
    TTEXT2( "d", "discontinue" );
    cmd = REDEBUG_WAIT;
    OR( DbgCmd )
    snprintf( mymsg, MAX_NAME_LEN, "Unknown Action: %s", readmsg );
    _writeXMsg( streamId, myhdr, mymsg );
    cmd = REDEBUG_WAIT;
    END_TRY( DbgCmd )
    PARSER_END( DbgCmd )
    freeRErrorContent( &errmsg );
    region_free( r );
    deletePointer( e );
    free( context );
    return cmd;
}