summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-08-19 06:04:34 +0000
committerultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-08-19 06:04:34 +0000
commit8f4119ce9a0b70de6380c1d032a4cb6e5b51787d (patch)
treeb68f4fd457de57168ede9a1457853f7ad4e76f70
parent72d890661194b248620c5c353777cb96be18c821 (diff)
downloadhercules-8f4119ce9a0b70de6380c1d032a4cb6e5b51787d.tar.gz
hercules-8f4119ce9a0b70de6380c1d032a4cb6e5b51787d.tar.bz2
hercules-8f4119ce9a0b70de6380c1d032a4cb6e5b51787d.tar.xz
hercules-8f4119ce9a0b70de6380c1d032a4cb6e5b51787d.zip
* Fixed a deallocation mistake and some buffer overflows in npc_chat.c after doing rtfm@pcre.txt (all caused by incorrect usage of pcre api)
* Removed underscores in npc_chat.c's variable names (easier to read) * Reindented the whole thing (used spaces half of the time ._.) * Moved npc pcre-data deallocation from npc_remove_map to npc_unload git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11036 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--Changelog-Trunk.txt5
-rw-r--r--conf-tmpl/charcommand_athena.conf121
-rw-r--r--src/map/map.h2
-rw-r--r--src/map/npc.c7
-rw-r--r--src/map/npc.h2
-rw-r--r--src/map/npc_chat.c648
6 files changed, 362 insertions, 423 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index d72a48ea9..0928916ad 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -3,6 +3,11 @@ 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/08/18
+ * Fixed a deallocation mistake and some buffer overflows in npc_chat.c
+ after doing rtfm@pcre.txt (all caused by incorrect usage of pcre api)
+ * Removed underscores in npc_chat.c's variable names (easier to read)
+ * Moved npc pcre-data deallocation from npc_remove_map to npc_unload
2007/08/17
* Implemented the official dual-wield aspd equation [ultramage]
- using 0.7 instead of 0.66 as modifier (so aspd will be lower now)
diff --git a/conf-tmpl/charcommand_athena.conf b/conf-tmpl/charcommand_athena.conf
index 927a44054..acd89779a 100644
--- a/conf-tmpl/charcommand_athena.conf
+++ b/conf-tmpl/charcommand_athena.conf
@@ -1,13 +1,13 @@
// Athena charcommand Configuration file.
// Translated by Peter Kieser <pfak@telus.net>
-// Set here the symbol that you want to use for your commands
-// Only 1 character is get (default is '#'). You can set any character,
-// except control-character (0x00-0x1f), '%' (party chat speaking),
-// '/' (standard ragnarok GM commands) and '@' (Standard GM Commands)
-// With default character, all commands begin by a '#', example: #save SomePlayer
+// The symbol that will be used to recognize commands.
+// You can set any one character, except control-characters (0x00-0x1f),
+// '%', '$' (party/guild chat speaking) and '/' (standard client commands).
+// The symbol must be different from from the standard GM command symbol.
command_symbol: #
+
//--------------------------
// 0: normal player commands
// None for security purposes.
@@ -25,85 +25,86 @@ command_symbol: #
// 40: Sub-GM commands
-//View the items in a character's cart
+// View the items in a character's cart
cartlist: 40
-//Apply an effect onto another character
+// Apply an effect onto another character
effect: 40
-//View the exp of a character
+// View the exp of a character
exp: 40
-//List a chacter's items
+// List a chacter's items
itemlist: 40
-//View the jail time remaining
+// View the jail time remaining
jailtime: 40
-//Refresh a character
+// Refresh a character
refresh: 40
-//List a chacter's stats
+// List a chacter's stats
stats: 40
-//List a chacter's storage items
+// List a chacter's storage items
storagelist: 40
//---------------------
// 50: Sub-GM+ commands
-//Change a character's clothing color
+// Change a character's clothing color
dye: 50
-//Give another character a fake name
+// Give another character a fake name
fakename: 50
-//Open the hatch dialog for a character
+// Open the hatch dialog for a character
hatch: 50
-//Change a character's hair color
+// Change a character's hair color
hcolor: 50
haircolor: 50
-//Change a character's hair style
+// Change a character's hair style
hstyle: 50
hairstyle: 50
// Changes character's model
model: 50
-//Give or remove a peco from a character
+// Give or remove a peco from a character
mount: 50
mountpeco: 50
-//Make another character's pet friendly/not
+// Make another character's pet friendly/not
petfriendly: 50
-//Rename another character's pet
+// Rename another character's pet
petrename: 50
-//Change a character's size
+// Change a character's size
size: 50
//----------------
// 60: GM commands
-//Resurrects a dead character
+// Resurrects a dead character
alive: 60
+revive: 60
-//Give a player all the skills available to him/her
+// Give a player all the skills available to him/her
allskill: 60
allskills: 60
skillall: 60
skillsall: 60
-//Give a character the maximum possible stats
+// Give a character the maximum possible stats
allstat: 60
allstats: 60
statall: 60
statsall: 60
-//Change another character's base level (3 same commands)
+// Change another character's base level (3 same commands)
blvl: 60
blevel: 60
baselvl: 60
@@ -112,118 +113,118 @@ baselevel: 60
// Changes the sex of an online player (all characters on the account)
changesex: 60
-//Delete items from a character
+// Delete items from a character
delitem: 60
-//Disguise a character
+// Disguise a character
disguise: 60
undisguise: 60
-//Resets another character's designated maps
+// Resets another character's designated maps
feelreset: 60
-//Change the guild level for a character's guild
+// Change the guild level for a character's guild
glvl: 60
glevel: 60
guildlvl: 60
guildlevel: 60
-//Open guild storage for a character
+// Open guild storage for a character
gstorage: 60
-//Heal a character
+// Heal a character
heal: 60
-//Invoke GM Hide on a character
+// Invoke GM Hide on a character
hide: 60
-//Increase a character's homunculus' level
+// Increase a character's homunculus' level
hlvl: 60
hlevel: 60
homlvl: 60
homlevel: 60
-//Evolve a character's homunculus
+// Evolve a character's homunculus
homevolve: 60
homevolution: 60
-//Change a character's homunculus' friendly value
+// Change a character's homunculus' friendly value
homfriendly: 60
-//Change a character's homunculus' hunger value
+// Change a character's homunculus' hunger value
homhungry: 60
-//View a character's homunculus' stats
+// View a character's homunculus' stats
hominfo: 40
-//Give another character an item
+// Give another character an item
item: 60
-//Create a specific item (with cards, refines, etc
+// Create a specific item (with cards, refines, etc
item2: 60
-//Remove all of a character's possessions
+// Remove all of a character's possessions
itemreset: 60
-//Change another character's job (2 same commands)
+// Change another character's job (2 same commands)
job: 60
jobchange: 60
-//Change another character's job level (3 same commands)
+// Change another character's job level (3 same commands)
jlvl: 60
jlevel: 60
joblvl: 60
joblevel: 60
-//Allow a character to attack anybody
+// Allow a character to attack anybody
killer: 60
-//Make a character killable by anybody
+// Make a character killable by anybody
killable: 60
-//Return a character to their respawn point
+// Return a character to their respawn point
load: 60
-//Take away a character's platinum skill
+// Take away a character's platinum skill
lostskill: 60
-//Make a character immune to monsters
+// Make a character immune to monsters
monsterignore: 60
-//Apply a certain option to another character
+// Apply a certain option to another character
option: 60
-//Change a character's pet's hungry value
+// Change a character's pet's hungry value
pethungry: 60
-//Produce forged equipment on a character (as if he/she was a blacksmith)
+// Produce forged equipment on a character (as if he/she was a blacksmith)
produce: 60
-//Give another character a platinum skill
+// Give another character a platinum skill
questskill: 60
-//Performs a stat and skill reset on someone else.
+// Performs a stat and skill reset on someone else.
reset: 60
-//Save another character
+// Save another character
save: 60
// Gives another character skill points
skpoint: 60
-//Change a character's walking speed
+// Change a character's walking speed
speed: 60
-//Give another character spiritball effect
+// Give another character spiritball effect
spiritball: 60
-//Open storage for a character
+// Open storage for a character
storage: 60
// Gives another character status points
stpoint: 60
-//Change a character's stats
+// Change a character's stats
str: 60
agi: 60
vit: 60
@@ -243,10 +244,10 @@ rura+: 60
//----------------------
// 80: GM Chief commands
-//Refine a character's equipment
+// Refine a character's equipment
refine: 80
-//Give another character zeny
+// Give another character zeny
zeny: 80
//---------------------------
diff --git a/src/map/map.h b/src/map/map.h
index 01af03789..4ec216a3e 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -844,7 +844,7 @@ struct npc_data {
int eventtimer[MAX_EVENTTIMER];
short arenaflag;
- void *chatdb;
+ void* chatdb; // pointer to a npc_parse struct (see npc_chat.c)
struct npc_data *master_nd;
union {
diff --git a/src/map/npc.c b/src/map/npc.c
index b5fc1cacf..352161189 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1441,9 +1441,6 @@ int npc_remove_map(struct npc_data* nd)
if(nd->bl.prev == NULL || nd->bl.m < 0)
return 1; //Not assigned to a map.
m = nd->bl.m;
-#ifdef PCRE_SUPPORT
- npc_chat_finalize(nd);
-#endif
clif_clearunit_area(&nd->bl,2);
//Remove corresponding NPC CELLs
if (nd->bl.subtype == WARP) {
@@ -1513,6 +1510,10 @@ int npc_unload(struct npc_data* nd)
if (nd->chat_id) // remove npc chatroom object and kick users
chat_deletenpcchat(nd);
+#ifdef PCRE_SUPPORT
+ npc_chat_finalize(nd); // deallocate npc PCRE data structures
+#endif
+
if (nd->bl.subtype == SCRIPT) {
ev_db->foreach(ev_db,npc_unload_ev,nd->exname); //Clean up all events related.
if (nd->u.scr.timerid != -1) {
diff --git a/src/map/npc.h b/src/map/npc.h
index 74d49dd3c..2ce21d473 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -4,6 +4,8 @@
#ifndef _NPC_H_
#define _NPC_H_
+#include "map.h" // TBL_NPC
+
#define START_NPC_NUM 110000000
#define WARP_CLASS 45
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
index 7d3a9a2fa..a1fdae0bc 100644
--- a/src/map/npc_chat.c
+++ b/src/map/npc_chat.c
@@ -3,27 +3,22 @@
#ifdef PCRE_SUPPORT
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-
#include "../common/timer.h"
#include "../common/malloc.h"
-#include "../common/version.h"
#include "../common/nullpo.h"
#include "../common/showmsg.h"
+#include "../common/strlib.h"
-#include "map.h"
-#include "status.h"
-#include "npc.h"
-#include "chat.h"
-#include "script.h"
-#include "battle.h"
+#include "map.h" // struct mob_data, struct npc_data
+#include "script.h" // set_var()
#include "pcre.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
/**
* Written by MouseJstr in a vision... (2/21/2005)
*
@@ -71,24 +66,21 @@
* deletes a pset
*/
-/* Structure containing all info associated with a single pattern
- block */
-
+/* Structure containing all info associated with a single pattern block */
struct pcrematch_entry {
- struct pcrematch_entry *next_;
- char *pattern_;
- pcre *pcre_;
- pcre_extra *pcre_extra_;
- char *label_;
+ struct pcrematch_entry* next;
+ char* pattern;
+ pcre* pcre;
+ pcre_extra* pcre_extra;
+ char* label;
};
-/* A set of patterns that can be activated and deactived with a single
- command */
-
+/* A set of patterns that can be activated and deactived with a single command */
struct pcrematch_set {
- struct pcrematch_set *next_, *prev_;
- struct pcrematch_entry *head_;
- int setid_;
+ struct pcrematch_set* prev;
+ struct pcrematch_set* next;
+ struct pcrematch_entry* head;
+ int setid;
};
/*
@@ -100,10 +92,9 @@ struct pcrematch_set {
* also wanted people to be able to grab this one file to get updates
* without having to do a large number of changes.
*/
-
struct npc_parse {
- struct pcrematch_set *active_;
- struct pcrematch_set *inactive_;
+ struct pcrematch_set* active;
+ struct pcrematch_set* inactive;
};
@@ -112,63 +103,51 @@ struct npc_parse {
*
* This does NOT do the list management
*/
-
-void finalize_pcrematch_entry(struct pcrematch_entry *e)
+void finalize_pcrematch_entry(struct pcrematch_entry* e)
{
-//TODO: For some odd reason this causes a already-free'd error under Windows, but not *nix! [Skotlex]
-#ifndef _WIN32
- if (e->pcre_) {
- free(e->pcre_);
- e->pcre_ = NULL;
- }
-#endif
- if (e->pcre_extra_) {
- free(e->pcre_extra_);
- e->pcre_ = NULL;
- }
- aFree(e->pattern_);
- aFree(e->label_);
+ pcre_free(e->pcre);
+ pcre_free(e->pcre_extra);
+ aFree(e->pattern);
+ aFree(e->label);
}
/**
* Lookup (and possibly create) a new set of patterns by the set id
*/
-static struct pcrematch_set * lookup_pcreset(struct npc_data *nd,int setid)
+static struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid)
{
- struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
- nd->chatdb = npcParse = (struct npc_parse *)
- aCalloc(sizeof(struct npc_parse), 1);
-
- pcreset = npcParse->active_;
-
- while (pcreset != NULL) {
- if (pcreset->setid_ == setid)
- break;
- pcreset = pcreset->next_;
- }
- if (pcreset == NULL)
- pcreset = npcParse->inactive_;
-
- while (pcreset != NULL) {
- if (pcreset->setid_ == setid)
- break;
- pcreset = pcreset->next_;
- }
-
- if (pcreset == NULL) {
- pcreset = (struct pcrematch_set *)
- aCalloc(sizeof(struct pcrematch_set), 1);
- pcreset->next_ = npcParse->inactive_;
- if (pcreset->next_ != NULL)
- pcreset->next_->prev_ = pcreset;
- pcreset->prev_ = 0;
- npcParse->inactive_ = pcreset;
- pcreset->setid_ = setid;
- }
-
- return pcreset;
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ nd->chatdb = npcParse = (struct npc_parse *) aCalloc(sizeof(struct npc_parse), 1);
+
+ pcreset = npcParse->active;
+
+ while (pcreset != NULL) {
+ if (pcreset->setid == setid)
+ break;
+ pcreset = pcreset->next;
+ }
+ if (pcreset == NULL)
+ pcreset = npcParse->inactive;
+
+ while (pcreset != NULL) {
+ if (pcreset->setid == setid)
+ break;
+ pcreset = pcreset->next;
+ }
+
+ if (pcreset == NULL) {
+ pcreset = (struct pcrematch_set *) aCalloc(sizeof(struct pcrematch_set), 1);
+ pcreset->next = npcParse->inactive;
+ if (pcreset->next != NULL)
+ pcreset->next->prev = pcreset;
+ pcreset->prev = 0;
+ npcParse->inactive = pcreset;
+ pcreset->setid = setid;
+ }
+
+ return pcreset;
}
/**
@@ -176,33 +155,32 @@ static struct pcrematch_set * lookup_pcreset(struct npc_data *nd,int setid)
*
* if the setid does not exist, this will silently return
*/
-
-static void activate_pcreset(struct npc_data *nd,int setid)
+static void activate_pcreset(struct npc_data* nd, int setid)
{
- struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
- return; // Nothing to activate...
- pcreset = npcParse->inactive_;
- while (pcreset != NULL) {
- if (pcreset->setid_ == setid)
- break;
- pcreset = pcreset->next_;
- }
- if (pcreset == NULL)
- return; // not in inactive list
- if (pcreset->next_ != NULL)
- pcreset->next_->prev_ = pcreset->prev_;
- if (pcreset->prev_ != NULL)
- pcreset->prev_->next_ = pcreset->next_;
- else
- npcParse->inactive_ = pcreset->next_;
-
- pcreset->prev_ = NULL;
- pcreset->next_ = npcParse->active_;
- if (pcreset->next_ != NULL)
- pcreset->next_->prev_ = pcreset;
- npcParse->active_ = pcreset;
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return; // Nothing to activate...
+ pcreset = npcParse->inactive;
+ while (pcreset != NULL) {
+ if (pcreset->setid == setid)
+ break;
+ pcreset = pcreset->next;
+ }
+ if (pcreset == NULL)
+ return; // not in inactive list
+ if (pcreset->next != NULL)
+ pcreset->next->prev = pcreset->prev;
+ if (pcreset->prev != NULL)
+ pcreset->prev->next = pcreset->next;
+ else
+ npcParse->inactive = pcreset->next;
+
+ pcreset->prev = NULL;
+ pcreset->next = npcParse->active;
+ if (pcreset->next != NULL)
+ pcreset->next->prev = pcreset;
+ npcParse->active = pcreset;
}
/**
@@ -210,138 +188,133 @@ static void activate_pcreset(struct npc_data *nd,int setid)
*
* if the setid does not exist, this will silently return
*/
-
-static void deactivate_pcreset(struct npc_data *nd,int setid)
+static void deactivate_pcreset(struct npc_data* nd, int setid)
{
- struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
- return; // Nothing to deactivate...
- if (setid == -1) {
- while(npcParse->active_ != NULL)
- deactivate_pcreset(nd, npcParse->active_->setid_);
- return;
- }
- pcreset = npcParse->active_;
- while (pcreset != NULL) {
- if (pcreset->setid_ == setid)
- break;
- pcreset = pcreset->next_;
- }
- if (pcreset == NULL)
- return; // not in active list
- if (pcreset->next_ != NULL)
- pcreset->next_->prev_ = pcreset->prev_;
- if (pcreset->prev_ != NULL)
- pcreset->prev_->next_ = pcreset->next_;
- else
- npcParse->active_ = pcreset->next_;
-
- pcreset->prev_ = NULL;
- pcreset->next_ = npcParse->inactive_;
- if (pcreset->next_ != NULL)
- pcreset->next_->prev_ = pcreset;
- npcParse->inactive_ = pcreset;
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return; // Nothing to deactivate...
+ if (setid == -1) {
+ while(npcParse->active != NULL)
+ deactivate_pcreset(nd, npcParse->active->setid);
+ return;
+ }
+ pcreset = npcParse->active;
+ while (pcreset != NULL) {
+ if (pcreset->setid == setid)
+ break;
+ pcreset = pcreset->next;
+ }
+ if (pcreset == NULL)
+ return; // not in active list
+ if (pcreset->next != NULL)
+ pcreset->next->prev = pcreset->prev;
+ if (pcreset->prev != NULL)
+ pcreset->prev->next = pcreset->next;
+ else
+ npcParse->active = pcreset->next;
+
+ pcreset->prev = NULL;
+ pcreset->next = npcParse->inactive;
+ if (pcreset->next != NULL)
+ pcreset->next->prev = pcreset;
+ npcParse->inactive = pcreset;
}
/**
* delete a set of patterns.
*/
-static void delete_pcreset(struct npc_data *nd,int setid)
+static void delete_pcreset(struct npc_data* nd, int setid)
{
- int active = 1;
- struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
- return; // Nothing to deactivate...
- pcreset = npcParse->active_;
- while (pcreset != NULL) {
- if (pcreset->setid_ == setid)
- break;
- pcreset = pcreset->next_;
- }
- if (pcreset == NULL) {
- active = 0;
- pcreset = npcParse->inactive_;
- while (pcreset != NULL) {
- if (pcreset->setid_ == setid)
- break;
- pcreset = pcreset->next_;
- }
- }
- if (pcreset == NULL)
- return;
-
- if (pcreset->next_ != NULL)
- pcreset->next_->prev_ = pcreset->prev_;
- if (pcreset->prev_ != NULL)
- pcreset->prev_->next_ = pcreset->next_;
-
+ int active = 1;
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return; // Nothing to deactivate...
+ pcreset = npcParse->active;
+ while (pcreset != NULL) {
+ if (pcreset->setid == setid)
+ break;
+ pcreset = pcreset->next;
+ }
+ if (pcreset == NULL) {
+ active = 0;
+ pcreset = npcParse->inactive;
+ while (pcreset != NULL) {
+ if (pcreset->setid == setid)
+ break;
+ pcreset = pcreset->next;
+ }
+ }
+ if (pcreset == NULL)
+ return;
+
+ if (pcreset->next != NULL)
+ pcreset->next->prev = pcreset->prev;
+ if (pcreset->prev != NULL)
+ pcreset->prev->next = pcreset->next;
+
if(active)
- npcParse->active_ = pcreset->next_;
+ npcParse->active = pcreset->next;
else
- npcParse->inactive_ = pcreset->next_;
-
- pcreset->prev_ = NULL;
- pcreset->next_ = NULL;
-
- while (pcreset->head_) {
- struct pcrematch_entry *n = pcreset->head_->next_;
- finalize_pcrematch_entry(pcreset->head_);
- aFree(pcreset->head_); // Cleanin' the last ones.. [Lance]
- pcreset->head_ = n;
- }
-
+ npcParse->inactive = pcreset->next;
+
+ pcreset->prev = NULL;
+ pcreset->next = NULL;
+
+ while (pcreset->head) {
+ struct pcrematch_entry* n = pcreset->head->next;
+ finalize_pcrematch_entry(pcreset->head);
+ aFree(pcreset->head); // Cleanin' the last ones.. [Lance]
+ pcreset->head = n;
+ }
+
aFree(pcreset);
}
/**
* create a new pattern entry
*/
-static struct pcrematch_entry *create_pcrematch_entry(struct pcrematch_set * set)
+static struct pcrematch_entry* create_pcrematch_entry(struct pcrematch_set* set)
{
- struct pcrematch_entry * e = (struct pcrematch_entry *)
- aCalloc(sizeof(struct pcrematch_entry), 1);
- struct pcrematch_entry * last = set->head_;
-
- // Normally we would have just stuck it at the end of the list but
- // this doesn't sink up with peoples usage pattern. They wanted
- // the items defined first to have a higher priority then the
- // items defined later.. as a result, we have to do some work up
- // front..
-
- /* if we are the first pattern, stick us at the end */
- if (last == NULL) {
- set->head_ = e;
- return e;
- }
-
- /* Look for the last entry */
- while (last->next_ != NULL)
- last = last->next_;
-
- last->next_ = e;
- e->next_ = NULL;
-
- return e;
+ struct pcrematch_entry * e = (struct pcrematch_entry *) aCalloc(sizeof(struct pcrematch_entry), 1);
+ struct pcrematch_entry * last = set->head;
+
+ // Normally we would have just stuck it at the end of the list but
+ // this doesn't sink up with peoples usage pattern. They wanted
+ // the items defined first to have a higher priority then the
+ // items defined later. as a result, we have to do some work up front.
+
+ /* if we are the first pattern, stick us at the end */
+ if (last == NULL) {
+ set->head = e;
+ return e;
+ }
+
+ /* Look for the last entry */
+ while (last->next != NULL)
+ last = last->next;
+
+ last->next = e;
+ e->next = NULL;
+
+ return e;
}
/**
* define/compile a new pattern
*/
-
-void npc_chat_def_pattern(struct npc_data *nd, int setid,
- const char *pattern, const char *label)
+void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, const char* label)
{
- const char *err;
- int erroff;
-
- struct pcrematch_set * s = lookup_pcreset(nd, setid);
- struct pcrematch_entry *e = create_pcrematch_entry(s);
- e->pattern_ = aStrdup(pattern);
- e->label_ = aStrdup(label);
- e->pcre_ = pcre_compile(pattern, PCRE_CASELESS, &err, &erroff, NULL);
- e->pcre_extra_ = pcre_study(e->pcre_, 0, &err);
+ const char *err;
+ int erroff;
+
+ struct pcrematch_set * s = lookup_pcreset(nd, setid);
+ struct pcrematch_entry *e = create_pcrematch_entry(s);
+ e->pattern = aStrdup(pattern);
+ e->label = aStrdup(label);
+ e->pcre = pcre_compile(pattern, PCRE_CASELESS, &err, &erroff, NULL);
+ e->pcre_extra = pcre_study(e->pcre, 0, &err);
}
/**
@@ -350,18 +323,18 @@ void npc_chat_def_pattern(struct npc_data *nd, int setid,
*
* this could be more efficent but.. how often do you do this?
*/
-void npc_chat_finalize(struct npc_data *nd)
+void npc_chat_finalize(struct npc_data* nd)
{
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
- return;
-
- while(npcParse->active_)
- delete_pcreset(nd, npcParse->active_->setid_);
-
- while(npcParse->inactive_)
- delete_pcreset(nd, npcParse->inactive_->setid_);
-
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return;
+
+ while(npcParse->active)
+ delete_pcreset(nd, npcParse->active->setid);
+
+ while(npcParse->inactive)
+ delete_pcreset(nd, npcParse->inactive->setid);
+
// Additional cleaning up [Lance]
aFree(npcParse);
}
@@ -369,158 +342,115 @@ void npc_chat_finalize(struct npc_data *nd)
/**
* Handler called whenever a global message is spoken in a NPC's area
*/
-int npc_chat_sub(struct block_list *bl, va_list ap)
+int npc_chat_sub(struct block_list* bl, va_list ap)
{
- struct npc_data *nd = (struct npc_data *)bl;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- char *msg;
- int len, pos, i;
- struct map_session_data *sd;
- struct npc_label_list *lst;
- struct pcrematch_set *pcreset;
-
- // Not interested in anything you might have to say...
- if (npcParse == NULL || npcParse->active_ == NULL)
- return 0;
-
- msg = va_arg(ap,char*);
- len = va_arg(ap,int);
- sd = va_arg(ap,struct map_session_data *);
-
- // grab the active list
- pcreset = npcParse->active_;
-
- // interate across all active sets
- while (pcreset != NULL) {
- struct pcrematch_entry *e = pcreset->head_;
- // interate across all patterns in that set
- while (e != NULL) {
- int offsets[20];
- char buf[255];
- // perform pattern match
- int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0,
- 0, offsets, sizeof(offsets) / sizeof(offsets[0]));
- if (r >= 0) {
- // save out the matched strings
- switch (r) {
- case 10:
- memcpy(buf, &msg[offsets[18]], offsets[19]);
- buf[offsets[19]] = '\0';
- set_var(sd, "$@p9$", buf);
- case 9:
- memcpy(buf, &msg[offsets[16]], offsets[17]);
- buf[offsets[17]] = '\0';
- set_var(sd, "$@p8$", buf);
- case 8:
- memcpy(buf, &msg[offsets[14]], offsets[15]);
- buf[offsets[15]] = '\0';
- set_var(sd, "$@p7$", buf);
- case 7:
- memcpy(buf, &msg[offsets[12]], offsets[13]);
- buf[offsets[13]] = '\0';
- set_var(sd, "$@p6$", buf);
- case 6:
- memcpy(buf, &msg[offsets[10]], offsets[11]);
- buf[offsets[11]] = '\0';
- set_var(sd, "$@p5$", buf);
- case 5:
- memcpy(buf, &msg[offsets[8]], offsets[9]);
- buf[offsets[9]] = '\0';
- set_var(sd, "$@p4$", buf);
- case 4:
- memcpy(buf, &msg[offsets[6]], offsets[7]);
- buf[offsets[7]] = '\0';
- set_var(sd, "$@p3$", buf);
- case 3:
- memcpy(buf, &msg[offsets[4]], offsets[5]);
- buf[offsets[5]] = '\0';
- set_var(sd, "$@p2$", buf);
- case 2:
- memcpy(buf, &msg[offsets[2]], offsets[3]);
- buf[offsets[3]] = '\0';
- set_var(sd, "$@p1$", buf);
- case 1:
- memcpy(buf, &msg[offsets[0]], offsets[1]);
- buf[offsets[1]] = '\0';
- set_var(sd, "$@p0$", buf);
- }
-
- // find the target label.. this sucks..
- lst=nd->u.scr.label_list;
- pos = -1;
- for (i = 0; i < nd->u.scr.label_list_num; i++) {
- if (strncmp(lst[i].name, e->label_, sizeof(lst[i].name)) == 0) {
- pos = lst[i].pos;
- break;
- }
- }
- if (pos == -1) {
- ShowWarning("Unable to find label: %s", e->label_);
- // unable to find label... do something..
- return 0;
- }
- // run the npc script
- run_script(nd->u.scr.script,pos,sd->bl.id,nd->bl.id);
- return 0;
- }
- e = e->next_;
- }
- pcreset = pcreset->next_;
- }
-
- return 0;
+ struct npc_data* nd = (struct npc_data *) bl;
+ struct npc_parse* npcParse = (struct npc_parse *) nd->chatdb;
+ char* msg;
+ int len, i;
+ struct map_session_data* sd;
+ struct npc_label_list* lst;
+ struct pcrematch_set* pcreset;
+ struct pcrematch_entry* e;
+
+ // Not interested in anything you might have to say...
+ if (npcParse == NULL || npcParse->active == NULL)
+ return 0;
+
+ msg = va_arg(ap,char*);
+ len = va_arg(ap,int);
+ sd = va_arg(ap,struct map_session_data *);
+
+ // iterate across all active sets
+ for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next)
+ {
+ // interate across all patterns in that set
+ for (e = pcreset->head; e != NULL; e = e->next)
+ {
+ int offsets[2*10 + 10]; // 1/3 reserved for temp space requred by pcre_exec
+
+ // perform pattern match
+ int r = pcre_exec(e->pcre, e->pcre_extra, msg, len, 0, 0, offsets, ARRAYLENGTH(offsets));
+ if (r > 0)
+ {
+ // save out the matched strings
+ for (i = 0; i < r; i++)
+ {
+ char var[6], val[255];
+ snprintf(var, sizeof(var), "$@p%i$", i);
+ pcre_copy_substring(msg, offsets, r, i, val, sizeof(val));
+ set_var(sd, var, val);
+ }
+
+ // find the target label.. this sucks..
+ lst = nd->u.scr.label_list;
+ ARR_FIND(0, nd->u.scr.label_list_num, i, strncmp(lst[i].name, e->label, sizeof(lst[i].name)) == 0);
+ if (i == nd->u.scr.label_list_num) {
+ ShowWarning("Unable to find label: %s", e->label);
+ return 0;
+ }
+
+ // run the npc script
+ run_script(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id);
+ return 0;
+ }
+ }
+ }
+
+ return 0;
}
-int mob_chat_sub(struct block_list *bl, va_list ap){
+int mob_chat_sub(struct block_list* bl, va_list ap)
+{
struct mob_data *md = (struct mob_data *)bl;
- if(md->nd){
+ if(md->nd)
npc_chat_sub(&md->nd->bl, ap);
- }
+
return 0;
}
// Various script builtins used to support these functions
-int buildin_defpattern(struct script_state *st)
+int buildin_defpattern(struct script_state* st)
{
- int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
- const char *pattern=conv_str(st,& (st->stack->stack_data[st->start+3]));
- const char *label=conv_str(st,& (st->stack->stack_data[st->start+4]));
- struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
-
- npc_chat_def_pattern(nd, setid, pattern, label);
-
- return 0;
+ int setid = conv_num(st,& (st->stack->stack_data[st->start+2]));
+ const char* pattern = conv_str(st,& (st->stack->stack_data[st->start+3]));
+ const char* label = conv_str(st,& (st->stack->stack_data[st->start+4]));
+ struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid);
+
+ npc_chat_def_pattern(nd, setid, pattern, label);
+
+ return 0;
}
-int buildin_activatepset(struct script_state *st)
+int buildin_activatepset(struct script_state* st)
{
- int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
- struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
-
- activate_pcreset(nd, setid);
-
- return 0;
+ int setid = conv_num(st,& (st->stack->stack_data[st->start+2]));
+ struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid);
+
+ activate_pcreset(nd, setid);
+
+ return 0;
}
-int buildin_deactivatepset(struct script_state *st)
+int buildin_deactivatepset(struct script_state* st)
{
- int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
- struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
-
- deactivate_pcreset(nd, setid);
-
- return 0;
+ int setid = conv_num(st,& (st->stack->stack_data[st->start+2]));
+ struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid);
+
+ deactivate_pcreset(nd, setid);
+
+ return 0;
}
-int buildin_deletepset(struct script_state *st)
+int buildin_deletepset(struct script_state* st)
{
- int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
- struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
-
- delete_pcreset(nd, setid);
-
- return 0;
+ int setid = conv_num(st,& (st->stack->stack_data[st->start+2]));
+ struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid);
+
+ delete_pcreset(nd, setid);
+
+ return 0;
}
#endif //PCRE_SUPPORT