/** * extend_heap - Extend the heap by number of bytes adjusted_size. * * This differs from the example extend_heap function in that the parameter * passed is in BYTES rather than WORDS. Constantly converting between the two * is confusing and unnecessary. * * Furthermore, it should be a size already adjusted to fit byte and header * alignment. This function merely sets header/footer/successor as needed. */ static void *extend_heap(size_t adjusted_size) { char *bp; size_t prev_alloc; TRACE("Entering extend_heap(adjusted_size=%u)\n", adjusted_size); if ((long)(bp = mem_sbrk(adjusted_size)) == -1) return NULL; /* Initialize free block header/footer and the epilogue header. heap_end points to one byte before the next payload, so reading the PREVALLOC field of heap_end + 1 will yield the actual prev-alloc for the block just before the end of the heap. */ prev_alloc = GET_PREVALLOC(heap_end + 1); /* Free block header */ PUTW(GET_BLOCKHDR(bp), PACK(adjusted_size, prev_alloc)); /* Free block header */ PUTW(GET_BLOCKFTR(bp), PACK(adjusted_size, prev_alloc)); /* New epilogue header */ PUTW(GET_BLOCKHDR(GET_NEXTBLOCK(bp)), PACK(0xEA7F00D0, THISALLOC)); heap_end = mem_heap_hi(); TRACE("<<<---Leaving extend_heap() with a call to coalesce()\n"); /* Coalesce if the previous block was free */ return coalesce(bp); /* coalesce handles adding block to free list */ }
void DoFixOffs(FIXOFFS *fix) { S32 value,newoffset; if(fix) { while(fix) { value = GetLabelObjectOffset(fix->data, fix->type); if(fix->size==FIXOFFS_NEAR) { newoffset = (S32)value-fix->org; if(newoffset<-128||newoffset>127) { errorf(fix->filename,fix->line,ERR_FIXOFFSNEAR,GetLabelObjectName(fix->data, fix->type)); } else PUTB(fix->ptr, (U8)newoffset); } else if(fix->size==FIXOFFS_FAR) { PUTW(fix->ptr, (U16)value); } else if(fix->size==FIXOFFS_WORD) { PUTW(fix->ptr, (U16)value); } else if(fix->size==FIXOFFS_BYTE) { PUTB(fix->ptr, (U8)value); } else { newoffset = AccOpNum(fix->size-FIXOFFS_ARITH, (U16)value); PUTB(fix->ptr, (U8)newoffset); } fix = fix->prev; } } }
/** * free_block - Mark block at specified address as free. * Payload remains intact until later overwritten. */ static void free_block(void *bp, size_t adjusted_size) { size_t size; size_t is_prev_alloc; TRACE(">>>Entering free_block(bp=0x%X, adjusted_size=%u)\n", (unsigned int)bp, adjusted_size); is_prev_alloc = GET_PREVALLOC(bp); size = GET_THISSIZE(bp); PUTW(GET_BLOCKHDR(bp), PACK(size, is_prev_alloc)); PUTW(GET_BLOCKFTR(bp), PACK(size, is_prev_alloc)); TRACE("<<<---Leaving free_block()\n"); }
/** * allocate - Place block, i.e. write header and footer. */ static void allocate(void *bp, size_t adjusted_size) { size_t csize = GET_THISSIZE(bp); size_t is_prev_alloc = GET_PREVALLOC(bp); TRACE(">>>Entering allocate(bp=0x%X, adjusted_size=%u)\n", (unsigned int)bp, adjusted_size); /* We will always need to remove tshi block from the free list */ remove_from_list(bp, calc_list_index(csize)); /* See if there's room to split this block into two */ if ((csize - adjusted_size) >= (MIN_SIZE)) { PUTW(GET_BLOCKHDR(bp), PACK(adjusted_size, THISALLOC | is_prev_alloc)); PUTW(GET_BLOCKFTR(bp), PACK(adjusted_size, THISALLOC | is_prev_alloc)); /* Using the new header info, mark the newly created block as free */ bp = GET_NEXTBLOCK(bp); PUTW(GET_BLOCKHDR(bp), PACK(csize - adjusted_size, PREVALLOC)); PUTW(GET_BLOCKFTR(bp), PACK(csize - adjusted_size, PREVALLOC)); /* And add it to the appropriate free list */ coalesce(bp); } else {/* If there's not room to create split the block, just extend the amount to allocated */ PUTW(GET_BLOCKHDR(bp), PACK(csize, THISALLOC | is_prev_alloc)); PUTW(GET_BLOCKFTR(bp), PACK(csize, THISALLOC | is_prev_alloc)); /* Make sure the next block's header has the prevalloc field marked */ bp = GET_BLOCKHDR(GET_NEXTBLOCK(bp)); PUTW(bp, GETW(bp) | PREVALLOC); } TRACE("<<<---Leaving allocate()\n"); }
/** * coalesce - Concatenate adjacent blocks to prevent fragmentation. * * Should upkeep the free list. Assumes that bp is a free block. * Also assumes that bp has not yet been added to a free list. */ static void *coalesce(void *bp) { size_t prev_alloc = GET_PREVALLOC(bp); size_t next_alloc = GET_NEXTALLOC(bp); size_t size = GET_THISSIZE(bp); char *next_block = GET_NEXTBLOCK(bp); char *prev_block = GET_PREVBLOCK(bp); TRACE(">>>Entering coalesce(bp=0x%X)\n", (unsigned int)bp); /* Case 1, Both blocks allocated, does not need its own if statement */ if (prev_alloc && !next_alloc) { /* Case 2: only next_block is free */ remove_from_list(next_block, calc_list_index(GET_THISSIZE(next_block))); /* Only need to update the size field */ size += GET_SIZE(GET_BLOCKHDR(next_block)); PUTW(GET_BLOCKHDR(bp), PACK(size, prev_alloc)); PUTW(GET_BLOCKFTR(bp), PACK(size, prev_alloc)); } else if (!prev_alloc && next_alloc) { /* Case 3: only prev_block is free */ remove_from_list(prev_block, calc_list_index(GET_THISSIZE(prev_block))); /* Need to update the size and prev_alloc field */ size += GET_THISSIZE(prev_block); prev_alloc = GET_PREVALLOC(prev_block); PUTW(GET_BLOCKFTR(bp), PACK(size, prev_alloc)); PUTW(GET_BLOCKHDR(prev_block), PACK(size, prev_alloc)); bp = prev_block; } else if (!prev_alloc && !next_alloc) { /* Case 4: Both blocks are free */ remove_from_list(next_block, calc_list_index(GET_THISSIZE(next_block))); remove_from_list(prev_block, calc_list_index(GET_THISSIZE(prev_block))); /* Need to update the size and prev_alloc field */ size += GET_THISSIZE(prev_block) + GET_THISSIZE(next_block); prev_alloc = GET_PREVALLOC(prev_block); PUTW(GET_BLOCKHDR(GET_PREVBLOCK(bp)), PACK(size, prev_alloc)); PUTW(GET_BLOCKFTR(GET_NEXTBLOCK(bp)), PACK(size, prev_alloc)); bp = GET_PREVBLOCK(bp); } /* coalesce() is always called after a block is marked free so it needs to add the block to the appropriate free list */ add_to_list(bp, calc_list_index(size)); TRACE("<<<---Leaving coalesce()\n"); return bp; }
/** * mm_init - Initialize the malloc package. */ int mm_init(void) { TRACE(">>>Entering mm_init()\n"); mem_init(); #ifdef DO_MM_CHECK /* initialize the ENTIRE heap provided by memlib to 0x00 */ memset(mem_heap_lo(), 0, MAX_HEAP); #endif /*Each element in free_lists starts off as the empty head of a linked list*/ memset(free_lists, (int)NULL, sizeof(free_lists)); /* Initialize write-once variables */ PAGE_SIZE = mem_pagesize(); ADJUSTED_PAGESIZE = ADJUST_BYTESIZE((PAGE_SIZE*2)); /* Initially allocate 1 page of memory plus room for the prologue and epilogue blocks and free block header */ if((heap_start = mem_sbrk(ADJUSTED_PAGESIZE + (4 * WSIZE))) == NULL) return -1; heap_end = mem_heap_hi(); /* Alignment word */ PUTW(heap_start, 0x8BADF00D); /* Prologue header */ PUTW(heap_start + (1 * WSIZE), PACK(DSIZE, THISALLOC | PREVALLOC)); PUTW(heap_start + (2 * WSIZE), PACK(DSIZE, THISALLOC | PREVALLOC)); /* Epilogue header */ PUTW(heap_start + ADJUSTED_PAGESIZE + 3 * WSIZE, PACK(0xEA7F00D0, THISALLOC)); /* Setup initial free block */ PUTW(heap_start + (3 * WSIZE), PACK(ADJUSTED_PAGESIZE, PREVALLOC)); PUTW((heap_end - WSIZE + 1) - WSIZE, PACK(ADJUSTED_PAGESIZE, PREVALLOC)); add_to_list(heap_start + (4 * WSIZE), calc_list_index(ADJUSTED_PAGESIZE)); RUN_MM_CHECK(); TRACE("<<<---Leaving mm_init()\n"); return 0; }
BOOL FASTCALL comProc_IfLoop(U16 flags, S16 *brackCnt) { BOOL BRACK=FALSE,FAR_BRANCH=FALSE,FLIPOP; S32 start,whilestart,offset; BANK *bank; U8 *condPtr,*elsePtr; int index,mode; CheckCurBank(); if((mode=StrInStrint(szTemp,siIffys))!=-1) { if(mode==IFMODE_DOWHILE) { bank = curBank; start = GetBankOffset(); if(STRCMP(GetNextWord(),"while")) { // 'ist der code block! GetCode(flags|CF_BRACEOK, brackCnt); if(STRCMP(GetNextWord(),"while")) error(ERR_WHILEEXP,szTemp); } } if(GetNextWord()[0]!='(') error(ERR_INVCOND,szTemp); else { GetNextWord(); BRACK = TRUE; } USE_DEFS = FALSE; if(!STRCMP(szTemp,"far")) { FAR_BRANCH = TRUE; GetNextWord(); } else if(!STRCMP(szTemp,"near")) { GetNextWord(); } // parse the "is" "is not" "not" "no", etc. FLIPOP = FALSE; while((index=StrInStrint(szTemp,siIsNot))!=-1) { if(!siIsNot[index].index) FLIPOP = !FLIPOP; GetNextWord(); } USE_DEFS = TRUE; if(!PRECOMPILING) { if((index=StrInStrint(szTemp,siConditions))==-1) { error(ERR_INVALIDCOND,szTemp); condPtr = NULL; } else { if(mode==IFMODE_IF || mode==IFMODE_WHILE) FLIPOP = !FLIPOP; index = (FLIPOP)? RelSwapOp(siConditions[index].index): siConditions[index].index; if(mode==IFMODE_WHILE) whilestart = GetBankOffset(); if(FAR_BRANCH) { WriteOpcodeB(RelSwapOp(index),3); WriteOpcode(opJMP_ABS); condPtr = curBank->ptr; WriteCodeW(0); } else { condPtr = curBank->ptr+1; WriteOpcodeB(index,0); } } if(mode!=IFMODE_DOWHILE) { bank = curBank; start = GetBankOffset(); } } if(BRACK && GetNextWord()[0]!=')') { error(ERR_IFCONDCLOSEEXP,szTemp); } if(mode!=IFMODE_DOWHILE) GetCode(flags|CF_BRACEOK|CF_GETNEXTWORD, brackCnt); elsePtr = NULL; if(!STRCMP(PeekNextWord(),"else")) { GetNextWord(); if(mode!=IFMODE_IF) error(ERR_ONLYIFSELSE); else { if(!PRECOMPILING) WriteOpcode(opJMP_ABS); elsePtr = curBank->ptr; if(!PRECOMPILING) WriteCodeW(0); } } if(!PRECOMPILING) { if(bank != curBank) error(ERR_FOREVEROUTOFBANK,bank->label,curBank->label); else if(condPtr) { if(mode==IFMODE_WHILE) { WriteOpcodeW(opJMP_ABS,whilestart); } if(FAR_BRANCH) { if(mode==IFMODE_DOWHILE) { PUTW(condPtr,start); } else { PUTW(condPtr,GetBankOffset()); } } else { offset = mode==IFMODE_DOWHILE? start-GetBankOffset(): GetBankOffset()-start; if((offset<-128 || offset>127)) error(ERR_BRANCHOUTOFRANGE); else PUTB(condPtr,(U8)offset); } } } if(elsePtr) { GetCode(flags|CF_BRACEOK|CF_GETNEXTWORD, brackCnt); if(!PRECOMPILING) PUTW(elsePtr,GetBankOffset()); } } else if(!STRCMP(szTemp,"forever")) { bank = curBank; start = GetBankOffset(); GetCode(flags|CF_BRACEOK|CF_GETNEXTWORD, brackCnt); if(bank != curBank) error(ERR_FOREVEROUTOFBANK,bank->label,curBank->label); else WriteOpcodeW(opJMP_ABS,start); } else return FALSE; return TRUE; }
/******************************************************************* KF 6/14/90 write_pixmap_file(display, filename, pm, width, height) and write_pixmap_file_xy(display, filename, pm, x, y, width, height) has been merged into one function. INPUT: display dsp, screen s, file name fn to write the file in, window id wid where pixmap is, upper left corner x, y of original pixmap, width and height of pixmap OUTPUT: binary file with data PURPOSE: write_pixmap_file gets the image structure of the input pixmap, convert the image data with the permutation color vector, writes the image structure out to filename. Note that writing out a Z pixmap is 8x faster than XY pixmap. This is because XY writes out each pixel value per plane, thus number of bits; Z writes out each pixel, or 8 bits at a time. The XY format may have been chosen for a reason -- I don't know. ********************************************************************/ void write_pixmap_file(Display *dsp, int scr, char *fn, Window wid, int x, int y, int width,int height) { XImage *xi; FILE *file; int *permVector; int num; int num_colors; /* get color map and permutation vector */ if ((num_colors = makePermVector(dsp, scr,(unsigned long **)&permVector)) < 0) { printf("num_colors < 0!!\n"); exit(-1); } /* reads image structure in ZPixmap format */ xi = XGetImage(dsp, wid, x, y, width, height, AllPlanes, ZPixmap); file = fopen(fn, "wb"); if (file == NULL) { perror("opening pixmap file for write"); exit(-1); } #define PUTW(a,b) putw(htonl(a),b) PUTW(xi->width, file); PUTW(xi->height, file); PUTW(xi->xoffset, file); PUTW(xi->format, file); PUTW(xi->byte_order, file); PUTW(xi->bitmap_unit, file); PUTW(xi->bitmap_bit_order, file); PUTW(xi->bitmap_pad, file); PUTW(xi->depth, file); PUTW(xi->bytes_per_line, file); PUTW(xi->bits_per_pixel, file); PUTW(xi->red_mask, file); PUTW(xi->green_mask, file); PUTW(xi->blue_mask, file); num = xi->bytes_per_line * height; /* total number of pixels in pixmap */ /* store value from permutation */ { int ii, jj; for (ii = 0; ii < width; ii++) for (jj = 0; jj < height; jj++) { XPutPixel(xi, ii, jj, permVector[(int) XGetPixel(xi, ii, jj)]); } } fwrite(xi->data, 1, num, file); fclose(file); }