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; }
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; }
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; }
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; }
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; }