int do_command(void) { const char *cmd; int i; char lbuf[10]; cmd = word + 1; /* Comments don't need the space */ if (strncmp(cmd, "\\\"", 2) == 0) cmd = "\\\""; for (i = 0; cmd_list[i].cmd[0]; i++) { if (strcmp(cmd_list[i].cmd, cmd) == 0) break; } if (cmd_list[i].cmd[0] == 0) { if (verbose) { strncpy(lbuf, cmd, 3); lbuf[3] = 0; line_break(); i = left_indent; left_indent = 0; strcpy(word, "**** Unknown formatter command: ."); strcat(word, lbuf); print_word(word); line_break(); left_indent = i; } i = 0; /* Treat as comment */ } switch (cmd_list[i].class) { case 1: /* Parametered commands */ return do_argvcmd(cmd_list[i].id); case 2: /* Font changers */ return do_fontwords(cmd_list[i].id / 10, cmd_list[i].id % 10, 0); case 3: /* .so */ fetch_word(); strcat(man_file, word); close_page(); if (find_page(man_file, (char *) 0) < 0) { fprintf(stderr, "Cannot open .so file %s\n", word); return -1; } ungetc('\r', ifd); break; default: do_skipeol(); if (cmd_list[i].id) return do_noargs(cmd_list[i].id); } return 0; }
void *fm_allocate (enum palloc_flags flags, bool lock) { lock_acquire(&frame_table_lock); void *kaddr = palloc_get_page(PAL_USER | flags); struct frame *fm; if (kaddr == NULL){ fm = select_fm(); fm->isPinned = true; fm->locked = lock; kaddr = fm->k_addr; struct hash *ht_thread_uaddr = &fm->ht_thread_uaddr; hash_first(&fm->iter_htu, ht_thread_uaddr); struct thread_uaddr *thread_uaddr; while (hash_next(&fm->iter_htu)){ thread_uaddr = hash_entry(hash_cur(&fm->iter_htu), struct thread_uaddr, elem); struct page* p = find_page(thread_uaddr->uaddr, thread_uaddr->t); p->isLoaded = false; pagedir_clear_page(thread_uaddr->t->pagedir, p->vaddr); if (p->type == STACK){ page_to_swap(p); } else if (p->type == SEGMENT){ if (p->writable && (if_fm_dirty(fm) || p->isDirty)){ p->isDirty = true; page_to_swap(p); } } else { write_mmap_page_to_file(p); } } hash_clear(&fm->ht_thread_uaddr, remove_thread_uaddr); } else {
// Allocca n_pages richieste unsigned int get_page(unsigned int n_pages) { unsigned int i, page = find_page(n_pages); // Restituisce la prima pagina libera if(!page) // Se find_page() ritorna 0 { video_scrivi_stringa("\nImpossibile soddisfare la richiesta... (get_page()) => Loop"); debug_stringa("\nImpossibile soddisfare la richiesta... (get_page()) => Loop"); for(;;); } // Setta la pagine come occupate nella bitmap for(i = 0; i < n_pages; i++) setP_bitmap(page + i); // Cerca la prima entry libera del costrutto (Riutilizza i) for(i = bitmap_info.curr_index; i < 500; i++) if(bitmap_info.n_pages[i] == 0) break; if(i == 500) // Se il costrutto bitmap_inf è pieno ç_ç { video_scrivi_stringa("\nBitmap_info piena... => Loop"); debug_stringa("\nBitmap_info piena... => Loop"); for(;;); } // Adesso il nostro nuovo indice sarà i bitmap_info.start_page[i] = page; // Entry della bitmap di partenza bitmap_info.n_pages[i] = n_pages; // Richiamando un'altra volta la funzione get_page(), nel costrutto si partirà a cercare da i + 1 bitmap_info.curr_index = i + 1; return page*0x1000; // Ritorna l'indirizzo fisico }
/** * Free an allocated memory block. * * Whenever a block is freed, the allocator checks its buddy. If the buddy is * free as well, then the two buddies are combined to form a bigger block. This * process continues until one of the buddies is not free. * * @param addr memory block address to be freed */ void buddy_free(void *addr) { /* TODO: IMPLEMENT THIS FUNCTION */ int page = ADDR_TO_PAGE(addr); Node* node = find_page(page); // printf("Found node in tree with order: %d\n", node->order); node->free = 1; Node* parent = node->parent; while(parent != 0 && (parent->left->free + parent->right->free == 2)) { free(parent->left); free(parent->right); parent->left = 0; parent->right = 0; page = parent->pageIndex; node = parent; parent = node->parent; node->free = 1; } // page_t* page = &g_pages[ADDR_TO_PAGE(addr)]; // int index = page->order; // page_t* buddy = &g_pages[ADDR_TO_PAGE(BUDDY_ADDR(PAGE_TO_ADDR((unsigned long) (page - g_pages)), (index)))]; // struct list_head* head = list_for_each_entry(buddy, &(buddy->list), list); }
void LinkerBlockAllocator::free(void* block) { if (block == nullptr) { return; } LinkerBlockAllocatorPage* page = find_page(block); if (page == nullptr) { abort(); } ssize_t offset = reinterpret_cast<uint8_t*>(block) - page->bytes; if (offset % block_size_ != 0) { abort(); } memset(block, 0, block_size_); FreeBlockInfo* block_info = reinterpret_cast<FreeBlockInfo*>(block); block_info->next_block = free_block_list_; block_info->num_free_blocks = 1; free_block_list_ = block_info; }
struct page * lookup_swap_cache(unsigned long entry) { struct page *found; #ifdef SWAP_CACHE_INFO swap_cache_find_total++; #endif while (1) { found = find_page(&swapper_inode, entry); if (!found) return 0; if (found->inode != &swapper_inode || !PageSwapCache(found)) goto out_bad; if (!PageLocked(found)) { #ifdef SWAP_CACHE_INFO swap_cache_find_success++; #endif return found; } __free_page(found); __wait_on_page(found); } out_bad: printk (KERN_ERR "VM: Found a non-swapper swap page!\n"); __free_page(found); return 0; }
/* Search dialog callback function */ static void find_page_callback(const char *search_title, void *data) { /* save the search string for possible repeat */ last_search = (char *)realloc(last_search, strlen(search_title)+1); strcpy(last_search, search_title); find_page(search_title, data); }
/* This function is called when the virtual memory system unmaps a page from * the virtual address space. Remove the page from the list of resident * pages. */ void policy_page_unmapped(page_t page) { pageinfo_t *pginfo, *prev; pginfo = find_page(&pagelist, page, &prev); assert(pginfo != NULL); remove_from_list(&pagelist, pginfo, prev); }
void free_page (void *kaddr) { struct page *page = find_page(kaddr); if (page != NULL) { do_free_page(page); } }
int fifo_evict(struct page *p) { //Evict the victim struct page *victim = find_page(coremap[slot].vaddr); victim->pframe = -1; //increment the slot with wrap around after the return int rSlot = slot; slot = (slot+1) % memsize; return rSlot; }
/* We must have : 0 <= offset <= b->total_size */ void eb_delete(EditBuffer *b, int offset, int size) { int n, len; Page *del_start, *p; if (offset >= b->total_size) return; b->total_size -= size; eb_addlog(b, LOGOP_DELETE, offset, size); /* find the correct page */ p = find_page(b, &offset); n = 0; del_start = NULL; while (size > 0) { len = p->size - offset; if (len > size) len = size; if (len == p->size) { if (!del_start) del_start = p; /* we cannot free if read only */ if (!(p->flags & PG_READ_ONLY)) free(p->data); p++; offset = 0; n++; } else { update_page(p); memmove(p->data + offset, p->data + offset + len, p->size - offset - len); p->size -= len; p->data = realloc(p->data, p->size); offset += len; if (offset >= p->size) { p++; offset = 0; } } size -= len; } /* now delete the requested pages */ if (n > 0) { b->nb_pages -= n; memmove(del_start, del_start + n, (b->page_table + b->nb_pages - del_start) * sizeof(Page)); b->page_table = realloc(b->page_table, b->nb_pages * sizeof(Page)); } /* the page cache is no longer valid */ b->cur_page = NULL; }
/* Add the specified page to the end of the linked list. This is a wrapper * for the add_to_tail() function. */ void add_page(pagelist_t *list, page_t page) { pageinfo_t *pginfo; assert(list != NULL); assert(find_page(list, page, NULL) == NULL); /* Always add the page to the back of the queue. */ pginfo = malloc(sizeof(pageinfo_t)); pginfo->page = page; pginfo->next = NULL; add_to_tail(list, pginfo); }
/* We must have : 0 <= offset <= b->total_size */ static void eb_insert_lowlevel(EditBuffer *b, int offset, const u8 *buf, int size) { int len, len_out, page_index; Page *p; b->total_size += size; /* find the correct page */ p = b->page_table; if (offset > 0) { offset--; p = find_page(b, &offset); offset++; /* compute what we can insert in current page */ len = MAX_PAGE_SIZE - offset; if (len > size) len = size; /* number of bytes to put in next pages */ len_out = p->size + len - MAX_PAGE_SIZE; page_index = p - b->page_table; if (len_out > 0) eb_insert1(b, page_index + 1, p->data + p->size - len_out, len_out); else len_out = 0; /* now we can insert in current page */ if (len > 0) { p = b->page_table + page_index; update_page(p); p->size += len - len_out; p->data = realloc(p->data, p->size); memmove(p->data + offset + len, p->data + offset, p->size - (offset + len)); memcpy(p->data + offset, buf, len); buf += len; size -= len; } } else { page_index = -1; } /* insert the remaining data in the next pages */ if (size > 0) eb_insert1(b, page_index + 1, buf, size); /* the page cache is no longer valid */ b->cur_page = NULL; }
/** @fn void* pool_slab_malloc(pool_slab* p, pool_size size, pool_err* err) @brief Allocates size bytes in the memory @param[in] p The slab struct @param[in] size The number of bytes to allocate @param[out] err The error that happened */ POOL_FUNC void* pool_slab_malloc(pool_slab* p, pool_size size, pool_err* err) { POOL_SET_ERR(err, POOL_ERR_OK); POOL_SET_ERR_IF(p == NULL, err, POOL_ERR_INVALID_POOL, NULL); pool_u n_pages, page; pool_u i = 0; pool_size s; pool_err err2; // RAW Page if (size > POOL_SLAB_PAGE_SIZE) { n_pages = POOL_CEIL_DIV(size + sizeof(pool_u), POOL_SLAB_PAGE_SIZE); page = find_empty_page(p->slabs, n_pages); POOL_SET_ERR_IF(page == POOL_SLAB_PAGE_N, err, POOL_ERR_OUT_OF_MEM, NULL); for (i = page; i < page + n_pages; i++) set_2_bits(p->slabs, i, RAW); void* ret = page*POOL_SLAB_PAGE_SIZE + (char*)p->mem; *((pool_u*)ret) = n_pages; ret = (char*)ret + sizeof(pool_u); return ret; } // Page with buddy allocator else { page = 0; while(page < POOL_SLAB_PAGE_N) { page = find_page(p, size, page, POOL_SLAB_PAGE_N); void* ret = pool_buddy_malloc(p->buddies + page, size, &err2); if(!err2) { s = p->buddies[page].allocated*POOL_BUDDY_BLOCK_SIZE; POOL_SET_ERR_IF(err ? *err : 0, err, *err, NULL); if (s == POOL_SLAB_PAGE_SIZE) set_2_bits(p->slabs, page, FULL); else set_2_bits(p->slabs, page, PARTIAL); return ret; } page++; } POOL_SET_ERR(err, POOL_ERR_OUT_OF_MEM); } return NULL; }
/** * Check dirty pages first, else read page from file */ uint64_t file_transaction::read( char* data, uint64_t len ) { // rout( status, "pos %1% len %2%", %m_pos %len ); // rout( status, "filetrx read %3% pos %1% len %2%", %m_pos %len %this ); uint64_t start_page = m_pos / sizeof(page); uint32_t start_page_pos = m_pos % sizeof(page); char* pos = data; const char* end = data + len; while( pos != end && m_pos != m_size ) { uint32_t page_pos = m_pos % sizeof(page); // rout( status, "pos-data: %1% page_pos %2% len: %3% sizeof(page)-page_pos: %4%", %(pos-data) %page_pos %len %(sizeof(page)-page_pos) ); uint32_t read_size = std::min( uint64_t(sizeof(page) - page_pos), uint64_t(len - (pos - data) ) ); if( m_pos + read_size >= m_size ) { if( m_pos >= m_size ) return (pos - data); // rout( status, "m_size: %1% m_pos: %2%", %m_size %m_pos ); read_size = m_size - m_pos; } page* p = find_page( m_pos / sizeof(page) ); if( p ) memcpy( pos, &((*p)[page_pos]), read_size ); else { uint64_t fp = m_file->pos(); m_file->seek( m_pos ); uint64_t r = m_file->read( pos, read_size ); m_file->seek( fp ); if( r != read_size ) { m_pos += r; return (pos - data) + r; } } m_pos += read_size; pos += read_size; } return (pos - data); }
int lru_evict(struct page *p) { //The idea is to maintain a counter that will keep counting down when the page is not chosen //when the page is called the new counter is put onto it. //to evict we simply look for the lowest counter and remove it int lowest = 0; int chosen = 0; int i = 0; for (; i< memsize; i++){ if (coremap[i].counter < lowest){ lowest = coremap[i].counter; chosen = i; } coremap[i].counter--; } struct page *victim = find_page(coremap[chosen].vaddr); victim->pframe = -1; return chosen; return 0; }
/* Read or write in the buffer. We must have 0 <= offset < b->total_size */ static int eb_rw(EditBuffer *b, int offset, u8 *buf, int size1, int do_write) { Page *p; int len, size; if ((offset + size1) > b->total_size) size1 = b->total_size - offset; if (size1 <= 0) return 0; size = size1; if (do_write) eb_addlog(b, LOGOP_WRITE, offset, size); p = find_page(b, &offset); while (size > 0) { len = p->size - offset; if (len > size) len = size; if (do_write) { update_page(p); memcpy(p->data + offset, buf, len); } else { memcpy(buf, p->data + offset, len); } buf += len; size -= len; offset += len; if (offset >= p->size) { p++; offset = 0; } } return size1; }
/* * returning 1 will cause the currently running engine to exit */ uint8_t process_keys(void) { uint8_t c; if (kbhit() > 0) { c=cgetc(); CLEARKEYBUF; if (c == 'p') { #ifdef MIXED_MODE printf("PAUSED. Press p to Continue.\n"); #endif wait_for_keypress('p'); } else if (c == '1') { engine_sel = ENGINE_SEL_WRAP_NAIVE; engine_state = ENGINE_RUN; #ifdef MIXED_MODE printf("Naive wrap mode enabled.\n"); #endif return 1; } else if (c == '2') { engine_sel = ENGINE_SEL_NOWRAP_NAIVE; engine_state = ENGINE_RUN; #ifdef MIXED_MODE printf("Naive nowrap mode enabled.\n"); #endif return 1; } else if (c == '3') { engine_sel = ENGINE_SEL_WRAP_OPT; engine_state = ENGINE_RUN; #ifdef MIXED_MODE printf("Optimized wrap mode enabled.\n"); #endif return 1; } else if (c == '4') { engine_sel = ENGINE_SEL_NOWRAP_OPT; engine_state = ENGINE_RUN; #ifdef MIXED_MODE printf("Optimized nowrap mode enabled.\n"); #endif return 1; } else if (tolower(c) == 'q') { engine_state = ENGINE_STOP; return 1; } else if (c == '?') { memcpy((uint8_t *)0x5000,0x400,0x800); text_mode(); printf("\n\n\n\n\n\n\n"); show_hotkeys(); #ifdef MIXED_MODE gotoxy(0,MAXROWPAIRCNT); POKE(TEXTWINDOW_TOP_EDGE,MAXROWPAIRCNT); gr_mode(SS_PAGE2OFF, SS_MIXEDON); #else gr_mode(SS_PAGE2OFF, SS_MIXEDOFF); #endif memcpy((uint8_t *)0x400,0x5000,0x800); } else if (tolower(c) == 'r') randomize(gr_page[find_page()], 400); else if (tolower(c) == 'g') gospergun(gr_page[find_page()]); else if (tolower(c) == 's') simkins(gr_page[find_page()]); } return 0; }
/* Insert 'size bytes of 'src' buffer from position 'src_offset' into buffer 'dest' at offset 'dest_offset'. 'src' MUST BE DIFFERENT from 'dest' */ void eb_insert_buffer(EditBuffer *dest, int dest_offset, EditBuffer *src, int src_offset, int size) { Page *p, *p_start, *q; int size_start, len, n, page_index; if (size == 0) return; eb_addlog(dest, LOGOP_INSERT, dest_offset, size); /* insert the data from the first page if it is not completely selected */ p = find_page(src, &src_offset); if (src_offset > 0) { len = p->size - src_offset; if (len > size) len = size; eb_insert_lowlevel(dest, dest_offset, p->data + src_offset, len); dest_offset += len; size -= len; p++; } if (size == 0) return; /* cut the page at dest offset if needed */ if (dest_offset < dest->total_size) { q = find_page(dest, &dest_offset); page_index = q - dest->page_table; if (dest_offset > 0) { page_index++; eb_insert1(dest, page_index, q->data + dest_offset, q->size - dest_offset); /* must reload q because page_table may have been realloced */ q = dest->page_table + page_index - 1; update_page(q); q->data = realloc(q->data, dest_offset); q->size = dest_offset; } } else { page_index = dest->nb_pages; } /* update total_size */ dest->total_size += size; /* compute the number of complete pages to insert */ p_start = p; size_start = size; while (size > 0 && p->size <= size) { size -= p->size; p++; } n = p - p_start; /* number of pages to insert */ p = p_start; if (n > 0) { /* add the pages */ dest->nb_pages += n; dest->page_table = realloc(dest->page_table, dest->nb_pages * sizeof(Page)); q = dest->page_table + page_index; memmove(q + n, q, sizeof(Page) * (dest->nb_pages - n - page_index)); p = p_start; while (n > 0) { len = p->size; q->size = len; if (p->flags & PG_READ_ONLY) { /* simply copy the reference */ q->flags = PG_READ_ONLY; q->data = p->data; } else { /* allocate a new page */ q->flags = 0; q->data = malloc(len); memcpy(q->data, p->data, len); } n--; p++; q++; } page_index = q - dest->page_table; } /* insert the remaning bytes */ if (size > 0) { eb_insert1(dest, page_index, p->data, size); } /* the page cache is no longer valid */ dest->cur_page = NULL; }
int display_encyclopedia_handler(window_info *win) { _Text *t=Page[currentpage].T.Next; _Image *i=Page[currentpage].I.Next; int j; j=vscrollbar_get_pos(encyclopedia_win, encyclopedia_scroll_id); while(t) { int ylen=(t->size)?18:15; int xlen=strlen(t->text)*((t->size)?11:8); // Bounds Check the Text if((t->y-j > 0) && (t->y-j < encyclopedia_menu_y_len-20 )) { if(t->ref) { //draw a line glColor3f(0.5,0.5,0.5); glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); glVertex3i(t->x+4,t->y+ylen-j,0); glVertex3i(t->x+4+xlen-8,t->y+ylen-j,0); glEnd(); glEnable(GL_TEXTURE_2D); #ifdef OPENGL_TRACE CHECK_GL_ERRORS(); #endif //OPENGL_TRACE } if(t->size) { if(t->ref && mouse_x>(t->x+win->cur_x) && mouse_x<(t->x+xlen+win->cur_x) && mouse_y>(t->y+win->cur_y-j) && mouse_y<(t->y+ylen+win->cur_y-j)) glColor3f(0.3,0.6,1.0); else glColor3f(t->r,t->g,t->b); draw_string(t->x,t->y-j,(unsigned char*)t->text,1); } else { if(t->ref && mouse_x>(t->x+win->cur_x) && mouse_x<(t->x+xlen+win->cur_x) && mouse_y>(t->y+win->cur_y-j) && mouse_y<(t->y+ylen+win->cur_y-j)) glColor3f(0.3,0.6,1.0); else glColor3f(t->r,t->g,t->b); draw_string_small(t->x,t->y-j,(unsigned char*)t->text,1); } } // No next line? if(!t->Next) break; t=t->Next; } glColor3f(1.0f,1.0f,1.0f); while(i){ // Bounds Check the Text if((i->y-j > 0) && (i->yend-j < encyclopedia_menu_y_len-40 )) { if(i->mouseover==1) { i=i->Next; continue; } if(mouse_x>(i->x+win->cur_x) && mouse_x<(win->cur_x+i->xend) && mouse_y>(i->y+win->cur_y-j) && mouse_y<(win->cur_y-j+i->yend)) { if(i->Next!=NULL) { if(i->Next->mouseover==1) i=i->Next; } } #ifdef NEW_TEXTURES bind_texture(i->id); #else /* NEW_TEXTURES */ get_and_set_texture_id(i->id); #endif /* NEW_TEXTURES */ glBegin(GL_QUADS); draw_2d_thing(i->u, i->v, i->uend, i->vend,i->x, i->y-j,i->xend,i->yend-j); glEnd(); } i=i->Next; } #ifdef ENCYCL_NAVIGATION if (repeat_search && last_search != NULL) { find_page(last_search, NULL); repeat_search = 0; } if (show_cm_help) { show_help(cm_encycl_help_str, 0, win->len_y+10); show_cm_help = 0; } #endif return 1; }
/**************************************************************************** * Main routine, hunt down the manpage. */ int main(int argc, char **argv) { int do_pclose_ofd = 0; int ar; char *mansect = 0; char *manname = 0; ofd = stdout; ifd = stdin; for (ar = 1; ar < argc; ar++) if (argv[ar][0] == '-') { char *p; for (p = argv[ar] + 1; *p; p++) switch (*p) { case 'w': flg_w = 1; break; case 'v': verbose = 1; break; case 'q': verbose = 0; break; } } else if (isdigit(argv[ar][0])) mansect = argv[ar]; else if (manname == 0) manname = argv[ar]; else if (mansect == 0) { mansect = manname; manname = argv[ar]; } else { fprintf(stderr, "Ignoring argument %s\n", argv[ar]); break; } if (manname == 0) { fprintf(stderr, "Which manpage ?\n"); exit(1); } if (find_page(manname, mansect) < 0) { if (mansect) fprintf(stderr, "No entry for %s in section %s of the manual.\n", manname, mansect); else fprintf(stderr, "No manual entry for %s\n", manname); exit(1); } if (flg_w) exit(0); /* ifd is now the file - display it */ if (isatty(1)) { /* If writing to a tty try to do it to a pager */ /* The original way that this was coded relied on popen returning NULL if PAGER was undefined. However, both on Linux and on the V7 sh in FUZIX, sh barfed when getenv returned NULL: sh: 0: -c requires an argument */ if (getenv("PAGER")) { ofd = popen(getenv("PAGER"), "w"); } else { ofd = popen("more", "w"); } if (ofd == 0) { /* This is likely unreachable because the popen will croak in the absence of more: sh: 1: tmore: not found so we don't get the chance to fall-back to stdout */ ofd = stdout; } else { do_pclose_ofd = 1; page_length = 0; right_margin = 78; } } do_file(); /* Close files */ if (do_pclose_ofd) pclose(ofd); close_page(); exit(0); }
static void handle_button(int button, XButtonEvent * event) { HyperLink *link; HyperDocPage *page = NULL; char *page_name; /* find page name from sub-window handle */ link = get_hyper_link(event); if (link == NULL) { /* user clicked on an inactive area */ /* BeepAtTheUser(); */ /* I always thought this was annoying. RSS */ return; } switch (link->type) { case openaxiom_Pastebutton_token: page = paste_button(link->reference.paste); break; case openaxiom_Link_token: page_name = print_to_string(link->reference.node); page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, page_name); break; case openaxiom_Helpbutton_token: helpForHyperDoc(); page = NULL; break; case openaxiom_Scrollbar_token: scrollScroller(event); break; case Scrollupbutton: scrollUp(); break; case Scrolldownbutton: scrollDown(); break; case openaxiom_Inputstring_token: /* We must be changing input focus or getting a selection */ change_input_focus(link); if ( button == Button2 ) { XConvertSelection(gXDisplay, XA_PRIMARY, XA_STRING, XInternAtom(gXDisplay, "PASTE_SELECTION", False), gWindow->fMainWindow, CurrentTime); gSavedInputAreaLink = link; } break; case openaxiom_SimpleBox_token: page = NULL; toggle_input_box(link); break; case openaxiom_Radiobox_token: page = NULL; toggle_radio_box(link); break; case openaxiom_Quitbutton_token: quitHyperDoc(); break; case openaxiom_Returnbutton_token: /* pop memo information */ page = returnlink(); break; case openaxiom_Upbutton_token: /* pop downlink information */ page = uplink(); break; case openaxiom_Downlink_token: page = find_page(link->reference.node); if (page && NotSpecial(page->type)) downlink(); break; case openaxiom_Memolink_token: page = find_page(link->reference.node); if (page && NotSpecial(page->type)) memolink(); break; case openaxiom_Windowlink_token: page = find_page(link->reference.node); if (page && NotSpecial(page->type)) { windowlink_handler(link->reference.node); gNeedIconName = 1; page = NULL; } break; case openaxiom_Lispwindowlink_token: lispwindowlink_handler(link); gNeedIconName = 1; page = NULL; break; case openaxiom_LispMemoLink_token: case openaxiom_Spadmemolink_token: page = issue_server_command(link); if (page && NotSpecial(page->type)) memolink(); break; case openaxiom_LispDownLink_token: case openaxiom_Spaddownlink_token: page = issue_server_command(link); if (page && NotSpecial(page->type)) downlink(); break; case openaxiom_Spadlink_token: case openaxiom_Lisplink_token: page = issue_server_command(link); break; case openaxiom_Lispcommand_token: case openaxiom_Qspadcall_token: case openaxiom_Spadcall_token: page = issue_server_command(link); break; case openaxiom_Lispcommandquit_token: case openaxiom_Spadcallquit_token: case openaxiom_Qspadcallquit_token: page = issue_server_command(link); exitHyperDoc(); break; case openaxiom_Spadcommand_token: case openaxiom_Spadgraph_token: case openaxiom_Spadsrc_token: issue_spadcommand(gWindow->page, link->reference.node, button == Button1, link->type); break; case openaxiom_Unixlink_token: page = issue_unixlink(link->reference.node); if (page && NotSpecial(page->type)) { downlink(); } break; case openaxiom_Unixcommand_token: issue_unixcommand(link->reference.node); break; default: break; } if (page) { switch (page->type) { /* check for special button types */ case openaxiom_Quitbutton_token: exitHyperDoc(); return; case openaxiom_Returnbutton_token: gWindow->page = returnlink(); break; case openaxiom_Upbutton_token: gWindow->page = uplink(); break; case ErrorPage: case UnknownPage: case UlUnknownPage: if (page->type == UlUnknownPage) page->type = UnloadedPageType; downlink(); gWindow->page = page; break; default: /* a normal link */ gWindow->page = page; break; } if (link->type != openaxiom_Pastebutton_token) display_page(gWindow->page); gWindow->fWindowHashTable = gWindow->page->fLinkHashTable; /* reset the window hash */ } }
void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *data), void *data, void (**oldf)(void *p, void *data), void **olddata) { GCTYPE *gc = GC_get_GC(); Fnl *fnl; if (!is_finalizable_page(gc, p)) { /* Never collected. Don't finalize it. */ if (oldf) *oldf = NULL; if (olddata) *olddata = NULL; return; } gc->splayed_gen0_finalizers = fnl_splay((intptr_t)p, gc->splayed_gen0_finalizers); fnl = gc->splayed_gen0_finalizers; if (!fnl || (fnl->p != p)) { gc->splayed_finalizers = fnl_splay((intptr_t)p, gc->splayed_finalizers); fnl = gc->splayed_finalizers; if (!fnl || (fnl->p != p)) fnl = NULL; else { /* since we're mutating this finalizer, move it to the gen0 list and tree */ remove_finalizer(fnl, 0, gc); add_finalizer(fnl, 1, gc); } } if (fnl && (fnl->p == p)) { if (oldf) *oldf = fnl->f; if (olddata) *olddata = fnl->data; if (f) { fnl->f = f; fnl->data = data; fnl->eager_level = level; } else { /* remove finalizer */ remove_finalizer(fnl, 1, gc); --gc->num_fnls; } return; } if (oldf) *oldf = NULL; if (olddata) *olddata = NULL; if (!f) return; /* Allcation might trigger GC, so we use park: */ CHECK_PARK_UNUSED(gc); gc->park[0] = p; gc->park[1] = data; fnl = (Fnl *)GC_malloc_atomic(sizeof(Fnl)); memset(fnl, 0, sizeof(Fnl)); p = gc->park[0]; data = gc->park[1]; gc->park[0] = NULL; gc->park[1] = NULL; fnl->p = p; fnl->f = f; fnl->data = data; fnl->eager_level = level; fnl->tagged = tagged; #if CHECKS { MPage *m; m = find_page(p); if (tagged) { if ((m->type != MTYPE_TAGGED) || (m->type != MTYPE_PAIR)) { GCPRINT(GCOUTF, "Not tagged: %lx (%d)\n", (intptr_t)p, m->type); CRASH(4); } } } #endif add_finalizer(fnl, 1, gc); gc->num_fnls++; }