void destroy_itemset( struct itemset * this_itemset ) { int i; char * key; struct list * key_list = new_list(); list_keys_in_hash( this_itemset->items, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { key = listlookup( key_list, i ); struct item * data = hashlookup( this_itemset->items, key )->data; free( data ); } destroy_key_list( key_list ); destroy_hash( this_itemset->items ); key_list = new_list(); list_keys_in_hash( this_itemset->ready_for, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { key = listlookup( key_list, i ); struct list * ready_items = hashlookup( this_itemset->ready_for, key )->data; destroy_list( ready_items ); } destroy_key_list( key_list ); destroy_hash( this_itemset->ready_for ); destroy_list( this_itemset->complete ); free( this_itemset ); return; }
char * print_hash_key_set( struct hash * current ) { struct list * var_list = new_list(); list_keys_in_hash( current, var_list, "" ); int var_list_len = 0; int i = var_list->next_index; while ( i-- ) { var_list_len += strlen(listlookup( var_list, i )); } int brace_len = BRACE_LEN; int comma_len = COMMA_LEN; char * key_set_str = malloc( ( var_list->next_index * comma_len + var_list_len + 2 * brace_len + 1 ) * sizeof(char) ); *key_set_str = '\0'; sprintf( key_set_str, "{" ); i = var_list->next_index; while ( i-- ) { strcat( key_set_str, listlookup( var_list, i )); if ( i ) { strcat( key_set_str, "," ); } } strcat( key_set_str, "}" ); destroy_key_list(var_list); return key_set_str; }
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 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 fill_TRIE( struct hash * token_types ) { int i; char * path; char * accepting_type; TRIE = new_trie_node(); struct list * key_list = new_list(); list_keys_in_hash( token_types, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { path = listlookup( key_list, i ); accepting_type = hashlookup( token_types, path )->data; add_to_trie( TRIE, path, accepting_type ); } destroy_key_list( key_list ); return; }
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 ); } }
void wtls_pdu_destroy(wtls_PDU *pdu) { if (pdu == NULL) return; switch (pdu->type) { case ChangeCipher_PDU: /* no memory was allocated for ChangeCipher_PDU */ break; case Alert_PDU: octstr_destroy(pdu->u.alert.chksum ); break; case Handshake_PDU: switch (pdu->u.handshake.msg_type) { case hello_request: break; case client_hello: destroy_random(pdu->u.handshake.client_hello->random); octstr_destroy(pdu->u.handshake.client_hello->session_id); destroy_key_list(pdu->u.handshake.client_hello->client_key_ids); destroy_key_list(pdu->u.handshake.client_hello->trusted_key_ids); destroy_ciphersuite_list(pdu->u.handshake.client_hello->ciphersuites); destroy_compression_method_list(pdu->u.handshake.client_hello->comp_methods); /* destroy the client_hello struct */ gw_free(pdu->u.handshake.client_hello); break; case server_hello: destroy_random(pdu->u.handshake.server_hello->random); octstr_destroy(pdu->u.handshake.server_hello->session_id); /* destroy the server_hello struct */ gw_free(pdu->u.handshake.server_hello); break; case certificate: switch (pdu->u.handshake.certificate->certificateformat) { case WTLSCert: destroy_wtls_certificate(pdu->u.handshake.certificate->wtls_certificate); break; case X509Cert: octstr_destroy(pdu->u.handshake.certificate->x509_certificate); break; case X968Cert: octstr_destroy(pdu->u.handshake.certificate->x968_certificate); break; } gw_free(pdu->u.handshake.certificate); break; case server_key_exchange: destroy_param_spec(pdu->u.handshake.server_key_exchange->param_spec); switch (client_key_exchange_algo) { case rsa_anon: destroy_rsa_pubkey(pdu->u.handshake.server_key_exchange->rsa_params); break; case dh_anon: destroy_dh_pubkey(pdu->u.handshake.server_key_exchange->dh_params); break; case ecdh_anon: destroy_ec_pubkey(pdu->u.handshake.server_key_exchange->ecdh_params); break; } gw_free(pdu->u.handshake.server_key_exchange); break; case client_key_exchange: switch (client_key_exchange_algo) { case rsa: case rsa_anon: destroy_rsa_encrypted_secret(pdu->u.handshake.client_key_exchange->rsa_params); break; case dh_anon: destroy_dh_pubkey(pdu->u.handshake.client_key_exchange->dh_anon_params); break; case ecdh_anon: case ecdh_ecdsa: destroy_ec_pubkey(pdu->u.handshake.client_key_exchange->ecdh_params); break; } gw_free(pdu->u.handshake.client_key_exchange); break; case server_hello_done: /* nothing to do here */ break; } break; case Application_PDU: octstr_destroy(pdu->u.application.data); break; } gw_free(pdu); }
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; }