Selaa lähdekoodia

-Fix some CppCheck
-Fix bugreport:9088 (constant not always recognize if stating by number) thx to Hercule is_number
-Add infos on read_constant for check/debug

lighta 11 vuotta sitten
vanhempi
commit
79f4600dcd
7 muutettua tiedostoa jossa 122 lisäystä ja 67 poistoa
  1. 3 0
      npc/pre-re/scripts_main.conf
  2. 7 5
      src/char/char.c
  3. 4 5
      src/char/char_mapif.c
  4. 5 8
      src/common/sql.c
  5. 2 1
      src/map/battle.c
  6. 11 8
      src/map/clif.c
  7. 90 40
      src/map/script.c

+ 3 - 0
npc/pre-re/scripts_main.conf

@@ -40,6 +40,9 @@ import: npc/pre-re/scripts_mapflags.conf
 import: npc/pre-re/scripts_monsters.conf
 import: npc/pre-re/scripts_warps.conf
 
+// Test for regressions and such
+//import: npc/scripts_test.conf
+
 // ------------------- Custom Script Files ----------------------
 // - Your NPCs go in this file!
 import: npc/scripts_custom.conf

+ 7 - 5
src/char/char.c

@@ -2025,12 +2025,14 @@ int char_pincode_compare( int fd, struct char_session_data* sd, char* pin ){
 
 
 void char_pincode_decrypt( uint32 userSeed, char* pin ){
-	int i, pos;
+	int i;
 	char tab[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 	char *buf;
-	uint32 multiplier = 0x3498, baseSeed = 0x881234;
-
+	
 	for( i = 1; i < 10; i++ ){
+		int pos;
+		uint32 multiplier = 0x3498, baseSeed = 0x881234;
+		
 		userSeed = baseSeed + userSeed * multiplier;
 		pos = userSeed % ( i + 1 );
 		if( i != pos ){
@@ -2651,14 +2653,14 @@ int char_config_read(const char* cfgName){
 			if (charserv_config.start_zeny < 0)
 				charserv_config.start_zeny = 0;
 		} else if (strcmpi(w1, "start_items") == 0) {
-			int i=0, n=0;
+			int i=0;
 			char *lineitem, **fields;
 			int fields_length = 3+1;
 			fields = (char**)aMalloc(fields_length*sizeof(char*));
 
 			lineitem = strtok(w2, ":");
 			while (lineitem != NULL) {
-				n = sv_split(lineitem, strlen(lineitem), 0, ',', fields, fields_length, SV_NOESCAPE_NOTERMINATE);
+				int n = sv_split(lineitem, strlen(lineitem), 0, ',', fields, fields_length, SV_NOESCAPE_NOTERMINATE);
 				if(n+1 < fields_length){
 					ShowDebug("start_items: not enough arguments for %s! Skipping...\n",lineitem);
 					lineitem = strtok(NULL, ":"); //next itemline

+ 4 - 5
src/char/char_mapif.c

@@ -315,16 +315,15 @@ int chmapif_parse_regmapuser(int fd, int id){
 		return 0;
 	{
 		//TODO: When data mismatches memory, update guild/party online/offline states.
-		int aid, cid, i;
-		struct online_char_data* character;
 		DBMap* online_char_db = char_get_onlinedb();
+		int i;
 
 		map_server[id].users = RFIFOW(fd,4);
 		online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown'
 		for(i = 0; i < map_server[id].users; i++) {
-			aid = RFIFOL(fd,6+i*8);
-			cid = RFIFOL(fd,6+i*8+4);
-			character = idb_ensure(online_char_db, aid, char_create_online_data);
+			int aid = RFIFOL(fd,6+i*8);
+			int cid = RFIFOL(fd,6+i*8+4);
+			struct online_char_data* character = idb_ensure(online_char_db, aid, char_create_online_data);
 			if( character->server > -1 && character->server != id )
 			{
 				ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",

+ 5 - 8
src/common/sql.c

@@ -833,8 +833,6 @@ int SqlStmt_NextRow(SqlStmt* self)
 	int err;
 	size_t i;
 	size_t cols;
-	MYSQL_BIND* column;
-	unsigned long length;
 
 	if( self == NULL )
 		return SQL_ERROR;
@@ -864,7 +862,7 @@ int SqlStmt_NextRow(SqlStmt* self)
 		cols = SqlStmt_NumColumns(self);
 		for( i = 0; i < cols; ++i )
 		{
-			column = &self->columns[i];
+			MYSQL_BIND* column = &self->columns[i];
 			column->error = &truncated;
 			mysql_stmt_fetch_column(self->stmt, column, (unsigned int)i, 0);
 			column->error = NULL;
@@ -889,8 +887,8 @@ int SqlStmt_NextRow(SqlStmt* self)
 	cols = SqlStmt_NumColumns(self);
 	for( i = 0; i < cols; ++i )
 	{
-		length = self->column_lengths[i].length;
-		column = &self->columns[i];
+		unsigned long length = self->column_lengths[i].length;
+		MYSQL_BIND* column = &self->columns[i];
 #if !defined(MYSQL_DATA_TRUNCATED)
 		// MySQL 4.1/(below?) returns success even if data is truncated, so we test truncation manually [FlavioJS]
 		if( column->buffer_length < length )
@@ -965,10 +963,10 @@ void SqlStmt_Free(SqlStmt* self)
 
 /// Receives MySQL error codes during runtime (not on first-time-connects).
 void ra_mysql_error_handler(unsigned int ecode) {
-	static unsigned int retry = 1;
 	switch( ecode ) {
 		case 2003:// Can't connect to MySQL (this error only happens here when failing to reconnect)
 			if( mysql_reconnect_type == 1 ) {
+				static unsigned int retry = 1;
 				if( ++retry > mysql_reconnect_count ) {
 					ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry);
 					exit(EXIT_FAILURE);
@@ -979,7 +977,6 @@ void ra_mysql_error_handler(unsigned int ecode) {
 }
 
 void Sql_inter_server_read(const char* cfgName, bool first) {
-	int i;
 	char line[1024], w1[1024], w2[1024];
 	FILE* fp;
 
@@ -994,7 +991,7 @@ void Sql_inter_server_read(const char* cfgName, bool first) {
 	}
 
 	while(fgets(line, sizeof(line), fp)) {
-		i = sscanf(line, "%[^:]: %[^\r\n]", w1, w2);
+		int i = sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2);
 		if(i != 2)
 			continue;
 

+ 2 - 1
src/map/battle.c

@@ -3613,8 +3613,9 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 			if( sc && sc->data[SC_EXPLOSIONSPIRITS] ) {
 				skillratio += sc->data[SC_EXPLOSIONSPIRITS]->val1 * 20;
 				RE_LVL_DMOD(120);
-			} else
+			} else {
 				RE_LVL_DMOD(150);
+			}
 			break;
 		case SR_KNUCKLEARROW:
 			if( wd.miscflag&4 ){  // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] %

+ 11 - 8
src/map/clif.c

@@ -7447,7 +7447,7 @@ void clif_mvp_exp(struct map_session_data *sd, unsigned int exp)
 	fd=sd->fd;
 	WFIFOHEAD(fd,packet_len(0x10b));
 	WFIFOW(fd,0)=0x10b;
-	WFIFOL(fd,2)=cap_value(exp,0,INT32_MAX);
+	WFIFOL(fd,2)=min(exp,UINT32_MAX);
 	WFIFOSET(fd,packet_len(0x10b));
 }
 
@@ -15478,7 +15478,7 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
 			}
 			break;
 		case SP_MATK1:
-			WFIFOL(fd,4) = cap_value(status->matk_max, 0, INT16_MAX);
+			WFIFOL(fd,4) = min(status->matk_max, UINT16_MAX);
 			break;
 		case SP_HIT:
 			WFIFOL(fd,4) = status->hit;
@@ -15545,7 +15545,7 @@ void clif_mercenary_info(struct map_session_data *sd)
 	// Mercenary shows ATK as a random value between ATK ~ ATK2
 	atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk;
 	WFIFOW(fd,6) = cap_value(atk, 0, INT16_MAX);
-	WFIFOW(fd,8) = cap_value(status->matk_max, 0, INT16_MAX);
+	WFIFOW(fd,8) = min(status->matk_max, UINT16_MAX);
 	WFIFOW(fd,10) = status->hit;
 	WFIFOW(fd,12) = status->cri/10;
 	WFIFOW(fd,14) = status->def;
@@ -15572,7 +15572,7 @@ void clif_mercenary_info(struct map_session_data *sd)
 void clif_mercenary_skillblock(struct map_session_data *sd)
 {
 	struct mercenary_data *md;
-	int fd, i, len = 4, id, j;
+	int fd, i, len = 4;
 
 	if( sd == NULL || (md = sd->md) == NULL )
 		return;
@@ -15582,6 +15582,7 @@ void clif_mercenary_skillblock(struct map_session_data *sd)
 	WFIFOW(fd,0) = 0x29d;
 	for( i = 0; i < MAX_MERCSKILL; i++ )
 	{
+		int id, j;
 		if( (id = md->db->skill[i].id) == 0 )
 			continue;
 		j = id - MC_SKILLBASE;
@@ -17487,8 +17488,8 @@ void packetdb_readdb(void)
 {
 	FILE *fp;
 	char line[1024];
-	int ln=0, entries=0;
-	int cmd,i,j,packet_ver;
+	int ln=0;
+	int cmd,i,j;
 	int max_cmd=-1;
 	bool skip_ver = false;
 	int warned = 0;
@@ -17984,7 +17985,9 @@ void packetdb_readdb(void)
 
 	clif_config.packet_db_ver = MAX_PACKET_VER;
 	for(f = 0; f<ARRAYLENGTH(filename); f++){
-		entries = 0;
+		int entries = 0;
+		int packet_ver = MAX_PACKET_VER;	// read into packet_db's version by default
+		
 		sprintf(line, "%s/%s", db_path,filename[f]);
 		if( (fp=fopen(line,"r"))==NULL ){
 			if(f==0) {
@@ -17993,7 +17996,7 @@ void packetdb_readdb(void)
 			}
 			return;
 		}
-		packet_ver = MAX_PACKET_VER;	// read into packet_db's version by default
+		
 		while( fgets(line, sizeof(line), fp) )
 		{
 			ln++;

+ 90 - 40
src/map/script.c

@@ -606,7 +606,7 @@ static void script_reportdata(struct script_data* data)
 /// Reports on the console information about the current built-in function.
 static void script_reportfunc(struct script_state* st)
 {
-	int i, params, id;
+	int params, id;
 	struct script_data* data;
 
 	if( !script_hasdata(st,0) )
@@ -626,6 +626,7 @@ static void script_reportfunc(struct script_state* st)
 
 	if( params > 0 )
 	{
+		int i;
 		ShowDebug("Function: %s (%d parameter%s):\n", get_str(id), params, ( params == 1 ) ? "" : "s");
 
 		for( i = 2; i <= script_lastdata(st); i++ )
@@ -729,7 +730,7 @@ static int search_str(const char* p)
 /// If an identical string is already present, returns its id instead.
 int add_str(const char* p)
 {
-	int i, h;
+	int h;
 	int len;
 
 	h = calc_hash(p);
@@ -740,6 +741,7 @@ int add_str(const char* p)
 	}
 	else
 	{// scan for end of list, or occurence of identical string
+		int i;
 		for( i = str_hash[h]; ; i = str_data[i].next )
 		{
 			if( strcasecmp(get_str(i),p) == 0 )
@@ -868,7 +870,7 @@ static void add_scriptl(int l)
  *------------------------------------------*/
 void set_label(int l,int pos, const char* script_pos_cur)
 {
-	int i,next;
+	int i;
 
 	if(str_data[l].type==C_INT || str_data[l].type==C_PARAM || str_data[l].type==C_FUNC)
 	{	//Prevent overwriting constants values, parameters and built-in functions [Skotlex]
@@ -882,7 +884,7 @@ void set_label(int l,int pos, const char* script_pos_cur)
 	str_data[l].type=(str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
 	str_data[l].label=pos;
 	for(i=str_data[l].backpatch;i>=0 && i!=0x00ffffff;){
-		next=GETVALUE(script_buf,i);
+		int next=GETVALUE(script_buf,i);
 		script_buf[i-1]=(str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
 		SETVALUE(script_buf,i,pos);
 		i=next;
@@ -1105,7 +1107,7 @@ static void parse_nextline(bool first, const char* p)
 /// @param p script position where the function should run from
 /// @return NULL if not a variable assignment, the new position otherwise
 const char* parse_variable(const char* p) {
-	int i, j, word;
+	int word;
 	c_op type = C_NOP;
 	const char *p2 = NULL;
 	const char *var = p;
@@ -1119,6 +1121,7 @@ const char* parse_variable(const char* p) {
 	}
 
 	if( *p == '[' ) {// array variable so process the array as appropriate
+		int i,j;
 		for( p2 = p, i = 0, j = 1; p; ++ i ) {
 			if( *p ++ == ']' && --(j) == 0 ) break;
 			if( *p == '[' ) ++ j;
@@ -1238,6 +1241,43 @@ const char* parse_variable(const char* p) {
 	return p;
 }
 
+/*
+ * Checks whether the gives string is a number literal
+ *
+ * Mainly necessary to differentiate between number literals and NPC name
+ * constants, since several of those start with a digit.
+ *
+ * All this does is to check if the string begins with an optional + or - sign,
+ * followed by a hexadecimal or decimal number literal literal and is NOT
+ * followed by a underscore or letter.
+ *
+ * @author : Hercules.ws
+ * @param p Pointer to the string to check
+ * @return Whether the string is a number literal
+ */
+bool is_number(const char *p) {
+	const char *np;
+	if (!p)
+		return false;
+	if (*p == '-' || *p == '+')
+		p++;
+	np = p;
+	if (*p == '0' && p[1] == 'x') {
+		p+=2;
+		np = p;
+		// Hexadecimal
+		while (ISXDIGIT(*np))
+			np++;
+	} else {
+		// Decimal
+		while (ISDIGIT(*np))
+			np++;
+	}
+	if (p != np && *np != '_' && !ISALPHA(*np)) // At least one digit, and next isn't a letter or _
+		return true;
+	return false;
+}
+
 /*==========================================
  * Analysis section
  *------------------------------------------*/
@@ -1265,7 +1305,7 @@ const char* parse_simpleexpr(const char *p)
 		if( *p != ')' )
 			disp_error_message("parse_simpleexpr: unmatched ')'",p);
 		++p;
-	} else if(ISDIGIT(*p) || ((*p=='-' || *p=='+') && ISDIGIT(p[1]))){
+	} else if(is_number(p)) {
 		char *np;
 		while(*p == '0' && ISDIGIT(p[1])) p++;
 		i=strtoll(p,&np,0);
@@ -1353,12 +1393,11 @@ const char* parse_simpleexpr(const char *p)
 const char* parse_subexpr(const char* p,int limit)
 {
 	int op,opl,len;
-	const char* tmpp;
 
 	p=skip_space(p);
 
 	if( *p == '-' ){
-		 tmpp = skip_space(p+1);
+		const char* tmpp = skip_space(p+1);
 		if( *tmpp == ';' || *tmpp == ',' ){
 			add_scriptl(LABEL_NEXTLINE);
 			p++;
@@ -1611,21 +1650,23 @@ const char* parse_syntax(const char* p)
 					disp_error_message("parse_syntax: expected a space ' '",p);
 				}
 				// check whether case label is integer or not
-				v = strtol(p,&np,0);
-				if(np == p) { //Check for constants
+				if(is_number(p)) {
+					//Numeric value
+					v = (int)strtol(p,&np,0);
+					if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word
+						p++;
+					p = skip_word(p);
+					if(np != p)
+						disp_error_message("parse_syntax: 'case' label is not an integer",np);
+				} else {
+					//Check for constants
 					p2 = skip_word(p);
-					v = p2-p; // length of word at p2
+					v = (int)(size_t) (p2-p); // length of word at p2
 					memcpy(label,p,v);
 					label[v]='\0';
 					if( !script_get_constant(label, &v) )
 						disp_error_message("parse_syntax: 'case' label is not an integer",p);
 					p = skip_word(p);
-				} else { //Numeric value
-					if((*p == '-' || *p == '+') && ISDIGIT(p[1]))	// pre-skip because '-' can not skip_word
-						p++;
-					p = skip_word(p);
-					if(np != p)
-						disp_error_message("parse_syntax: 'case' label is not an integer",np);
 				}
 				p = skip_space(p);
 				if(*p != ':')
@@ -2161,8 +2202,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
  *------------------------------------------*/
 static void add_buildin_func(void)
 {
-	int i,n;
-	const char* p;
+	int i;
 	for( i = 0; buildin_func[i].func; i++ )
 	{
 		// arg must follow the pattern: (v|s|i|r|l)*\?*\*?
@@ -2173,7 +2213,7 @@ static void add_buildin_func(void)
 		// 'l' - label
 		// '?' - one optional parameter
 		// '*' - unknown number of optional parameters
-		p = buildin_func[i].arg;
+		const char* p = buildin_func[i].arg;
 		while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p;
 		while( *p == '?' ) ++p;
 		if( *p == '*' ) ++p;
@@ -2182,15 +2222,15 @@ static void add_buildin_func(void)
 		} else if( *skip_word(buildin_func[i].name) != 0 ){
 			ShowWarning("add_buildin_func: ignoring function with invalid name \"%s\" (must be a word).\n", buildin_func[i].name);
 		} else {
-			n = add_str(buildin_func[i].name);
+			int n = add_str(buildin_func[i].name);
 			str_data[n].type = C_FUNC;
 			str_data[n].val = i;
 			str_data[n].func = buildin_func[i].func;
 
-		if (!strcmp(buildin_func[i].name, "set")) buildin_set_ref = n;
-		else if (!strcmp(buildin_func[i].name, "callsub")) buildin_callsub_ref = n;
-		else if (!strcmp(buildin_func[i].name, "callfunc")) buildin_callfunc_ref = n;
-		else if( !strcmp(buildin_func[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n;
+			if (!strcmp(buildin_func[i].name, "set")) buildin_set_ref = n;
+			else if (!strcmp(buildin_func[i].name, "callsub")) buildin_callsub_ref = n;
+			else if (!strcmp(buildin_func[i].name, "callfunc")) buildin_callfunc_ref = n;
+			else if( !strcmp(buildin_func[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n;
 		}
 	}
 }
@@ -2238,6 +2278,7 @@ static void read_constdb(void)
 	FILE *fp;
 	char line[1024],name[1024],val[1024];
 	int type;
+	int entries=0, skipped=0, linenum=0;
 
 	sprintf(line, "%s/const.txt", db_path);
 	fp=fopen(line, "r");
@@ -2247,15 +2288,28 @@ static void read_constdb(void)
 	}
 	while(fgets(line, sizeof(line), fp))
 	{
-		if(line[0]=='/' && line[1]=='/')
+		linenum++;
+		if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r') //ignore empty line
+			continue;
+		if(line[0]=='/' && line[1]=='/') //ignore commented line
 			continue;
+		
 		type=0;
-		if(sscanf(line,"%[A-Za-z0-9_],%[-0-9xXA-Fa-f],%d",name,val,&type)>=2 ||
-		   sscanf(line,"%[A-Za-z0-9_] %[-0-9xXA-Fa-f] %d",name,val,&type)>=2){
+		if(sscanf(line,"%1023[A-Za-z0-9/_],%1023[A-Za-z0-9/_-],%d",name,val,&type)>=2 ||
+		   sscanf(line,"%1023[A-Za-z0-9/_] %1023[A-Za-z0-9/_-] %d",name,val,&type)>=2){
+			entries++;
 			script_set_constant(name, (int)strtol(val, NULL, 0), (bool)type);
 		}
+		else {
+			skipped++;
+			ShowWarning("Skipping line '"CL_WHITE"%d"CL_RESET"', invalide constant definition\n",linenum);
+		}
 	}
 	fclose(fp);
+	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s/const.txt"CL_RESET"'.\n", entries, db_path);
+	if(skipped){
+		ShowWarning("Skipped '"CL_WHITE"%d"CL_RESET"', entries\n",skipped);
+	}
 }
 
 /**
@@ -2521,11 +2575,11 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 	// default unknown references to variables
 	for(i=LABEL_START;i<str_num;i++){
 		if(str_data[i].type==C_NOP){
-			int j,next;
+			int j;
 			str_data[i].type=C_NAME;
 			str_data[i].label=i;
 			for(j=str_data[i].backpatch;j>=0 && j!=0x00ffffff;){
-				next=GETVALUE(script_buf,j);
+				int next=GETVALUE(script_buf,j);
 				SETVALUE(script_buf,j,i);
 				j=next;
 			}
@@ -2915,9 +2969,6 @@ const char* conv_str(struct script_state* st, struct script_data* data)
 /// Converts the data to an int
 int conv_num(struct script_state* st, struct script_data* data)
 {
-	char* p;
-	long num;
-
 	get_val(st, data);
 	if( data_isint(data) )
 	{// nothing to convert
@@ -2927,7 +2978,9 @@ int conv_num(struct script_state* st, struct script_data* data)
 	{// string -> int
 		// the result does not overflow or underflow, it is capped instead
 		// ex: 999999999999 is capped to INT_MAX (2147483647)
-		p = data->u.str;
+		char* p = data->u.str;
+		long num;
+		
 		errno = 0;
 		num = strtol(data->u.str, NULL, 10);// change radix to 0 to support octal numbers "o377" and hex numbers "0xFF"
 		if( errno == ERANGE
@@ -3465,15 +3518,13 @@ void op_1(struct script_state* st, int op)
 /// @param func Built-in function for which the arguments are intended.
 static void script_check_buildin_argtype(struct script_state* st, int func)
 {
-	char type;
 	int idx, invalid = 0;
-	script_function* sf = &buildin_func[str_data[func].val];
 
 	for( idx = 2; script_hasdata(st, idx); idx++ )
 	{
 		struct script_data* data = script_getdata(st, idx);
-
-		type = sf->arg[idx-2];
+		script_function* sf = &buildin_func[str_data[func].val];
+		char type = sf->arg[idx-2];
 
 		if( type == '?' || type == '*' )
 		{// optional argument or unknown number of optional parameters ( no types are after this )
@@ -3922,7 +3973,6 @@ void run_script_main(struct script_state *st)
 				intif_saveregistry(sd,1);
 		}
 		script_free_state(st);
-		st = NULL;
 	}
 }
 
@@ -3942,7 +3992,7 @@ int script_config_read(char *cfgName)
 	{
 		if(line[0] == '/' && line[1] == '/')
 			continue;
-		i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
+		i=sscanf(line,"%1023[^:]: %1023[^\r\n]",w1,w2);
 		if(i!=2)
 			continue;