Thread: Matching name does not match???

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Matching name does not match???

    I'll start with the relevant function (as far as I can see):
    Code:
    void* GetSpotByName( pool_t pool, spot_t *spot, char const *name ) {
    	size_t i = 0;
    static int called = 0;
    	++called;
    	spot_t *spots = (spot_t*)pool.list.data.data;
    	printf( "Call: %d, Name: %s\n", called, name );
    	for ( ; i < pool.list.used; ++i ) {
    		if ( !spots[i].data.name ) continue;
    		printf( "Call: %d, Byte: %zu, Node: %zu, Name: %s\n",
    			called, spots[i].byte, spots[i].node, spots[i].data.name );
    		if ( strcmp( spots[i].data.name, name ) == 0 ) {
    			puts("This one was returned");
    			if ( spot ) *spot = spots[i];
    			return spots[i].data.data;
    		}
    	}
    	if ( spot ) memset( spot, 0, sizeof(spot_t) );
    	return NULL;
    }
    Now the relevant output:
    Code:
    ...
    clang	-o mitsy.elf mitsy.o memory.o
    ./mitsy.elf
    mitsy alpha
    Opening test.c...
    Allocating text buffer...
    Passing execution pool & text buffer to compiler...
    Entering compiler loop...
    Call: 1, Name: int
    Call: 1, Byte: 18446744073709551615, Node: 0, Name: test.c
    Call: 1, Byte: 0, Node: 1, Name: _start
    Call: 1, Byte: 10, Node: 2, Name: exit
    Call: 1, Byte: 18446744073709551615, Node: 3, Name: __db
    Call: 1, Byte: 18446744073709551615, Node: 4, Name: __dw
    Call: 1, Byte: 18446744073709551615, Node: 5, Name: __dd
    Call: 1, Byte: 18446744073709551615, Node: 6, Name: __dq
    Call: 1, Byte: 18446744073709551615, Node: 7, Name: char
    Call: 1, Byte: 18446744073709551615, Node: 8, Name: short
    Call: 1, Byte: 18446744073709551615, Node: 9, Name: int
    Call: 1, Byte: 18446744073709551615, Node: 10, Name: signed
    Call: 1, Byte: 18446744073709551615, Node: 11, Name: unsigned
    Call: 1, Byte: 18446744073709551615, Node: 12, Name: long long
    Call: 1, Byte: 18446744073709551615, Node: 13, Name: float
    Call: 1, Byte: 18446744073709551615, Node: 14, Name: double
    Call: 1, Byte: 18446744073709551615, Node: 15, Name: long
    test.c:0:0:0, Unkown Type int
    Compilation Failed: ret = 1, errno = 0
    makefile:41: recipe for target 'run' failed
    make: *** [run] Error 1
    Compilation failed.
    As you will notice the program unexpectedly ignores the correct result leaving me confused as why it's doing so,
    I check the docs of strcmp() and I'm using it right so I haven't been able to identify the error in my code, I even tried switching my ctx->text[len] = 0 for ctx->text[len] = '\0' before passing it to this function and still same output.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Make it obvious what strings are being compared.
    Trailing whilespace in either of your strings could be stopping you.
    Code:
        printf( "Call: %d, Name: >>%s<<\n", called, name );
        for ( ; i < pool.list.used; ++i ) {
            if ( !spots[i].data.name ) continue;
            printf( "Call: %d, Byte: %zu, Node: %zu, Name: >>%s<<\n",
                called, spots[i].byte, spots[i].node, spots[i].data.name );
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    The whitespace is already replaced by 0 before calling the function, as for the names listed after that, they are all filled with string literals, in this case the literal "int" is being compared against, the code hands, here's the snippets of code before the call:
    Code:
    size_t wordlen( char const * text ) {
    	size_t len = 0;
    	if ( !text ) return 0;
    	for ( ; *text; ++text, ++len ) {
    		if ( *text > 127u )
    			continue;
    		if ( isalnum(*text) == 0 )
    			return len;
    	}
    	return len;
    }
    ...
    			len = wordlen( ctx->text ) + 1;
    			c = ctx->text[len];
    			ctx->text[len] = 0;
    ... comparisons for other stuff, no fiddling done
    				RETC = TypeOf( *(ctx->exec_content), ctx->text ); // does not fiddle, just passes directly

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    And yet it fails....

    I don't care what you think you've done, you need to examine what it's actually doing.

    Because what you think is happening, and what is actually happening are two different things.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    After some modifications (such as being explicit with \0 in my string literals) I now have this output:
    Code:
    ...
    clang	-o mitsy.elf mitsy.o memory.o
    ./mitsy.elf
    mitsy alpha
    Opening test.c...
    Allocating text buffer...
    Passing execution pool & text buffer to compiler...
    Entering compiler loop...
    Call: 1, Name: int
    Call: 1, Byte: 18446744073709551615, Node: 0, Name: test.c
    This one returned, name[11]: i, spot.data.name[11] = a
    test.c:0:0:0, Unkown Type int
    Compilation Failed: ret = 1, errno = 0
    makefile:41: recipe for target 'run' failed
    make: *** [run] Error 1
    Compilation failed.
    Again no modifications beyond replacing the character after 't' with '\0'

  6. #6
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    It seems strcmp & possibly strlen are doing something different than expected, after I added these:
    Code:
    size_t StrLeng( char const * txt ) {
    	size_t len;
    	if ( !txt ) return 0;
    	for ( len = 0; *txt != '\0'; ++len, ++txt );
    	return len;
    }
    int StrCompare( char const *txt, char const *val ) {
    	int pos;
    	if ( !txt || !val ) return -1;
    	if ( txt == val ) return 0;
    	for ( pos = 1; *txt == *val && *txt != '\0' && *val != '\0';
    		++txt, ++val, ++pos );
    	if ( *txt == *val ) return 0;
    	return pos;
    }
    And switched to them I started getting expected results

    Edit: Replaced Faulty StrCompare with not so faulty version (perhaps no faults?)
    Last edited by awsdert; 05-22-2019 at 05:05 AM.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Did you implement Salem's suggestion? There's really no harm doing it just to be sure.

    Quote Originally Posted by awsdert
    Code:
    if ( !txt || !val ) return -1;
    Why should the first argument be "less than" the second argument just because one of them is a null pointer? Since the pointers being not null is a pre-condition, you should write:
    Code:
    assert(txt && val && "Arguments must not be null pointers");
    Also, it looks like the computation of pos is incorrect: you don't return a negative integer when the first argument is "less than" the second argument.
    Last edited by laserlight; 05-22-2019 at 05:11 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    It's not necessary to identify if one string is less than the other, just returning the position of the first character that's different is fine, the position can then be used if it's needed, in this case I'm using it to print the character of each in the GetSpotFromName(), I'm now also returning forcibly if the pos is equal to the length of either name (allowing for Typeof to still return STT_NUM on an unfinished integer like long long when long is given), it's the caller's responsibility to determine what they use the position for whether it be, less than 0 being an error, 0 or more being used for less/greater than comparison, more text needed, simple mismatch or something else

  9. #9
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    945
    I tested out your function, unmodified, after adding my own "spot_t" and "pool_t" structures (I have no idea what yours look like so I had to guess from how they're used):

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    typedef struct {
            struct {
                    const char *name;
                    void *data;
            } data;
            size_t byte;
            size_t node;
    } spot_t;
    
    
    typedef struct {
            struct {
                    struct {
                            const spot_t *data;
                    } data;
                    size_t used;
            } list;
    } pool_t;
    
    
    void* GetSpotByName( pool_t pool, spot_t *spot, char const *name ) {
            size_t i = 0;
    static int called = 0;
            ++called;
            spot_t *spots = (spot_t*)pool.list.data.data;
            printf( "Call: %d, Name: %s\n", called, name );
            for ( ; i < pool.list.used; ++i ) {
                    if ( !spots[i].data.name ) continue;
                    printf( "Call: %d, Byte: %zu, Node: %zu, Name: %s\n",
                            called, spots[i].byte, spots[i].node, spots[i].data.name );
                    if ( strcmp( spots[i].data.name, name ) == 0 ) {
                            puts("This one was returned");
                            if ( spot ) *spot = spots[i];
                            return spots[i].data.data;
                    }
            }
            if ( spot ) memset( spot, 0, sizeof(spot_t) );
            return NULL;
    }
    
    
    int main()
    {
            spot_t spots[] = {
                    { .byte = 18446744073709551615LLU, .node =  0, .data.name = "test.c", },
                    { .byte =                    0LLU, .node =  1, .data.name = "_start", },
                    { .byte =                   10LLU, .node =  2, .data.name = "exit", },
                    { .byte = 18446744073709551615LLU, .node =  3, .data.name = "__db", },
                    { .byte = 18446744073709551615LLU, .node =  4, .data.name = "__dw", },
                    { .byte = 18446744073709551615LLU, .node =  5, .data.name = "__dd", },
                    { .byte = 18446744073709551615LLU, .node =  6, .data.name = "__dq", },
                    { .byte = 18446744073709551615LLU, .node =  7, .data.name = "char", },
                    { .byte = 18446744073709551615LLU, .node =  8, .data.name = "short", },
                    { .byte = 18446744073709551615LLU, .node =  9, .data.name = "int", },
                    { .byte = 18446744073709551615LLU, .node = 10, .data.name = "signed", },
                    { .byte = 18446744073709551615LLU, .node = 11, .data.name = "unsigned", },
                    { .byte = 18446744073709551615LLU, .node = 12, .data.name = "long long", },
                    { .byte = 18446744073709551615LLU, .node = 13, .data.name = "float", },
                    { .byte = 18446744073709551615LLU, .node = 14, .data.name = "double", },
                    { .byte = 18446744073709551615LLU, .node = 15, .data.name = "long", },
            };
            pool_t pool = {
                    .list = {
                            .data.data = spots,
                            .used = 16,
                    },
            };
            GetSpotByName(pool, NULL, "int");
            return 0;
    }
    Output:

    Code:
    Call: 1, Name: int
    Call: 1, Byte: 18446744073709551615, Node: 0, Name: test.c
    Call: 1, Byte: 0, Node: 1, Name: _start
    Call: 1, Byte: 10, Node: 2, Name: exit
    Call: 1, Byte: 18446744073709551615, Node: 3, Name: __db
    Call: 1, Byte: 18446744073709551615, Node: 4, Name: __dw
    Call: 1, Byte: 18446744073709551615, Node: 5, Name: __dd
    Call: 1, Byte: 18446744073709551615, Node: 6, Name: __dq
    Call: 1, Byte: 18446744073709551615, Node: 7, Name: char
    Call: 1, Byte: 18446744073709551615, Node: 8, Name: short
    Call: 1, Byte: 18446744073709551615, Node: 9, Name: int
    This one was returned
    So there must be something wrong (whitespace?) with the name in your spot_t structure or in the string you're passing in to GetSpotByName (or there could be undefined behavior caused by some code that you didn't post).

  10. #10
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by christop View Post
    I tested out your function, unmodified, after adding my own "spot_t" and "pool_t" structures (I have no idea what yours look like so I had to guess from how they're used):

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    typedef struct {
            struct {
                    const char *name;
                    void *data;
            } data;
            size_t byte;
            size_t node;
    } spot_t;
    
    
    typedef struct {
            struct {
                    struct {
                            const spot_t *data;
                    } data;
                    size_t used;
            } list;
    } pool_t;
    
    
    void* GetSpotByName( pool_t pool, spot_t *spot, char const *name ) {
            size_t i = 0;
    static int called = 0;
            ++called;
            spot_t *spots = (spot_t*)pool.list.data.data;
            printf( "Call: %d, Name: %s\n", called, name );
            for ( ; i < pool.list.used; ++i ) {
                    if ( !spots[i].data.name ) continue;
                    printf( "Call: %d, Byte: %zu, Node: %zu, Name: %s\n",
                            called, spots[i].byte, spots[i].node, spots[i].data.name );
                    if ( strcmp( spots[i].data.name, name ) == 0 ) {
                            puts("This one was returned");
                            if ( spot ) *spot = spots[i];
                            return spots[i].data.data;
                    }
            }
            if ( spot ) memset( spot, 0, sizeof(spot_t) );
            return NULL;
    }
    
    
    int main()
    {
            spot_t spots[] = {
                    { .byte = 18446744073709551615LLU, .node =  0, .data.name = "test.c", },
                    { .byte =                    0LLU, .node =  1, .data.name = "_start", },
                    { .byte =                   10LLU, .node =  2, .data.name = "exit", },
                    { .byte = 18446744073709551615LLU, .node =  3, .data.name = "__db", },
                    { .byte = 18446744073709551615LLU, .node =  4, .data.name = "__dw", },
                    { .byte = 18446744073709551615LLU, .node =  5, .data.name = "__dd", },
                    { .byte = 18446744073709551615LLU, .node =  6, .data.name = "__dq", },
                    { .byte = 18446744073709551615LLU, .node =  7, .data.name = "char", },
                    { .byte = 18446744073709551615LLU, .node =  8, .data.name = "short", },
                    { .byte = 18446744073709551615LLU, .node =  9, .data.name = "int", },
                    { .byte = 18446744073709551615LLU, .node = 10, .data.name = "signed", },
                    { .byte = 18446744073709551615LLU, .node = 11, .data.name = "unsigned", },
                    { .byte = 18446744073709551615LLU, .node = 12, .data.name = "long long", },
                    { .byte = 18446744073709551615LLU, .node = 13, .data.name = "float", },
                    { .byte = 18446744073709551615LLU, .node = 14, .data.name = "double", },
                    { .byte = 18446744073709551615LLU, .node = 15, .data.name = "long", },
            };
            pool_t pool = {
                    .list = {
                            .data.data = spots,
                            .used = 16,
                    },
            };
            GetSpotByName(pool, NULL, "int");
            return 0;
    }
    Output:

    Code:
    Call: 1, Name: int
    Call: 1, Byte: 18446744073709551615, Node: 0, Name: test.c
    Call: 1, Byte: 0, Node: 1, Name: _start
    Call: 1, Byte: 10, Node: 2, Name: exit
    Call: 1, Byte: 18446744073709551615, Node: 3, Name: __db
    Call: 1, Byte: 18446744073709551615, Node: 4, Name: __dw
    Call: 1, Byte: 18446744073709551615, Node: 5, Name: __dd
    Call: 1, Byte: 18446744073709551615, Node: 6, Name: __dq
    Call: 1, Byte: 18446744073709551615, Node: 7, Name: char
    Call: 1, Byte: 18446744073709551615, Node: 8, Name: short
    Call: 1, Byte: 18446744073709551615, Node: 9, Name: int
    This one was returned
    So there must be something wrong (whitespace?) with the name in your spot_t structure or in the string you're passing in to GetSpotByName (or there could be undefined behavior caused by some code that you didn't post).
    Well in theory it could be used like that, it's actually a holder for another 2 typedef structs which have their own management functions, but simply put yeah pool is a non-shrinkable list used for text & execution code in this case, anyways the .byte part is actually set to -1 by default to forcibly put it >= pool.data.size which is an indication it doesn't exist in the pool itself but is used by it's siblings in one way or another, I used something similar in mine to create a default list which is then added to ctx->exec_content before processing code, it's my way of handling data types and eventually typedefs without sticking them all in the executation code which gets passed to a linker function later (once I start actually adding conversion from code to hex).

    Aside from that there was a whitespace being caught somehow when passed to this function (turned out to be some code I forgot to delete) which is now resolved, I'll stick with these functions though to avoid another scenario where I can't see what the character actually was, honestly strcmp() is only useful in a strict usage scenario which makes it inflexible for any other usage, at least my function is actually flexible in how it is used

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 03-15-2019, 12:57 PM
  2. Replies: 3
    Last Post: 10-30-2014, 08:49 PM
  3. Exact Match
    By pritin in forum C++ Programming
    Replies: 2
    Last Post: 03-26-2007, 08:50 AM
  4. no match for operator << ??
    By neoragexxx in forum C++ Programming
    Replies: 6
    Last Post: 05-01-2006, 05:02 PM
  5. How do you match 2 files?
    By sketchit in forum C Programming
    Replies: 1
    Last Post: 11-10-2001, 08:06 PM

Tags for this Thread