示例#1
0
struct itemset * new_itemset() {
    struct itemset * this_itemset = malloc( sizeof( struct itemset ) );
    this_itemset->items = new_hash();
    this_itemset->ready_for = new_hash();
    this_itemset->complete = new_list();
    return this_itemset;
}
示例#2
0
void fill_TABLES() {
    struct hash * looked_up;
    struct hash * row;
    struct parser_generator * parser_generator = new_parser_generator();
    append_to_list( parser_generator->TABLE, new_hash() );
    append_to_list( parser_generator->GOTO, new_hash() );
    add_initial_itemset( parser_generator );
    struct list * itemsets = parser_generator->itemsets;
    int i = 0;
    while ( i < parser_generator->itemsets->next_index ) {
        struct itemset * current_itemset = listlookup( itemsets, i );
        looked_up = listlookup( parser_generator->TABLE, i );
        if ( ! looked_up ) {
            row = new_hash();
            append_to_list( parser_generator->TABLE, row );
        }
        looked_up = listlookup( parser_generator->GOTO, i );
        if ( ! looked_up ) {
            row = new_hash();
            append_to_list( parser_generator->GOTO, row );
        }
        install_incomplete_transitions( i, current_itemset, parser_generator );
        install_complete_transitions( i, current_itemset, parser_generator );
        i++;
    }
    TABLE = parser_generator->TABLE;
    GOTO = parser_generator->GOTO;
    
}
示例#3
0
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;
}
示例#4
0
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 * hash_leaf_node( struct hash_search_state search_state, void * value ) {
    struct hash * new_node = new_hash();
    char * unmatched = search_state.str + search_state.num_matched;
    char decision_char = *(unmatched++); // Unmatched portion starts after decision char.
    char * new_sigstr = malloc( ( strlen(unmatched) + 1 ) * sizeof(char) );
    strcpy( new_sigstr, unmatched );
    new_node->sigstr = new_sigstr;
    new_node->data = value;
    add_to_charhash( search_state.node->child, decision_char, new_node );
    search_state.node->num_children++;
    return new_node;
}
示例#6
0
struct parser_generator * new_parser_generator() {
    struct list * my_itemsets = new_list();
    struct hash * my_itemsets_by_key = new_hash();
    struct list * my_TABLE = new_list();
    struct list * my_GOTO = new_list();
    struct parser_generator * this_parser_generator = malloc( sizeof( struct parser_generator ) );
    this_parser_generator->itemsets = my_itemsets;
    this_parser_generator->itemsets_by_key = my_itemsets_by_key;
    this_parser_generator->TABLE = my_TABLE;
    this_parser_generator->GOTO = my_GOTO;
    return this_parser_generator;
}
示例#7
0
/* Dumps data from a single thread. */
static MVMObject * dump_thread_data(MVMThreadContext *tc, ProfDumpStrs *pds,
                                    const MVMProfileThreadData *ptd) {
    MVMObject *thread_hash = new_hash(tc);
    MVMObject *thread_gcs  = new_array(tc);
    MVMuint32  i;

    /* Add time. */
    MVM_repr_bind_key_o(tc, thread_hash, pds->total_time,
        box_i(tc, (ptd->end_time - ptd->start_time) / 1000));

    /* Add call graph. */
    if (ptd->call_graph)
        MVM_repr_bind_key_o(tc, thread_hash, pds->call_graph,
            dump_call_graph_node(tc, pds, ptd->call_graph));

    /* Add GCs. */
    for (i = 0; i < ptd->num_gcs; i++) {
        MVMObject *gc_hash = new_hash(tc);
        MVM_repr_bind_key_o(tc, gc_hash, pds->time,
            box_i(tc, ptd->gcs[i].time / 1000));
        MVM_repr_bind_key_o(tc, gc_hash, pds->full,
            box_i(tc, ptd->gcs[i].full));
        MVM_repr_bind_key_o(tc, gc_hash, pds->cleared_bytes,
            box_i(tc, ptd->gcs[i].cleared_bytes));
        MVM_repr_bind_key_o(tc, gc_hash, pds->retained_bytes,
            box_i(tc, ptd->gcs[i].retained_bytes));
        MVM_repr_bind_key_o(tc, gc_hash, pds->promoted_bytes,
            box_i(tc, ptd->gcs[i].promoted_bytes));
        MVM_repr_bind_key_o(tc, gc_hash, pds->gen2_roots,
            box_i(tc, ptd->gcs[i].num_gen2roots));
        MVM_repr_push_o(tc, thread_gcs, gc_hash);
    }
    MVM_repr_bind_key_o(tc, thread_hash, pds->gcs, thread_gcs);

    /* Add spesh time. */
    MVM_repr_bind_key_o(tc, thread_hash, pds->spesh_time,
        box_i(tc, ptd->spesh_time / 1000));

    return thread_hash;
}
示例#8
0
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 );
            }
        }
    }
}
示例#9
0
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 );
        }
    }
}
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;
}
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 );

}
示例#12
0
文件: init.c 项目: ErezSavir/openu
/* This is the main initialization function.
 * The function allocates memory to all of the global system hashes above
 * The function also fills the system hashes with the relevant data (commands, registers...)
 */
void init()
{
	/* init list of errors */
	errors = new_hash();

	/* init list of registers */
	registers = new_hash();
	hash_add_item(registers,0,"r0");
	hash_add_item(registers,1,"r1");
	hash_add_item(registers,2,"r2");
	hash_add_item(registers,3,"r3");
	hash_add_item(registers,4,"r4");
	hash_add_item(registers,5,"r5");
	hash_add_item(registers,6,"r6");
	hash_add_item(registers,7,"r7");

	/* init list of commands */
	commands = new_hash();
	hash_add_item(commands,0,"mov");
	hash_add_item(commands,1,"cmp");
	hash_add_item(commands,2,"add");
	hash_add_item(commands,3,"sub");
	hash_add_item(commands,4,"ror");
	hash_add_item(commands,5,"shr");
	hash_add_item(commands,6,"lea");
	hash_add_item(commands,7,"inc");
	hash_add_item(commands,8,"dec");
	hash_add_item(commands,9,"jmp");
	hash_add_item(commands,10,"bne");
	hash_add_item(commands,11,"red");
	hash_add_item(commands,12,"prn");
	hash_add_item(commands,13,"jsr");
	hash_add_item(commands,14,"rts");
	hash_add_item(commands,15,"hlt");

	/* init list of commands types */
	operand_types = new_hash();
	hash_add_item(operand_types,0,"#");
	hash_add_item(operand_types,3,"*");

	/* init global hashes */
	symbols = new_hash();
	data_symbols = new_hash();
	externals = new_hash();
	entry = new_hash();
}
示例#13
0
文件: spider.c 项目: leetking/spider
void init_spider(char const *start_host)
{
	link_que = g_queue_new();		
	link_hash = new_hash();
	link_t *link = calloc(sizeof(link_t), 1);
	assert(NULL != link);

	/* 默认首页先为index.html */
	link->host = strdup(start_host);
	/*
	 * NOTE www.cwnu.edu.cn时就会出错!!!
	 * 不知道是什么原因了!!!
	 */
	link->link = strdup("/index.html");
	init_http();
	g_queue_init(link_que);
	g_queue_push_tail(link_que, (gpointer)link);
}
示例#14
0
void initialize_universes()
{
	int i;

	dhcp_universe.name = "dhcp";
	dhcp_universe.hash = new_hash ();
	if (!dhcp_universe.hash)
		error ("Can't allocate dhcp option hash table.");
	for (i = 0; i < 256; i++) {
		dhcp_universe.options [i] = &dhcp_options [i];
		add_hash (dhcp_universe.hash,
			  (unsigned char *)dhcp_options [i].name, 0,
			  (unsigned char *)&dhcp_options [i]);
	}
	universe_hash.hash_count = DEFAULT_HASH_SIZE;
	add_hash (&universe_hash,
		  (unsigned char *)dhcp_universe.name, 0,
		  (unsigned char *)&dhcp_universe);
}
struct hash * hash_branch_node( struct hash_search_state search_state ) {

    // Construct a new branch node with the matched portion as its sigstr.
    char * new_sigstr = malloc( ( search_state.num_matched + 1 ) * sizeof(char) );
    sub_strcpy( new_sigstr, search_state.node->sigstr, search_state.num_matched );
    struct hash * new_node = new_hash();
    new_node->sigstr = new_sigstr;
    char * unmatched = search_state.node->sigstr + search_state.num_matched;
    char decision_char = *(unmatched++); // Unmatched portion starts after decision char.

    // Change the search_state node's sigstr to the unmatched portion.
    new_sigstr = malloc( ( strlen(unmatched) + 1 ) * sizeof(char) );
    strcpy( new_sigstr, unmatched );
    free(search_state.node->sigstr);
    search_state.node->sigstr = new_sigstr;

    // Insert new branch node between search_state.parent and search_state.node.
    add_to_charhash( search_state.parent->child, search_state.parent_choice, (void*) new_node );
    add_to_charhash( new_node->child, decision_char, search_state.node );
    new_node->num_children++;
    return new_node;
}
示例#16
0
文件: dag.c 项目: bjarneh/organice
struct dag * new_dag(void){

    struct dag * d = malloc(sizeof(struct dag));
    
    d->pkgs        = new_hash();
    d->sorted      = NULL;
    d->parse       = &dag_parse;
    d->build       = &dag_build;
    d->topsort     = &dag_topsort;
    d->compile     = &dag_compile;
    d->pcompile    = &dag_compile_par;
    d->clean       = &dag_clean;
    d->dryrun      = &dag_dryrun;
    d->sort        = &dag_sort;
    d->link        = &dag_link;
    d->print       = &dag_print;
    d->fancy       = &dag_fancy;
    d->add_test    = &dag_add_test;
    d->unlink_test = &dag_unlink_test;
    d->free        = &dag_free;

    return d;
};
示例#17
0
文件: global.c 项目: bjarneh/organice
void global_init(void) {
    // in case it's called multiple times
    if(globals == NULL){
        globals = new_hash();
    }
};
示例#18
0
/* Dumps a call graph node. */
static MVMObject * dump_call_graph_node(MVMThreadContext *tc, ProfDumpStrs *pds,
                                        const MVMProfileCallNode *pcn) {
    MVMObject *node_hash  = new_hash(tc);
    MVMuint32  i;

    /* Let's see if we're dealing with a native call or a regular moar call */
    if (pcn->sf) {
        /* Try to resolve the code filename and line number. */
        MVMBytecodeAnnotation *annot = MVM_bytecode_resolve_annotation(tc,
            &(pcn->sf->body), 0);
        MVMint32 fshi = annot ? (MVMint32)annot->filename_string_heap_index : -1;

        /* Add name of code object. */
        MVM_repr_bind_key_o(tc, node_hash, pds->name,
            box_s(tc, pcn->sf->body.name));

        /* Add line number and file name. */
        if (fshi >= 0 && fshi < pcn->sf->body.cu->body.num_strings)
            MVM_repr_bind_key_o(tc, node_hash, pds->file,
                box_s(tc, MVM_cu_string(tc, pcn->sf->body.cu, fshi)));
        else if (pcn->sf->body.cu->body.filename)
            MVM_repr_bind_key_o(tc, node_hash, pds->file,
                box_s(tc, pcn->sf->body.cu->body.filename));
        else
            MVM_repr_bind_key_o(tc, node_hash, pds->file,
                box_s(tc, tc->instance->str_consts.empty));
        MVM_repr_bind_key_o(tc, node_hash, pds->line,
            box_i(tc, annot ? (MVMint32)annot->line_number : -1));
        MVM_free(annot);

        /* Use static frame memory address to get a unique ID. */
        MVM_repr_bind_key_o(tc, node_hash, pds->id,
            box_i(tc, (MVMint64)pcn->sf));
    } else {
        MVMString *function_name_string =
            MVM_string_utf8_c8_decode(tc, tc->instance->VMString,
                                      pcn->native_target_name, strlen(pcn->native_target_name));

        MVM_repr_bind_key_o(tc, node_hash, pds->name,
            box_s(tc, function_name_string));
        MVM_repr_bind_key_o(tc, node_hash, pds->file,
            box_s(tc, pds->native_lib));

        MVM_repr_bind_key_o(tc, node_hash, pds->line,
            box_i(tc, -2));

        /* Use the address of the name string as unique ID. a hack, but oh well. */
        MVM_repr_bind_key_o(tc, node_hash, pds->id,
            box_i(tc, (MVMint64)pcn->native_target_name));
    }

    /* Entry counts. */
    if (pcn->total_entries)
        MVM_repr_bind_key_o(tc, node_hash, pds->entries,
            box_i(tc, pcn->total_entries));
    if (pcn->specialized_entries)
        MVM_repr_bind_key_o(tc, node_hash, pds->spesh_entries,
            box_i(tc, pcn->specialized_entries));
    if (pcn->jit_entries)
        MVM_repr_bind_key_o(tc, node_hash, pds->jit_entries,
            box_i(tc, pcn->jit_entries));
    if (pcn->inlined_entries)
        MVM_repr_bind_key_o(tc, node_hash, pds->inlined_entries,
            box_i(tc, pcn->inlined_entries));

    /* Total (inclusive) time. */
    MVM_repr_bind_key_o(tc, node_hash, pds->inclusive_time,
        box_i(tc, pcn->total_time / 1000));

    /* OSR and deopt counts. */
    if (pcn->osr_count)
        MVM_repr_bind_key_o(tc, node_hash, pds->osr,
            box_i(tc, pcn->osr_count));
    if (pcn->deopt_one_count)
        MVM_repr_bind_key_o(tc, node_hash, pds->deopt_one,
            box_i(tc, pcn->deopt_one_count));
    if (pcn->deopt_all_count)
        MVM_repr_bind_key_o(tc, node_hash, pds->deopt_all,
            box_i(tc, pcn->deopt_all_count));

    /* Visit successors in the call graph, dumping them and working out the
     * exclusive time. */
    if (pcn->num_succ) {
        MVMObject *callees        = new_array(tc);
        MVMuint64  exclusive_time = pcn->total_time;
        for (i = 0; i < pcn->num_succ; i++) {
            MVM_repr_push_o(tc, callees,
                dump_call_graph_node(tc, pds, pcn->succ[i]));
            exclusive_time -= pcn->succ[i]->total_time;
        }
        MVM_repr_bind_key_o(tc, node_hash, pds->exclusive_time,
            box_i(tc, exclusive_time / 1000));
        MVM_repr_bind_key_o(tc, node_hash, pds->callees, callees);
    }
    else {
        MVM_repr_bind_key_o(tc, node_hash, pds->exclusive_time,
            box_i(tc, pcn->total_time / 1000));
    }

    if (pcn->num_alloc) {
        /* Emit allocations. */
        MVMObject *alloc_list = new_array(tc);
        MVM_repr_bind_key_o(tc, node_hash, pds->allocations, alloc_list);
        for (i = 0; i < pcn->num_alloc; i++) {
            MVMObject *alloc_info = new_hash(tc);
            MVMProfileAllocationCount *alloc = &pcn->alloc[i];

            MVMObject *type       = pcn->alloc[i].type;

            MVM_repr_bind_key_o(tc, alloc_info, pds->id, box_i(tc, (MVMint64)type));
            MVM_repr_bind_key_o(tc, alloc_info, pds->type, type);
            if (alloc->allocations_spesh)
                MVM_repr_bind_key_o(tc, alloc_info, pds->spesh,
                    box_i(tc, alloc->allocations_spesh));
            if (alloc->allocations_jit)
                MVM_repr_bind_key_o(tc, alloc_info, pds->jit,
                    box_i(tc, alloc->allocations_jit));
            MVM_repr_bind_key_o(tc, alloc_info, pds->count,
                box_i(tc, alloc->allocations_interp
                          + alloc->allocations_spesh
                          + alloc->allocations_jit));
            MVM_repr_push_o(tc, alloc_list, alloc_info);
        }
    }

    return node_hash;
}
示例#19
0
文件: cfg.c 项目: Jekshmek/siege
/** 
 * Reads filename into memory and populates
 * the config_t struct with the result. Uses
 * parse to ignore comments and empty lines. 
 */ 
int 
read_cfg_file(LINES *l, char *filename)
{
  /* file pointer  */
  FILE *file; 
  HASH H;
  char *line;
  char *option;
  char *value;

  /* char array to hold contents */
  
  /* make sure LINES has been initialized. */
  if (!l) {	
    printf("Structure not initialized!\n");
    return -1;
  }

  if ((file = fopen(filename, "r")) == NULL) {
    /* this is a fatal problem, but we want  
       to enlighten the user before dying   */
    NOTIFY(WARNING, "unable to open file: %s", filename);
    display_help();
    exit(EXIT_FAILURE);
  }
 
  line = xmalloc(BUFSIZE);
  memset(line, '\0', BUFSIZE);

  H = new_hash();

  l->index = 0;
  while (fgets(line, BUFSIZE, file) != NULL) {
    int  num; char *p = strchr(line, '\n');      
    /**
     * if the line is longer than our buffer, we're 
     * just going to chuck it rather then fsck with it.
     */
    if(p) { 
      *p = '\0';
    } else {  
      /**
       * Small fix by Gargoyle - 19/07/2006
       * Check to see if we are at the end of the file. If so
       * keep the line, otherwise throw it away!
       */
      if ((num = fgetc(file)) != EOF) {
        while ((num = fgetc(file)) != EOF && num != '\n');
        line[0]='\0';
      }
    }
    parse(line);
    chomp(line);
    if (strlen(line) == 0);
    else if (is_variable_line(line)) {
      char *tmp = line;
      option = tmp;
      while (*tmp && !ISSPACE((int)*tmp) && !ISSEPARATOR(*tmp))
        tmp++; 
      *tmp++=0;
      while (ISSPACE((int)*tmp) || ISSEPARATOR(*tmp))
        tmp++;
      value  = tmp;
      while (*tmp)
        tmp++;
      *tmp++=0;
      hash_add(H, option, value); 
    } else {
    char *tmp = xstrdup(line);
      while (strstr(tmp, "$")) {
        tmp = evaluate(H, tmp);
      }
      l->line = (char**)realloc(l->line, sizeof(char *) * (l->index + 1));
      l->line[l->index] = (char *)strdup(tmp);
      l->index++;	
      
      free(tmp);
    }
    memset(line, 0, BUFSIZE);
  }

  fclose(file);
  xfree(line);
  hash_destroy(H);
  return l->index;
}