Example #1
0
static int Compiler_compileWhileNode(Context* context, Node* node) {
    int start = Block_position(context->block) - 1;
    Reg cond = Compiler_compile(context, node->left);

    int cond_jmp = Block_append(context->block, OP_JNS, cond, 0) + 2;
    Compiler_compile(context, node->right);

    int diff = start - Block_position(context->block);
    int end = Block_append(context->block, OP_JMP, diff);
    Block_replace(context->block, cond_jmp, end);

    return cond;
}
Example #2
0
static int Compiler_compileTryNode(Context* context, Node* node) {
    int catch_jmp = Block_append(context->block, OP_TRY, 0) + 1;
    int ret = Compiler_compile(context, node->left);
    Block_append(context->block, OP_ENDTRY);

    int skip_catch = Block_append(context->block, OP_JMP, 0) + 1;

    int diff;
    diff = Block_position(context->block) - catch_jmp;
    Block_replace(context->block, catch_jmp, diff);

    Compiler_compile(context, node->right);

    diff = Block_position(context->block) - skip_catch;
    Block_replace(context->block, skip_catch, diff);

    return ret;
}
Example #3
0
static int Compiler_compileIfNode(Context* context, Node* node) {
    int diff;
    Reg res = context->reg++;

    // compile condition
    Reg cond = Compiler_compile(context, node->left);
    int cond_jmp = Block_append(context->block, OP_JNS, cond, 0) + 2;

    if (node->right->tag == ElseNode) {
        Reg res_a = Compiler_compile(context, node->right->left);
        Block_append(context->block, OP_MOV, res, res_a);
    }
    else {
        Reg res_a = Compiler_compile(context, node->right);
        Block_append(context->block, OP_MOV, res, res_a);
    }

    // add jump to the end
    int end_jmp = Block_append(context->block, OP_JMP, 0) + 1;

    // change condition jump to this position
    diff = Block_position(context->block) - cond_jmp + 1;
    Block_replace(context->block, cond_jmp, diff);

    if (node->right->tag == ElseNode) {
        Reg res_b = Compiler_compile(context, node->right->right);
        Block_append(context->block, OP_MOV, res, res_b);
    }
    else {
        Block_append(context->block, OP_NIL, res);
    }

    // change end jump to this position
    diff = Block_position(context->block) - end_jmp;
    Block_replace(context->block, end_jmp, diff);

    return res;
}
Example #4
0
SOLOCAL int
DiskFile_write(DiskFile *self, Image *image,
        const BlockPosition *startPosition)
{
    const BlockPosition inval = { 0, 0 };
    const BlockPosition *start, *current;
    IBlockAllocator *alloc = Image_allocator(image);
    uint8_t *contentPos = self->content;
    size_t toWrite = self->size;
    int writereserved = 0;

    uint8_t *blockData;
    Block *block, *nextBlock;
    size_t blockWrite;

    if (!toWrite)
    {
        start = &inval;
        goto DiskFile_write_done;
    }

    alloc->setInterleave(alloc, self->interleave);
    alloc->setConsiderReserved(alloc, 0);

    if (startPosition && startPosition->track)
    {
        /* fixed start position requested */
        nextBlock = Image_allocateAt(image, startPosition);
    }
    else
    {
        /* automatic start position requested, use allocator */
        nextBlock = alloc->allocFirstBlock(alloc);
        if (!nextBlock)
        {
            writereserved = 1;
            alloc->setConsiderReserved(alloc, 1);
            nextBlock = alloc->allocFirstBlock(alloc);
        }
    }

    if (!nextBlock) return 0;

    start = Block_position(nextBlock);
    current = start;
    self->blocks = 1;

    do
    {
        block = nextBlock;
        blockWrite = (toWrite > BLOCK_SIZE) ? BLOCK_SIZE : toWrite;
        toWrite -= blockWrite;
        blockData = Block_data(block);
        DBGd2("writing file", current->track, current->sector);
        memcpy(blockData, contentPos, blockWrite);
        if (toWrite)
        {
            nextBlock = alloc->allocNextBlock(alloc, current);
            if (!nextBlock && !writereserved)
            {
                writereserved = 1;
                alloc->setConsiderReserved(alloc, 1);
                nextBlock = alloc->allocNextBlock(alloc, current);
            }
            if (!nextBlock)
            {
                Block_setNextTrack(block, 0);
                _rollbackWrite(image, start);
                return 0;
            }
            current = Block_position(nextBlock);
            Block_setNextTrack(block, current->track);
            Block_setNextSector(block, current->sector);
            contentPos += blockWrite;
            ++(self->blocks);
        }
        else
        {
            Block_setNextTrack(block, 0);
            Block_setNextSector(block, blockWrite + 1);
        }
    } while (toWrite);

DiskFile_write_done:
    FileMap_add(Image_fileMap(image), self, start);

    ModRepo_allFileWritten(Mkd64_modRepo(MKD64), self, start);

    return 1;
}
Example #5
0
static void
reserveDirSlot(Cbmdos *self)
{
    Block *nextBlock;
    BlockPosition pos;
    DirBlock *tmp;

    if (self->flags & CDFL_SLOTRESERVED) return;

    ++(self->currentDirSlot);
    if (self->currentDirSlot > 7)
    {
        if (self->directory)
        {
            nextBlock = Image_block(self->image, &(self->directory->pos));
            Block_allocate(nextBlock);
            tmp = self->directory;
            self->directory = tmp->next;
            free(tmp);
        }
        else
        {
            if (self->currentDirBlock)
            {
                pos.track = Block_position(self->currentDirBlock)->track;
                pos.sector = Block_position(self->currentDirBlock)->sector;
            }
            else
            {
                pos.track = 0;
                pos.sector = 0;
            }
            if (nextDirBlock(self, &pos, 1))
            {
                DBGd2("cbmdos: allocated extra directory block",
                        pos.track, pos.sector);
                nextBlock = Image_block(self->image, &pos);
                ++(self->extraDirBlocks);
            }
            else
            {
                fputs("[cbmdos] ERROR: no space left for directory!\n", stderr);
                --(self->currentDirSlot);
                self->flags |= CDFL_DIROVERFLOW;
                return;
            }
        }
        if (self->currentDirBlock)
        {
            Block_setNextTrack(self->currentDirBlock,
                    Block_position(nextBlock)->track);
            Block_setNextSector(self->currentDirBlock,
                    Block_position(nextBlock)->sector);
        }
        self->currentDirBlock = nextBlock;
        memset(Block_rawData(self->currentDirBlock), 0, 256);
        self->currentDirSlot = 0;
        ++(self->usedDirBlocks);
    }
    self->flags |= CDFL_SLOTRESERVED;
}