Beispiel #1
0
void AllocateLocalContext(BLOCKDATA *block, SYMBOL *sp)
{
    HASHTABLE *tn = CreateHashTable(1);
    STATEMENT *st;
    LIST *l;
    int label = nextLabel++;
    st = stmtNode(NULL, block, st_dbgblock);
    st->label = 1;
    if (block && cparams.prm_debug)
    {
        st = stmtNode(NULL, block, st_label);
        st->label = label;
        tn->blocknum = st->blocknum;
    }
    tn->next = tn->chain = localNameSpace->syms;
    localNameSpace->syms = tn;
    tn = CreateHashTable(1);
    if (block && cparams.prm_debug)
    {
        tn->blocknum = st->blocknum;
    }
    tn->next = tn->chain = localNameSpace->tags;
    localNameSpace->tags = tn;
    if (sp)
        localNameSpace->tags->blockLevel = sp->value.i++;
    
    l = Alloc(sizeof(LIST));
    l->data = localNameSpace->usingDirectives;
    l->next = usingDirectives;
    usingDirectives = l;
    
}
Beispiel #2
0
void syminit(void)
{
    globalNameSpace = Alloc(sizeof(NAMESPACEVALUES));
    globalNameSpace->syms = CreateHashTable(GLOBALHASHSIZE);
    globalNameSpace->tags = CreateHashTable(GLOBALHASHSIZE);
    localNameSpace = Alloc(sizeof(NAMESPACEVALUES));
    usingDirectives = NULL;
}
Beispiel #3
0
//-----------------------------------------------------------------------------------------//
int main()
	{
	hash_table_t *t = CreateHashTable();

	{
	Set( t, u("abc"), 3, u("ABC"), 3 );
	uint8_t tmp[4];
	size_t rs = 0;
	Get( t, u("abc"), 3, tmp, sizeof( tmp ), &rs );
	tmp[rs] = '\0';
	assert( rs == 3 );
	assert( memcmp( tmp, "ABC", rs ) == 0 );
	}
	
	{
	for( size_t i = 0 ; i < 0xffff; ++i )
		{
		assert( Set( t, u( &i ), sizeof( i ), u( &i ), sizeof( i ) ) );
		}
	
	for( size_t i = 0 ; i < 0xffff; ++i )
		{
		size_t n = 0;
		size_t s = 0;
		assert( Get( t, u( &i ), sizeof( i ), u( &n ), sizeof( n ), &s ) == true );
		assert( s == sizeof( i ) );
		assert( memcmp( &i, &n, s ) == 0 );
		}
	}

	{
	for( size_t i = 0 ; i < 0xffff; ++i )
		{
		Set( t, u( &i ), sizeof( i ), u( &i ), sizeof( i ) );
		}
	for( size_t i = 0 ; i < 0xffff; ++i )
		{
		assert( Remove( t, u( &i ), sizeof( i ) ) );
		}
	for( size_t i = 0 ; i < 0xffff; ++i )
		{
		size_t n = 0;
		assert( Get( t, u( &i ), sizeof( i ), u( &n ), sizeof( n ), NULL ) == false );
		}
	}

	{
	assert( Set( t, u( "abc" ), 3, u( "ABC" ), 3 ) );
	assert( Append( t, u( "abc" ), 3, u( "DEF" ), 3 ) );
	uint8_t tmp[6];
	size_t n = 0;
	assert( Get( t, u( "abc" ), 3, tmp, 6, &n ) == true );
	assert( n == 6 );
	assert( memcmp( "ABCDEF", tmp, 6 ) == 0 );
	}

	DeleteHashTable( t );
	
	return 0;
	}
Beispiel #4
0
void ccReset(void)
{
    whndln = whndlm = whndls =whndlf = NULL;
    shndln = shndlm = shndls =shndlf = NULL;
    listn = CreateHashTable(32000);
    listm = CreateHashTable(32000);
    lists = CreateHashTable(32000);
    listf = CreateHashTable(32000);
    ccLoadIdsFromNameTable("Names", listn);
    ccLoadIdsFromNameTable("MemberNames", listm);
    ccLoadIdsFromNameTable("StructNames", lists);
    ccLoadIdsFromNameTable("FileNames", listf);

    map = CreateHashTable(32000);

}
Beispiel #5
0
void inlineinit(void)
{
    namenumber = 0;
    inlineHead = NULL;
    inlineVTabHead = NULL;
    thisptrs = NULL;
    vc1Thunks = CreateHashTable(1);
}
Beispiel #6
0
void libcxx_init(void)
{
    int i;
    intrinsicHash = CreateHashTable(32);
    for (i=0; i < sizeof(defaults)/sizeof(defaults[0]); i++)
        AddName((SYMBOL *)&defaults[i], intrinsicHash);
           
}
Beispiel #7
0
int main()
{
	HashTable H;
	CreateHashTable(H, "HASH_TABLE.txt");
	DisplayHashTable(H);

	return 0;
}
Beispiel #8
0
jc_void NewGotoTable(CJcGotoStack * pStack)
{
	CJcGotoTable* pTable = New(CJcGotoTable);
	pTable->pPrev = pStack->pGotoTable;
	pTable->nCount = 0;
	pTable->pGotoTable = NULL;
	pTable->pLabelTable = CreateHashTable(NULL, HashFunction, HashKeyEqual, g_oInterface.Free, g_oInterface.Free);
	pStack->pGotoTable = pTable;
}
Beispiel #9
0
int main()
{
    hash_table_t *ht = CreateHashTable();
    Dump( ht, "init" );
    for( size_t i = 0; i < 10; ++i )
    {
        uint8_t k = i;
        uint8_t v = i + 0x10;
        Insert( ht, (uint8_t*)&k, 1, (uint8_t*)&v, 1 );
    }
    Dump( ht, "added" );

    return 0;
}
Beispiel #10
0
/* duck.print(output) */
int DuckPrint(int argument_count, void* data)
{
    int error = 0;
    VALUE argument = GetRecord("output", gCurrentContext);
    
    duck_print_records = CreateHashTable();

    PrintValue(argument);

    FreeHashTable(duck_print_records);
    duck_print_records = NULL;

    gLastExpression.type = VAL_NIL;
    gLastExpression.data.primitive = 0;

    return error;
}
Beispiel #11
0
char* ToString(VALUE value)
{
    char* string;
    unsigned int size;

    duck_print_records = CreateHashTable();

    size = 512;
    string = (char*)malloc(size * sizeof(char));
    sprintf(string, "");

     PrintValueString(&string, &size, value);

    FreeHashTable(duck_print_records);
    duck_print_records = NULL;

    return string;
}
Beispiel #12
0
int StringSplit(int argument_count, void* data)
{
    int error = 0;

    VALUE argument = GetRecord("string", gCurrentContext);

    if (argument.type == VAL_STRING) 
    {
        const char* data = argument.data.string;
        unsigned int length = strlen(data);
        unsigned int index;

        HASH_TABLE* dictionary = CreateHashTable();
        GCAddDictionary(dictionary, &gGCManager);

        for (index = 0; index < length; index++)
        {
            VALUE key;
            VALUE expr;

            key.type = VAL_PRIMITIVE;
            key.data.primitive = index;
            
            expr.type = VAL_STRING;
            expr.const_string = 0;
            char* char_string = (char*)ALLOC(sizeof(char) * 2);
            GCAddString(char_string, &gGCManager);
            char_string[0] = data[index];
            char_string[1] = '\0';
            expr.data.string = char_string;

            HashStore(key, expr, dictionary);
        }

        gLastExpression.type = VAL_DICTIONARY;
        gLastExpression.data.dictionary = dictionary;
    } else {
        gLastExpression.type = VAL_NIL;
        gLastExpression.data.primitive = 0;
    }

    return error;
}
Beispiel #13
0
static void createConverter(SYMBOL *self)
{
    SYMBOL *caller = createPtrCaller(self);
    TYPE *args = realArgs(lambdas->func);
    SYMBOL *func = makeID(sc_member, Alloc(sizeof(TYPE)), NULL, overloadNameTab[CI_CAST]);
    BLOCKDATA block1, block2;
    STATEMENT *st;
    EXPRESSION *exp;
    SYMBOL *sym = makeID(sc_parameter, &stdvoid, NULL, AnonymousName());
    HASHREC *hr = Alloc(sizeof(HASHREC));
    func->tp->type = bt_func;
    func->tp->btp = Alloc(sizeof(TYPE));
    func->tp->btp->type = bt_pointer;
    func->tp->btp->size = getSize(bt_pointer);
    func->tp->btp->btp = args;
    func->tp->syms = CreateHashTable(1);
    func->linkage = lk_virtual;
    func->isInline = FALSE;
    hr->p = (struct _hrintern_ *)sym;
    func->tp->syms->table[0] = hr;
    func->parentClass = lambdas->cls;
    memset(&block1, 0, sizeof(BLOCKDATA));
    memset(&block2, 0, sizeof(BLOCKDATA));
    func->castoperator = TRUE;
    insertFunc(lambdas->cls, func);
    InsertInline(func);
    InsertInline(caller);
    st = stmtNode(NULL, &block2, st_return);
    st->select = varNode(en_pc, caller);
    st = stmtNode(NULL, &block1, st_block);
    st->lower = block2.head;
    st->blockTail = block2. blockTail;
    func->inlineFunc.stmt = stmtNode(NULL, NULL, st_block);
    func->inlineFunc.stmt->lower = block1.head;
    func->inlineFunc.stmt->blockTail = block1.blockTail;
}
Beispiel #14
0
LEXEME *expression_lambda(LEXEME *lex, SYMBOL *funcsp, TYPE *atp, TYPE **tp, EXPRESSION **exp, int flags)
{
    LAMBDA *self;
    SYMBOL *vpl, *ths;
    HASHREC *hrl;
    TYPE *ltp;
    STRUCTSYM ssl;
    if (funcsp)
        funcsp->noinline = TRUE;
    IncGlobalFlag();
    self = Alloc(sizeof(LAMBDA));
    ltp = Alloc(sizeof(TYPE));
    ltp->type = bt_struct;
    ltp->syms = CreateHashTable(1);
    ltp->tags = CreateHashTable(1);
    ltp->size = 0;
    self->captured = CreateHashTable(1);
    self->oldSyms = localNameSpace->syms;
    self->oldTags = localNameSpace->tags;
    self->index = lambdaIndex;
    self->captureMode = cmNone;
    self->isMutable = FALSE;
    self->captureThis = FALSE;
    self->cls = makeID(sc_type, ltp, NULL, LambdaName());
    ltp->sp = self->cls;
    SetLinkerNames(self->cls, lk_cdecl);
    self->cls->islambda = TRUE;
    self->cls->structAlign = getAlign(sc_global, &stdpointer);
    self->func = makeID(sc_member, ltp, NULL, "$internalFunc");
    self->func->parentClass = self->cls;
    self->functp = &stdauto;
    self->enclosingFunc = theCurrentFunc;
    if (lambdas)
        lambdas->prev = self;
    self->next = lambdas;
    lambdas = self;
    
    localNameSpace->syms = CreateHashTable(1);
    localNameSpace->tags = CreateHashTable(1);
    if (lambdas->next)
    {
        self->lthis = lambdas->next->lthis;
    }
    else if (funcsp && funcsp->parentClass)
    {
        self->lthis = ((SYMBOL *)funcsp->tp->syms->table[0]->p);
    }
    lex = getsym(); // past [
    if (funcsp)
    {
        // can have a capture list;
        if (MATCHKW(lex, assign))
        {
            lex = getsym();
            if (MATCHKW(lex, comma) || MATCHKW(lex, closebr))
            {
                self->captureMode = cmValue;
                skip(&lex, comma);
            }
            else
            {
                lex = backupsym();
            }
        }
        else if (MATCHKW(lex, and))
        {
            lex = getsym();
            if (MATCHKW(lex, comma) || MATCHKW(lex, closebr))
            {
                self->captureMode = cmRef;
                skip(&lex, comma);
            }
            else
            {
                lex = backupsym();
            }
        }
        if (!MATCHKW(lex, comma) && !MATCHKW(lex, closebr))
        {
            do            
            {
                enum e_cm localMode = self->captureMode;
                if (MATCHKW(lex, comma))
                    skip(&lex, comma);
                if (MATCHKW(lex, kw_this))
                {
                    lex = getsym();
                    if (localMode == cmValue || !self->lthis)
                    {
                        error(ERR_CANNOT_CAPTURE_THIS);
                    }
                    else
                    {
                        if (self->captureThis)
                        {
                            error(ERR_CAPTURE_ITEM_LISTED_MULTIPLE_TIMES);
                        }
                        self->captureThis = TRUE;
                        lambda_capture(NULL, cmThis, TRUE);
                    }
                    continue;
                }
                else if (MATCHKW(lex, and))
                {
                    if (localMode == cmRef)
                    {
                        error(ERR_INVALID_LAMBDA_CAPTURE_MODE);
                    }
                    localMode = cmRef;
                    lex = getsym();
                }
                else 
                {
                    if (localMode == cmValue)
                    {
                        error(ERR_INVALID_LAMBDA_CAPTURE_MODE);
                    }
                    localMode = cmValue;
                }
                if (ISID(lex))
                {
                    SYMBOL *sp = search(lex->value.s.a, localNameSpace->syms);
                    LAMBDA *current = lambdas;
                    while (current && !sp)
                    {
                        sp = search(lex->value.s.a, current->oldSyms);
                        current = current->next;
                        
                    }
                    lex = getsym();
                    if (sp)
                    {
                        if (sp->packed)
                        {
                            if (!MATCHKW(lex, ellipse))
                                error(ERR_PACK_SPECIFIER_REQUIRED_HERE);
                            else
                                lex = getsym();
                        }
                        if (sp->packed)
                        {
                            int n;
                            TEMPLATEPARAMLIST * templateParam = sp->tp->templateParam->p->byPack.pack;
                            HASHREC *hr;
                            for (n=0; templateParam; templateParam = templateParam->next, n++);
                            hr = funcsp->tp->syms->table[0];
                            while (hr && ((SYMBOL *)hr->p) != sp)
                                hr = hr->next;
                            while (hr && n)
                            {
                                lambda_capture((SYMBOL *)hr->p, localMode, TRUE);
                                hr = hr->next;
                                n--;
                            }
                        }
                        else
                        {
                            lambda_capture(sp, localMode, TRUE);
                        }
                    }
                    else
                        errorstr(ERR_UNDEFINED_IDENTIFIER, lex->value.s.a);
                }
                else
                {
                    error(ERR_INVALID_LAMBDA_CAPTURE_MODE);
                }
            } while (MATCHKW(lex, comma));
        }
        needkw(&lex, closebr);
    }
    else
    {
        if (!MATCHKW(lex, closebr))
        {
            error(ERR_LAMBDA_CANNOT_CAPTURE);
        }
        else
        {
            lex = getsym();
        }
    }
    if (MATCHKW(lex, openpa))
    {
        TYPE *tpx = &stdvoid;
        HASHREC *hr;
        lex = getFunctionParams(lex, NULL, &self->func, &tpx, FALSE, sc_auto);
        self->funcargs = self->func->tp->syms->table[0];
        hr = self->func->tp->syms->table[0];
        while (hr)
        {
            SYMBOL *sym = (SYMBOL *)hr->p;
            if (sym->init)
            {
                error(ERR_CANNOT_DEFAULT_PARAMETERS_WITH_LAMBDA);
            }
            hr = hr->next;
        }
        if (MATCHKW(lex, kw_mutable))
        {
            HASHREC *hr = self->captured->table[0];
            while (hr)
            {
                LAMBDASP *lsp = (LAMBDASP *)hr->p;
                if (lsp->sym->lambdaMode == cmValue)
                {
                    lsp->sym->tp = basetype(lsp->sym->tp);
                }
                hr = hr->next;
            }
            self->isMutable = TRUE;
            
            lex = getsym();
        }
        ParseAttributeSpecifiers(&lex, funcsp, TRUE);
        if (MATCHKW(lex, pointsto))
        {
            lex = getsym();
            lex = get_type_id(lex, &self->functp, funcsp, sc_cast, FALSE, TRUE);
        }
    }
    else
    {
        TYPE *tp1 = Alloc(sizeof(TYPE));
        SYMBOL *spi;
        tp1->type = bt_func;
        tp1->size = getSize(bt_pointer);
        tp1->btp = &stdvoid;
        tp1->sp = self->func;
        self->func->tp = tp1;
        spi = makeID(sc_parameter, tp1, NULL, AnonymousName());
        spi->anonymous = TRUE;
        spi->tp = Alloc(sizeof(TYPE));
        spi->tp->type = bt_void;
        insert(spi, localNameSpace->syms);
        SetLinkerNames(spi, lk_cpp);
        self->func->tp->syms = localNameSpace->syms;
        self->funcargs = self->func->tp->syms->table[0];
        self->func->tp->syms->table[0] = NULL;
    }
    vpl = makeID(sc_parameter, &stdpointer, NULL, AnonymousName());
    vpl->assigned = vpl->used = TRUE;
    SetLinkerNames(vpl, lk_cdecl);
    hrl = Alloc(sizeof(HASHREC));
    hrl->p = (struct _hrintern_ *)vpl;
    hrl->next = lambdas->func->tp->syms->table[0];
    lambdas->func->tp->syms->table[0] = hrl;
    vpl = makeID(sc_parameter, &stdpointer, NULL, AnonymousName());
    vpl->assigned = vpl->used = TRUE;
    SetLinkerNames(vpl, lk_cdecl);
    hrl = Alloc(sizeof(HASHREC));
    hrl->p = (struct _hrintern_ *)vpl;
    hrl->next = lambdas->func->tp->syms->table[0];
    lambdas->func->tp->syms->table[0] = hrl;
    SetLinkerNames(lambdas->func, lk_cdecl);
    injectThisPtr(lambdas->func, basetype(lambdas->func->tp)->syms);
    lambdas->func->tp->btp = self->functp;
    lambdas->func->linkage = lk_virtual;
    lambdas->func->isInline = TRUE;
    ssl.str = self->cls;
    ssl.tmpl = NULL;
    addStructureDeclaration(&ssl);
    ths = makeID(sc_member, &stdpointer, NULL, "$this");
    lambda_insert(ths, lambdas);
    if (MATCHKW(lex, begin))
    {
        lex = body(lex, self->func);
    }
    else
    {
        error(ERR_LAMBDA_FUNCTION_BODY_EXPECTED);
    }
    dropStructureDeclaration();
    localNameSpace->syms = self->oldSyms;
    localNameSpace->tags = self->oldTags;
    inferType();
    finishClass();
    *exp = createLambda(0);
    *tp = lambdas->cls->tp;
    lambdas = lambdas->next;
    if (lambdas)
        lambdas->prev = NULL;
    DecGlobalFlag();
    return lex;
}
Beispiel #15
0
int main(int argc, char *argv[]) {
	struct dht *NameToInet,*InetToName;
	dhtElement	*hhe, *he;
	struct hostent	*host;
	int		i;
	char		*hostsfile;


	if (argc > 1) {
	    hostsfile= argv[1];
	}
	else
	    hostsfile= "/etc/hosts";
	
#if defined(FXF)
	/* we want to use only 300K for all hashing */
	fxfInit(300*1024);
#endif /*FXF*/

	/*
	fputs("MallocInfo before first malloc\n",stderr);
	fDumpMallinfo(stderr);
	*/
#if defined(USE_MEMVAL)
#if !defined(PRE_REGISTER)
	dhtRegisterValue(dhtMemoryValue, 0, &dhtMemoryProcs);
	dhtRegisterValue(dhtSimpleValue, 0, &dhtSimpleProcs);
#endif
	if ((NameToInet=dhtCreate(dhtMemoryValue, dhtCopy, dhtSimpleValue, dhtNoCopy)) == NilHashTable) {
		fputs("Sorry, no space for more HashTables\n",stderr);
		exit(5);
	}

	if ((InetToName=CreateHashTable(dhtSimpleValue, dhtNoCopy, dhtMemoryValue, dhtCopy)) == NilHashTable) {
		fputs("Sorry, no space for more HashTables\n",stderr);
		exit(7);
	}
#else
#if !defined(PRE_REGISTER)
	dhtRegisterValue(dhtStringValue, 0, &dhtStringProcs);
	dhtRegisterValue(dhtSimpleValue, 0, &dhtSimpleProcs);
#endif
	if ((NameToInet=dhtCreate(dhtStringValue, dhtCopy,
			dhtSimpleValue, dhtNoCopy)) == dhtNilHashTable) {
		fputs("Sorry, no space for more HashTables\n",stderr);
		exit(5);
	}

	if ((InetToName=dhtCreate(dhtSimpleValue, dhtNoCopy,
			dhtStringValue, dhtCopy)) == dhtNilHashTable) {
		fputs("Sorry, no space for more HashTables\n",stderr);
		exit(7);
	}
#endif /*USE_MEMVAL*/

	/*
	fputs("MallocInfo after creating the HashTables\n",stderr);
	fDumpMallinfo(stderr);
	*/
#if defined(FXF)
	fputs("fxf-Info after creation of hash tables\n",stderr);
	fxfInfo(stderr);
#endif /*FXF*/

#define BYT(x)	(uChar)(x&0xff)
	while ((host=gethent(hostsfile))) {
		unsigned long InetAddr;
		char *h;
#if defined(USE_MEMVAL)
		MemVal mvHostName, *HostName= &mvHostName;
#else
		char *HostName;
#endif /*USE_MEMVAL*/

		h= host->h_addr;
#if defined(USE_MEMVAL)
		mvHostName.Leng= strlen(host->h_name);
		mvHostName.Data= (uChar *)host->h_name;
#else
		HostName= host->h_name;
#endif /*USE_MEMVAL*/
		/*
		*/
		InetAddr= *(uLong *)h; 

		if (dhtLookupElement(NameToInet, (dhtValue)HostName)) {
			fprintf(stderr, "Hostname %s already entered\n", host->h_name);
		}
		dhtEnterElement(NameToInet, (dhtValue)HostName, (dhtValue)InetAddr);
		if (dhtLookupElement(InetToName, (dhtValue)InetAddr)) {
			fprintf(stderr, "InetAddr 0x%08lx already entered\n", InetAddr);
		}
		dhtEnterElement(InetToName, (dhtValue)InetAddr, (dhtValue)HostName);
	}
#if defined(FXF)
	fputs("fxf-Info after filling the hash tables\n",stderr);
	fxfInfo(stderr);
#endif /*FXF*/

	/* Dump both Tables */
	printf("Dumping the hashtables ..."); fflush(stdout);
	dhtDump(NameToInet,stderr);
	dhtDump(InetToName,stderr);
	printf(" done\n");

	/*
	fputs("MallocInfo after filling the HashTables\n",stderr);
	fDumpMallinfo(stderr);
	*/

	fputs("Testing if we get alle entries from NameToInet via GetFirst and GetNext...\n",stderr); 
	he= dhtGetFirstElement(NameToInet);
	i= 0;
	while (he) {
		i++;
		he= dhtGetNextElement(NameToInet);
	}
	fprintf(stderr, "Got %d entries\n", i);

	fputs("Testing if we get alle entries from InetToName via GetFirst and GetNext...\n",stderr); 
	he= dhtGetFirstElement(InetToName);
	i= 0;
	while (he) {
		i++;
		he= dhtGetNextElement(InetToName);
	}
	fprintf(stderr, "Got %d entries\n", i);

	he= dhtGetFirstElement(NameToInet);
	while (he) {
		uLong adr= (uLong)he->Data;
		char *Name;
#if defined(USE_MEMVAL)
		strncpy(str,
		  (char *)((MemVal *)he->Key)->Data,
		  ((MemVal *)he->Key)->Leng);
		str[((MemVal *)he->Key)->Leng]='\0';
		Name= str;
#else
		Name= (char *)he->Key;
#endif /*USE_MEMVAL*/
		printf("%3u.%3u.%3u.%3u = %s   ", BYT(adr), BYT(adr>>8),
			BYT(adr>>16), BYT(adr>>24), Name);

		dhtRemoveElement(NameToInet, he->Key);
		dhtRemoveElement(InetToName, he->Data);
		printf("   Deleting and checking consistency (Load=%ld... ", dhtActualLoad(NameToInet));
		i=0;
		hhe= dhtGetFirstElement(NameToInet);
		printf("    "); fflush(stdout);
		while (hhe) {
			dhtElement *he1= dhtLookupElement(InetToName, hhe->Data);
			if (strcmp((char *)he1->Data, (char *)hhe->Key) != 0) {
				fputs("\nSorry, Mismatch\n",stdout);
				exit(1);
			}
			if (he1->Key != hhe->Data) {
				fputs("\nSorry, Mismatch\n",stdout);
				exit(2);
			}
			i=i+1;
			/*
			printf("\b\b\b\b%4d",i); fflush(stdout);
			*/
			hhe= dhtGetNextElement(NameToInet);
		}
		printf(" done\n");
		he= dhtGetFirstElement(NameToInet);
		/*he= GetNextHashElement(NameToInet);*/
	}
#if defined(FXF)
	fputs("fxf-Info after emptying the hash tables\n",stderr);
	fxfInfo(stderr);
#endif /*FXF*/
	printf("Dumping the hashtables after removing ..."); fflush(stdout);
	dhtDump(NameToInet,stderr);
	dhtDump(InetToName,stderr);
	/*
	fputs("MallocInfo after emptying the HashTables\n",stderr);
	fDumpMallinfo(stderr);
	*/


	dhtDestroy(NameToInet);
	dhtDestroy(InetToName);

#if defined(FXF)
	fputs("fxf-Info after destroying the hash tables\n",stderr);
	fxfInfo(stderr);
#endif /*FXF*/

	/*
	fputs("MallocInfo after emptying the HashTables\n",stderr);
	fDumpMallinfo(stderr);
	*/
	exit(0);
}
bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq)
{
    TFileStream * pStream = NULL;           // File stream
    TMPQArchive * ha = NULL;                // MPQ archive handle
    ULONGLONG MpqPos = 0;                   // Position of MPQ header in the file
    HANDLE hMpq = NULL;
    DWORD dwBlockTableSize = 0;             // Initial block table size
    DWORD dwHashTableSize = 0;
    DWORD dwMaxFileCount;
    int nError = ERROR_SUCCESS;

    // Check the parameters, if they are valid
    if(szMpqName == NULL || *szMpqName == 0 || pCreateInfo == NULL || phMpq == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return false;
    }

    // Verify if all variables in SFILE_CREATE_MPQ are correct
    if((pCreateInfo->cbSize == 0 || pCreateInfo->cbSize > sizeof(SFILE_CREATE_MPQ)) ||
       (pCreateInfo->dwMpqVersion > MPQ_FORMAT_VERSION_4)                        ||
       (pCreateInfo->pvUserData != NULL || pCreateInfo->cbUserData != 0)            ||
       (pCreateInfo->dwAttrFlags & ~MPQ_ATTRIBUTE_ALL)                              ||
       (pCreateInfo->dwSectorSize & (pCreateInfo->dwSectorSize - 1))                ||
       (pCreateInfo->dwRawChunkSize & (pCreateInfo->dwRawChunkSize - 1))            ||
       (pCreateInfo->dwMaxFileCount < 4))
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return false;
    }

    // One time initialization of MPQ cryptography
    InitializeMpqCryptography();

    // We verify if the file already exists and if it's a MPQ archive.
    // If yes, we won't allow to overwrite it.
    if(SFileOpenArchive(szMpqName, 0, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE | MPQ_OPEN_NO_ATTRIBUTES | MPQ_OPEN_NO_LISTFILE, &hMpq))
    {
        SFileCloseArchive(hMpq);
        SetLastError(ERROR_ALREADY_EXISTS);
        return false;
    }

    //
    // At this point, we have to create the archive.
    // - If the file exists, convert it to MPQ archive.
    // - If the file doesn't exist, create new empty file
    //

    pStream = FileStream_OpenFile(szMpqName, pCreateInfo->dwStreamFlags);
    if(pStream == NULL)
    {
        pStream = FileStream_CreateFile(szMpqName, pCreateInfo->dwStreamFlags);
        if(pStream == NULL)
            return false;
    }

    // Increment the maximum amount of files to have space
    // for listfile and attributes file
    dwMaxFileCount = pCreateInfo->dwMaxFileCount;
    if(pCreateInfo->dwAttrFlags != 0)
        dwMaxFileCount++;
    dwMaxFileCount++;

    // If file count is not zero, initialize the hash table size
    dwHashTableSize = GetHashTableSizeForFileCount(dwMaxFileCount);

    // Retrieve the file size and round it up to 0x200 bytes
    FileStream_GetSize(pStream, MpqPos);
    MpqPos = (MpqPos + 0x1FF) & (ULONGLONG)0xFFFFFFFFFFFFFE00ULL;
    if(!FileStream_SetSize(pStream, MpqPos))
        nError = GetLastError();

#ifdef _DEBUG    
    // Debug code, used for testing StormLib
//  dwBlockTableSize = dwHashTableSize * 2;
#endif

    // Create the archive handle
    if(nError == ERROR_SUCCESS)
    {
        if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Fill the MPQ archive handle structure
    if(nError == ERROR_SUCCESS)
    {
        memset(ha, 0, sizeof(TMPQArchive));
        ha->pStream         = pStream;
        ha->dwSectorSize    = pCreateInfo->dwSectorSize;
        ha->UserDataPos     = MpqPos;
        ha->MpqPos          = MpqPos;
        ha->pHeader         = (TMPQHeader *)ha->HeaderData;
        ha->dwMaxFileCount  = dwMaxFileCount;
        ha->dwFileTableSize = 0;
        ha->dwFileFlags1    = pCreateInfo->dwFileFlags1;
        ha->dwFileFlags2    = pCreateInfo->dwFileFlags2;
        ha->dwFlags         = 0;

        // Setup the attributes
        ha->dwAttrFlags     = pCreateInfo->dwAttrFlags;
        pStream = NULL;
    }

    // Fill the MPQ header
    if(nError == ERROR_SUCCESS)
    {
        TMPQHeader * pHeader = ha->pHeader;

        // Fill the MPQ header
        memset(pHeader, 0, sizeof(ha->HeaderData));
        pHeader->dwID             = ID_MPQ;
        pHeader->dwHeaderSize     = MpqHeaderSizes[pCreateInfo->dwMpqVersion];
        pHeader->dwArchiveSize    = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash);
        pHeader->wFormatVersion   = (USHORT)pCreateInfo->dwMpqVersion;
        pHeader->wSectorSize      = GetSectorSizeShift(ha->dwSectorSize);
        pHeader->dwHashTablePos   = pHeader->dwHeaderSize;
        pHeader->dwHashTableSize  = dwHashTableSize;
        pHeader->dwBlockTablePos  = pHeader->dwHashTablePos + dwHashTableSize * sizeof(TMPQHash);
        pHeader->dwBlockTableSize = dwBlockTableSize;

        // For MPQs version 4 and higher, we set the size of raw data block
        // for calculating MD5
        if(pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_4)
            pHeader->dwRawChunkSize = pCreateInfo->dwRawChunkSize;

        // Write the naked MPQ header
        nError = WriteNakedMPQHeader(ha);

        // Remember that the (listfile) and (attributes) need to be saved
        ha->dwFlags |= MPQ_FLAG_CHANGED | MPQ_FLAG_INV_LISTFILE | MPQ_FLAG_INV_ATTRIBUTES;
    }

    // Create initial HET table, if the caller required an MPQ format 3.0 or newer
    if(nError == ERROR_SUCCESS && pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_3)
    {
        ha->pHetTable = CreateHetTable(ha->dwMaxFileCount, 0x40, true);
        if(ha->pHetTable == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Create initial hash table
    if(nError == ERROR_SUCCESS)
    {
        nError = CreateHashTable(ha, dwHashTableSize);
    }

    // Create initial file table
    if(nError == ERROR_SUCCESS)
    {
        ha->pFileTable = STORM_ALLOC(TFileEntry, ha->dwMaxFileCount);
        if(ha->pFileTable != NULL)
            memset(ha->pFileTable, 0x00, sizeof(TFileEntry) * ha->dwMaxFileCount);
        else
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Cleanup : If an error, delete all buffers and return
    if(nError != ERROR_SUCCESS)
    {
        FileStream_Close(pStream);
        FreeMPQArchive(ha);
        SetLastError(nError);
        ha = NULL;
    }
    
    // Return the values
    *phMpq = (HANDLE)ha;
    return (nError == ERROR_SUCCESS);
}
Beispiel #17
0
//----------------------------------------------------------------------------
NTSTATUS
InitNotOs(
    void
    )

/*++

Routine Description:

    This is the initialization routine for the Non-OS Specific side of the
    NBT device driver.

    pNbtGlobConfig must be initialized before this is called!

Arguments:

Return Value:

    NTSTATUS - The function value is the final status from the initialization
        operation.

--*/

{
    NTSTATUS            status = STATUS_SUCCESS;
    ULONG               i;


    CTEPagedCode();
    //
    // for multihomed hosts, this tracks the number of adapters as each one
    // is created.
    //
    NbtConfig.AdapterCount = 0;
    NbtConfig.MultiHomed = FALSE;
    NbtConfig.SingleResponse = FALSE;


    //
    // Initialize the name statistics
    //
    CTEZeroMemory( &NameStatsInfo,sizeof(tNAMESTATS_INFO) );

    InitializeListHead(&pNbtGlobConfig->DeviceContexts);

#ifndef _IO_DELETE_DEVICE_SUPPORTED
    InitializeListHead(&pNbtGlobConfig->FreeDevCtx);
#endif

    InitializeListHead(&NbtConfig.AddressHead);
    InitializeListHead(&NbtConfig.PendingNameQueries);

#ifdef VXD
    InitializeListHead(&NbtConfig.DNSDirectNameQueries);
#endif

    // initialize the spin lock
    CTEInitLock(&pNbtGlobConfig->SpinLock);
    CTEInitLock(&pNbtGlobConfig->JointLock.SpinLock);
    NbtConfig.LockNumber = NBTCONFIG_LOCK;
    NbtConfig.JointLock.LockNumber = JOINT_LOCK;
    NbtMemoryAllocated = 0;

#if DBG
    for (i=0;i<MAXIMUM_PROCESSORS ;i++ )
    {
        NbtConfig.CurrentLockNumber[i] = 0;
    }
#endif
    InitializeListHead(&UsedTrackers);
    InitializeListHead(&UsedIrps);

    // create the hash tables for storing names in.
    status = CreateHashTable(&pNbtGlobConfig->pLocalHashTbl,
                pNbtGlobConfig->uNumBucketsLocal,
                NBT_LOCAL);

    if ( !NT_SUCCESS( status ) )
    {
        ASSERTMSG("NBT:Unable to create hash tables for Netbios Names\n",
                (status == STATUS_SUCCESS));
        return status ;
    }
    // we always have a remote hash table, but if we are a Proxy, it is
    // a larger table. In the Non-proxy case the remote table just caches
    // names resolved with the NS.  In the Proxy case it also holds names
    // resolved for all other clients on the local broadcast area.
    // The node size registry parameter controls the number of remote buckets.
    status = InitRemoteHashTable(pNbtGlobConfig,
                    pNbtGlobConfig->uNumBucketsRemote,
                    pNbtGlobConfig->uNumRemoteNames);

    if ( !NT_SUCCESS( status ) )
        return status ;

    //
    // initialize the linked lists associated with the global configuration
    // data structures
    //
    InitializeListHead(&NbtConfig.NodeStatusHead);
    InitializeListHead(&NbtConfig.DgramTrackerFreeQ);
#ifndef VXD
    InitializeListHead(&NbtConfig.IrpFreeList);
    pWinsInfo = 0;

    {

        //
        // Setup the default disconnect timeout - 10 seconds - convert
        // to negative 100 Ns.
        //
        DefaultDisconnectTimeout.QuadPart = Int32x32To64(DEFAULT_DISC_TIMEOUT,
                                                          MILLISEC_TO_100NS);
        DefaultDisconnectTimeout.QuadPart = -(DefaultDisconnectTimeout.QuadPart);
    }

#else
    DefaultDisconnectTimeout = DEFAULT_DISC_TIMEOUT * 1000; // convert to milliseconds

    InitializeListHead(&NbtConfig.SendTimeoutHead) ;
    InitializeListHead(&NbtConfig.SessionBufferFreeList) ;
    InitializeListHead(&NbtConfig.SendContextFreeList) ;
    InitializeListHead(&NbtConfig.RcvContextFreeList) ;

    //
    //  For session headers, since they are only four bytes and we can't
    //  change the size of the structure, we'll covertly add enough for
    //  a full LIST_ENTRY and treat it like a standalone LIST_ENTRY structure
    //  when adding and removing from the list.
    //
    NbtConfig.iBufferSize[eNBT_SESSION_HDR]  = sizeof(tSESSIONHDR) +
                                    sizeof( LIST_ENTRY ) - sizeof(tSESSIONHDR) ;
    NbtConfig.iBufferSize[eNBT_SEND_CONTEXT] = sizeof(TDI_SEND_CONTEXT);
    NbtConfig.iBufferSize[eNBT_RCV_CONTEXT]  = sizeof(RCV_CONTEXT);

    NbtConfig.iCurrentNumBuff[eNBT_SESSION_HDR]    = NBT_INITIAL_NUM;
    status = NbtInitQ( &NbtConfig.SessionBufferFreeList,
                       NbtConfig.iBufferSize[eNBT_SESSION_HDR],
                       NBT_INITIAL_NUM);

    if ( !NT_SUCCESS( status ) )
        return status ;

    NbtConfig.iCurrentNumBuff[eNBT_SEND_CONTEXT]   = NBT_INITIAL_NUM;
    status = NbtInitQ( &NbtConfig.SendContextFreeList,
                       sizeof( TDI_SEND_CONTEXT ),
                       NBT_INITIAL_NUM);

    if ( !NT_SUCCESS( status ) )
        return status ;

    NbtConfig.iCurrentNumBuff[eNBT_RCV_CONTEXT]    = NBT_INITIAL_NUM;
    status = NbtInitQ( &NbtConfig.RcvContextFreeList,
                       sizeof( RCV_CONTEXT ),
                       NBT_INITIAL_NUM);

    if ( !NT_SUCCESS( status ) )
        return status ;
#endif

    //
    // create trackers List
    //
    pNbtGlobConfig->iBufferSize[eNBT_DGRAM_TRACKER] =
                                             sizeof(tDGRAM_SEND_TRACKING);

    NbtConfig.iCurrentNumBuff[eNBT_DGRAM_TRACKER] = 0;

    status = NbtInitTrackerQ( &NbtConfig.DgramTrackerFreeQ,NBT_INITIAL_NUM);

    if ( !NT_SUCCESS( status ) )
        return status ;


    CTEZeroMemory(&LmHostQueries,sizeof(tLMHOST_QUERIES));
    InitializeListHead(&DomainNames.DomainList);
    InitializeListHead(&LmHostQueries.ToResolve);

#ifndef VXD
        // set up a list for connections when we run out of resources and need to
        // disconnect these connections. An Irp is also needed for this list, and
        // it is allocated in Driver.C after we have created the connections to the
        // transport and therefore know our Irp Stack Size.
        //
        InitializeListHead(&NbtConfig.OutOfRsrc.ConnectionHead);

        // use this resources to synchronize access to the security info between
        // assigning security and checking it - when adding names to the
        // name local name table through NbtregisterName.  This also insures
        // that the name is in the local hash table (from a previous Registration)
        // before the next registration is allowed to proceed and check for
        // the name in the table.
        //
        ExInitializeResource(&NbtConfig.Resource);

        //
        // this resource is used to synchronize access to the Dns structure
        //
        CTEZeroMemory(&DnsQueries,sizeof(tDNS_QUERIES));

        InitializeListHead(&DnsQueries.ToResolve);

        //
        // this resource is used to synchronize access to the Dns structure
        //
        CTEZeroMemory(&CheckAddr,sizeof(tCHECK_ADDR));

        InitializeListHead(&CheckAddr.ToResolve);
#endif // VXD

    return status ;
}
Beispiel #18
0
bool WINAPI SFileCreateArchive(const char * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq)
{
    TFileStream * pStream = NULL;           // File stream
    TMPQArchive * ha = NULL;                // MPQ archive handle
    ULONGLONG MpqPos = 0;                   // Position of MPQ header in the file
    HANDLE hMpq = NULL;
    USHORT wFormatVersion = MPQ_FORMAT_VERSION_1;
    DWORD dwBlockTableSize = 0;             // Initial block table size
    DWORD dwHashTableSize = 0;
    int nError = ERROR_SUCCESS;

    // Check the parameters, if they are valid
    if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return false;
    }

    // One time initialization of MPQ cryptography
    InitializeMpqCryptography();

    // We verify if the file already exists and if it's a MPQ archive.
    // If yes, we won't allow to overwrite it.
    if(SFileOpenArchive(szMpqName, 0, dwFlags, &hMpq))
    {
        SFileCloseArchive(hMpq);
        SetLastError(ERROR_ALREADY_EXISTS);
        return false;
    }

    //
    // At this point, we have to create the archive.
    // - If the file exists, convert it to MPQ archive.
    // - If the file doesn't exist, create new empty file
    //

    pStream = FileStream_OpenFile(szMpqName, true);
    if(pStream == NULL)
    {
        pStream = FileStream_CreateFile(szMpqName);
        if(pStream == NULL)
            return false;
    }

    // Decide what format to use
    wFormatVersion = (USHORT)((dwFlags & MPQ_CREATE_ARCHIVE_VMASK) >> 16);
    if(wFormatVersion > MPQ_FORMAT_VERSION_4)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return false;
    }

    // Increment the maximum amount of files to have space
    // for listfile and attributes file
    if(dwFlags & MPQ_CREATE_ATTRIBUTES)
        dwMaxFileCount++;
    dwMaxFileCount++;

    // If file count is not zero, initialize the hash table size
    dwHashTableSize = GetHashTableSizeForFileCount(dwMaxFileCount);

    // Retrieve the file size and round it up to 0x200 bytes
    FileStream_GetSize(pStream, MpqPos);
    MpqPos = (MpqPos + 0x1FF) & (ULONGLONG)0xFFFFFFFFFFFFFE00ULL;
    if(!FileStream_SetSize(pStream, MpqPos))
        nError = GetLastError();

#ifdef _DEBUG    
    // Debug code, used for testing StormLib
//  dwBlockTableSize = dwHashTableSize * 2;
#endif

    // Create the archive handle
    if(nError == ERROR_SUCCESS)
    {
        if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Fill the MPQ archive handle structure
    if(nError == ERROR_SUCCESS)
    {
        memset(ha, 0, sizeof(TMPQArchive));
        ha->pStream         = pStream;
        ha->dwSectorSize    = (wFormatVersion >= MPQ_FORMAT_VERSION_3) ? 0x4000 : 0x1000;
        ha->UserDataPos     = MpqPos;
        ha->MpqPos          = MpqPos;
        ha->pHeader         = (TMPQHeader *)ha->HeaderData;
        ha->dwMaxFileCount  = dwMaxFileCount;
        ha->dwFileTableSize = 0;
        ha->dwFileFlags1    = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS |  MPQ_FILE_REPLACEEXISTING;
        ha->dwFileFlags2    = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS |  MPQ_FILE_REPLACEEXISTING;
        ha->dwFlags         = 0;

        // Setup the attributes
        if(dwFlags & MPQ_CREATE_ATTRIBUTES)
            ha->dwAttrFlags = MPQ_ATTRIBUTE_CRC32 | MPQ_ATTRIBUTE_FILETIME | MPQ_ATTRIBUTE_MD5;
        pStream = NULL;
    }

    // Fill the MPQ header
    if(nError == ERROR_SUCCESS)
    {
        TMPQHeader * pHeader = ha->pHeader;

        // Fill the MPQ header
        memset(pHeader, 0, sizeof(ha->HeaderData));
        pHeader->dwID             = ID_MPQ;
        pHeader->dwHeaderSize     = MpqHeaderSizes[wFormatVersion];
        pHeader->dwArchiveSize    = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash);
        pHeader->wFormatVersion   = wFormatVersion;
        pHeader->wSectorSize      = GetSectorSizeShift(ha->dwSectorSize);
        pHeader->dwHashTablePos   = pHeader->dwHeaderSize;
        pHeader->dwHashTableSize  = dwHashTableSize;
        pHeader->dwBlockTablePos  = pHeader->dwHashTablePos + dwHashTableSize * sizeof(TMPQHash);
        pHeader->dwBlockTableSize = dwBlockTableSize;

        // For MPQs version 4 and higher, we set the size of raw data block
        // for calculating MD5
        if(wFormatVersion >= MPQ_FORMAT_VERSION_4)
            pHeader->dwRawChunkSize = 0x4000;

        // Write the naked MPQ header
        nError = WriteNakedMPQHeader(ha);

        //
        // Note: Don't recalculate position of MPQ tables at this point.
        // We merely set a flag that indicates that the MPQ tables
        // have been changed, and SaveMpqTables will do the work when closing the archive.
        //

        ha->dwFlags |= MPQ_FLAG_CHANGED;
    }

    // Create initial hash table
    if(nError == ERROR_SUCCESS)
    {
        nError = CreateHashTable(ha, dwHashTableSize);
    }

    // Create initial HET table, if the caller required an MPQ format 3.0 or newer
    if(nError == ERROR_SUCCESS && wFormatVersion >= MPQ_FORMAT_VERSION_3)
    {
        ha->pHetTable = CreateHetTable(ha->dwMaxFileCount, 0x40, true);
        if(ha->pHetTable == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Create initial file table
    if(nError == ERROR_SUCCESS)
    {
        ha->pFileTable = ALLOCMEM(TFileEntry, dwMaxFileCount);
        if(ha->pFileTable != NULL)
            memset(ha->pFileTable, 0x00, sizeof(TFileEntry) * dwMaxFileCount);
        else
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Cleanup : If an error, delete all buffers and return
    if(nError != ERROR_SUCCESS)
    {
        FileStream_Close(pStream);
        FreeMPQArchive(ha);
        SetLastError(nError);
        ha = NULL;
    }
    
    // Return the values
    *phMpq = (HANDLE)ha;
    return (nError == ERROR_SUCCESS);
}
Beispiel #19
0
int main() {
	HashTablePTR table = NULL;
	for(;;) {
		char cmd[80];
		printf("Command: ");
		int retval = scanf("%79s", cmd);
		if (retval <= 0) break;
		if (strcmp(cmd, "create") == 0) {
			printf("Size: ");
			int size;
			scanf("%d", &size);
			/* note: this is a signed int because unsigned int
			 * conversion in scanf is drunk and return 0xffffffff
			 * for -1.
			 */
			if (size < 0) {
				printf("Size cannot be negative, clamping to 0.\n");
				size = 0;
			}
			if (table != NULL) DestroyHashTable(&table);
			CreateHashTable(&table, (unsigned int) size);
			
			if (table == NULL) {
				printf("create returned NULL\n");
			} else {
				printf("create returned non-NULL\n");
			}
		} else if (strcmp(cmd, "destroy") == 0) {
			freeHashTableContents(table);
			DestroyHashTable(&table);
			if (table != NULL) {
				printf("FAIL: destroy did not set NULL");
			}
		} else if (strcmp(cmd, "print") == 0) {
			printHashTable(table);
		} else if (strcmp(cmd, "set") == 0) {
			printf("Key: ");
			char key[81];
			scanf(" %80s", key);
			char* value = malloc(81 * sizeof(char));
			scanf(" %80s", value);
			char* existingData = NULL;
			int success = InsertEntry(table, key, value, (void**) &existingData);
			switch(success){
				case GET_NONE:
					printf("Inserted into blank space\n");
					break;
				case GET_COLLIDE:
					printf("Inserted after resolving hash collision\n");
					break;
				case GET_EXISTS:
					printf("Inserted after removing existing data: %s\n", existingData);
					free(existingData);
					break;
				default:
					printf("InsertEntry failed\n");
					free(value);
					break;
			}
			if (success >= 0) {
				HashTableInfo info;
				int status2 = GetHashTableInfo(table, &info);
				if (status2 == 0) {
					if (info.dynamicBehaviour && info.useFactor > info.expandUseFactor) {
						printf("Insert FAIL: use factor %f"
							" greater than expand use factor. %f\n",
							info.useFactor, info.expandUseFactor);
					}
				}
			}
		} else if (strcmp(cmd, "read") == 0) {
			printf("Key: ");
			char key[81];
			scanf(" %80s", key);
			char* value;
			int success = FindEntry(table, key, (void**) &value);
			if (success == 0) {
				printf("%s\n", value);
			} else {
				printf("readPosition returned failure\n");
			}
		} else if (strcmp(cmd, "delete") == 0) {
			printf("Key: ");
			char key[81];
			scanf(" %80s", key);
			char* value;
			int success = DeleteEntry(table, key, (void**) &value);
			if (success == 0) {
				printf("Deleted (was %s)\n", value);
				free(value);
				HashTableInfo info;
				int status2 = GetHashTableInfo(table, &info);
				if (status2 == 0) {
					if (info.dynamicBehaviour &&
						info.useFactor < info.contractUseFactor) {
						printf("Delete FAIL: use factor %f"
							" less than contract use factor. %f\n",
							info.useFactor, info.contractUseFactor);
					}
				}
			} else {
				printf("DeleteValue returned failure\n");
			}
		} else if (strcmp(cmd, "load") == 0) {
			float myfloat;
			int status = GetLoadFactor(table, &myfloat);
			if (status == 0) {
				printf("Load factor: %f\n", myfloat);
			} else {
				printf("Load factor returned failure\n");
			}
		} else if (strcmp(cmd, "sentinel") == 0) {
			sentinelTest();
		} else if (strcmp(cmd, "info") == 0) {
			HashTableInfo info;
			int status = GetHashTableInfo(table, &info);
			if (status == 0) {
				printf(
					"Bucket count: %u\n"
					"Load factor: %f\n"
					"Use factor: %f\n"
					"Largest bucket size: %u\n"
					"Dynamic behaviour: %d\n"
					"Expand use factor: %f\n"
					"Contract use factor: %f\n",
					info.bucketCount, info.loadFactor, info.useFactor, info.largestBucketSize,
					info.dynamicBehaviour, info.expandUseFactor, info.contractUseFactor);
			} else {
				printf("GetHashTableInfo returned failure\n");
			}
		} else if (strcmp(cmd, "setresize") == 0) {
			int resize;
			float expand, contract;
			printf("Resize: (0/1) ");
			scanf("%d", &resize);
			printf("Expand: ");
			scanf("%f", &expand);
			printf("Contract: ");
			scanf("%f", &contract);
			int status = SetResizeBehaviour(table, resize, expand, contract);
			if (status != 0) {
				printf("Set resize returned failure\n");
			}
		} else if (strcmp(cmd, "quit") == 0) {
			break;
		} else {
			printf("Invalid command\n");
		}
	}
	if (table != NULL) {
		freeHashTableContents(table);
		DestroyHashTable(&table);
	}
	return 0;
}