/* newsegment - create a new segment (only called here and in xlimage.c) */ SEGMENT *newsegment(int n) { SEGMENT *newseg; /* allocate the new segment */ if ((newseg = (SEGMENT *)calloc(1,segsize(n))) == NULL) return (NULL); /* initialize the new segment */ newseg->sg_size = n; newseg->sg_next = NULL; if (segs) lastseg->sg_next = newseg; else segs = newseg; lastseg = newseg; /* update the statistics */ total += (long)segsize(n); nnodes += (long)n; nfree += (long)n; ++nsegs; /* return the new segment */ return (newseg); }
// // Free empty segments // LOCAL void freesegs() { SEGMENT *seg; SEGMENT *next; // Free up as many nodes as possible gc(); // Reset free node tracking fnodes = NIL; nfree = 0L; // Reset the last segment pointer lastseg = NULL; // Scan all segments for (seg = segs; seg != NULL; seg = next) { int n = seg->sg_size; int empty = TRUE; int i; LVAL p; // Check this segment for in-use nodes p = &seg->sg_nodes[0]; for (i = n; --i >= 0; ++p) { if (ntype(p) != FREE_NODE) { empty = FALSE; break; } } // Retain pointer to next segment next = seg->sg_next; // Was the current segment empty? if (empty) { // Free the segment; free((void *) seg); // Unlink it from the list. No need to worry about a NULL lastseg // pointer here since the fixnum and char segments will always exist // at the head of the list and they will always have nodes. So, lastseg // will have been set before we find any empty nodes. lastseg->sg_next = next; // Reduce the stats total -= (long) segsize(n); nsegs--; nnodes -= n; } else { // Not empty, so remember this node as the last segment lastseg = seg; // Add all of the free nodes in this segment to the free list p = &seg->sg_nodes[0]; for (i = n; --i >= 0; ++p) { if (ntype(p) == FREE_NODE) { rplaca(p, NIL); rplacd(p, fnodes); fnodes = p; nfree++; } } } } }
int main(){ int t,n; scanf("%u",&t); while(t--){ switch(scanf("\n"),getchar()){ case 'M'://Move k scanf("ove %u",&n); for(curseg=head->next; curseg!=null&&n>=segsize(*curseg); n-=segsize(*curseg),curseg=curseg->next); cur=curseg->begin+n; break; case 'I'://Insert n endl S scanf("nsert %u",&n); if(cur>curseg->begin){ new segment(curseg->begin,cur,curseg->last,curseg); curseg->begin=cur; } cur=newc; while(n--){ while((*newc=getchar())=='\n'); newc++; } curseg=new segment(cur,newc,curseg->last,curseg); break; case 'D'://Delete n scanf("elete %u",&n); if(cur!=curseg->begin){ new segment(curseg->begin,cur,curseg->last,curseg); curseg->begin=cur; } while(curseg!=null&&n>=segsize(*curseg)){ n-=segsize(*curseg); curseg=curseg->next; delete curseg->last; } cur=curseg->begin+=n; break; case 'G'://Get n scanf("et %u",&n); tmpcur=cur; tmpcurseg=curseg; while(curseg!=null&&n>=curseg->end-cur){ n-=curseg->end-cur; fwrite(cur,1,curseg->end-cur,stdout); curseg=curseg->next; cur=curseg->begin; } fwrite(cur,1,n,stdout); putchar('\n'); curseg=tmpcurseg; cur=tmpcur; break; case 'P'://Prev scanf("rev"); if(cur!=curseg->begin) cur--; else curseg=curseg->last,cur=curseg->end-1; break; case 'N'://Next scanf("ext"); if(++cur==curseg->end) curseg=curseg->next,cur=curseg->begin; break; } } }