void * hinsert(htable_t *ht, void *key, int key_len, void *data, hcallback_func_t *destructor, hcallback_func_t *can_replace, hcallback_func_t *do_delete, int *did_delete) { uint32_t index; hash_entry_t *hen; hash_entry_t *hen_old; void *data_old = NULL; null_if_null(ht); index = h_index(ht, key, key_len); hen = h_entry(ht, index, key, key_len); hen_old = hen; data_old = hen ? hen->data : NULL; if (did_delete) { *did_delete = 0; } if(can_replace != NULL && !can_replace(key, key_len, data_old, data)) { return data; } if (NULL == (hen = h_alloc_hen(key_len))) { return data; } if (hen_old) { /* * entry already exists - we are about to replace it. * * If not for the iterators, we'd be all fine and dandy. * * But there can be iterators referencing this item * (hence, can't wipe out key/data). */ h_try_delete(ht, hen_old, do_delete, did_delete); } else { if (did_delete) { *did_delete = 0; } } /* * fill in the new hen */ memcpy(hen->key, key, key_len); hen->data = data; hen->destructor = destructor; LIST_INSERT_HEAD(&ht->buckets[index], hen, entries); // inserting in the head of all entries ensures we don't have // to mess with the iterators LIST_INSERT_HEAD(&ht->all_entries, hen, all_entries); // successfully inserted ht->total_items++; return data_old; }
static int replace(int argc, const char *argv[], char *newstr) { int i,j,k; struct { char *op; char *str; int max_operands; } ops[] = { { "add", "1 = 2 + 3", 3}, { "addi", "1 = 2 + 3", 3}, { "addiu", "1 = 2 + 3", 3}, { "addu", "1 = 2 + 3", 3}, { "and", "1 = 2 & 3", 3}, { "andi", "1 = 2 & 3", 3}, { "b", "goto 1", 1}, { "bal", "call 1", 1}, { "begzal", "if (1 >= 0) call 2", 2}, { "beq", "if (1 == 2) goto 3", 3}, { "beqz", "if (!1) goto 2", 2}, { "bgez", "if (1 >= 0) goto 2", 2}, { "bgtz", "if (1 > 0) goto 2", 2}, { "blez", "if (1 <= 0) goto 2", 2}, { "bltz", "if (1 < 0) goto 2", 2}, { "bltzal", "if (1 < 0) call 2", 2}, { "bne", "if (1 != 2) goto 3", 3}, { "bnez", "if (1) goto 2", 2}, { "j", "goto 1", 1}, { "jal", "call 1", 1}, { "jalr", "call 1", 1}, { "jr", "goto 1", 1}, { "lb", "1 = byte [3 + 2]", 3}, { "lbu", "1 = (unsigned) byte [3 + 2]", 3}, { "lh", "1 = halfword [3 + 2]", 3}, { "lhu", "1 = (unsigned) halfword [3 + 2]", 3}, { "li", "1 = 2", 2}, { "lui", "1 = 2 << 16", 2}, { "lw", "1 = [3 + 2]", 3}, { "mfhi", "1 = hi", 1}, { "mflo", "1 = lo", 1}, { "move", "1 = 2", 2}, { "movn", "if (3) 1 = 2", 3}, { "movz", "if (!3) 1 = 2", 3}, { "mult", "(hi,lo) = 1 * 2", 2}, { "multu", "unsigned (hi,lo) = 1 * 2", 2}, { "mul", "1 = 2 * 3", 3}, { "mulu", "1 = 2 * 3", 3}, { "negu", "1 = ~2", 2}, { "nop", "", 0}, { "nor", "1 = ~(2 | 3)", 3}, { "or", "1 = 2 | 3", 3}, { "ori", "1 = 2 | 3", 3}, { "sb", "byte [3 + 2] = 1", 3}, { "sh", "halfword [3 + 2] = 1", 3}, { "sll", "1 = 2 << 3", 3}, { "sllv", "1 = 2 << 3", 3}, { "slr", "1 = 2 >> 3", 3}, // logic { "slt", "1 = (2 < 3)", 3}, { "slti", "1 = (2 < 3)", 3}, { "sltiu", "1 = (unsigned) (2 < 3)", 3}, { "sltu", "1 = (unsigned) (2 < 3)", 3}, { "sra", "1 = (signed) 2 >> 3", 3}, // arithmetic { "srl", "1 = 2 >> 3", 3}, { "srlv", "1 = 2 >> 3", 3}, { "subu", "1 = 2 - 3", 3}, { "sub", "1 = 2 - 3", 3}, { "sw", "[3 + 2] = 1", 3}, { "syscall", "syscall", 0}, { "xor", "1 = 2 ^ 3", 3}, { "xori", "1 = 2 ^ 3", 3}, { NULL } }; for (i=0; ops[i].op != NULL; i++) { if (!strcmp (ops[i].op, argv[0])) { if (newstr != NULL) { for (j=k=0;ops[i].str[j]!='\0';j++,k++) { if (can_replace (ops[i].str, j, ops[i].max_operands)) { const char *w = argv[ ops[i].str[j]-'0' ]; if (w != NULL) { strcpy (newstr+k, w); k += strlen (w) - 1; } } else { newstr[k] = ops[i].str[j]; } } newstr[k]='\0'; } return true; } } /* TODO: this is slow */ if (newstr != NULL) { newstr[0] = '\0'; for (i=0; i<argc; i++) { strcat (newstr, argv[i]); strcat (newstr, (i == 0 || i== argc - 1)?" ":", "); } } return false; }