Ver código fonte

* Displaying op names instead of numbers in script engine errors.
* Fixed a bug introduced in the last rework of the fame ranking.
* Created safestrncpy that ensures the string is nul-terminated.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@10667 54d463be-8e91-2dee-dedb-b68131a5f0ec

FlavioJS 18 anos atrás
pai
commit
f68f40f94d
7 arquivos alterados com 213 adições e 108 exclusões
  1. 4 0
      Changelog-Trunk.txt
  2. 26 47
      src/char/char.c
  3. 25 46
      src/char_sql/char.c
  4. 77 0
      src/common/db.h
  5. 15 4
      src/common/strlib.c
  6. 7 2
      src/common/strlib.h
  7. 59 9
      src/map/script.c

+ 4 - 0
Changelog-Trunk.txt

@@ -3,6 +3,10 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2007/06/02
+	* Displaying op names instead of numbers in script engine errors.
+	* Fixed a bug introduced in the last rework of the fame ranking.
+	* Created safestrncpy that ensures the string is nul-terminated. [FlavioJS]
 2007/06/01
 	* Updated sql files [Playtester]
 	* Fixed ircbot not processing new users

+ 26 - 47
src/char/char.c

@@ -3123,7 +3123,9 @@ int parse_frommap(int fd)
 			char type = RFIFOB(fd, 10);
 			int size;
 			struct fame_list* list;
-			
+			int player_pos;
+			int fame_pos;
+
 			switch(type)
 			{
 				case 1:  size = fame_list_size_smith;   list = smith_fame_list;   break;
@@ -3131,56 +3133,33 @@ int parse_frommap(int fd)
 				case 3:  size = fame_list_size_taekwon; list = taekwon_fame_list; break;
 				default: size = 0;                      list = NULL;              break;
 			}
-			if( size == 0 )
-			{// No list
-				RFIFOSKIP(fd,11);
-				break; 
+
+			ARR_FIND(0, size, player_pos, list[player_pos].id == cid);
+			ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);
+
+			if( player_pos == size && fame_pos == size )
+				;// not on list and not enough fame to get on it
+			else if( fame_pos == player_pos )
+			{// same position
+				list[player_pos].fame = fame;
+				char_update_fame_list(type, player_pos, fame);
 			}
-			for( i = 0; i < size; ++i )
-			{
-				if( list[i].id != cid )
-					continue;
-				// player found, update position
-				if( i > 0 && fame >= list[i - 1].fame )
-				{// moved up
-					struct fame_list entry;
-					int t;
-					for( t = 0; fame < list[t].fame ; ++t )
-						;// get target position (always < i)
-					memcpy(&entry, &list[i], sizeof(struct fame_list));
-					entry.fame = fame;
-					memmove(&list[t + 1], &list[t], (t - i)*sizeof(struct fame_list));
-					memcpy(&list[t], &entry, sizeof(struct fame_list));
-					char_send_fame_list(-1);
-				}
-				else if( i < size - 1 && fame < list[i + 1].fame )
-				{// moved down - always stays in the list
-					struct fame_list entry;
-					int t;
-					for( t = i + 2; t < size && fame < list[t].fame ; ++t )
-						;// get target position
-					--t;
-					memcpy(&entry, &list[i], sizeof(struct fame_list));
-					entry.fame = fame;
-					memmove(&list[i], &list[i + 1], (t - i)*sizeof(struct fame_list));
-					memcpy(&list[t], &entry, sizeof(struct fame_list));
-					char_send_fame_list(-1);
+			else
+			{// move in the list
+				if( player_pos == size )
+				{// new ranker - not in the list
+					ARR_MOVE(size - 1, fame_pos, list, struct fame_list);
+					list[fame_pos].id = cid;
+					list[fame_pos].fame = fame;
+					char_loadName(cid, list[fame_pos].name);
 				}
 				else
-				{// same position
-					list[i].fame = fame;
-					char_update_fame_list(type, i, fame);
+				{// already in the list
+					if( fame_pos == size )
+						--fame_pos;// move to the end of the list
+					ARR_MOVE(player_pos, fame_pos, list, struct fame_list);
+					list[fame_pos].fame = fame;
 				}
-				break;
-			}
-
-			if( i == size && fame >= list[size - 1].fame )
-			{// not on list and has enough fame
-				for( i = 0; fame < list[i].fame; ++i )
-					;// get target position
-				list[i].id = cid;
-				list[i].fame = fame;
-				char_loadName(list[i].id, list[i].name);
 				char_send_fame_list(-1);
 			}
 

+ 25 - 46
src/char_sql/char.c

@@ -2822,6 +2822,8 @@ int parse_frommap(int fd)
 			char type = RFIFOB(fd, 10);
 			int size;
 			struct fame_list* list;
+			int player_pos;
+			int fame_pos;
 
 			switch(type)
 			{
@@ -2830,56 +2832,33 @@ int parse_frommap(int fd)
 				case 3:  size = fame_list_size_taekwon; list = taekwon_fame_list; break;
 				default: size = 0;                      list = NULL;              break;
 			}
-			if( size == 0 )
-			{// No list
-				RFIFOSKIP(fd,11);
-				break; 
+
+			ARR_FIND(0, size, player_pos, list[player_pos].id == cid);
+			ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);
+
+			if( player_pos == size && fame_pos == size )
+				;// not on list and not enough fame to get on it
+			else if( fame_pos == player_pos )
+			{// same position
+				list[player_pos].fame = fame;
+				char_update_fame_list(type, player_pos, fame);
 			}
-			for( i = 0; i < size; ++i )
-			{
-				if( list[i].id != cid )
-					continue;
-				// player found, update position
-				if( i > 0 && fame >= list[i - 1].fame )
-				{// moved up
-					struct fame_list entry;
-					int t;
-					for( t = 0; fame < list[t].fame ; ++t )
-						;// get target position (always < i)
-					memcpy(&entry, &list[i], sizeof(struct fame_list));
-					entry.fame = fame;
-					memmove(&list[t + 1], &list[t], (t - i)*sizeof(struct fame_list));
-					memcpy(&list[t], &entry, sizeof(struct fame_list));
-					char_send_fame_list(-1);
-				}
-				else if( i < size - 1 && fame < list[i + 1].fame )
-				{// moved down - always stays in the list
-					struct fame_list entry;
-					int t;
-					for( t = i + 2; t < size && fame < list[t].fame ; ++t )
-						;// get target position
-					--t;
-					memcpy(&entry, &list[i], sizeof(struct fame_list));
-					entry.fame = fame;
-					memmove(&list[i], &list[i + 1], (t - i)*sizeof(struct fame_list));
-					memcpy(&list[t], &entry, sizeof(struct fame_list));
-					char_send_fame_list(-1);
+			else
+			{// move in the list
+				if( player_pos == size )
+				{// new ranker - not in the list
+					ARR_MOVE(size - 1, fame_pos, list, struct fame_list);
+					list[fame_pos].id = cid;
+					list[fame_pos].fame = fame;
+					char_loadName(cid, list[fame_pos].name);
 				}
 				else
-				{// same position
-					list[i].fame = fame;
-					char_update_fame_list(type, i, fame);
+				{// already in the list
+					if( fame_pos == size )
+						--fame_pos;// move to the end of the list
+					ARR_MOVE(player_pos, fame_pos, list, struct fame_list);
+					list[fame_pos].fame = fame;
 				}
-				break;
-			}
-
-			if( i == size && fame >= list[size - 1].fame )
-			{// not on list and has enough fame
-				for( i = 0; fame < list[i].fame; ++i )
-					;// get target position
-				list[i].id = cid;
-				list[i].fame = fame;
-				char_loadName(list[i].id, list[i].name);
 				char_send_fame_list(-1);
 			}
 

+ 77 - 0
src/common/db.h

@@ -691,4 +691,81 @@ void* linkdb_search ( struct linkdb_node** head, void *key);
 void* linkdb_erase  ( struct linkdb_node** head, void *key);
 void  linkdb_final  ( struct linkdb_node** head );
 
+
+
+/// Finds an entry in an array.
+/// ex: ARR_FIND(0, size, i, list[i] == target);
+///
+/// @param __start   Starting index (ex: 0)
+/// @param __end     End index (ex: size of the array)
+/// @param __var     Index variable
+/// @param __cmp     Expression that returns true when the target entry is found
+#define ARR_FIND(__start, __end, __var, __cmp) \
+	do{ \
+		for( (__var) = (__start); (__var) < (__end); ++(__var) ) \
+			if( __cmp ) \
+				break; \
+	}while(0)
+
+
+
+/// Moves an entry of the array.
+/// Use ARR_MOVERIGHT/ARR_MOVELEFT if __from and __to are direct numbers.
+/// ex: ARR_MOVE(i, 0, list, int);// move index i to index 0
+///
+///
+/// @param __from   Initial index of the entry
+/// @param __end    Target index of the entry
+/// @param __arr    Array
+/// @param __type   Type of entry
+#define ARR_MOVE(__from, __to, __arr, __type) \
+	do{ \
+		if( (__from) != (__to) ) \
+		{ \
+			__type __backup__; \
+			memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
+			if( (__from) < (__to) ) \
+				memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
+			else if( (__from) > (__to) ) \
+				memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
+			memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
+		} \
+	}while(0)
+
+
+
+/// Moves an entry of the array to the right.
+/// ex: ARR_MOVERIGHT(1, 4, list, int);// move index 1 to index 4
+///
+/// @param __from   Initial index of the entry
+/// @param __end    Target index of the entry
+/// @param __arr    Array
+/// @param __type   Type of entry
+#define ARR_MOVERIGHT(__from, __to, __arr, __type) \
+	do{ \
+		__type __backup__; \
+		memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
+		memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
+		memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
+	}while(0)
+
+
+
+/// Moves an entry of the array to the left.
+/// ex: ARR_MOVELEFT(3, 0, list, int);// move index 3 to index 0
+///
+/// @param __from   Initial index of the entry
+/// @param __end    Target index of the entry
+/// @param __arr    Array
+/// @param __type   Type of entry
+#define ARR_MOVELEFT(__from, __to, __arr, __type) \
+	do{ \
+		__type __backup__; \
+		memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
+		memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
+		memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
+	}while(0)
+
+
+
 #endif /* _DB_H_ */

+ 15 - 4
src/common/strlib.c

@@ -1,14 +1,15 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/utils.h"
+#include "strlib.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "strlib.h"
-#include "../common/cbasetypes.h"
-#include "../common/utils.h"
-#include "../common/malloc.h"
 
 
 #define J_MAX_MALLOC_SIZE 65535
@@ -299,3 +300,13 @@ int config_switch(const char* str)
 
 	return (int)strtol(str, NULL, 0);
 }
+
+/// always nul-terminates the string
+char* safestrncpy(char* dst, const char* src, size_t n)
+{
+	char* ret;
+	ret = strncpy(dst, src, n);
+	if( ret != NULL )
+		ret[n - 1] = '\0';
+	return ret;
+}

+ 7 - 2
src/common/strlib.h

@@ -4,7 +4,9 @@
 #ifndef _STRLIB_H_
 #define _STRLIB_H_
 
-#include <stddef.h> // size_t
+#ifndef _CBASETYPES_H_
+#include "../common/cbasetypes.h"
+#endif
 
 char* jstrescape (char* pt);
 char* jstrescapecpy (char* pt, const char* spt);
@@ -15,7 +17,7 @@ char* trim(char* str);
 char* normalize_name(char* str,const char* delims);
 const char *stristr(const char *haystack, const char *needle);
 
-#ifdef __WIN32
+#ifdef WIN32
 #define HAVE_STRTOK_R
 #define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr))
 char* _strtok_r(char* s1, const char* s2, char** lasts);
@@ -28,4 +30,7 @@ size_t strnlen (const char* string, size_t maxlen);
 int e_mail_check(char* email);
 int config_switch(const char* str);
 
+/// always nul-terminates the string
+char* safestrncpy(char* dst, const char* src, size_t n);
+
 #endif /* _STRLIB_H_ */

+ 59 - 9
src/map/script.c

@@ -314,6 +314,56 @@ enum {
 	MF_GUILDLOCK
 };
 
+const char* script_op2name(int op)
+{
+#define RETURN_OP_NAME(type) case type: return #type
+	switch( op )
+	{
+	RETURN_OP_NAME(C_NOP);
+	RETURN_OP_NAME(C_POS);
+	RETURN_OP_NAME(C_INT);
+	RETURN_OP_NAME(C_PARAM);
+	RETURN_OP_NAME(C_FUNC);
+	RETURN_OP_NAME(C_STR);
+	RETURN_OP_NAME(C_CONSTSTR);
+	RETURN_OP_NAME(C_ARG);
+	RETURN_OP_NAME(C_NAME);
+	RETURN_OP_NAME(C_EOL);
+	RETURN_OP_NAME(C_RETINFO);
+	RETURN_OP_NAME(C_USERFUNC);
+	RETURN_OP_NAME(C_USERFUNC_POS);
+
+	// operators
+	RETURN_OP_NAME(C_OP3);
+	RETURN_OP_NAME(C_LOR);
+	RETURN_OP_NAME(C_LAND);
+	RETURN_OP_NAME(C_LE);
+	RETURN_OP_NAME(C_LT);
+	RETURN_OP_NAME(C_GE);
+	RETURN_OP_NAME(C_GT);
+	RETURN_OP_NAME(C_EQ);
+	RETURN_OP_NAME(C_NE);
+	RETURN_OP_NAME(C_XOR);
+	RETURN_OP_NAME(C_OR);
+	RETURN_OP_NAME(C_AND);
+	RETURN_OP_NAME(C_ADD);
+	RETURN_OP_NAME(C_SUB);
+	RETURN_OP_NAME(C_MUL);
+	RETURN_OP_NAME(C_DIV);
+	RETURN_OP_NAME(C_MOD);
+	RETURN_OP_NAME(C_NEG);
+	RETURN_OP_NAME(C_LNOT);
+	RETURN_OP_NAME(C_NOT);
+	RETURN_OP_NAME(C_R_SHIFT);
+	RETURN_OP_NAME(C_L_SHIFT);
+
+	default:
+		ShowDebug("script_op2name: unexpected op=%d\n", op);
+		return "???";
+	}
+#undef RETURN_OP_NAME
+}
+
 //Reports on the console the src of a script error.
 static void report_src(struct script_state *st)
 {
@@ -2392,7 +2442,7 @@ void op_3(struct script_state* st, int op)
 		flag = data->u.num;
 	else
 	{
-		ShowError("script:op_3: invalid type of data op:%d data:%d\n", op, data->type);
+		ShowError("script:op_3: invalid type of data op:%s data:%s\n", script_op2name(op), script_op2name(data->type));
 		report_src(st);
 		script_removetop(st, -3, 0);
 		script_pushnil(st);
@@ -2433,7 +2483,7 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
 			return;
 		}
 	default:
-		ShowError("script:op2_str: unexpected string operator op:%d\n", op);
+		ShowError("script:op2_str: unexpected string operator op:%s\n", script_op2name(op));
 		report_src(st);
 		script_pushnil(st);
 		st->state = END;
@@ -2469,7 +2519,7 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
 	case C_MOD:
 		if( i2 == 0 )
 		{
-			ShowError("script:op_2num: division by zero detected op:%d\n", op);
+			ShowError("script:op_2num: division by zero detected op:%s\n", script_op2name(op));
 			report_src(st);
 			script_pushnil(st);
 			st->state = END;
@@ -2487,20 +2537,20 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
 		case C_SUB: ret = i1 - i2; ret_double = (double)i1 - (double)i2; break;
 		case C_MUL: ret = i1 * i2; ret_double = (double)i1 * (double)i2; break;
 		default:
-			ShowError("script:op_2num: unexpected number operator op:%d\n", op);
+			ShowError("script:op_2num: unexpected number operator op:%s\n", script_op2name(op));
 			report_src(st);
 			script_pushnil(st);
 			return;
 		}
 		if( ret_double < INT_MIN )
 		{
-			ShowWarning("script:op_2num: underflow detected op:%d\n", op);
+			ShowWarning("script:op_2num: underflow detected op:%s\n", script_op2name(op));
 			report_src(st);
 			ret = INT_MIN;
 		}
 		else if( ret_double > INT_MAX )
 		{
-			ShowWarning("script:op_2num: overflow detected op:%d\n", op);
+			ShowWarning("script:op_2num: overflow detected op:%s\n", script_op2name(op));
 			report_src(st);
 			ret = INT_MAX;
 		}
@@ -2546,7 +2596,7 @@ void op_2(struct script_state *st, int op)
 	}
 	else
 	{// invalid argument
-		ShowError("script:op_2: invalid type of data op:%d left:%d right:%d\n", op, left->type, right->type);
+		ShowError("script:op_2: invalid type of data op:%s left:%s right:%s\n", script_op2name(op), script_op2name(left->type), script_op2name(right->type));
 		report_src(st);
 		script_removetop(st, -2, 0);
 		script_pushnil(st);
@@ -2568,7 +2618,7 @@ void op_1(struct script_state* st, int op)
 
 	if( !data_isint(data) )
 	{// not a number
-		ShowError("script:op_1: invalid type of data op:%d data:%d\n", op, data->type);
+		ShowError("script:op_1: invalid type of data op:%s data:%s\n", script_op2name(op), script_op2name(data->type));
 		report_src(st);
 		script_pushnil(st);
 		st->state = END;
@@ -2583,7 +2633,7 @@ void op_1(struct script_state* st, int op)
 	case C_NOT: i1 = ~i1; break;
 	case C_LNOT: i1 = !i1; break;
 	default:
-		ShowError("script:op_1: unexpected operator op:%d\n", op);
+		ShowError("script:op_1: unexpected operator op:%s\n", script_op2name(op));
 		report_src(st);
 		script_pushnil(st);
 		st->state = END;