MudBytes
Pages: << prev 1, 2 next >>
Compile Error
Mudder
Sorcerer






Group: Members
Posts: 324
Joined: Oct 17, 2009

Go to the bottom of the page Go to the top of the page
#1 id:48164 Posted Jul 10, 2010, 8:03 am

It's been awhile since I've done active work and I'm slightly rusty getting back in. I'm using Linux Mint KDE 9 Isadora, I downloaded g++ and g++-4.4 and I'm using netbeans with the C++ plugin.

I'm not exactly what is causing this error.


act_comm.c: In function ‘void do_pmote(CHAR_DATA*, const char*)’:
act_comm.c:853: error: invalid conversion from ‘const char*’ to ‘char*’


This is line 853.

        if ( ( letter = strstr( argument, vch->name ) ) == NULL )


This is the whole function.

Code (C):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
void do_pmote( CHAR_DATA *ch, const char *argument )
{
    CHAR_DATA              *vch = NULL;
    char                   *letter = NULL;
    char                   *name = NULL;
    char                    last[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    char                    temp[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0";
    size_t                  matches = 0;
 
    if ( !IS_NPC( ch ) && IS_SET( ch->comm, COMM_NOEMOTE ) )
    {
        ch_printf( ch, "You can't show your emotions.\r\n" );
        return;
    }
 
    if ( argument[0] == '\0' )
    {
        ch_printf( ch, "Emote what?\r\n" );
        return;
    }
 
    act( "$n $t", ch, argument, NULL, TO_CHAR );
 
    for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room )
    {
        if ( vch->desc == NULL || vch == ch )
            continue;
 
        if ( ( letter = strstr( argument, vch->name ) ) == NULL )
        {
            MOBtrigger = false;
            act( "$N $t", vch, argument, ch, TO_CHAR );
            MOBtrigger = true;
            continue;
        }
 
        strcpy( temp, argument );
        temp[strlen( argument ) - strlen( letter )] = '\0';
        last[0] = '\0';
        name = vch->name;
 
        for ( ; *letter != '\0'; letter++ )
        {
            if ( *letter == '\'' && matches == strlen( vch->name ) )
            {
                strcat( temp, "r" );
                continue;
            }
 
            if ( *letter == 's' && matches == strlen( vch->name ) )
            {
                matches = 0;
                continue;
            }
 
            if ( matches == strlen( vch->name ) )
            {
                matches = 0;
            }
 
            if ( *letter == *name )
            {
                matches++;
                name++;
                if ( matches == strlen( vch->name ) )
                {
                    strcat( temp, "you" );
                    last[0] = '\0';
                    name = vch->name;
                    continue;
                }
                strncat( last, letter, 1 );
                continue;
            }
 
            matches = 0;
            strcat( temp, last );
            strncat( temp, letter, 1 );
            last[0] = '\0';
            name = vch->name;
        }
        MOBtrigger = false;
        act( "$N $t", vch, temp, ch, TO_CHAR );
        MOBtrigger = true;
    }
 
    return;
}
.........................
A wise man once said:
Never underestimate a newbie coder and the sheer amount of spare time they may accumulate.

RaM Fire Development Team. ROM from C to C++

Developing a tinymudserver codebase.

Runter
Wizard






Group: Developer
Posts: 2,929
Joined: Jun 1, 2006

Go to the bottom of the page Go to the top of the page
#2 id:48165 Posted Jul 10, 2010, 8:30 am

strstr() expects a char * and you're passing a const char * as the first argument to it.
.........................
CoralMud project (Mud codebase in Ruby)
HaikuMud project (HTML/JS/Ruby, web-app based MMO codebase)
My Web CV

JohnnyStarr
Wizard






Group: Members
Posts: 953
Joined: Feb 14, 2009

Go to the bottom of the page Go to the top of the page
#3 id:48179 Posted Jul 10, 2010, 9:08 pm

In this scope argument is type const char* instead of char* as Runter pointed out.
It sounds like this project is just in C? C++ has an overloaded function for strstr(char * str1, const char * str2) as it's parameter list.

Not sure where you're at as far as upgrading to g++, but it might be worth looking into.
If thats not an option you will need to take a different approach.

Last edited Jul 10, 2010, 9:14 pm by JohnnyStarr
Mudder
Sorcerer






Group: Members
Posts: 324
Joined: Oct 17, 2009

Go to the bottom of the page Go to the top of the page
#4 id:48182 Posted Jul 11, 2010, 3:34 am

I'm not sure. I never had this error with cygwin, but I compile this project with g++
.........................
A wise man once said:
Never underestimate a newbie coder and the sheer amount of spare time they may accumulate.

RaM Fire Development Team. ROM from C to C++

Developing a tinymudserver codebase.

Tyche
Wizard






Group: Members
Posts: 1,702
Joined: May 23, 2006

Go to the bottom of the page Go to the top of the page
#5 id:48183 Posted Jul 11, 2010, 5:00 am

Mudder said:
I'm not sure. I never had this error with cygwin, but I compile this project with g++


Different compiler versions. 
The latest cygwin g++ is 4.3.4 and produces a warning that the conversion from const char * to char * will be deprecated.
I think g++ 4.4.x versions flag it as an error now.
The latest VisualC++ compiler also flags it as an error.
.........................
Proud member of Team Hetero
http://jlsysinc.gotdns.com/ladybug_laugh2.jpghttp://jlsysinc.gotdns.com/teensymud_250x80.pnghttp://jlsysinc.gotdns.com/palin_calendar.jpg
For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known.

Mudder
Sorcerer






Group: Members
Posts: 324
Joined: Oct 17, 2009

Go to the bottom of the page Go to the top of the page
#6 id:48186 Posted Jul 11, 2010, 7:30 am

Ah, I see. Yes, I am using 4.4 on my linux.
.........................
A wise man once said:
Never underestimate a newbie coder and the sheer amount of spare time they may accumulate.

RaM Fire Development Team. ROM from C to C++

Developing a tinymudserver codebase.

quixadhal
Wizard






Group: Members
Posts: 1,815
Joined: Oct 17, 2007

Go to the bottom of the page Go to the top of the page
#7 id:48190 Posted Jul 11, 2010, 12:57 pm

Anything which is declared as "const" is treated as "constant" or "unchanging" by the compiler.  It allows it to do optimizations that assume the value of that variable on entry to the function doesn't change by the time the function exits (however that happens).  Since DikuMUD code was written before compilers generally did such things, in many cases things ended up declared "const" but then modified anyways, since the compiler let them get away with it.

In your case, the library function strstr() changes the argument passed to it during processing (It puts NULL bytes into the string as it goes, handing you back substrings).  Since your argument is declared const, you can't do that.

To work around it (and you'll need to do a LOT of this in any Dikurivative that hasn't already done it for you), you need to make a temporary copy of your string and do your parsing on it.  You can also try to trick the compiler by declaring a "char *" and later setting it to point to the same memory of the "const char *", but if the compiler realizes you did this, you're back to square one.

Good luck!
.........................
http://i302.photobucket.com/albums/nn96/quixadhal/DramaBytes2.png

Tyche
Wizard






Group: Members
Posts: 1,702
Joined: May 23, 2006

Go to the bottom of the page Go to the top of the page
#8 id:48192 Posted Jul 11, 2010, 2:37 pm

quixadhal said:
Anything which is declared as "const" is treated as "constant" or "unchanging" by the compiler.  It allows it to do optimizations that assume the value of that variable on entry to the function doesn't change by the time the function exits (however that happens).  Since DikuMUD code was written before compilers generally did such things, in many cases things ended up declared "const" but then modified anyways, since the compiler let them get away with it.

In your case, the library function strstr() changes the argument passed to it during processing (It puts NULL bytes into the string as it goes, handing you back substrings).  Since your argument is declared const, you can't do that.

To work around it (and you'll need to do a LOT of this in any Dikurivative that hasn't already done it for you), you need to make a temporary copy of your string and do your parsing on it.  You can also try to trick the compiler by declaring a "char *" and later setting it to point to the same memory of the "const char *", but if the compiler realizes you did this, you're back to square one.

Good luck!


This problem has nothing whatsoever to do with Diku code.  They wrote Diku in C and not C++.

strstr() does not modify the string by inserting NUL characters.

In fact it's perfectly valid ANSI C code and declared as:
  char * strstr(const char *s1, const char *s2);

However the problem is this declaration doesn't really make sense for obvious reasons. 

So in ANSI C++ they declared strstr() as follows:
  char * strstr(char *s1, const char *s2);
  const char * strstr(const char *s1, const char *s2);

So the variable holding the returned pointer has to be the same type as the first parameter.
.........................
Proud member of Team Hetero
http://jlsysinc.gotdns.com/ladybug_laugh2.jpghttp://jlsysinc.gotdns.com/teensymud_250x80.pnghttp://jlsysinc.gotdns.com/palin_calendar.jpg
For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known.

Last edited Jul 11, 2010, 2:38 pm by Tyche
JohnnyStarr
Wizard






Group: Members
Posts: 953
Joined: Feb 14, 2009

Go to the bottom of the page Go to the top of the page
#9 id:48193 Posted Jul 11, 2010, 3:26 pm

Dude, just use an std::string and move on ;)
Code (C++):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
#include <iostream>
#include <string.h>
#include <string>
 
using namespace std;
 
int main(void)
{
	const char* argument = "Hey you guys";
	string str;
	str.append(argument);
	str.replace(str.find("guys"), 5, "Girls!");
	cout << str;
}
 


Code (Output):
1
2
3
Hey you Girls!


Last edited Jul 11, 2010, 3:37 pm by JohnnyStarr
Tyche
Wizard






Group: Members
Posts: 1,702
Joined: May 23, 2006

Go to the bottom of the page Go to the top of the page
#10 id:48194 Posted Jul 11, 2010, 3:37 pm

JohnnyStarr said:
Ahh, that makes sense. I was wondering why it wasn't working with the overloaded method.
So if mudder changes "letter" to be const char* it should be fine yes?


Yes...err maybe.  I don't know how vch->name is declared.  He might have to cast it to const char*.
.........................
Proud member of Team Hetero
http://jlsysinc.gotdns.com/ladybug_laugh2.jpghttp://jlsysinc.gotdns.com/teensymud_250x80.pnghttp://jlsysinc.gotdns.com/palin_calendar.jpg
For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known.

Last edited Jul 11, 2010, 3:41 pm by Tyche
quixadhal
Wizard






Group: Members
Posts: 1,815
Joined: Oct 17, 2007

Go to the bottom of the page Go to the top of the page
#11 id:48196 Posted Jul 11, 2010, 9:57 pm

Tyche said:
strstr() does not modify the string by inserting NUL characters.

Sorry, I was thinking of strtok().  My bad.

As to the Diku authors using C instead of C++, whatever.  You use C functions out of the standard library, you are writing C code however you may like to delude yourself.
.........................
http://i302.photobucket.com/albums/nn96/quixadhal/DramaBytes2.png

Tyche
Wizard






Group: Members
Posts: 1,702
Joined: May 23, 2006

Go to the bottom of the page Go to the top of the page
#12 id:48198 Posted Jul 11, 2010, 11:16 pm

quixadhal said:

As to the Diku authors using C instead of C++, whatever.  You use C functions out of the standard library, you are writing C code however you may like to delude yourself.


Nonsense.
.........................
Proud member of Team Hetero
http://jlsysinc.gotdns.com/ladybug_laugh2.jpghttp://jlsysinc.gotdns.com/teensymud_250x80.pnghttp://jlsysinc.gotdns.com/palin_calendar.jpg
For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known.

David Haley
Wizard






Group: Members
Posts: 7,783
Joined: Jun 30, 2007

Go to the bottom of the page Go to the top of the page
#13 id:48199 Posted Jul 12, 2010, 6:28 am

The C vs. C++ declaration of strstr thing is a red herring. The point is that DikuMUD was lax with string constness in many places, and often treats string literals as char* when you really shouldn't.
.........................
-- d.c.h --
BabbleMUD Project (custom codebase)
Legends of the Darkstone (head coder)
http://david.the-haleys.org
.........................

Tyche
Wizard






Group: Members
Posts: 1,702
Joined: May 23, 2006

Go to the bottom of the page Go to the top of the page
#14 id:48203 Posted Jul 12, 2010, 9:25 am

Fact.  The do_pmote function was introduced in ROM.
Fact.  ROM was written in C, not C++. 
Fact.  The do_pmote function the poster listed compiles cleanly in modern ANSI-99 standard C.[1]
Fact.  The RaM project converted ROM from C to C++
Fact.  The RaM project authors are the sole source of the bug the poster posted.
Fact.  Neither the Diku team, Merc team nor ROM team are responsible for this bug. 
Fact.  I provided the poster with a fix.

[1] Proof:

Compile of pmote function from ROM 2.4B6
Code (text):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 
$ cat rompmote.c
#include <string.h>
#include <time.h>
#include <stdio.h>
#include "merc.h"
 
void do_pmote( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *vch;
    char *letter,*name;
    char last[MAX_INPUT_LENGTH], temp[MAX_STRING_LENGTH];
    int matches = 0;
 
    if ( !IS_NPC(ch) && IS_SET(ch->comm, COMM_NOEMOTE) )
    {
        send_to_char( "You can't show your emotions.\n\r", ch );
        return;
    }
 
    if ( argument[0] == '\0' )
    {
        send_to_char( "Emote what?\n\r", ch );
        return;
    }
 
    act( "$n $t", ch, argument, NULL, TO_CHAR );
 
    for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
    {
        if (vch->desc == NULL || vch == ch)
            continue;
 
        if ((letter = strstr(argument,vch->name)) == NULL)
        {
            act("$N $t",vch,argument,ch,TO_CHAR);
            continue;
        }
 
        strcpy(temp,argument);
        temp[strlen(argument) - strlen(letter)] = '\0';
        last[0] = '\0';
        name = vch->name;
 
        for (; *letter != '\0'; letter++)
        { 
            if (*letter == '\'' && matches == strlen(vch->name))
            {
                strcat(temp,"r");
                continue;
            }
 
            if (*letter == 's' && matches == strlen(vch->name))
            {
                matches = 0;
                continue;
            }
 
            if (matches == strlen(vch->name))
            {
                matches = 0;
            }
 
            if (*letter == *name)
            {
                matches++;
                name++;
                if (matches == strlen(vch->name))
                {
                    strcat(temp,"you");
                    last[0] = '\0';
                    name = vch->name;
                    continue;
                }
                strncat(last,letter,1);
                continue;
            }
 
            matches = 0;
            strcat(temp,last);
            strncat(temp,letter,1);
            last[0] = '\0';
            name = vch->name;
        }
 
        act("$N $t",vch,temp,ch,TO_CHAR);
    }
 
    return;
}
 
 
 
jlambert@atlas ~
$ gcc -Wall -ansi -std=c99 -c rompmote.c 
 


As you can see not only is ROM's pmote function 100% valid modern ANSI-C99, the merc.h header is as well.

Q.E.D.
.........................
Proud member of Team Hetero
http://jlsysinc.gotdns.com/ladybug_laugh2.jpghttp://jlsysinc.gotdns.com/teensymud_250x80.pnghttp://jlsysinc.gotdns.com/palin_calendar.jpg
For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known.

quixadhal
Wizard






Group: Members
Posts: 1,815
Joined: Oct 17, 2007

Go to the bottom of the page Go to the top of the page
#15 id:48205 Posted Jul 12, 2010, 11:29 am

Fact:  I was trying to explain *WHY* the const char * issue would likely appear again, not just hand-wave a fix at the OP.
Fact:  I didn't see any mention of RaM until Tyche mentioned it.
Observation:  Tyche has a rather painful stick lodged in a place that makes sitting down a mite uncomfortable.

I had already explained that I misread strstr() as strtok(), and I maintain that if you're mucking about with string functions from libc, you are indeed using C, even if you're ALSO using C++.  Anything else you feel like ####ing about today?
.........................
http://i302.photobucket.com/albums/nn96/quixadhal/DramaBytes2.png

Pages:<< prev 1, 2 next >>

Valid XHTML 1.1! Valid CSS!