void egbb_init(void) { // init Egbb->init = false; Egbb->load = false; Egbb->size = CacheSize; Egbb->piece_nb = 0; Egbb->read_hit = 0; Egbb->read_nb = 0; LibHandler = LOAD_LIB(EgbbLib); if (LibHandler != NULL) { send("egbb library loaded"); load_egbb_ptr = (load_egbb_5men) GET_ENTRY(LibHandler,"load_egbb_5men"); probe_egbb_ptr = (probe_egbb_5men) GET_ENTRY(LibHandler,"probe_egbb_5men"); if (load_egbb_ptr == NULL) my_fatal("egbb_init(): load_egbb_5men() not found\n"); if (probe_egbb_ptr == NULL) my_fatal("egbb_init(): probe_egbb_5men() not found\n"); Egbb->init = true; } }
/******************************************************************** Function: adi_fsd_cache_Write Description: Unlock cache sector, signals to the cache that the FSD has finished modifying block until next read. ********************************************************************/ __ADI_FSD_CACHE_SECTION_CODE u32 adi_fsd_cache_Write( ADI_FSD_CACHE_HANDLE CacheHandle, u8 *pData) { u32 Result; PDD_FSD_CACHE_DEF *pCache; Result=ADI_DEV_RESULT_SUCCESS; pCache=(PDD_FSD_CACHE_DEF *)CacheHandle; if (pData) { PDD_FSD_CACHE_ENTRY *pEntry; /* locate beginning of enclosing data block */ pEntry = GET_ENTRY(pData); pEntry->Locked--; pEntry->Modified=1; /* If Flush on Write flag is set flush buffer */ if (pCache->Flags&ADI_FSD_CACHE_FLUSH_ON_WRITE) { Result=pdd_Transfer( pCache, pEntry, WRITE, 0, 0); } } return Result; }
/** * Finds a RWEntry for the calling thread. This function must be called * under synchronization. Returns NULL if entry for calling thread does not * exist. */ STATIC RWEntry * RWLOCK_FindEntry(RWLock * lock) { int i; ThrID self = THREAD_Self(); for (i=0; i<lock->entriesInUse; i++) { RWEntry * entry = GET_ENTRY(lock,i); if (entry->id == self) { return entry; } } return NULL; }
// Gets the minimum element int heap_min(heap* h, void** key, void** value) { // Check the number of elements, abort if 0 if (h->active_entries == 0) return 0; // Get the 0th element heap_entry* root = GET_ENTRY(0, h->table); // Set the key and value if (key) *key = root->key; if (value) *value = root->value; // Success return 1; }
// Allows a user to iterate over all entries, e.g. to free() the memory void heap_foreach(heap* h, void (*func)(void*,void*)) { // Store the current index and max index int index = 0; int entries = h->active_entries; heap_entry* entry; heap_entry* table = h->table; for (;index<entries;index++) { // Get the entry entry = GET_ENTRY(index,table); // Call the user function func(entry->key, entry->value); } }
void heap_foreach_entry(heap* h, void (*func)(heap_entry*, void*), void* arg) { // Store the current index and max index int index = 0; int entries = h->active_entries; heap_entry* entry; void** map_table = h->mapping_table; for (;index<entries;index++) { // Get the entry entry = GET_ENTRY(index,map_table); // Call the user function func(entry, arg); } }
/******************************************************************** Function: adi_fsd_cache_Release Description: Unlock a sector without updating the modify flag, this is used when a sector is read but not modified. The caller has to execute either the Write or Release function after a Read ********************************************************************/ __ADI_FSD_CACHE_SECTION_CODE u32 adi_fsd_cache_Release( ADI_FSD_CACHE_HANDLE CacheHandle, u8 *pData) { PDD_FSD_CACHE_DEF *pCache; PDD_FSD_CACHE_ENTRY *pEntry; pCache=(PDD_FSD_CACHE_DEF *)CacheHandle; if (pData) { /* locate beginning of enclosing data block */ pEntry = GET_ENTRY(pData); pEntry->Locked--; } return ADI_DEV_RESULT_SUCCESS; }
// Deletes the minimum entry in the heap int heap_delmin(heap* h, void** key, void** value) { // Check there is a minimum if (h->active_entries == 0) return 0; // Load in the map table heap_entry* table = h->table; // Get the root element int current_index = 0; heap_entry* current = GET_ENTRY(current_index, table); // Store the outputs if (key) *key = current->key; if (value) *value = current->value; // Reduce the number of active entries h->active_entries--; // Get the active entries int entries = h->active_entries; // If there are any other nodes, we may need to move them up if (h->active_entries > 0) { // Move the last element to the root heap_entry* last = GET_ENTRY(entries,table); current->key = last->key; current->value = last->value; // Loop variables heap_entry* left_child; heap_entry* right_child; // Load the comparison function int (*cmp_func)(void*,void*) = h->compare_func; // Store the left index int left_child_index; while (left_child_index = LEFT_CHILD(current_index), left_child_index < entries) { // Load the left child left_child = GET_ENTRY(left_child_index, table); // We have a left + right child if (left_child_index+1 < entries) { // Load the right child right_child = GET_ENTRY((left_child_index+1), table); // Find the smaller child if (cmp_func(left_child->key, right_child->key) <= 0) { // Swap with the left if it is smaller if (cmp_func(current->key, left_child->key) == 1) { SWAP_ENTRIES(current,left_child); current_index = left_child_index; current = left_child; // Otherwise, the current is smaller } else break; // Right child is smaller } else { // Swap with the right if it is smaller if (cmp_func(current->key, right_child->key) == 1) { SWAP_ENTRIES(current,right_child); current_index = left_child_index+1; current = right_child; // Current is smaller } else break; } // We only have a left child, only do something if the left is smaller } else if (cmp_func(current->key, left_child->key) == 1) { SWAP_ENTRIES(current,left_child); current_index = left_child_index; current = left_child; // Done otherwise } else break; } } // Check if we should release a page of memory int used_pages = entries / ENTRIES_PER_PAGE + ((entries % ENTRIES_PER_PAGE > 0) ? 1 : 0); // Allow one empty page, but not two if (h->allocated_pages / 2 > used_pages + 1 && h->allocated_pages / 2 >= h->minimum_pages) { // Get the new number of entries we need int new_size = h->allocated_pages / 2; // Map in a new table heap_entry* new_table = map_in_pages(new_size); // Copy the old entries, copy the entire pages memcpy(new_table, h->table, used_pages*PAGE_SIZE); // Cleanup the old table map_out_pages(h->table, h->allocated_pages); // Switch to the new table h->table = new_table; h->allocated_pages = new_size; } // Success return 1; }
// Insert a new element void heap_insert(heap *h, void* key, void* value) { // Check if this heap is not destoyed assert(h->table != NULL); // Check if we have room int max_entries = h->allocated_pages * ENTRIES_PER_PAGE; if (h->active_entries + 1 > max_entries) { // Get the new number of entries we need int new_size = h->allocated_pages * 2; // Map in a new table heap_entry* new_table = map_in_pages(new_size); // Copy the old entries, copy the entire pages memcpy(new_table, h->table, h->allocated_pages*PAGE_SIZE); // Cleanup the old table map_out_pages(h->table, h->allocated_pages); // Switch to the new table h->table = new_table; h->allocated_pages = new_size; } // Store the comparison function int (*cmp_func)(void*,void*) = h->compare_func; // Store the table address heap_entry* table = h->table; // Get the current index int current_index = h->active_entries; heap_entry* current = GET_ENTRY(current_index, table); // Loop variables int parent_index; heap_entry *parent; // While we can, keep swapping with our parent while (current_index > 0) { // Get the parent index parent_index = PARENT_ENTRY(current_index); // Get the parent entry parent = GET_ENTRY(parent_index, table); // Compare the keys, and swap if we need to if (cmp_func(key, parent->key) < 0) { // Move the parent down current->key = parent->key; current->value = parent->value; // Move our reference current_index = parent_index; current = parent; // We are done swapping } else break; } // Insert at the current index current->key = key; current->value = value; // Increase the number of active entries h->active_entries++; }
/** * Returns available RWEntry for the calling thread. Reallocates array * of thread entries if necessary. Obviously, this function must be called * under synchronization. Returns NULL only if we run out of thread entries * and memory allocation fails. */ STATIC RWEntry * RWLOCK_GetEntry(RWLock * lock) { int i; ThrID self = THREAD_Self(); RWEntry * empty = NULL; /* vacant empty entry */ /* * try to find existing entry for this thread. At the same time * pick up the first available empty slot. */ for (i=0; i<lock->entriesInUse; i++) { RWEntry * entry = GET_ENTRY(lock,i); if (entry->id == self) { return entry; } else if (!empty && !entry->id) { empty = entry; } } /* * we didn't find existing slot for the calling thread. * We have to find an empty slot. */ if (!empty) { for (; i<lock->numEntries; i++) { RWEntry * entry = GET_ENTRY(lock,i); if (!entry->id) { empty = entry; break; } } /* * looks like we are out of luck. We need to reallocate the array * of thread entries. */ if (!empty) { int count = lock->numEntries + STATIC_ENTRIES; size_t size = count * sizeof(RWEntry); RWEntry * newEntries = (RWEntry*) MEM_Realloc(lock->moreEntries, size); if (!newEntries) { return NULL; } lock->moreEntries = newEntries; lock->numEntries = count; empty = lock->moreEntries + i - STATIC_ENTRIES; memset(empty, 0, sizeof(RWEntry) * STATIC_ENTRIES); } lock->entriesInUse = i + 1; } lock->entriesActive++; /* * initialize the empty entry. */ empty->id = self; empty->read = empty->write = 0L; return empty; }
static gint prefs_actions_clist_set_row(gint row) { const gchar *entry_text; gint len, action_nb; gchar action[PREFSBUFSIZE]; gchar *new_action; GET_ENTRY(actions.name_entry); if (entry_text[0] == '\0') { alertpanel_error(_("Menu name is not set.")); return -1; } if (entry_text[0] == '/') { alertpanel_error(_("A leading '/' is not allowed in the menu name.")); return -1; } if (strchr(entry_text, ':')) { alertpanel_error(_("Colon ':' is not allowed in the menu name.")); return -1; } action_nb = prefs_actions_find_by_name(entry_text); if ((action_nb != -1) && ((row == -1) || (row != action_nb + 1))) { alertpanel_error(_("There is an action with this name already.")); return -1; } strncpy(action, entry_text, PREFSBUFSIZE - 1); while (strstr(action, "//")) { char *to_move = strstr(action, "//")+1; char *where = strstr(action, "//"); int old_len = strlen(action); memmove(where, to_move, strlen(to_move)); action[old_len-1] = '\0'; } g_strstrip(action); /* Keep space for the ': ' delimiter */ len = strlen(action) + 2; if (len >= PREFSBUFSIZE - 1) { alertpanel_error(_("Menu name is too long.")); return -1; } strcat(action, ": "); GET_ENTRY(actions.cmd_entry); if (entry_text[0] == '\0') { alertpanel_error(_("Command-line not set.")); return -1; } if (len + strlen(entry_text) >= PREFSBUFSIZE - 1) { alertpanel_error(_("Menu name and command are too long.")); return -1; } if (action_get_type(entry_text) == ACTION_ERROR) { gchar *message; message = g_markup_printf_escaped(_("The command\n%s\nhas a syntax error."), entry_text); alertpanel_error("%s", message); g_free(message); return -1; } strcat(action, entry_text); new_action = g_strdup(action); prefs_actions_list_view_insert_action(actions.actions_list_view, row, new_action, TRUE); prefs_actions_set_list(); return 0; }
if (param) { if (param == U_DPAGE_INIT) { usp_init_wi_auth(); return; } if (param == U_DPAGE_DESTROY) { usp_end_wi_auth(); return; } if (param == U_DPAGE_SIGHUP) { usp_sighup_wi_auth(); return; } if (param >= U_DPAGE_FORK) return; } U_http_info.endHeader = 0; static UHTTP::service_info GET_table[] = { // NB: the table must be ordered alphabetically for binary search... GET_ENTRY(admin), GET_ENTRY(admin_edit_ap), GET_ENTRY(admin_export_statistics_login_as_csv), GET_ENTRY(admin_export_statistics_registration_as_csv), GET_ENTRY(admin_export_view_using_historical_as_csv), GET_ENTRY(admin_historical_statistics_login), GET_ENTRY(admin_login_nodog), GET_ENTRY(admin_login_nodog_historical), GET_ENTRY(admin_login_nodog_historical_view_data), GET_ENTRY(admin_printlog), GET_ENTRY(admin_recovery), GET_ENTRY(admin_status_network), GET_ENTRY(admin_status_nodog), GET_ENTRY(admin_status_nodog_and_user), GET_ENTRY(admin_status_nodog_and_user_as_csv), GET_ENTRY(admin_view_statistics_login),
/** * Release n recursively acquired locks. */ void RWLOCK_UnlockMany(RWLock * lock, int n) { if (n > 0) { RWEntry * entry; MUTEX_Lock(&lock->mutex); entry = RWLOCK_FindEntry(lock); /* * if we cannot find the entry, it means that current thread * does not own the lock. It's a programming error. */ ASSERT(entry); if (entry) { lock->locks--; /* first release write locks */ if (entry->write > 0) { if (entry->write >= n) { entry->write -= n; n = 0; } else { n -= entry->write; entry->write = 0; } } /* then read locks */ if (n > 0) { entry->read -= n; } /* * ASSERT that current thread does not release more locks than * it has acquired */ ASSERT(lock->locks >= 0); ASSERT(entry->read >= 0); ASSERT(entry->write >= 0); /* * no more work to do unless calling thread has released the * resource (i.e. usage count came down to zero) */ if ((entry->read + entry->write) <= 0) { int i; int inUse; QEntry * e; RWLockWaiter * shareWaiter = NULL; RWLockWaiter * exclusiveWaiter = NULL; entry->id = 0; lock->entriesActive--; ASSERT(lock->entriesActive >= 0); /* * update lock->entriesInUse * NOTE that RWLOCK_FindStaticEntry() may access it without * synchronization. */ i = lock->entriesInUse - 1; inUse = 0; while (i >= 0) { RWEntry * lockEntry = GET_ENTRY(lock,i); if (lockEntry->id) { inUse = i + 1; break; } i--; } lock->entriesInUse = inUse; /* * if resource was acquired exclusively, it must be free now */ if (lock->flags & RWLOCK_FLAG_EXCLUSIVE_LOCK) { ASSERT(!lock->locks); lock->flags &= ~RWLOCK_FLAG_EXCLUSIVE_LOCK; } /* * release the waiters in the order they have arrived */ e = QUEUE_First(&lock->shareWaiters); if (e) shareWaiter = QCAST(e,RWLockWaiter,entry); e = QUEUE_First(&lock->exclusiveWaiters); if (e) exclusiveWaiter = QCAST(e,RWLockWaiter,entry); if (exclusiveWaiter && (!shareWaiter || exclusiveWaiter->index < shareWaiter->index)) { EVENT_Set(exclusiveWaiter->event); } else if (shareWaiter) { /* this should unblock all shared waiters */ EVENT_Set(shareWaiter->event); } } else if (lock->flags & RWLOCK_FLAG_EXCLUSIVE_LOCK) { /* * if the owner of the lock has released all its WRITE locks * but still have some READ locks, switch to shared mode. */ if (!entry->write) { QEntry * e; RWLockWaiter * shareWaiter = NULL; RWLockWaiter * exclusiveWaiter = NULL; ASSERT(entry->read > 0); lock->flags &= ~RWLOCK_FLAG_EXCLUSIVE_LOCK; /* * wake up shared waiters only unless the exclusive * waiter is first in the line */ e = QUEUE_First(&lock->shareWaiters); if (e) shareWaiter = QCAST(e,RWLockWaiter,entry); e = QUEUE_First(&lock->exclusiveWaiters); if (e) exclusiveWaiter = QCAST(e,RWLockWaiter,entry); if (shareWaiter && (!exclusiveWaiter || shareWaiter->index < exclusiveWaiter->index)) { EVENT_Set(shareWaiter->event); } } } } MUTEX_Unlock(&lock->mutex); } }
void PerformRender(renderlist_t *RenderList, gamestate_t *GameState) { drawbuffer_t *DrawBuffer = &GameState->DrawBuffer; uint BufferSize = DrawBuffer->Width * DrawBuffer->Height; u8 *Pixels = (u8 *)(DrawBuffer->Buffer); u8 *Address = (u8 *)RenderList->Data; bool FirstRender = false; for (renderop_e RenderOp = (renderop_e)*Address; RenderOp != RenderOp_stop; RenderOp = (renderop_e)*Address) { // Skip past render op Address += sizeof(renderop_e); #define RENDERDATA(SubType) (renderdata_##SubType##_t *)Address; Address += sizeof(renderdata_##SubType##_t) switch (RenderOp) { case RenderOp_clear: { uint Color = *(uint *)Address; Address += sizeof(uint); uint *Dst = (uint *)Pixels; for (uint i=0; i < BufferSize; ++i) { *Dst++ = Color; } FirstRender = true; // Why? Because everything's gone now break; } case RenderOp_bitmap: { renderdata_bitmap_t *Bitmap = RENDERDATA(bitmap); artfile_entry_t *Entry = GET_ENTRY((&ArtsMemory), Bitmap->Id); u8 *EntryData = GET_ENTRY_DATA((&ArtsMemory), Bitmap->Id); int StartX = Bitmap->X * DrawBuffer->Width; int StartY = Bitmap->Y * DrawBuffer->Height; bool UseColorKey = Bitmap->Flags & BitmapFlag_ColorKey; bool UseAlpha = Bitmap->Flags & BitmapFlag_Alpha; if (Bitmap->Flags & BitmapFlag_AlignLeft) { StartX = 0; } else if (Bitmap->Flags & BitmapFlag_AlignRight) { StartX = DrawBuffer->Width - Entry->Dim.Width * Bitmap->Width; } if (Bitmap->Flags & BitmapFlag_AlignTop) { StartY = 0; } else if (Bitmap->Flags & BitmapFlag_AlignBottom) { StartY = DrawBuffer->Height - Entry->Dim.Height * Bitmap->Height; } /* if (((StartX + Entry->Dim.Width < 0) && (StartY + Entry->Dim.Height < 0)) || (StartX > DrawBuffer->Width) && (StartY > DrawBuffer->Height)) { // Not visible break; } */ Bitmap->Width = (Bitmap->Width < 0 ? 0 : Bitmap->Width); Bitmap->Height = (Bitmap->Height < 0 ? 0 : Bitmap->Height); uint RealDimWidth = Entry->Dim.Width; uint RealDimHeight = Entry->Dim.Height; u8 *Src = EntryData; if (StartY < 0) { Src += abs(StartY) * Entry->Dim.Width; RealDimHeight -= abs(StartY); StartY = 0; } if (StartX < 0) { Src += abs(StartX); RealDimWidth -= abs(StartX); StartX = 0; } if (StartX + RealDimWidth > DrawBuffer->Width) { RealDimWidth -= (StartX + RealDimWidth) - DrawBuffer->Width; } if (StartY + RealDimHeight > DrawBuffer->Height) { RealDimHeight -= (StartY + RealDimHeight) - DrawBuffer->Height; } uint *Dst = (uint *)(Pixels + 4 * (StartY * DrawBuffer->Width + StartX)); // uint *LastDst = (uint *)(Pixels + 4 * DrawBuffer->Width * DrawBuffer->Height - 1); float StepX = 1 / Bitmap->Width; float StepY = 1 / Bitmap->Height; uint DrawBufferSize = 4 * DrawBuffer->Width * DrawBuffer->Height - 1; for (float Y = 0; Y < Entry->Dim.Height; Y += StepY) { if (((uint)(Y+0.5f)) >= RealDimHeight || !BoundsCheck(Pixels, DrawBufferSize, Dst) /*Dst > LastDst*/) { break; } uint iY = (uint)Y; uint Scanline = 0; for (float X = 0; X < Entry->Dim.Width; X += StepX) { //if (Dst > LastDst) { if (Scanline >= DrawBuffer->Width || !BoundsCheck(Pixels, DrawBufferSize, Dst)) { break; } uint iX = (uint)X; u8 C = *(Src + iY * Entry->Dim.Width + iX); uint FinalColor = 0; if (C) { FinalColor = Bitmap->Color; } if (X < RealDimWidth && (!UseColorKey || FinalColor)) { if (!FirstRender && UseAlpha) { uint DstRaw = *Dst; color_t DstColor = UintToColor(DstRaw); color_t SrcColor = UintToColor(FinalColor); float OneMinusSrcA = 1.0f - SrcColor.A; DstColor.R = SrcColor.R + (DstColor.R * OneMinusSrcA); DstColor.G = SrcColor.G + (DstColor.G * OneMinusSrcA); DstColor.B = SrcColor.B + (DstColor.B * OneMinusSrcA); FinalColor = ColorToRGB(DstColor); } *Dst = FinalColor; } ++Dst; ++Scanline; } Dst += DrawBuffer->Width - Scanline; } FirstRender = false; break; } default: assert(!"Unknown render op"); } #undef RENDERDATA } }
// Deletes the minimum entry in the heap int heap_delmin(heap* h, void** key, void** value) { // Check there is a minimum if (h->active_entries == 0) return 0; // Load in the map table void** map_table = h->mapping_table; // Get the root element int current_index = 0; heap_entry* current = GET_ENTRY(current_index, map_table); // Store the outputs if (key != NULL && value != NULL) { *key = current->key; *value = current->value; } // Reduce the number of active entries h->active_entries--; // Get the active entries int entries = h->active_entries; // If there are any other nodes, we may need to move them up if (h->active_entries > 0) { // Move the last element to the root heap_entry* last = GET_ENTRY(entries,map_table); current->key = last->key; current->value = last->value; // Loop variables heap_entry* left_child; heap_entry* right_child; // Load the comparison function int (*cmp_func)(void*,void*) = h->compare_func; // Store the left index int left_child_index; while (left_child_index = LEFT_CHILD(current_index), left_child_index < entries) { // Load the left child left_child = GET_ENTRY(left_child_index, map_table); // We have a left + right child if (left_child_index+1 < entries) { // Load the right child right_child = GET_ENTRY((left_child_index+1), map_table); // Find the smaller child if (cmp_func(left_child->key, right_child->key) <= 0) { // Swap with the left if it is smaller if (cmp_func(current->key, left_child->key) == 1) { SWAP_ENTRIES(current,left_child); current_index = left_child_index; current = left_child; // Otherwise, the current is smaller } else break; // Right child is smaller } else { // Swap with the right if it is smaller if (cmp_func(current->key, right_child->key) == 1) { SWAP_ENTRIES(current,right_child); current_index = left_child_index+1; current = right_child; // Current is smaller } else break; } // We only have a left child, only do something if the left is smaller } else if (cmp_func(current->key, left_child->key) == 1) { SWAP_ENTRIES(current,left_child); current_index = left_child_index; current = left_child; // Done otherwise } else break; } } // Check if we should release a page of memory int used_pages = entries / ENTRIES_PER_PAGE + ((entries % ENTRIES_PER_PAGE > 0) ? 1 : 0); // Allow one empty page, but not two if (h->allocated_pages > used_pages + 1 && h->allocated_pages > h->minimum_pages) { // Get the address of the page to delete void* addr = *(map_table+h->allocated_pages-1); // Map out map_out_pages(addr, 1); // Decrement the allocated count h->allocated_pages--; } // Success return 1; }
// Insert a new element void heap_insert(heap *h, void* key, void* value) { // Check if this heap is not destoyed assert(h->mapping_table != NULL); // Check if we have room int max_entries = h->allocated_pages * ENTRIES_PER_PAGE; if (h->active_entries + 1 > max_entries) { // Get the number of map pages int map_pages = h->map_pages; // We need a new page, do we have room? int mapable_pages = map_pages * PAGE_SIZE / sizeof(void*); // Check if we need to grow the map table if (h->allocated_pages + 1 > mapable_pages) { // Allocate a new table, slightly bigger void *new_table = map_in_pages(map_pages + 1); // Get the old table void *old_table = (void*)h->mapping_table; // Copy the old entries to the new table memcpy(new_table, old_table, map_pages * PAGE_SIZE); // Delete the old table map_out_pages(old_table, map_pages); // Swap to the new table h->mapping_table = (void**)new_table; // Update the number of map pages h->map_pages = map_pages + 1; } // Allocate a new page void* addr = map_in_pages(1); // Add this to the map *(h->mapping_table+h->allocated_pages) = addr; // Update the number of allocated pages h->allocated_pages++; } // Store the comparison function int (*cmp_func)(void*,void*) = h->compare_func; // Store the map table address void** map_table = h->mapping_table; // Get the current index int current_index = h->active_entries; heap_entry* current = GET_ENTRY(current_index, map_table); // Loop variables int parent_index; heap_entry *parent; // While we can, keep swapping with our parent while (current_index > 0) { // Get the parent index parent_index = PARENT_ENTRY(current_index); // Get the parent entry parent = GET_ENTRY(parent_index, map_table); // Compare the keys, and swap if we need to if (cmp_func(key, parent->key) < 0) { // Move the parent down current->key = parent->key; current->value = parent->value; // Move our reference current_index = parent_index; current = parent; // We are done swapping } else break; } // Insert at the current index current->key = key; current->value = value; // Increase the number of active entries h->active_entries++; }
static void cgen_expression(pSymbol func, pNode expr) { switch (GET_TYPE(expr)) { case EXPRESSION: { // Function call if (!GET_DATA(expr)) { puts("\t# Function call"); pNode iden = GET_CHILD(expr, 0), args = GET_CHILD(expr, 1); for (size_t i = 0; i < GET_SIZE(args); i++) { printf("\t# Arg num %zu\n", i); pNode arg = GET_CHILD(args, i); cgen_expression(func, arg); ASM1(pushq, %rax); } for (size_t i = 1; i <= GET_SIZE(args); i++) FASM1(popq, %s, record[GET_SIZE(args) - i]); FASM1(call, _%s, GET_ENTRY(iden)->name); puts(""); return; } puts("\t# Expression evaluation"); // Unary minus if (GET_SIZE(expr) == 1) { puts("\t# Unary minus"); pNode ch = GET_CHILD(expr, 0); ADDR(movq, cgen_resaddr(func, GET_ENTRY(ch)), %rax); ASM1(negq, %rax); return; } // Normal operator epxression pNode ch0 = GET_CHILD(expr, 0), ch1 = GET_CHILD(expr, 1); // Left hand side cgen_expression(func, ch0); ASM1(pushq, %rax); // Right hand side cgen_expression(func, ch1); ASM1(popq, %r8); switch (*(char *)GET_DATA(expr)) { case '+': puts("\t# Addition"); ASM2(addq, %r8, %rax); break; case '-': puts("\t# Subtraction"); ASM2(subq, %rax, %r8); ASM2(movq, %r8, %rax); break; case '*': puts("\t# Multiplication"); ASM0(cqo); ASM1(imulq, %r8); break; case '/': puts("\t# Divition"); ASM2(xchg, %rax, %r8); ASM0(cqo); ASM1(idivq, %r8); break; } puts(""); break; }