Mudder
Sorcerer


Group: Members
Posts: 324
Joined: Oct 17, 2009
|
#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.
|
|
|
|
JohnnyStarr
Wizard


Group: Members
Posts: 953
Joined: Feb 14, 2009
|
#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
|
#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
|
#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
 
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
|
#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
|
#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!
|
......................... 
|
|
Tyche
Wizard


Group: Members
Posts: 1,702
Joined: May 23, 2006
|
#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
 
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
|
#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;
}
|
|
Last edited Jul 11, 2010, 3:37 pm by JohnnyStarr
|
|
Tyche
Wizard


Group: Members
Posts: 1,702
Joined: May 23, 2006
|
#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
 
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
|
#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.
|
......................... 
|
|
Tyche
Wizard


Group: Members
Posts: 1,702
Joined: May 23, 2006
|
#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
 
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.
|
|
|
|
Tyche
Wizard


Group: Members
Posts: 1,702
Joined: May 23, 2006
|
#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
 
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.
|
|
|
|