void init_NODE_HASH() { NODE_HASH = new_hash(); add_to_hash( NODE_HASH, "BETA", (void *) new_hash() ); add_to_hash( NODE_HASH, "LAMBDA", (void *) new_hash() ); add_to_hash( NODE_HASH, "VAR", (void *) new_hash() ); return; }
int add_to_double_hash(double_hash_t* hash, dc_t* cell) { if(add_to_hash(hash->dhash, hash->hash_size, cell, DHASH)<0) return -1; if(add_to_hash(hash->chash, hash->hash_size, cell, CHASH)<0) { remove_from_hash(hash->dhash, hash->hash_size, cell, DHASH); return -1; } return 0; }
void add_initial_itemset( struct parser_generator * self ) { struct item * initial_item = new_item(); char * initial_item_key = create_item_key( initial_item ); struct itemset * initial_itemset = new_itemset(); add_to_hash( initial_itemset->items, initial_item_key, (void *) initial_item ); free( initial_item_key ); char * initial_itemset_key = create_closure_key( initial_itemset ); append_to_list( self->itemsets, (void *) initial_itemset ); int initial_state = self->itemsets->next_index - 1; add_to_hash( self->itemsets_by_key, initial_itemset_key, (void *) (long int) initial_state ); free( initial_itemset_key ); return; }
/** * Tries to generate a blank challenge. * @param word_length The total length of the word. * @param max_sol The number of maximum solutions allowed. * @param num_blanks Number of blanks. * @return 1 if success, 0 if failure */ int try_generate_blank_challenge(int word_length, int max_sol, int num_blanks, NODE* node, FILE* fp) { char str[16]; int success, i; gen_random_rack(str, word_length - num_blanks, num_blanks); success = anagram(node, str, "anagram", &answers, 0, max_sol); if (success) { for (i = 0; i < answers.num_answers; i++) { if (g_hash_table_contains(all_answers_hash, answers.answers[i])) { // This answer is already in the all_answers_hash; don't // allow. printf("Generated duplicate, ignoring, %s, %s\n", str, answers.answers[i]); cleanup_answers(&answers); return 0; } } fprintf(fp, "%s ", str); for (i = 0; i < answers.num_answers; i++) { add_to_hash(answers.answers[i]); fprintf(fp, "%s ", answers.answers[i]); } fprintf(fp, "\n"); cleanup_answers(&answers); } return success; }
static void add_edge1(HASH *hash, NODE *from, NODE *to, EDGE_TYPE type) { HASH_ENTRY *he = find_in_hash(hash, from, sizeof(void *)); HASH *subhash; if (he) { subhash = he->data; } else { subhash = create_hash(10, key_type_direct); add_to_hash(hash, from, sizeof(void *), subhash); } add_to_hash(subhash, to, sizeof(void *), (void *) type); }
char *add_string(MODULE *module, char *str, size_t len) { HASH_ENTRY *he = find_in_hash(module->strings, str, len); if (he) return he->data; str = strndup(str, len); add_to_hash(module->strings, str, len, str); return str; }
static void populate_keywords() { KEYWORD *k; keyword_map = create_hash(20, key_type_indirect); for (k = keywords; k->word; k++) { add_to_hash(keyword_map, k->word, strlen(k->word), (void *) k->id); } }
void fill_FIRST() { FIRST = new_hash(); int i; int j; char * symbol; char * lhs; char * left_corner; struct list * key_list = new_list(); list_keys_in_hash( IS_TERMINAL, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { symbol = listlookup( key_list, i ); struct hash * symbol_firsts = new_hash(); if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &TRUE ) { // Terminals self-derive. add_to_hash( symbol_firsts, symbol, (void *) (long int) 1 ); } add_to_hash( FIRST, symbol, (void *) symbol_firsts ); } destroy_key_list( key_list ); int change = 1; while ( change ) { change = 0; for ( i = 0; i < NUM_PRODUCTIONS; i++ ) { struct list * production = GRAMMAR[i].production; lhs = listlookup( production, 0 ); left_corner = listlookup( production, 1 ); key_list = new_list(); list_keys_in_hash( hashlookup( FIRST, left_corner )->data, key_list, "" ); for ( j = 0; j < key_list->next_index; j++ ) { // Go through all the firsts of left_corner. symbol = listlookup( key_list, j ); struct hash * lhs_firsts = hashlookup( FIRST, lhs )->data; struct hash * looked_up = hashlookup( lhs_firsts, symbol ); if ( ! looked_up ) { add_to_hash( lhs_firsts, symbol, (void *) &TRUE ); // Add them to firsts of lhs. change = 1; } } destroy_key_list( key_list ); } } }
void analyze_productions() { GSIZE = NUM_PRODUCTIONS; int i; int j; struct list * production; struct list * productions_for_symbol; char * symbol; if ( ! IS_TERMINAL ) { IS_TERMINAL = new_hash(); } if ( ! PRODUCTIONS_FOR ) { PRODUCTIONS_FOR = new_hash(); } for ( i = 0; i < NUM_PRODUCTIONS; i++ ) { production = GRAMMAR[i].production; if ( production->next_index > GSIZE ) { GSIZE = production->next_index; } for ( j = 0; j < production->next_index; j++ ) { symbol = listlookup( production, j ); struct hash * looked_up = hashlookup( IS_TERMINAL, symbol ); if ( ! looked_up ) { // Assume each new symbol is a terminal. add_to_hash( IS_TERMINAL, symbol, (void *) &TRUE ); } if ( j == 0 ) { // Symbols on the left side of a productions are nonterminal. add_to_hash( IS_TERMINAL, symbol, (void *) &FALSE ); looked_up = hashlookup( PRODUCTIONS_FOR, symbol ); if ( ! looked_up ) { productions_for_symbol = new_list(); add_to_hash( PRODUCTIONS_FOR, symbol, (void *) productions_for_symbol ); } else { productions_for_symbol = looked_up->data; } append_to_list( productions_for_symbol, (void *) (long int) i ); } } } }
void fill_FOLLOW() { FOLLOW = new_hash(); char * symbol; char * next_symbol; char * lhs; int i; int j; struct list * production; int change; struct hash * symbol_followers; struct list * key_list = new_list(); list_keys_in_hash( IS_TERMINAL, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { symbol = listlookup( key_list, i ); if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &FALSE ) { symbol_followers = new_hash(); add_to_hash( FOLLOW, symbol, (void *) symbol_followers ); } } destroy_key_list( key_list ); change = 1; while ( change ) { change = 0; for ( i = 0; i < NUM_PRODUCTIONS; i++ ) { production = GRAMMAR[i].production; lhs = listlookup( production, 0 ); for ( j = 1; j < production->next_index; j++ ) { // Loop RHS symbols. symbol = listlookup( production, j ); if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &TRUE ) { // No FOLLOW for terminals. continue; } symbol_followers = hashlookup( FOLLOW, symbol )->data; if ( j + 1 < production->next_index ) { // There is an adjacent symbol. next_symbol = listlookup( production, j + 1 ); struct hash * next_symbol_firsts = hashlookup( FIRST, next_symbol )->data; // Everything in FIRST{next_symbol} should be in FOLLOW{symbol}. change = expand_hash( symbol_followers, next_symbol_firsts ) || change; continue; } else { // Last symbol in production is nonterminal. struct hash * lhs_followers = hashlookup( FOLLOW, lhs )->data; // Everything in FOLLOW{lhs} should be in FOLLOW{symbol}. change = expand_hash( symbol_followers, lhs_followers ) || change; continue; } } } } }
struct hash * copy_shallow_hash( struct hash * original ) { struct hash * copy = new_hash(); struct list * key_list = new_list(); list_keys_in_hash( original, key_list, "" ); char * key = NULL; int i = key_list->next_index; while ( i-- ) { key = listlookup( key_list, i ); add_to_hash( copy, key, hashlookup( original, key ) ); } destroy_key_list( key_list ); return copy; }
void install_incomplete_transitions( int i, struct itemset * current_itemset, struct parser_generator * self ) { struct list * itemsets = self->itemsets; struct hash * itemsets_by_key = self->itemsets_by_key; struct hash * ready_for = current_itemset->ready_for; // Prepare to loop through the keys of current_itemset->ready_for. struct list * key_list = new_list(); list_keys_in_hash( ready_for, key_list, "" ); int j; int k; for ( j = 0; j < key_list->next_index; j++ ) { // Loop ready-for symbols. char * symbol = listlookup( key_list, j ); struct list * ready_for_symbol = hashlookup( ready_for, symbol )->data; struct itemset * proposed_itemset = new_itemset(); for ( k = 0; k < ready_for_symbol->next_index; k++ ) { // Loop symbol items. struct item * ready_item = listlookup( ready_for_symbol, k ); struct item * proposed_item = new_item(); proposed_item->prod_num = ready_item->prod_num; proposed_item->dot = ready_item->dot + 1; char * proposed_item_key = create_item_key( proposed_item ); add_to_hash( proposed_itemset->items, proposed_item_key, (void *) proposed_item ); free( proposed_item_key ); // It's now in the hash. } // End symbol items loop. char * proposed_itemset_key = create_closure_key( proposed_itemset ); struct hash * looked_up = hashlookup( itemsets_by_key, proposed_itemset_key ); if ( ! looked_up ) { append_to_list( itemsets, (void *) proposed_itemset ); int state_num = itemsets->next_index - 1; looked_up = add_to_hash( itemsets_by_key, proposed_itemset_key, (void *) (long int) state_num ); } else { destroy_itemset( proposed_itemset ); } int destination = (long int) looked_up->data; install_incomplete_transition( i, symbol, destination, self ); } // End ready-for symbols loop. return; }
int main() { struct hash * frequency_hash = new_hash(); char char_string[2] = { ' ', '\0' }; int number_of_characters = 0; int i; char c; while ( ( c = getchar() ) != EOF ) { if ( c == '\n' ) { continue; } char_string[0] = c; struct hash * looked_up = hashlookup( frequency_hash, char_string ); struct index_frequency * data; if ( !looked_up ) { data = malloc( sizeof( struct index_frequency ) ); data->index = number_of_characters; data->frequency = 0; looked_up = add_to_hash( frequency_hash, char_string, (void *) data ); } data = looked_up->data; int frequency = data->frequency; data->frequency = frequency + 1; number_of_characters++; } struct list * key_list = new_list(); list_keys_in_hash( frequency_hash, key_list, "" ); int min_index = number_of_characters + 1; char * min_key = ""; int min_frequency = number_of_characters + 1; for ( i = 0; i < key_list->next_index; i++ ) { char * key = listlookup( key_list, i ); struct index_frequency * data; data = hashlookup( frequency_hash, key )->data; if ( data->frequency < min_frequency ) { min_index = data->index; min_frequency = data->frequency; min_key = key; } else if ( data->frequency == min_frequency ) { if ( data->index < min_index ) { min_index = data->index; min_key = key; } } } printf( "The first non-repeated character is: \n%s\n", min_key ); }
static enum TDB_ERROR replace_data(struct tdb_context *tdb, struct hash_info *h, struct tdb_data key, struct tdb_data dbuf, tdb_off_t old_off, tdb_len_t old_room, bool growing) { tdb_off_t new_off; enum TDB_ERROR ecode; /* Allocate a new record. */ new_off = alloc(tdb, key.dsize, dbuf.dsize, h->h, TDB_USED_MAGIC, growing); if (TDB_OFF_IS_ERR(new_off)) { return new_off; } /* We didn't like the existing one: remove it. */ if (old_off) { tdb->stats.frees++; ecode = add_free_record(tdb, old_off, sizeof(struct tdb_used_record) + key.dsize + old_room, TDB_LOCK_WAIT, true); if (ecode == TDB_SUCCESS) ecode = replace_in_hash(tdb, h, new_off); } else { ecode = add_to_hash(tdb, h, new_off); } if (ecode != TDB_SUCCESS) { return ecode; } new_off += sizeof(struct tdb_used_record); ecode = tdb->methods->twrite(tdb, new_off, key.dptr, key.dsize); if (ecode != TDB_SUCCESS) { return ecode; } new_off += key.dsize; ecode = tdb->methods->twrite(tdb, new_off, dbuf.dptr, dbuf.dsize); if (ecode != TDB_SUCCESS) { return ecode; } if (tdb->flags & TDB_SEQNUM) tdb_inc_seqnum(tdb); return TDB_SUCCESS; }
void install_incomplete_transition( int i, char * symbol, int destination, struct parser_generator * self ) { struct hash * table_row = listlookup( self->TABLE, i ); struct hash * goto_row = listlookup( self->GOTO, i ); struct list * trans_list; struct hash * looked_up; if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &TRUE ) { // Transitions on terminals go in TABLE. looked_up = hashlookup( table_row, symbol ); if ( ! looked_up ) { trans_list = new_list(); add_to_hash( table_row, symbol, (void *) trans_list ); } else { trans_list = looked_up->data; } struct transition * terminal_transition = new_transition(); terminal_transition->action = "shift"; terminal_transition->arg = destination; if ( ! strcmp( symbol, "end" ) ) { terminal_transition->action = "accept"; } append_to_list( trans_list, (void *) terminal_transition ); } else { // Transitions on nonterminals go in GOTO. looked_up = hashlookup( goto_row, symbol ); if ( ! looked_up ) { trans_list = new_list(); add_to_hash( goto_row, symbol, (void *) trans_list ); } else { trans_list = looked_up->data; } append_to_list( trans_list, (void *) (long int) destination ); } }
static void pp_add_new_ts(Poco_cb *pcb, char *name, char *value, SHORT pcount, Ts_flags flags) /***************************************************************************** * allocate a new Text_symbol, fill in the fields, add to hash table. ****************************************************************************/ { register Text_symbol *ts; ts = po_memalloc(pcb, sizeof(Text_symbol)); ts->name = name; ts->value = value; ts->parmcount = pcount; ts->flags = flags; add_to_hash(ts, pcb->t.define_list); }
static enum NTDB_ERROR replace_data(struct ntdb_context *ntdb, struct hash_info *h, NTDB_DATA key, NTDB_DATA dbuf, ntdb_off_t old_off, ntdb_len_t old_room, bool growing) { ntdb_off_t new_off; enum NTDB_ERROR ecode; /* Allocate a new record. */ new_off = alloc(ntdb, key.dsize, dbuf.dsize, NTDB_USED_MAGIC, growing); if (NTDB_OFF_IS_ERR(new_off)) { return NTDB_OFF_TO_ERR(new_off); } /* We didn't like the existing one: remove it. */ if (old_off) { ntdb->stats.frees++; ecode = add_free_record(ntdb, old_off, sizeof(struct ntdb_used_record) + key.dsize + old_room, NTDB_LOCK_WAIT, true); if (ecode == NTDB_SUCCESS) ecode = replace_in_hash(ntdb, h, new_off); } else { ecode = add_to_hash(ntdb, h, new_off); } if (ecode != NTDB_SUCCESS) { return ecode; } new_off += sizeof(struct ntdb_used_record); ecode = ntdb->io->twrite(ntdb, new_off, key.dptr, key.dsize); if (ecode != NTDB_SUCCESS) { return ecode; } new_off += key.dsize; ecode = ntdb->io->twrite(ntdb, new_off, dbuf.dptr, dbuf.dsize); if (ecode != NTDB_SUCCESS) { return ecode; } if (ntdb->flags & NTDB_SEQNUM) ntdb_inc_seqnum(ntdb); return NTDB_SUCCESS; }
int main(){ while (1) { char* word; word = malloc(200); scanf("%s", word); add_to_hash(word); free(word); if (should_stop()){ break; } } sort_all(); print_all(); return 0; }
void add_vertex(GRAPH *graph, NODE *vertex) { if (!vertex) { /* N.B. Vertex positions are sometimes important, so a NULL one still needs to occupy a position in the child list. */ tree_add_child(graph, vertex); return; } HASH_ENTRY *he = find_in_hash(graph->labels, vertex, sizeof(void *)); if (he) return; add_to_hash(graph->labels, vertex, sizeof(void *), (void *) tree_num_children(graph)); tree_add_child(graph, vertex); }
struct hash * add_pairs_to_hash( struct hash * my_hash, int num_pairs, ... ) { va_list arg_pointer; char * key; void * value; va_start( arg_pointer, num_pairs ); while ( num_pairs-- ) { key = va_arg( arg_pointer, char * ); value = va_arg( arg_pointer, void * ); add_to_hash( my_hash, key, value ); } return my_hash; }
int expand_hash( struct hash * target, struct hash * source ) { int i; char * symbol; void * value; int change = 0; struct list * key_list = new_list(); list_keys_in_hash( source, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { symbol = listlookup( key_list, i ); struct hash * looked_up = hashlookup( target, symbol ); if ( ! looked_up ) { value = hashlookup( source, symbol )->data; add_to_hash( target, symbol, value ); // Use the same value or pointer. change = 1; } } return change; }
EXPRESSION *make_new_temp(MODULE *module, FUNCTION *func, TYPE *type, int source_line) { static int next_id = 0; char next_name[100]; if (!type) error("declaration needs a type!"); sprintf(next_name, "$t%d", next_id++); char *str = add_string(module, next_name, strlen(next_name)); DECLARATION *new_temp = make_declaration(type, str, source_line); add_to_hash(func->table, str, strlen(str), new_temp); VARIABLE *new_var = CAST_TO_VARIABLE(make_variable(str, source_line)); new_var->decl = new_temp; EXPRESSION *new_expr = CAST_TO_EXPRESSION(new_var); new_expr->type = type; return new_expr; }
EXPRESSION *make_closure(MODULE *mod, TYPE *type, DECLARATION *args, BLOCK *body, int source_line) { static int next_id = 0; char name[100]; sprintf(name, "closure%d", next_id++); char *str = add_string(mod, name, strlen(name)); FUNCTION *func = make_function(type, str, args, source_line); tree_get_child(func, 0) = body; EXPRESSION *expr = create_ast_node(EXPR_CLOSURE, source_line); tree_add_child(expr, func); expr->type = make_map_type(args->type, type, source_line); /* Add new function to module. */ tree_add_child(mod, func); add_to_hash(mod->table, str, strlen(str), func); return expr; }
int main (int argc, char **argv) { GHashTable *hash; g_type_init (); hash = g_hash_table_new (g_str_hash, g_str_equal); add_to_hash (hash, "image_hash", "10YnP"); add_to_hash (hash, "small_thumbnail", "http://i.imgur.com/10YnPs.jpg"); add_to_hash (hash, "original_image", "http://i.imgur.com/10YnP.jpg"); add_to_hash (hash, "large_thumbnail", "http://i.imgur.com/10YnPl.jpg"); add_to_hash (hash, "delete_hash", "inQAUnHqeypbFs0"); add_to_hash (hash, "delete_page", "http://imgur.com/delete/inQAUnHqeypbFs0"); add_to_hash (hash, "imgur_page", "http://imgur.com/10YnP"); imgur_recording_store (hash, "/tmp/lsm.jpg"); }
void install_complete_transitions( int i, struct itemset * current_itemset, struct parser_generator * self ) { struct list * table = self->TABLE; struct list * complete_items = current_itemset->complete; char * lhs; struct item * complete_item; struct list * complete_production; int j; int k; struct hash * table_row = listlookup( self->TABLE, i ); for ( j = 0; j < complete_items->next_index; j++ ) { complete_item = listlookup( complete_items, j ); int prod_num = complete_item->prod_num; complete_production = GRAMMAR[prod_num].production; lhs = listlookup( complete_production, 0 ); // Loop all terminals which can follow this lhs. struct list * key_list = new_list(); list_keys_in_hash( hashlookup( FOLLOW, lhs )->data, key_list, "" ); for ( k = 0; k < key_list->next_index; k++ ) { struct list * trans_list; char * follower = listlookup( key_list, k ); // Add a reduce transition on each follower token. struct hash * looked_up = hashlookup( table_row, follower ); if ( ! looked_up ) { trans_list = new_list(); add_to_hash( table_row, follower, (void *) trans_list ); } else { trans_list = looked_up->data; } struct transition * reduce_transition = new_transition(); reduce_transition->action = "reduce"; reduce_transition->arg = prod_num; append_to_list( trans_list, reduce_transition ); } destroy_key_list( key_list ); } }
int Upload_stream(Connection *conn, Handler *handler, int content_len) { char *data = NULL; int avail = 0; int offset = 0; int first_chunk = 1; int rc; hash_t *altheaders = NULL; bstring offsetstr; debug("max content length: %d, content_len: %d", MAX_CONTENT_LENGTH, content_len); IOBuf_resize(conn->iob, MAX_CONTENT_LENGTH); // give us a good buffer size while(content_len > 0) { if(first_chunk) { // read whatever's there data = IOBuf_read_some(conn->iob, &avail); } else if(conn->sendCredits > 0) { // read up to credits data = IOBuf_read(conn->iob, conn->sendCredits < content_len ? conn->sendCredits : content_len, &avail); conn->sendCredits -= avail; } else { // sleep until we have credits tasksleep(&conn->uploadRendez); continue; } check(!IOBuf_closed(conn->iob), "Closed while reading from IOBuf."); content_len -= avail; offsetstr = bformat("%d", offset); if(first_chunk) { Request_set(conn->req, &UPLOAD_STREAM, offsetstr, 1); if(content_len == 0) { Request_set(conn->req, &UPLOAD_STREAM_DONE, bfromcstr("1"), 1); } } else { altheaders = hash_create(2, (hash_comp_t)bstrcmp, bstr_hash_fun); add_to_hash(altheaders, &UPLOAD_STREAM, offsetstr); if(content_len == 0) { add_to_hash(altheaders, &UPLOAD_STREAM_DONE, bfromcstr("1")); } } rc = Connection_send_to_handler(conn, handler, data, avail, altheaders); check_debug(rc == 0, "Failed to deliver to the handler."); if(altheaders != NULL) { hash_free_nodes(altheaders); hash_destroy(altheaders); altheaders = NULL; } check(IOBuf_read_commit(conn->iob, avail) != -1, "Commit failed while streaming."); first_chunk = 0; offset += avail; } check(content_len == 0, "Failed to write everything to the large upload tmpfile."); return 0; error: return -1; }
int pdt_add_to_hash(hash_list_t *hl, str* sdomain, str *sp, str *sd) { hash_t *it, *prev, *ph; if(hl==NULL || sdomain==NULL || sdomain->s==NULL || sp==NULL || sp->s==NULL || sd==NULL || sd->s==NULL) { LM_ERR("bad parameters\n"); return -1; } lock_get(&hl->hl_lock); /* search the it position where to insert new domain */ it = hl->hash; prev=NULL; while(it!=NULL && str_strcmp(&it->sdomain, sdomain)<0) { prev=it; it=it->next; } /* add new sdomain, i.e. new entry in the hash list */ if(it==NULL || str_strcmp(&it->sdomain, sdomain)>0) { /* !!!! check this hash size setting mode */ ph = init_hash(hl->hash_size, sdomain); if(ph==NULL) { LM_ERR("null pointer returned\n"); goto error1; } if(add_to_hash(ph, sp, sd)<0) { LM_ERR("could not add to hash\n"); goto error; } if(prev==NULL) /* list initially empty */ hl->hash = ph; else prev->next = ph; ph->next = it; } else { /* it is the entry of sdomain, just add a new prefix/domain pair * to its hash */ if(add_to_hash(it, sp, sd)<0) { LM_ERR("could not add to hash\n"); goto error1; } } lock_release(&hl->hl_lock); return 0; error: free_hash(ph); error1: lock_release(&hl->hl_lock); return -1; }
char * create_closure_key( struct itemset * current_itemset ) { struct item * current_item; struct hash * looked_up; struct list * production; int p; int d; int i; // Push all the items in the itemset onto the unchecked stack. struct list * unchecked = new_list(); struct hash * current_items = current_itemset->items; struct list * key_list = new_list(); list_keys_in_hash( current_items, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { char * key = listlookup( key_list, i ); append_to_list( unchecked, (void *) hashlookup( current_items, key )->data ); } destroy_key_list( key_list ); // Now process unchecked items, possibly adding more along the way. while ( unchecked->next_index ) { current_item = pop_from_list( unchecked ); p = current_item->prod_num; d = current_item->dot; production = GRAMMAR[p].production; if ( d == production->next_index - 1 ) { // This item is complete. append_to_list( current_itemset->complete, (void *) current_item ); continue; // Nothing more to do here. } // Otherwise, this item is incomplete, // so record it in the appropriate ready_for slot for this itemset. char * predicted = listlookup( production, d + 1 ); struct list * items_ready_for = NULL; struct hash * looked_up = hashlookup( current_itemset->ready_for, predicted ); if ( ! looked_up ) { items_ready_for = new_list(); add_to_hash( current_itemset->ready_for, predicted, (void *) items_ready_for ); } else { items_ready_for = looked_up->data; } append_to_list( items_ready_for, (void *) current_item ); // If the predicted symbol is terminal, this item is done processing. if ( ( (int *) hashlookup( IS_TERMINAL, predicted )->data ) == &TRUE ) { continue; // Can't expand terminals. } // Otherwise, the predicted symbol is nonterminal, // so expand the itemset using all applicable productions. struct list * predicted_productions = hashlookup( PRODUCTIONS_FOR, predicted )->data; for ( i = 0; i < predicted_productions->next_index; i++ ) { int predicted_p = (long int) listlookup( predicted_productions, i ); struct item * predicted_item = new_item(); predicted_item->prod_num = predicted_p; char * predicted_key = create_item_key( predicted_item ); if ( looked_up = hashlookup( current_items, predicted_key ) ) { // Item unneeded. free( predicted_item ); free( predicted_key ); continue; } // Otherwise, add the new item to the itemset, and to the unchecked stack. add_to_hash( current_items, predicted_key, (void *) predicted_item ); free( predicted_key ); append_to_list( unchecked, (void *) predicted_item ); } } // Now that the itemset has been filled out, create and return its identifying string. key_list = new_list(); list_keys_in_hash( current_items, key_list, "" ); char * closure_key = join_key_list( key_list, "_" ); destroy_key_list( key_list ); return closure_key; }
int emit_function(FUNCTION *func, EMIT_FUNCTIONS *functions, void *data) { GRAPH *graph = func->graph; QUEUE *queue = create_queue(); HASH *done = create_hash(10, key_type_direct); queue_push(queue, tree_get_child(graph, 0)); NODE *last = NULL; while (!queue_is_empty(queue)) { NODE *vertex = queue_pop(queue); if (find_in_hash(done, vertex, sizeof(void *))) continue; do_next: add_to_hash(done, vertex, sizeof(void *), (void *) 1); int label = (int) get_from_hash(graph->labels, vertex, sizeof(void *)); HASH *predecessor_hash = get_from_hash(graph->backward, vertex, sizeof(void *)); HASH_ITERATOR iter; hash_iterator(predecessor_hash, &iter); if (predecessor_hash && (predecessor_hash->num > 1 || (predecessor_hash->num == 1 && last != iter.entry->key))) { functions->emit_label(label, data); } functions->emit_comment(vertex, data); HASH *successor_hash = get_from_hash(graph->forward, vertex, sizeof(void *)); NODE *successor; int successor_label; if (successor_hash) { hash_iterator(successor_hash, &iter); successor = iter.entry->key; successor_label = (int) get_from_hash(graph->labels, successor, sizeof(void *)); } else successor = NULL; if (tree_is_type(vertex, STMT_ENTER)) { functions->emit_enter(vertex, data); } else if (tree_is_type(vertex, STMT_EXIT)) { functions->emit_exit(vertex, data); last = vertex; continue; } else if (tree_is_type(vertex, STMT_ASSIGN)) functions->emit_assign(vertex, data); else if (tree_is_type(vertex, STMT_RETURN)) functions->emit_return(vertex, data); else if (tree_is_type(vertex, STMT_TEST)) { hash_iterator_next(&iter); NODE *branch = iter.entry->key; EDGE_TYPE branch_type = (EDGE_TYPE) iter.entry->data; int branch_label = (int) get_from_hash(graph->labels, branch, sizeof(void *)); functions->emit_test(vertex, branch_type, branch_label, data); if (!find_in_hash(done, branch, sizeof(void *))) queue_push(queue, branch); /* Force label on next vertex, in case we jumped to it in the test's branch. Fixes a bug where the label is omitted just because the test was before it, by neglecting to notice that the test reaches it by a jump. */ vertex = NULL; } last = vertex; if (find_in_hash(done, successor, sizeof(void *))) { functions->emit_jump(successor_label, data); continue; } vertex = successor; if (vertex) goto do_next; } functions->emit_end(data); destroy_queue(queue); destroy_hash(done); return 1; }